Skip to content

Commit 515dade

Browse files
committed
Improve activity propagation to message authors
Send activities to the original message authors as well to ensure better federation - Send Create, Announce, Undo, Update, and Delete activities to original message authors - Ensure proper delivery of activities between interacting users
1 parent 55e8920 commit 515dade

4 files changed

Lines changed: 118 additions & 13 deletions

File tree

CHANGES.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ To be released.
4343

4444
- Added `SessionGetOutboxOptions` interface.
4545

46+
- Activities are more precisely propagated.
47+
48+
- The `Message.reply()` method now sends the `Create` activity to
49+
the author of the original message as well.
50+
- The `Message.share()` method now sends the `Announce` activity to
51+
the author of the original message as well.
52+
- The `AuthorizedSharedMessage.unshare()` method now sends the `Undo`
53+
activity to the author of the original message as well.
54+
- The `AuthorizedMessage.update()` method now sends the `Update` activity
55+
to the author of the original message as well if it is a reply.
56+
- The `AuthorizedMessage.delete()` method now sends the `Delete` activity
57+
to the author of the original message as well if it is a reply.
4658

4759

4860
Version 0.1.1

src/message-impl.test.ts

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,14 +270,22 @@ Deno.test("MessageImpl.reply()", async () => {
270270
assertEquals(await repository.countMessages(), 1);
271271
const [create] = await Array.fromAsync(repository.getMessages());
272272
assert(create != null);
273-
assertEquals(ctx.sentActivities.length, 1);
273+
assertEquals(ctx.sentActivities.length, 2);
274274
const { recipients, activity } = ctx.sentActivities[0];
275275
assertEquals(recipients, "followers");
276276
assertInstanceOf(activity, Create);
277277
assertEquals(
278278
await activity.toJsonLd({ format: "compact" }),
279279
await create.toJsonLd({ format: "compact" }),
280280
);
281+
const { recipients: recipients2, activity: activity2 } =
282+
ctx.sentActivities[1];
283+
assertEquals(recipients2, [originalMsg.actor]);
284+
assertInstanceOf(activity2, Create);
285+
assertEquals(
286+
await activity2.toJsonLd({ format: "compact" }),
287+
await create.toJsonLd({ format: "compact" }),
288+
);
281289
assertEquals(
282290
await reply.raw.toJsonLd({ format: "compact" }),
283291
await (await create.getObject())?.toJsonLd({ format: "compact" }),
@@ -319,7 +327,7 @@ Deno.test("MessageImpl.share()", async (t) => {
319327
assertEquals(await repository.countMessages(), 1);
320328
const [announce] = await Array.fromAsync(repository.getMessages());
321329
assert(announce != null);
322-
assertEquals(ctx.sentActivities.length, 1);
330+
assertEquals(ctx.sentActivities.length, 2);
323331
const { recipients, activity } = ctx.sentActivities[0];
324332
assertEquals(recipients, "followers");
325333
assertInstanceOf(activity, Announce);
@@ -332,6 +340,19 @@ Deno.test("MessageImpl.share()", async (t) => {
332340
await activity.toJsonLd({ format: "compact" }),
333341
await announce.toJsonLd({ format: "compact" }),
334342
);
343+
const { recipients: recipients2, activity: activity2 } =
344+
ctx.sentActivities[1];
345+
assertEquals(recipients2, [originalMsg.actor]);
346+
assertInstanceOf(activity2, Announce);
347+
assertEquals(activity2.toIds, [ctx.getFollowersUri(bot.identifier)]);
348+
assertEquals(activity2.ccIds, [
349+
PUBLIC_COLLECTION,
350+
originalPost.attributionId,
351+
]);
352+
assertEquals(
353+
await activity2.toJsonLd({ format: "compact" }),
354+
await announce.toJsonLd({ format: "compact" }),
355+
);
335356
assertEquals(
336357
await sharedMsg.raw.toJsonLd({ format: "compact" }),
337358
await announce.toJsonLd({ format: "compact" }),
@@ -346,7 +367,7 @@ Deno.test("MessageImpl.share()", async (t) => {
346367
await t.step("unshare()", async () => {
347368
await sharedMsg.unshare();
348369
assertEquals(await repository.countMessages(), 0);
349-
assertEquals(ctx.sentActivities.length, 1);
370+
assertEquals(ctx.sentActivities.length, 2);
350371
const { recipients, activity } = ctx.sentActivities[0];
351372
assertEquals(recipients, "followers");
352373
assertInstanceOf(activity, Undo);
@@ -357,6 +378,17 @@ Deno.test("MessageImpl.share()", async (t) => {
357378
originalPost.attributionId,
358379
]);
359380
assertEquals(activity.objectId, sharedMsg.id);
381+
const { recipients: recipients2, activity: activity2 } =
382+
ctx.sentActivities[1];
383+
assertEquals(recipients2, [originalMsg.actor]);
384+
assertInstanceOf(activity2, Undo);
385+
assertEquals(activity2.actorId, ctx.getActorUri(bot.identifier));
386+
assertEquals(activity2.toIds, [ctx.getFollowersUri(bot.identifier)]);
387+
assertEquals(activity2.ccIds, [
388+
PUBLIC_COLLECTION,
389+
originalPost.attributionId,
390+
]);
391+
assertEquals(activity2.objectId, sharedMsg.id);
360392
});
361393
});
362394

src/message-impl.ts

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,16 @@ export class MessageImpl<T extends MessageClass, TContextData>
182182
excludeBaseUris: [new URL(this.session.context.origin)],
183183
},
184184
);
185+
await this.session.context.sendActivity(
186+
this.session.bot,
187+
this.actor,
188+
announce,
189+
{
190+
preferSharedInbox: true,
191+
excludeBaseUris: [new URL(this.session.context.origin)],
192+
fanout: "skip",
193+
},
194+
);
185195
const actor = announce.actorId?.href === this.session.actorId.href
186196
? await this.session.getActor()
187197
: await announce.getActor(this.session.context);
@@ -194,21 +204,32 @@ export class MessageImpl<T extends MessageClass, TContextData>
194204
original: this,
195205
unshare: async () => {
196206
await this.session.bot.repository.removeMessage(id);
207+
const undo = new Undo({
208+
id: new URL("#delete", uri),
209+
actor: this.session.context.getActorUri(
210+
this.session.bot.identifier,
211+
),
212+
tos: announce.toIds,
213+
ccs: announce.ccIds,
214+
object: announce,
215+
});
197216
await this.session.context.sendActivity(
198217
this.session.bot,
199218
"followers",
200-
new Undo({
201-
id: new URL("#delete", uri),
202-
actor: this.session.context.getActorUri(
203-
this.session.bot.identifier,
204-
),
205-
tos: announce.toIds,
206-
ccs: announce.ccIds,
207-
object: announce,
208-
}),
219+
undo,
220+
{
221+
preferSharedInbox: true,
222+
excludeBaseUris: [new URL(this.session.context.origin)],
223+
},
224+
);
225+
await this.session.context.sendActivity(
226+
this.session.bot,
227+
this.actor,
228+
undo,
209229
{
210230
preferSharedInbox: true,
211231
excludeBaseUris: [new URL(this.session.context.origin)],
232+
fanout: "skip",
212233
},
213234
);
214235
},
@@ -474,6 +495,22 @@ export class AuthorizedMessageImpl<T extends MessageClass, TContextData>
474495
update,
475496
{ preferSharedInbox, excludeBaseUris },
476497
);
498+
if (this.replyTarget != null) {
499+
await this.session.context.sendActivity(
500+
this.session.bot,
501+
this.replyTarget.actor,
502+
update,
503+
{ preferSharedInbox: true, excludeBaseUris, fanout: "skip" },
504+
);
505+
}
506+
if (this.quoteTarget != null) {
507+
await this.session.context.sendActivity(
508+
this.session.bot,
509+
this.quoteTarget.actor,
510+
update,
511+
{ preferSharedInbox: true, excludeBaseUris, fanout: "skip" },
512+
);
513+
}
477514
}
478515

479516
async delete(): Promise<void> {
@@ -527,6 +564,22 @@ export class AuthorizedMessageImpl<T extends MessageClass, TContextData>
527564
{ preferSharedInbox: true, excludeBaseUris },
528565
);
529566
}
567+
if (this.replyTarget != null) {
568+
await this.session.context.sendActivity(
569+
this.session.bot,
570+
this.replyTarget.actor,
571+
activity,
572+
{ preferSharedInbox: true, excludeBaseUris, fanout: "skip" },
573+
);
574+
}
575+
if (this.quoteTarget != null) {
576+
await this.session.context.sendActivity(
577+
this.session.bot,
578+
this.quoteTarget.actor,
579+
activity,
580+
{ preferSharedInbox: true, excludeBaseUris, fanout: "skip" },
581+
);
582+
}
530583
}
531584
}
532585

src/session-impl.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,12 +316,20 @@ export class SessionImpl<TContextData> implements Session<TContextData> {
316316
{ preferSharedInbox, excludeBaseUris },
317317
);
318318
}
319+
if (options.replyTarget != null) {
320+
await this.context.sendActivity(
321+
this.bot,
322+
options.replyTarget.actor,
323+
activity,
324+
{ preferSharedInbox, excludeBaseUris, fanout: "skip" },
325+
);
326+
}
319327
if (options.quoteTarget != null) {
320328
await this.context.sendActivity(
321329
this.bot,
322330
options.quoteTarget.actor,
323331
activity,
324-
{ preferSharedInbox, excludeBaseUris },
332+
{ preferSharedInbox, excludeBaseUris, fanout: "skip" },
325333
);
326334
}
327335
return await createMessage(

0 commit comments

Comments
 (0)