@rmdes/indiekit-endpoint-activitypub 2.0.5 → 2.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -204,6 +204,42 @@ export function submitComposeController(mountPath, plugin) {
|
|
|
204
204
|
"https://www.w3.org/ns/activitystreams#Public",
|
|
205
205
|
);
|
|
206
206
|
const followersUri = ctx.getFollowersUri(handle);
|
|
207
|
+
|
|
208
|
+
// Resolve the original author BEFORE constructing the Note,
|
|
209
|
+
// so we can include them in cc (required for threading/notification)
|
|
210
|
+
let recipient = null;
|
|
211
|
+
if (inReplyTo) {
|
|
212
|
+
try {
|
|
213
|
+
const documentLoader = await ctx.getDocumentLoader({
|
|
214
|
+
identifier: handle,
|
|
215
|
+
});
|
|
216
|
+
const remoteObject = await ctx.lookupObject(new URL(inReplyTo), {
|
|
217
|
+
documentLoader,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
if (
|
|
221
|
+
remoteObject &&
|
|
222
|
+
typeof remoteObject.getAttributedTo === "function"
|
|
223
|
+
) {
|
|
224
|
+
const author = await remoteObject.getAttributedTo({
|
|
225
|
+
documentLoader,
|
|
226
|
+
});
|
|
227
|
+
recipient = Array.isArray(author) ? author[0] : author;
|
|
228
|
+
}
|
|
229
|
+
} catch (error) {
|
|
230
|
+
console.warn(
|
|
231
|
+
`[ActivityPub] lookupObject failed for ${inReplyTo} (quick reply):`,
|
|
232
|
+
error.message,
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Build cc list: always include followers, add original author for replies
|
|
238
|
+
const ccList = [followersUri];
|
|
239
|
+
if (recipient?.id) {
|
|
240
|
+
ccList.push(recipient.id);
|
|
241
|
+
}
|
|
242
|
+
|
|
207
243
|
const note = new Note({
|
|
208
244
|
id: new URL(noteId),
|
|
209
245
|
attribution: actorUri,
|
|
@@ -211,7 +247,7 @@ export function submitComposeController(mountPath, plugin) {
|
|
|
211
247
|
replyTarget: inReplyTo ? new URL(inReplyTo) : undefined,
|
|
212
248
|
published: Temporal.Now.instant(),
|
|
213
249
|
to: publicAddress,
|
|
214
|
-
|
|
250
|
+
ccs: ccList,
|
|
215
251
|
});
|
|
216
252
|
|
|
217
253
|
const create = new Create({
|
|
@@ -219,7 +255,7 @@ export function submitComposeController(mountPath, plugin) {
|
|
|
219
255
|
actor: actorUri,
|
|
220
256
|
object: note,
|
|
221
257
|
to: publicAddress,
|
|
222
|
-
|
|
258
|
+
ccs: ccList,
|
|
223
259
|
});
|
|
224
260
|
|
|
225
261
|
// Send to followers
|
|
@@ -229,38 +265,23 @@ export function submitComposeController(mountPath, plugin) {
|
|
|
229
265
|
orderingKey: noteId,
|
|
230
266
|
});
|
|
231
267
|
|
|
232
|
-
//
|
|
233
|
-
if (
|
|
268
|
+
// Also send directly to the original author's inbox
|
|
269
|
+
if (recipient) {
|
|
234
270
|
try {
|
|
235
|
-
|
|
236
|
-
identifier: handle,
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
const recipient = Array.isArray(author)
|
|
250
|
-
? author[0]
|
|
251
|
-
: author;
|
|
252
|
-
|
|
253
|
-
if (recipient) {
|
|
254
|
-
await ctx.sendActivity(
|
|
255
|
-
{ identifier: handle },
|
|
256
|
-
recipient,
|
|
257
|
-
create,
|
|
258
|
-
{ orderingKey: noteId },
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
} catch {
|
|
263
|
-
// Non-critical — followers still got it
|
|
271
|
+
await ctx.sendActivity(
|
|
272
|
+
{ identifier: handle },
|
|
273
|
+
recipient,
|
|
274
|
+
create,
|
|
275
|
+
{ orderingKey: noteId },
|
|
276
|
+
);
|
|
277
|
+
console.info(
|
|
278
|
+
`[ActivityPub] Sent quick reply directly to ${recipient.id?.href || "author"}`,
|
|
279
|
+
);
|
|
280
|
+
} catch (error) {
|
|
281
|
+
console.warn(
|
|
282
|
+
`[ActivityPub] Direct delivery to author failed (quick reply):`,
|
|
283
|
+
error.message,
|
|
284
|
+
);
|
|
264
285
|
}
|
|
265
286
|
}
|
|
266
287
|
|
|
@@ -41,13 +41,22 @@ export function boostController(mountPath, plugin) {
|
|
|
41
41
|
{ handle, publicationUrl: plugin._publicationUrl },
|
|
42
42
|
);
|
|
43
43
|
|
|
44
|
-
const
|
|
44
|
+
const uuid = crypto.randomUUID();
|
|
45
|
+
const baseUrl = plugin._publicationUrl.replace(/\/$/, "");
|
|
46
|
+
const activityId = `${baseUrl}/activitypub/boosts/${uuid}`;
|
|
47
|
+
|
|
48
|
+
const publicAddress = new URL(
|
|
49
|
+
"https://www.w3.org/ns/activitystreams#Public",
|
|
50
|
+
);
|
|
51
|
+
const followersUri = ctx.getFollowersUri(handle);
|
|
45
52
|
|
|
46
53
|
// Construct Announce activity
|
|
47
54
|
const announce = new Announce({
|
|
48
55
|
id: new URL(activityId),
|
|
49
56
|
actor: ctx.getActorUri(handle),
|
|
50
57
|
object: new URL(url),
|
|
58
|
+
to: publicAddress,
|
|
59
|
+
cc: followersUri,
|
|
51
60
|
});
|
|
52
61
|
|
|
53
62
|
// Send to followers via shared inbox
|
|
@@ -97,7 +97,9 @@ export function likeController(mountPath, plugin) {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
// Generate a unique activity ID
|
|
100
|
-
const
|
|
100
|
+
const uuid = crypto.randomUUID();
|
|
101
|
+
const baseUrl = plugin._publicationUrl.replace(/\/$/, "");
|
|
102
|
+
const activityId = `${baseUrl}/activitypub/likes/${uuid}`;
|
|
101
103
|
|
|
102
104
|
// Construct and send Like activity
|
|
103
105
|
const like = new Like({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rmdes/indiekit-endpoint-activitypub",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.7",
|
|
4
4
|
"description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"indiekit",
|