import type { User } from "@markone/core/user" import { Readability } from "@mozilla/readability" import { JSDOM } from "jsdom" import { db } from "~/database.ts" import { DEMO_BOOKMARKS } from "./demo-bookmarks.ts" import type { Bookmark, BookmarkTag } from "@markone/core/bookmark" class LinkUnreachable {} class UnsupportedLink {} interface CachedPage { title: string readableHtml: string } function insertDemoBookmarks(user: User) { const query = db.query(` INSERT OR IGNORE INTO bookmarks (id, user_id, kind, title, url) VALUES ($id, $userId, $kind, $title, $url) `) const insert = db.transaction((bookmarks) => { for (const bookmark of bookmarks) { query.run({ id: bookmark.id, userId: user.id, kind: bookmark.kind, title: bookmark.title, url: bookmark.url, }) } }) insert(DEMO_BOOKMARKS) } function findBookmarkHtml(id: string, user: User): string | null { const query = db.query("SELECT content_html FROM bookmarks WHERE id = $id AND user_id = $userId") const row = query.get({ id, userId: user.id }) if (!row) { return null } const { content_html } = row as { content_html: string } return content_html } function findBookmark(id: string, user: User): Bookmark | null { const bookmarkQuery = db.query( "SELECT id, kind, title, url FROM bookmarks WHERE id = $id AND user_id = $userId", ) const bookmark = bookmarkQuery.get({ id, userId: user.id }) if (!bookmark) { return null } const tagsQuery = db.query("SELECT id, name FROM tags WHERE bookmark_id = $id") const tags = tagsQuery.all({ id }) bookmark.tags = tags return bookmark } async function cacheWebsite(url: string): Promise { const websiteText = await fetch(url) .catch(() => { throw new LinkUnreachable() }) .then((res) => res.text()) .catch(() => { throw new UnsupportedLink() }) const dom = new JSDOM(websiteText, { url }) const reader = new Readability(dom.window.document) const article = reader.parse() if (!article) { return null } if (article.content) { const newDom = new JSDOM(article.content, { url }) const doc = newDom.window.document const lightStyleLink = doc.createElement("link") lightStyleLink.rel = "stylesheet" lightStyleLink.href = "/reader-styles/sakura.css" lightStyleLink.media = "screen" const darkStyleLink = doc.createElement("link") darkStyleLink.rel = "stylesheet" darkStyleLink.href = "/reader-styles/sakura-dark.css" darkStyleLink.media = "screen and (prefers-color-scheme: dark)" doc.head.appendChild(lightStyleLink) doc.head.appendChild(darkStyleLink) article.content = newDom.serialize() } return { title: article.title || "Untitled", readableHtml: article.content || "", } } export { insertDemoBookmarks, findBookmark, findBookmarkHtml, cacheWebsite } export { LinkUnreachable, UnsupportedLink }