import { api } from "misskey-js"; import type { Note } from "misskey-js/entities.js"; import type { Message } from "./llm"; import { sample } from "./util"; export const misskey = new api.APIClient({ origin: Bun.env["MISSKEY_ORIGIN"] || "https://misskey.cannorin.net", credential: Bun.env["MISSKEY_CREDENTIAL"], }); export const me = await misskey.request("i", {}); /** check if a note is suitable as an input */ export const isSuitableAsInput = (n: Note) => !n.user.isBot && !n.replyId && (!n.mentions || n.mentions.length === 0) && n.text?.length && n.text.length > 0; /** randomly sample some notes from the timeline */ export async function getNotes(localNotesCount = 5, globalNotesCount = 10) { // randomly sample N local notes const localNotes = (count: number) => misskey .request("notes/local-timeline", { limit: 100 }) .then((xs) => xs.filter(isSuitableAsInput)) .then((xs) => sample(xs, count)); // randomly sample N global notes const globalNotes = (count: number) => misskey .request("notes/global-timeline", { limit: 100 }) .then((xs) => xs.filter(isSuitableAsInput)) .then((xs) => sample(xs, count)); const notes = await Promise.all([ localNotes(localNotesCount), globalNotes(globalNotesCount), ]); return sample(notes.flat()); } /** fetch the whole reply tree */ export async function expandReplyTree( note: Note, acc: Note[] = [], cutoff = 5, ) { if (!note.reply || cutoff < 1) return [...acc, note]; const reply = await misskey.request("notes/show", { noteId: note.reply.id }); return await expandReplyTree(reply, [...acc, note], cutoff - 1); }