diff options
Diffstat (limited to 'app/src/lib/categorization.ts')
-rw-r--r-- | app/src/lib/categorization.ts | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/app/src/lib/categorization.ts b/app/src/lib/categorization.ts new file mode 100644 index 0000000..a692240 --- /dev/null +++ b/app/src/lib/categorization.ts @@ -0,0 +1,102 @@ +// import { Database } from "bun:sqlite"; +// const db = new Database("data/bookmarks.db", { create: true }); +import { TwitterBookmark } from "./twitter-api"; + +export interface CategorySuggestion { + categories: string[]; + confidence: number; + reasoning: string; +} + +export interface CategorizationRequest { + bookmark: TwitterBookmark; + userCategories: Array<{ name: string; criteria: string }>; +} + +export interface CategorizationResponse { + suggestedCategories: CategorySuggestion[]; + newCategories: string[]; + summary: string; + keyTopics: string[]; +} + +export interface UserCategories { + categories: string[]; +} + +export const userCategories = [ + { name: "AI", criteria: "AI, machine learning, LLMs, all AI related stuff" }, + { name: "Nix", criteria: "Nix and NixOS" }, + { name: "Urbit", criteria: "anything related to Urbit" }, + { + name: "Code", + criteria: + "other stuff related to software or software development (excludes the previous)", + }, + { name: "history", criteria: "posts about history or archeology" }, + { name: "Politics", criteria: "posts about politics" }, + { + name: "China", + criteria: + "posts about China or in Chinese which don't fall under any other category", + }, + { + name: "Japan", + criteria: + "posts about Japan or in Japanese which don't fall under any other category", + }, + { name: "Movies", criteria: "posts related to movies, anime or TV shows" }, + { name: "Demographics", criteria: "posts about demographics or birth rates" }, + { name: "Memes", criteria: "posts including memes or otherwise funny" }, +]; + +type FileTree = Map<string, FileEntry[]>; +type FileEntry = { file: string } | { dir: FileTree }; +// type FileTree = { dir: `${string}/`; files: string[]; dirs?: Record<string, FileTree> }; + +class Obsidian { + auth = `Bearer ${Bun.env.OBSIDIAN_API_KEY!}`; + url = `http://127.0.0.1:27123`; + tree: FileTree = new Map(); + async getFiles() {} + async list() { + this.populate(this.tree, "/"); + } + async populate(parent: FileTree, dir: `${string}/`) { + const entries: FileEntry[] = []; + const res = (await this.call("/vault/" + dir)) as { files: string[] }; + for (let entry of res.files) { + if (entry.endsWith(".md")) entries.push({ file: entry }); + else if (entry.endsWith("/")) this.populate(new Map(), entry as any); + // entries.push({ dir: new Map() }); + } + parent.set(dir, entries); + } + async call(path: string) { + const headers = { Authorization: this.auth }; + const opts = { headers }; + const res = await fetch(this.url + path, opts); + const j = await res.json(); + return j; + } + async post(path: string, body: string) { + const headers = { Authorization: this.auth }; + const opts = { headers, method: "POST", body }; + const res = await fetch(this.url + path, opts); + return res; + } + async saveToDisk( + bookmark: TwitterBookmark, + categorization: CategorizationResponse, + tags: string[], + ) { + // append to file + const body = `\n\n`; + const opts = { method: "POST", headers, body }; + const res = await this.post("/vault/", body); + if (!res.ok) { + const j = await res.json(); + return { error: j.message }; + } else return { ok: "" }; + } +} |