forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {createServer as createHTTPServer} from 'node:http'
2import {parse} from 'node:url'
3
4import {createServer, type TestPDS} from '../jest/test-pds'
5
6async function main() {
7 let server: TestPDS
8 createHTTPServer(async (req, res) => {
9 const url = parse(req.url || '/', true)
10 if (req.method !== 'POST') {
11 return res.writeHead(200).end()
12 }
13 try {
14 console.log('Closing old server')
15 await server?.close()
16 console.log('Starting new server')
17 const inviteRequired = url?.query && 'invite' in url.query
18 server = await createServer({inviteRequired})
19 console.log('Listening at', server.pdsUrl)
20 if (url?.query) {
21 if ('users' in url.query) {
22 console.log('Generating mock users')
23 await server.mocker.createUser('alice')
24 await server.mocker.createUser('bob')
25 await server.mocker.createUser('carla')
26 await server.mocker.users.alice.agent.upsertProfile(() => ({
27 displayName: 'Alice',
28 description: 'Test user 1',
29 }))
30 await server.mocker.users.bob.agent.upsertProfile(() => ({
31 displayName: 'Bob',
32 description: 'Test user 2',
33 }))
34 await server.mocker.users.carla.agent.upsertProfile(() => ({
35 displayName: 'Carla',
36 description: 'Test user 3',
37 }))
38 if (inviteRequired) {
39 await server.mocker.createInvite(server.mocker.users.alice.did)
40 }
41 }
42 if ('follows' in url.query) {
43 console.log('Generating mock follows')
44 await server.mocker.follow('alice', 'bob')
45 await server.mocker.follow('alice', 'carla')
46 await server.mocker.follow('bob', 'alice')
47 await server.mocker.follow('bob', 'carla')
48 await server.mocker.follow('carla', 'alice')
49 await server.mocker.follow('carla', 'bob')
50 }
51 if ('posts' in url.query) {
52 console.log('Generating mock posts')
53 for (let user in server.mocker.users) {
54 await server.mocker.users[user].agent.post({text: 'Post'})
55 }
56 }
57 if ('feeds' in url.query) {
58 console.log('Generating mock feed')
59 await server.mocker.createFeed('alice', 'alice-favs', [])
60 }
61 if ('thread' in url.query) {
62 console.log('Generating mock posts')
63 const res = await server.mocker.users.bob.agent.post({
64 text: 'Thread root',
65 })
66 await server.mocker.users.carla.agent.post({
67 text: 'Thread reply',
68 reply: {
69 parent: {cid: res.cid, uri: res.uri},
70 root: {cid: res.cid, uri: res.uri},
71 },
72 })
73 }
74 if ('mergefeed' in url.query) {
75 console.log('Generating mock users')
76 await server.mocker.createUser('alice')
77 await server.mocker.createUser('bob')
78 await server.mocker.createUser('carla')
79 await server.mocker.createUser('dan')
80 await server.mocker.users.alice.agent.upsertProfile(() => ({
81 displayName: 'Alice',
82 description: 'Test user 1',
83 }))
84 await server.mocker.users.bob.agent.upsertProfile(() => ({
85 displayName: 'Bob',
86 description: 'Test user 2',
87 }))
88 await server.mocker.users.carla.agent.upsertProfile(() => ({
89 displayName: 'Carla',
90 description: 'Test user 3',
91 }))
92 await server.mocker.users.dan.agent.upsertProfile(() => ({
93 displayName: 'Dan',
94 description: 'Test user 4',
95 }))
96 console.log('Generating mock follows')
97 await server.mocker.follow('alice', 'bob')
98 await server.mocker.follow('alice', 'carla')
99 console.log('Generating mock posts')
100 let posts: Record<string, any[]> = {
101 alice: [],
102 bob: [],
103 carla: [],
104 dan: [],
105 }
106 for (let i = 0; i < 10; i++) {
107 for (let user in server.mocker.users) {
108 if (user === 'alice') continue
109 posts[user].push(
110 await server.mocker.createPost(user, `Post ${i}`),
111 )
112 }
113 }
114 for (let i = 0; i < 10; i++) {
115 for (let user in server.mocker.users) {
116 if (user === 'alice') continue
117 if (i % 5 === 0) {
118 await server.mocker.createReply(user, 'Self reply', {
119 cid: posts[user][i].cid,
120 uri: posts[user][i].uri,
121 })
122 }
123 if (i % 5 === 1) {
124 await server.mocker.createReply(user, 'Reply to bob', {
125 cid: posts.bob[i].cid,
126 uri: posts.bob[i].uri,
127 })
128 }
129 if (i % 5 === 2) {
130 await server.mocker.createReply(user, 'Reply to dan', {
131 cid: posts.dan[i].cid,
132 uri: posts.dan[i].uri,
133 })
134 }
135 await server.mocker.users[user].agent.post({text: `Post ${i}`})
136 }
137 }
138 console.log('Generating mock feeds')
139 await server.mocker.createFeed(
140 'alice',
141 'alice-favs',
142 posts.dan.map(p => p.uri),
143 )
144 await server.mocker.createFeed(
145 'alice',
146 'alice-favs2',
147 posts.dan.map(p => p.uri),
148 )
149 }
150 if ('labels' in url.query) {
151 console.log('Generating naughty users with labels')
152
153 const anchorPost = await server.mocker.createPost(
154 'alice',
155 'Anchor post',
156 )
157
158 for (const user of [
159 'dmca-account',
160 'dmca-profile',
161 'dmca-posts',
162 'porn-account',
163 'porn-profile',
164 'porn-posts',
165 'nudity-account',
166 'nudity-profile',
167 'nudity-posts',
168 'scam-account',
169 'scam-profile',
170 'scam-posts',
171 'unknown-account',
172 'unknown-profile',
173 'unknown-posts',
174 'hide-account',
175 'hide-profile',
176 'hide-posts',
177 'no-promote-account',
178 'no-promote-profile',
179 'no-promote-posts',
180 'warn-account',
181 'warn-profile',
182 'warn-posts',
183 'muted-account',
184 'muted-by-list-acc',
185 'blocking-account',
186 'blockedby-account',
187 'mutual-block-acc',
188 ]) {
189 await server.mocker.createUser(user)
190 await server.mocker.follow('alice', user)
191 await server.mocker.follow(user, 'alice')
192 await server.mocker.createPost(user, `Unlabeled post from ${user}`)
193 await server.mocker.createReply(
194 user,
195 `Unlabeled reply from ${user}`,
196 anchorPost,
197 )
198 await server.mocker.like(user, anchorPost)
199 }
200
201 await server.mocker.labelAccount('dmca-violation', 'dmca-account')
202 await server.mocker.labelProfile('dmca-violation', 'dmca-profile')
203 await server.mocker.labelPost(
204 'dmca-violation',
205 await server.mocker.createPost('dmca-posts', 'dmca post'),
206 )
207 await server.mocker.labelPost(
208 'dmca-violation',
209 await server.mocker.createQuotePost(
210 'dmca-posts',
211 'dmca quote post',
212 anchorPost,
213 ),
214 )
215 await server.mocker.labelPost(
216 'dmca-violation',
217 await server.mocker.createReply(
218 'dmca-posts',
219 'dmca reply',
220 anchorPost,
221 ),
222 )
223
224 await server.mocker.labelAccount('porn', 'porn-account')
225 await server.mocker.labelProfile('porn', 'porn-profile')
226 await server.mocker.labelPost(
227 'porn',
228 await server.mocker.createImagePost('porn-posts', 'porn post'),
229 )
230 await server.mocker.labelPost(
231 'porn',
232 await server.mocker.createQuotePost(
233 'porn-posts',
234 'porn quote post',
235 anchorPost,
236 ),
237 )
238 await server.mocker.labelPost(
239 'porn',
240 await server.mocker.createReply(
241 'porn-posts',
242 'porn reply',
243 anchorPost,
244 ),
245 )
246
247 await server.mocker.labelAccount('nudity', 'nudity-account')
248 await server.mocker.labelProfile('nudity', 'nudity-profile')
249 await server.mocker.labelPost(
250 'nudity',
251 await server.mocker.createImagePost('nudity-posts', 'nudity post'),
252 )
253 await server.mocker.labelPost(
254 'nudity',
255 await server.mocker.createQuotePost(
256 'nudity-posts',
257 'nudity quote post',
258 anchorPost,
259 ),
260 )
261 await server.mocker.labelPost(
262 'nudity',
263 await server.mocker.createReply(
264 'nudity-posts',
265 'nudity reply',
266 anchorPost,
267 ),
268 )
269
270 await server.mocker.labelAccount('scam', 'scam-account')
271 await server.mocker.labelProfile('scam', 'scam-profile')
272 await server.mocker.labelPost(
273 'scam',
274 await server.mocker.createPost('scam-posts', 'scam post'),
275 )
276 await server.mocker.labelPost(
277 'scam',
278 await server.mocker.createQuotePost(
279 'scam-posts',
280 'scam quote post',
281 anchorPost,
282 ),
283 )
284 await server.mocker.labelPost(
285 'scam',
286 await server.mocker.createReply(
287 'scam-posts',
288 'scam reply',
289 anchorPost,
290 ),
291 )
292
293 await server.mocker.labelAccount(
294 'not-a-real-label',
295 'unknown-account',
296 )
297 await server.mocker.labelProfile(
298 'not-a-real-label',
299 'unknown-profile',
300 )
301 await server.mocker.labelPost(
302 'not-a-real-label',
303 await server.mocker.createPost('unknown-posts', 'unknown post'),
304 )
305 await server.mocker.labelPost(
306 'not-a-real-label',
307 await server.mocker.createQuotePost(
308 'unknown-posts',
309 'unknown quote post',
310 anchorPost,
311 ),
312 )
313 await server.mocker.labelPost(
314 'not-a-real-label',
315 await server.mocker.createReply(
316 'unknown-posts',
317 'unknown reply',
318 anchorPost,
319 ),
320 )
321
322 await server.mocker.labelAccount('!hide', 'hide-account')
323 await server.mocker.labelProfile('!hide', 'hide-profile')
324 await server.mocker.labelPost(
325 '!hide',
326 await server.mocker.createPost('hide-posts', 'hide post'),
327 )
328 await server.mocker.labelPost(
329 '!hide',
330 await server.mocker.createQuotePost(
331 'hide-posts',
332 'hide quote post',
333 anchorPost,
334 ),
335 )
336 await server.mocker.labelPost(
337 '!hide',
338 await server.mocker.createReply(
339 'hide-posts',
340 'hide reply',
341 anchorPost,
342 ),
343 )
344
345 await server.mocker.labelAccount('!no-promote', 'no-promote-account')
346 await server.mocker.labelProfile('!no-promote', 'no-promote-profile')
347 await server.mocker.labelPost(
348 '!no-promote',
349 await server.mocker.createPost(
350 'no-promote-posts',
351 'no-promote post',
352 ),
353 )
354 await server.mocker.labelPost(
355 '!no-promote',
356 await server.mocker.createQuotePost(
357 'no-promote-posts',
358 'no-promote quote post',
359 anchorPost,
360 ),
361 )
362 await server.mocker.labelPost(
363 '!no-promote',
364 await server.mocker.createReply(
365 'no-promote-posts',
366 'no-promote reply',
367 anchorPost,
368 ),
369 )
370
371 await server.mocker.labelAccount('!warn', 'warn-account')
372 await server.mocker.labelProfile('!warn', 'warn-profile')
373 await server.mocker.labelPost(
374 '!warn',
375 await server.mocker.createPost('warn-posts', 'warn post'),
376 )
377 await server.mocker.labelPost(
378 '!warn',
379 await server.mocker.createQuotePost(
380 'warn-posts',
381 'warn quote post',
382 anchorPost,
383 ),
384 )
385 await server.mocker.labelPost(
386 '!warn',
387 await server.mocker.createReply(
388 'warn-posts',
389 'warn reply',
390 anchorPost,
391 ),
392 )
393
394 await server.mocker.users.alice.agent.mute('muted-account.test')
395 await server.mocker.createPost('muted-account', 'muted post')
396 await server.mocker.createQuotePost(
397 'muted-account',
398 'muted quote post',
399 anchorPost,
400 )
401 await server.mocker.createReply(
402 'muted-account',
403 'muted reply',
404 anchorPost,
405 )
406
407 const list = await server.mocker.createMuteList(
408 'alice',
409 'Muted Users',
410 )
411 await server.mocker.addToMuteList(
412 'alice',
413 list,
414 server.mocker.users['muted-by-list-acc'].did,
415 )
416 await server.mocker.createPost('muted-by-list-acc', 'muted post')
417 await server.mocker.createQuotePost(
418 'muted-by-list-acc',
419 'account quote post',
420 anchorPost,
421 )
422 await server.mocker.createReply(
423 'muted-by-list-acc',
424 'account reply',
425 anchorPost,
426 )
427
428 await server.mocker.createPost('blocking-account', 'blocking post')
429 await server.mocker.createQuotePost(
430 'blocking-account',
431 'blocking quote post',
432 anchorPost,
433 )
434 await server.mocker.createReply(
435 'blocking-account',
436 'blocking reply',
437 anchorPost,
438 )
439 await server.mocker.users.alice.agent.app.bsky.graph.block.create(
440 {
441 repo: server.mocker.users.alice.did,
442 },
443 {
444 subject: server.mocker.users['blocking-account'].did,
445 createdAt: new Date().toISOString(),
446 },
447 )
448
449 await server.mocker.createPost('blockedby-account', 'blockedby post')
450 await server.mocker.createQuotePost(
451 'blockedby-account',
452 'blockedby quote post',
453 anchorPost,
454 )
455 await server.mocker.createReply(
456 'blockedby-account',
457 'blockedby reply',
458 anchorPost,
459 )
460 await server.mocker.users[
461 'blockedby-account'
462 ].agent.app.bsky.graph.block.create(
463 {
464 repo: server.mocker.users['blockedby-account'].did,
465 },
466 {
467 subject: server.mocker.users.alice.did,
468 createdAt: new Date().toISOString(),
469 },
470 )
471
472 await server.mocker.createPost(
473 'mutual-block-acc',
474 'mutual-block post',
475 )
476 await server.mocker.createQuotePost(
477 'mutual-block-acc',
478 'mutual-block quote post',
479 anchorPost,
480 )
481 await server.mocker.createReply(
482 'mutual-block-acc',
483 'mutual-block reply',
484 anchorPost,
485 )
486 await server.mocker.users.alice.agent.app.bsky.graph.block.create(
487 {
488 repo: server.mocker.users.alice.did,
489 },
490 {
491 subject: server.mocker.users['mutual-block-acc'].did,
492 createdAt: new Date().toISOString(),
493 },
494 )
495 await server.mocker.users[
496 'mutual-block-acc'
497 ].agent.app.bsky.graph.block.create(
498 {
499 repo: server.mocker.users['mutual-block-acc'].did,
500 },
501 {
502 subject: server.mocker.users.alice.did,
503 createdAt: new Date().toISOString(),
504 },
505 )
506
507 // flush caches
508 await server.mocker.testNet.processAll()
509 }
510 }
511 console.log('Ready')
512 return res
513 .writeHead(200, {
514 'content-type': 'application/json',
515 })
516 .end(
517 JSON.stringify({
518 pdsUrl: server.pdsUrl,
519 appviewDid: server.appviewDid,
520 }),
521 )
522 } catch (e) {
523 console.error('Error!', e)
524 return res.writeHead(500).end()
525 }
526 }).listen(1986)
527 console.log('Mock server manager listening on 1986')
528}
529main()