Skip to content

Commit 1bae600

Browse files
committed
Let quote authors fetch instruments
Private quote requests point the quoted author at the newly published instrument, so the stored note has to authorize that actor to fetch it. Add the quoted author to followers-only and direct quote audiences unless that actor is already included by a mention. #32 (comment) Assisted-by: Codex:gpt-5.5
1 parent 3809a7f commit 1bae600

2 files changed

Lines changed: 45 additions & 3 deletions

File tree

packages/botkit/src/session-impl.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,39 @@ test("SessionImpl.publish()", async (t) => {
554554
assert.deepStrictEqual(quote.quoteTarget?.id, originalMsg.id);
555555
});
556556

557+
await t.test("private quote includes quoted author in audience", async () => {
558+
const originalAuthorId = new URL("https://remote.example/ap/actor/john");
559+
const originalAuthor = new Person({
560+
id: originalAuthorId,
561+
preferredUsername: "john",
562+
});
563+
const originalPost = new Note({
564+
id: new URL("https://remote.example/ap/note/private"),
565+
content: "<p>Private post</p>",
566+
attribution: originalAuthor,
567+
to: new URL("https://remote.example/ap/actor/john/followers"),
568+
});
569+
const originalMsg = await createMessage<Note, void>(
570+
originalPost,
571+
session,
572+
{},
573+
);
574+
575+
for (const visibility of ["followers", "direct"] as const) {
576+
ctx.sentActivities = [];
577+
await session.publish(text`Private quote`, {
578+
quoteTarget: originalMsg,
579+
visibility,
580+
});
581+
582+
const { activity } = ctx.sentActivities[0];
583+
assert.ok(activity instanceof Create);
584+
const object = await activity.getObject(ctx);
585+
assert.ok(object instanceof Note);
586+
assert.ok(object.toIds.includes(originalAuthorId));
587+
}
588+
});
589+
557590
await t.test("poll single choice", async () => {
558591
ctx.sentActivities = [];
559592
const endTime = Temporal.Now.instant().add({ hours: 24 });

packages/botkit/src/session-impl.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,14 @@ export class SessionImpl<TContextData> implements Session<TContextData> {
288288
}),
289289
);
290290
}
291+
const actorId = this.context.getActorUri(this.bot.identifier);
292+
const quoteTargetActorId = options.quoteTarget?.actor.id;
293+
const privateQuoteAudienceIds = quoteTargetActorId != null &&
294+
quoteTargetActorId.href !== actorId.href &&
295+
(visibility === "followers" || visibility === "direct") &&
296+
!mentionedActorIds.some((id) => id.href === quoteTargetActorId.href)
297+
? [quoteTargetActorId]
298+
: [];
291299
let inclusiveOptions: Note[] = [];
292300
let exclusiveOptions: Note[] = [];
293301
let voters: number | null = null;
@@ -327,10 +335,10 @@ export class SessionImpl<TContextData> implements Session<TContextData> {
327335
tags,
328336
interactionPolicy: serializeQuotePolicy(
329337
options.quotePolicy ?? this.bot.quotePolicy,
330-
this.context.getActorUri(this.bot.identifier),
338+
actorId,
331339
this.context.getFollowersUri(this.bot.identifier),
332340
),
333-
attribution: this.context.getActorUri(this.bot.identifier),
341+
attribution: actorId,
334342
attachments: options.attachments ?? [],
335343
inclusiveOptions,
336344
exclusiveOptions,
@@ -342,8 +350,9 @@ export class SessionImpl<TContextData> implements Session<TContextData> {
342350
? [
343351
this.context.getFollowersUri(this.bot.identifier),
344352
...mentionedActorIds,
353+
...privateQuoteAudienceIds,
345354
]
346-
: mentionedActorIds,
355+
: [...mentionedActorIds, ...privateQuoteAudienceIds],
347356
ccs: visibility === "public"
348357
? [this.context.getFollowersUri(this.bot.identifier)]
349358
: visibility === "unlisted"

0 commit comments

Comments
 (0)