@atproto/dev-env 0.0.0-spaces-alpha-20260818163953

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.
Files changed (187) hide show
  1. package/CHANGELOG.md +3424 -0
  2. package/LICENSE.txt +7 -0
  3. package/README.md +39 -0
  4. package/bin.js +7 -0
  5. package/dist/bin-multi-pds.d.ts +2 -0
  6. package/dist/bin-multi-pds.d.ts.map +1 -0
  7. package/dist/bin-multi-pds.js +130 -0
  8. package/dist/bin-multi-pds.js.map +1 -0
  9. package/dist/bin.d.ts +2 -0
  10. package/dist/bin.d.ts.map +1 -0
  11. package/dist/bin.js +56 -0
  12. package/dist/bin.js.map +1 -0
  13. package/dist/bsky.d.ts +27 -0
  14. package/dist/bsky.d.ts.map +1 -0
  15. package/dist/bsky.js +165 -0
  16. package/dist/bsky.js.map +1 -0
  17. package/dist/bsync.d.ts +22 -0
  18. package/dist/bsync.d.ts.map +1 -0
  19. package/dist/bsync.js +54 -0
  20. package/dist/bsync.js.map +1 -0
  21. package/dist/const.d.ts +4 -0
  22. package/dist/const.d.ts.map +1 -0
  23. package/dist/const.js +4 -0
  24. package/dist/const.js.map +1 -0
  25. package/dist/env.d.ts +2 -0
  26. package/dist/env.d.ts.map +1 -0
  27. package/dist/env.js +10 -0
  28. package/dist/env.js.map +1 -0
  29. package/dist/feed-gen.d.ts +15 -0
  30. package/dist/feed-gen.d.ts.map +1 -0
  31. package/dist/feed-gen.js +73 -0
  32. package/dist/feed-gen.js.map +1 -0
  33. package/dist/index.d.ts +17 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +17 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/introspect.d.ts +22 -0
  38. package/dist/introspect.d.ts.map +1 -0
  39. package/dist/introspect.js +65 -0
  40. package/dist/introspect.js.map +1 -0
  41. package/dist/mock/data.d.ts +3 -0
  42. package/dist/mock/data.d.ts.map +1 -0
  43. package/dist/mock/data.js +46 -0
  44. package/dist/mock/data.js.map +1 -0
  45. package/dist/mock/img/blur-hash-avatar-b64.d.ts +3 -0
  46. package/dist/mock/img/blur-hash-avatar-b64.d.ts.map +1 -0
  47. package/dist/mock/img/blur-hash-avatar-b64.js +2 -0
  48. package/dist/mock/img/blur-hash-avatar-b64.js.map +1 -0
  49. package/dist/mock/img/labeled-img-b64.d.ts +3 -0
  50. package/dist/mock/img/labeled-img-b64.d.ts.map +1 -0
  51. package/dist/mock/img/labeled-img-b64.js +2 -0
  52. package/dist/mock/img/labeled-img-b64.js.map +1 -0
  53. package/dist/mock/index.d.ts +3 -0
  54. package/dist/mock/index.d.ts.map +1 -0
  55. package/dist/mock/index.js +574 -0
  56. package/dist/mock/index.js.map +1 -0
  57. package/dist/moderator-client.d.ts +58 -0
  58. package/dist/moderator-client.d.ts.map +1 -0
  59. package/dist/moderator-client.js +110 -0
  60. package/dist/moderator-client.js.map +1 -0
  61. package/dist/network-no-appview.d.ts +21 -0
  62. package/dist/network-no-appview.d.ts.map +1 -0
  63. package/dist/network-no-appview.js +74 -0
  64. package/dist/network-no-appview.js.map +1 -0
  65. package/dist/network.d.ts +32 -0
  66. package/dist/network.d.ts.map +1 -0
  67. package/dist/network.js +190 -0
  68. package/dist/network.js.map +1 -0
  69. package/dist/ozone.d.ts +31 -0
  70. package/dist/ozone.d.ts.map +1 -0
  71. package/dist/ozone.js +254 -0
  72. package/dist/ozone.js.map +1 -0
  73. package/dist/pds.d.ts +23 -0
  74. package/dist/pds.d.ts.map +1 -0
  75. package/dist/pds.js +97 -0
  76. package/dist/pds.js.map +1 -0
  77. package/dist/plc.d.ts +14 -0
  78. package/dist/plc.d.ts.map +1 -0
  79. package/dist/plc.js +28 -0
  80. package/dist/plc.js.map +1 -0
  81. package/dist/seed/author-feed.d.ts +4 -0
  82. package/dist/seed/author-feed.d.ts.map +1 -0
  83. package/dist/seed/author-feed.js +50 -0
  84. package/dist/seed/author-feed.js.map +1 -0
  85. package/dist/seed/basic.d.ts +16 -0
  86. package/dist/seed/basic.d.ts.map +1 -0
  87. package/dist/seed/basic.js +113 -0
  88. package/dist/seed/basic.js.map +1 -0
  89. package/dist/seed/client.d.ts +151 -0
  90. package/dist/seed/client.d.ts.map +1 -0
  91. package/dist/seed/client.js +365 -0
  92. package/dist/seed/client.js.map +1 -0
  93. package/dist/seed/follows.d.ts +4 -0
  94. package/dist/seed/follows.d.ts.map +1 -0
  95. package/dist/seed/follows.js +55 -0
  96. package/dist/seed/follows.js.map +1 -0
  97. package/dist/seed/index.d.ts +11 -0
  98. package/dist/seed/index.d.ts.map +1 -0
  99. package/dist/seed/index.js +11 -0
  100. package/dist/seed/index.js.map +1 -0
  101. package/dist/seed/likes.d.ts +4 -0
  102. package/dist/seed/likes.d.ts.map +1 -0
  103. package/dist/seed/likes.js +37 -0
  104. package/dist/seed/likes.js.map +1 -0
  105. package/dist/seed/quotes.d.ts +4 -0
  106. package/dist/seed/quotes.d.ts.map +1 -0
  107. package/dist/seed/quotes.js +21 -0
  108. package/dist/seed/quotes.js.map +1 -0
  109. package/dist/seed/reposts.d.ts +4 -0
  110. package/dist/seed/reposts.d.ts.map +1 -0
  111. package/dist/seed/reposts.js +17 -0
  112. package/dist/seed/reposts.js.map +1 -0
  113. package/dist/seed/thread-v2.d.ts +227 -0
  114. package/dist/seed/thread-v2.d.ts.map +1 -0
  115. package/dist/seed/thread-v2.js +755 -0
  116. package/dist/seed/thread-v2.js.map +1 -0
  117. package/dist/seed/users-bulk.d.ts +3 -0
  118. package/dist/seed/users-bulk.d.ts.map +1 -0
  119. package/dist/seed/users-bulk.js +224 -0
  120. package/dist/seed/users-bulk.js.map +1 -0
  121. package/dist/seed/users.d.ts +3 -0
  122. package/dist/seed/users.d.ts.map +1 -0
  123. package/dist/seed/users.js +45 -0
  124. package/dist/seed/users.js.map +1 -0
  125. package/dist/seed/verifications.d.ts +5 -0
  126. package/dist/seed/verifications.d.ts.map +1 -0
  127. package/dist/seed/verifications.js +164 -0
  128. package/dist/seed/verifications.js.map +1 -0
  129. package/dist/service-profile-lexicon.d.ts +11 -0
  130. package/dist/service-profile-lexicon.d.ts.map +1 -0
  131. package/dist/service-profile-lexicon.js +115 -0
  132. package/dist/service-profile-lexicon.js.map +1 -0
  133. package/dist/service-profile-ozone.d.ts +18 -0
  134. package/dist/service-profile-ozone.d.ts.map +1 -0
  135. package/dist/service-profile-ozone.js +333 -0
  136. package/dist/service-profile-ozone.js.map +1 -0
  137. package/dist/service-profile.d.ts +24 -0
  138. package/dist/service-profile.d.ts.map +1 -0
  139. package/dist/service-profile.js +61 -0
  140. package/dist/service-profile.js.map +1 -0
  141. package/dist/types.d.ts +61 -0
  142. package/dist/types.d.ts.map +1 -0
  143. package/dist/types.js +2 -0
  144. package/dist/types.js.map +1 -0
  145. package/dist/util.d.ts +14 -0
  146. package/dist/util.d.ts.map +1 -0
  147. package/dist/util.js +86 -0
  148. package/dist/util.js.map +1 -0
  149. package/package.json +69 -0
  150. package/src/bin-multi-pds.ts +166 -0
  151. package/src/bin.ts +64 -0
  152. package/src/bsky.ts +198 -0
  153. package/src/bsync.ts +66 -0
  154. package/src/const.ts +3 -0
  155. package/src/env.ts +9 -0
  156. package/src/feed-gen.ts +96 -0
  157. package/src/index.ts +17 -0
  158. package/src/introspect.ts +91 -0
  159. package/src/mock/data.ts +46 -0
  160. package/src/mock/img/blur-hash-avatar-b64.ts +1 -0
  161. package/src/mock/img/labeled-img-b64.ts +1 -0
  162. package/src/mock/index.ts +702 -0
  163. package/src/moderator-client.ts +267 -0
  164. package/src/network-no-appview.ts +89 -0
  165. package/src/network.ts +243 -0
  166. package/src/ozone.ts +287 -0
  167. package/src/pds.ts +118 -0
  168. package/src/plc.ts +33 -0
  169. package/src/seed/author-feed.ts +98 -0
  170. package/src/seed/basic.ts +189 -0
  171. package/src/seed/client.ts +676 -0
  172. package/src/seed/follows.ts +57 -0
  173. package/src/seed/index.ts +11 -0
  174. package/src/seed/likes.ts +43 -0
  175. package/src/seed/quotes.ts +53 -0
  176. package/src/seed/reposts.ts +18 -0
  177. package/src/seed/thread-v2.ts +925 -0
  178. package/src/seed/users-bulk.ts +229 -0
  179. package/src/seed/users.ts +64 -0
  180. package/src/seed/verifications.ts +254 -0
  181. package/src/service-profile-lexicon.ts +127 -0
  182. package/src/service-profile-ozone.ts +375 -0
  183. package/src/service-profile.ts +95 -0
  184. package/src/types.ts +68 -0
  185. package/src/util.ts +118 -0
  186. package/tsconfig.build.json +25 -0
  187. package/tsconfig.json +4 -0
@@ -0,0 +1,574 @@
1
+ import { COM_ATPROTO_MODERATION, ToolsOzoneQueueCreateQueue, } from '@atproto/api';
2
+ import { AtUri } from '@atproto/syntax';
3
+ import { EXAMPLE_LABELER, RecordRef } from '../index.js';
4
+ import { postTexts, replyTexts } from './data.js';
5
+ import blurHashB64 from './img/blur-hash-avatar-b64.js';
6
+ import labeledImgB64 from './img/labeled-img-b64.js';
7
+ // NOTE
8
+ // deterministic date generator
9
+ // we use this to ensure the mock dataset is always the same
10
+ // which is very useful when testing
11
+ // (not everything is currently deterministic but it could be)
12
+ function* dateGen() {
13
+ let start = 1657846031914;
14
+ while (true) {
15
+ yield new Date(start).toISOString();
16
+ start += 1e3;
17
+ }
18
+ }
19
+ export async function generateMockSetup(env) {
20
+ const date = dateGen();
21
+ const rand = (n) => Math.floor(Math.random() * n);
22
+ const picka = (arr) => {
23
+ if (arr.length) {
24
+ return arr[rand(arr.length)] || arr[0];
25
+ }
26
+ throw new Error('Not found');
27
+ };
28
+ const users = [
29
+ {
30
+ email: 'alice@test.com',
31
+ handle: `alice.test`,
32
+ password: 'hunter2',
33
+ displayName: 'Alice',
34
+ description: 'Test user 0',
35
+ },
36
+ {
37
+ email: 'bob@test.com',
38
+ handle: `bob.test`,
39
+ password: 'hunter2',
40
+ displayName: 'Bob',
41
+ description: 'Test user 1',
42
+ },
43
+ {
44
+ email: 'carla@test.com',
45
+ handle: `carla.test`,
46
+ password: 'hunter2',
47
+ displayName: 'Carla',
48
+ description: 'Test user 2',
49
+ },
50
+ {
51
+ email: 'triage@test.com',
52
+ handle: 'triage.test',
53
+ password: 'triage-pass',
54
+ },
55
+ {
56
+ email: 'mod@test.com',
57
+ handle: 'mod.test',
58
+ password: 'mod-pass',
59
+ },
60
+ {
61
+ email: 'admin-mod@test.com',
62
+ handle: 'admin-mod.test',
63
+ password: 'admin-mod-pass',
64
+ },
65
+ {
66
+ email: 'labeler@test.com',
67
+ handle: 'labeler.test',
68
+ password: 'hunter2',
69
+ displayName: 'Test Labeler',
70
+ description: 'Labeling things across the atmosphere',
71
+ },
72
+ ];
73
+ const userAgents = await Promise.all(users.map(async (user) => {
74
+ const agent = env.pds.getAgent();
75
+ await agent.createAccount(user);
76
+ agent.assertAuthenticated();
77
+ if (user.displayName || user.description) {
78
+ await agent.app.bsky.actor.profile.create({ repo: agent.did }, {
79
+ displayName: user.displayName,
80
+ description: user.description,
81
+ });
82
+ }
83
+ return agent;
84
+ }));
85
+ const [alice, bob, carla, triage, mod, adminMod, labeler] = userAgents;
86
+ // Create chat declarations for all users
87
+ for (const user of userAgents) {
88
+ await user.chat.bsky.actor.declaration.create({ repo: user.did }, { allowIncoming: 'all' });
89
+ }
90
+ // Add moderator roles
91
+ await env.ozone.addTriageDid(triage.did);
92
+ await env.ozone.addModeratorDid(mod.did);
93
+ await env.ozone.addAdminDid(adminMod.did);
94
+ // Create report queues
95
+ const ozoneAgent = env.ozone.getAgent();
96
+ const adminHeaders = async (nsid) => env.ozone.modHeaders(nsid, 'admin');
97
+ const createQueue = async (input) => {
98
+ try {
99
+ await ozoneAgent.tools.ozone.queue.createQueue(input, {
100
+ encoding: 'application/json',
101
+ headers: await adminHeaders('tools.ozone.queue.createQueue'),
102
+ });
103
+ }
104
+ catch (err) {
105
+ if (!(err instanceof ToolsOzoneQueueCreateQueue.ConflictingQueueError)) {
106
+ throw err;
107
+ }
108
+ }
109
+ };
110
+ await Promise.all([
111
+ createQueue({
112
+ name: 'Spammy Accounts',
113
+ subjectTypes: ['account'],
114
+ reportTypes: [COM_ATPROTO_MODERATION.DefsReasonSpam],
115
+ }),
116
+ createQueue({
117
+ name: 'Threatening Accounts',
118
+ subjectTypes: ['account'],
119
+ reportTypes: ['tools.ozone.report.defs#reasonViolenceThreats'],
120
+ }),
121
+ createQueue({
122
+ name: 'Spammy Posts',
123
+ subjectTypes: ['record'],
124
+ reportTypes: [COM_ATPROTO_MODERATION.DefsReasonSpam],
125
+ collection: 'app.bsky.feed.post',
126
+ }),
127
+ ]);
128
+ // Report one user (random)
129
+ const reporter = picka(userAgents);
130
+ await reporter.com.atproto.moderation.createReport({
131
+ reasonType: picka([
132
+ COM_ATPROTO_MODERATION.DefsReasonSpam,
133
+ COM_ATPROTO_MODERATION.DefsReasonOther,
134
+ ]),
135
+ reason: picka(["Didn't look right to me", undefined, undefined]),
136
+ subject: {
137
+ $type: 'com.atproto.admin.defs#repoRef',
138
+ did: picka(userAgents).did,
139
+ },
140
+ });
141
+ // Reports that target queues
142
+ await alice.com.atproto.moderation.createReport({
143
+ reasonType: COM_ATPROTO_MODERATION.DefsReasonSpam,
144
+ reason: 'This account is spamming',
145
+ subject: { $type: 'com.atproto.admin.defs#repoRef', did: bob.did },
146
+ });
147
+ await bob.com.atproto.moderation.createReport({
148
+ reasonType: 'tools.ozone.report.defs#reasonViolenceThreats',
149
+ reason: 'Threatened me',
150
+ subject: {
151
+ $type: 'com.atproto.admin.defs#repoRef',
152
+ did: carla.did,
153
+ },
154
+ });
155
+ // everybody follows everybody
156
+ const follow = async (author, subject) => {
157
+ await author.app.bsky.graph.follow.create({ repo: author.assertDid }, {
158
+ subject: subject.assertDid,
159
+ createdAt: date.next().value,
160
+ });
161
+ };
162
+ await follow(alice, bob);
163
+ await follow(alice, carla);
164
+ await follow(bob, alice);
165
+ await follow(bob, carla);
166
+ await follow(carla, alice);
167
+ await follow(carla, bob);
168
+ // a set of posts and reposts
169
+ const posts = [];
170
+ for (let i = 0; i < postTexts.length; i++) {
171
+ const author = picka(userAgents);
172
+ const post = await author.app.bsky.feed.post.create({ repo: author.did }, {
173
+ text: postTexts[i],
174
+ createdAt: date.next().value,
175
+ });
176
+ posts.push(post);
177
+ if (rand(10) === 0) {
178
+ const reposter = picka(userAgents);
179
+ await reposter.app.bsky.feed.repost.create({ repo: reposter.did }, {
180
+ subject: picka(posts),
181
+ createdAt: date.next().value,
182
+ });
183
+ }
184
+ if (rand(6) === 0) {
185
+ const reporter = picka(userAgents);
186
+ await reporter.com.atproto.moderation.createReport({
187
+ reasonType: picka([
188
+ COM_ATPROTO_MODERATION.DefsReasonSpam,
189
+ COM_ATPROTO_MODERATION.DefsReasonOther,
190
+ ]),
191
+ reason: picka(["Didn't look right to me", undefined, undefined]),
192
+ subject: {
193
+ $type: 'com.atproto.repo.strongRef',
194
+ uri: post.uri,
195
+ cid: post.cid,
196
+ },
197
+ });
198
+ }
199
+ }
200
+ // Spam post report
201
+ if (posts.length > 0) {
202
+ await carla.com.atproto.moderation.createReport({
203
+ reasonType: COM_ATPROTO_MODERATION.DefsReasonSpam,
204
+ reason: 'This post is spam',
205
+ subject: {
206
+ $type: 'com.atproto.repo.strongRef',
207
+ uri: posts[0].uri,
208
+ cid: posts[0].cid,
209
+ },
210
+ });
211
+ }
212
+ // Route all reports to queues
213
+ await env.ozone.daemon.ctx.queueRouter.routeReports();
214
+ // make some naughty posts & label them
215
+ const file = Buffer.from(labeledImgB64, 'base64');
216
+ const uploadedImg = await bob.com.atproto.repo.uploadBlob(file, {
217
+ encoding: 'image/png',
218
+ });
219
+ const labeledPost = await bob.app.bsky.feed.post.create({ repo: bob.assertDid }, {
220
+ text: 'naughty post',
221
+ embed: {
222
+ $type: 'app.bsky.embed.images',
223
+ images: [
224
+ {
225
+ image: uploadedImg.data.blob,
226
+ alt: 'naughty naughty',
227
+ },
228
+ ],
229
+ },
230
+ createdAt: date.next().value,
231
+ });
232
+ const filteredPost = await bob.app.bsky.feed.post.create({ repo: bob.assertDid }, {
233
+ text: 'really bad post should be deleted',
234
+ createdAt: date.next().value,
235
+ });
236
+ await createLabel(env.bsky.db, {
237
+ uri: labeledPost.uri,
238
+ cid: labeledPost.cid,
239
+ val: 'nudity',
240
+ });
241
+ await createLabel(env.bsky.db, {
242
+ uri: filteredPost.uri,
243
+ cid: filteredPost.cid,
244
+ val: 'dmca-violation',
245
+ });
246
+ // post with a gallery of images
247
+ const galleryItems = [];
248
+ for (let i = 0; i < 10; i++) {
249
+ galleryItems.push({
250
+ $type: 'app.bsky.embed.gallery#image',
251
+ image: uploadedImg.data.blob,
252
+ alt: 'naughty ' + (i + 1),
253
+ aspectRatio: {
254
+ $type: 'app.bsky.embed.defs#aspectRatio',
255
+ width: 10,
256
+ height: 10,
257
+ },
258
+ });
259
+ }
260
+ const galleryPost = await bob.app.bsky.feed.post.create({ repo: bob.assertDid }, {
261
+ text: 'look at my cool pics',
262
+ embed: {
263
+ $type: 'app.bsky.embed.gallery',
264
+ items: galleryItems,
265
+ },
266
+ createdAt: date.next().value,
267
+ });
268
+ posts.push(galleryPost);
269
+ // a set of replies
270
+ for (let i = 0; i < 100; i++) {
271
+ const targetUri = picka(posts).uri;
272
+ const urip = new AtUri(targetUri);
273
+ const target = await alice.app.bsky.feed.post.get({
274
+ repo: urip.host,
275
+ rkey: urip.rkey,
276
+ });
277
+ const author = picka(userAgents);
278
+ try {
279
+ const post = await author.app.bsky.feed.post.create({ repo: author.did }, {
280
+ text: picka(replyTexts),
281
+ reply: {
282
+ root: target.value.reply?.root ?? target,
283
+ parent: target,
284
+ },
285
+ createdAt: date.next().value,
286
+ });
287
+ posts.push(post);
288
+ }
289
+ catch (err) {
290
+ // @TODO Investigate why this sometimes fails.
291
+ console.error('Failed to create reply', err);
292
+ }
293
+ }
294
+ // a set of likes
295
+ for (const post of posts) {
296
+ for (const user of userAgents) {
297
+ if (rand(3) === 0) {
298
+ await user.app.bsky.feed.like.create({ repo: user.did }, {
299
+ subject: post,
300
+ createdAt: date.next().value,
301
+ });
302
+ }
303
+ }
304
+ }
305
+ // a couple feed generators that returns some posts
306
+ const fg1Uri = AtUri.make(alice.assertDid, 'app.bsky.feed.generator', 'alice-favs');
307
+ const fg1 = await env.createFeedGen({
308
+ [fg1Uri.toString()]: async () => {
309
+ const feed = posts
310
+ .filter(() => rand(2) === 0)
311
+ .map((post) => ({ post: post.uri }));
312
+ return {
313
+ encoding: 'application/json',
314
+ body: {
315
+ feed,
316
+ },
317
+ };
318
+ },
319
+ });
320
+ const avatarImg = Buffer.from(blurHashB64, 'base64');
321
+ const avatarRes = await alice.com.atproto.repo.uploadBlob(avatarImg, {
322
+ encoding: 'image/png',
323
+ });
324
+ const fgAliceRes = await alice.app.bsky.feed.generator.create({ repo: alice.assertDid, rkey: fg1Uri.rkey }, {
325
+ did: fg1.did,
326
+ displayName: 'alices feed',
327
+ description: 'all my fav stuff',
328
+ avatar: avatarRes.data.blob,
329
+ createdAt: date.next().value,
330
+ });
331
+ await alice.app.bsky.feed.post.create({ repo: alice.assertDid }, {
332
+ text: 'check out my algorithm!',
333
+ embed: {
334
+ $type: 'app.bsky.embed.record',
335
+ record: fgAliceRes,
336
+ },
337
+ createdAt: date.next().value,
338
+ });
339
+ for (const user of [alice, bob, carla]) {
340
+ await user.app.bsky.feed.like.create({ repo: user.did }, {
341
+ subject: fgAliceRes,
342
+ createdAt: date.next().value,
343
+ });
344
+ }
345
+ const fg2Uri = AtUri.make(bob.assertDid, 'app.bsky.feed.generator', 'bob-redux');
346
+ const fg2 = await env.createFeedGen({
347
+ [fg2Uri.toString()]: async () => {
348
+ const feed = posts
349
+ .filter(() => rand(2) === 0)
350
+ .map((post) => ({ post: post.uri }));
351
+ return {
352
+ encoding: 'application/json',
353
+ body: {
354
+ feed,
355
+ },
356
+ };
357
+ },
358
+ });
359
+ const fgBobRes = await bob.app.bsky.feed.generator.create({ repo: bob.assertDid, rkey: fg2Uri.rkey }, {
360
+ did: fg2.did,
361
+ displayName: 'Bobby boy hot new algo',
362
+ createdAt: date.next().value,
363
+ });
364
+ await alice.app.bsky.feed.post.create({ repo: alice.assertDid }, {
365
+ text: `bobs feed is neat too`,
366
+ embed: {
367
+ $type: 'app.bsky.embed.record',
368
+ record: fgBobRes,
369
+ },
370
+ createdAt: date.next().value,
371
+ });
372
+ const fg3Uri = AtUri.make(carla.assertDid, 'app.bsky.feed.generator', 'carla-intr-algo');
373
+ const fg3 = await env.createFeedGen({
374
+ [fg3Uri.toString()]: async () => {
375
+ const feed = posts
376
+ .filter(() => rand(2) === 0)
377
+ .map((post) => ({ post: post.uri }));
378
+ return {
379
+ encoding: 'application/json',
380
+ body: {
381
+ feed,
382
+ },
383
+ };
384
+ },
385
+ });
386
+ const fgCarlaRes = await carla.app.bsky.feed.generator.create({ repo: carla.assertDid, rkey: fg3Uri.rkey }, {
387
+ did: fg3.did,
388
+ displayName: `Acceptin' Generator`,
389
+ acceptsInteractions: true,
390
+ createdAt: date.next().value,
391
+ });
392
+ await alice.app.bsky.feed.post.create({ repo: alice.assertDid }, {
393
+ text: `carla accepts interactions on her feed`,
394
+ embed: {
395
+ $type: 'app.bsky.embed.record',
396
+ record: fgCarlaRes,
397
+ },
398
+ createdAt: date.next().value,
399
+ });
400
+ // create labeler service
401
+ {
402
+ await labeler.app.bsky.labeler.service.create({ repo: labeler.did, rkey: 'self' }, {
403
+ policies: {
404
+ labelValues: [
405
+ '!hide',
406
+ 'porn',
407
+ 'rude',
408
+ 'spam',
409
+ 'spider',
410
+ 'misinfo',
411
+ 'cool',
412
+ 'curate',
413
+ ],
414
+ labelValueDefinitions: [
415
+ {
416
+ identifier: 'rude',
417
+ blurs: 'content',
418
+ severity: 'alert',
419
+ defaultSetting: 'warn',
420
+ adultOnly: true,
421
+ locales: [
422
+ {
423
+ lang: 'en',
424
+ name: 'Rude',
425
+ description: 'Just such a jerk, you wouldnt believe it.',
426
+ },
427
+ ],
428
+ },
429
+ {
430
+ identifier: 'spam',
431
+ blurs: 'content',
432
+ severity: 'inform',
433
+ defaultSetting: 'hide',
434
+ locales: [
435
+ {
436
+ lang: 'en',
437
+ name: 'Spam',
438
+ description: 'Low quality posts that dont add to the conversation.',
439
+ },
440
+ ],
441
+ },
442
+ {
443
+ identifier: 'spider',
444
+ blurs: 'media',
445
+ severity: 'alert',
446
+ defaultSetting: 'warn',
447
+ locales: [
448
+ {
449
+ lang: 'en',
450
+ name: 'Spider!',
451
+ description: 'Oh no its a spider.',
452
+ },
453
+ ],
454
+ },
455
+ {
456
+ identifier: 'cool',
457
+ blurs: 'none',
458
+ severity: 'inform',
459
+ defaultSetting: 'warn',
460
+ locales: [
461
+ {
462
+ lang: 'en',
463
+ name: 'Cool',
464
+ description: 'The coolest peeps in the atmosphere.',
465
+ },
466
+ ],
467
+ },
468
+ {
469
+ identifier: 'curate',
470
+ blurs: 'none',
471
+ severity: 'none',
472
+ defaultSetting: 'warn',
473
+ locales: [
474
+ {
475
+ lang: 'en',
476
+ name: 'Curation filter',
477
+ description: 'We just dont want to see it as much.',
478
+ },
479
+ ],
480
+ },
481
+ ],
482
+ },
483
+ createdAt: date.next().value,
484
+ });
485
+ await createLabel(env.bsky.db, {
486
+ uri: alice.assertDid,
487
+ cid: '',
488
+ val: 'rude',
489
+ src: labeler.did,
490
+ });
491
+ await createLabel(env.bsky.db, {
492
+ uri: `at://${alice.assertDid}/app.bsky.feed.generator/alice-favs`,
493
+ cid: '',
494
+ val: 'cool',
495
+ src: labeler.did,
496
+ });
497
+ await createLabel(env.bsky.db, {
498
+ uri: bob.assertDid,
499
+ cid: '',
500
+ val: 'cool',
501
+ src: labeler.did,
502
+ });
503
+ await createLabel(env.bsky.db, {
504
+ uri: carla.assertDid,
505
+ cid: '',
506
+ val: 'spam',
507
+ src: labeler.did,
508
+ });
509
+ }
510
+ // Create lists and add people to the lists
511
+ {
512
+ const flowerLovers = await alice.app.bsky.graph.list.create({ repo: alice.assertDid }, {
513
+ name: 'Flower Lovers',
514
+ purpose: 'app.bsky.graph.defs#curatelist',
515
+ createdAt: new Date().toISOString(),
516
+ description: 'A list of posts about flowers',
517
+ });
518
+ const labelHaters = await bob.app.bsky.graph.list.create({ repo: bob.assertDid }, {
519
+ name: 'Label Haters',
520
+ purpose: 'app.bsky.graph.defs#modlist',
521
+ createdAt: new Date().toISOString(),
522
+ description: 'A list of people who hate labels',
523
+ });
524
+ await alice.app.bsky.graph.listitem.create({ repo: alice.assertDid }, {
525
+ subject: bob.assertDid,
526
+ createdAt: new Date().toISOString(),
527
+ list: new RecordRef(flowerLovers.uri, flowerLovers.cid).uriStr,
528
+ });
529
+ await bob.app.bsky.graph.listitem.create({ repo: bob.assertDid }, {
530
+ subject: alice.assertDid,
531
+ createdAt: new Date().toISOString(),
532
+ list: new RecordRef(labelHaters.uri, labelHaters.cid).uriStr,
533
+ });
534
+ }
535
+ await setVerifier(env.bsky.db, alice.assertDid);
536
+ // @TODO These are useful when testing complex threads, but don't need to be enabled all the time. We could make it configurable.
537
+ // import * as seedThreadV2 from '../seed/thread-v2.js'
538
+ // const sc = env.getSeedClient()
539
+ // await seedThreadV2.simple(sc)
540
+ // await seedThreadV2.long(sc)
541
+ // await seedThreadV2.deep(sc)
542
+ // await seedThreadV2.branchingFactor(sc)
543
+ // await seedThreadV2.annotateMoreReplies(sc)
544
+ // await seedThreadV2.annotateOP(sc)
545
+ // await seedThreadV2.sort(sc)
546
+ // await seedThreadV2.bumpOpAndViewer(sc)
547
+ // await seedThreadV2.bumpGroupSorting(sc)
548
+ // await seedThreadV2.bumpFollows(sc)
549
+ // await seedThreadV2.blockDeletionAuth(sc, env.bsky.ctx.cfg.modServiceDid)
550
+ // await seedThreadV2.mutes(sc)
551
+ // await seedThreadV2.threadgated(sc)
552
+ // await seedThreadV2.tags(sc)
553
+ }
554
+ const createLabel = async (db, opts) => {
555
+ await db.db
556
+ .insertInto('label')
557
+ .values({
558
+ uri: opts.uri,
559
+ cid: opts.cid,
560
+ val: opts.val,
561
+ cts: new Date().toISOString(),
562
+ neg: false,
563
+ src: opts.src ?? EXAMPLE_LABELER,
564
+ })
565
+ .execute();
566
+ };
567
+ const setVerifier = async (db, did) => {
568
+ await db.db
569
+ .updateTable('actor')
570
+ .set({ trustedVerifier: true })
571
+ .where('did', '=', did)
572
+ .execute();
573
+ };
574
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mock/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,cAAc,CAAA;AAErB,OAAO,EAAE,KAAK,EAAoB,MAAM,iBAAiB,CAAA;AACzD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAoB,MAAM,aAAa,CAAA;AAC1E,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACjD,OAAO,WAAW,MAAM,+BAA+B,CAAA;AACvD,OAAO,aAAa,MAAM,0BAA0B,CAAA;AAEpD,OAAO;AACP,+BAA+B;AAC/B,4DAA4D;AAC5D,oCAAoC;AACpC,8DAA8D;AAC9D,QAAQ,CAAC,CAAC,OAAO;IACf,IAAI,KAAK,GAAG,aAAa,CAAA;IACzB,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAA;QACnC,KAAK,IAAI,GAAG,CAAA;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,GAAgB;IACtD,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IAEtB,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;IACzD,MAAM,KAAK,GAAG,CAAI,GAAa,EAAK,EAAE;QACpC,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACf,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAA;QACxC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAA;IAC9B,CAAC,CAAA;IAED,MAAM,KAAK,GAAG;QACZ;YACE,KAAK,EAAE,gBAAgB;YACvB,MAAM,EAAE,YAAY;YACpB,QAAQ,EAAE,SAAS;YACnB,WAAW,EAAE,OAAO;YACpB,WAAW,EAAE,aAAa;SAC3B;QACD;YACE,KAAK,EAAE,cAAc;YACrB,MAAM,EAAE,UAAU;YAClB,QAAQ,EAAE,SAAS;YACnB,WAAW,EAAE,KAAK;YAClB,WAAW,EAAE,aAAa;SAC3B;QACD;YACE,KAAK,EAAE,gBAAgB;YACvB,MAAM,EAAE,YAAY;YACpB,QAAQ,EAAE,SAAS;YACnB,WAAW,EAAE,OAAO;YACpB,WAAW,EAAE,aAAa;SAC3B;QACD;YACE,KAAK,EAAE,iBAAiB;YACxB,MAAM,EAAE,aAAa;YACrB,QAAQ,EAAE,aAAa;SACxB;QACD;YACE,KAAK,EAAE,cAAc;YACrB,MAAM,EAAE,UAAU;YAClB,QAAQ,EAAE,UAAU;SACrB;QACD;YACE,KAAK,EAAE,oBAAoB;YAC3B,MAAM,EAAE,gBAAgB;YACxB,QAAQ,EAAE,gBAAgB;SAC3B;QACD;YACE,KAAK,EAAE,kBAAkB;YACzB,MAAM,EAAE,cAAc;YACtB,QAAQ,EAAE,SAAS;YACnB,WAAW,EAAE,cAAc;YAC3B,WAAW,EAAE,uCAAuC;SACrD;KACF,CAAA;IAED,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,GAAG,CAClC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,KAAK,GAAa,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAA;QAC1C,MAAM,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;QAC/B,KAAK,CAAC,mBAAmB,EAAE,CAAA;QAC3B,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACzC,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CACvC,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,EACnB;gBACE,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;aAC9B,CACF,CAAA;QACH,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC,CAAC,CACH,CAAA;IAED,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,GAAG,UAAU,CAAA;IAEtE,yCAAyC;IACzC,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAC3C,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAClB,EAAE,aAAa,EAAE,KAAK,EAAE,CACzB,CAAA;IACH,CAAC;IAED,sBAAsB;IACtB,MAAM,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACxC,MAAM,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;IAEzC,uBAAuB;IACvB,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAA;IACvC,MAAM,YAAY,GAAG,KAAK,EAAE,IAAY,EAAE,EAAE,CAC1C,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAErC,MAAM,WAAW,GAAG,KAAK,EAAE,KAK1B,EAAiB,EAAE;QAClB,IAAI,CAAC;YACH,MAAM,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE;gBACpD,QAAQ,EAAE,kBAAkB;gBAC5B,OAAO,EAAE,MAAM,YAAY,CAAC,+BAA+B,CAAC;aAC7D,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,CAAC,GAAG,YAAY,0BAA0B,CAAC,qBAAqB,CAAC,EAAE,CAAC;gBACvE,MAAM,GAAG,CAAA;YACX,CAAC;QACH,CAAC;IACH,CAAC,CAAA;IAED,MAAM,OAAO,CAAC,GAAG,CAAC;QAChB,WAAW,CAAC;YACV,IAAI,EAAE,iBAAiB;YACvB,YAAY,EAAE,CAAC,SAAS,CAAC;YACzB,WAAW,EAAE,CAAC,sBAAsB,CAAC,cAAc,CAAC;SACrD,CAAC;QACF,WAAW,CAAC;YACV,IAAI,EAAE,sBAAsB;YAC5B,YAAY,EAAE,CAAC,SAAS,CAAC;YACzB,WAAW,EAAE,CAAC,+CAA+C,CAAC;SAC/D,CAAC;QACF,WAAW,CAAC;YACV,IAAI,EAAE,cAAc;YACpB,YAAY,EAAE,CAAC,QAAQ,CAAC;YACxB,WAAW,EAAE,CAAC,sBAAsB,CAAC,cAAc,CAAC;YACpD,UAAU,EAAE,oBAAoB;SACjC,CAAC;KACH,CAAC,CAAA;IAEF,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,CAAA;IAClC,MAAM,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC;QACjD,UAAU,EAAE,KAAK,CAAC;YAChB,sBAAsB,CAAC,cAAc;YACrC,sBAAsB,CAAC,eAAe;SACvC,CAAC;QACF,MAAM,EAAE,KAAK,CAAC,CAAC,yBAAyB,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAChE,OAAO,EAAE;YACP,KAAK,EAAE,gCAAgC;YACvC,GAAG,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG;SAC3B;KACF,CAAC,CAAA;IAEF,6BAA6B;IAC7B,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC;QAC9C,UAAU,EAAE,sBAAsB,CAAC,cAAc;QACjD,MAAM,EAAE,0BAA0B;QAClC,OAAO,EAAE,EAAE,KAAK,EAAE,gCAAgC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE;KACnE,CAAC,CAAA;IACF,MAAM,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC;QAC5C,UAAU,EAAE,+CAA+C;QAC3D,MAAM,EAAE,eAAe;QACvB,OAAO,EAAE;YACP,KAAK,EAAE,gCAAgC;YACvC,GAAG,EAAE,KAAK,CAAC,GAAG;SACf;KACF,CAAC,CAAA;IAEF,8BAA8B;IAC9B,MAAM,MAAM,GAAG,KAAK,EAAE,MAAgB,EAAE,OAAiB,EAAE,EAAE;QAC3D,MAAM,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CACvC,EAAE,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,EAC1B;YACE,OAAO,EAAE,OAAO,CAAC,SAAS;YAC1B,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;SAC7B,CACF,CAAA;IACH,CAAC,CAAA;IACD,MAAM,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IACxB,MAAM,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;IAC1B,MAAM,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACxB,MAAM,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACxB,MAAM,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;IAC1B,MAAM,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IAExB,6BAA6B;IAC7B,MAAM,KAAK,GAAmC,EAAE,CAAA;IAChD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,CAAA;QAChC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CACjD,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,EACpB;YACE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;YAClB,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;SAC7B,CACF,CAAA;QACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAChB,IAAI,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;YACnB,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,CAAA;YAClC,MAAM,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CACxC,EAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,EAAE,EACtB;gBACE,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC;gBACrB,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;aAC7B,CACF,CAAA;QACH,CAAC;QACD,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,CAAA;YAClC,MAAM,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC;gBACjD,UAAU,EAAE,KAAK,CAAC;oBAChB,sBAAsB,CAAC,cAAc;oBACrC,sBAAsB,CAAC,eAAe;iBACvC,CAAC;gBACF,MAAM,EAAE,KAAK,CAAC,CAAC,yBAAyB,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;gBAChE,OAAO,EAAE;oBACP,KAAK,EAAE,4BAA4B;oBACnC,GAAG,EAAE,IAAI,CAAC,GAAG;oBACb,GAAG,EAAE,IAAI,CAAC,GAAG;iBACd;aACF,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC;YAC9C,UAAU,EAAE,sBAAsB,CAAC,cAAc;YACjD,MAAM,EAAE,mBAAmB;YAC3B,OAAO,EAAE;gBACP,KAAK,EAAE,4BAA4B;gBACnC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG;gBACjB,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG;aAClB;SACF,CAAC,CAAA;IACJ,CAAC;IAED,8BAA8B;IAC9B,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,YAAY,EAAE,CAAA;IAErD,uCAAuC;IACvC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAA;IACjD,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;QAC9D,QAAQ,EAAE,WAAW;KACtB,CAAC,CAAA;IACF,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CACrD,EAAE,IAAI,EAAE,GAAG,CAAC,SAAS,EAAE,EACvB;QACE,IAAI,EAAE,cAAc;QACpB,KAAK,EAAE;YACL,KAAK,EAAE,uBAAuB;YAC9B,MAAM,EAAE;gBACN;oBACE,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI;oBAC5B,GAAG,EAAE,iBAAiB;iBACvB;aACF;SACF;QACD,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;KAC7B,CACF,CAAA;IAED,MAAM,YAAY,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CACtD,EAAE,IAAI,EAAE,GAAG,CAAC,SAAS,EAAE,EACvB;QACE,IAAI,EAAE,mCAAmC;QACzC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;KAC7B,CACF,CAAA;IAED,MAAM,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;QAC7B,GAAG,EAAE,WAAW,CAAC,GAAG;QACpB,GAAG,EAAE,WAAW,CAAC,GAAG;QACpB,GAAG,EAAE,QAAQ;KACd,CAAC,CAAA;IACF,MAAM,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;QAC7B,GAAG,EAAE,YAAY,CAAC,GAAG;QACrB,GAAG,EAAE,YAAY,CAAC,GAAG;QACrB,GAAG,EAAE,gBAAgB;KACtB,CAAC,CAAA;IAEF,gCAAgC;IAChC,MAAM,YAAY,GAAe,EAAE,CAAA;IACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,YAAY,CAAC,IAAI,CAAC;YAChB,KAAK,EAAE,8BAA8B;YACrC,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI;YAC5B,GAAG,EAAE,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YACzB,WAAW,EAAE;gBACX,KAAK,EAAE,iCAAiC;gBACxC,KAAK,EAAE,EAAE;gBACT,MAAM,EAAE,EAAE;aACX;SACF,CAAC,CAAA;IACJ,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CACrD,EAAE,IAAI,EAAE,GAAG,CAAC,SAAS,EAAE,EACvB;QACE,IAAI,EAAE,sBAAsB;QAC5B,KAAK,EAAE;YACL,KAAK,EAAE,wBAAwB;YAC/B,KAAK,EAAE,YAAY;SACpB;QACD,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;KAC7B,CACF,CAAA;IACD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IAEvB,mBAAmB;IACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAA;QAClC,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,SAAS,CAAC,CAAA;QACjC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YAChD,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC,CAAA;QACF,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,CAAA;QAChC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CACjD,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,EACpB;gBACE,IAAI,EAAE,KAAK,CAAC,UAAU,CAAC;gBACvB,KAAK,EAAE;oBACL,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,IAAI,MAAM;oBACxC,MAAM,EAAE,MAAM;iBACf;gBACD,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;aAC7B,CACF,CAAA;YAED,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,8CAA8C;YAC9C,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAA;QAC9C,CAAC;IACH,CAAC;IAED,iBAAiB;IACjB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC9B,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;gBAClB,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAClC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAClB;oBACE,OAAO,EAAE,IAAI;oBACb,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;iBAC7B,CACF,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CACvB,KAAK,CAAC,SAAS,EACf,yBAAyB,EACzB,YAAY,CACb,CAAA;IACD,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC;QAClC,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,KAAK,IAAI,EAAE;YAC9B,MAAM,IAAI,GAAG,KAAK;iBACf,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;iBAC3B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAkB,EAAE,CAAC,CAAC,CAAA;YACrD,OAAO;gBACL,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE;oBACJ,IAAI;iBACL;aACF,CAAA;QACH,CAAC;KACF,CAAC,CAAA;IACF,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;IACpD,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE;QACnE,QAAQ,EAAE,WAAW;KACtB,CAAC,CAAA;IACF,MAAM,UAAU,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAC3D,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAC5C;QACE,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,kBAAkB;QAC/B,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI;QAC3B,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;KAC7B,CACF,CAAA;IAED,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CACnC,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,EACzB;QACE,IAAI,EAAE,yBAAyB;QAC/B,KAAK,EAAE;YACL,KAAK,EAAE,uBAAuB;YAC9B,MAAM,EAAE,UAAU;SACnB;QACD,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;KAC7B,CACF,CAAA;IACD,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAClC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAClB;YACE,OAAO,EAAE,UAAU;YACnB,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;SAC7B,CACF,CAAA;IACH,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CACvB,GAAG,CAAC,SAAS,EACb,yBAAyB,EACzB,WAAW,CACZ,CAAA;IACD,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC;QAClC,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,KAAK,IAAI,EAAE;YAC9B,MAAM,IAAI,GAAG,KAAK;iBACf,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;iBAC3B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAkB,EAAE,CAAC,CAAC,CAAA;YACrD,OAAO;gBACL,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE;oBACJ,IAAI;iBACL;aACF,CAAA;QACH,CAAC;KACF,CAAC,CAAA;IACF,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CACvD,EAAE,IAAI,EAAE,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAC1C;QACE,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,WAAW,EAAE,wBAAwB;QACrC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;KAC7B,CACF,CAAA;IAED,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CACnC,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,EACzB;QACE,IAAI,EAAE,uBAAuB;QAC7B,KAAK,EAAE;YACL,KAAK,EAAE,uBAAuB;YAC9B,MAAM,EAAE,QAAQ;SACjB;QACD,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;KAC7B,CACF,CAAA;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CACvB,KAAK,CAAC,SAAS,EACf,yBAAyB,EACzB,iBAAiB,CAClB,CAAA;IACD,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC;QAClC,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,KAAK,IAAI,EAAE;YAC9B,MAAM,IAAI,GAAG,KAAK;iBACf,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;iBAC3B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAkB,EAAE,CAAC,CAAC,CAAA;YACrD,OAAO;gBACL,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE;oBACJ,IAAI;iBACL;aACF,CAAA;QACH,CAAC;KACF,CAAC,CAAA;IACF,MAAM,UAAU,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAC3D,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAC5C;QACE,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,WAAW,EAAE,qBAAqB;QAClC,mBAAmB,EAAE,IAAI;QACzB,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;KAC7B,CACF,CAAA;IAED,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CACnC,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,EACzB;QACE,IAAI,EAAE,wCAAwC;QAC9C,KAAK,EAAE;YACL,KAAK,EAAE,uBAAuB;YAC9B,MAAM,EAAE,UAAU;SACnB;QACD,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;KAC7B,CACF,CAAA;IAED,yBAAyB;IACzB,CAAC;QACC,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAC3C,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,EACnC;YACE,QAAQ,EAAE;gBACR,WAAW,EAAE;oBACX,OAAO;oBACP,MAAM;oBACN,MAAM;oBACN,MAAM;oBACN,QAAQ;oBACR,SAAS;oBACT,MAAM;oBACN,QAAQ;iBACT;gBACD,qBAAqB,EAAE;oBACrB;wBACE,UAAU,EAAE,MAAM;wBAClB,KAAK,EAAE,SAAS;wBAChB,QAAQ,EAAE,OAAO;wBACjB,cAAc,EAAE,MAAM;wBACtB,SAAS,EAAE,IAAI;wBACf,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,IAAI;gCACV,IAAI,EAAE,MAAM;gCACZ,WAAW,EAAE,2CAA2C;6BACzD;yBACF;qBACF;oBACD;wBACE,UAAU,EAAE,MAAM;wBAClB,KAAK,EAAE,SAAS;wBAChB,QAAQ,EAAE,QAAQ;wBAClB,cAAc,EAAE,MAAM;wBACtB,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,IAAI;gCACV,IAAI,EAAE,MAAM;gCACZ,WAAW,EACT,sDAAsD;6BACzD;yBACF;qBACF;oBACD;wBACE,UAAU,EAAE,QAAQ;wBACpB,KAAK,EAAE,OAAO;wBACd,QAAQ,EAAE,OAAO;wBACjB,cAAc,EAAE,MAAM;wBACtB,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,IAAI;gCACV,IAAI,EAAE,SAAS;gCACf,WAAW,EAAE,qBAAqB;6BACnC;yBACF;qBACF;oBACD;wBACE,UAAU,EAAE,MAAM;wBAClB,KAAK,EAAE,MAAM;wBACb,QAAQ,EAAE,QAAQ;wBAClB,cAAc,EAAE,MAAM;wBACtB,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,IAAI;gCACV,IAAI,EAAE,MAAM;gCACZ,WAAW,EAAE,sCAAsC;6BACpD;yBACF;qBACF;oBACD;wBACE,UAAU,EAAE,QAAQ;wBACpB,KAAK,EAAE,MAAM;wBACb,QAAQ,EAAE,MAAM;wBAChB,cAAc,EAAE,MAAM;wBACtB,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,IAAI;gCACV,IAAI,EAAE,iBAAiB;gCACvB,WAAW,EAAE,sCAAsC;6BACpD;yBACF;qBACF;iBACF;aACF;YACD,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK;SAC7B,CACF,CAAA;QACD,MAAM,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;YAC7B,GAAG,EAAE,KAAK,CAAC,SAAS;YACpB,GAAG,EAAE,EAAE;YACP,GAAG,EAAE,MAAM;YACX,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAA;QACF,MAAM,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;YAC7B,GAAG,EAAE,QAAQ,KAAK,CAAC,SAAS,qCAAqC;YACjE,GAAG,EAAE,EAAE;YACP,GAAG,EAAE,MAAM;YACX,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAA;QACF,MAAM,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;YAC7B,GAAG,EAAE,GAAG,CAAC,SAAS;YAClB,GAAG,EAAE,EAAE;YACP,GAAG,EAAE,MAAM;YACX,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAA;QACF,MAAM,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;YAC7B,GAAG,EAAE,KAAK,CAAC,SAAS;YACpB,GAAG,EAAE,EAAE;YACP,GAAG,EAAE,MAAM;YACX,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAA;IACJ,CAAC;IAED,2CAA2C;IAC3C,CAAC;QACC,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CACzD,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,EACzB;YACE,IAAI,EAAE,eAAe;YACrB,OAAO,EAAE,gCAAgC;YACzC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,WAAW,EAAE,+BAA+B;SAC7C,CACF,CAAA;QACD,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CACtD,EAAE,IAAI,EAAE,GAAG,CAAC,SAAS,EAAE,EACvB;YACE,IAAI,EAAE,cAAc;YACpB,OAAO,EAAE,6BAA6B;YACtC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,WAAW,EAAE,kCAAkC;SAChD,CACF,CAAA;QACD,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CACxC,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,EACzB;YACE,OAAO,EAAE,GAAG,CAAC,SAAS;YACtB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,IAAI,EAAE,IAAI,SAAS,CAAC,YAAY,CAAC,GAAG,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,MAAM;SAC/D,CACF,CAAA;QACD,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CACtC,EAAE,IAAI,EAAE,GAAG,CAAC,SAAS,EAAE,EACvB;YACE,OAAO,EAAE,KAAK,CAAC,SAAS;YACxB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,IAAI,EAAE,IAAI,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM;SAC7D,CACF,CAAA;IACH,CAAC;IAED,MAAM,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,SAAS,CAAC,CAAA;IAE/C,iIAAiI;IACjI,uDAAuD;IACvD,iCAAiC;IACjC,gCAAgC;IAChC,8BAA8B;IAC9B,8BAA8B;IAC9B,yCAAyC;IACzC,6CAA6C;IAC7C,oCAAoC;IACpC,8BAA8B;IAC9B,yCAAyC;IACzC,0CAA0C;IAC1C,qCAAqC;IACrC,2EAA2E;IAC3E,+BAA+B;IAC/B,qCAAqC;IACrC,8BAA8B;AAChC,CAAC;AAED,MAAM,WAAW,GAAG,KAAK,EACvB,EAAY,EACZ,IAA6D,EAC7D,EAAE;IACF,MAAM,EAAE,CAAC,EAAE;SACR,UAAU,CAAC,OAAO,CAAC;SACnB,MAAM,CAAC;QACN,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,GAAG,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC7B,GAAG,EAAE,KAAK;QACV,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,eAAe;KACjC,CAAC;SACD,OAAO,EAAE,CAAA;AACd,CAAC,CAAA;AAED,MAAM,WAAW,GAAG,KAAK,EAAE,EAAY,EAAE,GAAW,EAAE,EAAE;IACtD,MAAM,EAAE,CAAC,EAAE;SACR,WAAW,CAAC,OAAO,CAAC;SACpB,GAAG,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;SAC9B,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC;SACtB,OAAO,EAAE,CAAA;AACd,CAAC,CAAA","sourcesContent":["import {\n type AtpAgent,\n COM_ATPROTO_MODERATION,\n ToolsOzoneQueueCreateQueue,\n} from '@atproto/api'\nimport type { Database } from '@atproto/bsky'\nimport { AtUri, type AtUriString } from '@atproto/syntax'\nimport { EXAMPLE_LABELER, RecordRef, type TestNetwork } from '../index.js'\nimport { postTexts, replyTexts } from './data.js'\nimport blurHashB64 from './img/blur-hash-avatar-b64.js'\nimport labeledImgB64 from './img/labeled-img-b64.js'\n\n// NOTE\n// deterministic date generator\n// we use this to ensure the mock dataset is always the same\n// which is very useful when testing\n// (not everything is currently deterministic but it could be)\nfunction* dateGen(): Generator<string, never> {\n let start = 1657846031914\n while (true) {\n yield new Date(start).toISOString()\n start += 1e3\n }\n}\n\nexport async function generateMockSetup(env: TestNetwork) {\n const date = dateGen()\n\n const rand = (n: number) => Math.floor(Math.random() * n)\n const picka = <T>(arr: Array<T>): T => {\n if (arr.length) {\n return arr[rand(arr.length)] || arr[0]\n }\n throw new Error('Not found')\n }\n\n const users = [\n {\n email: 'alice@test.com',\n handle: `alice.test`,\n password: 'hunter2',\n displayName: 'Alice',\n description: 'Test user 0',\n },\n {\n email: 'bob@test.com',\n handle: `bob.test`,\n password: 'hunter2',\n displayName: 'Bob',\n description: 'Test user 1',\n },\n {\n email: 'carla@test.com',\n handle: `carla.test`,\n password: 'hunter2',\n displayName: 'Carla',\n description: 'Test user 2',\n },\n {\n email: 'triage@test.com',\n handle: 'triage.test',\n password: 'triage-pass',\n },\n {\n email: 'mod@test.com',\n handle: 'mod.test',\n password: 'mod-pass',\n },\n {\n email: 'admin-mod@test.com',\n handle: 'admin-mod.test',\n password: 'admin-mod-pass',\n },\n {\n email: 'labeler@test.com',\n handle: 'labeler.test',\n password: 'hunter2',\n displayName: 'Test Labeler',\n description: 'Labeling things across the atmosphere',\n },\n ]\n\n const userAgents = await Promise.all(\n users.map(async (user) => {\n const agent: AtpAgent = env.pds.getAgent()\n await agent.createAccount(user)\n agent.assertAuthenticated()\n if (user.displayName || user.description) {\n await agent.app.bsky.actor.profile.create(\n { repo: agent.did },\n {\n displayName: user.displayName,\n description: user.description,\n },\n )\n }\n return agent\n }),\n )\n\n const [alice, bob, carla, triage, mod, adminMod, labeler] = userAgents\n\n // Create chat declarations for all users\n for (const user of userAgents) {\n await user.chat.bsky.actor.declaration.create(\n { repo: user.did },\n { allowIncoming: 'all' },\n )\n }\n\n // Add moderator roles\n await env.ozone.addTriageDid(triage.did)\n await env.ozone.addModeratorDid(mod.did)\n await env.ozone.addAdminDid(adminMod.did)\n\n // Create report queues\n const ozoneAgent = env.ozone.getAgent()\n const adminHeaders = async (nsid: string) =>\n env.ozone.modHeaders(nsid, 'admin')\n\n const createQueue = async (input: {\n name: string\n subjectTypes: string[]\n reportTypes: string[]\n collection?: string\n }): Promise<void> => {\n try {\n await ozoneAgent.tools.ozone.queue.createQueue(input, {\n encoding: 'application/json',\n headers: await adminHeaders('tools.ozone.queue.createQueue'),\n })\n } catch (err) {\n if (!(err instanceof ToolsOzoneQueueCreateQueue.ConflictingQueueError)) {\n throw err\n }\n }\n }\n\n await Promise.all([\n createQueue({\n name: 'Spammy Accounts',\n subjectTypes: ['account'],\n reportTypes: [COM_ATPROTO_MODERATION.DefsReasonSpam],\n }),\n createQueue({\n name: 'Threatening Accounts',\n subjectTypes: ['account'],\n reportTypes: ['tools.ozone.report.defs#reasonViolenceThreats'],\n }),\n createQueue({\n name: 'Spammy Posts',\n subjectTypes: ['record'],\n reportTypes: [COM_ATPROTO_MODERATION.DefsReasonSpam],\n collection: 'app.bsky.feed.post',\n }),\n ])\n\n // Report one user (random)\n const reporter = picka(userAgents)\n await reporter.com.atproto.moderation.createReport({\n reasonType: picka([\n COM_ATPROTO_MODERATION.DefsReasonSpam,\n COM_ATPROTO_MODERATION.DefsReasonOther,\n ]),\n reason: picka([\"Didn't look right to me\", undefined, undefined]),\n subject: {\n $type: 'com.atproto.admin.defs#repoRef',\n did: picka(userAgents).did,\n },\n })\n\n // Reports that target queues\n await alice.com.atproto.moderation.createReport({\n reasonType: COM_ATPROTO_MODERATION.DefsReasonSpam,\n reason: 'This account is spamming',\n subject: { $type: 'com.atproto.admin.defs#repoRef', did: bob.did },\n })\n await bob.com.atproto.moderation.createReport({\n reasonType: 'tools.ozone.report.defs#reasonViolenceThreats',\n reason: 'Threatened me',\n subject: {\n $type: 'com.atproto.admin.defs#repoRef',\n did: carla.did,\n },\n })\n\n // everybody follows everybody\n const follow = async (author: AtpAgent, subject: AtpAgent) => {\n await author.app.bsky.graph.follow.create(\n { repo: author.assertDid },\n {\n subject: subject.assertDid,\n createdAt: date.next().value,\n },\n )\n }\n await follow(alice, bob)\n await follow(alice, carla)\n await follow(bob, alice)\n await follow(bob, carla)\n await follow(carla, alice)\n await follow(carla, bob)\n\n // a set of posts and reposts\n const posts: { uri: string; cid: string }[] = []\n for (let i = 0; i < postTexts.length; i++) {\n const author = picka(userAgents)\n const post = await author.app.bsky.feed.post.create(\n { repo: author.did },\n {\n text: postTexts[i],\n createdAt: date.next().value,\n },\n )\n posts.push(post)\n if (rand(10) === 0) {\n const reposter = picka(userAgents)\n await reposter.app.bsky.feed.repost.create(\n { repo: reposter.did },\n {\n subject: picka(posts),\n createdAt: date.next().value,\n },\n )\n }\n if (rand(6) === 0) {\n const reporter = picka(userAgents)\n await reporter.com.atproto.moderation.createReport({\n reasonType: picka([\n COM_ATPROTO_MODERATION.DefsReasonSpam,\n COM_ATPROTO_MODERATION.DefsReasonOther,\n ]),\n reason: picka([\"Didn't look right to me\", undefined, undefined]),\n subject: {\n $type: 'com.atproto.repo.strongRef',\n uri: post.uri,\n cid: post.cid,\n },\n })\n }\n }\n\n // Spam post report\n if (posts.length > 0) {\n await carla.com.atproto.moderation.createReport({\n reasonType: COM_ATPROTO_MODERATION.DefsReasonSpam,\n reason: 'This post is spam',\n subject: {\n $type: 'com.atproto.repo.strongRef',\n uri: posts[0].uri,\n cid: posts[0].cid,\n },\n })\n }\n\n // Route all reports to queues\n await env.ozone.daemon.ctx.queueRouter.routeReports()\n\n // make some naughty posts & label them\n const file = Buffer.from(labeledImgB64, 'base64')\n const uploadedImg = await bob.com.atproto.repo.uploadBlob(file, {\n encoding: 'image/png',\n })\n const labeledPost = await bob.app.bsky.feed.post.create(\n { repo: bob.assertDid },\n {\n text: 'naughty post',\n embed: {\n $type: 'app.bsky.embed.images',\n images: [\n {\n image: uploadedImg.data.blob,\n alt: 'naughty naughty',\n },\n ],\n },\n createdAt: date.next().value,\n },\n )\n\n const filteredPost = await bob.app.bsky.feed.post.create(\n { repo: bob.assertDid },\n {\n text: 'really bad post should be deleted',\n createdAt: date.next().value,\n },\n )\n\n await createLabel(env.bsky.db, {\n uri: labeledPost.uri,\n cid: labeledPost.cid,\n val: 'nudity',\n })\n await createLabel(env.bsky.db, {\n uri: filteredPost.uri,\n cid: filteredPost.cid,\n val: 'dmca-violation',\n })\n\n // post with a gallery of images\n const galleryItems: Array<any> = []\n for (let i = 0; i < 10; i++) {\n galleryItems.push({\n $type: 'app.bsky.embed.gallery#image',\n image: uploadedImg.data.blob,\n alt: 'naughty ' + (i + 1),\n aspectRatio: {\n $type: 'app.bsky.embed.defs#aspectRatio',\n width: 10,\n height: 10,\n },\n })\n }\n const galleryPost = await bob.app.bsky.feed.post.create(\n { repo: bob.assertDid },\n {\n text: 'look at my cool pics',\n embed: {\n $type: 'app.bsky.embed.gallery',\n items: galleryItems,\n },\n createdAt: date.next().value,\n },\n )\n posts.push(galleryPost)\n\n // a set of replies\n for (let i = 0; i < 100; i++) {\n const targetUri = picka(posts).uri\n const urip = new AtUri(targetUri)\n const target = await alice.app.bsky.feed.post.get({\n repo: urip.host,\n rkey: urip.rkey,\n })\n const author = picka(userAgents)\n try {\n const post = await author.app.bsky.feed.post.create(\n { repo: author.did },\n {\n text: picka(replyTexts),\n reply: {\n root: target.value.reply?.root ?? target,\n parent: target,\n },\n createdAt: date.next().value,\n },\n )\n\n posts.push(post)\n } catch (err) {\n // @TODO Investigate why this sometimes fails.\n console.error('Failed to create reply', err)\n }\n }\n\n // a set of likes\n for (const post of posts) {\n for (const user of userAgents) {\n if (rand(3) === 0) {\n await user.app.bsky.feed.like.create(\n { repo: user.did },\n {\n subject: post,\n createdAt: date.next().value,\n },\n )\n }\n }\n }\n\n // a couple feed generators that returns some posts\n const fg1Uri = AtUri.make(\n alice.assertDid,\n 'app.bsky.feed.generator',\n 'alice-favs',\n )\n const fg1 = await env.createFeedGen({\n [fg1Uri.toString()]: async () => {\n const feed = posts\n .filter(() => rand(2) === 0)\n .map((post) => ({ post: post.uri as AtUriString }))\n return {\n encoding: 'application/json',\n body: {\n feed,\n },\n }\n },\n })\n const avatarImg = Buffer.from(blurHashB64, 'base64')\n const avatarRes = await alice.com.atproto.repo.uploadBlob(avatarImg, {\n encoding: 'image/png',\n })\n const fgAliceRes = await alice.app.bsky.feed.generator.create(\n { repo: alice.assertDid, rkey: fg1Uri.rkey },\n {\n did: fg1.did,\n displayName: 'alices feed',\n description: 'all my fav stuff',\n avatar: avatarRes.data.blob,\n createdAt: date.next().value,\n },\n )\n\n await alice.app.bsky.feed.post.create(\n { repo: alice.assertDid },\n {\n text: 'check out my algorithm!',\n embed: {\n $type: 'app.bsky.embed.record',\n record: fgAliceRes,\n },\n createdAt: date.next().value,\n },\n )\n for (const user of [alice, bob, carla]) {\n await user.app.bsky.feed.like.create(\n { repo: user.did },\n {\n subject: fgAliceRes,\n createdAt: date.next().value,\n },\n )\n }\n\n const fg2Uri = AtUri.make(\n bob.assertDid,\n 'app.bsky.feed.generator',\n 'bob-redux',\n )\n const fg2 = await env.createFeedGen({\n [fg2Uri.toString()]: async () => {\n const feed = posts\n .filter(() => rand(2) === 0)\n .map((post) => ({ post: post.uri as AtUriString }))\n return {\n encoding: 'application/json',\n body: {\n feed,\n },\n }\n },\n })\n const fgBobRes = await bob.app.bsky.feed.generator.create(\n { repo: bob.assertDid, rkey: fg2Uri.rkey },\n {\n did: fg2.did,\n displayName: 'Bobby boy hot new algo',\n createdAt: date.next().value,\n },\n )\n\n await alice.app.bsky.feed.post.create(\n { repo: alice.assertDid },\n {\n text: `bobs feed is neat too`,\n embed: {\n $type: 'app.bsky.embed.record',\n record: fgBobRes,\n },\n createdAt: date.next().value,\n },\n )\n\n const fg3Uri = AtUri.make(\n carla.assertDid,\n 'app.bsky.feed.generator',\n 'carla-intr-algo',\n )\n const fg3 = await env.createFeedGen({\n [fg3Uri.toString()]: async () => {\n const feed = posts\n .filter(() => rand(2) === 0)\n .map((post) => ({ post: post.uri as AtUriString }))\n return {\n encoding: 'application/json',\n body: {\n feed,\n },\n }\n },\n })\n const fgCarlaRes = await carla.app.bsky.feed.generator.create(\n { repo: carla.assertDid, rkey: fg3Uri.rkey },\n {\n did: fg3.did,\n displayName: `Acceptin' Generator`,\n acceptsInteractions: true,\n createdAt: date.next().value,\n },\n )\n\n await alice.app.bsky.feed.post.create(\n { repo: alice.assertDid },\n {\n text: `carla accepts interactions on her feed`,\n embed: {\n $type: 'app.bsky.embed.record',\n record: fgCarlaRes,\n },\n createdAt: date.next().value,\n },\n )\n\n // create labeler service\n {\n await labeler.app.bsky.labeler.service.create(\n { repo: labeler.did, rkey: 'self' },\n {\n policies: {\n labelValues: [\n '!hide',\n 'porn',\n 'rude',\n 'spam',\n 'spider',\n 'misinfo',\n 'cool',\n 'curate',\n ],\n labelValueDefinitions: [\n {\n identifier: 'rude',\n blurs: 'content',\n severity: 'alert',\n defaultSetting: 'warn',\n adultOnly: true,\n locales: [\n {\n lang: 'en',\n name: 'Rude',\n description: 'Just such a jerk, you wouldnt believe it.',\n },\n ],\n },\n {\n identifier: 'spam',\n blurs: 'content',\n severity: 'inform',\n defaultSetting: 'hide',\n locales: [\n {\n lang: 'en',\n name: 'Spam',\n description:\n 'Low quality posts that dont add to the conversation.',\n },\n ],\n },\n {\n identifier: 'spider',\n blurs: 'media',\n severity: 'alert',\n defaultSetting: 'warn',\n locales: [\n {\n lang: 'en',\n name: 'Spider!',\n description: 'Oh no its a spider.',\n },\n ],\n },\n {\n identifier: 'cool',\n blurs: 'none',\n severity: 'inform',\n defaultSetting: 'warn',\n locales: [\n {\n lang: 'en',\n name: 'Cool',\n description: 'The coolest peeps in the atmosphere.',\n },\n ],\n },\n {\n identifier: 'curate',\n blurs: 'none',\n severity: 'none',\n defaultSetting: 'warn',\n locales: [\n {\n lang: 'en',\n name: 'Curation filter',\n description: 'We just dont want to see it as much.',\n },\n ],\n },\n ],\n },\n createdAt: date.next().value,\n },\n )\n await createLabel(env.bsky.db, {\n uri: alice.assertDid,\n cid: '',\n val: 'rude',\n src: labeler.did,\n })\n await createLabel(env.bsky.db, {\n uri: `at://${alice.assertDid}/app.bsky.feed.generator/alice-favs`,\n cid: '',\n val: 'cool',\n src: labeler.did,\n })\n await createLabel(env.bsky.db, {\n uri: bob.assertDid,\n cid: '',\n val: 'cool',\n src: labeler.did,\n })\n await createLabel(env.bsky.db, {\n uri: carla.assertDid,\n cid: '',\n val: 'spam',\n src: labeler.did,\n })\n }\n\n // Create lists and add people to the lists\n {\n const flowerLovers = await alice.app.bsky.graph.list.create(\n { repo: alice.assertDid },\n {\n name: 'Flower Lovers',\n purpose: 'app.bsky.graph.defs#curatelist',\n createdAt: new Date().toISOString(),\n description: 'A list of posts about flowers',\n },\n )\n const labelHaters = await bob.app.bsky.graph.list.create(\n { repo: bob.assertDid },\n {\n name: 'Label Haters',\n purpose: 'app.bsky.graph.defs#modlist',\n createdAt: new Date().toISOString(),\n description: 'A list of people who hate labels',\n },\n )\n await alice.app.bsky.graph.listitem.create(\n { repo: alice.assertDid },\n {\n subject: bob.assertDid,\n createdAt: new Date().toISOString(),\n list: new RecordRef(flowerLovers.uri, flowerLovers.cid).uriStr,\n },\n )\n await bob.app.bsky.graph.listitem.create(\n { repo: bob.assertDid },\n {\n subject: alice.assertDid,\n createdAt: new Date().toISOString(),\n list: new RecordRef(labelHaters.uri, labelHaters.cid).uriStr,\n },\n )\n }\n\n await setVerifier(env.bsky.db, alice.assertDid)\n\n // @TODO These are useful when testing complex threads, but don't need to be enabled all the time. We could make it configurable.\n // import * as seedThreadV2 from '../seed/thread-v2.js'\n // const sc = env.getSeedClient()\n // await seedThreadV2.simple(sc)\n // await seedThreadV2.long(sc)\n // await seedThreadV2.deep(sc)\n // await seedThreadV2.branchingFactor(sc)\n // await seedThreadV2.annotateMoreReplies(sc)\n // await seedThreadV2.annotateOP(sc)\n // await seedThreadV2.sort(sc)\n // await seedThreadV2.bumpOpAndViewer(sc)\n // await seedThreadV2.bumpGroupSorting(sc)\n // await seedThreadV2.bumpFollows(sc)\n // await seedThreadV2.blockDeletionAuth(sc, env.bsky.ctx.cfg.modServiceDid)\n // await seedThreadV2.mutes(sc)\n // await seedThreadV2.threadgated(sc)\n // await seedThreadV2.tags(sc)\n}\n\nconst createLabel = async (\n db: Database,\n opts: { uri: string; cid: string; val: string; src?: string },\n) => {\n await db.db\n .insertInto('label')\n .values({\n uri: opts.uri,\n cid: opts.cid,\n val: opts.val,\n cts: new Date().toISOString(),\n neg: false,\n src: opts.src ?? EXAMPLE_LABELER,\n })\n .execute()\n}\n\nconst setVerifier = async (db: Database, did: string) => {\n await db.db\n .updateTable('actor')\n .set({ trustedVerifier: true })\n .where('did', '=', did)\n .execute()\n}\n"]}