From 3065049aaffdd304584a3ab4174b625ab1719d33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=AA=E5=AD=90?= Date: Sat, 16 May 2026 01:08:41 +0800 Subject: [PATCH] Update activitypub.ts --- src/activitypub.ts | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/activitypub.ts b/src/activitypub.ts index 81ed46e..9667986 100644 --- a/src/activitypub.ts +++ b/src/activitypub.ts @@ -217,8 +217,11 @@ export async function activityObject(env: Env, objectId: string): Promise(); if (!user) return json({ error: "not_found" }, 404); - const attachments = await loadStatusAttachments(env, status.id); - return activityJson(noteObject(env, user, status, { attachments })); + const [attachments, tag] = await Promise.all([ + loadStatusAttachments(env, status.id), + loadStatusTags(env, status.id) + ]); + return activityJson(noteObject(env, user, status, { attachments, tag })); } const tomb = await env.DB.prepare("SELECT * FROM deleted_statuses WHERE id = ?").bind(objectId).first<{ id: string; deleted_at: string }>(); if (tomb) { @@ -602,7 +605,10 @@ export async function createActivity(env: Env, user: User, status: Status, extra const audience = statusAudience(env, user, status); const to = extra.to ?? audience.to; const cc = extra.cc ?? audience.cc; - const attachments = await loadStatusAttachments(env, status.id); + const [attachments, tag] = await Promise.all([ + loadStatusAttachments(env, status.id), + loadStatusTags(env, status.id) + ]); return { "@context": [ACTIVITY_CONTEXT, SECURITY_CONTEXT], id: status.activity_id, @@ -611,7 +617,7 @@ export async function createActivity(env: Env, user: User, status: Status, extra published: status.created_at, to, cc, - object: noteObject(env, user, status, { to, cc, attachments }) + object: noteObject(env, user, status, { to, cc, attachments, tag }) }; } @@ -629,6 +635,21 @@ export async function loadStatusAttachments(env: Env, statusId: string): Promise return media.map((item) => attachmentObject(env, item)); } +export async function loadStatusTags(env: Env, statusId: string): Promise { + const [mentionRows, hashtagRows] = await Promise.all([ + env.DB.prepare("SELECT actor, acct FROM mentions WHERE status_id = ?").bind(statusId).all<{ actor: string; acct: string }>(), + env.DB.prepare("SELECT tag FROM hashtags WHERE status_id = ?").bind(statusId).all<{ tag: string }>() + ]); + const tags: Json[] = []; + for (const mention of mentionRows.results) { + tags.push({ type: "Mention", href: mention.actor, name: `@${mention.acct}` }); + } + for (const row of hashtagRows.results) { + tags.push({ type: "Hashtag", href: `${baseUrl(env)}/tags/${encodeURIComponent(row.tag)}`, name: `#${row.tag}` }); + } + return tags; +} + function statusAudience(env: Env, user: User, status: Status): { to: string[]; cc: string[] } { if (status.visibility === "unlisted") { return { to: [`${actorUrl(env, user)}/followers`], cc: [PUBLIC_COLLECTION] };