// 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; type FileEntry = { file: string } | { dir: FileTree }; // type FileTree = { dir: `${string}/`; files: string[]; dirs?: Record }; 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: "" }; } }