diff --git a/src/index.ts b/src/index.ts index 898337b..eafbc4e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -19,7 +19,7 @@ try { await bot.setChatPreference(IncomingChatPreference.All); bot.on("message", messages.handler); - logger.success("Registered events (reply, mention, quote)"); + logger.success("Registered events (message)"); } catch (e) { logger.error("Failure to log-in: ", e); process.exit(1); diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..beab6bb --- /dev/null +++ b/src/types.ts @@ -0,0 +1,12 @@ +export type ParsedPost = { + thread?: { + ancestors: ParsedPost[]; + }; + author: string; + text: string; + images?: { + index: number; + alt: string; + }[]; + quotePost?: ParsedPost; +}; diff --git a/src/utils/conversation.ts b/src/utils/conversation.ts index 7cf1820..02d46a2 100644 --- a/src/utils/conversation.ts +++ b/src/utils/conversation.ts @@ -9,7 +9,7 @@ import { conversations, messages } from "../db/schema"; import { and, eq } from "drizzle-orm"; import { env } from "../env"; import { bot, MAX_GRAPHEMES } from "../core"; -import { parsePostImages, traverseThread } from "./post"; +import { parsePost, parsePostImages, traverseThread } from "./post"; /* Utilities @@ -126,37 +126,31 @@ export async function parseConversation(convo: Conversation) { const post = await bot.getPost(row.postUri); const convoMessages = await getRelevantMessages(row!); - const thread = await traverseThread(post); + let parseResult = null; + try { + parseResult = yaml.dump({ + post: await parsePost(post, true), + messages: convoMessages.map((message) => { + const profile = resolveDid(convo, message.did); - return yaml.dump({ - post: { - thread: { - ancestors: thread.map((post) => ({ - author: post.author.displayName - ? `${post.author.displayName} (${post.author.handle})` - : `Handle: ${post.author.handle}`, - text: post.text, - })), - }, - author: post.author.displayName - ? `${post.author.displayName} (${post.author.handle})` - : `Handle: ${post.author.handle}`, - text: post.text, - images: parsePostImages(post), - likes: post.likeCount || 0, - replies: post.replyCount || 0, - }, - messages: convoMessages.map((message) => { - const profile = resolveDid(convo, message.did); + return { + user: profile.displayName + ? `${profile.displayName} (${profile.handle})` + : `Handle: ${profile.handle}`, + text: message.text, + }; + }), + }); + } catch (e) { + convo.sendMessage({ + text: + "Sorry, I ran into an issue analyzing that post. Please try again.", + }); - return { - user: profile.displayName - ? `${profile.displayName} (${profile.handle})` - : `Handle: ${profile.handle}`, - text: message.text, - }; - }), - }); + throw new Error("Failed to parse conversation"); + } + + return parseResult; } /* diff --git a/src/utils/post.ts b/src/utils/post.ts index eee7196..6d0782f 100644 --- a/src/utils/post.ts +++ b/src/utils/post.ts @@ -1,6 +1,53 @@ -import { EmbedImage, Post } from "@skyware/bot"; +import { + EmbedImage, + Post, + PostEmbed, + RecordEmbed, + RecordWithMediaEmbed, +} from "@skyware/bot"; import * as c from "../core"; import * as yaml from "js-yaml"; +import type { ParsedPost } from "../types"; + +export async function parsePost( + post: Post, + includeThread: boolean, +): Promise { + const [images, quotePost, ancestorPosts] = await Promise.all([ + parsePostImages(post), + parseQuote(post), + includeThread ? traverseThread(post) : Promise.resolve(null), + ]); + + return { + author: post.author.displayName + ? `${post.author.displayName} (${post.author.handle})` + : `Handle: ${post.author.handle}`, + text: post.text, + ...(images && { images }), + ...(quotePost && { quotePost }), + ...(ancestorPosts && { + thread: { + ancestors: await Promise.all( + ancestorPosts.map((ancestor) => parsePost(ancestor, false)), + ), + }, + }), + }; +} + +async function parseQuote(post: Post) { + if ( + !post.embed || (!post.embed.isRecord() && !post.embed.isRecordWithMedia()) + ) return undefined; + + const record = (post.embed as RecordEmbed || RecordWithMediaEmbed).record; + console.log("embed: ", post.embed); + console.log("record: ", record); + const embedPost = await c.bot.getPost(record.uri); + + return await parsePost(embedPost, false); +} export function parsePostImages(post: Post) { if (!post.embed) return [];