@fedify/botkit 0.3.0-dev.108
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/LICENSE +661 -0
- package/README.md +75 -0
- package/dist/bot-impl.d.ts +111 -0
- package/dist/bot-impl.d.ts.map +1 -0
- package/dist/bot-impl.js +602 -0
- package/dist/bot-impl.js.map +1 -0
- package/dist/bot-impl.test.d.ts +2 -0
- package/dist/bot-impl.test.js +1642 -0
- package/dist/bot-impl.test.js.map +1 -0
- package/dist/bot.d.ts +270 -0
- package/dist/bot.d.ts.map +1 -0
- package/dist/bot.js +118 -0
- package/dist/bot.js.map +1 -0
- package/dist/bot.test.d.ts +2 -0
- package/dist/bot.test.js +80 -0
- package/dist/bot.test.js.map +1 -0
- package/dist/components/Layout.d.ts +26 -0
- package/dist/components/Layout.d.ts.map +1 -0
- package/dist/components/Layout.js +36 -0
- package/dist/components/Layout.js.map +1 -0
- package/dist/components/Message.d.ts +21 -0
- package/dist/components/Message.d.ts.map +1 -0
- package/dist/components/Message.js +99 -0
- package/dist/components/Message.js.map +1 -0
- package/dist/components/Message.test.d.ts +2 -0
- package/dist/components/Message.test.js +32 -0
- package/dist/components/Message.test.js.map +1 -0
- package/dist/deno.js +73 -0
- package/dist/deno.js.map +1 -0
- package/dist/emoji.d.ts +87 -0
- package/dist/emoji.d.ts.map +1 -0
- package/dist/emoji.js +37 -0
- package/dist/emoji.js.map +1 -0
- package/dist/emoji.test.d.ts +2 -0
- package/dist/emoji.test.js +109 -0
- package/dist/emoji.test.js.map +1 -0
- package/dist/events.d.ts +110 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +4 -0
- package/dist/follow-impl.d.ts +23 -0
- package/dist/follow-impl.d.ts.map +1 -0
- package/dist/follow-impl.js +51 -0
- package/dist/follow-impl.js.map +1 -0
- package/dist/follow-impl.test.d.ts +2 -0
- package/dist/follow-impl.test.js +110 -0
- package/dist/follow-impl.test.js.map +1 -0
- package/dist/follow.d.ts +44 -0
- package/dist/follow.d.ts.map +1 -0
- package/dist/follow.js +4 -0
- package/dist/message-impl.d.ts +54 -0
- package/dist/message-impl.d.ts.map +1 -0
- package/dist/message-impl.js +439 -0
- package/dist/message-impl.js.map +1 -0
- package/dist/message-impl.test.d.ts +2 -0
- package/dist/message-impl.test.js +519 -0
- package/dist/message-impl.test.js.map +1 -0
- package/dist/message.d.ts +223 -0
- package/dist/message.d.ts.map +1 -0
- package/dist/message.js +8 -0
- package/dist/mod.d.ts +13 -0
- package/dist/mod.js +13 -0
- package/dist/pages.d.ts +20 -0
- package/dist/pages.d.ts.map +1 -0
- package/dist/pages.js +361 -0
- package/dist/pages.js.map +1 -0
- package/dist/reaction.d.ts +90 -0
- package/dist/reaction.d.ts.map +1 -0
- package/dist/reaction.js +7 -0
- package/dist/repository.d.ts +323 -0
- package/dist/repository.d.ts.map +1 -0
- package/dist/repository.js +483 -0
- package/dist/repository.js.map +1 -0
- package/dist/repository.test.d.ts +2 -0
- package/dist/repository.test.js +336 -0
- package/dist/repository.test.js.map +1 -0
- package/dist/session-impl.d.ts +32 -0
- package/dist/session-impl.d.ts.map +1 -0
- package/dist/session-impl.js +195 -0
- package/dist/session-impl.js.map +1 -0
- package/dist/session-impl.test.d.ts +20 -0
- package/dist/session-impl.test.d.ts.map +1 -0
- package/dist/session-impl.test.js +464 -0
- package/dist/session-impl.test.js.map +1 -0
- package/dist/session.d.ts +139 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +4 -0
- package/dist/text.d.ts +391 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +640 -0
- package/dist/text.js.map +1 -0
- package/dist/text.test.d.ts +2 -0
- package/dist/text.test.js +473 -0
- package/dist/text.test.js.map +1 -0
- package/package.json +137 -0
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
|
|
2
|
+
import { Temporal, toTemporalInstant } from "@js-temporal/polyfill";
|
|
3
|
+
Date.prototype.toTemporalInstant = toTemporalInstant;
|
|
4
|
+
|
|
5
|
+
import { emoji } from "./emoji.js";
|
|
6
|
+
import { createMessage, getMessageClass, getMessageVisibility, isMessageObject } from "./message-impl.js";
|
|
7
|
+
import { MemoryRepository } from "./repository.js";
|
|
8
|
+
import { SessionImpl } from "./session-impl.js";
|
|
9
|
+
import { BotImpl } from "./bot-impl.js";
|
|
10
|
+
import { text } from "./text.js";
|
|
11
|
+
import { createMockContext } from "./session-impl.test.js";
|
|
12
|
+
import { MemoryKvStore } from "@fedify/fedify/federation";
|
|
13
|
+
import { Announce, Article, ChatMessage, Create, Delete, Emoji, EmojiReact, Hashtag, Image, Like, Mention, Note, PUBLIC_COLLECTION, Person, Question, Tombstone, Undo, Update } from "@fedify/fedify/vocab";
|
|
14
|
+
import assert from "node:assert";
|
|
15
|
+
import { test } from "node:test";
|
|
16
|
+
|
|
17
|
+
//#region src/message-impl.test.ts
|
|
18
|
+
test("isMessageObject()", () => {
|
|
19
|
+
assert.ok(isMessageObject(new Article({})));
|
|
20
|
+
assert.ok(isMessageObject(new ChatMessage({})));
|
|
21
|
+
assert.ok(isMessageObject(new Note({})));
|
|
22
|
+
assert.ok(isMessageObject(new Question({})));
|
|
23
|
+
assert.ok(!isMessageObject(new Person({})));
|
|
24
|
+
});
|
|
25
|
+
test("getMessageClass()", () => {
|
|
26
|
+
assert.deepStrictEqual(getMessageClass(new Article({})), Article);
|
|
27
|
+
assert.deepStrictEqual(getMessageClass(new ChatMessage({})), ChatMessage);
|
|
28
|
+
assert.deepStrictEqual(getMessageClass(new Note({})), Note);
|
|
29
|
+
assert.deepStrictEqual(getMessageClass(new Question({})), Question);
|
|
30
|
+
});
|
|
31
|
+
test("createMessage()", async () => {
|
|
32
|
+
const bot = new BotImpl({
|
|
33
|
+
kv: new MemoryKvStore(),
|
|
34
|
+
username: "bot"
|
|
35
|
+
});
|
|
36
|
+
const session = bot.getSession("https://example.com", void 0);
|
|
37
|
+
await assert.rejects(() => createMessage(new Note({}), session, {}), TypeError, "The raw.id is required.");
|
|
38
|
+
await assert.rejects(() => createMessage(new Note({ id: new URL("https://example.com/notes/1") }), session, {}), TypeError, "The raw.content is required.");
|
|
39
|
+
await assert.rejects(() => createMessage(new Note({
|
|
40
|
+
id: new URL("https://example.com/notes/1"),
|
|
41
|
+
content: "<p>Hello, world!</p>"
|
|
42
|
+
}), session, {}), TypeError, "The raw.attributionId is required.");
|
|
43
|
+
const publicNote = new Note({
|
|
44
|
+
id: new URL("https://example.com/notes/1"),
|
|
45
|
+
content: "<p>#Hello, <em>world</em>!</p>",
|
|
46
|
+
attribution: new URL("https://example.com/ap/actor/bot"),
|
|
47
|
+
to: PUBLIC_COLLECTION,
|
|
48
|
+
cc: new URL("https://example.com/ap/actor/bot/followers"),
|
|
49
|
+
tags: [new Mention({
|
|
50
|
+
name: "@bot",
|
|
51
|
+
href: new URL("https://example.com/ap/actor/bot")
|
|
52
|
+
}), new Hashtag({
|
|
53
|
+
name: "#Hello",
|
|
54
|
+
href: new URL("https://example.com/tags/hello")
|
|
55
|
+
})]
|
|
56
|
+
});
|
|
57
|
+
const publicMessage = await createMessage(publicNote, session, {});
|
|
58
|
+
assert.deepStrictEqual(publicMessage.raw, publicNote);
|
|
59
|
+
assert.deepStrictEqual(publicMessage.id, publicNote.id);
|
|
60
|
+
assert.deepStrictEqual(publicMessage.actor, await session.getActor());
|
|
61
|
+
assert.deepStrictEqual(publicMessage.visibility, "public");
|
|
62
|
+
assert.deepStrictEqual(publicMessage.language, void 0);
|
|
63
|
+
assert.deepStrictEqual(publicMessage.text, "#Hello, world!");
|
|
64
|
+
assert.deepStrictEqual(publicMessage.html, "<p>#Hello, <em>world</em>!</p>");
|
|
65
|
+
assert.deepStrictEqual(publicMessage.replyTarget, void 0);
|
|
66
|
+
assert.deepStrictEqual(publicMessage.mentions, [await session.getActor()]);
|
|
67
|
+
assert.deepStrictEqual(publicMessage.hashtags, [new Hashtag({
|
|
68
|
+
name: "#Hello",
|
|
69
|
+
href: new URL("https://example.com/tags/hello")
|
|
70
|
+
})]);
|
|
71
|
+
assert.deepStrictEqual(publicMessage.attachments, []);
|
|
72
|
+
assert.deepStrictEqual(publicMessage.published, void 0);
|
|
73
|
+
assert.deepStrictEqual(publicMessage.updated, void 0);
|
|
74
|
+
const unlistedNote = publicNote.clone({
|
|
75
|
+
to: new URL("https://example.com/ap/actor/bot/followers"),
|
|
76
|
+
cc: PUBLIC_COLLECTION
|
|
77
|
+
});
|
|
78
|
+
const unlistedMessage = await createMessage(unlistedNote, session, {});
|
|
79
|
+
assert.deepStrictEqual(unlistedMessage.visibility, "unlisted");
|
|
80
|
+
const followersNote = publicNote.clone({
|
|
81
|
+
to: new URL("https://example.com/ap/actor/bot/followers"),
|
|
82
|
+
ccs: []
|
|
83
|
+
});
|
|
84
|
+
const followersMessage = await createMessage(followersNote, session, {});
|
|
85
|
+
assert.deepStrictEqual(followersMessage.visibility, "followers");
|
|
86
|
+
const direct = publicNote.clone({
|
|
87
|
+
to: new URL("https://example.com/ap/actor/bot"),
|
|
88
|
+
ccs: []
|
|
89
|
+
});
|
|
90
|
+
const directMessage = await createMessage(direct, session, {});
|
|
91
|
+
assert.deepStrictEqual(directMessage.visibility, "direct");
|
|
92
|
+
const unknown = publicNote.clone({
|
|
93
|
+
tos: [],
|
|
94
|
+
ccs: []
|
|
95
|
+
});
|
|
96
|
+
const unknownMessage = await createMessage(unknown, session, {});
|
|
97
|
+
assert.deepStrictEqual(unknownMessage.visibility, "unknown");
|
|
98
|
+
});
|
|
99
|
+
test("AuthorizedMessageImpl.delete()", async () => {
|
|
100
|
+
const repository = new MemoryRepository();
|
|
101
|
+
const bot = new BotImpl({
|
|
102
|
+
kv: new MemoryKvStore(),
|
|
103
|
+
repository,
|
|
104
|
+
username: "bot"
|
|
105
|
+
});
|
|
106
|
+
const ctx = createMockContext(bot, "https://example.com");
|
|
107
|
+
const session = new SessionImpl(bot, ctx);
|
|
108
|
+
const note = new Note({
|
|
109
|
+
id: new URL("https://example.com/ap/note/c1c792ce-a0be-4685-b396-e59e5ef8c788"),
|
|
110
|
+
content: "<p>Hello, world!</p>",
|
|
111
|
+
attribution: new URL("https://example.com/ap/actor/bot"),
|
|
112
|
+
to: PUBLIC_COLLECTION,
|
|
113
|
+
cc: new URL("https://example.com/ap/actor/bot/followers")
|
|
114
|
+
});
|
|
115
|
+
const msg = await createMessage(note, session, {}, void 0, void 0, true);
|
|
116
|
+
await repository.addMessage("c1c792ce-a0be-4685-b396-e59e5ef8c788", new Create({
|
|
117
|
+
id: new URL("https://example.com/ap/create/c1c792ce-a0be-4685-b396-e59e5ef8c788"),
|
|
118
|
+
actor: new URL("https://example.com/ap/actor/bot"),
|
|
119
|
+
to: PUBLIC_COLLECTION,
|
|
120
|
+
cc: new URL("https://example.com/ap/actor/bot/followers"),
|
|
121
|
+
object: note
|
|
122
|
+
}));
|
|
123
|
+
await msg.delete();
|
|
124
|
+
assert.deepStrictEqual(await repository.countMessages(), 0);
|
|
125
|
+
assert.deepStrictEqual(ctx.sentActivities.length, 1);
|
|
126
|
+
const { recipients, activity } = ctx.sentActivities[0];
|
|
127
|
+
assert.deepStrictEqual(recipients, "followers");
|
|
128
|
+
assert.ok(activity instanceof Delete);
|
|
129
|
+
assert.deepStrictEqual(activity.actorId, ctx.getActorUri(bot.identifier));
|
|
130
|
+
assert.deepStrictEqual(activity.toIds, [PUBLIC_COLLECTION]);
|
|
131
|
+
assert.deepStrictEqual(activity.ccIds, [ctx.getFollowersUri(bot.identifier)]);
|
|
132
|
+
const tombstone = await activity.getObject();
|
|
133
|
+
assert.ok(tombstone instanceof Tombstone);
|
|
134
|
+
assert.deepStrictEqual(tombstone.id, note.id);
|
|
135
|
+
});
|
|
136
|
+
test("MessageImpl.reply()", async () => {
|
|
137
|
+
const repository = new MemoryRepository();
|
|
138
|
+
const bot = new BotImpl({
|
|
139
|
+
kv: new MemoryKvStore(),
|
|
140
|
+
repository,
|
|
141
|
+
username: "bot"
|
|
142
|
+
});
|
|
143
|
+
const ctx = createMockContext(bot, "https://example.com");
|
|
144
|
+
const session = new SessionImpl(bot, ctx);
|
|
145
|
+
const originalPost = new Note({
|
|
146
|
+
id: new URL("https://example.com/ap/note/c1c792ce-a0be-4685-b396-e59e5ef8c788"),
|
|
147
|
+
content: "<p>Hello, world!</p>",
|
|
148
|
+
attribution: new Person({
|
|
149
|
+
id: new URL("https://example.com/ap/actor/john"),
|
|
150
|
+
preferredUsername: "john"
|
|
151
|
+
}),
|
|
152
|
+
to: new URL("https://example.com/ap/actor/john/followers"),
|
|
153
|
+
cc: PUBLIC_COLLECTION
|
|
154
|
+
});
|
|
155
|
+
const originalMsg = await createMessage(originalPost, session, {});
|
|
156
|
+
const reply = await originalMsg.reply(text`Hello, John!`);
|
|
157
|
+
assert.deepStrictEqual(await repository.countMessages(), 1);
|
|
158
|
+
const [create] = await Array.fromAsync(repository.getMessages());
|
|
159
|
+
assert.ok(create != null);
|
|
160
|
+
assert.deepStrictEqual(ctx.sentActivities.length, 2);
|
|
161
|
+
const { recipients, activity } = ctx.sentActivities[0];
|
|
162
|
+
assert.deepStrictEqual(recipients, "followers");
|
|
163
|
+
assert.ok(activity instanceof Create);
|
|
164
|
+
assert.deepStrictEqual(await activity.toJsonLd({ format: "compact" }), await create.toJsonLd({ format: "compact" }));
|
|
165
|
+
const { recipients: recipients2, activity: activity2 } = ctx.sentActivities[1];
|
|
166
|
+
assert.deepStrictEqual(recipients2, [originalMsg.actor]);
|
|
167
|
+
assert.ok(activity2 instanceof Create);
|
|
168
|
+
assert.deepStrictEqual(await activity2.toJsonLd({ format: "compact" }), await create.toJsonLd({ format: "compact" }));
|
|
169
|
+
assert.deepStrictEqual(await reply.raw.toJsonLd({ format: "compact" }), await (await create.getObject())?.toJsonLd({ format: "compact" }));
|
|
170
|
+
assert.deepStrictEqual(reply.actor, await session.getActor());
|
|
171
|
+
assert.deepStrictEqual(reply.replyTarget, originalMsg);
|
|
172
|
+
assert.deepStrictEqual(reply.visibility, "unlisted");
|
|
173
|
+
});
|
|
174
|
+
test("MessageImpl.share()", async (t) => {
|
|
175
|
+
const repository = new MemoryRepository();
|
|
176
|
+
const bot = new BotImpl({
|
|
177
|
+
kv: new MemoryKvStore(),
|
|
178
|
+
repository,
|
|
179
|
+
username: "bot"
|
|
180
|
+
});
|
|
181
|
+
const ctx = createMockContext(bot, "https://example.com");
|
|
182
|
+
const session = new SessionImpl(bot, ctx);
|
|
183
|
+
const originalPost = new Note({
|
|
184
|
+
id: new URL("https://example.com/ap/note/c1c792ce-a0be-4685-b396-e59e5ef8c788"),
|
|
185
|
+
content: "<p>Hello, world!</p>",
|
|
186
|
+
attribution: new Person({
|
|
187
|
+
id: new URL("https://example.com/ap/actor/john"),
|
|
188
|
+
preferredUsername: "john"
|
|
189
|
+
}),
|
|
190
|
+
to: new URL("https://example.com/ap/actor/john/followers"),
|
|
191
|
+
cc: PUBLIC_COLLECTION
|
|
192
|
+
});
|
|
193
|
+
const originalMsg = await createMessage(originalPost, session, {});
|
|
194
|
+
const sharedMsg = await originalMsg.share();
|
|
195
|
+
await t.test("share()", async () => {
|
|
196
|
+
assert.deepStrictEqual(await repository.countMessages(), 1);
|
|
197
|
+
const [announce] = await Array.fromAsync(repository.getMessages());
|
|
198
|
+
assert.ok(announce != null);
|
|
199
|
+
assert.deepStrictEqual(ctx.sentActivities.length, 2);
|
|
200
|
+
const { recipients, activity } = ctx.sentActivities[0];
|
|
201
|
+
assert.deepStrictEqual(recipients, "followers");
|
|
202
|
+
assert.ok(activity instanceof Announce);
|
|
203
|
+
assert.deepStrictEqual(activity.toIds, [ctx.getFollowersUri(bot.identifier)]);
|
|
204
|
+
assert.deepStrictEqual(activity.ccIds, [PUBLIC_COLLECTION, originalPost.attributionId]);
|
|
205
|
+
assert.deepStrictEqual(await activity.toJsonLd({ format: "compact" }), await announce.toJsonLd({ format: "compact" }));
|
|
206
|
+
const { recipients: recipients2, activity: activity2 } = ctx.sentActivities[1];
|
|
207
|
+
assert.deepStrictEqual(recipients2, [originalMsg.actor]);
|
|
208
|
+
assert.ok(activity2 instanceof Announce);
|
|
209
|
+
assert.deepStrictEqual(activity2.toIds, [ctx.getFollowersUri(bot.identifier)]);
|
|
210
|
+
assert.deepStrictEqual(activity2.ccIds, [PUBLIC_COLLECTION, originalPost.attributionId]);
|
|
211
|
+
assert.deepStrictEqual(await activity2.toJsonLd({ format: "compact" }), await announce.toJsonLd({ format: "compact" }));
|
|
212
|
+
assert.deepStrictEqual(await sharedMsg.raw.toJsonLd({ format: "compact" }), await announce.toJsonLd({ format: "compact" }));
|
|
213
|
+
assert.deepStrictEqual(sharedMsg.actor, await session.getActor());
|
|
214
|
+
assert.deepStrictEqual(sharedMsg.visibility, "unlisted");
|
|
215
|
+
assert.deepStrictEqual(sharedMsg.original, originalMsg);
|
|
216
|
+
});
|
|
217
|
+
await t.test("unshare()", async () => {
|
|
218
|
+
ctx.sentActivities = [];
|
|
219
|
+
await sharedMsg.unshare();
|
|
220
|
+
assert.deepStrictEqual(await repository.countMessages(), 0);
|
|
221
|
+
assert.deepStrictEqual(ctx.sentActivities.length, 2);
|
|
222
|
+
const { recipients, activity } = ctx.sentActivities[0];
|
|
223
|
+
assert.deepStrictEqual(recipients, "followers");
|
|
224
|
+
assert.ok(activity instanceof Undo);
|
|
225
|
+
assert.deepStrictEqual(activity.actorId, ctx.getActorUri(bot.identifier));
|
|
226
|
+
assert.deepStrictEqual(activity.toIds, [ctx.getFollowersUri(bot.identifier)]);
|
|
227
|
+
assert.deepStrictEqual(activity.ccIds, [PUBLIC_COLLECTION, originalPost.attributionId]);
|
|
228
|
+
assert.deepStrictEqual(activity.objectId, sharedMsg.id);
|
|
229
|
+
const { recipients: recipients2, activity: activity2 } = ctx.sentActivities[1];
|
|
230
|
+
assert.deepStrictEqual(recipients2, [originalMsg.actor]);
|
|
231
|
+
assert.ok(activity2 instanceof Undo);
|
|
232
|
+
assert.deepStrictEqual(activity2.actorId, ctx.getActorUri(bot.identifier));
|
|
233
|
+
assert.deepStrictEqual(activity2.toIds, [ctx.getFollowersUri(bot.identifier)]);
|
|
234
|
+
assert.deepStrictEqual(activity2.ccIds, [PUBLIC_COLLECTION, originalPost.attributionId]);
|
|
235
|
+
assert.deepStrictEqual(activity2.objectId, sharedMsg.id);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
test("MessageImpl.like()", async (t) => {
|
|
239
|
+
const bot = new BotImpl({
|
|
240
|
+
kv: new MemoryKvStore(),
|
|
241
|
+
username: "bot"
|
|
242
|
+
});
|
|
243
|
+
const ctx = createMockContext(bot, "https://example.com");
|
|
244
|
+
const session = new SessionImpl(bot, ctx);
|
|
245
|
+
const originalPost = new Note({
|
|
246
|
+
id: new URL("https://example.com/ap/note/c1c792ce-a0be-4685-b396-e59e5ef8c788"),
|
|
247
|
+
content: "<p>Hello, world!</p>",
|
|
248
|
+
attribution: new Person({
|
|
249
|
+
id: new URL("https://example.com/ap/actor/john"),
|
|
250
|
+
preferredUsername: "john"
|
|
251
|
+
}),
|
|
252
|
+
to: new URL("https://example.com/ap/actor/john/followers"),
|
|
253
|
+
cc: PUBLIC_COLLECTION
|
|
254
|
+
});
|
|
255
|
+
const message = await createMessage(originalPost, session, {});
|
|
256
|
+
const like = await message.like();
|
|
257
|
+
await t.test("like()", async () => {
|
|
258
|
+
assert.deepStrictEqual(ctx.sentActivities.length, 2);
|
|
259
|
+
const { recipients, activity } = ctx.sentActivities[0];
|
|
260
|
+
assert.deepStrictEqual(recipients, "followers");
|
|
261
|
+
assert.ok(activity instanceof Like);
|
|
262
|
+
assert.deepStrictEqual(activity.actorId, ctx.getActorUri(bot.identifier));
|
|
263
|
+
assert.deepStrictEqual(activity.objectId, message.id);
|
|
264
|
+
const { recipients: recipients2, activity: activity2 } = ctx.sentActivities[1];
|
|
265
|
+
assert.deepStrictEqual(recipients2, [message.actor]);
|
|
266
|
+
assert.ok(activity2 instanceof Like);
|
|
267
|
+
assert.deepStrictEqual(activity2, activity);
|
|
268
|
+
assert.deepStrictEqual(like.actor, await session.getActor());
|
|
269
|
+
assert.deepStrictEqual(like.raw, activity);
|
|
270
|
+
assert.deepStrictEqual(like.id, activity.id);
|
|
271
|
+
assert.deepStrictEqual(like.message, message);
|
|
272
|
+
});
|
|
273
|
+
await t.test("unlike()", async () => {
|
|
274
|
+
ctx.sentActivities = [];
|
|
275
|
+
await like.unlike();
|
|
276
|
+
assert.deepStrictEqual(ctx.sentActivities.length, 2);
|
|
277
|
+
const { recipients, activity } = ctx.sentActivities[0];
|
|
278
|
+
assert.deepStrictEqual(recipients, "followers");
|
|
279
|
+
assert.ok(activity instanceof Undo);
|
|
280
|
+
assert.deepStrictEqual(activity.actorId, ctx.getActorUri(bot.identifier));
|
|
281
|
+
const object = await activity.getObject();
|
|
282
|
+
assert.ok(object instanceof Like);
|
|
283
|
+
assert.deepStrictEqual(object.actorId, ctx.getActorUri(bot.identifier));
|
|
284
|
+
assert.deepStrictEqual(object.objectId, message.id);
|
|
285
|
+
const { recipients: recipients2, activity: activity2 } = ctx.sentActivities[1];
|
|
286
|
+
assert.deepStrictEqual(recipients2, [message.actor]);
|
|
287
|
+
assert.ok(activity2 instanceof Undo);
|
|
288
|
+
assert.deepStrictEqual(activity2, activity);
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
test("AuthorizedMessage.update()", async (t) => {
|
|
292
|
+
const actorA = new Person({
|
|
293
|
+
id: new URL("https://example.com/ap/actor/john"),
|
|
294
|
+
preferredUsername: "john"
|
|
295
|
+
});
|
|
296
|
+
const actorB = new Person({
|
|
297
|
+
id: new URL("https://example.com/ap/actor/jane"),
|
|
298
|
+
preferredUsername: "jane"
|
|
299
|
+
});
|
|
300
|
+
for (const visibility of [
|
|
301
|
+
"public",
|
|
302
|
+
"unlisted",
|
|
303
|
+
"followers",
|
|
304
|
+
"direct"
|
|
305
|
+
]) {
|
|
306
|
+
const repository = new MemoryRepository();
|
|
307
|
+
const bot = new BotImpl({
|
|
308
|
+
kv: new MemoryKvStore(),
|
|
309
|
+
repository,
|
|
310
|
+
username: "bot"
|
|
311
|
+
});
|
|
312
|
+
const ctx = createMockContext(bot, "https://example.com");
|
|
313
|
+
const session = new SessionImpl(bot, ctx);
|
|
314
|
+
await t.test(visibility, async () => {
|
|
315
|
+
const msg = await session.publish(text`Hello, ${actorA}`, { visibility });
|
|
316
|
+
assert.deepStrictEqual(await repository.countMessages(), 1);
|
|
317
|
+
const originalRaw = msg.raw;
|
|
318
|
+
ctx.sentActivities = [];
|
|
319
|
+
const before = Temporal.Now.instant();
|
|
320
|
+
await msg.update(text`Hello, ${actorB}`);
|
|
321
|
+
const after = Temporal.Now.instant();
|
|
322
|
+
assert.deepStrictEqual(msg.text, "Hello, @jane@example.com");
|
|
323
|
+
assert.deepStrictEqual(msg.html, "<p>Hello, <a href=\"https://example.com/ap/actor/jane\" translate=\"no\" class=\"h-card u-url mention\" target=\"_blank\">@<span>jane@example.com</span></a></p>");
|
|
324
|
+
assert.deepStrictEqual(msg.mentions.length, 1);
|
|
325
|
+
assert.deepStrictEqual(msg.mentions[0].id, actorB.id);
|
|
326
|
+
assert.deepStrictEqual(msg.hashtags, []);
|
|
327
|
+
assert.ok(msg.updated != null);
|
|
328
|
+
assert.ok(msg.updated.epochNanoseconds >= before.epochNanoseconds);
|
|
329
|
+
assert.ok(msg.updated.epochNanoseconds <= after.epochNanoseconds);
|
|
330
|
+
assert.deepStrictEqual(msg.raw.content, msg.html);
|
|
331
|
+
if (visibility === "public") {
|
|
332
|
+
assert.deepStrictEqual(msg.raw.toIds, [PUBLIC_COLLECTION, actorB.id]);
|
|
333
|
+
assert.deepStrictEqual(msg.raw.ccIds, [ctx.getFollowersUri(bot.identifier)]);
|
|
334
|
+
} else if (visibility === "unlisted") {
|
|
335
|
+
assert.deepStrictEqual(msg.raw.toIds, [ctx.getFollowersUri(bot.identifier), actorB.id]);
|
|
336
|
+
assert.deepStrictEqual(msg.raw.ccIds, [PUBLIC_COLLECTION]);
|
|
337
|
+
} else if (visibility === "followers") {
|
|
338
|
+
assert.deepStrictEqual(msg.raw.toIds, [ctx.getFollowersUri(bot.identifier), actorB.id]);
|
|
339
|
+
assert.deepStrictEqual(msg.raw.ccIds, []);
|
|
340
|
+
} else {
|
|
341
|
+
assert.deepStrictEqual(msg.raw.toIds, [actorB.id]);
|
|
342
|
+
assert.deepStrictEqual(msg.raw.ccIds, []);
|
|
343
|
+
}
|
|
344
|
+
const tags = await Array.fromAsync(msg.raw.getTags());
|
|
345
|
+
assert.deepStrictEqual(tags.length, 1);
|
|
346
|
+
assert.ok(tags[0] instanceof Mention);
|
|
347
|
+
assert.deepStrictEqual(tags[0].name, "@jane@example.com");
|
|
348
|
+
assert.deepStrictEqual(tags[0].href, actorB.id);
|
|
349
|
+
assert.deepStrictEqual(msg.raw.published, originalRaw.published);
|
|
350
|
+
assert.deepStrictEqual(msg.raw.updated, msg.updated);
|
|
351
|
+
const [create] = await Array.fromAsync(repository.getMessages());
|
|
352
|
+
assert.deepStrictEqual(await (await create.getObject())?.toJsonLd({ format: "compact" }), await msg.raw.toJsonLd({ format: "compact" }));
|
|
353
|
+
assert.deepStrictEqual(ctx.sentActivities.length, visibility === "direct" ? 1 : 2);
|
|
354
|
+
const { recipients, activity } = ctx.sentActivities[0];
|
|
355
|
+
assert.deepStrictEqual(recipients, visibility === "direct" ? [actorA, actorB] : "followers");
|
|
356
|
+
assert.ok(activity instanceof Update);
|
|
357
|
+
assert.deepStrictEqual(activity.actorId, ctx.getActorUri(bot.identifier));
|
|
358
|
+
if (visibility === "public") {
|
|
359
|
+
assert.deepStrictEqual(activity.toIds, [
|
|
360
|
+
PUBLIC_COLLECTION,
|
|
361
|
+
actorA.id,
|
|
362
|
+
actorB.id
|
|
363
|
+
]);
|
|
364
|
+
assert.deepStrictEqual(activity.ccIds, [ctx.getFollowersUri(bot.identifier)]);
|
|
365
|
+
} else if (visibility === "unlisted") {
|
|
366
|
+
assert.deepStrictEqual(activity.toIds, [
|
|
367
|
+
ctx.getFollowersUri(bot.identifier),
|
|
368
|
+
actorA.id,
|
|
369
|
+
actorB.id
|
|
370
|
+
]);
|
|
371
|
+
assert.deepStrictEqual(activity.ccIds, [PUBLIC_COLLECTION]);
|
|
372
|
+
} else if (visibility === "followers") {
|
|
373
|
+
assert.deepStrictEqual(activity.toIds, [
|
|
374
|
+
ctx.getFollowersUri(bot.identifier),
|
|
375
|
+
actorA.id,
|
|
376
|
+
actorB.id
|
|
377
|
+
]);
|
|
378
|
+
assert.deepStrictEqual(activity.ccIds, []);
|
|
379
|
+
} else {
|
|
380
|
+
assert.deepStrictEqual(activity.toIds, [actorA.id, actorB.id]);
|
|
381
|
+
assert.deepStrictEqual(activity.ccIds, []);
|
|
382
|
+
}
|
|
383
|
+
assert.deepStrictEqual(await activity.getObject(), msg.raw);
|
|
384
|
+
assert.deepStrictEqual(activity.updated, msg.updated);
|
|
385
|
+
if (visibility !== "direct") {
|
|
386
|
+
const { recipients: recipients$1, activity: activity$1 } = ctx.sentActivities[1];
|
|
387
|
+
assert.deepStrictEqual(recipients$1, [actorA, actorB]);
|
|
388
|
+
assert.ok(activity$1 instanceof Update);
|
|
389
|
+
assert.deepStrictEqual(activity$1.actorId, ctx.getActorUri(bot.identifier));
|
|
390
|
+
assert.deepStrictEqual(await activity$1.getObject(), msg.raw);
|
|
391
|
+
assert.deepStrictEqual(activity$1.updated, msg.updated);
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
test("getMessageVisibility()", () => {
|
|
397
|
+
assert.deepStrictEqual(getMessageVisibility([PUBLIC_COLLECTION], [], new Person({})), "public");
|
|
398
|
+
assert.deepStrictEqual(getMessageVisibility([], [PUBLIC_COLLECTION], new Person({})), "unlisted");
|
|
399
|
+
assert.deepStrictEqual(getMessageVisibility([], [new URL("https://example.com/followers")], new Person({ followers: new URL("https://example.com/followers") })), "followers");
|
|
400
|
+
assert.deepStrictEqual(getMessageVisibility([new URL("https://example.com/followers")], [], new Person({ followers: new URL("https://example.com/followers") })), "followers");
|
|
401
|
+
assert.deepStrictEqual(getMessageVisibility([new URL("https://example.com/actor")], [], new Person({}), new Set(["https://example.com/actor"])), "direct");
|
|
402
|
+
assert.deepStrictEqual(getMessageVisibility([], [], new Person({})), "unknown");
|
|
403
|
+
});
|
|
404
|
+
test("MessageImpl.react()", async (t) => {
|
|
405
|
+
const bot = new BotImpl({
|
|
406
|
+
kv: new MemoryKvStore(),
|
|
407
|
+
username: "bot"
|
|
408
|
+
});
|
|
409
|
+
const ctx = createMockContext(bot, "https://example.com");
|
|
410
|
+
const session = new SessionImpl(bot, ctx);
|
|
411
|
+
const originalPost = new Note({
|
|
412
|
+
id: new URL("https://example.com/ap/note/react-test-note"),
|
|
413
|
+
content: "<p>React to this!</p>",
|
|
414
|
+
attribution: new Person({
|
|
415
|
+
id: new URL("https://example.com/ap/actor/john"),
|
|
416
|
+
preferredUsername: "john"
|
|
417
|
+
}),
|
|
418
|
+
to: PUBLIC_COLLECTION
|
|
419
|
+
});
|
|
420
|
+
const message = await createMessage(originalPost, session, {});
|
|
421
|
+
await t.test("react() with string emoji", async () => {
|
|
422
|
+
ctx.sentActivities = [];
|
|
423
|
+
const reaction = await message.react(emoji`👍`);
|
|
424
|
+
assert.deepStrictEqual(ctx.sentActivities.length, 2);
|
|
425
|
+
const { recipients, activity } = ctx.sentActivities[0];
|
|
426
|
+
assert.deepStrictEqual(recipients, "followers");
|
|
427
|
+
assert.ok(activity instanceof EmojiReact);
|
|
428
|
+
assert.deepStrictEqual(activity.actorId, ctx.getActorUri(bot.identifier));
|
|
429
|
+
assert.deepStrictEqual(activity.objectId, message.id);
|
|
430
|
+
assert.deepStrictEqual(activity.name, "👍");
|
|
431
|
+
assert.deepStrictEqual(await Array.fromAsync(activity.getTags()), []);
|
|
432
|
+
const { recipients: recipients2, activity: activity2 } = ctx.sentActivities[1];
|
|
433
|
+
assert.deepStrictEqual(recipients2, [message.actor]);
|
|
434
|
+
assert.ok(activity2 instanceof EmojiReact);
|
|
435
|
+
assert.deepStrictEqual(activity2, activity);
|
|
436
|
+
assert.deepStrictEqual(reaction.actor, await session.getActor());
|
|
437
|
+
assert.deepStrictEqual(reaction.raw, activity);
|
|
438
|
+
assert.deepStrictEqual(reaction.id, activity.id);
|
|
439
|
+
assert.deepStrictEqual(reaction.message, message);
|
|
440
|
+
assert.deepStrictEqual(reaction.emoji, emoji`👍`);
|
|
441
|
+
ctx.sentActivities = [];
|
|
442
|
+
await reaction.unreact();
|
|
443
|
+
assert.deepStrictEqual(ctx.sentActivities.length, 2);
|
|
444
|
+
const { recipients: urRecipients, activity: urActivity } = ctx.sentActivities[0];
|
|
445
|
+
assert.deepStrictEqual(urRecipients, "followers");
|
|
446
|
+
assert.ok(urActivity instanceof Undo);
|
|
447
|
+
assert.deepStrictEqual(urActivity.actorId, ctx.getActorUri(bot.identifier));
|
|
448
|
+
const urObject = await urActivity.getObject();
|
|
449
|
+
assert.ok(urObject instanceof EmojiReact);
|
|
450
|
+
assert.deepStrictEqual(urObject.id, reaction.id);
|
|
451
|
+
const { recipients: urRecipients2, activity: urActivity2 } = ctx.sentActivities[1];
|
|
452
|
+
assert.deepStrictEqual(urRecipients2, [message.actor]);
|
|
453
|
+
assert.ok(urActivity2 instanceof Undo);
|
|
454
|
+
assert.deepStrictEqual(urActivity2, urActivity);
|
|
455
|
+
});
|
|
456
|
+
await t.test("react() with CustomEmoji", async () => {
|
|
457
|
+
ctx.sentActivities = [];
|
|
458
|
+
const customEmoji = new Emoji({
|
|
459
|
+
id: new URL("https://example.com/emojis/custom"),
|
|
460
|
+
name: ":custom:",
|
|
461
|
+
icon: new Image({ url: new URL("https://example.com/emojis/custom.png") })
|
|
462
|
+
});
|
|
463
|
+
const reaction = await message.react(customEmoji);
|
|
464
|
+
assert.deepStrictEqual(ctx.sentActivities.length, 2);
|
|
465
|
+
const { activity } = ctx.sentActivities[0];
|
|
466
|
+
assert.ok(activity instanceof EmojiReact);
|
|
467
|
+
assert.deepStrictEqual(activity.name, ":custom:");
|
|
468
|
+
const tags = await Array.fromAsync(activity.getTags());
|
|
469
|
+
assert.deepStrictEqual(tags.length, 1);
|
|
470
|
+
assert.deepStrictEqual(tags[0], customEmoji);
|
|
471
|
+
assert.deepStrictEqual(reaction.emoji, customEmoji);
|
|
472
|
+
ctx.sentActivities = [];
|
|
473
|
+
await reaction.unreact();
|
|
474
|
+
assert.deepStrictEqual(ctx.sentActivities.length, 2);
|
|
475
|
+
const { activity: urActivity } = ctx.sentActivities[0];
|
|
476
|
+
assert.ok(urActivity instanceof Undo);
|
|
477
|
+
const urObject = await urActivity.getObject();
|
|
478
|
+
assert.ok(urObject instanceof EmojiReact);
|
|
479
|
+
assert.deepStrictEqual(urObject.id, reaction.id);
|
|
480
|
+
const urTags = await Array.fromAsync(urActivity.getTags());
|
|
481
|
+
assert.deepStrictEqual(urTags.length, 1);
|
|
482
|
+
assert.deepStrictEqual(urTags[0], customEmoji);
|
|
483
|
+
});
|
|
484
|
+
await t.test("react() with DeferredCustomEmoji", async () => {
|
|
485
|
+
ctx.sentActivities = [];
|
|
486
|
+
const deferredEmoji = (sessionParam) => {
|
|
487
|
+
assert.deepStrictEqual(sessionParam, session);
|
|
488
|
+
return new Emoji({
|
|
489
|
+
id: new URL("https://example.com/emojis/deferred"),
|
|
490
|
+
name: ":deferred:",
|
|
491
|
+
icon: new Image({ url: new URL("https://example.com/emojis/deferred.png") })
|
|
492
|
+
});
|
|
493
|
+
};
|
|
494
|
+
const reaction = await message.react(deferredEmoji);
|
|
495
|
+
assert.deepStrictEqual(ctx.sentActivities.length, 2);
|
|
496
|
+
const { activity } = ctx.sentActivities[0];
|
|
497
|
+
assert.ok(activity instanceof EmojiReact);
|
|
498
|
+
assert.deepStrictEqual(activity.name, ":deferred:");
|
|
499
|
+
const tags = await Array.fromAsync(activity.getTags());
|
|
500
|
+
assert.deepStrictEqual(tags.length, 1);
|
|
501
|
+
assert.ok(tags[0] instanceof Emoji);
|
|
502
|
+
assert.deepStrictEqual(tags[0].id?.href, "https://example.com/emojis/deferred");
|
|
503
|
+
assert.deepStrictEqual(reaction.emoji, tags[0]);
|
|
504
|
+
ctx.sentActivities = [];
|
|
505
|
+
await reaction.unreact();
|
|
506
|
+
assert.deepStrictEqual(ctx.sentActivities.length, 2);
|
|
507
|
+
const { activity: urActivity } = ctx.sentActivities[0];
|
|
508
|
+
assert.ok(urActivity instanceof Undo);
|
|
509
|
+
const urObject = await urActivity.getObject();
|
|
510
|
+
assert.ok(urObject instanceof EmojiReact);
|
|
511
|
+
assert.deepStrictEqual(urObject.id, reaction.id);
|
|
512
|
+
const urTags = await Array.fromAsync(urActivity.getTags());
|
|
513
|
+
assert.deepStrictEqual(urTags.length, 1);
|
|
514
|
+
assert.deepStrictEqual(urTags[0], tags[0]);
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
//#endregion
|
|
519
|
+
//# sourceMappingURL=message-impl.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-impl.test.js","names":["RawLike","recipients","activity","CustomEmoji","deferredEmoji: DeferredCustomEmoji<void>"],"sources":["../src/message-impl.test.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 { MemoryKvStore } from \"@fedify/fedify/federation\";\nimport {\n Announce,\n Article,\n ChatMessage,\n Create,\n Delete,\n Emoji as CustomEmoji,\n EmojiReact,\n Hashtag,\n Image,\n Like as RawLike,\n Mention,\n Note,\n Person,\n PUBLIC_COLLECTION,\n Question,\n Tombstone,\n Undo,\n Update,\n} from \"@fedify/fedify/vocab\";\nimport assert from \"node:assert\";\nimport { test } from \"node:test\";\nimport { BotImpl } from \"./bot-impl.ts\";\nimport { type DeferredCustomEmoji, emoji } from \"./emoji.ts\";\nimport {\n createMessage,\n getMessageClass,\n getMessageVisibility,\n isMessageObject,\n} from \"./message-impl.ts\";\nimport { MemoryRepository } from \"./repository.ts\";\nimport { createMockContext } from \"./session-impl.test.ts\";\nimport { SessionImpl } from \"./session-impl.ts\";\nimport { text } from \"./text.ts\";\n\ntest(\"isMessageObject()\", () => {\n assert.ok(isMessageObject(new Article({})));\n assert.ok(isMessageObject(new ChatMessage({})));\n assert.ok(isMessageObject(new Note({})));\n assert.ok(isMessageObject(new Question({})));\n assert.ok(!isMessageObject(new Person({})));\n});\n\ntest(\"getMessageClass()\", () => {\n assert.deepStrictEqual(\n getMessageClass(new Article({})),\n Article,\n );\n assert.deepStrictEqual(\n getMessageClass(new ChatMessage({})),\n ChatMessage,\n );\n assert.deepStrictEqual(\n getMessageClass(new Note({})),\n Note,\n );\n assert.deepStrictEqual(\n getMessageClass(new Question({})),\n Question,\n );\n});\n\ntest(\"createMessage()\", async () => {\n const bot = new BotImpl<void>({ kv: new MemoryKvStore(), username: \"bot\" });\n const session = bot.getSession(\"https://example.com\", undefined);\n await assert.rejects(\n () => createMessage<Note, void>(new Note({}), session, {}),\n TypeError,\n \"The raw.id is required.\",\n );\n await assert.rejects(\n () =>\n createMessage<Note, void>(\n new Note({ id: new URL(\"https://example.com/notes/1\") }),\n session,\n {},\n ),\n TypeError,\n \"The raw.content is required.\",\n );\n await assert.rejects(\n () =>\n createMessage<Note, void>(\n new Note({\n id: new URL(\"https://example.com/notes/1\"),\n content: \"<p>Hello, world!</p>\",\n }),\n session,\n {},\n ),\n TypeError,\n \"The raw.attributionId is required.\",\n );\n\n const publicNote = new Note({\n id: new URL(\"https://example.com/notes/1\"),\n content: \"<p>#Hello, <em>world</em>!</p>\",\n attribution: new URL(\"https://example.com/ap/actor/bot\"),\n to: PUBLIC_COLLECTION,\n cc: new URL(\"https://example.com/ap/actor/bot/followers\"),\n tags: [\n new Mention({\n name: \"@bot\",\n href: new URL(\"https://example.com/ap/actor/bot\"),\n }),\n new Hashtag({\n name: \"#Hello\",\n href: new URL(\"https://example.com/tags/hello\"),\n }),\n ],\n });\n const publicMessage = await createMessage<Note, void>(\n publicNote,\n session,\n {},\n );\n assert.deepStrictEqual(publicMessage.raw, publicNote);\n assert.deepStrictEqual(publicMessage.id, publicNote.id);\n assert.deepStrictEqual(publicMessage.actor, await session.getActor());\n assert.deepStrictEqual(publicMessage.visibility, \"public\");\n assert.deepStrictEqual(publicMessage.language, undefined);\n assert.deepStrictEqual(publicMessage.text, \"#Hello, world!\");\n assert.deepStrictEqual(publicMessage.html, \"<p>#Hello, <em>world</em>!</p>\");\n assert.deepStrictEqual(publicMessage.replyTarget, undefined);\n assert.deepStrictEqual(publicMessage.mentions, [await session.getActor()]);\n assert.deepStrictEqual(publicMessage.hashtags, [\n new Hashtag({\n name: \"#Hello\",\n href: new URL(\"https://example.com/tags/hello\"),\n }),\n ]);\n assert.deepStrictEqual(publicMessage.attachments, []);\n assert.deepStrictEqual(publicMessage.published, undefined);\n assert.deepStrictEqual(publicMessage.updated, undefined);\n\n const unlistedNote = publicNote.clone({\n to: new URL(\"https://example.com/ap/actor/bot/followers\"),\n cc: PUBLIC_COLLECTION,\n });\n const unlistedMessage = await createMessage<Note, void>(\n unlistedNote,\n session,\n {},\n );\n assert.deepStrictEqual(unlistedMessage.visibility, \"unlisted\");\n\n const followersNote = publicNote.clone({\n to: new URL(\"https://example.com/ap/actor/bot/followers\"),\n ccs: [],\n });\n const followersMessage = await createMessage<Note, void>(\n followersNote,\n session,\n {},\n );\n assert.deepStrictEqual(followersMessage.visibility, \"followers\");\n\n const direct = publicNote.clone({\n to: new URL(\"https://example.com/ap/actor/bot\"),\n ccs: [],\n });\n const directMessage = await createMessage<Note, void>(direct, session, {});\n assert.deepStrictEqual(directMessage.visibility, \"direct\");\n\n const unknown = publicNote.clone({\n tos: [],\n ccs: [],\n });\n const unknownMessage = await createMessage<Note, void>(unknown, session, {});\n assert.deepStrictEqual(unknownMessage.visibility, \"unknown\");\n});\n\ntest(\"AuthorizedMessageImpl.delete()\", async () => {\n const repository = new MemoryRepository();\n const bot = new BotImpl<void>({\n kv: new MemoryKvStore(),\n repository,\n username: \"bot\",\n });\n const ctx = createMockContext(bot, \"https://example.com\");\n const session = new SessionImpl(bot, ctx);\n const note = new Note({\n id: new URL(\n \"https://example.com/ap/note/c1c792ce-a0be-4685-b396-e59e5ef8c788\",\n ),\n content: \"<p>Hello, world!</p>\",\n attribution: new URL(\"https://example.com/ap/actor/bot\"),\n to: PUBLIC_COLLECTION,\n cc: new URL(\"https://example.com/ap/actor/bot/followers\"),\n });\n const msg = await createMessage<Note, void>(\n note,\n session,\n {},\n undefined,\n undefined,\n true,\n );\n await repository.addMessage(\n \"c1c792ce-a0be-4685-b396-e59e5ef8c788\",\n new Create({\n id: new URL(\n \"https://example.com/ap/create/c1c792ce-a0be-4685-b396-e59e5ef8c788\",\n ),\n actor: new URL(\"https://example.com/ap/actor/bot\"),\n to: PUBLIC_COLLECTION,\n cc: new URL(\"https://example.com/ap/actor/bot/followers\"),\n object: note,\n }),\n );\n await msg.delete();\n assert.deepStrictEqual(await repository.countMessages(), 0);\n assert.deepStrictEqual(ctx.sentActivities.length, 1);\n const { recipients, activity } = ctx.sentActivities[0];\n assert.deepStrictEqual(recipients, \"followers\");\n assert.ok(activity instanceof Delete);\n assert.deepStrictEqual(activity.actorId, ctx.getActorUri(bot.identifier));\n assert.deepStrictEqual(activity.toIds, [PUBLIC_COLLECTION]);\n assert.deepStrictEqual(activity.ccIds, [ctx.getFollowersUri(bot.identifier)]);\n const tombstone = await activity.getObject();\n assert.ok(tombstone instanceof Tombstone);\n assert.deepStrictEqual(tombstone.id, note.id);\n});\n\ntest(\"MessageImpl.reply()\", async () => {\n const repository = new MemoryRepository();\n const bot = new BotImpl<void>({\n kv: new MemoryKvStore(),\n repository,\n username: \"bot\",\n });\n const ctx = createMockContext(bot, \"https://example.com\");\n const session = new SessionImpl(bot, ctx);\n const originalPost = new Note({\n id: new URL(\n \"https://example.com/ap/note/c1c792ce-a0be-4685-b396-e59e5ef8c788\",\n ),\n content: \"<p>Hello, world!</p>\",\n attribution: new Person({\n id: new URL(\"https://example.com/ap/actor/john\"),\n preferredUsername: \"john\",\n }),\n to: new URL(\"https://example.com/ap/actor/john/followers\"),\n cc: PUBLIC_COLLECTION,\n });\n const originalMsg = await createMessage<Note, void>(\n originalPost,\n session,\n {},\n );\n const reply = await originalMsg.reply(text`Hello, John!`);\n assert.deepStrictEqual(await repository.countMessages(), 1);\n const [create] = await Array.fromAsync(repository.getMessages());\n assert.ok(create != null);\n assert.deepStrictEqual(ctx.sentActivities.length, 2);\n const { recipients, activity } = ctx.sentActivities[0];\n assert.deepStrictEqual(recipients, \"followers\");\n assert.ok(activity instanceof Create);\n assert.deepStrictEqual(\n await activity.toJsonLd({ format: \"compact\" }),\n await create.toJsonLd({ format: \"compact\" }),\n );\n const { recipients: recipients2, activity: activity2 } =\n ctx.sentActivities[1];\n assert.deepStrictEqual(recipients2, [originalMsg.actor]);\n assert.ok(activity2 instanceof Create);\n assert.deepStrictEqual(\n await activity2.toJsonLd({ format: \"compact\" }),\n await create.toJsonLd({ format: \"compact\" }),\n );\n assert.deepStrictEqual(\n await reply.raw.toJsonLd({ format: \"compact\" }),\n await (await create.getObject())?.toJsonLd({ format: \"compact\" }),\n );\n assert.deepStrictEqual(reply.actor, await session.getActor());\n assert.deepStrictEqual(reply.replyTarget, originalMsg);\n assert.deepStrictEqual(reply.visibility, \"unlisted\");\n});\n\ntest(\"MessageImpl.share()\", async (t) => {\n const repository = new MemoryRepository();\n const bot = new BotImpl<void>({\n kv: new MemoryKvStore(),\n repository,\n username: \"bot\",\n });\n const ctx = createMockContext(bot, \"https://example.com\");\n const session = new SessionImpl(bot, ctx);\n const originalPost = new Note({\n id: new URL(\n \"https://example.com/ap/note/c1c792ce-a0be-4685-b396-e59e5ef8c788\",\n ),\n content: \"<p>Hello, world!</p>\",\n attribution: new Person({\n id: new URL(\"https://example.com/ap/actor/john\"),\n preferredUsername: \"john\",\n }),\n to: new URL(\"https://example.com/ap/actor/john/followers\"),\n cc: PUBLIC_COLLECTION,\n });\n const originalMsg = await createMessage<Note, void>(\n originalPost,\n session,\n {},\n );\n const sharedMsg = await originalMsg.share();\n\n await t.test(\"share()\", async () => {\n assert.deepStrictEqual(await repository.countMessages(), 1);\n const [announce] = await Array.fromAsync(repository.getMessages());\n assert.ok(announce != null);\n assert.deepStrictEqual(ctx.sentActivities.length, 2);\n const { recipients, activity } = ctx.sentActivities[0];\n assert.deepStrictEqual(recipients, \"followers\");\n assert.ok(activity instanceof Announce);\n assert.deepStrictEqual(activity.toIds, [\n ctx.getFollowersUri(bot.identifier),\n ]);\n assert.deepStrictEqual(activity.ccIds, [\n PUBLIC_COLLECTION,\n originalPost.attributionId,\n ]);\n assert.deepStrictEqual(\n await activity.toJsonLd({ format: \"compact\" }),\n await announce.toJsonLd({ format: \"compact\" }),\n );\n const { recipients: recipients2, activity: activity2 } =\n ctx.sentActivities[1];\n assert.deepStrictEqual(recipients2, [originalMsg.actor]);\n assert.ok(activity2 instanceof Announce);\n assert.deepStrictEqual(activity2.toIds, [\n ctx.getFollowersUri(bot.identifier),\n ]);\n assert.deepStrictEqual(activity2.ccIds, [\n PUBLIC_COLLECTION,\n originalPost.attributionId,\n ]);\n assert.deepStrictEqual(\n await activity2.toJsonLd({ format: \"compact\" }),\n await announce.toJsonLd({ format: \"compact\" }),\n );\n assert.deepStrictEqual(\n await sharedMsg.raw.toJsonLd({ format: \"compact\" }),\n await announce.toJsonLd({ format: \"compact\" }),\n );\n assert.deepStrictEqual(sharedMsg.actor, await session.getActor());\n assert.deepStrictEqual(sharedMsg.visibility, \"unlisted\");\n assert.deepStrictEqual(sharedMsg.original, originalMsg);\n });\n\n await t.test(\"unshare()\", async () => {\n ctx.sentActivities = [];\n\n await sharedMsg.unshare();\n assert.deepStrictEqual(await repository.countMessages(), 0);\n assert.deepStrictEqual(ctx.sentActivities.length, 2);\n const { recipients, activity } = ctx.sentActivities[0];\n assert.deepStrictEqual(recipients, \"followers\");\n assert.ok(activity instanceof Undo);\n assert.deepStrictEqual(activity.actorId, ctx.getActorUri(bot.identifier));\n assert.deepStrictEqual(activity.toIds, [\n ctx.getFollowersUri(bot.identifier),\n ]);\n assert.deepStrictEqual(activity.ccIds, [\n PUBLIC_COLLECTION,\n originalPost.attributionId,\n ]);\n assert.deepStrictEqual(activity.objectId, sharedMsg.id);\n const { recipients: recipients2, activity: activity2 } =\n ctx.sentActivities[1];\n assert.deepStrictEqual(recipients2, [originalMsg.actor]);\n assert.ok(activity2 instanceof Undo);\n assert.deepStrictEqual(activity2.actorId, ctx.getActorUri(bot.identifier));\n assert.deepStrictEqual(activity2.toIds, [\n ctx.getFollowersUri(bot.identifier),\n ]);\n assert.deepStrictEqual(activity2.ccIds, [\n PUBLIC_COLLECTION,\n originalPost.attributionId,\n ]);\n assert.deepStrictEqual(activity2.objectId, sharedMsg.id);\n });\n});\n\ntest(\"MessageImpl.like()\", async (t) => {\n const bot = new BotImpl<void>({\n kv: new MemoryKvStore(),\n username: \"bot\",\n });\n const ctx = createMockContext(bot, \"https://example.com\");\n const session = new SessionImpl(bot, ctx);\n const originalPost = new Note({\n id: new URL(\n \"https://example.com/ap/note/c1c792ce-a0be-4685-b396-e59e5ef8c788\",\n ),\n content: \"<p>Hello, world!</p>\",\n attribution: new Person({\n id: new URL(\"https://example.com/ap/actor/john\"),\n preferredUsername: \"john\",\n }),\n to: new URL(\"https://example.com/ap/actor/john/followers\"),\n cc: PUBLIC_COLLECTION,\n });\n const message = await createMessage<Note, void>(\n originalPost,\n session,\n {},\n );\n const like = await message.like();\n\n await t.test(\"like()\", async () => {\n assert.deepStrictEqual(ctx.sentActivities.length, 2);\n const { recipients, activity } = ctx.sentActivities[0];\n assert.deepStrictEqual(recipients, \"followers\");\n assert.ok(activity instanceof RawLike);\n assert.deepStrictEqual(activity.actorId, ctx.getActorUri(bot.identifier));\n assert.deepStrictEqual(activity.objectId, message.id);\n const { recipients: recipients2, activity: activity2 } =\n ctx.sentActivities[1];\n assert.deepStrictEqual(recipients2, [message.actor]);\n assert.ok(activity2 instanceof RawLike);\n assert.deepStrictEqual(activity2, activity);\n assert.deepStrictEqual(like.actor, await session.getActor());\n assert.deepStrictEqual(like.raw, activity);\n assert.deepStrictEqual(like.id, activity.id);\n assert.deepStrictEqual(like.message, message);\n });\n\n await t.test(\"unlike()\", async () => {\n ctx.sentActivities = [];\n\n await like.unlike();\n assert.deepStrictEqual(ctx.sentActivities.length, 2);\n const { recipients, activity } = ctx.sentActivities[0];\n assert.deepStrictEqual(recipients, \"followers\");\n assert.ok(activity instanceof Undo);\n assert.deepStrictEqual(activity.actorId, ctx.getActorUri(bot.identifier));\n const object = await activity.getObject();\n assert.ok(object instanceof RawLike);\n assert.deepStrictEqual(object.actorId, ctx.getActorUri(bot.identifier));\n assert.deepStrictEqual(object.objectId, message.id);\n const { recipients: recipients2, activity: activity2 } =\n ctx.sentActivities[1];\n assert.deepStrictEqual(recipients2, [message.actor]);\n assert.ok(activity2 instanceof Undo);\n assert.deepStrictEqual(activity2, activity);\n });\n});\n\ntest(\"AuthorizedMessage.update()\", async (t) => {\n const actorA = new Person({\n id: new URL(\"https://example.com/ap/actor/john\"),\n preferredUsername: \"john\",\n });\n const actorB = new Person({\n id: new URL(\"https://example.com/ap/actor/jane\"),\n preferredUsername: \"jane\",\n });\n\n for (\n const visibility of [\"public\", \"unlisted\", \"followers\", \"direct\"] as const\n ) {\n const repository = new MemoryRepository();\n const bot = new BotImpl<void>({\n kv: new MemoryKvStore(),\n repository,\n username: \"bot\",\n });\n const ctx = createMockContext(bot, \"https://example.com\");\n const session = new SessionImpl(bot, ctx);\n\n await t.test(visibility, async () => {\n const msg = await session.publish(text`Hello, ${actorA}`, { visibility });\n assert.deepStrictEqual(await repository.countMessages(), 1);\n const originalRaw = msg.raw;\n ctx.sentActivities = [];\n const before = Temporal.Now.instant();\n await msg.update(text`Hello, ${actorB}`);\n const after = Temporal.Now.instant();\n assert.deepStrictEqual(msg.text, \"Hello, @jane@example.com\");\n assert.deepStrictEqual(\n msg.html,\n '<p>Hello, <a href=\"https://example.com/ap/actor/jane\" ' +\n 'translate=\"no\" class=\"h-card u-url mention\" target=\"_blank\">' +\n \"@<span>jane@example.com</span></a></p>\",\n );\n assert.deepStrictEqual(msg.mentions.length, 1);\n assert.deepStrictEqual(msg.mentions[0].id, actorB.id);\n assert.deepStrictEqual(msg.hashtags, []);\n assert.ok(msg.updated != null);\n assert.ok(msg.updated.epochNanoseconds >= before.epochNanoseconds);\n assert.ok(msg.updated.epochNanoseconds <= after.epochNanoseconds);\n assert.deepStrictEqual(msg.raw.content, msg.html);\n if (visibility === \"public\") {\n assert.deepStrictEqual(msg.raw.toIds, [PUBLIC_COLLECTION, actorB.id]);\n assert.deepStrictEqual(msg.raw.ccIds, [\n ctx.getFollowersUri(bot.identifier),\n ]);\n } else if (visibility === \"unlisted\") {\n assert.deepStrictEqual(msg.raw.toIds, [\n ctx.getFollowersUri(bot.identifier),\n actorB.id,\n ]);\n assert.deepStrictEqual(msg.raw.ccIds, [PUBLIC_COLLECTION]);\n } else if (visibility === \"followers\") {\n assert.deepStrictEqual(msg.raw.toIds, [\n ctx.getFollowersUri(bot.identifier),\n actorB.id,\n ]);\n assert.deepStrictEqual(msg.raw.ccIds, []);\n } else {\n assert.deepStrictEqual(msg.raw.toIds, [actorB.id]);\n assert.deepStrictEqual(msg.raw.ccIds, []);\n }\n const tags = await Array.fromAsync(msg.raw.getTags());\n assert.deepStrictEqual(tags.length, 1);\n assert.ok(tags[0] instanceof Mention);\n assert.deepStrictEqual(tags[0].name, \"@jane@example.com\");\n assert.deepStrictEqual(tags[0].href, actorB.id);\n assert.deepStrictEqual(msg.raw.published, originalRaw.published);\n assert.deepStrictEqual(msg.raw.updated, msg.updated);\n const [create] = await Array.fromAsync(repository.getMessages());\n assert.deepStrictEqual(\n await (await create.getObject())?.toJsonLd({ format: \"compact\" }),\n await msg.raw.toJsonLd({ format: \"compact\" }),\n );\n assert.deepStrictEqual(\n ctx.sentActivities.length,\n visibility === \"direct\" ? 1 : 2,\n );\n const { recipients, activity } = ctx.sentActivities[0];\n assert.deepStrictEqual(\n recipients,\n visibility === \"direct\" ? [actorA, actorB] : \"followers\",\n );\n assert.ok(activity instanceof Update);\n assert.deepStrictEqual(activity.actorId, ctx.getActorUri(bot.identifier));\n if (visibility === \"public\") {\n assert.deepStrictEqual(activity.toIds, [\n PUBLIC_COLLECTION,\n actorA.id,\n actorB.id,\n ]);\n assert.deepStrictEqual(activity.ccIds, [\n ctx.getFollowersUri(bot.identifier),\n ]);\n } else if (visibility === \"unlisted\") {\n assert.deepStrictEqual(activity.toIds, [\n ctx.getFollowersUri(bot.identifier),\n actorA.id,\n actorB.id,\n ]);\n assert.deepStrictEqual(activity.ccIds, [PUBLIC_COLLECTION]);\n } else if (visibility === \"followers\") {\n assert.deepStrictEqual(activity.toIds, [\n ctx.getFollowersUri(bot.identifier),\n actorA.id,\n actorB.id,\n ]);\n assert.deepStrictEqual(activity.ccIds, []);\n } else {\n assert.deepStrictEqual(activity.toIds, [actorA.id, actorB.id]);\n assert.deepStrictEqual(activity.ccIds, []);\n }\n assert.deepStrictEqual(await activity.getObject(), msg.raw);\n assert.deepStrictEqual(activity.updated, msg.updated);\n if (visibility !== \"direct\") {\n const { recipients, activity } = ctx.sentActivities[1];\n assert.deepStrictEqual(recipients, [actorA, actorB]);\n assert.ok(activity instanceof Update);\n assert.deepStrictEqual(\n activity.actorId,\n ctx.getActorUri(bot.identifier),\n );\n assert.deepStrictEqual(await activity.getObject(), msg.raw);\n assert.deepStrictEqual(activity.updated, msg.updated);\n }\n });\n }\n});\n\ntest(\"getMessageVisibility()\", () => {\n assert.deepStrictEqual(\n getMessageVisibility([PUBLIC_COLLECTION], [], new Person({})),\n \"public\",\n );\n assert.deepStrictEqual(\n getMessageVisibility([], [PUBLIC_COLLECTION], new Person({})),\n \"unlisted\",\n );\n assert.deepStrictEqual(\n getMessageVisibility(\n [],\n [new URL(\"https://example.com/followers\")],\n new Person({\n followers: new URL(\"https://example.com/followers\"),\n }),\n ),\n \"followers\",\n );\n assert.deepStrictEqual(\n getMessageVisibility(\n [new URL(\"https://example.com/followers\")],\n [],\n new Person({\n followers: new URL(\"https://example.com/followers\"),\n }),\n ),\n \"followers\",\n );\n assert.deepStrictEqual(\n getMessageVisibility(\n [new URL(\"https://example.com/actor\")],\n [],\n new Person({}),\n new Set([\"https://example.com/actor\"]),\n ),\n \"direct\",\n );\n assert.deepStrictEqual(\n getMessageVisibility([], [], new Person({})),\n \"unknown\",\n );\n});\n\ntest(\"MessageImpl.react()\", async (t) => {\n const bot = new BotImpl<void>({\n kv: new MemoryKvStore(),\n username: \"bot\",\n });\n const ctx = createMockContext(bot, \"https://example.com\");\n const session = new SessionImpl(bot, ctx);\n const originalPost = new Note({\n id: new URL(\n \"https://example.com/ap/note/react-test-note\",\n ),\n content: \"<p>React to this!</p>\",\n attribution: new Person({\n id: new URL(\"https://example.com/ap/actor/john\"),\n preferredUsername: \"john\",\n }),\n to: PUBLIC_COLLECTION,\n });\n const message = await createMessage<Note, void>(\n originalPost,\n session,\n {},\n );\n\n await t.test(\"react() with string emoji\", async () => {\n ctx.sentActivities = []; // Clear previous activities\n const reaction = await message.react(emoji`👍`);\n assert.deepStrictEqual(ctx.sentActivities.length, 2);\n const { recipients, activity } = ctx.sentActivities[0];\n assert.deepStrictEqual(recipients, \"followers\");\n assert.ok(activity instanceof EmojiReact);\n assert.deepStrictEqual(activity.actorId, ctx.getActorUri(bot.identifier));\n assert.deepStrictEqual(activity.objectId, message.id);\n assert.deepStrictEqual(activity.name, \"👍\");\n assert.deepStrictEqual(await Array.fromAsync(activity.getTags()), []);\n const { recipients: recipients2, activity: activity2 } =\n ctx.sentActivities[1];\n assert.deepStrictEqual(recipients2, [message.actor]);\n assert.ok(activity2 instanceof EmojiReact);\n assert.deepStrictEqual(activity2, activity);\n assert.deepStrictEqual(reaction.actor, await session.getActor());\n assert.deepStrictEqual(reaction.raw, activity);\n assert.deepStrictEqual(reaction.id, activity.id);\n assert.deepStrictEqual(reaction.message, message);\n assert.deepStrictEqual(reaction.emoji, emoji`👍`);\n\n // Test unreact\n ctx.sentActivities = [];\n await reaction.unreact();\n assert.deepStrictEqual(ctx.sentActivities.length, 2);\n const { recipients: urRecipients, activity: urActivity } =\n ctx.sentActivities[0];\n assert.deepStrictEqual(urRecipients, \"followers\");\n assert.ok(urActivity instanceof Undo);\n assert.deepStrictEqual(urActivity.actorId, ctx.getActorUri(bot.identifier));\n const urObject = await urActivity.getObject();\n assert.ok(urObject instanceof EmojiReact);\n assert.deepStrictEqual(urObject.id, reaction.id);\n const { recipients: urRecipients2, activity: urActivity2 } =\n ctx.sentActivities[1];\n assert.deepStrictEqual(urRecipients2, [message.actor]);\n assert.ok(urActivity2 instanceof Undo);\n assert.deepStrictEqual(urActivity2, urActivity);\n });\n\n await t.test(\"react() with CustomEmoji\", async () => {\n ctx.sentActivities = [];\n const customEmoji = new CustomEmoji({\n id: new URL(\"https://example.com/emojis/custom\"),\n name: \":custom:\",\n icon: new Image({\n url: new URL(\"https://example.com/emojis/custom.png\"),\n }),\n });\n const reaction = await message.react(customEmoji);\n assert.deepStrictEqual(ctx.sentActivities.length, 2);\n const { activity } = ctx.sentActivities[0];\n assert.ok(activity instanceof EmojiReact);\n assert.deepStrictEqual(activity.name, \":custom:\");\n const tags = await Array.fromAsync(activity.getTags());\n assert.deepStrictEqual(tags.length, 1);\n assert.deepStrictEqual(tags[0], customEmoji);\n assert.deepStrictEqual(reaction.emoji, customEmoji);\n\n // Test unreact\n ctx.sentActivities = [];\n await reaction.unreact();\n assert.deepStrictEqual(ctx.sentActivities.length, 2);\n const { activity: urActivity } = ctx.sentActivities[0];\n assert.ok(urActivity instanceof Undo);\n const urObject = await urActivity.getObject();\n assert.ok(urObject instanceof EmojiReact);\n assert.deepStrictEqual(urObject.id, reaction.id);\n const urTags = await Array.fromAsync(urActivity.getTags());\n assert.deepStrictEqual(urTags.length, 1);\n assert.deepStrictEqual(urTags[0], customEmoji);\n });\n\n await t.test(\"react() with DeferredCustomEmoji\", async () => {\n ctx.sentActivities = [];\n const deferredEmoji: DeferredCustomEmoji<void> = (sessionParam) => {\n assert.deepStrictEqual(sessionParam, session); // Ensure correct session is passed\n return new CustomEmoji({\n id: new URL(\"https://example.com/emojis/deferred\"),\n name: \":deferred:\",\n icon: new Image({\n url: new URL(\"https://example.com/emojis/deferred.png\"),\n }),\n });\n };\n const reaction = await message.react(deferredEmoji);\n assert.deepStrictEqual(ctx.sentActivities.length, 2);\n const { activity } = ctx.sentActivities[0];\n assert.ok(activity instanceof EmojiReact);\n assert.deepStrictEqual(activity.name, \":deferred:\");\n const tags = await Array.fromAsync(activity.getTags());\n assert.deepStrictEqual(tags.length, 1);\n assert.ok(tags[0] instanceof CustomEmoji);\n assert.deepStrictEqual(\n tags[0].id?.href,\n \"https://example.com/emojis/deferred\",\n );\n assert.deepStrictEqual(reaction.emoji, tags[0]);\n\n // Test unreact\n ctx.sentActivities = [];\n await reaction.unreact();\n assert.deepStrictEqual(ctx.sentActivities.length, 2);\n const { activity: urActivity } = ctx.sentActivities[0];\n assert.ok(urActivity instanceof Undo);\n const urObject = await urActivity.getObject();\n assert.ok(urObject instanceof EmojiReact);\n assert.deepStrictEqual(urObject.id, reaction.id);\n const urTags = await Array.fromAsync(urActivity.getTags());\n assert.deepStrictEqual(urTags.length, 1);\n assert.deepStrictEqual(urTags[0], tags[0]); // Should be the resolved CustomEmoji\n });\n});\n"],"mappings":";;;;;;;;;;;;;;;;;AAmDA,KAAK,qBAAqB,MAAM;AAC9B,QAAO,GAAG,gBAAgB,IAAI,QAAQ,CAAE,GAAE,CAAC;AAC3C,QAAO,GAAG,gBAAgB,IAAI,YAAY,CAAE,GAAE,CAAC;AAC/C,QAAO,GAAG,gBAAgB,IAAI,KAAK,CAAE,GAAE,CAAC;AACxC,QAAO,GAAG,gBAAgB,IAAI,SAAS,CAAE,GAAE,CAAC;AAC5C,QAAO,IAAI,gBAAgB,IAAI,OAAO,CAAE,GAAE,CAAC;AAC5C,EAAC;AAEF,KAAK,qBAAqB,MAAM;AAC9B,QAAO,gBACL,gBAAgB,IAAI,QAAQ,CAAE,GAAE,EAChC,QACD;AACD,QAAO,gBACL,gBAAgB,IAAI,YAAY,CAAE,GAAE,EACpC,YACD;AACD,QAAO,gBACL,gBAAgB,IAAI,KAAK,CAAE,GAAE,EAC7B,KACD;AACD,QAAO,gBACL,gBAAgB,IAAI,SAAS,CAAE,GAAE,EACjC,SACD;AACF,EAAC;AAEF,KAAK,mBAAmB,YAAY;CAClC,MAAM,MAAM,IAAI,QAAc;EAAE,IAAI,IAAI;EAAiB,UAAU;CAAO;CAC1E,MAAM,UAAU,IAAI,WAAW,8BAAiC;AAChE,OAAM,OAAO,QACX,MAAM,cAA0B,IAAI,KAAK,CAAE,IAAG,SAAS,CAAE,EAAC,EAC1D,WACA,0BACD;AACD,OAAM,OAAO,QACX,MACE,cACE,IAAI,KAAK,EAAE,IAAI,IAAI,IAAI,+BAAgC,IACvD,SACA,CAAE,EACH,EACH,WACA,+BACD;AACD,OAAM,OAAO,QACX,MACE,cACE,IAAI,KAAK;EACP,IAAI,IAAI,IAAI;EACZ,SAAS;CACV,IACD,SACA,CAAE,EACH,EACH,WACA,qCACD;CAED,MAAM,aAAa,IAAI,KAAK;EAC1B,IAAI,IAAI,IAAI;EACZ,SAAS;EACT,aAAa,IAAI,IAAI;EACrB,IAAI;EACJ,IAAI,IAAI,IAAI;EACZ,MAAM,CACJ,IAAI,QAAQ;GACV,MAAM;GACN,MAAM,IAAI,IAAI;EACf,IACD,IAAI,QAAQ;GACV,MAAM;GACN,MAAM,IAAI,IAAI;EACf,EACF;CACF;CACD,MAAM,gBAAgB,MAAM,cAC1B,YACA,SACA,CAAE,EACH;AACD,QAAO,gBAAgB,cAAc,KAAK,WAAW;AACrD,QAAO,gBAAgB,cAAc,IAAI,WAAW,GAAG;AACvD,QAAO,gBAAgB,cAAc,OAAO,MAAM,QAAQ,UAAU,CAAC;AACrE,QAAO,gBAAgB,cAAc,YAAY,SAAS;AAC1D,QAAO,gBAAgB,cAAc,iBAAoB;AACzD,QAAO,gBAAgB,cAAc,MAAM,iBAAiB;AAC5D,QAAO,gBAAgB,cAAc,MAAM,iCAAiC;AAC5E,QAAO,gBAAgB,cAAc,oBAAuB;AAC5D,QAAO,gBAAgB,cAAc,UAAU,CAAC,MAAM,QAAQ,UAAU,AAAC,EAAC;AAC1E,QAAO,gBAAgB,cAAc,UAAU,CAC7C,IAAI,QAAQ;EACV,MAAM;EACN,MAAM,IAAI,IAAI;CACf,EACF,EAAC;AACF,QAAO,gBAAgB,cAAc,aAAa,CAAE,EAAC;AACrD,QAAO,gBAAgB,cAAc,kBAAqB;AAC1D,QAAO,gBAAgB,cAAc,gBAAmB;CAExD,MAAM,eAAe,WAAW,MAAM;EACpC,IAAI,IAAI,IAAI;EACZ,IAAI;CACL,EAAC;CACF,MAAM,kBAAkB,MAAM,cAC5B,cACA,SACA,CAAE,EACH;AACD,QAAO,gBAAgB,gBAAgB,YAAY,WAAW;CAE9D,MAAM,gBAAgB,WAAW,MAAM;EACrC,IAAI,IAAI,IAAI;EACZ,KAAK,CAAE;CACR,EAAC;CACF,MAAM,mBAAmB,MAAM,cAC7B,eACA,SACA,CAAE,EACH;AACD,QAAO,gBAAgB,iBAAiB,YAAY,YAAY;CAEhE,MAAM,SAAS,WAAW,MAAM;EAC9B,IAAI,IAAI,IAAI;EACZ,KAAK,CAAE;CACR,EAAC;CACF,MAAM,gBAAgB,MAAM,cAA0B,QAAQ,SAAS,CAAE,EAAC;AAC1E,QAAO,gBAAgB,cAAc,YAAY,SAAS;CAE1D,MAAM,UAAU,WAAW,MAAM;EAC/B,KAAK,CAAE;EACP,KAAK,CAAE;CACR,EAAC;CACF,MAAM,iBAAiB,MAAM,cAA0B,SAAS,SAAS,CAAE,EAAC;AAC5E,QAAO,gBAAgB,eAAe,YAAY,UAAU;AAC7D,EAAC;AAEF,KAAK,kCAAkC,YAAY;CACjD,MAAM,aAAa,IAAI;CACvB,MAAM,MAAM,IAAI,QAAc;EAC5B,IAAI,IAAI;EACR;EACA,UAAU;CACX;CACD,MAAM,MAAM,kBAAkB,KAAK,sBAAsB;CACzD,MAAM,UAAU,IAAI,YAAY,KAAK;CACrC,MAAM,OAAO,IAAI,KAAK;EACpB,IAAI,IAAI,IACN;EAEF,SAAS;EACT,aAAa,IAAI,IAAI;EACrB,IAAI;EACJ,IAAI,IAAI,IAAI;CACb;CACD,MAAM,MAAM,MAAM,cAChB,MACA,SACA,CAAE,mBAGF,KACD;AACD,OAAM,WAAW,WACf,wCACA,IAAI,OAAO;EACT,IAAI,IAAI,IACN;EAEF,OAAO,IAAI,IAAI;EACf,IAAI;EACJ,IAAI,IAAI,IAAI;EACZ,QAAQ;CACT,GACF;AACD,OAAM,IAAI,QAAQ;AAClB,QAAO,gBAAgB,MAAM,WAAW,eAAe,EAAE,EAAE;AAC3D,QAAO,gBAAgB,IAAI,eAAe,QAAQ,EAAE;CACpD,MAAM,EAAE,YAAY,UAAU,GAAG,IAAI,eAAe;AACpD,QAAO,gBAAgB,YAAY,YAAY;AAC/C,QAAO,GAAG,oBAAoB,OAAO;AACrC,QAAO,gBAAgB,SAAS,SAAS,IAAI,YAAY,IAAI,WAAW,CAAC;AACzE,QAAO,gBAAgB,SAAS,OAAO,CAAC,iBAAkB,EAAC;AAC3D,QAAO,gBAAgB,SAAS,OAAO,CAAC,IAAI,gBAAgB,IAAI,WAAW,AAAC,EAAC;CAC7E,MAAM,YAAY,MAAM,SAAS,WAAW;AAC5C,QAAO,GAAG,qBAAqB,UAAU;AACzC,QAAO,gBAAgB,UAAU,IAAI,KAAK,GAAG;AAC9C,EAAC;AAEF,KAAK,uBAAuB,YAAY;CACtC,MAAM,aAAa,IAAI;CACvB,MAAM,MAAM,IAAI,QAAc;EAC5B,IAAI,IAAI;EACR;EACA,UAAU;CACX;CACD,MAAM,MAAM,kBAAkB,KAAK,sBAAsB;CACzD,MAAM,UAAU,IAAI,YAAY,KAAK;CACrC,MAAM,eAAe,IAAI,KAAK;EAC5B,IAAI,IAAI,IACN;EAEF,SAAS;EACT,aAAa,IAAI,OAAO;GACtB,IAAI,IAAI,IAAI;GACZ,mBAAmB;EACpB;EACD,IAAI,IAAI,IAAI;EACZ,IAAI;CACL;CACD,MAAM,cAAc,MAAM,cACxB,cACA,SACA,CAAE,EACH;CACD,MAAM,QAAQ,MAAM,YAAY,MAAM,KAAK,cAAc;AACzD,QAAO,gBAAgB,MAAM,WAAW,eAAe,EAAE,EAAE;CAC3D,MAAM,CAAC,OAAO,GAAG,MAAM,MAAM,UAAU,WAAW,aAAa,CAAC;AAChE,QAAO,GAAG,UAAU,KAAK;AACzB,QAAO,gBAAgB,IAAI,eAAe,QAAQ,EAAE;CACpD,MAAM,EAAE,YAAY,UAAU,GAAG,IAAI,eAAe;AACpD,QAAO,gBAAgB,YAAY,YAAY;AAC/C,QAAO,GAAG,oBAAoB,OAAO;AACrC,QAAO,gBACL,MAAM,SAAS,SAAS,EAAE,QAAQ,UAAW,EAAC,EAC9C,MAAM,OAAO,SAAS,EAAE,QAAQ,UAAW,EAAC,CAC7C;CACD,MAAM,EAAE,YAAY,aAAa,UAAU,WAAW,GACpD,IAAI,eAAe;AACrB,QAAO,gBAAgB,aAAa,CAAC,YAAY,KAAM,EAAC;AACxD,QAAO,GAAG,qBAAqB,OAAO;AACtC,QAAO,gBACL,MAAM,UAAU,SAAS,EAAE,QAAQ,UAAW,EAAC,EAC/C,MAAM,OAAO,SAAS,EAAE,QAAQ,UAAW,EAAC,CAC7C;AACD,QAAO,gBACL,MAAM,MAAM,IAAI,SAAS,EAAE,QAAQ,UAAW,EAAC,EAC/C,MAAM,CAAC,MAAM,OAAO,WAAW,GAAG,SAAS,EAAE,QAAQ,UAAW,EAAC,CAClE;AACD,QAAO,gBAAgB,MAAM,OAAO,MAAM,QAAQ,UAAU,CAAC;AAC7D,QAAO,gBAAgB,MAAM,aAAa,YAAY;AACtD,QAAO,gBAAgB,MAAM,YAAY,WAAW;AACrD,EAAC;AAEF,KAAK,uBAAuB,OAAO,MAAM;CACvC,MAAM,aAAa,IAAI;CACvB,MAAM,MAAM,IAAI,QAAc;EAC5B,IAAI,IAAI;EACR;EACA,UAAU;CACX;CACD,MAAM,MAAM,kBAAkB,KAAK,sBAAsB;CACzD,MAAM,UAAU,IAAI,YAAY,KAAK;CACrC,MAAM,eAAe,IAAI,KAAK;EAC5B,IAAI,IAAI,IACN;EAEF,SAAS;EACT,aAAa,IAAI,OAAO;GACtB,IAAI,IAAI,IAAI;GACZ,mBAAmB;EACpB;EACD,IAAI,IAAI,IAAI;EACZ,IAAI;CACL;CACD,MAAM,cAAc,MAAM,cACxB,cACA,SACA,CAAE,EACH;CACD,MAAM,YAAY,MAAM,YAAY,OAAO;AAE3C,OAAM,EAAE,KAAK,WAAW,YAAY;AAClC,SAAO,gBAAgB,MAAM,WAAW,eAAe,EAAE,EAAE;EAC3D,MAAM,CAAC,SAAS,GAAG,MAAM,MAAM,UAAU,WAAW,aAAa,CAAC;AAClE,SAAO,GAAG,YAAY,KAAK;AAC3B,SAAO,gBAAgB,IAAI,eAAe,QAAQ,EAAE;EACpD,MAAM,EAAE,YAAY,UAAU,GAAG,IAAI,eAAe;AACpD,SAAO,gBAAgB,YAAY,YAAY;AAC/C,SAAO,GAAG,oBAAoB,SAAS;AACvC,SAAO,gBAAgB,SAAS,OAAO,CACrC,IAAI,gBAAgB,IAAI,WAAW,AACpC,EAAC;AACF,SAAO,gBAAgB,SAAS,OAAO,CACrC,mBACA,aAAa,aACd,EAAC;AACF,SAAO,gBACL,MAAM,SAAS,SAAS,EAAE,QAAQ,UAAW,EAAC,EAC9C,MAAM,SAAS,SAAS,EAAE,QAAQ,UAAW,EAAC,CAC/C;EACD,MAAM,EAAE,YAAY,aAAa,UAAU,WAAW,GACpD,IAAI,eAAe;AACrB,SAAO,gBAAgB,aAAa,CAAC,YAAY,KAAM,EAAC;AACxD,SAAO,GAAG,qBAAqB,SAAS;AACxC,SAAO,gBAAgB,UAAU,OAAO,CACtC,IAAI,gBAAgB,IAAI,WAAW,AACpC,EAAC;AACF,SAAO,gBAAgB,UAAU,OAAO,CACtC,mBACA,aAAa,aACd,EAAC;AACF,SAAO,gBACL,MAAM,UAAU,SAAS,EAAE,QAAQ,UAAW,EAAC,EAC/C,MAAM,SAAS,SAAS,EAAE,QAAQ,UAAW,EAAC,CAC/C;AACD,SAAO,gBACL,MAAM,UAAU,IAAI,SAAS,EAAE,QAAQ,UAAW,EAAC,EACnD,MAAM,SAAS,SAAS,EAAE,QAAQ,UAAW,EAAC,CAC/C;AACD,SAAO,gBAAgB,UAAU,OAAO,MAAM,QAAQ,UAAU,CAAC;AACjE,SAAO,gBAAgB,UAAU,YAAY,WAAW;AACxD,SAAO,gBAAgB,UAAU,UAAU,YAAY;CACxD,EAAC;AAEF,OAAM,EAAE,KAAK,aAAa,YAAY;AACpC,MAAI,iBAAiB,CAAE;AAEvB,QAAM,UAAU,SAAS;AACzB,SAAO,gBAAgB,MAAM,WAAW,eAAe,EAAE,EAAE;AAC3D,SAAO,gBAAgB,IAAI,eAAe,QAAQ,EAAE;EACpD,MAAM,EAAE,YAAY,UAAU,GAAG,IAAI,eAAe;AACpD,SAAO,gBAAgB,YAAY,YAAY;AAC/C,SAAO,GAAG,oBAAoB,KAAK;AACnC,SAAO,gBAAgB,SAAS,SAAS,IAAI,YAAY,IAAI,WAAW,CAAC;AACzE,SAAO,gBAAgB,SAAS,OAAO,CACrC,IAAI,gBAAgB,IAAI,WAAW,AACpC,EAAC;AACF,SAAO,gBAAgB,SAAS,OAAO,CACrC,mBACA,aAAa,aACd,EAAC;AACF,SAAO,gBAAgB,SAAS,UAAU,UAAU,GAAG;EACvD,MAAM,EAAE,YAAY,aAAa,UAAU,WAAW,GACpD,IAAI,eAAe;AACrB,SAAO,gBAAgB,aAAa,CAAC,YAAY,KAAM,EAAC;AACxD,SAAO,GAAG,qBAAqB,KAAK;AACpC,SAAO,gBAAgB,UAAU,SAAS,IAAI,YAAY,IAAI,WAAW,CAAC;AAC1E,SAAO,gBAAgB,UAAU,OAAO,CACtC,IAAI,gBAAgB,IAAI,WAAW,AACpC,EAAC;AACF,SAAO,gBAAgB,UAAU,OAAO,CACtC,mBACA,aAAa,aACd,EAAC;AACF,SAAO,gBAAgB,UAAU,UAAU,UAAU,GAAG;CACzD,EAAC;AACH,EAAC;AAEF,KAAK,sBAAsB,OAAO,MAAM;CACtC,MAAM,MAAM,IAAI,QAAc;EAC5B,IAAI,IAAI;EACR,UAAU;CACX;CACD,MAAM,MAAM,kBAAkB,KAAK,sBAAsB;CACzD,MAAM,UAAU,IAAI,YAAY,KAAK;CACrC,MAAM,eAAe,IAAI,KAAK;EAC5B,IAAI,IAAI,IACN;EAEF,SAAS;EACT,aAAa,IAAI,OAAO;GACtB,IAAI,IAAI,IAAI;GACZ,mBAAmB;EACpB;EACD,IAAI,IAAI,IAAI;EACZ,IAAI;CACL;CACD,MAAM,UAAU,MAAM,cACpB,cACA,SACA,CAAE,EACH;CACD,MAAM,OAAO,MAAM,QAAQ,MAAM;AAEjC,OAAM,EAAE,KAAK,UAAU,YAAY;AACjC,SAAO,gBAAgB,IAAI,eAAe,QAAQ,EAAE;EACpD,MAAM,EAAE,YAAY,UAAU,GAAG,IAAI,eAAe;AACpD,SAAO,gBAAgB,YAAY,YAAY;AAC/C,SAAO,GAAG,oBAAoBA,KAAQ;AACtC,SAAO,gBAAgB,SAAS,SAAS,IAAI,YAAY,IAAI,WAAW,CAAC;AACzE,SAAO,gBAAgB,SAAS,UAAU,QAAQ,GAAG;EACrD,MAAM,EAAE,YAAY,aAAa,UAAU,WAAW,GACpD,IAAI,eAAe;AACrB,SAAO,gBAAgB,aAAa,CAAC,QAAQ,KAAM,EAAC;AACpD,SAAO,GAAG,qBAAqBA,KAAQ;AACvC,SAAO,gBAAgB,WAAW,SAAS;AAC3C,SAAO,gBAAgB,KAAK,OAAO,MAAM,QAAQ,UAAU,CAAC;AAC5D,SAAO,gBAAgB,KAAK,KAAK,SAAS;AAC1C,SAAO,gBAAgB,KAAK,IAAI,SAAS,GAAG;AAC5C,SAAO,gBAAgB,KAAK,SAAS,QAAQ;CAC9C,EAAC;AAEF,OAAM,EAAE,KAAK,YAAY,YAAY;AACnC,MAAI,iBAAiB,CAAE;AAEvB,QAAM,KAAK,QAAQ;AACnB,SAAO,gBAAgB,IAAI,eAAe,QAAQ,EAAE;EACpD,MAAM,EAAE,YAAY,UAAU,GAAG,IAAI,eAAe;AACpD,SAAO,gBAAgB,YAAY,YAAY;AAC/C,SAAO,GAAG,oBAAoB,KAAK;AACnC,SAAO,gBAAgB,SAAS,SAAS,IAAI,YAAY,IAAI,WAAW,CAAC;EACzE,MAAM,SAAS,MAAM,SAAS,WAAW;AACzC,SAAO,GAAG,kBAAkBA,KAAQ;AACpC,SAAO,gBAAgB,OAAO,SAAS,IAAI,YAAY,IAAI,WAAW,CAAC;AACvE,SAAO,gBAAgB,OAAO,UAAU,QAAQ,GAAG;EACnD,MAAM,EAAE,YAAY,aAAa,UAAU,WAAW,GACpD,IAAI,eAAe;AACrB,SAAO,gBAAgB,aAAa,CAAC,QAAQ,KAAM,EAAC;AACpD,SAAO,GAAG,qBAAqB,KAAK;AACpC,SAAO,gBAAgB,WAAW,SAAS;CAC5C,EAAC;AACH,EAAC;AAEF,KAAK,8BAA8B,OAAO,MAAM;CAC9C,MAAM,SAAS,IAAI,OAAO;EACxB,IAAI,IAAI,IAAI;EACZ,mBAAmB;CACpB;CACD,MAAM,SAAS,IAAI,OAAO;EACxB,IAAI,IAAI,IAAI;EACZ,mBAAmB;CACpB;AAED,MACE,MAAM,cAAc;EAAC;EAAU;EAAY;EAAa;CAAS,GACjE;EACA,MAAM,aAAa,IAAI;EACvB,MAAM,MAAM,IAAI,QAAc;GAC5B,IAAI,IAAI;GACR;GACA,UAAU;EACX;EACD,MAAM,MAAM,kBAAkB,KAAK,sBAAsB;EACzD,MAAM,UAAU,IAAI,YAAY,KAAK;AAErC,QAAM,EAAE,KAAK,YAAY,YAAY;GACnC,MAAM,MAAM,MAAM,QAAQ,QAAQ,KAAK,SAAS,OAAO,GAAG,EAAE,WAAY,EAAC;AACzE,UAAO,gBAAgB,MAAM,WAAW,eAAe,EAAE,EAAE;GAC3D,MAAM,cAAc,IAAI;AACxB,OAAI,iBAAiB,CAAE;GACvB,MAAM,SAAS,SAAS,IAAI,SAAS;AACrC,SAAM,IAAI,OAAO,KAAK,SAAS,OAAO,EAAE;GACxC,MAAM,QAAQ,SAAS,IAAI,SAAS;AACpC,UAAO,gBAAgB,IAAI,MAAM,2BAA2B;AAC5D,UAAO,gBACL,IAAI,MACJ,mKAGD;AACD,UAAO,gBAAgB,IAAI,SAAS,QAAQ,EAAE;AAC9C,UAAO,gBAAgB,IAAI,SAAS,GAAG,IAAI,OAAO,GAAG;AACrD,UAAO,gBAAgB,IAAI,UAAU,CAAE,EAAC;AACxC,UAAO,GAAG,IAAI,WAAW,KAAK;AAC9B,UAAO,GAAG,IAAI,QAAQ,oBAAoB,OAAO,iBAAiB;AAClE,UAAO,GAAG,IAAI,QAAQ,oBAAoB,MAAM,iBAAiB;AACjE,UAAO,gBAAgB,IAAI,IAAI,SAAS,IAAI,KAAK;AACjD,OAAI,eAAe,UAAU;AAC3B,WAAO,gBAAgB,IAAI,IAAI,OAAO,CAAC,mBAAmB,OAAO,EAAG,EAAC;AACrE,WAAO,gBAAgB,IAAI,IAAI,OAAO,CACpC,IAAI,gBAAgB,IAAI,WAAW,AACpC,EAAC;GACH,WAAU,eAAe,YAAY;AACpC,WAAO,gBAAgB,IAAI,IAAI,OAAO,CACpC,IAAI,gBAAgB,IAAI,WAAW,EACnC,OAAO,EACR,EAAC;AACF,WAAO,gBAAgB,IAAI,IAAI,OAAO,CAAC,iBAAkB,EAAC;GAC3D,WAAU,eAAe,aAAa;AACrC,WAAO,gBAAgB,IAAI,IAAI,OAAO,CACpC,IAAI,gBAAgB,IAAI,WAAW,EACnC,OAAO,EACR,EAAC;AACF,WAAO,gBAAgB,IAAI,IAAI,OAAO,CAAE,EAAC;GAC1C,OAAM;AACL,WAAO,gBAAgB,IAAI,IAAI,OAAO,CAAC,OAAO,EAAG,EAAC;AAClD,WAAO,gBAAgB,IAAI,IAAI,OAAO,CAAE,EAAC;GAC1C;GACD,MAAM,OAAO,MAAM,MAAM,UAAU,IAAI,IAAI,SAAS,CAAC;AACrD,UAAO,gBAAgB,KAAK,QAAQ,EAAE;AACtC,UAAO,GAAG,KAAK,cAAc,QAAQ;AACrC,UAAO,gBAAgB,KAAK,GAAG,MAAM,oBAAoB;AACzD,UAAO,gBAAgB,KAAK,GAAG,MAAM,OAAO,GAAG;AAC/C,UAAO,gBAAgB,IAAI,IAAI,WAAW,YAAY,UAAU;AAChE,UAAO,gBAAgB,IAAI,IAAI,SAAS,IAAI,QAAQ;GACpD,MAAM,CAAC,OAAO,GAAG,MAAM,MAAM,UAAU,WAAW,aAAa,CAAC;AAChE,UAAO,gBACL,MAAM,CAAC,MAAM,OAAO,WAAW,GAAG,SAAS,EAAE,QAAQ,UAAW,EAAC,EACjE,MAAM,IAAI,IAAI,SAAS,EAAE,QAAQ,UAAW,EAAC,CAC9C;AACD,UAAO,gBACL,IAAI,eAAe,QACnB,eAAe,WAAW,IAAI,EAC/B;GACD,MAAM,EAAE,YAAY,UAAU,GAAG,IAAI,eAAe;AACpD,UAAO,gBACL,YACA,eAAe,WAAW,CAAC,QAAQ,MAAO,IAAG,YAC9C;AACD,UAAO,GAAG,oBAAoB,OAAO;AACrC,UAAO,gBAAgB,SAAS,SAAS,IAAI,YAAY,IAAI,WAAW,CAAC;AACzE,OAAI,eAAe,UAAU;AAC3B,WAAO,gBAAgB,SAAS,OAAO;KACrC;KACA,OAAO;KACP,OAAO;IACR,EAAC;AACF,WAAO,gBAAgB,SAAS,OAAO,CACrC,IAAI,gBAAgB,IAAI,WAAW,AACpC,EAAC;GACH,WAAU,eAAe,YAAY;AACpC,WAAO,gBAAgB,SAAS,OAAO;KACrC,IAAI,gBAAgB,IAAI,WAAW;KACnC,OAAO;KACP,OAAO;IACR,EAAC;AACF,WAAO,gBAAgB,SAAS,OAAO,CAAC,iBAAkB,EAAC;GAC5D,WAAU,eAAe,aAAa;AACrC,WAAO,gBAAgB,SAAS,OAAO;KACrC,IAAI,gBAAgB,IAAI,WAAW;KACnC,OAAO;KACP,OAAO;IACR,EAAC;AACF,WAAO,gBAAgB,SAAS,OAAO,CAAE,EAAC;GAC3C,OAAM;AACL,WAAO,gBAAgB,SAAS,OAAO,CAAC,OAAO,IAAI,OAAO,EAAG,EAAC;AAC9D,WAAO,gBAAgB,SAAS,OAAO,CAAE,EAAC;GAC3C;AACD,UAAO,gBAAgB,MAAM,SAAS,WAAW,EAAE,IAAI,IAAI;AAC3D,UAAO,gBAAgB,SAAS,SAAS,IAAI,QAAQ;AACrD,OAAI,eAAe,UAAU;IAC3B,MAAM,EAAE,0BAAY,sBAAU,GAAG,IAAI,eAAe;AACpD,WAAO,gBAAgBC,cAAY,CAAC,QAAQ,MAAO,EAAC;AACpD,WAAO,GAAGC,sBAAoB,OAAO;AACrC,WAAO,gBACLA,WAAS,SACT,IAAI,YAAY,IAAI,WAAW,CAChC;AACD,WAAO,gBAAgB,MAAM,WAAS,WAAW,EAAE,IAAI,IAAI;AAC3D,WAAO,gBAAgBA,WAAS,SAAS,IAAI,QAAQ;GACtD;EACF,EAAC;CACH;AACF,EAAC;AAEF,KAAK,0BAA0B,MAAM;AACnC,QAAO,gBACL,qBAAqB,CAAC,iBAAkB,GAAE,CAAE,GAAE,IAAI,OAAO,CAAE,GAAE,EAC7D,SACD;AACD,QAAO,gBACL,qBAAqB,CAAE,GAAE,CAAC,iBAAkB,GAAE,IAAI,OAAO,CAAE,GAAE,EAC7D,WACD;AACD,QAAO,gBACL,qBACE,CAAE,GACF,CAAC,IAAI,IAAI,gCAAiC,GAC1C,IAAI,OAAO,EACT,WAAW,IAAI,IAAI,iCACpB,GACF,EACD,YACD;AACD,QAAO,gBACL,qBACE,CAAC,IAAI,IAAI,gCAAiC,GAC1C,CAAE,GACF,IAAI,OAAO,EACT,WAAW,IAAI,IAAI,iCACpB,GACF,EACD,YACD;AACD,QAAO,gBACL,qBACE,CAAC,IAAI,IAAI,4BAA6B,GACtC,CAAE,GACF,IAAI,OAAO,CAAE,IACb,IAAI,IAAI,CAAC,2BAA4B,GACtC,EACD,SACD;AACD,QAAO,gBACL,qBAAqB,CAAE,GAAE,CAAE,GAAE,IAAI,OAAO,CAAE,GAAE,EAC5C,UACD;AACF,EAAC;AAEF,KAAK,uBAAuB,OAAO,MAAM;CACvC,MAAM,MAAM,IAAI,QAAc;EAC5B,IAAI,IAAI;EACR,UAAU;CACX;CACD,MAAM,MAAM,kBAAkB,KAAK,sBAAsB;CACzD,MAAM,UAAU,IAAI,YAAY,KAAK;CACrC,MAAM,eAAe,IAAI,KAAK;EAC5B,IAAI,IAAI,IACN;EAEF,SAAS;EACT,aAAa,IAAI,OAAO;GACtB,IAAI,IAAI,IAAI;GACZ,mBAAmB;EACpB;EACD,IAAI;CACL;CACD,MAAM,UAAU,MAAM,cACpB,cACA,SACA,CAAE,EACH;AAED,OAAM,EAAE,KAAK,6BAA6B,YAAY;AACpD,MAAI,iBAAiB,CAAE;EACvB,MAAM,WAAW,MAAM,QAAQ,MAAM,MAAM,IAAI;AAC/C,SAAO,gBAAgB,IAAI,eAAe,QAAQ,EAAE;EACpD,MAAM,EAAE,YAAY,UAAU,GAAG,IAAI,eAAe;AACpD,SAAO,gBAAgB,YAAY,YAAY;AAC/C,SAAO,GAAG,oBAAoB,WAAW;AACzC,SAAO,gBAAgB,SAAS,SAAS,IAAI,YAAY,IAAI,WAAW,CAAC;AACzE,SAAO,gBAAgB,SAAS,UAAU,QAAQ,GAAG;AACrD,SAAO,gBAAgB,SAAS,MAAM,KAAK;AAC3C,SAAO,gBAAgB,MAAM,MAAM,UAAU,SAAS,SAAS,CAAC,EAAE,CAAE,EAAC;EACrE,MAAM,EAAE,YAAY,aAAa,UAAU,WAAW,GACpD,IAAI,eAAe;AACrB,SAAO,gBAAgB,aAAa,CAAC,QAAQ,KAAM,EAAC;AACpD,SAAO,GAAG,qBAAqB,WAAW;AAC1C,SAAO,gBAAgB,WAAW,SAAS;AAC3C,SAAO,gBAAgB,SAAS,OAAO,MAAM,QAAQ,UAAU,CAAC;AAChE,SAAO,gBAAgB,SAAS,KAAK,SAAS;AAC9C,SAAO,gBAAgB,SAAS,IAAI,SAAS,GAAG;AAChD,SAAO,gBAAgB,SAAS,SAAS,QAAQ;AACjD,SAAO,gBAAgB,SAAS,OAAO,MAAM,IAAI;AAGjD,MAAI,iBAAiB,CAAE;AACvB,QAAM,SAAS,SAAS;AACxB,SAAO,gBAAgB,IAAI,eAAe,QAAQ,EAAE;EACpD,MAAM,EAAE,YAAY,cAAc,UAAU,YAAY,GACtD,IAAI,eAAe;AACrB,SAAO,gBAAgB,cAAc,YAAY;AACjD,SAAO,GAAG,sBAAsB,KAAK;AACrC,SAAO,gBAAgB,WAAW,SAAS,IAAI,YAAY,IAAI,WAAW,CAAC;EAC3E,MAAM,WAAW,MAAM,WAAW,WAAW;AAC7C,SAAO,GAAG,oBAAoB,WAAW;AACzC,SAAO,gBAAgB,SAAS,IAAI,SAAS,GAAG;EAChD,MAAM,EAAE,YAAY,eAAe,UAAU,aAAa,GACxD,IAAI,eAAe;AACrB,SAAO,gBAAgB,eAAe,CAAC,QAAQ,KAAM,EAAC;AACtD,SAAO,GAAG,uBAAuB,KAAK;AACtC,SAAO,gBAAgB,aAAa,WAAW;CAChD,EAAC;AAEF,OAAM,EAAE,KAAK,4BAA4B,YAAY;AACnD,MAAI,iBAAiB,CAAE;EACvB,MAAM,cAAc,IAAIC,MAAY;GAClC,IAAI,IAAI,IAAI;GACZ,MAAM;GACN,MAAM,IAAI,MAAM,EACd,KAAK,IAAI,IAAI,yCACd;EACF;EACD,MAAM,WAAW,MAAM,QAAQ,MAAM,YAAY;AACjD,SAAO,gBAAgB,IAAI,eAAe,QAAQ,EAAE;EACpD,MAAM,EAAE,UAAU,GAAG,IAAI,eAAe;AACxC,SAAO,GAAG,oBAAoB,WAAW;AACzC,SAAO,gBAAgB,SAAS,MAAM,WAAW;EACjD,MAAM,OAAO,MAAM,MAAM,UAAU,SAAS,SAAS,CAAC;AACtD,SAAO,gBAAgB,KAAK,QAAQ,EAAE;AACtC,SAAO,gBAAgB,KAAK,IAAI,YAAY;AAC5C,SAAO,gBAAgB,SAAS,OAAO,YAAY;AAGnD,MAAI,iBAAiB,CAAE;AACvB,QAAM,SAAS,SAAS;AACxB,SAAO,gBAAgB,IAAI,eAAe,QAAQ,EAAE;EACpD,MAAM,EAAE,UAAU,YAAY,GAAG,IAAI,eAAe;AACpD,SAAO,GAAG,sBAAsB,KAAK;EACrC,MAAM,WAAW,MAAM,WAAW,WAAW;AAC7C,SAAO,GAAG,oBAAoB,WAAW;AACzC,SAAO,gBAAgB,SAAS,IAAI,SAAS,GAAG;EAChD,MAAM,SAAS,MAAM,MAAM,UAAU,WAAW,SAAS,CAAC;AAC1D,SAAO,gBAAgB,OAAO,QAAQ,EAAE;AACxC,SAAO,gBAAgB,OAAO,IAAI,YAAY;CAC/C,EAAC;AAEF,OAAM,EAAE,KAAK,oCAAoC,YAAY;AAC3D,MAAI,iBAAiB,CAAE;EACvB,MAAMC,gBAA2C,CAAC,iBAAiB;AACjE,UAAO,gBAAgB,cAAc,QAAQ;AAC7C,UAAO,IAAID,MAAY;IACrB,IAAI,IAAI,IAAI;IACZ,MAAM;IACN,MAAM,IAAI,MAAM,EACd,KAAK,IAAI,IAAI,2CACd;GACF;EACF;EACD,MAAM,WAAW,MAAM,QAAQ,MAAM,cAAc;AACnD,SAAO,gBAAgB,IAAI,eAAe,QAAQ,EAAE;EACpD,MAAM,EAAE,UAAU,GAAG,IAAI,eAAe;AACxC,SAAO,GAAG,oBAAoB,WAAW;AACzC,SAAO,gBAAgB,SAAS,MAAM,aAAa;EACnD,MAAM,OAAO,MAAM,MAAM,UAAU,SAAS,SAAS,CAAC;AACtD,SAAO,gBAAgB,KAAK,QAAQ,EAAE;AACtC,SAAO,GAAG,KAAK,cAAcA,MAAY;AACzC,SAAO,gBACL,KAAK,GAAG,IAAI,MACZ,sCACD;AACD,SAAO,gBAAgB,SAAS,OAAO,KAAK,GAAG;AAG/C,MAAI,iBAAiB,CAAE;AACvB,QAAM,SAAS,SAAS;AACxB,SAAO,gBAAgB,IAAI,eAAe,QAAQ,EAAE;EACpD,MAAM,EAAE,UAAU,YAAY,GAAG,IAAI,eAAe;AACpD,SAAO,GAAG,sBAAsB,KAAK;EACrC,MAAM,WAAW,MAAM,WAAW,WAAW;AAC7C,SAAO,GAAG,oBAAoB,WAAW;AACzC,SAAO,gBAAgB,SAAS,IAAI,SAAS,GAAG;EAChD,MAAM,SAAS,MAAM,MAAM,UAAU,WAAW,SAAS,CAAC;AAC1D,SAAO,gBAAgB,OAAO,QAAQ,EAAE;AACxC,SAAO,gBAAgB,OAAO,IAAI,KAAK,GAAG;CAC3C,EAAC;AACH,EAAC"}
|