@evanp/activitypub-bot 0.13.0 → 0.13.2
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/package.json +2 -2
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/main.yml +0 -34
- package/.github/workflows/tag.yml +0 -106
- package/.nvmrc +0 -1
- package/Dockerfile +0 -17
- package/docs/activitypub.bot.drawio +0 -110
- package/tests/activitydistributor.test.js +0 -606
- package/tests/activityhandler.test.js +0 -2276
- package/tests/activitypubclient.test.js +0 -210
- package/tests/actorstorage.test.js +0 -283
- package/tests/app.test.js +0 -17
- package/tests/authorizer.test.js +0 -301
- package/tests/bot.donothing.test.js +0 -30
- package/tests/bot.ok.test.js +0 -101
- package/tests/botcontext.test.js +0 -720
- package/tests/botdatastorage.test.js +0 -88
- package/tests/botfactory.provincebotfactory.test.js +0 -430
- package/tests/digester.test.js +0 -56
- package/tests/fixtures/bots.js +0 -27
- package/tests/fixtures/eventloggingbot.js +0 -57
- package/tests/fixtures/provincebotfactory.js +0 -53
- package/tests/httpsignature.test.js +0 -199
- package/tests/httpsignatureauthenticator.test.js +0 -463
- package/tests/index.test.js +0 -12
- package/tests/keystorage.test.js +0 -124
- package/tests/microsyntax.test.js +0 -123
- package/tests/objectcache.test.js +0 -133
- package/tests/objectstorage.test.js +0 -149
- package/tests/remotekeystorage.test.js +0 -78
- package/tests/routes.actor.test.js +0 -214
- package/tests/routes.collection.test.js +0 -310
- package/tests/routes.health.test.js +0 -41
- package/tests/routes.inbox.test.js +0 -216
- package/tests/routes.object.test.js +0 -525
- package/tests/routes.server.test.js +0 -69
- package/tests/routes.sharedinbox.test.js +0 -473
- package/tests/routes.webfinger.test.js +0 -68
- package/tests/urlformatter.test.js +0 -164
- package/tests/utils/digest.js +0 -7
- package/tests/utils/nock.js +0 -499
|
@@ -1,473 +0,0 @@
|
|
|
1
|
-
import { describe, it, before } from 'node:test'
|
|
2
|
-
import assert from 'node:assert'
|
|
3
|
-
import as2 from '../lib/activitystreams.js'
|
|
4
|
-
import request from 'supertest'
|
|
5
|
-
|
|
6
|
-
import { makeApp } from '../lib/app.js'
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
nockSetup,
|
|
10
|
-
nockSignature,
|
|
11
|
-
nockFormat,
|
|
12
|
-
makeActor,
|
|
13
|
-
addFollower,
|
|
14
|
-
addFollowing,
|
|
15
|
-
addToCollection
|
|
16
|
-
} from './utils/nock.js'
|
|
17
|
-
import { makeDigest } from './utils/digest.js'
|
|
18
|
-
import bots from './fixtures/bots.js'
|
|
19
|
-
|
|
20
|
-
describe('routes.sharedinbox', async () => {
|
|
21
|
-
const host = 'activitypubbot.test'
|
|
22
|
-
const remoteHost = 'social.example'
|
|
23
|
-
const origin = `https://${host}`
|
|
24
|
-
const databaseUrl = 'sqlite::memory:'
|
|
25
|
-
let app = null
|
|
26
|
-
let formatter = null
|
|
27
|
-
let actorStorage = null
|
|
28
|
-
|
|
29
|
-
before(async () => {
|
|
30
|
-
nockSetup(remoteHost)
|
|
31
|
-
app = await makeApp(databaseUrl, origin, bots, 'silent')
|
|
32
|
-
formatter = app.locals.formatter
|
|
33
|
-
actorStorage = app.locals.actorStorage
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
describe('can handle an directly addressed activity', async () => {
|
|
37
|
-
const username = 'actor1'
|
|
38
|
-
const botName = 'test0'
|
|
39
|
-
const path = '/shared/inbox'
|
|
40
|
-
const url = `${origin}${path}`
|
|
41
|
-
const date = new Date().toUTCString()
|
|
42
|
-
let response = null
|
|
43
|
-
let signature = null
|
|
44
|
-
let body = null
|
|
45
|
-
let digest = null
|
|
46
|
-
let activity = null
|
|
47
|
-
before(async () => {
|
|
48
|
-
activity = await as2.import({
|
|
49
|
-
type: 'Activity',
|
|
50
|
-
actor: nockFormat({ username }),
|
|
51
|
-
id: nockFormat({ username, type: 'activity', num: 1 }),
|
|
52
|
-
to: formatter.format({ username: botName })
|
|
53
|
-
})
|
|
54
|
-
body = await activity.write()
|
|
55
|
-
digest = makeDigest(body)
|
|
56
|
-
signature = await nockSignature({
|
|
57
|
-
method: 'POST',
|
|
58
|
-
username,
|
|
59
|
-
url,
|
|
60
|
-
digest,
|
|
61
|
-
date
|
|
62
|
-
})
|
|
63
|
-
})
|
|
64
|
-
it('should work without an error', async () => {
|
|
65
|
-
response = await request(app)
|
|
66
|
-
.post(path)
|
|
67
|
-
.send(body)
|
|
68
|
-
.set('Signature', signature)
|
|
69
|
-
.set('Date', date)
|
|
70
|
-
.set('Host', host)
|
|
71
|
-
.set('Digest', digest)
|
|
72
|
-
.set('Content-Type', 'application/activity+json')
|
|
73
|
-
assert.ok(response)
|
|
74
|
-
await app.onIdle()
|
|
75
|
-
})
|
|
76
|
-
it('should return a 200 status', async () => {
|
|
77
|
-
assert.strictEqual(response.status, 200)
|
|
78
|
-
})
|
|
79
|
-
it('should appear in the inbox', async () => {
|
|
80
|
-
assert.strictEqual(
|
|
81
|
-
true,
|
|
82
|
-
await actorStorage.isInCollection(
|
|
83
|
-
botName,
|
|
84
|
-
'inbox',
|
|
85
|
-
activity
|
|
86
|
-
)
|
|
87
|
-
)
|
|
88
|
-
})
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
describe('can handle an followers-only activity', async () => {
|
|
92
|
-
const username = 'actor2'
|
|
93
|
-
const botNames = ['test1', 'test2']
|
|
94
|
-
const path = '/shared/inbox'
|
|
95
|
-
const url = `${origin}${path}`
|
|
96
|
-
const date = new Date().toUTCString()
|
|
97
|
-
let response = null
|
|
98
|
-
let signature = null
|
|
99
|
-
let body = null
|
|
100
|
-
let digest = null
|
|
101
|
-
let activity = null
|
|
102
|
-
let actor = null
|
|
103
|
-
before(async () => {
|
|
104
|
-
actor = await makeActor(username, remoteHost)
|
|
105
|
-
for (const botName of botNames) {
|
|
106
|
-
const botId = formatter.format({ username: botName })
|
|
107
|
-
addFollower(username, botId, remoteHost)
|
|
108
|
-
await actorStorage.addToCollection(botName, 'following', actor)
|
|
109
|
-
}
|
|
110
|
-
activity = await as2.import({
|
|
111
|
-
type: 'Activity',
|
|
112
|
-
actor: actor.id,
|
|
113
|
-
id: nockFormat({ username, type: 'activity', num: 1 }),
|
|
114
|
-
to: nockFormat({ username, collection: 'followers' })
|
|
115
|
-
})
|
|
116
|
-
body = await activity.write()
|
|
117
|
-
digest = makeDigest(body)
|
|
118
|
-
signature = await nockSignature({
|
|
119
|
-
method: 'POST',
|
|
120
|
-
username,
|
|
121
|
-
url,
|
|
122
|
-
digest,
|
|
123
|
-
date
|
|
124
|
-
})
|
|
125
|
-
})
|
|
126
|
-
it('should work without an error', async () => {
|
|
127
|
-
response = await request(app)
|
|
128
|
-
.post(path)
|
|
129
|
-
.send(body)
|
|
130
|
-
.set('Signature', signature)
|
|
131
|
-
.set('Date', date)
|
|
132
|
-
.set('Host', host)
|
|
133
|
-
.set('Digest', digest)
|
|
134
|
-
.set('Content-Type', 'application/activity+json')
|
|
135
|
-
assert.ok(response)
|
|
136
|
-
await app.onIdle()
|
|
137
|
-
})
|
|
138
|
-
it('should return a 200 status', async () => {
|
|
139
|
-
assert.strictEqual(response.status, 200)
|
|
140
|
-
})
|
|
141
|
-
it('should appear in all inboxes', async () => {
|
|
142
|
-
for (const botName of botNames) {
|
|
143
|
-
assert.strictEqual(
|
|
144
|
-
true,
|
|
145
|
-
await actorStorage.isInCollection(
|
|
146
|
-
botName,
|
|
147
|
-
'inbox',
|
|
148
|
-
activity
|
|
149
|
-
)
|
|
150
|
-
)
|
|
151
|
-
}
|
|
152
|
-
})
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
describe('can handle an public activity', async () => {
|
|
156
|
-
const username = 'actor3'
|
|
157
|
-
const path = '/shared/inbox'
|
|
158
|
-
const url = `${origin}${path}`
|
|
159
|
-
const date = new Date().toUTCString()
|
|
160
|
-
let response = null
|
|
161
|
-
let signature = null
|
|
162
|
-
let body = null
|
|
163
|
-
let digest = null
|
|
164
|
-
let activity = null
|
|
165
|
-
let actor = null
|
|
166
|
-
before(async () => {
|
|
167
|
-
actor = await makeActor(username, remoteHost)
|
|
168
|
-
activity = await as2.import({
|
|
169
|
-
type: 'Activity',
|
|
170
|
-
actor: actor.id,
|
|
171
|
-
id: nockFormat({ username, type: 'activity', num: 1 }),
|
|
172
|
-
to: 'as:Public'
|
|
173
|
-
})
|
|
174
|
-
body = await activity.write()
|
|
175
|
-
digest = makeDigest(body)
|
|
176
|
-
signature = await nockSignature({
|
|
177
|
-
method: 'POST',
|
|
178
|
-
username,
|
|
179
|
-
url,
|
|
180
|
-
digest,
|
|
181
|
-
date
|
|
182
|
-
})
|
|
183
|
-
})
|
|
184
|
-
it('should work without an error', async () => {
|
|
185
|
-
response = await request(app)
|
|
186
|
-
.post(path)
|
|
187
|
-
.send(body)
|
|
188
|
-
.set('Signature', signature)
|
|
189
|
-
.set('Date', date)
|
|
190
|
-
.set('Host', host)
|
|
191
|
-
.set('Digest', digest)
|
|
192
|
-
.set('Content-Type', 'application/activity+json')
|
|
193
|
-
assert.ok(response)
|
|
194
|
-
await app.onIdle()
|
|
195
|
-
})
|
|
196
|
-
it('should return a 200 status', async () => {
|
|
197
|
-
assert.strictEqual(response.status, 200)
|
|
198
|
-
})
|
|
199
|
-
it('should appear in all inboxes', async () => {
|
|
200
|
-
const lb = bots.logging
|
|
201
|
-
assert.ok(lb.publics.has(activity.id))
|
|
202
|
-
})
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
describe('can handle an activity to local followers collection', async () => {
|
|
206
|
-
const username = 'actor4'
|
|
207
|
-
const botNames = ['test3', 'test4', 'test5']
|
|
208
|
-
const followedBot = 'test6'
|
|
209
|
-
const path = '/shared/inbox'
|
|
210
|
-
const url = `${origin}${path}`
|
|
211
|
-
const date = new Date().toUTCString()
|
|
212
|
-
let response = null
|
|
213
|
-
let signature = null
|
|
214
|
-
let body = null
|
|
215
|
-
let digest = null
|
|
216
|
-
let activity = null
|
|
217
|
-
let actor = null
|
|
218
|
-
before(async () => {
|
|
219
|
-
actor = await makeActor(username, remoteHost)
|
|
220
|
-
const followed = await as2.import({
|
|
221
|
-
id: formatter.format({ username: followedBot })
|
|
222
|
-
})
|
|
223
|
-
for (const botName of botNames) {
|
|
224
|
-
const botId = formatter.format({ username: botName })
|
|
225
|
-
const bot = await as2.import({ id: botId })
|
|
226
|
-
await actorStorage.addToCollection(followedBot, 'followers', bot)
|
|
227
|
-
await actorStorage.addToCollection(botName, 'following', followed)
|
|
228
|
-
}
|
|
229
|
-
activity = await as2.import({
|
|
230
|
-
type: 'Activity',
|
|
231
|
-
actor: actor.id,
|
|
232
|
-
id: nockFormat({ username, type: 'activity', num: 1 }),
|
|
233
|
-
to: formatter.format({ username: followedBot, collection: 'followers' })
|
|
234
|
-
})
|
|
235
|
-
body = await activity.write()
|
|
236
|
-
digest = makeDigest(body)
|
|
237
|
-
signature = await nockSignature({
|
|
238
|
-
method: 'POST',
|
|
239
|
-
username,
|
|
240
|
-
url,
|
|
241
|
-
digest,
|
|
242
|
-
date
|
|
243
|
-
})
|
|
244
|
-
})
|
|
245
|
-
it('should work without an error', async () => {
|
|
246
|
-
response = await request(app)
|
|
247
|
-
.post(path)
|
|
248
|
-
.send(body)
|
|
249
|
-
.set('Signature', signature)
|
|
250
|
-
.set('Date', date)
|
|
251
|
-
.set('Host', host)
|
|
252
|
-
.set('Digest', digest)
|
|
253
|
-
.set('Content-Type', 'application/activity+json')
|
|
254
|
-
assert.ok(response)
|
|
255
|
-
await app.onIdle()
|
|
256
|
-
})
|
|
257
|
-
it('should return a 200 status', async () => {
|
|
258
|
-
assert.strictEqual(response.status, 200)
|
|
259
|
-
})
|
|
260
|
-
it('should appear in all inboxes', async () => {
|
|
261
|
-
for (const botName of botNames) {
|
|
262
|
-
assert.strictEqual(
|
|
263
|
-
true,
|
|
264
|
-
await actorStorage.isInCollection(
|
|
265
|
-
botName,
|
|
266
|
-
'inbox',
|
|
267
|
-
activity
|
|
268
|
-
)
|
|
269
|
-
)
|
|
270
|
-
}
|
|
271
|
-
})
|
|
272
|
-
})
|
|
273
|
-
|
|
274
|
-
describe('can handle an activity to local following collection', async () => {
|
|
275
|
-
const username = 'actor5'
|
|
276
|
-
const botNames = ['test7', 'test8']
|
|
277
|
-
const followingBot = 'test9'
|
|
278
|
-
const path = '/shared/inbox'
|
|
279
|
-
const url = `${origin}${path}`
|
|
280
|
-
const date = new Date().toUTCString()
|
|
281
|
-
let response = null
|
|
282
|
-
let signature = null
|
|
283
|
-
let body = null
|
|
284
|
-
let digest = null
|
|
285
|
-
let activity = null
|
|
286
|
-
let actor = null
|
|
287
|
-
before(async () => {
|
|
288
|
-
actor = await makeActor(username, remoteHost)
|
|
289
|
-
const following = await as2.import({
|
|
290
|
-
id: formatter.format({ username: followingBot })
|
|
291
|
-
})
|
|
292
|
-
for (const botName of botNames) {
|
|
293
|
-
const botId = formatter.format({ username: botName })
|
|
294
|
-
const bot = await as2.import({ id: botId })
|
|
295
|
-
await actorStorage.addToCollection(followingBot, 'following', bot)
|
|
296
|
-
await actorStorage.addToCollection(botName, 'followers', following)
|
|
297
|
-
}
|
|
298
|
-
activity = await as2.import({
|
|
299
|
-
type: 'Activity',
|
|
300
|
-
actor: actor.id,
|
|
301
|
-
id: nockFormat({ username, type: 'activity', num: 1 }),
|
|
302
|
-
to: formatter.format({
|
|
303
|
-
username: followingBot,
|
|
304
|
-
collection: 'following'
|
|
305
|
-
})
|
|
306
|
-
})
|
|
307
|
-
body = await activity.write()
|
|
308
|
-
digest = makeDigest(body)
|
|
309
|
-
signature = await nockSignature({
|
|
310
|
-
method: 'POST',
|
|
311
|
-
username,
|
|
312
|
-
url,
|
|
313
|
-
digest,
|
|
314
|
-
date
|
|
315
|
-
})
|
|
316
|
-
})
|
|
317
|
-
it('should work without an error', async () => {
|
|
318
|
-
response = await request(app)
|
|
319
|
-
.post(path)
|
|
320
|
-
.send(body)
|
|
321
|
-
.set('Signature', signature)
|
|
322
|
-
.set('Date', date)
|
|
323
|
-
.set('Host', host)
|
|
324
|
-
.set('Digest', digest)
|
|
325
|
-
.set('Content-Type', 'application/activity+json')
|
|
326
|
-
assert.ok(response)
|
|
327
|
-
await app.onIdle()
|
|
328
|
-
})
|
|
329
|
-
it('should return a 200 status', async () => {
|
|
330
|
-
assert.strictEqual(response.status, 200)
|
|
331
|
-
})
|
|
332
|
-
it('should appear in all inboxes', async () => {
|
|
333
|
-
for (const botName of botNames) {
|
|
334
|
-
assert.strictEqual(
|
|
335
|
-
true,
|
|
336
|
-
await actorStorage.isInCollection(
|
|
337
|
-
botName,
|
|
338
|
-
'inbox',
|
|
339
|
-
activity
|
|
340
|
-
)
|
|
341
|
-
)
|
|
342
|
-
}
|
|
343
|
-
})
|
|
344
|
-
})
|
|
345
|
-
|
|
346
|
-
describe('can handle an activity to remote following collection', async () => {
|
|
347
|
-
const username = 'actor6'
|
|
348
|
-
const botNames = ['test10', 'test11', 'test12']
|
|
349
|
-
const path = '/shared/inbox'
|
|
350
|
-
const url = `${origin}${path}`
|
|
351
|
-
const date = new Date().toUTCString()
|
|
352
|
-
let response = null
|
|
353
|
-
let signature = null
|
|
354
|
-
let body = null
|
|
355
|
-
let digest = null
|
|
356
|
-
let activity = null
|
|
357
|
-
let actor = null
|
|
358
|
-
before(async () => {
|
|
359
|
-
actor = await makeActor(username, remoteHost)
|
|
360
|
-
for (const botName of botNames) {
|
|
361
|
-
const botId = formatter.format({ username: botName })
|
|
362
|
-
addFollowing(username, botId, remoteHost)
|
|
363
|
-
await actorStorage.addToCollection(botName, 'followers', actor)
|
|
364
|
-
}
|
|
365
|
-
activity = await as2.import({
|
|
366
|
-
type: 'Activity',
|
|
367
|
-
actor: actor.id,
|
|
368
|
-
id: nockFormat({ username, type: 'activity', num: 1 }),
|
|
369
|
-
to: nockFormat({ username, collection: 'following' })
|
|
370
|
-
})
|
|
371
|
-
body = await activity.write()
|
|
372
|
-
digest = makeDigest(body)
|
|
373
|
-
signature = await nockSignature({
|
|
374
|
-
method: 'POST',
|
|
375
|
-
username,
|
|
376
|
-
url,
|
|
377
|
-
digest,
|
|
378
|
-
date
|
|
379
|
-
})
|
|
380
|
-
})
|
|
381
|
-
it('should work without an error', async () => {
|
|
382
|
-
response = await request(app)
|
|
383
|
-
.post(path)
|
|
384
|
-
.send(body)
|
|
385
|
-
.set('Signature', signature)
|
|
386
|
-
.set('Date', date)
|
|
387
|
-
.set('Host', host)
|
|
388
|
-
.set('Digest', digest)
|
|
389
|
-
.set('Content-Type', 'application/activity+json')
|
|
390
|
-
assert.ok(response)
|
|
391
|
-
await app.onIdle()
|
|
392
|
-
})
|
|
393
|
-
it('should return a 200 status', async () => {
|
|
394
|
-
assert.strictEqual(response.status, 200)
|
|
395
|
-
})
|
|
396
|
-
it('should appear in all inboxes', async () => {
|
|
397
|
-
for (const botName of botNames) {
|
|
398
|
-
assert.strictEqual(
|
|
399
|
-
true,
|
|
400
|
-
await actorStorage.isInCollection(
|
|
401
|
-
botName,
|
|
402
|
-
'inbox',
|
|
403
|
-
activity
|
|
404
|
-
)
|
|
405
|
-
)
|
|
406
|
-
}
|
|
407
|
-
})
|
|
408
|
-
})
|
|
409
|
-
|
|
410
|
-
describe('can handle an activity to remote actor collection', async () => {
|
|
411
|
-
const username = 'actor7'
|
|
412
|
-
const botNames = ['test13', 'test14', 'test15']
|
|
413
|
-
const path = '/shared/inbox'
|
|
414
|
-
const url = `${origin}${path}`
|
|
415
|
-
const collection = 1
|
|
416
|
-
const date = new Date().toUTCString()
|
|
417
|
-
let response = null
|
|
418
|
-
let signature = null
|
|
419
|
-
let body = null
|
|
420
|
-
let digest = null
|
|
421
|
-
let activity = null
|
|
422
|
-
let actor = null
|
|
423
|
-
before(async () => {
|
|
424
|
-
actor = await makeActor(username, remoteHost)
|
|
425
|
-
for (const botName of botNames) {
|
|
426
|
-
const botId = formatter.format({ username: botName })
|
|
427
|
-
addToCollection(username, collection, botId, remoteHost)
|
|
428
|
-
}
|
|
429
|
-
activity = await as2.import({
|
|
430
|
-
type: 'Activity',
|
|
431
|
-
actor: actor.id,
|
|
432
|
-
id: nockFormat({ username, type: 'activity', num: 1 }),
|
|
433
|
-
to: nockFormat({ username, type: 'collection', num: collection })
|
|
434
|
-
})
|
|
435
|
-
body = await activity.write()
|
|
436
|
-
digest = makeDigest(body)
|
|
437
|
-
signature = await nockSignature({
|
|
438
|
-
method: 'POST',
|
|
439
|
-
username,
|
|
440
|
-
url,
|
|
441
|
-
digest,
|
|
442
|
-
date
|
|
443
|
-
})
|
|
444
|
-
})
|
|
445
|
-
it('should work without an error', async () => {
|
|
446
|
-
response = await request(app)
|
|
447
|
-
.post(path)
|
|
448
|
-
.send(body)
|
|
449
|
-
.set('Signature', signature)
|
|
450
|
-
.set('Date', date)
|
|
451
|
-
.set('Host', host)
|
|
452
|
-
.set('Digest', digest)
|
|
453
|
-
.set('Content-Type', 'application/activity+json')
|
|
454
|
-
assert.ok(response)
|
|
455
|
-
await app.onIdle()
|
|
456
|
-
})
|
|
457
|
-
it('should return a 200 status', async () => {
|
|
458
|
-
assert.strictEqual(response.status, 200)
|
|
459
|
-
})
|
|
460
|
-
it('should appear in all inboxes', async () => {
|
|
461
|
-
for (const botName of botNames) {
|
|
462
|
-
assert.strictEqual(
|
|
463
|
-
true,
|
|
464
|
-
await actorStorage.isInCollection(
|
|
465
|
-
botName,
|
|
466
|
-
'inbox',
|
|
467
|
-
activity
|
|
468
|
-
)
|
|
469
|
-
)
|
|
470
|
-
}
|
|
471
|
-
})
|
|
472
|
-
})
|
|
473
|
-
})
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test'
|
|
2
|
-
import assert from 'node:assert'
|
|
3
|
-
import { makeApp } from '../lib/app.js'
|
|
4
|
-
import request from 'supertest'
|
|
5
|
-
import bots from './fixtures/bots.js'
|
|
6
|
-
|
|
7
|
-
describe('webfinger routes', async () => {
|
|
8
|
-
const databaseUrl = 'sqlite::memory:'
|
|
9
|
-
const origin = 'https://activitypubbot.test'
|
|
10
|
-
const app = await makeApp(databaseUrl, origin, bots, 'silent')
|
|
11
|
-
describe('GET /.well-known/webfinger', async () => {
|
|
12
|
-
let response = null
|
|
13
|
-
it('should work without an error', async () => {
|
|
14
|
-
response = await request(app).get('/.well-known/webfinger?resource=acct%3Aok%40activitypubbot.test')
|
|
15
|
-
})
|
|
16
|
-
it('should return 200 OK', async () => {
|
|
17
|
-
assert.strictEqual(response.status, 200)
|
|
18
|
-
})
|
|
19
|
-
it('should return JRD', async () => {
|
|
20
|
-
assert.strictEqual(response.type, 'application/jrd+json')
|
|
21
|
-
})
|
|
22
|
-
it('should return an object with a subject', async () => {
|
|
23
|
-
assert.strictEqual(typeof response.body.subject, 'string')
|
|
24
|
-
})
|
|
25
|
-
it('should return an object with an subject matching the request', async () => {
|
|
26
|
-
assert.strictEqual(response.body.subject, 'acct:ok@activitypubbot.test')
|
|
27
|
-
})
|
|
28
|
-
it('should return an object with a links array', async () => {
|
|
29
|
-
assert.strictEqual(Array.isArray(response.body.links), true)
|
|
30
|
-
})
|
|
31
|
-
it('should return an object with a links array containing the actor id', async () => {
|
|
32
|
-
assert.strictEqual(response.body.links.length, 1)
|
|
33
|
-
assert.strictEqual(typeof response.body.links[0].rel, 'string')
|
|
34
|
-
assert.strictEqual(response.body.links[0].rel, 'self')
|
|
35
|
-
assert.strictEqual(typeof response.body.links[0].type, 'string')
|
|
36
|
-
assert.strictEqual(response.body.links[0].type, 'application/activity+json')
|
|
37
|
-
assert.strictEqual(typeof response.body.links[0].href, 'string')
|
|
38
|
-
assert.strictEqual(response.body.links[0].href, 'https://activitypubbot.test/user/ok')
|
|
39
|
-
})
|
|
40
|
-
})
|
|
41
|
-
describe('Webfinger discovery for non-existent user', async () => {
|
|
42
|
-
let response = null
|
|
43
|
-
it('should work without an error', async () => {
|
|
44
|
-
response = await request(app).get('/.well-known/webfinger?resource=acct%3Adne%40activitypubbot.test')
|
|
45
|
-
})
|
|
46
|
-
it('should return 404 Not Found', async () => {
|
|
47
|
-
assert.strictEqual(response.status, 404)
|
|
48
|
-
})
|
|
49
|
-
})
|
|
50
|
-
describe('Webfinger discovery for wrong domain', async () => {
|
|
51
|
-
let response = null
|
|
52
|
-
it('should work without an error', async () => {
|
|
53
|
-
response = await request(app).get('/.well-known/webfinger?resource=acct%3Adne%wrongdomain.test')
|
|
54
|
-
})
|
|
55
|
-
it('should return 400 Bad Request', async () => {
|
|
56
|
-
assert.strictEqual(response.status, 400)
|
|
57
|
-
})
|
|
58
|
-
})
|
|
59
|
-
describe('Webfinger discovery for HTTPS', async () => {
|
|
60
|
-
let response = null
|
|
61
|
-
it('should work without an error', async () => {
|
|
62
|
-
response = await request(app).get('/.well-known/webfinger?resource=' + encodeURIComponent('https://activitypubbot.test/user/ok'))
|
|
63
|
-
})
|
|
64
|
-
it('should return 400 Bad Request', async () => {
|
|
65
|
-
assert.strictEqual(response.status, 400)
|
|
66
|
-
})
|
|
67
|
-
})
|
|
68
|
-
})
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test'
|
|
2
|
-
import assert from 'node:assert'
|
|
3
|
-
import { UrlFormatter } from '../lib/urlformatter.js'
|
|
4
|
-
|
|
5
|
-
describe('UrlFormatter', () => {
|
|
6
|
-
const origin = 'https://activitypubbot.example'
|
|
7
|
-
let formatter = null
|
|
8
|
-
it('can initialize', () => {
|
|
9
|
-
formatter = new UrlFormatter(origin)
|
|
10
|
-
})
|
|
11
|
-
it('can format a user URL', () => {
|
|
12
|
-
const url = formatter.format({ username: 'megabot' })
|
|
13
|
-
assert.equal(url, 'https://activitypubbot.example/user/megabot')
|
|
14
|
-
})
|
|
15
|
-
it('can format a public key URL', () => {
|
|
16
|
-
const url = formatter.format({ username: 'megabot', type: 'publickey' })
|
|
17
|
-
assert.equal(url, 'https://activitypubbot.example/user/megabot/publickey')
|
|
18
|
-
})
|
|
19
|
-
it('can format an inbox URL', () => {
|
|
20
|
-
const url = formatter.format({ username: 'megabot', collection: 'inbox' })
|
|
21
|
-
assert.equal(url, 'https://activitypubbot.example/user/megabot/inbox')
|
|
22
|
-
})
|
|
23
|
-
it('can format an inbox URL page', () => {
|
|
24
|
-
const url = formatter.format({
|
|
25
|
-
username: 'megabot',
|
|
26
|
-
collection: 'inbox',
|
|
27
|
-
page: 3
|
|
28
|
-
})
|
|
29
|
-
assert.equal(url, 'https://activitypubbot.example/user/megabot/inbox/3')
|
|
30
|
-
})
|
|
31
|
-
it('can format an activity URL', () => {
|
|
32
|
-
const url = formatter.format({
|
|
33
|
-
username: 'megabot',
|
|
34
|
-
type: 'like',
|
|
35
|
-
nanoid: 'LNPUlv9kmvhAdr4eoqkil'
|
|
36
|
-
})
|
|
37
|
-
assert.equal(url, 'https://activitypubbot.example/user/megabot/like/LNPUlv9kmvhAdr4eoqkil')
|
|
38
|
-
})
|
|
39
|
-
it('can format a note URL', () => {
|
|
40
|
-
const url = formatter.format({
|
|
41
|
-
username: 'megabot',
|
|
42
|
-
type: 'note',
|
|
43
|
-
nanoid: 'LNPUlv9kmvhAdr4eoqkil'
|
|
44
|
-
})
|
|
45
|
-
assert.equal(url, 'https://activitypubbot.example/user/megabot/note/LNPUlv9kmvhAdr4eoqkil')
|
|
46
|
-
})
|
|
47
|
-
it('can format a note replies URL', () => {
|
|
48
|
-
const url = formatter.format({
|
|
49
|
-
username: 'megabot',
|
|
50
|
-
type: 'note',
|
|
51
|
-
nanoid: 'LNPUlv9kmvhAdr4eoqkil',
|
|
52
|
-
collection: 'replies'
|
|
53
|
-
})
|
|
54
|
-
assert.equal(url, 'https://activitypubbot.example/user/megabot/note/LNPUlv9kmvhAdr4eoqkil/replies')
|
|
55
|
-
})
|
|
56
|
-
it('can format a note replies page URL', () => {
|
|
57
|
-
const url = formatter.format({
|
|
58
|
-
username: 'megabot',
|
|
59
|
-
type: 'note',
|
|
60
|
-
nanoid: 'LNPUlv9kmvhAdr4eoqkil',
|
|
61
|
-
collection: 'replies',
|
|
62
|
-
page: 4
|
|
63
|
-
})
|
|
64
|
-
assert.equal(url, 'https://activitypubbot.example/user/megabot/note/LNPUlv9kmvhAdr4eoqkil/replies/4')
|
|
65
|
-
})
|
|
66
|
-
it('can format a server URL', () => {
|
|
67
|
-
const url = formatter.format({
|
|
68
|
-
server: true
|
|
69
|
-
})
|
|
70
|
-
assert.equal(url, 'https://activitypubbot.example/')
|
|
71
|
-
})
|
|
72
|
-
it('can format a server public key URL', () => {
|
|
73
|
-
const url = formatter.format({
|
|
74
|
-
server: true,
|
|
75
|
-
type: 'publickey'
|
|
76
|
-
})
|
|
77
|
-
assert.equal(url, 'https://activitypubbot.example/publickey')
|
|
78
|
-
})
|
|
79
|
-
it('can tell if an URL is local', () => {
|
|
80
|
-
assert.ok(formatter.isLocal('https://activitypubbot.example/user/megabot'))
|
|
81
|
-
assert.ok(!formatter.isLocal('https://social.example/user/megabot'))
|
|
82
|
-
})
|
|
83
|
-
it('can get a username from a user URL', () => {
|
|
84
|
-
const username = formatter.getUserName('https://activitypubbot.example/user/megabot')
|
|
85
|
-
assert.equal(username, 'megabot')
|
|
86
|
-
})
|
|
87
|
-
it('refuses to unformat a remote URL', () => {
|
|
88
|
-
assert.throws(() => formatter.unformat(
|
|
89
|
-
'https://remote.example/some/unrelated/33/path/format'
|
|
90
|
-
))
|
|
91
|
-
})
|
|
92
|
-
it('can unformat a user URL', () => {
|
|
93
|
-
const parts = formatter.unformat(
|
|
94
|
-
'https://activitypubbot.example/user/megabot'
|
|
95
|
-
)
|
|
96
|
-
assert.equal(parts.username, 'megabot')
|
|
97
|
-
})
|
|
98
|
-
it('can unformat a public key URL', () => {
|
|
99
|
-
const parts = formatter.unformat(
|
|
100
|
-
'https://activitypubbot.example/user/megabot/publickey'
|
|
101
|
-
)
|
|
102
|
-
assert.equal(parts.username, 'megabot')
|
|
103
|
-
assert.equal(parts.type, 'publickey')
|
|
104
|
-
})
|
|
105
|
-
it('can unformat an inbox URL', () => {
|
|
106
|
-
const parts = formatter.unformat(
|
|
107
|
-
'https://activitypubbot.example/user/megabot/inbox'
|
|
108
|
-
)
|
|
109
|
-
assert.equal(parts.username, 'megabot')
|
|
110
|
-
assert.equal(parts.collection, 'inbox')
|
|
111
|
-
})
|
|
112
|
-
it('can unformat an inbox page URL', () => {
|
|
113
|
-
const parts = formatter.unformat(
|
|
114
|
-
'https://activitypubbot.example/user/megabot/inbox/3'
|
|
115
|
-
)
|
|
116
|
-
assert.equal(parts.username, 'megabot')
|
|
117
|
-
assert.equal(parts.collection, 'inbox')
|
|
118
|
-
assert.equal(parts.page, 3)
|
|
119
|
-
})
|
|
120
|
-
it('can unformat an activity URL', () => {
|
|
121
|
-
const parts = formatter.unformat(
|
|
122
|
-
'https://activitypubbot.example/user/megabot/like/LNPUlv9kmvhAdr4eoqkil'
|
|
123
|
-
)
|
|
124
|
-
assert.equal(parts.username, 'megabot')
|
|
125
|
-
assert.equal(parts.type, 'like')
|
|
126
|
-
assert.equal(parts.nanoid, 'LNPUlv9kmvhAdr4eoqkil')
|
|
127
|
-
})
|
|
128
|
-
it('can unformat a note URL', () => {
|
|
129
|
-
const parts = formatter.unformat(
|
|
130
|
-
'https://activitypubbot.example/user/megabot/note/LNPUlv9kmvhAdr4eoqkil'
|
|
131
|
-
)
|
|
132
|
-
assert.equal(parts.username, 'megabot')
|
|
133
|
-
assert.equal(parts.type, 'note')
|
|
134
|
-
assert.equal(parts.nanoid, 'LNPUlv9kmvhAdr4eoqkil')
|
|
135
|
-
})
|
|
136
|
-
it('can unformat a note replies URL', () => {
|
|
137
|
-
const parts = formatter.unformat(
|
|
138
|
-
'https://activitypubbot.example/user/megabot/note/LNPUlv9kmvhAdr4eoqkil/replies'
|
|
139
|
-
)
|
|
140
|
-
assert.equal(parts.username, 'megabot')
|
|
141
|
-
assert.equal(parts.type, 'note')
|
|
142
|
-
assert.equal(parts.nanoid, 'LNPUlv9kmvhAdr4eoqkil')
|
|
143
|
-
assert.equal(parts.collection, 'replies')
|
|
144
|
-
})
|
|
145
|
-
it('can unformat a note replies page URL', () => {
|
|
146
|
-
const parts = formatter.unformat(
|
|
147
|
-
'https://activitypubbot.example/user/megabot/note/LNPUlv9kmvhAdr4eoqkil/replies/4'
|
|
148
|
-
)
|
|
149
|
-
assert.equal(parts.username, 'megabot')
|
|
150
|
-
assert.equal(parts.type, 'note')
|
|
151
|
-
assert.equal(parts.nanoid, 'LNPUlv9kmvhAdr4eoqkil')
|
|
152
|
-
assert.equal(parts.collection, 'replies')
|
|
153
|
-
assert.equal(parts.page, 4)
|
|
154
|
-
})
|
|
155
|
-
it('can unformat a server URL', () => {
|
|
156
|
-
const parts = formatter.unformat('https://activitypubbot.example/')
|
|
157
|
-
assert.ok(parts.server)
|
|
158
|
-
})
|
|
159
|
-
it('can unformat a server public key URL', () => {
|
|
160
|
-
const parts = formatter.unformat('https://activitypubbot.example/publickey')
|
|
161
|
-
assert.ok(parts.server)
|
|
162
|
-
assert.equal(parts.type, 'publickey')
|
|
163
|
-
})
|
|
164
|
-
})
|