diff --git a/CHANGES.md b/CHANGES.md index 46d7fd19..950e9ba0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,20 @@ Version 1.3.0 To be released. +Version 1.2.2 +------------- + +Released on November 1, 2024. + + - Handle connection errors (rather than HTTP errors) in + the `Context.sendActivity()` method. + + - Support the `fedify` command on Windows on ARM64 via x64 emulation. + [[#160]] + +[#160]: https://github.com/dahlia/fedify/issues/160 + + Version 1.2.1 ------------- diff --git a/cli/npm/install.mjs b/cli/npm/install.mjs index efe04288..7b4faebe 100644 --- a/cli/npm/install.mjs +++ b/cli/npm/install.mjs @@ -12,6 +12,7 @@ import { } from "node:fs/promises"; import { tmpdir } from "node:os"; import { dirname, join } from "node:path"; +import process from "node:process"; import { Readable } from "node:stream"; import { fileURLToPath } from "node:url"; @@ -25,6 +26,7 @@ const platforms = { x64: "linux-x86_64.tar.xz", }, win32: { + arm64: "windows-x86_64.zip", x64: "windows-x86_64.zip", }, }; diff --git a/docs/manual/inbox.md b/docs/manual/inbox.md index 493a97e3..bdfd436c 100644 --- a/docs/manual/inbox.md +++ b/docs/manual/inbox.md @@ -76,6 +76,106 @@ multiple inbox listeners for different activity types. [shared inbox]: https://www.w3.org/TR/activitypub/#shared-inbox-delivery +Determining the recipient of an activity +---------------------------------------- + +### Looking at the `to`, `cc`, `bto`, and `bcc` fields + +When you receive an activity, you may want to determine the recipient of the +activity. The recipient is usually the actor who is mentioned in +the `to`, `cc`, `bto`, or `bcc` field of the activity. The following shows +how to determine the recipient of a `Create` activity: + +~~~~ typescript twoslash +import { Create, type InboxListenerSetters } from "@fedify/fedify"; +(0 as unknown as InboxListenerSetters) +// ---cut-before--- +.on(Create, async (ctx, create) => { + if (create.toId == null) return; + const to = ctx.parseUri(create.toId); + if (to?.type !== "actor") return; + const recipient = to.identifier; + // Do something with the recipient +}); +~~~~ + +The `to`, `cc`, `bto`, and `bcc` fields can contain multiple recipients, +so you may need to iterate over them to determine the recipient of the activity: + +~~~~ typescript twoslash +import { Create, type InboxListenerSetters } from "@fedify/fedify"; +(0 as unknown as InboxListenerSetters) +// ---cut-before--- +.on(Create, async (ctx, create) => { + for (const toId of create.toIds) { + const to = ctx.parseUri(toId); + if (to?.type !== "actor") continue; + const recipient = to.identifier; + // Do something with the recipient + } +}); +~~~~ + +Also, the `to`, `cc`, `bto`, and `bcc` fields can contain both actor and +collection objects. In such cases, you may need to recursively resolve the +collection objects to determine the recipients of the activity: + +~~~~ typescript twoslash +import { + Collection, + Create, + type InboxListenerSetters, + isActor, +} from "@fedify/fedify"; +(0 as unknown as InboxListenerSetters) +// ---cut-before--- +.on(Create, async (ctx, create) => { + for await (const to of create.getTos()) { + if (isActor(to)) { + // `to` is a recipient of the activity + // Do something with the recipient + } else if (to instanceof Collection) { + // `to` is a collection object + for await (const actor of to.getItems()) { + if (!isActor(actor)) continue; + // `actor` is a recipient of the activity + // Do something with the recipient + } + } + } +}); +~~~~ + +> [!TIP] +> It might look strange, non-scalar accessor methods for `to`, `cc`, `bto`, +> and `bcc` fields are named as `~Object.getTos()`, `~Object.getCcs()`, +> `~Object.getBtos()`, and `~Object.getBccs()`, respectively. + +### Looking at the `InboxContext.recipient` property + +*This API is available since Fedify 1.2.0.* + +However, the `to`, `cc`, `bto`, and `bcc` fields are not always present in +an activity. In such cases, you can determine the recipient by looking at +the `InboxContext.recipient` property. The below example shows how to determine +the recipient of a `Follow` activity: + +~~~~ typescript twoslash +import { Follow, type InboxListenerSetters } from "@fedify/fedify"; +(0 as unknown as InboxListenerSetters) +// ---cut-before--- +.on(Follow, async (ctx, follow) => { + const recipient = ctx.recipient; + // Do something with the recipient +}); +~~~~ + +The `~InboxContext.recipient` property is set to the identifier of the actor +who is the recipient of the activity. If the invocation is not for a personal +inbox, but for a shared inbox, the `~InboxContext.recipient` property is set to +`null`. + + `Context.documentLoader` on an inbox listener --------------------------------------------- diff --git a/src/federation/send.ts b/src/federation/send.ts index 4ab07468..2768dd7d 100644 --- a/src/federation/send.ts +++ b/src/federation/send.ts @@ -152,7 +152,20 @@ export async function sendActivity( } else { request = await signRequest(request, rsaKey.privateKey, rsaKey.keyId); } - const response = await fetch(request); + let response: Response; + try { + response = await fetch(request); + } catch (error) { + logger.error( + "Failed to send activity {activityId} to {inbox}:\n{error}", + { + activityId, + inbox: inbox.href, + error, + }, + ); + throw error; + } if (!response.ok) { let error; try {