@fedify/botkit 0.5.0-dev.210 → 0.5.0-dev.226
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-group.test.d.ts +2 -0
- package/dist/bot-group.test.js +220 -0
- package/dist/bot-group.test.js.map +1 -0
- package/dist/bot-impl.d.ts +132 -13
- package/dist/bot-impl.d.ts.map +1 -1
- package/dist/bot-impl.js +400 -178
- package/dist/bot-impl.js.map +1 -1
- package/dist/bot-impl.test.js +214 -76
- package/dist/bot-impl.test.js.map +1 -1
- package/dist/bot.d.ts +94 -48
- package/dist/bot.d.ts.map +1 -1
- package/dist/bot.js +2 -104
- package/dist/bot.js.map +1 -1
- package/dist/bot.test.js +59 -0
- package/dist/bot.test.js.map +1 -1
- package/dist/components/FollowButton.d.ts +3 -1
- package/dist/components/FollowButton.d.ts.map +1 -1
- package/dist/components/FollowButton.js +2 -2
- package/dist/components/FollowButton.js.map +1 -1
- package/dist/components/Layout.js +1 -1
- package/dist/components/Layout.js.map +1 -1
- package/dist/components/Message.d.ts +2 -2
- package/dist/deno.js +3 -13
- package/dist/deno.js.map +1 -1
- package/dist/follow-impl.test.js +3 -3
- package/dist/follow-impl.test.js.map +1 -1
- package/dist/instance-impl.d.ts +158 -0
- package/dist/instance-impl.d.ts.map +1 -0
- package/dist/instance-impl.js +603 -0
- package/dist/instance-impl.js.map +1 -0
- package/dist/instance-impl.test.d.ts +2 -0
- package/dist/instance-impl.test.js +103 -0
- package/dist/instance-impl.test.js.map +1 -0
- package/dist/instance-multi.test.d.ts +2 -0
- package/dist/instance-multi.test.js +151 -0
- package/dist/instance-multi.test.js.map +1 -0
- package/dist/instance-routing.test.d.ts +2 -0
- package/dist/instance-routing.test.js +367 -0
- package/dist/instance-routing.test.js.map +1 -0
- package/dist/instance.d.ts +318 -0
- package/dist/instance.d.ts.map +1 -0
- package/dist/instance.js +51 -0
- package/dist/instance.js.map +1 -0
- package/dist/message-impl.d.ts.map +1 -1
- package/dist/message-impl.js +17 -10
- package/dist/message-impl.js.map +1 -1
- package/dist/message-impl.test.js +43 -9
- package/dist/message-impl.test.js.map +1 -1
- package/dist/mod.d.ts +5 -3
- package/dist/mod.js +4 -2
- package/dist/pages.d.ts +10 -1
- package/dist/pages.d.ts.map +1 -1
- package/dist/pages.js +112 -41
- package/dist/pages.js.map +1 -1
- package/dist/pages.test.d.ts +2 -0
- package/dist/pages.test.js +170 -0
- package/dist/pages.test.js.map +1 -0
- package/dist/repository.d.ts +385 -138
- package/dist/repository.d.ts.map +1 -1
- package/dist/repository.js +595 -223
- package/dist/repository.js.map +1 -1
- package/dist/repository.test.js +564 -136
- package/dist/repository.test.js.map +1 -1
- package/dist/session-impl.d.ts.map +1 -1
- package/dist/session-impl.js +13 -4
- package/dist/session-impl.js.map +1 -1
- package/dist/session-impl.test.d.ts.map +1 -1
- package/dist/session-impl.test.js +9 -9
- package/dist/session-impl.test.js.map +1 -1
- package/dist/session.d.ts +8 -3
- package/dist/session.d.ts.map +1 -1
- package/dist/text.d.ts.map +1 -1
- package/dist/text.js +27 -10
- package/dist/text.js.map +1 -1
- package/dist/text.test.js +37 -2
- package/dist/text.test.js.map +1 -1
- package/dist/uri.d.ts +46 -0
- package/dist/uri.d.ts.map +1 -0
- package/dist/uri.js +64 -0
- package/dist/uri.js.map +1 -0
- package/dist/uri.test.d.ts +2 -0
- package/dist/uri.test.js +93 -0
- package/dist/uri.test.js.map +1 -0
- package/package.json +6 -2
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { Temporal, toTemporalInstant } from "@js-temporal/polyfill";
|
|
2
|
+
Date.prototype.toTemporalInstant = toTemporalInstant;
|
|
3
|
+
import { Text } from "./text.js";
|
|
4
|
+
import { Session } from "./session.js";
|
|
5
|
+
import { CustomEmoji, DeferredCustomEmoji } from "./emoji.js";
|
|
6
|
+
import { Repository } from "./repository.js";
|
|
7
|
+
import { Bot, BotEventHandlers, PagesOptions } from "./bot.js";
|
|
8
|
+
import { DEFAULT_INSTANCE_ACTOR_IDENTIFIER } from "./instance-impl.js";
|
|
9
|
+
import { Context, Federation, KvStore, MessageQueue } from "@fedify/fedify/federation";
|
|
10
|
+
import { Application, Image, Service } from "@fedify/vocab";
|
|
11
|
+
import { Software } from "@fedify/fedify/nodeinfo";
|
|
12
|
+
|
|
13
|
+
//#region src/instance.d.ts
|
|
14
|
+
/**
|
|
15
|
+
* The profile of a bot actor hosted on an {@link Instance}. It configures
|
|
16
|
+
* everything about a bot except its identifier and the shared infrastructure,
|
|
17
|
+
* which belong to the instance.
|
|
18
|
+
* @since 0.5.0
|
|
19
|
+
*/
|
|
20
|
+
interface BotProfile<TContextData> {
|
|
21
|
+
/**
|
|
22
|
+
* The type of the bot actor. It should be either `Service` or
|
|
23
|
+
* `Application`.
|
|
24
|
+
*
|
|
25
|
+
* If omitted, `Service` will be used.
|
|
26
|
+
* @default `Service`
|
|
27
|
+
*/
|
|
28
|
+
readonly class?: typeof Service | typeof Application;
|
|
29
|
+
/**
|
|
30
|
+
* The username of the bot. It will be a part of the fediverse handle.
|
|
31
|
+
* It can be changed after the bot is federated.
|
|
32
|
+
*/
|
|
33
|
+
readonly username: string;
|
|
34
|
+
/**
|
|
35
|
+
* The display name of the bot. It can be changed after the bot is
|
|
36
|
+
* federated.
|
|
37
|
+
*/
|
|
38
|
+
readonly name?: string;
|
|
39
|
+
/**
|
|
40
|
+
* The description of the bot. It can be changed after the bot is
|
|
41
|
+
* federated.
|
|
42
|
+
*/
|
|
43
|
+
readonly summary?: Text<"block", TContextData>;
|
|
44
|
+
/**
|
|
45
|
+
* The avatar URL of the bot. It can be changed after the bot is federated.
|
|
46
|
+
*/
|
|
47
|
+
readonly icon?: URL | Image;
|
|
48
|
+
/**
|
|
49
|
+
* The header image URL of the bot. It can be changed after the bot is
|
|
50
|
+
* federated.
|
|
51
|
+
*/
|
|
52
|
+
readonly image?: URL | Image;
|
|
53
|
+
/**
|
|
54
|
+
* The custom properties of the bot. It can be changed after the bot is
|
|
55
|
+
* federated.
|
|
56
|
+
*/
|
|
57
|
+
readonly properties?: Record<string, Text<"block" | "inline", TContextData>>;
|
|
58
|
+
/**
|
|
59
|
+
* How to handle incoming follow requests. Note that this behavior can
|
|
60
|
+
* be overridden by manually invoking {@link FollowRequest.accept} or
|
|
61
|
+
* {@link FollowRequest.reject} in the {@link BotEventHandlers.onFollow}
|
|
62
|
+
* event handler.
|
|
63
|
+
*
|
|
64
|
+
* - `"accept"` (default): Automatically accept all incoming follow
|
|
65
|
+
* requests.
|
|
66
|
+
* - `"reject"`: Automatically reject all incoming follow requests.
|
|
67
|
+
* - `"manual"`: Require manual handling of incoming follow requests.
|
|
68
|
+
* @default `"accept"`
|
|
69
|
+
*/
|
|
70
|
+
readonly followerPolicy?: "accept" | "reject" | "manual";
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A function that resolves the profile of a dynamically hosted bot from its
|
|
74
|
+
* identifier. It is invoked whenever an identifier needs to be resolved,
|
|
75
|
+
* e.g. for dispatching an actor or routing an incoming activity, so it
|
|
76
|
+
* should be fast; look profiles up from a database rather than computing
|
|
77
|
+
* them expensively.
|
|
78
|
+
* @param ctx The Fedify context.
|
|
79
|
+
* @param identifier The identifier to resolve.
|
|
80
|
+
* @returns The profile of the bot, or `null` if the dispatcher does not
|
|
81
|
+
* recognize the identifier.
|
|
82
|
+
* @since 0.5.0
|
|
83
|
+
*/
|
|
84
|
+
type BotDispatcher<TContextData> = (ctx: Context<TContextData>, identifier: string) => BotProfile<TContextData> | null | Promise<BotProfile<TContextData> | null>;
|
|
85
|
+
/**
|
|
86
|
+
* Options for creating a dynamic {@link BotGroup}.
|
|
87
|
+
* @since 0.5.0
|
|
88
|
+
*/
|
|
89
|
+
interface CreateBotGroupOptions<TContextData> {
|
|
90
|
+
/**
|
|
91
|
+
* Maps a WebFinger username to the identifier of a bot the group's
|
|
92
|
+
* dispatcher can resolve. If omitted, usernames are assumed to equal
|
|
93
|
+
* identifiers.
|
|
94
|
+
* @param ctx The Fedify context.
|
|
95
|
+
* @param username The username to map.
|
|
96
|
+
* @returns The identifier of the bot, or `null` if the username does not
|
|
97
|
+
* belong to this group.
|
|
98
|
+
*/
|
|
99
|
+
mapUsername?(ctx: Context<TContextData>, username: string): string | null | Promise<string | null>;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* A group of dynamically hosted bots sharing the same event handlers.
|
|
103
|
+
* A group is created by passing a {@link BotDispatcher} to
|
|
104
|
+
* {@link Instance.createBot}; the dispatcher resolves individual bots
|
|
105
|
+
* on demand, and the handlers registered on the group are invoked for
|
|
106
|
+
* every bot it resolves. Handlers can tell which bot they are running as
|
|
107
|
+
* through {@link Session.bot}.
|
|
108
|
+
* @since 0.5.0
|
|
109
|
+
*/
|
|
110
|
+
interface BotGroup<TContextData> extends BotEventHandlers<TContextData> {
|
|
111
|
+
/**
|
|
112
|
+
* Gets a new session to control one of the group's bots for a specific
|
|
113
|
+
* origin and context data.
|
|
114
|
+
* @param origin The origin of the session. Even if a URL with some path
|
|
115
|
+
* or query is passed, only the origin part will be used.
|
|
116
|
+
* @param identifier The identifier of the bot to control.
|
|
117
|
+
* @param contextData The context data to pass to the federation. It can
|
|
118
|
+
* be omitted when `TContextData` is `void`.
|
|
119
|
+
* @returns The session for the bot.
|
|
120
|
+
* @throws {TypeError} If the group's dispatcher does not resolve
|
|
121
|
+
* the identifier.
|
|
122
|
+
*/
|
|
123
|
+
getSession(origin: string | URL, identifier: string, contextData: TContextData): Promise<Session<TContextData>>;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* A server instance that can host multiple bots. An instance owns the
|
|
127
|
+
* shared infrastructure—the key–value store, the message queue, the
|
|
128
|
+
* repository, and HTTP handling—while each bot hosted on it has its own
|
|
129
|
+
* actor identity and event handlers.
|
|
130
|
+
* @since 0.5.0
|
|
131
|
+
*/
|
|
132
|
+
interface Instance<TContextData> {
|
|
133
|
+
/**
|
|
134
|
+
* An internal Fedify federation instance. Normally you don't need to
|
|
135
|
+
* access this directly.
|
|
136
|
+
*/
|
|
137
|
+
readonly federation: Federation<TContextData>;
|
|
138
|
+
/**
|
|
139
|
+
* Creates a bot with a fixed identifier and profile, hosted on this
|
|
140
|
+
* instance.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* const greetBot = instance.createBot("greet", {
|
|
145
|
+
* username: "greetbot",
|
|
146
|
+
* name: "Greeting Bot",
|
|
147
|
+
* });
|
|
148
|
+
*
|
|
149
|
+
* greetBot.onFollow = async (session, followRequest) => {
|
|
150
|
+
* await followRequest.accept();
|
|
151
|
+
* };
|
|
152
|
+
* ```
|
|
153
|
+
*
|
|
154
|
+
* @param identifier The internal identifier for the bot. Since it is used
|
|
155
|
+
* for the actor URI, it *should not* be changed after
|
|
156
|
+
* the bot is federated.
|
|
157
|
+
* @param profile The profile of the bot.
|
|
158
|
+
* @returns The created bot.
|
|
159
|
+
* @throws {TypeError} If a bot with the same identifier or username
|
|
160
|
+
* already exists on the instance.
|
|
161
|
+
*/
|
|
162
|
+
createBot(identifier: string, profile: BotProfile<TContextData>): Bot<TContextData>;
|
|
163
|
+
/**
|
|
164
|
+
* Creates a group of dynamic bots resolved on demand by a dispatcher
|
|
165
|
+
* function. This suits scenarios like “one bot per region,” where
|
|
166
|
+
* thousands of potential bots are backed by a database rather than
|
|
167
|
+
* declared up front.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const weatherBots = instance.createBot(async (ctx, identifier) => {
|
|
172
|
+
* // Return null for identifiers this dispatcher doesn't handle:
|
|
173
|
+
* if (!identifier.startsWith("weather_")) return null;
|
|
174
|
+
* const region = await db.getRegion(identifier.slice("weather_".length));
|
|
175
|
+
* if (region == null) return null;
|
|
176
|
+
* return { username: identifier, name: `${region.name} Weather Bot` };
|
|
177
|
+
* });
|
|
178
|
+
*
|
|
179
|
+
* weatherBots.onMention = async (session, message) => {
|
|
180
|
+
* // session.bot tells which bot is being mentioned:
|
|
181
|
+
* const region = session.bot.identifier.slice("weather_".length);
|
|
182
|
+
* await message.reply(text`The weather in ${region} is sunny!`);
|
|
183
|
+
* };
|
|
184
|
+
* ```
|
|
185
|
+
*
|
|
186
|
+
* @param dispatcher A function resolving a bot profile from an
|
|
187
|
+
* identifier, or `null` for identifiers it does not
|
|
188
|
+
* recognize.
|
|
189
|
+
* @param options The options for the group.
|
|
190
|
+
* @returns The created bot group.
|
|
191
|
+
*/
|
|
192
|
+
createBot(dispatcher: BotDispatcher<TContextData>, options?: CreateBotGroupOptions<TContextData>): BotGroup<TContextData>;
|
|
193
|
+
/**
|
|
194
|
+
* The fetch API for handling HTTP requests. You can pass this to an HTTP
|
|
195
|
+
* server (e.g., `Deno.serve()`, `Bun.serve()`) to handle incoming
|
|
196
|
+
* requests.
|
|
197
|
+
* @param request The request to handle.
|
|
198
|
+
* @param contextData The context data to pass to the federation.
|
|
199
|
+
* @returns The response to the request.
|
|
200
|
+
*/
|
|
201
|
+
fetch(request: Request, contextData: TContextData): Promise<Response>;
|
|
202
|
+
/**
|
|
203
|
+
* Defines custom emojis for the instance. The custom emojis are shared by
|
|
204
|
+
* all bots hosted on the instance and are used for rendering their
|
|
205
|
+
* profiles and posts.
|
|
206
|
+
* @param emojis The custom emojis to define. The keys are the names of
|
|
207
|
+
* the emojis, and the values are the custom emoji
|
|
208
|
+
* definitions.
|
|
209
|
+
* @returns The defined emojis. The keys are the names of the emojis, and
|
|
210
|
+
* the values are the emoji objects, which are used for passing
|
|
211
|
+
* to the {@link customEmoji} function.
|
|
212
|
+
* @throws {TypeError} If any emoji name is invalid or duplicate.
|
|
213
|
+
*/
|
|
214
|
+
addCustomEmojis<TEmojiName extends string>(emojis: Readonly<Record<TEmojiName, CustomEmoji>>): Readonly<Record<TEmojiName, DeferredCustomEmoji<TContextData>>>;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* A specialized {@link Instance} type that doesn't require context data.
|
|
218
|
+
* @since 0.5.0
|
|
219
|
+
*/
|
|
220
|
+
interface InstanceWithVoidContextData extends Instance<void> {
|
|
221
|
+
/**
|
|
222
|
+
* The fetch API for handling HTTP requests. You can pass this to an HTTP
|
|
223
|
+
* server (e.g., `Deno.serve()`, `Bun.serve()`) to handle incoming
|
|
224
|
+
* requests.
|
|
225
|
+
* @param request The request to handle.
|
|
226
|
+
* @returns The response to the request.
|
|
227
|
+
*/
|
|
228
|
+
fetch(request: Request): Promise<Response>;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Options for creating an {@link Instance}.
|
|
232
|
+
* @since 0.5.0
|
|
233
|
+
*/
|
|
234
|
+
interface CreateInstanceOptions {
|
|
235
|
+
/**
|
|
236
|
+
* The underlying key–value store to use for storing data.
|
|
237
|
+
*/
|
|
238
|
+
readonly kv: KvStore;
|
|
239
|
+
/**
|
|
240
|
+
* The repository to use for storing bot data. A single repository stores
|
|
241
|
+
* the data of every bot hosted on the instance, scoped by their
|
|
242
|
+
* identifiers. If omitted, a {@link KvRepository} backed by `kv` will be
|
|
243
|
+
* used.
|
|
244
|
+
*/
|
|
245
|
+
readonly repository?: Repository;
|
|
246
|
+
/**
|
|
247
|
+
* The underlying message queue to use for handling incoming and outgoing
|
|
248
|
+
* activities. If omitted, incoming activities are processed immediately,
|
|
249
|
+
* and outgoing activities are sent immediately.
|
|
250
|
+
*/
|
|
251
|
+
readonly queue?: MessageQueue;
|
|
252
|
+
/**
|
|
253
|
+
* The software information of the instance. If omitted, the NodeInfo
|
|
254
|
+
* protocol will be unimplemented.
|
|
255
|
+
*/
|
|
256
|
+
readonly software?: Software;
|
|
257
|
+
/**
|
|
258
|
+
* Whether to trust `X-Forwarded-*` headers. If your instance is behind
|
|
259
|
+
* an L7 reverse proxy, turn it on.
|
|
260
|
+
*
|
|
261
|
+
* Turned off by default.
|
|
262
|
+
* @default `false`
|
|
263
|
+
*/
|
|
264
|
+
readonly behindProxy?: boolean;
|
|
265
|
+
/**
|
|
266
|
+
* The options for the web pages of the instance. If omitted, the default
|
|
267
|
+
* options will be used.
|
|
268
|
+
*/
|
|
269
|
+
readonly pages?: PagesOptions;
|
|
270
|
+
/**
|
|
271
|
+
* The identifier of the instance actor: an internal `Application` actor
|
|
272
|
+
* the instance uses for signing shared-inbox related requests. Override
|
|
273
|
+
* it when the default identifier collides with a bot you want to host.
|
|
274
|
+
* Since it is used for the actor URI, it *should not* be changed after
|
|
275
|
+
* the instance is federated.
|
|
276
|
+
* @default `"__botkit_instance__"`
|
|
277
|
+
*/
|
|
278
|
+
readonly instanceActorIdentifier?: string;
|
|
279
|
+
/**
|
|
280
|
+
* Configures the recognition of local object URIs in the legacy (pre-0.5)
|
|
281
|
+
* format, which did not carry the owning bot actor identifier. Set this
|
|
282
|
+
* when the instance hosts a bot that was deployed with BotKit 0.4 or
|
|
283
|
+
* earlier, so that object URIs stored by remote servers keep working.
|
|
284
|
+
*
|
|
285
|
+
* Legacy URIs can only occur in deployments that hosted a single bot
|
|
286
|
+
* before the upgrade, so they are attributed to the configured bot.
|
|
287
|
+
*/
|
|
288
|
+
readonly legacyObjectUris?: {
|
|
289
|
+
/**
|
|
290
|
+
* The identifier of the bot actor that owns objects with legacy URIs.
|
|
291
|
+
*/
|
|
292
|
+
readonly identifier: string;
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Creates an {@link Instance} that can host multiple bots sharing the same
|
|
297
|
+
* infrastructure.
|
|
298
|
+
*
|
|
299
|
+
* @example
|
|
300
|
+
* ```typescript
|
|
301
|
+
* import { createInstance } from "@fedify/botkit";
|
|
302
|
+
* import { MemoryKvStore } from "@fedify/fedify/federation";
|
|
303
|
+
*
|
|
304
|
+
* const instance = createInstance<void>({ kv: new MemoryKvStore() });
|
|
305
|
+
* const greetBot = instance.createBot("greet", { username: "greetbot" });
|
|
306
|
+
*
|
|
307
|
+
* export default instance;
|
|
308
|
+
* ```
|
|
309
|
+
*
|
|
310
|
+
* @param options The options for creating the instance.
|
|
311
|
+
* @returns The created instance.
|
|
312
|
+
* @since 0.5.0
|
|
313
|
+
*/
|
|
314
|
+
declare function createInstance<TContextData = void>(options: CreateInstanceOptions): TContextData extends void ? InstanceWithVoidContextData : Instance<TContextData>;
|
|
315
|
+
//# sourceMappingURL=instance.d.ts.map
|
|
316
|
+
//#endregion
|
|
317
|
+
export { BotDispatcher, BotGroup, BotProfile, CreateBotGroupOptions, CreateInstanceOptions, DEFAULT_INSTANCE_ACTOR_IDENTIFIER, Instance, InstanceWithVoidContextData, createInstance };
|
|
318
|
+
//# sourceMappingURL=instance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance.d.ts","names":[],"sources":["../src/instance.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;AAqCiB,UAAA,UAAU,CAAA,YAAA,CAAA,CAAA;EAAA;;;;;;;EA+BE,SAMV,KAAA,CAAA,EAAA,OA7BO,OA6BP,GAAA,OA7BwB,WA6BxB;EAAG;;;;EAMQ,SAAA,QAAA,EAAA,MAAA;EA6BlB;;;;EACE,SAEE,IAAA,CAAA,EAAA,MAAA;EAAY;;;;EAAkB,SAAA,OAAA,CAAA,EAjDzB,IAiDyB,CAAA,OAAA,EAjDX,YAiDW,CAAA;EAM7B;;;EAWY,SAApB,IAAA,CAAA,EA7DS,GA6DT,GA7De,KA6Df;EAAO;AAEY;AAY5B;;EAAyB,SAAwC,KAAA,CAAA,EArE9C,GAqE8C,GArExC,KAqEwC;EAAY;;;;EAiBzD,SAAf,UAAA,CAAA,EAhFmB,MAgFnB,CAAA,MAAA,EAhFkC,IAgFlC,CAAA,OAAA,GAAA,QAAA,EAhF2D,YAgF3D,CAAA,CAAA;EAAO;AAjBoD;AA2BhE;;;;;;;;;;EAkE6B,SACO,cAAA,CAAA,EAAA,QAAA,GAAA,QAAA,GAAA,QAAA;;;;;;;;;;;;;;AA2BH,KA3JrB,aA2JqB,CAAA,YAAA,CAAA,GAAA,CAAA,GAAA,EA1J1B,OA0J0B,CA1JlB,YA0JkB,CAAA,EAAA,UAAA,EAAA,MAAA,EAAA,GAxJ5B,UAwJ4B,CAxJjB,YAwJiB,CAAA,GAAA,IAAA,GAxJM,OAwJN,CAxJc,UAwJd,CAxJyB,YAwJzB,CAAA,GAAA,IAAA,CAAA;;;AAApB;AAOb;AAA6C,UAzJ5B,qBAyJ4B,CAAA,YAAA,CAAA,CAAA;EAAA;;;;AAAgB;AAe7D;;;;EAYkC,WAOf,EAAA,GAAA,EAhLV,OAgLU,CAhLF,YAgLE,CAAA,EAAA,QAAA,EAAA,MAAA,CAAA,EAAA,MAAA,GAAA,IAAA,GA9KE,OA8KF,CAAA,MAAA,GAAA,IAAA,CAAA;;;AAqBY;AAgD/B;;;;;;;AAGY,UA1OK,QA0OL,CAAA,YAAA,CAAA,SA1OoC,gBA0OpC,CA1OqD,YA0OrD,CAAA,CAAA;;;;;;;;;;;;;8BA5NS,sCAEJ,eACZ,QAAQ,QAAQ;;;;;;;;;UAUJ;;;;;uBAKM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;yCA4BrB,WAAW,gBACnB,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAgCO,cAAc,yBAChB,sBAAsB,gBAC/B,SAAS;;;;;;;;;iBAUG,sBAAsB,eAAe,QAAQ;;;;;;;;;;;;;qDAelD,SAAS,OAAO,YAAY,gBACnC,SAAS,OAAO,YAAY,oBAAoB;;;;;;UAOpC,2BAAA,SAAoC;;;;;;;;iBAQpC,UAAU,QAAQ;;;;;;UAOlB,qBAAA;;;;eAIF;;;;;;;wBAQS;;;;;;mBAOL;;;;;sBAMG;;;;;;;;;;;;;mBAeH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgDH,6CACL,wBACR,4BAA4B,8BAC3B,SAAS"}
|
package/dist/instance.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
|
|
2
|
+
import { Temporal, toTemporalInstant } from "@js-temporal/polyfill";
|
|
3
|
+
Date.prototype.toTemporalInstant = toTemporalInstant;
|
|
4
|
+
|
|
5
|
+
import { DEFAULT_INSTANCE_ACTOR_IDENTIFIER, InstanceImpl } from "./instance-impl.js";
|
|
6
|
+
|
|
7
|
+
//#region src/instance.ts
|
|
8
|
+
/**
|
|
9
|
+
* Creates an {@link Instance} that can host multiple bots sharing the same
|
|
10
|
+
* infrastructure.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { createInstance } from "@fedify/botkit";
|
|
15
|
+
* import { MemoryKvStore } from "@fedify/fedify/federation";
|
|
16
|
+
*
|
|
17
|
+
* const instance = createInstance<void>({ kv: new MemoryKvStore() });
|
|
18
|
+
* const greetBot = instance.createBot("greet", { username: "greetbot" });
|
|
19
|
+
*
|
|
20
|
+
* export default instance;
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @param options The options for creating the instance.
|
|
24
|
+
* @returns The created instance.
|
|
25
|
+
* @since 0.5.0
|
|
26
|
+
*/
|
|
27
|
+
function createInstance(options) {
|
|
28
|
+
const instance = new InstanceImpl(options);
|
|
29
|
+
function createBotFn(identifierOrDispatcher, profileOrOptions) {
|
|
30
|
+
if (typeof identifierOrDispatcher === "string") return instance.createBot(identifierOrDispatcher, profileOrOptions);
|
|
31
|
+
return instance.createBot(identifierOrDispatcher, profileOrOptions);
|
|
32
|
+
}
|
|
33
|
+
const wrapper = {
|
|
34
|
+
impl: instance,
|
|
35
|
+
get federation() {
|
|
36
|
+
return instance.federation;
|
|
37
|
+
},
|
|
38
|
+
createBot: createBotFn,
|
|
39
|
+
fetch(request, contextData) {
|
|
40
|
+
return instance.fetch(request, contextData);
|
|
41
|
+
},
|
|
42
|
+
addCustomEmojis(emojis) {
|
|
43
|
+
return instance.addCustomEmojis(emojis);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
return wrapper;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
export { DEFAULT_INSTANCE_ACTOR_IDENTIFIER, createInstance };
|
|
51
|
+
//# sourceMappingURL=instance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance.js","names":["options: CreateInstanceOptions","identifierOrDispatcher: string | BotDispatcher<TContextData>","profileOrOptions?:\n | BotProfile<TContextData>\n | CreateBotGroupOptions<TContextData>","request: Request","contextData: TContextData","emojis: Readonly<Record<TEmojiName, CustomEmoji>>"],"sources":["../src/instance.ts"],"sourcesContent":["// BotKit by Fedify: A framework for creating ActivityPub bots\n// Copyright (C) 2025–2026 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 type {\n Context,\n Federation,\n KvStore,\n MessageQueue,\n} from \"@fedify/fedify/federation\";\nimport type { Software } from \"@fedify/fedify/nodeinfo\";\nimport type { Application, Image, Service } from \"@fedify/vocab\";\nimport type { Bot, BotEventHandlers, PagesOptions } from \"./bot.ts\";\nimport type { CustomEmoji, DeferredCustomEmoji } from \"./emoji.ts\";\nimport { InstanceImpl } from \"./instance-impl.ts\";\nexport { DEFAULT_INSTANCE_ACTOR_IDENTIFIER } from \"./instance-impl.ts\";\nimport type { Repository } from \"./repository.ts\";\nimport type { Session } from \"./session.ts\";\nimport type { Text } from \"./text.ts\";\n\n/**\n * The profile of a bot actor hosted on an {@link Instance}. It configures\n * everything about a bot except its identifier and the shared infrastructure,\n * which belong to the instance.\n * @since 0.5.0\n */\nexport interface BotProfile<TContextData> {\n /**\n * The type of the bot actor. It should be either `Service` or\n * `Application`.\n *\n * If omitted, `Service` will be used.\n * @default `Service`\n */\n readonly class?: typeof Service | typeof Application;\n\n /**\n * The username of the bot. It will be a part of the fediverse handle.\n * It can be changed after the bot is federated.\n */\n readonly username: string;\n\n /**\n * The display name of the bot. It can be changed after the bot is\n * federated.\n */\n readonly name?: string;\n\n /**\n * The description of the bot. It can be changed after the bot is\n * federated.\n */\n readonly summary?: Text<\"block\", TContextData>;\n\n /**\n * The avatar URL of the bot. It can be changed after the bot is federated.\n */\n readonly icon?: URL | Image;\n\n /**\n * The header image URL of the bot. It can be changed after the bot is\n * federated.\n */\n readonly image?: URL | Image;\n\n /**\n * The custom properties of the bot. It can be changed after the bot is\n * federated.\n */\n readonly properties?: Record<string, Text<\"block\" | \"inline\", TContextData>>;\n\n /**\n * How to handle incoming follow requests. Note that this behavior can\n * be overridden by manually invoking {@link FollowRequest.accept} or\n * {@link FollowRequest.reject} in the {@link BotEventHandlers.onFollow}\n * event handler.\n *\n * - `\"accept\"` (default): Automatically accept all incoming follow\n * requests.\n * - `\"reject\"`: Automatically reject all incoming follow requests.\n * - `\"manual\"`: Require manual handling of incoming follow requests.\n * @default `\"accept\"`\n */\n readonly followerPolicy?: \"accept\" | \"reject\" | \"manual\";\n}\n\n/**\n * A function that resolves the profile of a dynamically hosted bot from its\n * identifier. It is invoked whenever an identifier needs to be resolved,\n * e.g. for dispatching an actor or routing an incoming activity, so it\n * should be fast; look profiles up from a database rather than computing\n * them expensively.\n * @param ctx The Fedify context.\n * @param identifier The identifier to resolve.\n * @returns The profile of the bot, or `null` if the dispatcher does not\n * recognize the identifier.\n * @since 0.5.0\n */\nexport type BotDispatcher<TContextData> = (\n ctx: Context<TContextData>,\n identifier: string,\n) => BotProfile<TContextData> | null | Promise<BotProfile<TContextData> | null>;\n\n/**\n * Options for creating a dynamic {@link BotGroup}.\n * @since 0.5.0\n */\nexport interface CreateBotGroupOptions<TContextData> {\n /**\n * Maps a WebFinger username to the identifier of a bot the group's\n * dispatcher can resolve. If omitted, usernames are assumed to equal\n * identifiers.\n * @param ctx The Fedify context.\n * @param username The username to map.\n * @returns The identifier of the bot, or `null` if the username does not\n * belong to this group.\n */\n mapUsername?(\n ctx: Context<TContextData>,\n username: string,\n ): string | null | Promise<string | null>;\n}\n\n/**\n * A group of dynamically hosted bots sharing the same event handlers.\n * A group is created by passing a {@link BotDispatcher} to\n * {@link Instance.createBot}; the dispatcher resolves individual bots\n * on demand, and the handlers registered on the group are invoked for\n * every bot it resolves. Handlers can tell which bot they are running as\n * through {@link Session.bot}.\n * @since 0.5.0\n */\nexport interface BotGroup<TContextData> extends BotEventHandlers<TContextData> {\n /**\n * Gets a new session to control one of the group's bots for a specific\n * origin and context data.\n * @param origin The origin of the session. Even if a URL with some path\n * or query is passed, only the origin part will be used.\n * @param identifier The identifier of the bot to control.\n * @param contextData The context data to pass to the federation. It can\n * be omitted when `TContextData` is `void`.\n * @returns The session for the bot.\n * @throws {TypeError} If the group's dispatcher does not resolve\n * the identifier.\n */\n getSession(\n origin: string | URL,\n identifier: string,\n contextData: TContextData,\n ): Promise<Session<TContextData>>;\n}\n\n/**\n * A server instance that can host multiple bots. An instance owns the\n * shared infrastructure—the key–value store, the message queue, the\n * repository, and HTTP handling—while each bot hosted on it has its own\n * actor identity and event handlers.\n * @since 0.5.0\n */\nexport interface Instance<TContextData> {\n /**\n * An internal Fedify federation instance. Normally you don't need to\n * access this directly.\n */\n readonly federation: Federation<TContextData>;\n\n /**\n * Creates a bot with a fixed identifier and profile, hosted on this\n * instance.\n *\n * @example\n * ```typescript\n * const greetBot = instance.createBot(\"greet\", {\n * username: \"greetbot\",\n * name: \"Greeting Bot\",\n * });\n *\n * greetBot.onFollow = async (session, followRequest) => {\n * await followRequest.accept();\n * };\n * ```\n *\n * @param identifier The internal identifier for the bot. Since it is used\n * for the actor URI, it *should not* be changed after\n * the bot is federated.\n * @param profile The profile of the bot.\n * @returns The created bot.\n * @throws {TypeError} If a bot with the same identifier or username\n * already exists on the instance.\n */\n createBot(\n identifier: string,\n profile: BotProfile<TContextData>,\n ): Bot<TContextData>;\n\n /**\n * Creates a group of dynamic bots resolved on demand by a dispatcher\n * function. This suits scenarios like “one bot per region,” where\n * thousands of potential bots are backed by a database rather than\n * declared up front.\n *\n * @example\n * ```typescript\n * const weatherBots = instance.createBot(async (ctx, identifier) => {\n * // Return null for identifiers this dispatcher doesn't handle:\n * if (!identifier.startsWith(\"weather_\")) return null;\n * const region = await db.getRegion(identifier.slice(\"weather_\".length));\n * if (region == null) return null;\n * return { username: identifier, name: `${region.name} Weather Bot` };\n * });\n *\n * weatherBots.onMention = async (session, message) => {\n * // session.bot tells which bot is being mentioned:\n * const region = session.bot.identifier.slice(\"weather_\".length);\n * await message.reply(text`The weather in ${region} is sunny!`);\n * };\n * ```\n *\n * @param dispatcher A function resolving a bot profile from an\n * identifier, or `null` for identifiers it does not\n * recognize.\n * @param options The options for the group.\n * @returns The created bot group.\n */\n createBot(\n dispatcher: BotDispatcher<TContextData>,\n options?: CreateBotGroupOptions<TContextData>,\n ): BotGroup<TContextData>;\n\n /**\n * The fetch API for handling HTTP requests. You can pass this to an HTTP\n * server (e.g., `Deno.serve()`, `Bun.serve()`) to handle incoming\n * requests.\n * @param request The request to handle.\n * @param contextData The context data to pass to the federation.\n * @returns The response to the request.\n */\n fetch(request: Request, contextData: TContextData): Promise<Response>;\n\n /**\n * Defines custom emojis for the instance. The custom emojis are shared by\n * all bots hosted on the instance and are used for rendering their\n * profiles and posts.\n * @param emojis The custom emojis to define. The keys are the names of\n * the emojis, and the values are the custom emoji\n * definitions.\n * @returns The defined emojis. The keys are the names of the emojis, and\n * the values are the emoji objects, which are used for passing\n * to the {@link customEmoji} function.\n * @throws {TypeError} If any emoji name is invalid or duplicate.\n */\n addCustomEmojis<TEmojiName extends string>(\n emojis: Readonly<Record<TEmojiName, CustomEmoji>>,\n ): Readonly<Record<TEmojiName, DeferredCustomEmoji<TContextData>>>;\n}\n\n/**\n * A specialized {@link Instance} type that doesn't require context data.\n * @since 0.5.0\n */\nexport interface InstanceWithVoidContextData extends Instance<void> {\n /**\n * The fetch API for handling HTTP requests. You can pass this to an HTTP\n * server (e.g., `Deno.serve()`, `Bun.serve()`) to handle incoming\n * requests.\n * @param request The request to handle.\n * @returns The response to the request.\n */\n fetch(request: Request): Promise<Response>;\n}\n\n/**\n * Options for creating an {@link Instance}.\n * @since 0.5.0\n */\nexport interface CreateInstanceOptions {\n /**\n * The underlying key–value store to use for storing data.\n */\n readonly kv: KvStore;\n\n /**\n * The repository to use for storing bot data. A single repository stores\n * the data of every bot hosted on the instance, scoped by their\n * identifiers. If omitted, a {@link KvRepository} backed by `kv` will be\n * used.\n */\n readonly repository?: Repository;\n\n /**\n * The underlying message queue to use for handling incoming and outgoing\n * activities. If omitted, incoming activities are processed immediately,\n * and outgoing activities are sent immediately.\n */\n readonly queue?: MessageQueue;\n\n /**\n * The software information of the instance. If omitted, the NodeInfo\n * protocol will be unimplemented.\n */\n readonly software?: Software;\n\n /**\n * Whether to trust `X-Forwarded-*` headers. If your instance is behind\n * an L7 reverse proxy, turn it on.\n *\n * Turned off by default.\n * @default `false`\n */\n readonly behindProxy?: boolean;\n\n /**\n * The options for the web pages of the instance. If omitted, the default\n * options will be used.\n */\n readonly pages?: PagesOptions;\n\n /**\n * The identifier of the instance actor: an internal `Application` actor\n * the instance uses for signing shared-inbox related requests. Override\n * it when the default identifier collides with a bot you want to host.\n * Since it is used for the actor URI, it *should not* be changed after\n * the instance is federated.\n * @default `\"__botkit_instance__\"`\n */\n readonly instanceActorIdentifier?: string;\n\n /**\n * Configures the recognition of local object URIs in the legacy (pre-0.5)\n * format, which did not carry the owning bot actor identifier. Set this\n * when the instance hosts a bot that was deployed with BotKit 0.4 or\n * earlier, so that object URIs stored by remote servers keep working.\n *\n * Legacy URIs can only occur in deployments that hosted a single bot\n * before the upgrade, so they are attributed to the configured bot.\n */\n readonly legacyObjectUris?: {\n /**\n * The identifier of the bot actor that owns objects with legacy URIs.\n */\n readonly identifier: string;\n };\n}\n\n/**\n * Creates an {@link Instance} that can host multiple bots sharing the same\n * infrastructure.\n *\n * @example\n * ```typescript\n * import { createInstance } from \"@fedify/botkit\";\n * import { MemoryKvStore } from \"@fedify/fedify/federation\";\n *\n * const instance = createInstance<void>({ kv: new MemoryKvStore() });\n * const greetBot = instance.createBot(\"greet\", { username: \"greetbot\" });\n *\n * export default instance;\n * ```\n *\n * @param options The options for creating the instance.\n * @returns The created instance.\n * @since 0.5.0\n */\nexport function createInstance<TContextData = void>(\n options: CreateInstanceOptions,\n): TContextData extends void ? InstanceWithVoidContextData\n : Instance<TContextData> {\n const instance = new InstanceImpl<TContextData>(options);\n function createBotFn(\n identifier: string,\n profile: BotProfile<TContextData>,\n ): Bot<TContextData>;\n function createBotFn(\n dispatcher: BotDispatcher<TContextData>,\n options?: CreateBotGroupOptions<TContextData>,\n ): BotGroup<TContextData>;\n function createBotFn(\n identifierOrDispatcher: string | BotDispatcher<TContextData>,\n profileOrOptions?:\n | BotProfile<TContextData>\n | CreateBotGroupOptions<TContextData>,\n ): Bot<TContextData> | BotGroup<TContextData> {\n if (typeof identifierOrDispatcher === \"string\") {\n return instance.createBot(\n identifierOrDispatcher,\n profileOrOptions as BotProfile<TContextData>,\n );\n }\n return instance.createBot(\n identifierOrDispatcher,\n profileOrOptions as CreateBotGroupOptions<TContextData> | undefined,\n );\n }\n // Since `deno serve` does not recognize a class instance having fetch(),\n // we wrap an InstanceImpl instance with a plain object.\n // See also https://github.com/denoland/deno/issues/24062\n const wrapper = {\n impl: instance,\n get federation(): Federation<TContextData> {\n return instance.federation;\n },\n createBot: createBotFn,\n fetch(request: Request, contextData: TContextData): Promise<Response> {\n return instance.fetch(request, contextData);\n },\n addCustomEmojis<TEmojiName extends string>(\n emojis: Readonly<Record<TEmojiName, CustomEmoji>>,\n ): Readonly<Record<TEmojiName, DeferredCustomEmoji<TContextData>>> {\n return instance.addCustomEmojis(emojis);\n },\n } satisfies Instance<TContextData> & { impl: InstanceImpl<TContextData> };\n // @ts-ignore: the wrapper implements InstanceWithVoidContextData\n return wrapper;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAsXA,SAAgB,eACdA,SAEyB;CACzB,MAAM,WAAW,IAAI,aAA2B;CAShD,SAAS,YACPC,wBACAC,kBAG4C;AAC5C,aAAW,2BAA2B,SACpC,QAAO,SAAS,UACd,wBACA,iBACD;AAEH,SAAO,SAAS,UACd,wBACA,iBACD;CACF;CAID,MAAM,UAAU;EACd,MAAM;EACN,IAAI,aAAuC;AACzC,UAAO,SAAS;EACjB;EACD,WAAW;EACX,MAAMC,SAAkBC,aAA8C;AACpE,UAAO,SAAS,MAAM,SAAS,YAAY;EAC5C;EACD,gBACEC,QACiE;AACjE,UAAO,SAAS,gBAAgB,OAAO;EACxC;CACF;AAED,QAAO;AACR"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-impl.d.ts","names":[],"sources":["../src/message-impl.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"message-impl.d.ts","names":[],"sources":["../src/message-impl.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/message-impl.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Temporal, toTemporalInstant } from "@js-temporal/polyfill";
|
|
3
3
|
Date.prototype.toTemporalInstant = toTemporalInstant;
|
|
4
4
|
|
|
5
|
+
import { parseLocalUri } from "./uri.js";
|
|
5
6
|
import { Announce, Article, ChatMessage, Create, Delete, Document, EmojiReact, Hashtag, Like, Link, Mention, Note, PUBLIC_COLLECTION, Question, Tombstone, Undo, Update, isActor } from "@fedify/vocab";
|
|
6
7
|
import { LanguageString } from "@fedify/vocab-runtime";
|
|
7
8
|
import { decode } from "html-entities";
|
|
@@ -66,7 +67,10 @@ var MessageImpl = class {
|
|
|
66
67
|
const id = v7({ msecs: +published });
|
|
67
68
|
const visibility = options.visibility ?? this.visibility;
|
|
68
69
|
const originalActor = this.actor.id == null ? [] : [this.actor.id];
|
|
69
|
-
const uri = this.session.context.getObjectUri(Announce, {
|
|
70
|
+
const uri = this.session.context.getObjectUri(Announce, {
|
|
71
|
+
identifier: this.session.bot.identifier,
|
|
72
|
+
id
|
|
73
|
+
});
|
|
70
74
|
const announce = new Announce({
|
|
71
75
|
id: uri,
|
|
72
76
|
actor: this.session.context.getActorUri(this.session.bot.identifier),
|
|
@@ -205,8 +209,8 @@ var MessageImpl = class {
|
|
|
205
209
|
};
|
|
206
210
|
var AuthorizedMessageImpl = class extends MessageImpl {
|
|
207
211
|
async update(text) {
|
|
208
|
-
const parsed = this.session.context.
|
|
209
|
-
if (parsed?.type !== "object" || !messageClasses.some((cls) => parsed.class === cls)) return;
|
|
212
|
+
const parsed = parseLocalUri(this.session.context, this.id, this.session.bot.legacyObjectUrisIdentifier);
|
|
213
|
+
if (parsed?.type !== "object" || !messageClasses.some((cls) => parsed.class === cls) || parsed.values.identifier !== this.session.bot.identifier) return;
|
|
210
214
|
const { id } = parsed.values;
|
|
211
215
|
let existingMentions = [];
|
|
212
216
|
let mentionedActors = [];
|
|
@@ -260,7 +264,10 @@ var AuthorizedMessageImpl = class extends MessageImpl {
|
|
|
260
264
|
const cc = create.ccIds.map((url) => url.href);
|
|
261
265
|
for (const url of newMessage.ccIds) if (!cc.includes(url.href)) cc.push(url.href);
|
|
262
266
|
update = new Update({
|
|
263
|
-
id: new URL(`#updated/${updated$1.toString()}`, this.session.context.getObjectUri(Create, {
|
|
267
|
+
id: new URL(`#updated/${updated$1.toString()}`, this.session.context.getObjectUri(Create, {
|
|
268
|
+
identifier: this.session.bot.identifier,
|
|
269
|
+
id
|
|
270
|
+
})),
|
|
264
271
|
actors: newMessage.attributionIds,
|
|
265
272
|
tos: to.map((url) => new URL(url)),
|
|
266
273
|
ccs: cc.map((url) => new URL(url)),
|
|
@@ -292,8 +299,8 @@ var AuthorizedMessageImpl = class extends MessageImpl {
|
|
|
292
299
|
});
|
|
293
300
|
}
|
|
294
301
|
async delete() {
|
|
295
|
-
const parsed = this.session.context.
|
|
296
|
-
if (parsed?.type !== "object" || !messageClasses.some((cls) => parsed.class === cls)) return;
|
|
302
|
+
const parsed = parseLocalUri(this.session.context, this.id, this.session.bot.legacyObjectUrisIdentifier);
|
|
303
|
+
if (parsed?.type !== "object" || !messageClasses.some((cls) => parsed.class === cls) || parsed.values.identifier !== this.session.bot.identifier) return;
|
|
297
304
|
const { id } = parsed.values;
|
|
298
305
|
const create = await this.session.bot.repository.removeMessage(id);
|
|
299
306
|
if (create == null) return;
|
|
@@ -374,8 +381,8 @@ async function createMessage(raw, session, cachedObjects, replyTarget, quoteTarg
|
|
|
374
381
|
for await (const attachment of raw.getAttachments(options)) if (attachment instanceof Document) attachments.push(attachment);
|
|
375
382
|
if (replyTarget == null) {
|
|
376
383
|
let rt;
|
|
377
|
-
const parsed = session.context
|
|
378
|
-
if (parsed?.type === "object" && messageClasses.includes(parsed.class)) {
|
|
384
|
+
const parsed = parseLocalUri(session.context, raw.replyTargetId, session.bot.legacyObjectUrisIdentifier);
|
|
385
|
+
if (parsed?.type === "object" && messageClasses.includes(parsed.class) && parsed.values.identifier === session.bot.identifier) {
|
|
379
386
|
const cls = parsed.class;
|
|
380
387
|
rt = await session.bot.dispatchMessage(cls, session.context, parsed.values.id);
|
|
381
388
|
} else rt = await raw.getReplyTarget(options);
|
|
@@ -390,8 +397,8 @@ async function createMessage(raw, session, cachedObjects, replyTarget, quoteTarg
|
|
|
390
397
|
}
|
|
391
398
|
if (quoteUrl == null) quoteUrl = raw.quoteUrl;
|
|
392
399
|
let qt = null;
|
|
393
|
-
const parsed = session.context.
|
|
394
|
-
if (parsed?.type === "object" && messageClasses.includes(parsed.class)) {
|
|
400
|
+
const parsed = parseLocalUri(session.context, quoteUrl, session.bot.legacyObjectUrisIdentifier);
|
|
401
|
+
if (parsed?.type === "object" && messageClasses.includes(parsed.class) && parsed.values.identifier === session.bot.identifier) {
|
|
395
402
|
const cls = parsed.class;
|
|
396
403
|
qt = await session.bot.dispatchMessage(cls, session.context, parsed.values.id);
|
|
397
404
|
} else if (quoteUrl != null) qt = await session.context.lookupObject(quoteUrl, options);
|