提交
This commit is contained in:
+57
-3
@@ -1,17 +1,21 @@
|
||||
import {
|
||||
deleteActorFromCache,
|
||||
deleteCachedStatus,
|
||||
exportUserPublicKeyPem,
|
||||
findFavourite,
|
||||
findReblog,
|
||||
getCachedStatusByObjectId,
|
||||
getStatus,
|
||||
getStatusByObjectId,
|
||||
getUserByUsername,
|
||||
recordNotification,
|
||||
upsertActorCache
|
||||
upsertActorCache,
|
||||
upsertCachedStatus
|
||||
} from "./db";
|
||||
import {
|
||||
deliverToInboxes,
|
||||
isDuplicateActivity,
|
||||
isFollowedByAnyLocalUser,
|
||||
notifyForLocalStatus,
|
||||
objectAsJson,
|
||||
objectIdString,
|
||||
@@ -360,11 +364,12 @@ async function handleDelete(ctx: InboxContext): Promise<Response> {
|
||||
await env.DB.prepare("DELETE FROM favourites WHERE actor = ?").bind(actorId).run();
|
||||
await env.DB.prepare("DELETE FROM reblogs WHERE actor = ?").bind(actorId).run();
|
||||
await env.DB.prepare("DELETE FROM notifications WHERE actor = ?").bind(actorId).run();
|
||||
await env.DB.prepare("DELETE FROM cached_statuses WHERE actor = ?").bind(actorId).run();
|
||||
await deleteActorFromCache(env, actorId);
|
||||
return new Response(null, { status: 202 });
|
||||
}
|
||||
|
||||
await env.DB.prepare("DELETE FROM favourites WHERE actor = ? AND activity_id LIKE ?").bind(actorId, `%${target}%`).run();
|
||||
await deleteCachedStatus(env, target);
|
||||
return new Response(null, { status: 202 });
|
||||
}
|
||||
|
||||
@@ -374,6 +379,13 @@ async function handleUpdate(ctx: InboxContext): Promise<Response> {
|
||||
if (!obj) return new Response(null, { status: 202 });
|
||||
if (String(obj.type ?? "") === "Person" && obj.id === actorId) {
|
||||
await upsertActorCache(env, obj as unknown as RemoteActor);
|
||||
return new Response(null, { status: 202 });
|
||||
}
|
||||
if (String(obj.type ?? "") === "Note" && typeof obj.id === "string") {
|
||||
const existing = await getCachedStatusByObjectId(env, obj.id);
|
||||
if (existing && existing.actor === actorId) {
|
||||
await cacheRemoteNote(env, actorId, obj);
|
||||
}
|
||||
}
|
||||
return new Response(null, { status: 202 });
|
||||
}
|
||||
@@ -381,7 +393,7 @@ async function handleUpdate(ctx: InboxContext): Promise<Response> {
|
||||
async function handleCreate(ctx: InboxContext): Promise<Response> {
|
||||
const { env, activity, actorId } = ctx;
|
||||
const obj = objectAsJson(activity.body.object);
|
||||
if (!obj) return new Response(null, { status: 202 });
|
||||
if (!obj || String(obj.type ?? "") !== "Note") return new Response(null, { status: 202 });
|
||||
|
||||
const recipients = collectRecipients(activity.body, obj);
|
||||
const localActorIds = new Set<string>();
|
||||
@@ -391,6 +403,12 @@ async function handleCreate(ctx: InboxContext): Promise<Response> {
|
||||
if (m) localActorIds.add(m[1]);
|
||||
}
|
||||
|
||||
const isPublic = recipients.includes(PUBLIC_COLLECTION);
|
||||
const followed = await isFollowedByAnyLocalUser(env, actorId);
|
||||
if (followed && (isPublic || localActorIds.size > 0)) {
|
||||
await cacheRemoteNote(env, actorId, obj);
|
||||
}
|
||||
|
||||
for (const username of localActorIds) {
|
||||
const localUser = await getUserByUsername(env, username);
|
||||
if (!localUser) continue;
|
||||
@@ -405,6 +423,42 @@ async function handleCreate(ctx: InboxContext): Promise<Response> {
|
||||
return new Response(null, { status: 202 });
|
||||
}
|
||||
|
||||
async function cacheRemoteNote(env: Env, actorId: string, note: Json): Promise<void> {
|
||||
if (typeof note.id !== "string") return;
|
||||
const cachedId = note.id;
|
||||
const stored = await upsertCachedStatus(env, {
|
||||
id: cachedId,
|
||||
object_id: cachedId,
|
||||
actor: actorId,
|
||||
content: typeof note.content === "string" ? note.content : "",
|
||||
summary: typeof note.summary === "string" ? note.summary : "",
|
||||
sensitive: note.sensitive ? 1 : 0,
|
||||
language: typeof note.contentMap === "object" && note.contentMap ? Object.keys(note.contentMap as Json)[0] ?? "en" : "en",
|
||||
in_reply_to: typeof note.inReplyTo === "string" ? note.inReplyTo : null,
|
||||
url: typeof note.url === "string" ? note.url : cachedId,
|
||||
published: typeof note.published === "string" ? note.published : new Date().toISOString()
|
||||
});
|
||||
if (!stored) return;
|
||||
await env.DB.prepare("DELETE FROM cached_status_attachments WHERE cached_status_id = ?").bind(stored.id).run();
|
||||
const attachments = Array.isArray(note.attachment) ? note.attachment : note.attachment ? [note.attachment] : [];
|
||||
let position = 0;
|
||||
for (const raw of attachments) {
|
||||
if (!raw || typeof raw !== "object") continue;
|
||||
const att = raw as Json;
|
||||
const url = typeof att.url === "string" ? att.url
|
||||
: (att.url && typeof att.url === "object" && typeof (att.url as Json).href === "string") ? String((att.url as Json).href)
|
||||
: null;
|
||||
if (!url) continue;
|
||||
const mime = typeof att.mediaType === "string" ? att.mediaType : "application/octet-stream";
|
||||
const description = typeof att.name === "string" ? att.name
|
||||
: typeof att.summary === "string" ? att.summary : null;
|
||||
await env.DB.prepare(
|
||||
"INSERT OR REPLACE INTO cached_status_attachments (cached_status_id, position, url, preview_url, mime_type, description) VALUES (?, ?, ?, ?, ?, ?)"
|
||||
).bind(stored.id, position, url, null, mime, description).run();
|
||||
position++;
|
||||
}
|
||||
}
|
||||
|
||||
function collectRecipients(activity: Json, object: Json): string[] {
|
||||
const fields: unknown[] = [activity.to, activity.cc, activity.bto, activity.bcc, object.to, object.cc];
|
||||
const out = new Set<string>();
|
||||
|
||||
Reference in New Issue
Block a user