@fedify/botkit 0.3.0-dev.112 → 0.3.0-dev.115

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.
package/dist/bot-impl.js CHANGED
@@ -423,7 +423,7 @@ var BotImpl = class {
423
423
  };
424
424
  await this.onVote(session, vote);
425
425
  const update = new Update$1({
426
- id: new URL(`#update-votes/${Date.now()}`, updatedQuestion.id ?? ctx.origin),
426
+ id: new URL(`#update-votes/${crypto.randomUUID()}`, updatedQuestion.id ?? ctx.origin),
427
427
  actor: ctx.getActorUri(this.identifier),
428
428
  object: updatedPollMessage.id,
429
429
  tos: updatedPollMessage.toIds,
@@ -1 +1 @@
1
- {"version":3,"file":"bot-impl.js","names":["options: BotImplOptions<TContextData>","#summary","#properties","metadata","APEmoji","RawLike","session: Session<TContextData>","tags: (Link | Object)[]","pairs: PropertyValue[]","ctx: Context<TContextData>","identifier: string","Object","_ctx: Context<TContextData>","username: string","cursor: string | null","followers: AsyncIterable<Actor>","nextCursor: string | null","items: Recipient[]","ctx: RequestContext<TContextData>","owner: Actor | null","object: Object","items: Activity[]","nextPublished: Temporal.Instant | null","_ctx: RequestContext<TContextData>","values: { id: string }","_signedKey: CryptographicKey | null","signedKeyOwner: Actor | null","cls: new (values: any) => T","ctx: Context<TContextData> | RequestContext<TContextData>","id: string","values: { name: string }","ctx: InboxContext<TContextData>","follow: Follow","undo: Undo","accept: Accept","reject: Reject","create: Create","messageCache: Message<MessageClass, TContextData> | null","optionNotes: Note[]","options: string[]","updatedOptionNotes: Note[]","vote: Vote<TContextData>","Update","quoteUrl: URL | null","announce: Announce","object: Object | null","sharedMessage: SharedMessage<MessageClass, TContextData>","#parseLike","like: RawLike","#parseReaction","react: EmojiReact | RawLike","emoji: Emoji | APEmoji | undefined","origin: string | URL | Context<TContextData>","contextData?: TContextData","request: Request","contextData: TContextData","file: fs.FileHandle","name: string","data: CustomEmoji","url: URL","name: TEmojiName","emojis: Readonly<Record<TEmojiName, CustomEmoji>>"],"sources":["../src/bot-impl.ts"],"sourcesContent":["// BotKit by Fedify: A framework for creating ActivityPub bots\n// Copyright (C) 2025 Hong Minhee <https://hongminhee.org/>\n//\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as\n// published by the Free Software Foundation, either version 3 of the\n// License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program. If not, see <https://www.gnu.org/licenses/>.\nimport {\n type Context,\n createFederation,\n type Federation,\n generateCryptoKeyPair,\n type InboxContext,\n type NodeInfo,\n Object,\n type PageItems,\n type Recipient,\n type RequestContext,\n type Software,\n Update,\n} from \"@fedify/fedify\";\nimport {\n Accept,\n type Activity,\n type Actor,\n Announce,\n type Application,\n Article,\n ChatMessage,\n Create,\n type CryptographicKey,\n Emoji as APEmoji,\n EmojiReact,\n Endpoints,\n Follow,\n Image,\n isActor,\n Like as RawLike,\n Link,\n Mention,\n Note,\n PropertyValue,\n PUBLIC_COLLECTION,\n Question,\n Reject,\n Service,\n Undo,\n} from \"@fedify/fedify/vocab\";\nimport { getLogger } from \"@logtape/logtape\";\nimport mimeDb from \"mime-db\";\nimport fs from \"node:fs/promises\";\nimport { getXForwardedRequest } from \"x-forwarded-fetch\";\nimport metadata from \"../deno.json\" with { type: \"json\" };\nimport type { Bot, CreateBotOptions, PagesOptions } from \"./bot.ts\";\nimport {\n type CustomEmoji,\n type DeferredCustomEmoji,\n type Emoji,\n isEmoji,\n} from \"./emoji.ts\";\nimport type {\n AcceptEventHandler,\n FollowEventHandler,\n LikeEventHandler,\n MentionEventHandler,\n MessageEventHandler,\n QuoteEventHandler,\n ReactionEventHandler,\n RejectEventHandler,\n ReplyEventHandler,\n SharedMessageEventHandler,\n UndoneReactionEventHandler,\n UnfollowEventHandler,\n UnlikeEventHandler,\n VoteEventHandler,\n} from \"./events.ts\";\nimport { FollowRequestImpl } from \"./follow-impl.ts\";\nimport {\n createMessage,\n getMessageVisibility,\n isMessageObject,\n isQuoteLink,\n messageClasses,\n} from \"./message-impl.ts\";\nimport type { Message, MessageClass, SharedMessage } from \"./message.ts\";\nimport { app } from \"./pages.tsx\";\nimport type { Vote } from \"./poll.ts\";\nimport type { Like, Reaction } from \"./reaction.ts\";\nimport { KvRepository, type Repository, type Uuid } from \"./repository.ts\";\nimport { SessionImpl } from \"./session-impl.ts\";\nimport type { Session } from \"./session.ts\";\nimport type { Text } from \"./text.ts\";\n\nexport interface BotImplOptions<TContextData>\n extends CreateBotOptions<TContextData> {\n collectionWindow?: number;\n}\n\nexport class BotImpl<TContextData> implements Bot<TContextData> {\n readonly identifier: string;\n readonly class: typeof Service | typeof Application;\n readonly username: string;\n readonly name?: string;\n readonly summary?: Text<\"block\", TContextData>;\n #summary: { text: string; tags: (Link | Object)[] } | null;\n readonly icon?: URL | Image;\n readonly image?: URL | Image;\n readonly properties: Record<string, Text<\"block\" | \"inline\", TContextData>>;\n #properties: { pairs: PropertyValue[]; tags: (Link | Object)[] } | null;\n readonly followerPolicy: \"accept\" | \"reject\" | \"manual\";\n readonly customEmojis: Record<string, CustomEmoji>;\n readonly repository: Repository;\n readonly software?: Software;\n readonly behindProxy: boolean;\n readonly pages: Required<PagesOptions>;\n readonly collectionWindow: number;\n readonly federation: Federation<TContextData>;\n\n onFollow?: FollowEventHandler<TContextData>;\n onUnfollow?: UnfollowEventHandler<TContextData>;\n onAcceptFollow?: AcceptEventHandler<TContextData>;\n onRejectFollow?: RejectEventHandler<TContextData>;\n onMention?: MentionEventHandler<TContextData>;\n onReply?: ReplyEventHandler<TContextData>;\n onQuote?: QuoteEventHandler<TContextData>;\n onMessage?: MessageEventHandler<TContextData>;\n onSharedMessage?: SharedMessageEventHandler<TContextData>;\n onLike?: LikeEventHandler<TContextData>;\n onUnlike?: UnlikeEventHandler<TContextData>;\n onReact?: ReactionEventHandler<TContextData>;\n onUnreact?: UndoneReactionEventHandler<TContextData>;\n onVote?: VoteEventHandler<TContextData>;\n\n constructor(options: BotImplOptions<TContextData>) {\n this.identifier = options.identifier ?? \"bot\";\n this.class = options.class ?? Service;\n this.username = options.username;\n this.name = options.name;\n this.summary = options.summary;\n this.#summary = null;\n this.icon = options.icon;\n this.image = options.image;\n this.properties = options.properties ?? {};\n this.#properties = null;\n this.followerPolicy = options.followerPolicy ?? \"accept\";\n this.customEmojis = {};\n this.repository = options.repository ?? new KvRepository(options.kv);\n this.software = options.software;\n this.pages = {\n color: \"green\",\n css: \"\",\n ...(options.pages ?? {}),\n };\n this.federation = createFederation<TContextData>({\n kv: options.kv,\n queue: options.queue,\n userAgent: {\n software: `BotKit/${metadata.version}`,\n },\n });\n this.behindProxy = options.behindProxy ?? false;\n this.collectionWindow = options.collectionWindow ?? 50;\n this.initialize();\n }\n\n initialize(): void {\n this.federation\n .setActorDispatcher(\n \"/ap/actor/{identifier}\",\n this.dispatchActor.bind(this),\n )\n .mapHandle(this.mapHandle.bind(this))\n .setKeyPairsDispatcher(this.dispatchActorKeyPairs.bind(this));\n this.federation\n .setFollowersDispatcher(\n \"/ap/actor/{identifier}/followers\",\n this.dispatchFollowers.bind(this),\n )\n .setFirstCursor(this.getFollowersFirstCursor.bind(this))\n .setCounter(this.countFollowers.bind(this));\n this.federation\n .setOutboxDispatcher(\n \"/ap/actor/{identifier}/outbox\",\n this.dispatchOutbox.bind(this),\n )\n .setFirstCursor(this.getOutboxFirstCursor.bind(this))\n .setCounter(this.countOutbox.bind(this));\n this.federation\n .setObjectDispatcher(\n Follow,\n \"/ap/follow/{id}\",\n this.dispatchFollow.bind(this),\n )\n .authorize(this.authorizeFollow.bind(this));\n this.federation.setObjectDispatcher(\n Create,\n \"/ap/create/{id}\",\n this.dispatchCreate.bind(this),\n );\n this.federation.setObjectDispatcher(\n Article,\n \"/ap/article/{id}\",\n (ctx, values) => this.dispatchMessage(Article, ctx, values.id),\n );\n this.federation.setObjectDispatcher(\n ChatMessage,\n \"/ap/chat-message/{id}\",\n (ctx, values) => this.dispatchMessage(ChatMessage, ctx, values.id),\n );\n this.federation.setObjectDispatcher(\n Note,\n \"/ap/note/{id}\",\n (ctx, values) => this.dispatchMessage(Note, ctx, values.id),\n );\n this.federation.setObjectDispatcher(\n Question,\n \"/ap/question/{id}\",\n (ctx, values) => this.dispatchMessage(Question, ctx, values.id),\n );\n this.federation.setObjectDispatcher(\n Announce,\n \"/ap/announce/{id}\",\n this.dispatchAnnounce.bind(this),\n );\n this.federation.setObjectDispatcher(\n APEmoji,\n \"/ap/emoji/{name}\",\n this.dispatchEmoji.bind(this),\n );\n this.federation\n .setInboxListeners(\"/ap/actor/{identifier}/inbox\", \"/ap/inbox\")\n .on(Follow, this.onFollowed.bind(this))\n .on(Undo, async (ctx, undo) => {\n const object = await undo.getObject(ctx);\n if (object instanceof Follow) await this.onUnfollowed(ctx, undo);\n else if (object instanceof RawLike) await this.onUnliked(ctx, undo);\n else {\n const logger = getLogger([\"botkit\", \"bot\", \"inbox\"]);\n logger.warn(\n \"The Undo object {undoId} is not about Follow or Like: {object}.\",\n { undoId: undo.id?.href, object },\n );\n }\n })\n .on(Accept, this.onFollowAccepted.bind(this))\n .on(Reject, this.onFollowRejected.bind(this))\n .on(Create, this.onCreated.bind(this))\n .on(Announce, this.onAnnounced.bind(this))\n .on(RawLike, this.onLiked.bind(this))\n .setSharedKeyDispatcher(this.dispatchSharedKey.bind(this));\n if (this.software != null) {\n this.federation.setNodeInfoDispatcher(\n \"/nodeinfo/2.1\",\n this.dispatchNodeInfo.bind(this),\n );\n }\n }\n\n async getActorSummary(\n session: Session<TContextData>,\n ): Promise<{ text: string; tags: (Link | Object)[] } | null> {\n if (this.summary == null) return null;\n if (this.#summary == null) {\n let summary = \"\";\n const tags: (Link | Object)[] = [];\n for await (const chunk of this.summary.getHtml(session)) {\n summary += chunk;\n }\n for await (const tag of this.summary.getTags(session)) {\n tags.push(tag);\n }\n return this.#summary = { text: summary, tags };\n }\n return this.#summary;\n }\n\n async getActorProperties(\n session: Session<TContextData>,\n ): Promise<{ pairs: PropertyValue[]; tags: (Link | Object)[] }> {\n if (this.#properties != null) return this.#properties;\n const pairs: PropertyValue[] = [];\n const tags: (Link | Object)[] = [];\n for (const name in this.properties) {\n const value = this.properties[name];\n const pair = new PropertyValue({\n name,\n value: (await Array.fromAsync(value.getHtml(session))).join(\"\"),\n });\n pairs.push(pair);\n for await (const tag of value.getTags(session)) {\n tags.push(tag);\n }\n }\n return this.#properties = { pairs, tags };\n }\n\n async dispatchActor(\n ctx: Context<TContextData>,\n identifier: string,\n ): Promise<Actor | null> {\n if (this.identifier !== identifier) return null;\n const session = this.getSession(ctx);\n const summary = await this.getActorSummary(session);\n const { pairs, tags } = await this.getActorProperties(session);\n const allTags = summary == null ? tags : [...tags, ...summary.tags];\n const keyPairs = await ctx.getActorKeyPairs(identifier);\n return new this.class({\n id: ctx.getActorUri(identifier),\n preferredUsername: this.username,\n name: this.name,\n summary: summary == null ? null : summary.text,\n attachments: pairs,\n tags: allTags.filter((tag, i) =>\n allTags.findIndex((t) =>\n t.name?.toString() === tag.name?.toString() &&\n (t instanceof Link\n ? tag instanceof Link && t.href?.href === tag.href?.href\n : tag instanceof Object && t.id?.href === tag.id?.href)\n ) === i\n ),\n icon: this.icon == null\n ? null\n : this.icon instanceof Image\n ? this.icon\n : new Image({ url: this.icon }),\n image: this.image == null\n ? null\n : this.image instanceof Image\n ? this.image\n : new Image({ url: this.image }),\n inbox: ctx.getInboxUri(identifier),\n endpoints: new Endpoints({\n sharedInbox: ctx.getInboxUri(),\n }),\n followers: ctx.getFollowersUri(identifier),\n outbox: ctx.getOutboxUri(identifier),\n publicKey: keyPairs[0].cryptographicKey,\n assertionMethods: keyPairs.map((pair) => pair.multikey),\n url: new URL(\"/\", ctx.origin),\n });\n }\n\n mapHandle(_ctx: Context<TContextData>, username: string): string | null {\n return username === this.username ? this.identifier : null;\n }\n\n async dispatchActorKeyPairs(\n _ctx: Context<TContextData>,\n identifier: string,\n ): Promise<CryptoKeyPair[]> {\n if (identifier !== this.identifier) return [];\n let keyPairs = await this.repository.getKeyPairs();\n if (keyPairs == null) {\n const rsa = await generateCryptoKeyPair(\"RSASSA-PKCS1-v1_5\");\n const ed25519 = await generateCryptoKeyPair(\"Ed25519\");\n keyPairs = [rsa, ed25519];\n await this.repository.setKeyPairs(keyPairs);\n }\n return keyPairs;\n }\n\n async dispatchFollowers(\n _ctx: Context<TContextData>,\n identifier: string,\n cursor: string | null,\n ): Promise<PageItems<Recipient> | null> {\n if (identifier !== this.identifier) return null;\n let followers: AsyncIterable<Actor>;\n let nextCursor: string | null;\n if (cursor == null) {\n followers = this.repository.getFollowers();\n nextCursor = null;\n } else {\n const offset = cursor.match(/^\\d+$/) ? parseInt(cursor) : 0;\n followers = this.repository.getFollowers({\n offset,\n limit: this.collectionWindow,\n });\n nextCursor = (offset + this.collectionWindow).toString();\n }\n const items: Recipient[] = [];\n let i = 0;\n for await (const follower of followers) {\n items.push(follower);\n i++;\n }\n if (i < this.collectionWindow) nextCursor = null;\n return { items, nextCursor };\n }\n\n getFollowersFirstCursor(\n _ctx: Context<TContextData>,\n identifier: string,\n ): string | null {\n if (identifier !== this.identifier) return null;\n return \"0\";\n }\n\n async countFollowers(\n _ctx: Context<TContextData>,\n identifier: string,\n ): Promise<number | null> {\n if (identifier !== this.identifier) return null;\n return await this.repository.countFollowers();\n }\n\n async getPermissionChecker(\n ctx: RequestContext<TContextData>,\n ): Promise<(object: Object) => boolean> {\n let owner: Actor | null;\n try {\n owner = await ctx.getSignedKeyOwner();\n } catch {\n owner = null;\n }\n let follower = false;\n const ownerUri = owner?.id;\n if (ownerUri != null) {\n follower = await this.repository.hasFollower(ownerUri);\n }\n const followersUri = ctx.getFollowersUri(this.identifier);\n return (object: Object): boolean => {\n const recipients = [...object.toIds, ...object.ccIds].map((u) => u.href);\n if (recipients.includes(PUBLIC_COLLECTION.href)) return true;\n if (recipients.includes(followersUri.href) && follower) return true;\n return ownerUri == null ? false : recipients.includes(ownerUri.href);\n };\n }\n\n async dispatchOutbox(\n ctx: RequestContext<TContextData>,\n identifier: string,\n cursor: string | null,\n ): Promise<PageItems<Activity> | null> {\n if (identifier !== this.identifier) return null;\n const activities = this.repository.getMessages({\n order: \"newest\",\n until: cursor == null || cursor === \"\"\n ? undefined\n : Temporal.Instant.from(cursor),\n limit: cursor == null ? undefined : this.collectionWindow + 1,\n });\n const items: Activity[] = [];\n const isVisible = await this.getPermissionChecker(ctx);\n let i = 0;\n let nextPublished: Temporal.Instant | null = null;\n for await (const activity of activities) {\n if (cursor != null && i >= this.collectionWindow) {\n nextPublished = activity.published ??\n (await activity.getObject())?.published ?? null;\n break;\n }\n if (isVisible(activity)) items.push(activity);\n i++;\n }\n return { items, nextCursor: nextPublished?.toString() ?? null };\n }\n\n getOutboxFirstCursor(\n _ctx: Context<TContextData>,\n identifier: string,\n ): string | null {\n if (identifier !== this.identifier) return null;\n return \"\";\n }\n\n async countOutbox(\n _ctx: Context<TContextData>,\n identifier: string,\n ): Promise<number | null> {\n if (identifier !== this.identifier) return null;\n return await this.repository.countMessages();\n }\n\n async dispatchFollow(\n _ctx: RequestContext<TContextData>,\n values: { id: string },\n ): Promise<Follow | null> {\n const id = values.id as Uuid;\n const follow = await this.repository.getSentFollow(id);\n return follow ?? null;\n }\n\n async authorizeFollow(\n _ctx: RequestContext<TContextData>,\n values: { id: string },\n _signedKey: CryptographicKey | null,\n signedKeyOwner: Actor | null,\n ): Promise<boolean> {\n if (signedKeyOwner == null || signedKeyOwner.id == null) return false;\n const id = values.id as Uuid;\n const follow = await this.repository.getSentFollow(id);\n if (follow == null) return false;\n return signedKeyOwner.id.href === follow.objectId?.href ||\n signedKeyOwner.id.href === follow.actorId?.href;\n }\n\n async dispatchCreate(\n ctx: RequestContext<TContextData>,\n values: { id: string },\n ): Promise<Create | null> {\n const activity = await this.repository.getMessage(values.id as Uuid);\n if (!(activity instanceof Create)) return null;\n const isVisible = await this.getPermissionChecker(ctx);\n return isVisible(activity) ? activity : null;\n }\n\n async dispatchMessage<T extends MessageClass>(\n // deno-lint-ignore no-explicit-any\n cls: new (values: any) => T,\n ctx: Context<TContextData> | RequestContext<TContextData>,\n id: string,\n ): Promise<T | null> {\n const activity = await this.repository.getMessage(id as Uuid);\n if (!(activity instanceof Create)) return null;\n if (\"request\" in ctx) {\n // TODO: Split this method into two\n const isVisible = await this.getPermissionChecker(ctx);\n if (!isVisible(activity)) return null;\n }\n const object = await activity.getObject(ctx);\n if (object == null || !(object instanceof cls)) return null;\n return object;\n }\n\n async dispatchAnnounce(\n ctx: RequestContext<TContextData>,\n values: { id: string },\n ): Promise<Announce | null> {\n const activity = await this.repository.getMessage(values.id as Uuid);\n if (!(activity instanceof Announce)) return null;\n const isVisible = await this.getPermissionChecker(ctx);\n return isVisible(activity) ? activity : null;\n }\n\n dispatchEmoji(\n ctx: Context<TContextData>,\n values: { name: string },\n ): APEmoji | null {\n const customEmoji = this.customEmojis[values.name];\n if (customEmoji == null) return null;\n return this.getEmoji(ctx, values.name, customEmoji);\n }\n\n dispatchSharedKey(_ctx: Context<TContextData>): { identifier: string } {\n return { identifier: this.identifier };\n }\n\n async onFollowed(\n ctx: InboxContext<TContextData>,\n follow: Follow,\n ): Promise<void> {\n const botUri = ctx.getActorUri(this.identifier);\n if (\n follow.actorId?.href === botUri.href ||\n follow.objectId?.href !== botUri.href\n ) {\n return;\n }\n const follower = await follow.getActor({\n contextLoader: ctx.contextLoader,\n documentLoader: ctx.documentLoader,\n suppressError: true,\n });\n if (follower == null || follower.id == null) return;\n const session = this.getSession(ctx);\n const followRequest = new FollowRequestImpl<TContextData>(\n session,\n follow,\n follower,\n );\n await this.onFollow?.(session, followRequest);\n if (followRequest.state === \"pending\") {\n if (this.followerPolicy === \"accept\") await followRequest.accept();\n else if (this.followerPolicy === \"reject\") await followRequest.reject();\n }\n }\n\n async onUnfollowed(\n ctx: InboxContext<TContextData>,\n undo: Undo,\n ): Promise<void> {\n const followId = undo.objectId;\n if (followId == null || undo.actorId == null) return;\n const follower = await this.repository.removeFollower(\n followId,\n undo.actorId,\n );\n if (this.onUnfollow != null && follower != null) {\n const session = this.getSession(ctx);\n await this.onUnfollow(session, follower);\n }\n }\n\n async onFollowAccepted(\n ctx: InboxContext<TContextData>,\n accept: Accept,\n ): Promise<void> {\n const parsedObj = ctx.parseUri(accept.objectId);\n if (parsedObj?.type !== \"object\" || parsedObj.class !== Follow) return;\n const follow = await this.repository.getSentFollow(\n parsedObj.values.id as Uuid,\n );\n if (follow == null) return;\n const followee = await follow.getObject(ctx);\n if (\n !isActor(followee) || followee.id == null ||\n followee.id.href !== accept.actorId?.href\n ) {\n return;\n }\n await this.repository.addFollowee(followee.id, follow);\n if (this.onAcceptFollow != null) {\n const session = this.getSession(ctx);\n await this.onAcceptFollow(session, followee);\n }\n }\n\n async onFollowRejected(\n ctx: InboxContext<TContextData>,\n reject: Reject,\n ): Promise<void> {\n const parsedObj = ctx.parseUri(reject.objectId);\n if (parsedObj?.type !== \"object\" || parsedObj.class !== Follow) return;\n const id = parsedObj.values.id as Uuid;\n const follow = await this.repository.getSentFollow(id);\n if (follow == null) return;\n const followee = await follow.getObject(ctx);\n if (\n !isActor(followee) || followee.id == null ||\n followee.id.href !== reject.actorId?.href\n ) {\n return;\n }\n await this.repository.removeSentFollow(id);\n if (this.onRejectFollow != null) {\n const session = this.getSession(ctx);\n await this.onRejectFollow(session, followee);\n }\n }\n\n async onCreated(\n ctx: InboxContext<TContextData>,\n create: Create,\n ): Promise<void> {\n const object = await create.getObject(ctx);\n if (\n !(object instanceof Article || object instanceof ChatMessage ||\n object instanceof Note || object instanceof Question) ||\n object.attributionId?.href !== create.actorId?.href\n ) {\n return;\n }\n const session = this.getSession(ctx);\n let messageCache: Message<MessageClass, TContextData> | null = null;\n const getMessage = async () => {\n if (messageCache != null) return messageCache;\n return messageCache = await createMessage(object, session, {});\n };\n const replyTarget = ctx.parseUri(object.replyTargetId);\n if (\n this.onVote != null &&\n object instanceof Note && replyTarget?.type === \"object\" &&\n // @ts-ignore: replyTarget.class satisfies (typeof messageClasses)[number]\n messageClasses.includes(replyTarget.class) &&\n object.name != null\n ) {\n if (create.actorId?.href === session.actorId.href) return;\n const actor = await create.getActor(ctx);\n if (actor == null) return;\n const pollMessage = await this.repository.getMessage(\n replyTarget.values.id as Uuid,\n );\n if (!(pollMessage instanceof Create)) return;\n const question = await pollMessage.getObject(ctx);\n if (\n !(question instanceof Question) || question.endTime == null ||\n Temporal.Instant.compare(question.endTime, Temporal.Now.instant()) < 0\n ) {\n return;\n }\n const optionNotes: Note[] = [];\n const options: string[] = [];\n for await (const note of question.getInclusiveOptions(ctx)) {\n if (!(note instanceof Note)) continue;\n optionNotes.push(note);\n if (note.name != null) options.push(note.name.toString());\n }\n const multiple = options.length > 0;\n for await (const note of question.getExclusiveOptions(ctx)) {\n if (!(note instanceof Note)) continue;\n optionNotes.push(note);\n if (note.name != null) options.push(note.name.toString());\n }\n const option = object.name.toString();\n if (!options.includes(option)) return;\n const updatedOptionNotes: Note[] = [...optionNotes];\n let i = 0;\n for (const note of updatedOptionNotes) {\n if (note.name === option) {\n const replies = await note.getReplies(ctx);\n if (replies != null && replies.totalItems != null) {\n updatedOptionNotes[i] = note.clone({\n replies: replies.clone({\n // FIXME: This way of updating vote count is not only inefficient,\n // but also can lead to incorrect counts if multiple votes are\n // cast at the same time.\n totalItems: replies.totalItems + 1,\n }),\n });\n }\n }\n i++;\n }\n const updatedQuestion = question.clone({\n inclusiveOptions: multiple ? updatedOptionNotes : [],\n exclusiveOptions: !multiple ? updatedOptionNotes : [],\n });\n const updatedPollMessage = pollMessage.clone({\n object: updatedQuestion,\n });\n await this.repository.updateMessage(\n replyTarget.values.id as Uuid,\n () => updatedPollMessage,\n );\n const message = await createMessage(updatedQuestion, session, {});\n const vote: Vote<TContextData> = {\n raw: object,\n actor,\n message,\n poll: {\n multiple,\n options,\n endTime: question.endTime,\n },\n option,\n };\n await this.onVote(session, vote);\n const update = new Update({\n id: new URL(\n `#update-votes/${Date.now()}`,\n updatedQuestion.id ?? ctx.origin,\n ),\n actor: ctx.getActorUri(this.identifier),\n object: updatedPollMessage.id,\n tos: updatedPollMessage.toIds,\n ccs: updatedPollMessage.ccIds,\n });\n if (message.visibility === \"direct\") {\n await ctx.forwardActivity(this, [...message.mentions], {\n skipIfUnsigned: true,\n excludeBaseUris: [new URL(ctx.origin)],\n });\n await ctx.sendActivity(\n this,\n [...message.mentions],\n update,\n { excludeBaseUris: [new URL(ctx.origin)] },\n );\n } else {\n await ctx.forwardActivity(this, \"followers\", {\n skipIfUnsigned: true,\n preferSharedInbox: true,\n excludeBaseUris: [new URL(ctx.origin)],\n });\n await ctx.sendActivity(\n this,\n \"followers\",\n update,\n {\n preferSharedInbox: true,\n excludeBaseUris: [new URL(ctx.origin)],\n },\n );\n }\n return;\n }\n if (\n this.onReply != null &&\n replyTarget?.type === \"object\" &&\n // @ts-ignore: replyTarget.class satisfies (typeof messageClasses)[number]\n messageClasses.includes(replyTarget.class)\n ) {\n const message = await getMessage();\n if (\n message.visibility === \"public\" || message.visibility === \"unlisted\"\n ) {\n await ctx.forwardActivity(this, \"followers\", {\n skipIfUnsigned: true,\n preferSharedInbox: true,\n excludeBaseUris: [new URL(ctx.origin)],\n });\n }\n await this.onReply(session, message);\n }\n let quoteUrl: URL | null = null;\n // FIXME: eliminate this duplication\n for await (const tag of object.getTags(ctx)) {\n if (tag instanceof Link && isQuoteLink(tag)) {\n quoteUrl = tag.href;\n break;\n }\n }\n if (quoteUrl == null) quoteUrl = object.quoteUrl;\n const quoteTarget = ctx.parseUri(quoteUrl);\n if (\n this.onQuote != null &&\n quoteTarget?.type === \"object\" &&\n // @ts-ignore: quoteTarget.class satisfies (typeof messageClasses)[number]\n messageClasses.includes(quoteTarget.class)\n ) {\n const message = await getMessage();\n if (\n message.visibility === \"public\" || message.visibility === \"unlisted\"\n ) {\n await ctx.forwardActivity(this, \"followers\", {\n skipIfUnsigned: true,\n preferSharedInbox: true,\n excludeBaseUris: [new URL(ctx.origin)],\n });\n }\n await this.onQuote(session, message);\n }\n for await (const tag of object.getTags(ctx)) {\n if (\n tag instanceof Mention && tag.href != null && this.onMention != null\n ) {\n const parsed = ctx.parseUri(tag.href);\n if (\n parsed?.type === \"actor\" && parsed.identifier === this.identifier\n ) {\n await this.onMention(session, await getMessage());\n break;\n }\n }\n }\n if (this.onMessage != null) {\n await this.onMessage(session, await getMessage());\n }\n }\n\n async onAnnounced(\n ctx: InboxContext<TContextData>,\n announce: Announce,\n ): Promise<void> {\n if (\n this.onSharedMessage == null || announce.id == null ||\n announce.actorId == null\n ) return;\n const objectUri = ctx.parseUri(announce.objectId);\n let object: Object | null = null;\n if (\n objectUri?.type === \"object\" &&\n // deno-lint-ignore no-explicit-any\n messageClasses.includes(objectUri.class as any)\n ) {\n const msg = await this.repository.getMessage(objectUri.values.id as Uuid);\n if (msg instanceof Create) object = await msg.getObject(ctx);\n } else {\n object = await announce.getObject(ctx);\n }\n if (!isMessageObject(object)) return;\n const session = this.getSession(ctx);\n const actor = announce.actorId.href == session.actorId.href\n ? await session.getActor()\n : await announce.getActor(ctx);\n if (actor == null) return;\n const original = await createMessage(object, session, {});\n const sharedMessage: SharedMessage<MessageClass, TContextData> = {\n raw: announce,\n id: announce.id,\n actor,\n visibility: getMessageVisibility(announce.toIds, announce.ccIds, actor),\n original,\n };\n await this.onSharedMessage(session, sharedMessage);\n }\n\n async #parseLike(\n ctx: InboxContext<TContextData>,\n like: RawLike,\n ): Promise<\n { session: Session<TContextData>; like: Like<TContextData> } | undefined\n > {\n if (like.id == null || like.actorId == null) return undefined;\n const objectUri = ctx.parseUri(like.objectId);\n let object: Object | null = null;\n if (\n objectUri?.type === \"object\" &&\n // deno-lint-ignore no-explicit-any\n messageClasses.includes(objectUri.class as any)\n ) {\n const msg = await this.repository.getMessage(objectUri.values.id as Uuid);\n if (msg instanceof Create) object = await msg.getObject(ctx);\n } else {\n object = await like.getObject(ctx);\n }\n if (!isMessageObject(object)) return undefined;\n const session = this.getSession(ctx);\n const actor = like.actorId.href == session.actorId.href\n ? await session.getActor()\n : await like.getActor(ctx);\n if (actor == null) return;\n const message = await createMessage(object, session, {});\n return {\n session,\n like: {\n raw: like,\n id: like.id,\n actor,\n message,\n },\n };\n }\n\n async onLiked(ctx: InboxContext<TContextData>, like: RawLike): Promise<void> {\n if (like.name != null) return this.onReacted(ctx, like);\n if (this.onLike == null) return;\n const sessionAndLike = await this.#parseLike(ctx, like);\n if (sessionAndLike == null) return;\n const { session, like: likeObject } = sessionAndLike;\n await this.onLike(session, likeObject);\n }\n\n async onUnliked(ctx: InboxContext<TContextData>, undo: Undo): Promise<void> {\n const like = await undo.getObject(ctx);\n if (!(like instanceof RawLike)) return;\n if (like.name != null) return this.onUnreacted(ctx, undo);\n if (this.onUnlike == null) return;\n if (undo.actorId?.href !== like.actorId?.href) return;\n const sessionAndLike = await this.#parseLike(ctx, like);\n if (sessionAndLike == null) return;\n const { session, like: likeObject } = sessionAndLike;\n await this.onUnlike(session, likeObject);\n }\n\n async #parseReaction(\n ctx: InboxContext<TContextData>,\n react: EmojiReact | RawLike,\n ): Promise<\n | { session: Session<TContextData>; reaction: Reaction<TContextData> }\n | undefined\n > {\n if (react.id == null || react.actorId == null || react.name == null) {\n return undefined;\n }\n let emoji: Emoji | APEmoji | undefined;\n if (isEmoji(react.name)) {\n emoji = react.name;\n } else if (\n typeof react.name === \"string\" && react.name.startsWith(\":\") &&\n react.name.endsWith(\":\")\n ) {\n for await (const tag of react.getTags(ctx)) {\n if (tag instanceof APEmoji && tag.name === react.name) {\n emoji = tag;\n break;\n }\n }\n }\n if (emoji == null) return undefined;\n const objectUri = ctx.parseUri(react.objectId);\n let object: Object | null = null;\n if (\n objectUri?.type === \"object\" &&\n // deno-lint-ignore no-explicit-any\n messageClasses.includes(objectUri.class as any)\n ) {\n const msg = await this.repository.getMessage(objectUri.values.id as Uuid);\n if (msg instanceof Create) object = await msg.getObject(ctx);\n } else {\n object = await react.getObject(ctx);\n }\n if (!isMessageObject(object)) return undefined;\n const session = this.getSession(ctx);\n const actor = react.actorId.href == session.actorId.href\n ? await session.getActor()\n : await react.getActor(ctx);\n if (actor == null) return;\n const message = await createMessage(object, session, {});\n return {\n session,\n reaction: {\n raw: react,\n id: react.id,\n actor,\n message,\n emoji,\n },\n };\n }\n\n async onReacted(\n ctx: InboxContext<TContextData>,\n react: EmojiReact | RawLike,\n ): Promise<void> {\n if (this.onReact == null) return;\n const sessionAndReaction = await this.#parseReaction(ctx, react);\n if (sessionAndReaction == null) return;\n const { session, reaction } = sessionAndReaction;\n await this.onReact(session, reaction);\n }\n\n async onUnreacted(\n ctx: InboxContext<TContextData>,\n undo: Undo,\n ): Promise<void> {\n if (this.onUnreact == null) return;\n const react = await undo.getObject(ctx);\n if (!(react instanceof EmojiReact || react instanceof RawLike)) return;\n if (undo.actorId?.href !== react.actorId?.href) return;\n const sessionAndReaction = await this.#parseReaction(ctx, react);\n if (sessionAndReaction == null) return;\n const { session, reaction } = sessionAndReaction;\n await this.onUnreact(session, reaction);\n }\n\n dispatchNodeInfo(_ctx: Context<TContextData>): NodeInfo {\n return {\n software: this.software!,\n protocols: [\"activitypub\"],\n services: {\n outbound: [\"atom1.0\"], // TODO\n },\n usage: {\n users: {\n total: 1,\n activeMonth: 1, // FIXME\n activeHalfyear: 1, // FIXME\n },\n localPosts: 0, // FIXME\n localComments: 0,\n },\n };\n }\n\n getSession(\n origin: string | URL,\n contextData: TContextData,\n ): SessionImpl<TContextData>;\n getSession(origin: string | URL): SessionImpl<TContextData>;\n getSession(context: Context<TContextData>): SessionImpl<TContextData>;\n\n getSession(\n origin: string | URL | Context<TContextData>,\n contextData?: TContextData,\n ): SessionImpl<TContextData> {\n const ctx = typeof origin === \"string\" || origin instanceof URL\n ? this.federation.createContext(new URL(origin), contextData!)\n : origin;\n return new SessionImpl(this, ctx);\n }\n\n async fetch(request: Request, contextData: TContextData): Promise<Response> {\n if (this.behindProxy) {\n request = await getXForwardedRequest(request);\n }\n const url = new URL(request.url);\n if (\n url.pathname.startsWith(\"/.well-known/\") ||\n url.pathname.startsWith(\"/ap/\") ||\n url.pathname.startsWith(\"/nodeinfo/\")\n ) {\n return await this.federation.fetch(request, { contextData });\n }\n const match = /^\\/emojis\\/([a-z0-9-_]+)(?:$|\\.)/.exec(url.pathname);\n if (match != null) {\n const customEmoji = this.customEmojis[match[1]];\n if (customEmoji == null || !(\"file\" in customEmoji)) {\n return new Response(\"Not Found\", { status: 404 });\n }\n let file: fs.FileHandle;\n try {\n file = await fs.open(customEmoji.file, \"r\");\n } catch (error) {\n if (\n typeof error === \"object\" && error != null && \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return new Response(\"Not Found\", { status: 404 });\n }\n throw error;\n }\n const fileInfo = await file.stat();\n return new Response(file.readableWebStream(), {\n headers: {\n \"Content-Type\": customEmoji.type,\n \"Content-Length\": fileInfo.size.toString(),\n \"Cache-Control\": \"public, max-age=31536000, immutable\",\n \"Last-Modified\": (fileInfo.mtime ?? new Date()).toUTCString(),\n \"ETag\": `\"${fileInfo.mtime?.getTime().toString(36)}${\n fileInfo.size.toString(36)\n }\"`,\n },\n });\n }\n return await app.fetch(request, { bot: this, contextData });\n }\n\n getEmoji(\n ctx: Context<TContextData>,\n name: string,\n data: CustomEmoji,\n ): APEmoji {\n let url: URL;\n if (\"url\" in data) {\n url = new URL(data.url);\n } else {\n // @ts-ignore: data.type satisfies keyof typeof mimeDb\n const t = mimeDb[data.type];\n url = new URL(\n `/emojis/${name}${\n t == null || t.extensions == null || t.extensions.length < 1\n ? \"\"\n : `.${t.extensions[0]}`\n }`,\n ctx.origin,\n );\n }\n return new APEmoji({\n id: ctx.getObjectUri(APEmoji, { name }),\n name: `:${name}:`,\n icon: new Image({\n mediaType: data.type,\n url,\n }),\n });\n }\n\n addCustomEmoji<TEmojiName extends string>(\n name: TEmojiName,\n data: CustomEmoji,\n ): DeferredCustomEmoji<TContextData> {\n if (!name.match(/^[a-z0-9-_]+$/i)) {\n throw new TypeError(\n `Invalid custom emoji name: ${name}. It must match /^[a-z0-9-_]+$/i.`,\n );\n } else if (name in this.customEmojis) {\n throw new TypeError(`Duplicate custom emoji name: ${name}`);\n } else if (!data.type.startsWith(\"image/\")) {\n throw new TypeError(`Unsupported media type: ${data.type}`);\n }\n this.customEmojis[name] = data;\n return (session: Session<TContextData>) =>\n this.getEmoji(\n session.context,\n name,\n data,\n );\n }\n\n addCustomEmojis<TEmojiName extends string>(\n emojis: Readonly<Record<TEmojiName, CustomEmoji>>,\n ): Readonly<Record<TEmojiName, DeferredCustomEmoji<TContextData>>> {\n const emojiMap = {} as Record<\n TEmojiName,\n DeferredCustomEmoji<TContextData>\n >;\n for (const name in emojis) {\n emojiMap[name] = this.addCustomEmoji(name, emojis[name]);\n }\n return emojiMap;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bot-impl.js","names":["options: BotImplOptions<TContextData>","#summary","#properties","metadata","APEmoji","RawLike","session: Session<TContextData>","tags: (Link | Object)[]","pairs: PropertyValue[]","ctx: Context<TContextData>","identifier: string","Object","_ctx: Context<TContextData>","username: string","cursor: string | null","followers: AsyncIterable<Actor>","nextCursor: string | null","items: Recipient[]","ctx: RequestContext<TContextData>","owner: Actor | null","object: Object","items: Activity[]","nextPublished: Temporal.Instant | null","_ctx: RequestContext<TContextData>","values: { id: string }","_signedKey: CryptographicKey | null","signedKeyOwner: Actor | null","cls: new (values: any) => T","ctx: Context<TContextData> | RequestContext<TContextData>","id: string","values: { name: string }","ctx: InboxContext<TContextData>","follow: Follow","undo: Undo","accept: Accept","reject: Reject","create: Create","messageCache: Message<MessageClass, TContextData> | null","optionNotes: Note[]","options: string[]","updatedOptionNotes: Note[]","vote: Vote<TContextData>","Update","quoteUrl: URL | null","announce: Announce","object: Object | null","sharedMessage: SharedMessage<MessageClass, TContextData>","#parseLike","like: RawLike","#parseReaction","react: EmojiReact | RawLike","emoji: Emoji | APEmoji | undefined","origin: string | URL | Context<TContextData>","contextData?: TContextData","request: Request","contextData: TContextData","file: fs.FileHandle","name: string","data: CustomEmoji","url: URL","name: TEmojiName","emojis: Readonly<Record<TEmojiName, CustomEmoji>>"],"sources":["../src/bot-impl.ts"],"sourcesContent":["// BotKit by Fedify: A framework for creating ActivityPub bots\n// Copyright (C) 2025 Hong Minhee <https://hongminhee.org/>\n//\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as\n// published by the Free Software Foundation, either version 3 of the\n// License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program. If not, see <https://www.gnu.org/licenses/>.\nimport {\n type Context,\n createFederation,\n type Federation,\n generateCryptoKeyPair,\n type InboxContext,\n type NodeInfo,\n Object,\n type PageItems,\n type Recipient,\n type RequestContext,\n type Software,\n Update,\n} from \"@fedify/fedify\";\nimport {\n Accept,\n type Activity,\n type Actor,\n Announce,\n type Application,\n Article,\n ChatMessage,\n Create,\n type CryptographicKey,\n Emoji as APEmoji,\n EmojiReact,\n Endpoints,\n Follow,\n Image,\n isActor,\n Like as RawLike,\n Link,\n Mention,\n Note,\n PropertyValue,\n PUBLIC_COLLECTION,\n Question,\n Reject,\n Service,\n Undo,\n} from \"@fedify/fedify/vocab\";\nimport { getLogger } from \"@logtape/logtape\";\nimport mimeDb from \"mime-db\";\nimport fs from \"node:fs/promises\";\nimport { getXForwardedRequest } from \"x-forwarded-fetch\";\nimport metadata from \"../deno.json\" with { type: \"json\" };\nimport type { Bot, CreateBotOptions, PagesOptions } from \"./bot.ts\";\nimport {\n type CustomEmoji,\n type DeferredCustomEmoji,\n type Emoji,\n isEmoji,\n} from \"./emoji.ts\";\nimport type {\n AcceptEventHandler,\n FollowEventHandler,\n LikeEventHandler,\n MentionEventHandler,\n MessageEventHandler,\n QuoteEventHandler,\n ReactionEventHandler,\n RejectEventHandler,\n ReplyEventHandler,\n SharedMessageEventHandler,\n UndoneReactionEventHandler,\n UnfollowEventHandler,\n UnlikeEventHandler,\n VoteEventHandler,\n} from \"./events.ts\";\nimport { FollowRequestImpl } from \"./follow-impl.ts\";\nimport {\n createMessage,\n getMessageVisibility,\n isMessageObject,\n isQuoteLink,\n messageClasses,\n} from \"./message-impl.ts\";\nimport type { Message, MessageClass, SharedMessage } from \"./message.ts\";\nimport { app } from \"./pages.tsx\";\nimport type { Vote } from \"./poll.ts\";\nimport type { Like, Reaction } from \"./reaction.ts\";\nimport { KvRepository, type Repository, type Uuid } from \"./repository.ts\";\nimport { SessionImpl } from \"./session-impl.ts\";\nimport type { Session } from \"./session.ts\";\nimport type { Text } from \"./text.ts\";\n\nexport interface BotImplOptions<TContextData>\n extends CreateBotOptions<TContextData> {\n collectionWindow?: number;\n}\n\nexport class BotImpl<TContextData> implements Bot<TContextData> {\n readonly identifier: string;\n readonly class: typeof Service | typeof Application;\n readonly username: string;\n readonly name?: string;\n readonly summary?: Text<\"block\", TContextData>;\n #summary: { text: string; tags: (Link | Object)[] } | null;\n readonly icon?: URL | Image;\n readonly image?: URL | Image;\n readonly properties: Record<string, Text<\"block\" | \"inline\", TContextData>>;\n #properties: { pairs: PropertyValue[]; tags: (Link | Object)[] } | null;\n readonly followerPolicy: \"accept\" | \"reject\" | \"manual\";\n readonly customEmojis: Record<string, CustomEmoji>;\n readonly repository: Repository;\n readonly software?: Software;\n readonly behindProxy: boolean;\n readonly pages: Required<PagesOptions>;\n readonly collectionWindow: number;\n readonly federation: Federation<TContextData>;\n\n onFollow?: FollowEventHandler<TContextData>;\n onUnfollow?: UnfollowEventHandler<TContextData>;\n onAcceptFollow?: AcceptEventHandler<TContextData>;\n onRejectFollow?: RejectEventHandler<TContextData>;\n onMention?: MentionEventHandler<TContextData>;\n onReply?: ReplyEventHandler<TContextData>;\n onQuote?: QuoteEventHandler<TContextData>;\n onMessage?: MessageEventHandler<TContextData>;\n onSharedMessage?: SharedMessageEventHandler<TContextData>;\n onLike?: LikeEventHandler<TContextData>;\n onUnlike?: UnlikeEventHandler<TContextData>;\n onReact?: ReactionEventHandler<TContextData>;\n onUnreact?: UndoneReactionEventHandler<TContextData>;\n onVote?: VoteEventHandler<TContextData>;\n\n constructor(options: BotImplOptions<TContextData>) {\n this.identifier = options.identifier ?? \"bot\";\n this.class = options.class ?? Service;\n this.username = options.username;\n this.name = options.name;\n this.summary = options.summary;\n this.#summary = null;\n this.icon = options.icon;\n this.image = options.image;\n this.properties = options.properties ?? {};\n this.#properties = null;\n this.followerPolicy = options.followerPolicy ?? \"accept\";\n this.customEmojis = {};\n this.repository = options.repository ?? new KvRepository(options.kv);\n this.software = options.software;\n this.pages = {\n color: \"green\",\n css: \"\",\n ...(options.pages ?? {}),\n };\n this.federation = createFederation<TContextData>({\n kv: options.kv,\n queue: options.queue,\n userAgent: {\n software: `BotKit/${metadata.version}`,\n },\n });\n this.behindProxy = options.behindProxy ?? false;\n this.collectionWindow = options.collectionWindow ?? 50;\n this.initialize();\n }\n\n initialize(): void {\n this.federation\n .setActorDispatcher(\n \"/ap/actor/{identifier}\",\n this.dispatchActor.bind(this),\n )\n .mapHandle(this.mapHandle.bind(this))\n .setKeyPairsDispatcher(this.dispatchActorKeyPairs.bind(this));\n this.federation\n .setFollowersDispatcher(\n \"/ap/actor/{identifier}/followers\",\n this.dispatchFollowers.bind(this),\n )\n .setFirstCursor(this.getFollowersFirstCursor.bind(this))\n .setCounter(this.countFollowers.bind(this));\n this.federation\n .setOutboxDispatcher(\n \"/ap/actor/{identifier}/outbox\",\n this.dispatchOutbox.bind(this),\n )\n .setFirstCursor(this.getOutboxFirstCursor.bind(this))\n .setCounter(this.countOutbox.bind(this));\n this.federation\n .setObjectDispatcher(\n Follow,\n \"/ap/follow/{id}\",\n this.dispatchFollow.bind(this),\n )\n .authorize(this.authorizeFollow.bind(this));\n this.federation.setObjectDispatcher(\n Create,\n \"/ap/create/{id}\",\n this.dispatchCreate.bind(this),\n );\n this.federation.setObjectDispatcher(\n Article,\n \"/ap/article/{id}\",\n (ctx, values) => this.dispatchMessage(Article, ctx, values.id),\n );\n this.federation.setObjectDispatcher(\n ChatMessage,\n \"/ap/chat-message/{id}\",\n (ctx, values) => this.dispatchMessage(ChatMessage, ctx, values.id),\n );\n this.federation.setObjectDispatcher(\n Note,\n \"/ap/note/{id}\",\n (ctx, values) => this.dispatchMessage(Note, ctx, values.id),\n );\n this.federation.setObjectDispatcher(\n Question,\n \"/ap/question/{id}\",\n (ctx, values) => this.dispatchMessage(Question, ctx, values.id),\n );\n this.federation.setObjectDispatcher(\n Announce,\n \"/ap/announce/{id}\",\n this.dispatchAnnounce.bind(this),\n );\n this.federation.setObjectDispatcher(\n APEmoji,\n \"/ap/emoji/{name}\",\n this.dispatchEmoji.bind(this),\n );\n this.federation\n .setInboxListeners(\"/ap/actor/{identifier}/inbox\", \"/ap/inbox\")\n .on(Follow, this.onFollowed.bind(this))\n .on(Undo, async (ctx, undo) => {\n const object = await undo.getObject(ctx);\n if (object instanceof Follow) await this.onUnfollowed(ctx, undo);\n else if (object instanceof RawLike) await this.onUnliked(ctx, undo);\n else {\n const logger = getLogger([\"botkit\", \"bot\", \"inbox\"]);\n logger.warn(\n \"The Undo object {undoId} is not about Follow or Like: {object}.\",\n { undoId: undo.id?.href, object },\n );\n }\n })\n .on(Accept, this.onFollowAccepted.bind(this))\n .on(Reject, this.onFollowRejected.bind(this))\n .on(Create, this.onCreated.bind(this))\n .on(Announce, this.onAnnounced.bind(this))\n .on(RawLike, this.onLiked.bind(this))\n .setSharedKeyDispatcher(this.dispatchSharedKey.bind(this));\n if (this.software != null) {\n this.federation.setNodeInfoDispatcher(\n \"/nodeinfo/2.1\",\n this.dispatchNodeInfo.bind(this),\n );\n }\n }\n\n async getActorSummary(\n session: Session<TContextData>,\n ): Promise<{ text: string; tags: (Link | Object)[] } | null> {\n if (this.summary == null) return null;\n if (this.#summary == null) {\n let summary = \"\";\n const tags: (Link | Object)[] = [];\n for await (const chunk of this.summary.getHtml(session)) {\n summary += chunk;\n }\n for await (const tag of this.summary.getTags(session)) {\n tags.push(tag);\n }\n return this.#summary = { text: summary, tags };\n }\n return this.#summary;\n }\n\n async getActorProperties(\n session: Session<TContextData>,\n ): Promise<{ pairs: PropertyValue[]; tags: (Link | Object)[] }> {\n if (this.#properties != null) return this.#properties;\n const pairs: PropertyValue[] = [];\n const tags: (Link | Object)[] = [];\n for (const name in this.properties) {\n const value = this.properties[name];\n const pair = new PropertyValue({\n name,\n value: (await Array.fromAsync(value.getHtml(session))).join(\"\"),\n });\n pairs.push(pair);\n for await (const tag of value.getTags(session)) {\n tags.push(tag);\n }\n }\n return this.#properties = { pairs, tags };\n }\n\n async dispatchActor(\n ctx: Context<TContextData>,\n identifier: string,\n ): Promise<Actor | null> {\n if (this.identifier !== identifier) return null;\n const session = this.getSession(ctx);\n const summary = await this.getActorSummary(session);\n const { pairs, tags } = await this.getActorProperties(session);\n const allTags = summary == null ? tags : [...tags, ...summary.tags];\n const keyPairs = await ctx.getActorKeyPairs(identifier);\n return new this.class({\n id: ctx.getActorUri(identifier),\n preferredUsername: this.username,\n name: this.name,\n summary: summary == null ? null : summary.text,\n attachments: pairs,\n tags: allTags.filter((tag, i) =>\n allTags.findIndex((t) =>\n t.name?.toString() === tag.name?.toString() &&\n (t instanceof Link\n ? tag instanceof Link && t.href?.href === tag.href?.href\n : tag instanceof Object && t.id?.href === tag.id?.href)\n ) === i\n ),\n icon: this.icon == null\n ? null\n : this.icon instanceof Image\n ? this.icon\n : new Image({ url: this.icon }),\n image: this.image == null\n ? null\n : this.image instanceof Image\n ? this.image\n : new Image({ url: this.image }),\n inbox: ctx.getInboxUri(identifier),\n endpoints: new Endpoints({\n sharedInbox: ctx.getInboxUri(),\n }),\n followers: ctx.getFollowersUri(identifier),\n outbox: ctx.getOutboxUri(identifier),\n publicKey: keyPairs[0].cryptographicKey,\n assertionMethods: keyPairs.map((pair) => pair.multikey),\n url: new URL(\"/\", ctx.origin),\n });\n }\n\n mapHandle(_ctx: Context<TContextData>, username: string): string | null {\n return username === this.username ? this.identifier : null;\n }\n\n async dispatchActorKeyPairs(\n _ctx: Context<TContextData>,\n identifier: string,\n ): Promise<CryptoKeyPair[]> {\n if (identifier !== this.identifier) return [];\n let keyPairs = await this.repository.getKeyPairs();\n if (keyPairs == null) {\n const rsa = await generateCryptoKeyPair(\"RSASSA-PKCS1-v1_5\");\n const ed25519 = await generateCryptoKeyPair(\"Ed25519\");\n keyPairs = [rsa, ed25519];\n await this.repository.setKeyPairs(keyPairs);\n }\n return keyPairs;\n }\n\n async dispatchFollowers(\n _ctx: Context<TContextData>,\n identifier: string,\n cursor: string | null,\n ): Promise<PageItems<Recipient> | null> {\n if (identifier !== this.identifier) return null;\n let followers: AsyncIterable<Actor>;\n let nextCursor: string | null;\n if (cursor == null) {\n followers = this.repository.getFollowers();\n nextCursor = null;\n } else {\n const offset = cursor.match(/^\\d+$/) ? parseInt(cursor) : 0;\n followers = this.repository.getFollowers({\n offset,\n limit: this.collectionWindow,\n });\n nextCursor = (offset + this.collectionWindow).toString();\n }\n const items: Recipient[] = [];\n let i = 0;\n for await (const follower of followers) {\n items.push(follower);\n i++;\n }\n if (i < this.collectionWindow) nextCursor = null;\n return { items, nextCursor };\n }\n\n getFollowersFirstCursor(\n _ctx: Context<TContextData>,\n identifier: string,\n ): string | null {\n if (identifier !== this.identifier) return null;\n return \"0\";\n }\n\n async countFollowers(\n _ctx: Context<TContextData>,\n identifier: string,\n ): Promise<number | null> {\n if (identifier !== this.identifier) return null;\n return await this.repository.countFollowers();\n }\n\n async getPermissionChecker(\n ctx: RequestContext<TContextData>,\n ): Promise<(object: Object) => boolean> {\n let owner: Actor | null;\n try {\n owner = await ctx.getSignedKeyOwner();\n } catch {\n owner = null;\n }\n let follower = false;\n const ownerUri = owner?.id;\n if (ownerUri != null) {\n follower = await this.repository.hasFollower(ownerUri);\n }\n const followersUri = ctx.getFollowersUri(this.identifier);\n return (object: Object): boolean => {\n const recipients = [...object.toIds, ...object.ccIds].map((u) => u.href);\n if (recipients.includes(PUBLIC_COLLECTION.href)) return true;\n if (recipients.includes(followersUri.href) && follower) return true;\n return ownerUri == null ? false : recipients.includes(ownerUri.href);\n };\n }\n\n async dispatchOutbox(\n ctx: RequestContext<TContextData>,\n identifier: string,\n cursor: string | null,\n ): Promise<PageItems<Activity> | null> {\n if (identifier !== this.identifier) return null;\n const activities = this.repository.getMessages({\n order: \"newest\",\n until: cursor == null || cursor === \"\"\n ? undefined\n : Temporal.Instant.from(cursor),\n limit: cursor == null ? undefined : this.collectionWindow + 1,\n });\n const items: Activity[] = [];\n const isVisible = await this.getPermissionChecker(ctx);\n let i = 0;\n let nextPublished: Temporal.Instant | null = null;\n for await (const activity of activities) {\n if (cursor != null && i >= this.collectionWindow) {\n nextPublished = activity.published ??\n (await activity.getObject())?.published ?? null;\n break;\n }\n if (isVisible(activity)) items.push(activity);\n i++;\n }\n return { items, nextCursor: nextPublished?.toString() ?? null };\n }\n\n getOutboxFirstCursor(\n _ctx: Context<TContextData>,\n identifier: string,\n ): string | null {\n if (identifier !== this.identifier) return null;\n return \"\";\n }\n\n async countOutbox(\n _ctx: Context<TContextData>,\n identifier: string,\n ): Promise<number | null> {\n if (identifier !== this.identifier) return null;\n return await this.repository.countMessages();\n }\n\n async dispatchFollow(\n _ctx: RequestContext<TContextData>,\n values: { id: string },\n ): Promise<Follow | null> {\n const id = values.id as Uuid;\n const follow = await this.repository.getSentFollow(id);\n return follow ?? null;\n }\n\n async authorizeFollow(\n _ctx: RequestContext<TContextData>,\n values: { id: string },\n _signedKey: CryptographicKey | null,\n signedKeyOwner: Actor | null,\n ): Promise<boolean> {\n if (signedKeyOwner == null || signedKeyOwner.id == null) return false;\n const id = values.id as Uuid;\n const follow = await this.repository.getSentFollow(id);\n if (follow == null) return false;\n return signedKeyOwner.id.href === follow.objectId?.href ||\n signedKeyOwner.id.href === follow.actorId?.href;\n }\n\n async dispatchCreate(\n ctx: RequestContext<TContextData>,\n values: { id: string },\n ): Promise<Create | null> {\n const activity = await this.repository.getMessage(values.id as Uuid);\n if (!(activity instanceof Create)) return null;\n const isVisible = await this.getPermissionChecker(ctx);\n return isVisible(activity) ? activity : null;\n }\n\n async dispatchMessage<T extends MessageClass>(\n // deno-lint-ignore no-explicit-any\n cls: new (values: any) => T,\n ctx: Context<TContextData> | RequestContext<TContextData>,\n id: string,\n ): Promise<T | null> {\n const activity = await this.repository.getMessage(id as Uuid);\n if (!(activity instanceof Create)) return null;\n if (\"request\" in ctx) {\n // TODO: Split this method into two\n const isVisible = await this.getPermissionChecker(ctx);\n if (!isVisible(activity)) return null;\n }\n const object = await activity.getObject(ctx);\n if (object == null || !(object instanceof cls)) return null;\n return object;\n }\n\n async dispatchAnnounce(\n ctx: RequestContext<TContextData>,\n values: { id: string },\n ): Promise<Announce | null> {\n const activity = await this.repository.getMessage(values.id as Uuid);\n if (!(activity instanceof Announce)) return null;\n const isVisible = await this.getPermissionChecker(ctx);\n return isVisible(activity) ? activity : null;\n }\n\n dispatchEmoji(\n ctx: Context<TContextData>,\n values: { name: string },\n ): APEmoji | null {\n const customEmoji = this.customEmojis[values.name];\n if (customEmoji == null) return null;\n return this.getEmoji(ctx, values.name, customEmoji);\n }\n\n dispatchSharedKey(_ctx: Context<TContextData>): { identifier: string } {\n return { identifier: this.identifier };\n }\n\n async onFollowed(\n ctx: InboxContext<TContextData>,\n follow: Follow,\n ): Promise<void> {\n const botUri = ctx.getActorUri(this.identifier);\n if (\n follow.actorId?.href === botUri.href ||\n follow.objectId?.href !== botUri.href\n ) {\n return;\n }\n const follower = await follow.getActor({\n contextLoader: ctx.contextLoader,\n documentLoader: ctx.documentLoader,\n suppressError: true,\n });\n if (follower == null || follower.id == null) return;\n const session = this.getSession(ctx);\n const followRequest = new FollowRequestImpl<TContextData>(\n session,\n follow,\n follower,\n );\n await this.onFollow?.(session, followRequest);\n if (followRequest.state === \"pending\") {\n if (this.followerPolicy === \"accept\") await followRequest.accept();\n else if (this.followerPolicy === \"reject\") await followRequest.reject();\n }\n }\n\n async onUnfollowed(\n ctx: InboxContext<TContextData>,\n undo: Undo,\n ): Promise<void> {\n const followId = undo.objectId;\n if (followId == null || undo.actorId == null) return;\n const follower = await this.repository.removeFollower(\n followId,\n undo.actorId,\n );\n if (this.onUnfollow != null && follower != null) {\n const session = this.getSession(ctx);\n await this.onUnfollow(session, follower);\n }\n }\n\n async onFollowAccepted(\n ctx: InboxContext<TContextData>,\n accept: Accept,\n ): Promise<void> {\n const parsedObj = ctx.parseUri(accept.objectId);\n if (parsedObj?.type !== \"object\" || parsedObj.class !== Follow) return;\n const follow = await this.repository.getSentFollow(\n parsedObj.values.id as Uuid,\n );\n if (follow == null) return;\n const followee = await follow.getObject(ctx);\n if (\n !isActor(followee) || followee.id == null ||\n followee.id.href !== accept.actorId?.href\n ) {\n return;\n }\n await this.repository.addFollowee(followee.id, follow);\n if (this.onAcceptFollow != null) {\n const session = this.getSession(ctx);\n await this.onAcceptFollow(session, followee);\n }\n }\n\n async onFollowRejected(\n ctx: InboxContext<TContextData>,\n reject: Reject,\n ): Promise<void> {\n const parsedObj = ctx.parseUri(reject.objectId);\n if (parsedObj?.type !== \"object\" || parsedObj.class !== Follow) return;\n const id = parsedObj.values.id as Uuid;\n const follow = await this.repository.getSentFollow(id);\n if (follow == null) return;\n const followee = await follow.getObject(ctx);\n if (\n !isActor(followee) || followee.id == null ||\n followee.id.href !== reject.actorId?.href\n ) {\n return;\n }\n await this.repository.removeSentFollow(id);\n if (this.onRejectFollow != null) {\n const session = this.getSession(ctx);\n await this.onRejectFollow(session, followee);\n }\n }\n\n async onCreated(\n ctx: InboxContext<TContextData>,\n create: Create,\n ): Promise<void> {\n const object = await create.getObject(ctx);\n if (\n !(object instanceof Article || object instanceof ChatMessage ||\n object instanceof Note || object instanceof Question) ||\n object.attributionId?.href !== create.actorId?.href\n ) {\n return;\n }\n const session = this.getSession(ctx);\n let messageCache: Message<MessageClass, TContextData> | null = null;\n const getMessage = async () => {\n if (messageCache != null) return messageCache;\n return messageCache = await createMessage(object, session, {});\n };\n const replyTarget = ctx.parseUri(object.replyTargetId);\n if (\n this.onVote != null &&\n object instanceof Note && replyTarget?.type === \"object\" &&\n // @ts-ignore: replyTarget.class satisfies (typeof messageClasses)[number]\n messageClasses.includes(replyTarget.class) &&\n object.name != null\n ) {\n if (create.actorId?.href === session.actorId.href) return;\n const actor = await create.getActor(ctx);\n if (actor == null) return;\n const pollMessage = await this.repository.getMessage(\n replyTarget.values.id as Uuid,\n );\n if (!(pollMessage instanceof Create)) return;\n const question = await pollMessage.getObject(ctx);\n if (\n !(question instanceof Question) || question.endTime == null ||\n Temporal.Instant.compare(question.endTime, Temporal.Now.instant()) < 0\n ) {\n return;\n }\n const optionNotes: Note[] = [];\n const options: string[] = [];\n for await (const note of question.getInclusiveOptions(ctx)) {\n if (!(note instanceof Note)) continue;\n optionNotes.push(note);\n if (note.name != null) options.push(note.name.toString());\n }\n const multiple = options.length > 0;\n for await (const note of question.getExclusiveOptions(ctx)) {\n if (!(note instanceof Note)) continue;\n optionNotes.push(note);\n if (note.name != null) options.push(note.name.toString());\n }\n const option = object.name.toString();\n if (!options.includes(option)) return;\n const updatedOptionNotes: Note[] = [...optionNotes];\n let i = 0;\n for (const note of updatedOptionNotes) {\n if (note.name === option) {\n const replies = await note.getReplies(ctx);\n if (replies != null && replies.totalItems != null) {\n updatedOptionNotes[i] = note.clone({\n replies: replies.clone({\n // FIXME: This way of updating vote count is not only inefficient,\n // but also can lead to incorrect counts if multiple votes are\n // cast at the same time.\n totalItems: replies.totalItems + 1,\n }),\n });\n }\n }\n i++;\n }\n const updatedQuestion = question.clone({\n inclusiveOptions: multiple ? updatedOptionNotes : [],\n exclusiveOptions: !multiple ? updatedOptionNotes : [],\n });\n const updatedPollMessage = pollMessage.clone({\n object: updatedQuestion,\n });\n await this.repository.updateMessage(\n replyTarget.values.id as Uuid,\n () => updatedPollMessage,\n );\n const message = await createMessage(updatedQuestion, session, {});\n const vote: Vote<TContextData> = {\n raw: object,\n actor,\n message,\n poll: {\n multiple,\n options,\n endTime: question.endTime,\n },\n option,\n };\n await this.onVote(session, vote);\n const update = new Update({\n id: new URL(\n `#update-votes/${crypto.randomUUID()}`,\n updatedQuestion.id ?? ctx.origin,\n ),\n actor: ctx.getActorUri(this.identifier),\n object: updatedPollMessage.id,\n tos: updatedPollMessage.toIds,\n ccs: updatedPollMessage.ccIds,\n });\n if (message.visibility === \"direct\") {\n await ctx.forwardActivity(this, [...message.mentions], {\n skipIfUnsigned: true,\n excludeBaseUris: [new URL(ctx.origin)],\n });\n await ctx.sendActivity(\n this,\n [...message.mentions],\n update,\n { excludeBaseUris: [new URL(ctx.origin)] },\n );\n } else {\n await ctx.forwardActivity(this, \"followers\", {\n skipIfUnsigned: true,\n preferSharedInbox: true,\n excludeBaseUris: [new URL(ctx.origin)],\n });\n await ctx.sendActivity(\n this,\n \"followers\",\n update,\n {\n preferSharedInbox: true,\n excludeBaseUris: [new URL(ctx.origin)],\n },\n );\n }\n return;\n }\n if (\n this.onReply != null &&\n replyTarget?.type === \"object\" &&\n // @ts-ignore: replyTarget.class satisfies (typeof messageClasses)[number]\n messageClasses.includes(replyTarget.class)\n ) {\n const message = await getMessage();\n if (\n message.visibility === \"public\" || message.visibility === \"unlisted\"\n ) {\n await ctx.forwardActivity(this, \"followers\", {\n skipIfUnsigned: true,\n preferSharedInbox: true,\n excludeBaseUris: [new URL(ctx.origin)],\n });\n }\n await this.onReply(session, message);\n }\n let quoteUrl: URL | null = null;\n // FIXME: eliminate this duplication\n for await (const tag of object.getTags(ctx)) {\n if (tag instanceof Link && isQuoteLink(tag)) {\n quoteUrl = tag.href;\n break;\n }\n }\n if (quoteUrl == null) quoteUrl = object.quoteUrl;\n const quoteTarget = ctx.parseUri(quoteUrl);\n if (\n this.onQuote != null &&\n quoteTarget?.type === \"object\" &&\n // @ts-ignore: quoteTarget.class satisfies (typeof messageClasses)[number]\n messageClasses.includes(quoteTarget.class)\n ) {\n const message = await getMessage();\n if (\n message.visibility === \"public\" || message.visibility === \"unlisted\"\n ) {\n await ctx.forwardActivity(this, \"followers\", {\n skipIfUnsigned: true,\n preferSharedInbox: true,\n excludeBaseUris: [new URL(ctx.origin)],\n });\n }\n await this.onQuote(session, message);\n }\n for await (const tag of object.getTags(ctx)) {\n if (\n tag instanceof Mention && tag.href != null && this.onMention != null\n ) {\n const parsed = ctx.parseUri(tag.href);\n if (\n parsed?.type === \"actor\" && parsed.identifier === this.identifier\n ) {\n await this.onMention(session, await getMessage());\n break;\n }\n }\n }\n if (this.onMessage != null) {\n await this.onMessage(session, await getMessage());\n }\n }\n\n async onAnnounced(\n ctx: InboxContext<TContextData>,\n announce: Announce,\n ): Promise<void> {\n if (\n this.onSharedMessage == null || announce.id == null ||\n announce.actorId == null\n ) return;\n const objectUri = ctx.parseUri(announce.objectId);\n let object: Object | null = null;\n if (\n objectUri?.type === \"object\" &&\n // deno-lint-ignore no-explicit-any\n messageClasses.includes(objectUri.class as any)\n ) {\n const msg = await this.repository.getMessage(objectUri.values.id as Uuid);\n if (msg instanceof Create) object = await msg.getObject(ctx);\n } else {\n object = await announce.getObject(ctx);\n }\n if (!isMessageObject(object)) return;\n const session = this.getSession(ctx);\n const actor = announce.actorId.href == session.actorId.href\n ? await session.getActor()\n : await announce.getActor(ctx);\n if (actor == null) return;\n const original = await createMessage(object, session, {});\n const sharedMessage: SharedMessage<MessageClass, TContextData> = {\n raw: announce,\n id: announce.id,\n actor,\n visibility: getMessageVisibility(announce.toIds, announce.ccIds, actor),\n original,\n };\n await this.onSharedMessage(session, sharedMessage);\n }\n\n async #parseLike(\n ctx: InboxContext<TContextData>,\n like: RawLike,\n ): Promise<\n { session: Session<TContextData>; like: Like<TContextData> } | undefined\n > {\n if (like.id == null || like.actorId == null) return undefined;\n const objectUri = ctx.parseUri(like.objectId);\n let object: Object | null = null;\n if (\n objectUri?.type === \"object\" &&\n // deno-lint-ignore no-explicit-any\n messageClasses.includes(objectUri.class as any)\n ) {\n const msg = await this.repository.getMessage(objectUri.values.id as Uuid);\n if (msg instanceof Create) object = await msg.getObject(ctx);\n } else {\n object = await like.getObject(ctx);\n }\n if (!isMessageObject(object)) return undefined;\n const session = this.getSession(ctx);\n const actor = like.actorId.href == session.actorId.href\n ? await session.getActor()\n : await like.getActor(ctx);\n if (actor == null) return;\n const message = await createMessage(object, session, {});\n return {\n session,\n like: {\n raw: like,\n id: like.id,\n actor,\n message,\n },\n };\n }\n\n async onLiked(ctx: InboxContext<TContextData>, like: RawLike): Promise<void> {\n if (like.name != null) return this.onReacted(ctx, like);\n if (this.onLike == null) return;\n const sessionAndLike = await this.#parseLike(ctx, like);\n if (sessionAndLike == null) return;\n const { session, like: likeObject } = sessionAndLike;\n await this.onLike(session, likeObject);\n }\n\n async onUnliked(ctx: InboxContext<TContextData>, undo: Undo): Promise<void> {\n const like = await undo.getObject(ctx);\n if (!(like instanceof RawLike)) return;\n if (like.name != null) return this.onUnreacted(ctx, undo);\n if (this.onUnlike == null) return;\n if (undo.actorId?.href !== like.actorId?.href) return;\n const sessionAndLike = await this.#parseLike(ctx, like);\n if (sessionAndLike == null) return;\n const { session, like: likeObject } = sessionAndLike;\n await this.onUnlike(session, likeObject);\n }\n\n async #parseReaction(\n ctx: InboxContext<TContextData>,\n react: EmojiReact | RawLike,\n ): Promise<\n | { session: Session<TContextData>; reaction: Reaction<TContextData> }\n | undefined\n > {\n if (react.id == null || react.actorId == null || react.name == null) {\n return undefined;\n }\n let emoji: Emoji | APEmoji | undefined;\n if (isEmoji(react.name)) {\n emoji = react.name;\n } else if (\n typeof react.name === \"string\" && react.name.startsWith(\":\") &&\n react.name.endsWith(\":\")\n ) {\n for await (const tag of react.getTags(ctx)) {\n if (tag instanceof APEmoji && tag.name === react.name) {\n emoji = tag;\n break;\n }\n }\n }\n if (emoji == null) return undefined;\n const objectUri = ctx.parseUri(react.objectId);\n let object: Object | null = null;\n if (\n objectUri?.type === \"object\" &&\n // deno-lint-ignore no-explicit-any\n messageClasses.includes(objectUri.class as any)\n ) {\n const msg = await this.repository.getMessage(objectUri.values.id as Uuid);\n if (msg instanceof Create) object = await msg.getObject(ctx);\n } else {\n object = await react.getObject(ctx);\n }\n if (!isMessageObject(object)) return undefined;\n const session = this.getSession(ctx);\n const actor = react.actorId.href == session.actorId.href\n ? await session.getActor()\n : await react.getActor(ctx);\n if (actor == null) return;\n const message = await createMessage(object, session, {});\n return {\n session,\n reaction: {\n raw: react,\n id: react.id,\n actor,\n message,\n emoji,\n },\n };\n }\n\n async onReacted(\n ctx: InboxContext<TContextData>,\n react: EmojiReact | RawLike,\n ): Promise<void> {\n if (this.onReact == null) return;\n const sessionAndReaction = await this.#parseReaction(ctx, react);\n if (sessionAndReaction == null) return;\n const { session, reaction } = sessionAndReaction;\n await this.onReact(session, reaction);\n }\n\n async onUnreacted(\n ctx: InboxContext<TContextData>,\n undo: Undo,\n ): Promise<void> {\n if (this.onUnreact == null) return;\n const react = await undo.getObject(ctx);\n if (!(react instanceof EmojiReact || react instanceof RawLike)) return;\n if (undo.actorId?.href !== react.actorId?.href) return;\n const sessionAndReaction = await this.#parseReaction(ctx, react);\n if (sessionAndReaction == null) return;\n const { session, reaction } = sessionAndReaction;\n await this.onUnreact(session, reaction);\n }\n\n dispatchNodeInfo(_ctx: Context<TContextData>): NodeInfo {\n return {\n software: this.software!,\n protocols: [\"activitypub\"],\n services: {\n outbound: [\"atom1.0\"], // TODO\n },\n usage: {\n users: {\n total: 1,\n activeMonth: 1, // FIXME\n activeHalfyear: 1, // FIXME\n },\n localPosts: 0, // FIXME\n localComments: 0,\n },\n };\n }\n\n getSession(\n origin: string | URL,\n contextData: TContextData,\n ): SessionImpl<TContextData>;\n getSession(origin: string | URL): SessionImpl<TContextData>;\n getSession(context: Context<TContextData>): SessionImpl<TContextData>;\n\n getSession(\n origin: string | URL | Context<TContextData>,\n contextData?: TContextData,\n ): SessionImpl<TContextData> {\n const ctx = typeof origin === \"string\" || origin instanceof URL\n ? this.federation.createContext(new URL(origin), contextData!)\n : origin;\n return new SessionImpl(this, ctx);\n }\n\n async fetch(request: Request, contextData: TContextData): Promise<Response> {\n if (this.behindProxy) {\n request = await getXForwardedRequest(request);\n }\n const url = new URL(request.url);\n if (\n url.pathname.startsWith(\"/.well-known/\") ||\n url.pathname.startsWith(\"/ap/\") ||\n url.pathname.startsWith(\"/nodeinfo/\")\n ) {\n return await this.federation.fetch(request, { contextData });\n }\n const match = /^\\/emojis\\/([a-z0-9-_]+)(?:$|\\.)/.exec(url.pathname);\n if (match != null) {\n const customEmoji = this.customEmojis[match[1]];\n if (customEmoji == null || !(\"file\" in customEmoji)) {\n return new Response(\"Not Found\", { status: 404 });\n }\n let file: fs.FileHandle;\n try {\n file = await fs.open(customEmoji.file, \"r\");\n } catch (error) {\n if (\n typeof error === \"object\" && error != null && \"code\" in error &&\n error.code === \"ENOENT\"\n ) {\n return new Response(\"Not Found\", { status: 404 });\n }\n throw error;\n }\n const fileInfo = await file.stat();\n return new Response(file.readableWebStream(), {\n headers: {\n \"Content-Type\": customEmoji.type,\n \"Content-Length\": fileInfo.size.toString(),\n \"Cache-Control\": \"public, max-age=31536000, immutable\",\n \"Last-Modified\": (fileInfo.mtime ?? new Date()).toUTCString(),\n \"ETag\": `\"${fileInfo.mtime?.getTime().toString(36)}${\n fileInfo.size.toString(36)\n }\"`,\n },\n });\n }\n return await app.fetch(request, { bot: this, contextData });\n }\n\n getEmoji(\n ctx: Context<TContextData>,\n name: string,\n data: CustomEmoji,\n ): APEmoji {\n let url: URL;\n if (\"url\" in data) {\n url = new URL(data.url);\n } else {\n // @ts-ignore: data.type satisfies keyof typeof mimeDb\n const t = mimeDb[data.type];\n url = new URL(\n `/emojis/${name}${\n t == null || t.extensions == null || t.extensions.length < 1\n ? \"\"\n : `.${t.extensions[0]}`\n }`,\n ctx.origin,\n );\n }\n return new APEmoji({\n id: ctx.getObjectUri(APEmoji, { name }),\n name: `:${name}:`,\n icon: new Image({\n mediaType: data.type,\n url,\n }),\n });\n }\n\n addCustomEmoji<TEmojiName extends string>(\n name: TEmojiName,\n data: CustomEmoji,\n ): DeferredCustomEmoji<TContextData> {\n if (!name.match(/^[a-z0-9-_]+$/i)) {\n throw new TypeError(\n `Invalid custom emoji name: ${name}. It must match /^[a-z0-9-_]+$/i.`,\n );\n } else if (name in this.customEmojis) {\n throw new TypeError(`Duplicate custom emoji name: ${name}`);\n } else if (!data.type.startsWith(\"image/\")) {\n throw new TypeError(`Unsupported media type: ${data.type}`);\n }\n this.customEmojis[name] = data;\n return (session: Session<TContextData>) =>\n this.getEmoji(\n session.context,\n name,\n data,\n );\n }\n\n addCustomEmojis<TEmojiName extends string>(\n emojis: Readonly<Record<TEmojiName, CustomEmoji>>,\n ): Readonly<Record<TEmojiName, DeferredCustomEmoji<TContextData>>> {\n const emojiMap = {} as Record<\n TEmojiName,\n DeferredCustomEmoji<TContextData>\n >;\n for (const name in emojis) {\n emojiMap[name] = this.addCustomEmoji(name, emojis[name]);\n }\n return emojiMap;\n }\n}\n"],"mappings":"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"}
package/dist/deno.js CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  //#region deno.json
6
6
  var name = "@fedify/botkit";
7
- var version = "0.3.0-dev.112+8f983226";
7
+ var version = "0.3.0-dev.115+d719ad73";
8
8
  var license = "AGPL-3.0-only";
9
9
  var unstable = ["kv", "temporal"];
10
10
  var exports = {
package/dist/deno.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"deno.js","names":[],"sources":["../deno.json"],"sourcesContent":["{\n \"name\": \"@fedify/botkit\",\n \"version\": \"0.3.0-dev.112+8f983226\",\n \"license\": \"AGPL-3.0-only\",\n \"unstable\": [\n \"kv\",\n \"temporal\"\n ],\n \"exports\": {\n \".\": \"./src/mod.ts\",\n \"./bot\": \"./src/bot.ts\",\n \"./emoji\": \"./src/emoji.ts\",\n \"./events\": \"./src/events.ts\",\n \"./follow\": \"./src/follow.ts\",\n \"./message\": \"./src/message.ts\",\n \"./poll\": \"./src/poll.ts\",\n \"./reaction\": \"./src/reaction.ts\",\n \"./repository\": \"./src/repository.ts\",\n \"./session\": \"./src/session.ts\",\n \"./text\": \"./src/text.ts\"\n },\n \"imports\": {\n \"@fedify/fedify\": \"jsr:@fedify/fedify@^1.7.1\",\n \"@fedify/markdown-it-hashtag\": \"jsr:@fedify/markdown-it-hashtag@^0.3.0\",\n \"@fedify/markdown-it-mention\": \"jsr:@fedify/markdown-it-mention@^0.3.0\",\n \"@logtape/logtape\": \"jsr:@logtape/logtape@^1.0.0\",\n \"@phensley/language-tag\": \"npm:@phensley/language-tag@^1.12.2\",\n \"hono\": \"jsr:@hono/hono@^4.8.2\",\n \"html-entities\": \"npm:html-entities@^2.6.0\",\n \"markdown-it\": \"npm:markdown-it@^14.1.0\",\n \"mime-db\": \"npm:mime-db@^1.54.0\",\n \"tsdown\": \"npm:tsdown@^0.12.8\",\n \"uuid\": \"npm:uuid@^11.1.0\",\n \"x-forwarded-fetch\": \"jsr:@hongminhee/x-forwarded-fetch@^0.2.0\",\n \"xss\": \"npm:xss@^1.0.15\"\n },\n \"nodeModulesDir\": \"none\",\n \"exclude\": [\n \".github\",\n \".vscode\",\n \"dist\",\n \"docs\",\n \"src/css\"\n ],\n \"fmt\": {\n \"exclude\": [\n \"*.md\",\n \"*.yaml\",\n \"*.yml\",\n \"src/static/*.ts\"\n ]\n },\n \"tasks\": {\n \"check\": \"deno check src/ && deno lint && deno fmt --check && deno publish --dry-run --allow-dirty && deno run scripts/check_versions.ts\",\n \"test\": \"deno test --allow-env=NODE_V8_COVERAGE,JEST_WORKER_ID --allow-net=hollo.social --parallel\",\n \"test:node\": \"pnpm install && pnpm test\",\n \"test-all\": {\n \"dependencies\": [\n \"check\",\n \"test\",\n \"test:node\"\n ]\n },\n \"coverage\": \"deno task test --coverage --clean && deno coverage --html\",\n \"hooks:install\": \"deno run --allow-read=deno.json,.git/hooks/ --allow-write=.git/hooks/ jsr:@hongminhee/deno-task-hooks\",\n \"hooks:pre-commit\": \"deno task check\"\n }\n}\n"],"mappings":";;;;;WACU;cACG;cACA;eACC,CACV,MACA,UACD;cACU;CACT,KAAK;CACL,SAAS;CACT,WAAW;CACX,YAAY;CACZ,YAAY;CACZ,aAAa;CACb,UAAU;CACV,cAAc;CACd,gBAAgB;CAChB,aAAa;CACb,UAAU;AACX;cACU;CACT,kBAAkB;CAClB,+BAA+B;CAC/B,+BAA+B;CAC/B,oBAAoB;CACpB,0BAA0B;CAC1B,QAAQ;CACR,iBAAiB;CACjB,eAAe;CACf,WAAW;CACX,UAAU;CACV,QAAQ;CACR,qBAAqB;CACrB,OAAO;AACR;qBACiB;cACP;CACT;CACA;CACA;CACA;CACA;AACD;UACM,EACL,WAAW;CACT;CACA;CACA;CACA;AACD,EACF;YACQ;CACP,SAAS;CACT,QAAQ;CACR,aAAa;CACb,YAAY,EACV,gBAAgB;EACd;EACA;EACA;CACD,EACF;CACD,YAAY;CACZ,iBAAiB;CACjB,oBAAoB;AACrB;mBAlEH;;;;;;;;;;;AAmEC"}
1
+ {"version":3,"file":"deno.js","names":[],"sources":["../deno.json"],"sourcesContent":["{\n \"name\": \"@fedify/botkit\",\n \"version\": \"0.3.0-dev.115+d719ad73\",\n \"license\": \"AGPL-3.0-only\",\n \"unstable\": [\n \"kv\",\n \"temporal\"\n ],\n \"exports\": {\n \".\": \"./src/mod.ts\",\n \"./bot\": \"./src/bot.ts\",\n \"./emoji\": \"./src/emoji.ts\",\n \"./events\": \"./src/events.ts\",\n \"./follow\": \"./src/follow.ts\",\n \"./message\": \"./src/message.ts\",\n \"./poll\": \"./src/poll.ts\",\n \"./reaction\": \"./src/reaction.ts\",\n \"./repository\": \"./src/repository.ts\",\n \"./session\": \"./src/session.ts\",\n \"./text\": \"./src/text.ts\"\n },\n \"imports\": {\n \"@fedify/fedify\": \"jsr:@fedify/fedify@^1.7.1\",\n \"@fedify/markdown-it-hashtag\": \"jsr:@fedify/markdown-it-hashtag@^0.3.0\",\n \"@fedify/markdown-it-mention\": \"jsr:@fedify/markdown-it-mention@^0.3.0\",\n \"@logtape/logtape\": \"jsr:@logtape/logtape@^1.0.0\",\n \"@phensley/language-tag\": \"npm:@phensley/language-tag@^1.12.2\",\n \"hono\": \"jsr:@hono/hono@^4.8.2\",\n \"html-entities\": \"npm:html-entities@^2.6.0\",\n \"markdown-it\": \"npm:markdown-it@^14.1.0\",\n \"mime-db\": \"npm:mime-db@^1.54.0\",\n \"tsdown\": \"npm:tsdown@^0.12.8\",\n \"uuid\": \"npm:uuid@^11.1.0\",\n \"x-forwarded-fetch\": \"jsr:@hongminhee/x-forwarded-fetch@^0.2.0\",\n \"xss\": \"npm:xss@^1.0.15\"\n },\n \"nodeModulesDir\": \"none\",\n \"exclude\": [\n \".github\",\n \".vscode\",\n \"dist\",\n \"docs\",\n \"src/css\"\n ],\n \"fmt\": {\n \"exclude\": [\n \"*.md\",\n \"*.yaml\",\n \"*.yml\",\n \"src/static/*.ts\"\n ]\n },\n \"tasks\": {\n \"check\": \"deno check src/ && deno lint && deno fmt --check && deno publish --dry-run --allow-dirty && deno run scripts/check_versions.ts\",\n \"test\": \"deno test --allow-env=NODE_V8_COVERAGE,JEST_WORKER_ID --allow-net=hollo.social --parallel\",\n \"test:node\": \"pnpm install && pnpm test\",\n \"test-all\": {\n \"dependencies\": [\n \"check\",\n \"test\",\n \"test:node\"\n ]\n },\n \"coverage\": \"deno task test --coverage --clean && deno coverage --html\",\n \"hooks:install\": \"deno run --allow-read=deno.json,.git/hooks/ --allow-write=.git/hooks/ jsr:@hongminhee/deno-task-hooks\",\n \"hooks:pre-commit\": \"deno task check\"\n }\n}\n"],"mappings":";;;;;WACU;cACG;cACA;eACC,CACV,MACA,UACD;cACU;CACT,KAAK;CACL,SAAS;CACT,WAAW;CACX,YAAY;CACZ,YAAY;CACZ,aAAa;CACb,UAAU;CACV,cAAc;CACd,gBAAgB;CAChB,aAAa;CACb,UAAU;AACX;cACU;CACT,kBAAkB;CAClB,+BAA+B;CAC/B,+BAA+B;CAC/B,oBAAoB;CACpB,0BAA0B;CAC1B,QAAQ;CACR,iBAAiB;CACjB,eAAe;CACf,WAAW;CACX,UAAU;CACV,QAAQ;CACR,qBAAqB;CACrB,OAAO;AACR;qBACiB;cACP;CACT;CACA;CACA;CACA;CACA;AACD;UACM,EACL,WAAW;CACT;CACA;CACA;CACA;AACD,EACF;YACQ;CACP,SAAS;CACT,QAAQ;CACR,aAAa;CACb,YAAY,EACV,gBAAgB;EACd;EACA;EACA;CACD,EACF;CACD,YAAY;CACZ,iBAAiB;CACjB,oBAAoB;AACrB;mBAlEH;;;;;;;;;;;AAmEC"}
@@ -1 +1 @@
1
- {"version":3,"file":"session-impl.d.ts","names":[],"sources":["../src/session-impl.ts"],"sourcesContent":[],"mappings":";;;;;;;;;UAkDiB,gDACP,sBAAsB;gBAChB,QAAQ,cAAc;;UAGrB,6CACL,oCAGV,+BAA+B,GAAG,eAClC,0BAA0B;UAGX,4DAEb,kCAAkC,eAClC,mCAAmC,UAAU,eAhBjD;AAA0C,cAmB7B,WAnB6B,CAAA,YAAA,CAAA,YAmBQ,OAnBR,CAmBgB,YAnBhB,CAAA,CAAA;EAAA,SACV,GAAA,EAmBhB,OAnBgB,CAmBR,YAnBQ,CAAA;EAAY,SACpB,OAAA,EAmBJ,OAnBI,CAmBI,YAnBJ,CAAA;EAAY,WAAE,CAAA,GAAA,EAqBnB,OArBmB,CAqBX,YArBW,CAAA,EAAA,OAAA,EAqBa,OArBb,CAqBqB,YArBrB,CAAA;EAAY,IAAlC,OAAA,CAAA,CAAA,EA0BH,GA1BG;EAAO,IADb,WAAA,CAAA,CAAA,EAAA,IAAA,MAAA,IAAA,MAAA,EAAA;EAAqB,QAAA,CAAA,CAAA,EAmCX,OAnCW,CAmCH,KAnCG,CAAA;EAId,MAAA,CAAA,KAAA,EAmCK,KAnCL,GAmCa,GAnCb,GAAA,MAAA,CAAA,EAmC4B,OAnCM,CAAA,IAAA,CAAA;EAAA,QAAA,CAAA,KAAA,EAgF3B,KAhF2B,GAgFnB,GAhFmB,GAAA,MAAA,CAAA,EAgFJ,OAhFI,CAAA,IAAA,CAAA;EAAA,OACvC,CAAA,KAAA,EA4HW,KA5HX,GA4HmB,GA5HnB,GAAA,MAAA,CAAA,EA4HkC,OA5HlC,CAAA,OAAA,CAAA;EAAY,OAGS,CAAA,OAAA,EA0JpB,IA1JoB,CAAA,OAAA,EA0JN,YA1JM,CAAA,EAAA,OAAA,CAAA,EA2JnB,yBA3JmB,CA2JO,YA3JP,CAAA,CAAA,EA4J5B,OA5J4B,CA4JpB,iBA5JoB,CA4JF,IA5JE,EA4JI,YA5JJ,CAAA,CAAA;EAAC,OAAE,CAAA,UA6JV,YA7JU,CAAA,CAAA,OAAA,EA8JvB,IA9JuB,CAAA,OAAA,EA8JT,YA9JS,CAAA,EAAA,OAAA,EA+JvB,kCA/JuB,CA+JY,CA/JZ,EA+Je,YA/Jf,CAAA,CAAA,EAgK/B,OAhK+B,CAgKvB,iBAhKuB,CAgKL,CAhKK,EAgKF,YAhKE,CAAA,CAAA;EAAY,OACpB,CAAA,OAAA,EAiKf,IAjKe,CAAA,OAAA,EAiKD,YAjKC,CAAA,EAAA,OAAA,EAkKf,qCAlKe,CAkKuB,YAlKvB,CAAA,CAAA,EAmKvB,OAnKuB,CAmKf,iBAnKe,CAmKG,QAnKH,EAmKa,YAnKb,CAAA,CAAA;EAAY,SADtC,CAAA,OAAA,CAAA,EAmUW,uBAnUX,CAAA,EAoUG,aApUH,CAoUiB,iBApUjB,CAoUmC,YApUnC,EAoUiD,YApUjD,CAAA,CAAA;;AACyB"}
1
+ {"version":3,"file":"session-impl.d.ts","names":[],"sources":["../src/session-impl.ts"],"sourcesContent":[],"mappings":";;;;;;;;;UAkDiB,gDACP,sBAAsB;gBAChB,QAAQ,cAAc;;UAGrB,6CACL,oCAGV,+BAA+B,GAAG,eAClC,0BAA0B;UAGX,4DAEb,kCAAkC,eAClC,mCAAmC,UAAU,eAhBjD;AAA0C,cAmB7B,WAnB6B,CAAA,YAAA,CAAA,YAmBQ,OAnBR,CAmBgB,YAnBhB,CAAA,CAAA;EAAA,SACV,GAAA,EAmBhB,OAnBgB,CAmBR,YAnBQ,CAAA;EAAY,SACpB,OAAA,EAmBJ,OAnBI,CAmBI,YAnBJ,CAAA;EAAY,WAAE,CAAA,GAAA,EAqBnB,OArBmB,CAqBX,YArBW,CAAA,EAAA,OAAA,EAqBa,OArBb,CAqBqB,YArBrB,CAAA;EAAY,IAAlC,OAAA,CAAA,CAAA,EA0BH,GA1BG;EAAO,IADb,WAAA,CAAA,CAAA,EAAA,IAAA,MAAA,IAAA,MAAA,EAAA;EAAqB,QAAA,CAAA,CAAA,EAmCX,OAnCW,CAmCH,KAnCG,CAAA;EAId,MAAA,CAAA,KAAA,EAmCK,KAnCL,GAmCa,GAnCb,GAAA,MAAA,CAAA,EAmC4B,OAnCM,CAAA,IAAA,CAAA;EAAA,QAAA,CAAA,KAAA,EAgF3B,KAhF2B,GAgFnB,GAhFmB,GAAA,MAAA,CAAA,EAgFJ,OAhFI,CAAA,IAAA,CAAA;EAAA,OACvC,CAAA,KAAA,EA4HW,KA5HX,GA4HmB,GA5HnB,GAAA,MAAA,CAAA,EA4HkC,OA5HlC,CAAA,OAAA,CAAA;EAAY,OAGS,CAAA,OAAA,EA0JpB,IA1JoB,CAAA,OAAA,EA0JN,YA1JM,CAAA,EAAA,OAAA,CAAA,EA2JnB,yBA3JmB,CA2JO,YA3JP,CAAA,CAAA,EA4J5B,OA5J4B,CA4JpB,iBA5JoB,CA4JF,IA5JE,EA4JI,YA5JJ,CAAA,CAAA;EAAC,OAAE,CAAA,UA6JV,YA7JU,CAAA,CAAA,OAAA,EA8JvB,IA9JuB,CAAA,OAAA,EA8JT,YA9JS,CAAA,EAAA,OAAA,EA+JvB,kCA/JuB,CA+JY,CA/JZ,EA+Je,YA/Jf,CAAA,CAAA,EAgK/B,OAhK+B,CAgKvB,iBAhKuB,CAgKL,CAhKK,EAgKF,YAhKE,CAAA,CAAA;EAAY,OACpB,CAAA,OAAA,EAiKf,IAjKe,CAAA,OAAA,EAiKD,YAjKC,CAAA,EAAA,OAAA,EAkKf,qCAlKe,CAkKuB,YAlKvB,CAAA,CAAA,EAmKvB,OAnKuB,CAmKf,iBAnKe,CAmKG,QAnKH,EAmKa,YAnKb,CAAA,CAAA;EAAY,SADtC,CAAA,OAAA,CAAA,EA4UW,uBA5UX,CAAA,EA6UG,aA7UH,CA6UiB,iBA7UjB,CA6UmC,YA7UnC,EA6UiD,YA7UjD,CAAA,CAAA;;AACyB"}
@@ -121,6 +121,9 @@ var SessionImpl = class {
121
121
  let voters = null;
122
122
  let endTime = null;
123
123
  if ("class" in options && options.class === Question && "poll" in options) {
124
+ if (options.poll.options.length < 2) throw new TypeError("At least two options are required in a poll.");
125
+ else if (new Set(options.poll.options).size != options.poll.options.length) throw new TypeError("Duplicate options are not allowed in a poll.");
126
+ else if (options.poll.options.some((o) => o.trim() === "")) throw new TypeError("Poll options cannot be empty.");
124
127
  const pollOptions = options.poll.options.map((option) => new Note$1({
125
128
  name: option,
126
129
  replies: new Collection({ totalItems: 0 })
@@ -1 +1 @@
1
- {"version":3,"file":"session-impl.js","names":["bot: BotImpl<TContextData>","context: Context<TContextData>","actor: Actor | URL | string","actorId: URL","content: Text<\"block\", TContextData>","options:\n | SessionImplPublishOptions<TContextData>\n | SessionImplPublishOptionsWithClass<MessageClass, TContextData>\n | SessionImplPublishOptionsWithQuestion<TContextData>","Note","mentionedActorIds: URL[]","Mention","inclusiveOptions: Note[]","exclusiveOptions: Note[]","voters: number | null","endTime: Temporal.Instant | null","PUBLIC_COLLECTION","Create","cachedObjects: Record<string, Object>","promises: Promise<Object | null>[]","isActor","options: SessionGetOutboxOptions","object: Object | null"],"sources":["../src/session-impl.ts"],"sourcesContent":["// BotKit by Fedify: A framework for creating ActivityPub bots\n// Copyright (C) 2025 Hong Minhee <https://hongminhee.org/>\n//\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as\n// published by the Free Software Foundation, either version 3 of the\n// License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program. If not, see <https://www.gnu.org/licenses/>.\nimport {\n type Actor,\n type Context,\n Create,\n isActor,\n LanguageString,\n Mention,\n Note,\n type Object,\n PUBLIC_COLLECTION,\n} from \"@fedify/fedify\";\nimport { Collection, Follow, Link, Undo } from \"@fedify/fedify/vocab\";\nimport { getLogger } from \"@logtape/logtape\";\nimport { encode } from \"html-entities\";\nimport { v7 as uuidv7 } from \"uuid\";\nimport type { BotImpl } from \"./bot-impl.ts\";\nimport { createMessage, isMessageObject } from \"./message-impl.ts\";\nimport {\n type AuthorizedMessage,\n type Message,\n type MessageClass,\n Question,\n} from \"./message.ts\";\nimport type { Uuid } from \"./repository.ts\";\nimport type {\n Session,\n SessionGetOutboxOptions,\n SessionPublishOptions,\n SessionPublishOptionsWithClass,\n SessionPublishOptionsWithQuestion,\n} from \"./session.ts\";\nimport type { Text } from \"./text.ts\";\n\nconst logger = getLogger([\"botkit\", \"session\"]);\n\nexport interface SessionImplPublishOptions<TContextData>\n extends SessionPublishOptions<TContextData> {\n replyTarget?: Message<MessageClass, TContextData>;\n}\n\nexport interface SessionImplPublishOptionsWithClass<\n T extends MessageClass,\n TContextData,\n> extends\n SessionPublishOptionsWithClass<T, TContextData>,\n SessionImplPublishOptions<TContextData> {\n}\n\nexport interface SessionImplPublishOptionsWithQuestion<TContextData>\n extends\n SessionPublishOptionsWithQuestion<TContextData>,\n SessionImplPublishOptionsWithClass<Question, TContextData> {\n}\n\nexport class SessionImpl<TContextData> implements Session<TContextData> {\n readonly bot: BotImpl<TContextData>;\n readonly context: Context<TContextData>;\n\n constructor(bot: BotImpl<TContextData>, context: Context<TContextData>) {\n this.bot = bot;\n this.context = context;\n }\n\n get actorId() {\n return this.context.getActorUri(this.bot.identifier);\n }\n\n get actorHandle() {\n return `@${this.bot.username}@${this.context.host}` as const;\n }\n\n async getActor(): Promise<Actor> {\n return (await this.bot.dispatchActor(this.context, this.bot.identifier))!;\n }\n\n async follow(actor: Actor | URL | string): Promise<void> {\n if (actor instanceof URL || typeof actor === \"string\") {\n if (\n actor instanceof URL && actor.href === this.actorId.href ||\n typeof actor === \"string\" &&\n (actor === this.actorId.href || actor === this.actorHandle)\n ) {\n throw new TypeError(\"The bot cannot follow itself.\");\n }\n const documentLoader = await this.context.getDocumentLoader(this.bot);\n const object = await this.context.lookupObject(actor, { documentLoader });\n if (!isActor(object)) {\n throw new TypeError(\"The resolved object is not an Actor.\");\n }\n actor = object;\n }\n if (actor.id == null) {\n throw new TypeError(\"The actor does not have an ID.\");\n } else if (actor.id.href === this.actorId.href) {\n throw new TypeError(\"The bot cannot follow itself.\");\n }\n const followee = await this.bot.repository.getFollowee(actor.id);\n if (followee != null) {\n logger.warn(\n \"The bot is already following the actor {actor}.\",\n { actor: actor.id.href },\n );\n return;\n }\n const id = uuidv7() as Uuid;\n const follow = new Follow({\n id: this.context.getObjectUri(Follow, { id }),\n actor: this.context.getActorUri(this.bot.identifier),\n object: actor.id,\n to: actor.id,\n });\n await this.bot.repository.addSentFollow(id, follow);\n await this.context.sendActivity(\n this.bot,\n actor,\n follow,\n { excludeBaseUris: [new URL(this.context.origin)] },\n );\n }\n\n async unfollow(actor: Actor | URL | string): Promise<void> {\n const documentLoader = await this.context.getDocumentLoader(this.bot);\n if (actor instanceof URL || typeof actor === \"string\") {\n if (\n actor instanceof URL && actor.href === this.actorId.href ||\n typeof actor === \"string\" &&\n (actor === this.actorId.href || actor === this.actorHandle)\n ) {\n throw new TypeError(\"The bot cannot unfollow itself.\");\n }\n const object = await this.context.lookupObject(actor, { documentLoader });\n if (!isActor(object)) {\n throw new TypeError(\"The resolved object is not an Actor.\");\n }\n actor = object;\n }\n if (actor.id == null) {\n throw new TypeError(\"The actor does not have an ID.\");\n } else if (actor.id.href === this.actorId.href) {\n throw new TypeError(\"The bot cannot unfollow itself.\");\n }\n const follow = await this.bot.repository.getFollowee(actor.id);\n if (follow == null) {\n logger.warn(\n \"The bot is not following the actor {actor}.\",\n { actor: actor.id.href },\n );\n return;\n }\n await this.bot.repository.removeFollowee(actor.id);\n if (follow.id != null && follow.objectId?.href === actor.id.href) {\n await this.context.sendActivity(\n this.bot,\n actor,\n new Undo({\n id: new URL(\"#undo\", follow.id),\n actor: this.context.getActorUri(this.bot.identifier),\n object: follow,\n to: actor.id,\n }),\n { excludeBaseUris: [new URL(this.context.origin)] },\n );\n }\n }\n\n async follows(actor: Actor | URL | string): Promise<boolean> {\n let actorId: URL;\n if (isActor(actor)) {\n if (actor.id == null) {\n throw new TypeError(\"The actor does not have an ID.\");\n }\n actorId = actor.id;\n } else if (actor instanceof URL) {\n actorId = actor;\n } else {\n if (actor.startsWith(\"http://\") || actor.startsWith(\"https://\")) {\n actorId = new URL(actor);\n } else {\n if (actor === this.actorHandle) return false;\n const documentLoader = await this.context.getDocumentLoader(this.bot);\n const object = await this.context.lookupObject(actor, {\n documentLoader,\n });\n if (!isActor(object)) {\n throw new TypeError(\"The resolved object is not an Actor.\");\n }\n if (object.id == null) {\n throw new TypeError(\"The actor does not have an ID.\");\n }\n actorId = object.id;\n }\n }\n if (actorId.href === this.actorId.href) return false;\n const follow = await this.bot.repository.getFollowee(actorId);\n return follow != null;\n }\n\n async publish(\n content: Text<\"block\", TContextData>,\n options?: SessionImplPublishOptions<TContextData>,\n ): Promise<AuthorizedMessage<Note, TContextData>>;\n async publish<T extends MessageClass>(\n content: Text<\"block\", TContextData>,\n options: SessionImplPublishOptionsWithClass<T, TContextData>,\n ): Promise<AuthorizedMessage<T, TContextData>>;\n async publish(\n content: Text<\"block\", TContextData>,\n options: SessionImplPublishOptionsWithQuestion<TContextData>,\n ): Promise<AuthorizedMessage<Question, TContextData>>;\n async publish(\n content: Text<\"block\", TContextData>,\n options:\n | SessionImplPublishOptions<TContextData>\n | SessionImplPublishOptionsWithClass<MessageClass, TContextData>\n | SessionImplPublishOptionsWithQuestion<TContextData> = {},\n ): Promise<AuthorizedMessage<MessageClass, TContextData>> {\n const published = new Date();\n const id = uuidv7({ msecs: +published }) as Uuid;\n const cls = \"class\" in options ? options.class : Note;\n const visibility = options.visibility ?? \"public\";\n let contentHtml = \"\";\n for await (const chunk of content.getHtml(this)) {\n contentHtml += chunk;\n }\n const tags = await Array.fromAsync(content.getTags(this));\n const mentionedActorIds: URL[] = [];\n for (const tag of tags) {\n if (tag instanceof Mention && tag.href != null) {\n mentionedActorIds.push(tag.href);\n }\n }\n if (options.quoteTarget != null) {\n let url = options.quoteTarget.raw.url ?? options.quoteTarget.id;\n if (url instanceof Link) url = url.href ?? options.quoteTarget.id;\n contentHtml += `\\n\\n<p class=\"quote-inline\"><br>RE: <a href=\"${\n encode(url.href)\n }\">${encode(url.href)}</a></p>`;\n tags.push(\n new Link({\n mediaType:\n 'application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"',\n rel: \"https://misskey-hub.net/ns#_misskey_quote\",\n href: options.quoteTarget.id,\n name: `RE: ${url.href}`,\n }),\n );\n }\n let inclusiveOptions: Note[] = [];\n let exclusiveOptions: Note[] = [];\n let voters: number | null = null;\n let endTime: Temporal.Instant | null = null;\n if (\"class\" in options && options.class === Question && \"poll\" in options) {\n const pollOptions = options.poll.options.map((option) =>\n new Note({\n name: option,\n replies: new Collection({ totalItems: 0 }),\n })\n );\n if (options.poll.multiple) inclusiveOptions = pollOptions;\n else exclusiveOptions = pollOptions;\n voters = 0;\n endTime = options.poll.endTime;\n }\n const msg = new cls({\n id: this.context.getObjectUri<MessageClass>(cls, { id }),\n contents: options.language == null\n ? [contentHtml]\n : [new LanguageString(contentHtml, options.language), contentHtml],\n replyTarget: options.replyTarget?.id,\n quoteUrl: options.quoteTarget?.id,\n tags,\n attribution: this.context.getActorUri(this.bot.identifier),\n attachments: options.attachments ?? [],\n inclusiveOptions,\n exclusiveOptions,\n voters,\n endTime,\n tos: visibility === \"public\"\n ? [PUBLIC_COLLECTION, ...mentionedActorIds]\n : visibility === \"unlisted\" || visibility === \"followers\"\n ? [\n this.context.getFollowersUri(this.bot.identifier),\n ...mentionedActorIds,\n ]\n : mentionedActorIds,\n ccs: visibility === \"public\"\n ? [this.context.getFollowersUri(this.bot.identifier)]\n : visibility === \"unlisted\"\n ? [PUBLIC_COLLECTION]\n : [],\n published: published.toTemporalInstant(),\n url: new URL(`/message/${id}`, this.context.origin),\n });\n const activity = new Create({\n id: this.context.getObjectUri(Create, { id }),\n actors: msg.attributionIds,\n tos: msg.toIds,\n ccs: msg.ccIds,\n object: msg,\n published: published.toTemporalInstant(),\n });\n await this.bot.repository.addMessage(id, activity);\n const preferSharedInbox = visibility === \"public\" ||\n visibility === \"unlisted\" || visibility === \"followers\";\n const excludeBaseUris = [new URL(this.context.origin)];\n if (preferSharedInbox) {\n await this.context.sendActivity(\n this.bot,\n \"followers\",\n activity,\n { preferSharedInbox, excludeBaseUris },\n );\n }\n const cachedObjects: Record<string, Object> = {};\n for (const cachedObject of content.getCachedObjects()) {\n if (cachedObject.id == null) continue;\n cachedObjects[cachedObject.id.href] = cachedObject;\n }\n if (mentionedActorIds.length > 0) {\n const documentLoader = await this.context.getDocumentLoader(this.bot);\n const promises: Promise<Object | null>[] = [];\n for (const mentionedActorId of mentionedActorIds) {\n const cachedObject = cachedObjects[mentionedActorId.href];\n const promise = cachedObject == null\n ? this.context.lookupObject(\n mentionedActorId,\n { documentLoader },\n )\n : Promise.resolve(cachedObject);\n promises.push(promise);\n }\n const objects = await Promise.all(promises);\n const mentionedActors = objects.filter(isActor);\n await this.context.sendActivity(\n this.bot,\n mentionedActors,\n activity,\n { preferSharedInbox, excludeBaseUris },\n );\n }\n if (options.replyTarget != null) {\n await this.context.sendActivity(\n this.bot,\n options.replyTarget.actor,\n activity,\n { preferSharedInbox, excludeBaseUris, fanout: \"skip\" },\n );\n }\n if (options.quoteTarget != null) {\n await this.context.sendActivity(\n this.bot,\n options.quoteTarget.actor,\n activity,\n { preferSharedInbox, excludeBaseUris, fanout: \"skip\" },\n );\n }\n return await createMessage(\n msg,\n this,\n cachedObjects,\n options.replyTarget,\n options.quoteTarget,\n true,\n );\n }\n\n async *getOutbox(\n options: SessionGetOutboxOptions = {},\n ): AsyncIterable<AuthorizedMessage<MessageClass, TContextData>> {\n for await (const activity of this.bot.repository.getMessages(options)) {\n let object: Object | null;\n try {\n object = await activity.getObject(this.context);\n } catch {\n continue;\n }\n if (object == null || !isMessageObject(object)) continue;\n const message = await createMessage(object, this, {});\n yield message;\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"session-impl.js","names":["bot: BotImpl<TContextData>","context: Context<TContextData>","actor: Actor | URL | string","actorId: URL","content: Text<\"block\", TContextData>","options:\n | SessionImplPublishOptions<TContextData>\n | SessionImplPublishOptionsWithClass<MessageClass, TContextData>\n | SessionImplPublishOptionsWithQuestion<TContextData>","Note","mentionedActorIds: URL[]","Mention","inclusiveOptions: Note[]","exclusiveOptions: Note[]","voters: number | null","endTime: Temporal.Instant | null","PUBLIC_COLLECTION","Create","cachedObjects: Record<string, Object>","promises: Promise<Object | null>[]","isActor","options: SessionGetOutboxOptions","object: Object | null"],"sources":["../src/session-impl.ts"],"sourcesContent":["// BotKit by Fedify: A framework for creating ActivityPub bots\n// Copyright (C) 2025 Hong Minhee <https://hongminhee.org/>\n//\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as\n// published by the Free Software Foundation, either version 3 of the\n// License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program. If not, see <https://www.gnu.org/licenses/>.\nimport {\n type Actor,\n type Context,\n Create,\n isActor,\n LanguageString,\n Mention,\n Note,\n type Object,\n PUBLIC_COLLECTION,\n} from \"@fedify/fedify\";\nimport { Collection, Follow, Link, Undo } from \"@fedify/fedify/vocab\";\nimport { getLogger } from \"@logtape/logtape\";\nimport { encode } from \"html-entities\";\nimport { v7 as uuidv7 } from \"uuid\";\nimport type { BotImpl } from \"./bot-impl.ts\";\nimport { createMessage, isMessageObject } from \"./message-impl.ts\";\nimport {\n type AuthorizedMessage,\n type Message,\n type MessageClass,\n Question,\n} from \"./message.ts\";\nimport type { Uuid } from \"./repository.ts\";\nimport type {\n Session,\n SessionGetOutboxOptions,\n SessionPublishOptions,\n SessionPublishOptionsWithClass,\n SessionPublishOptionsWithQuestion,\n} from \"./session.ts\";\nimport type { Text } from \"./text.ts\";\n\nconst logger = getLogger([\"botkit\", \"session\"]);\n\nexport interface SessionImplPublishOptions<TContextData>\n extends SessionPublishOptions<TContextData> {\n replyTarget?: Message<MessageClass, TContextData>;\n}\n\nexport interface SessionImplPublishOptionsWithClass<\n T extends MessageClass,\n TContextData,\n> extends\n SessionPublishOptionsWithClass<T, TContextData>,\n SessionImplPublishOptions<TContextData> {\n}\n\nexport interface SessionImplPublishOptionsWithQuestion<TContextData>\n extends\n SessionPublishOptionsWithQuestion<TContextData>,\n SessionImplPublishOptionsWithClass<Question, TContextData> {\n}\n\nexport class SessionImpl<TContextData> implements Session<TContextData> {\n readonly bot: BotImpl<TContextData>;\n readonly context: Context<TContextData>;\n\n constructor(bot: BotImpl<TContextData>, context: Context<TContextData>) {\n this.bot = bot;\n this.context = context;\n }\n\n get actorId() {\n return this.context.getActorUri(this.bot.identifier);\n }\n\n get actorHandle() {\n return `@${this.bot.username}@${this.context.host}` as const;\n }\n\n async getActor(): Promise<Actor> {\n return (await this.bot.dispatchActor(this.context, this.bot.identifier))!;\n }\n\n async follow(actor: Actor | URL | string): Promise<void> {\n if (actor instanceof URL || typeof actor === \"string\") {\n if (\n actor instanceof URL && actor.href === this.actorId.href ||\n typeof actor === \"string\" &&\n (actor === this.actorId.href || actor === this.actorHandle)\n ) {\n throw new TypeError(\"The bot cannot follow itself.\");\n }\n const documentLoader = await this.context.getDocumentLoader(this.bot);\n const object = await this.context.lookupObject(actor, { documentLoader });\n if (!isActor(object)) {\n throw new TypeError(\"The resolved object is not an Actor.\");\n }\n actor = object;\n }\n if (actor.id == null) {\n throw new TypeError(\"The actor does not have an ID.\");\n } else if (actor.id.href === this.actorId.href) {\n throw new TypeError(\"The bot cannot follow itself.\");\n }\n const followee = await this.bot.repository.getFollowee(actor.id);\n if (followee != null) {\n logger.warn(\n \"The bot is already following the actor {actor}.\",\n { actor: actor.id.href },\n );\n return;\n }\n const id = uuidv7() as Uuid;\n const follow = new Follow({\n id: this.context.getObjectUri(Follow, { id }),\n actor: this.context.getActorUri(this.bot.identifier),\n object: actor.id,\n to: actor.id,\n });\n await this.bot.repository.addSentFollow(id, follow);\n await this.context.sendActivity(\n this.bot,\n actor,\n follow,\n { excludeBaseUris: [new URL(this.context.origin)] },\n );\n }\n\n async unfollow(actor: Actor | URL | string): Promise<void> {\n const documentLoader = await this.context.getDocumentLoader(this.bot);\n if (actor instanceof URL || typeof actor === \"string\") {\n if (\n actor instanceof URL && actor.href === this.actorId.href ||\n typeof actor === \"string\" &&\n (actor === this.actorId.href || actor === this.actorHandle)\n ) {\n throw new TypeError(\"The bot cannot unfollow itself.\");\n }\n const object = await this.context.lookupObject(actor, { documentLoader });\n if (!isActor(object)) {\n throw new TypeError(\"The resolved object is not an Actor.\");\n }\n actor = object;\n }\n if (actor.id == null) {\n throw new TypeError(\"The actor does not have an ID.\");\n } else if (actor.id.href === this.actorId.href) {\n throw new TypeError(\"The bot cannot unfollow itself.\");\n }\n const follow = await this.bot.repository.getFollowee(actor.id);\n if (follow == null) {\n logger.warn(\n \"The bot is not following the actor {actor}.\",\n { actor: actor.id.href },\n );\n return;\n }\n await this.bot.repository.removeFollowee(actor.id);\n if (follow.id != null && follow.objectId?.href === actor.id.href) {\n await this.context.sendActivity(\n this.bot,\n actor,\n new Undo({\n id: new URL(\"#undo\", follow.id),\n actor: this.context.getActorUri(this.bot.identifier),\n object: follow,\n to: actor.id,\n }),\n { excludeBaseUris: [new URL(this.context.origin)] },\n );\n }\n }\n\n async follows(actor: Actor | URL | string): Promise<boolean> {\n let actorId: URL;\n if (isActor(actor)) {\n if (actor.id == null) {\n throw new TypeError(\"The actor does not have an ID.\");\n }\n actorId = actor.id;\n } else if (actor instanceof URL) {\n actorId = actor;\n } else {\n if (actor.startsWith(\"http://\") || actor.startsWith(\"https://\")) {\n actorId = new URL(actor);\n } else {\n if (actor === this.actorHandle) return false;\n const documentLoader = await this.context.getDocumentLoader(this.bot);\n const object = await this.context.lookupObject(actor, {\n documentLoader,\n });\n if (!isActor(object)) {\n throw new TypeError(\"The resolved object is not an Actor.\");\n }\n if (object.id == null) {\n throw new TypeError(\"The actor does not have an ID.\");\n }\n actorId = object.id;\n }\n }\n if (actorId.href === this.actorId.href) return false;\n const follow = await this.bot.repository.getFollowee(actorId);\n return follow != null;\n }\n\n async publish(\n content: Text<\"block\", TContextData>,\n options?: SessionImplPublishOptions<TContextData>,\n ): Promise<AuthorizedMessage<Note, TContextData>>;\n async publish<T extends MessageClass>(\n content: Text<\"block\", TContextData>,\n options: SessionImplPublishOptionsWithClass<T, TContextData>,\n ): Promise<AuthorizedMessage<T, TContextData>>;\n async publish(\n content: Text<\"block\", TContextData>,\n options: SessionImplPublishOptionsWithQuestion<TContextData>,\n ): Promise<AuthorizedMessage<Question, TContextData>>;\n async publish(\n content: Text<\"block\", TContextData>,\n options:\n | SessionImplPublishOptions<TContextData>\n | SessionImplPublishOptionsWithClass<MessageClass, TContextData>\n | SessionImplPublishOptionsWithQuestion<TContextData> = {},\n ): Promise<AuthorizedMessage<MessageClass, TContextData>> {\n const published = new Date();\n const id = uuidv7({ msecs: +published }) as Uuid;\n const cls = \"class\" in options ? options.class : Note;\n const visibility = options.visibility ?? \"public\";\n let contentHtml = \"\";\n for await (const chunk of content.getHtml(this)) {\n contentHtml += chunk;\n }\n const tags = await Array.fromAsync(content.getTags(this));\n const mentionedActorIds: URL[] = [];\n for (const tag of tags) {\n if (tag instanceof Mention && tag.href != null) {\n mentionedActorIds.push(tag.href);\n }\n }\n if (options.quoteTarget != null) {\n let url = options.quoteTarget.raw.url ?? options.quoteTarget.id;\n if (url instanceof Link) url = url.href ?? options.quoteTarget.id;\n contentHtml += `\\n\\n<p class=\"quote-inline\"><br>RE: <a href=\"${\n encode(url.href)\n }\">${encode(url.href)}</a></p>`;\n tags.push(\n new Link({\n mediaType:\n 'application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"',\n rel: \"https://misskey-hub.net/ns#_misskey_quote\",\n href: options.quoteTarget.id,\n name: `RE: ${url.href}`,\n }),\n );\n }\n let inclusiveOptions: Note[] = [];\n let exclusiveOptions: Note[] = [];\n let voters: number | null = null;\n let endTime: Temporal.Instant | null = null;\n if (\"class\" in options && options.class === Question && \"poll\" in options) {\n if (options.poll.options.length < 2) {\n throw new TypeError(\"At least two options are required in a poll.\");\n } else if (\n new Set(options.poll.options).size != options.poll.options.length\n ) {\n throw new TypeError(\"Duplicate options are not allowed in a poll.\");\n } else if (options.poll.options.some((o) => o.trim() === \"\")) {\n throw new TypeError(\"Poll options cannot be empty.\");\n }\n const pollOptions = options.poll.options.map((option) =>\n new Note({\n name: option,\n replies: new Collection({ totalItems: 0 }),\n })\n );\n if (options.poll.multiple) inclusiveOptions = pollOptions;\n else exclusiveOptions = pollOptions;\n voters = 0;\n endTime = options.poll.endTime;\n }\n const msg = new cls({\n id: this.context.getObjectUri<MessageClass>(cls, { id }),\n contents: options.language == null\n ? [contentHtml]\n : [new LanguageString(contentHtml, options.language), contentHtml],\n replyTarget: options.replyTarget?.id,\n quoteUrl: options.quoteTarget?.id,\n tags,\n attribution: this.context.getActorUri(this.bot.identifier),\n attachments: options.attachments ?? [],\n inclusiveOptions,\n exclusiveOptions,\n voters,\n endTime,\n tos: visibility === \"public\"\n ? [PUBLIC_COLLECTION, ...mentionedActorIds]\n : visibility === \"unlisted\" || visibility === \"followers\"\n ? [\n this.context.getFollowersUri(this.bot.identifier),\n ...mentionedActorIds,\n ]\n : mentionedActorIds,\n ccs: visibility === \"public\"\n ? [this.context.getFollowersUri(this.bot.identifier)]\n : visibility === \"unlisted\"\n ? [PUBLIC_COLLECTION]\n : [],\n published: published.toTemporalInstant(),\n url: new URL(`/message/${id}`, this.context.origin),\n });\n const activity = new Create({\n id: this.context.getObjectUri(Create, { id }),\n actors: msg.attributionIds,\n tos: msg.toIds,\n ccs: msg.ccIds,\n object: msg,\n published: published.toTemporalInstant(),\n });\n await this.bot.repository.addMessage(id, activity);\n const preferSharedInbox = visibility === \"public\" ||\n visibility === \"unlisted\" || visibility === \"followers\";\n const excludeBaseUris = [new URL(this.context.origin)];\n if (preferSharedInbox) {\n await this.context.sendActivity(\n this.bot,\n \"followers\",\n activity,\n { preferSharedInbox, excludeBaseUris },\n );\n }\n const cachedObjects: Record<string, Object> = {};\n for (const cachedObject of content.getCachedObjects()) {\n if (cachedObject.id == null) continue;\n cachedObjects[cachedObject.id.href] = cachedObject;\n }\n if (mentionedActorIds.length > 0) {\n const documentLoader = await this.context.getDocumentLoader(this.bot);\n const promises: Promise<Object | null>[] = [];\n for (const mentionedActorId of mentionedActorIds) {\n const cachedObject = cachedObjects[mentionedActorId.href];\n const promise = cachedObject == null\n ? this.context.lookupObject(\n mentionedActorId,\n { documentLoader },\n )\n : Promise.resolve(cachedObject);\n promises.push(promise);\n }\n const objects = await Promise.all(promises);\n const mentionedActors = objects.filter(isActor);\n await this.context.sendActivity(\n this.bot,\n mentionedActors,\n activity,\n { preferSharedInbox, excludeBaseUris },\n );\n }\n if (options.replyTarget != null) {\n await this.context.sendActivity(\n this.bot,\n options.replyTarget.actor,\n activity,\n { preferSharedInbox, excludeBaseUris, fanout: \"skip\" },\n );\n }\n if (options.quoteTarget != null) {\n await this.context.sendActivity(\n this.bot,\n options.quoteTarget.actor,\n activity,\n { preferSharedInbox, excludeBaseUris, fanout: \"skip\" },\n );\n }\n return await createMessage(\n msg,\n this,\n cachedObjects,\n options.replyTarget,\n options.quoteTarget,\n true,\n );\n }\n\n async *getOutbox(\n options: SessionGetOutboxOptions = {},\n ): AsyncIterable<AuthorizedMessage<MessageClass, TContextData>> {\n for await (const activity of this.bot.repository.getMessages(options)) {\n let object: Object | null;\n try {\n object = await activity.getObject(this.context);\n } catch {\n continue;\n }\n if (object == null || !isMessageObject(object)) continue;\n const message = await createMessage(object, this, {});\n yield message;\n }\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/botkit",
3
- "version": "0.3.0-dev.112+8f983226",
3
+ "version": "0.3.0-dev.115+d719ad73",
4
4
  "description": "A framework for creating ActivityPub bots",
5
5
  "license": "AGPL-3.0-only",
6
6
  "author": {