@@ -25,6 +25,7 @@ import {
25
25
PUBLIC_COLLECTION ,
26
26
Tombstone ,
27
27
Undo ,
28
+ Update ,
28
29
} from "@fedify/fedify/vocab" ;
29
30
import { assert } from "@std/assert/assert" ;
30
31
import { assertEquals } from "@std/assert/equals" ;
@@ -40,7 +41,7 @@ Deno.test("createMessage()", async () => {
40
41
const bot = new BotImpl < void > ( { kv : new MemoryKvStore ( ) , username : "bot" } ) ;
41
42
const session = bot . getSession ( "https://example.com" , undefined ) ;
42
43
await assertRejects (
43
- ( ) => createMessage < Note , void > ( new Note ( { } ) , session ) ,
44
+ ( ) => createMessage < Note , void > ( new Note ( { } ) , session , { } ) ,
44
45
TypeError ,
45
46
"The raw.id is required." ,
46
47
) ;
@@ -49,6 +50,7 @@ Deno.test("createMessage()", async () => {
49
50
createMessage < Note , void > (
50
51
new Note ( { id : new URL ( "https://example.com/notes/1" ) } ) ,
51
52
session ,
53
+ { } ,
52
54
) ,
53
55
TypeError ,
54
56
"The raw.content is required." ,
@@ -61,6 +63,7 @@ Deno.test("createMessage()", async () => {
61
63
content : "<p>Hello, world!</p>" ,
62
64
} ) ,
63
65
session ,
66
+ { } ,
64
67
) ,
65
68
TypeError ,
66
69
"The raw.attributionId is required." ,
@@ -83,7 +86,11 @@ Deno.test("createMessage()", async () => {
83
86
} ) ,
84
87
] ,
85
88
} ) ;
86
- const publicMessage = await createMessage < Note , void > ( publicNote , session ) ;
89
+ const publicMessage = await createMessage < Note , void > (
90
+ publicNote ,
91
+ session ,
92
+ { } ,
93
+ ) ;
87
94
assertEquals ( publicMessage . raw , publicNote ) ;
88
95
assertEquals ( publicMessage . id , publicNote . id ) ;
89
96
assertEquals ( publicMessage . actor , await session . getActor ( ) ) ;
@@ -110,6 +117,7 @@ Deno.test("createMessage()", async () => {
110
117
const unlistedMessage = await createMessage < Note , void > (
111
118
unlistedNote ,
112
119
session ,
120
+ { } ,
113
121
) ;
114
122
assertEquals ( unlistedMessage . visibility , "unlisted" ) ;
115
123
@@ -120,21 +128,22 @@ Deno.test("createMessage()", async () => {
120
128
const followersMessage = await createMessage < Note , void > (
121
129
followersNote ,
122
130
session ,
131
+ { } ,
123
132
) ;
124
133
assertEquals ( followersMessage . visibility , "followers" ) ;
125
134
126
135
const direct = publicNote . clone ( {
127
136
to : new URL ( "https://example.com/ap/actor/bot" ) ,
128
137
ccs : [ ] ,
129
138
} ) ;
130
- const directMessage = await createMessage < Note , void > ( direct , session ) ;
139
+ const directMessage = await createMessage < Note , void > ( direct , session , { } ) ;
131
140
assertEquals ( directMessage . visibility , "direct" ) ;
132
141
133
142
const unknown = publicNote . clone ( {
134
143
tos : [ ] ,
135
144
ccs : [ ] ,
136
145
} ) ;
137
- const unknownMessage = await createMessage < Note , void > ( unknown , session ) ;
146
+ const unknownMessage = await createMessage < Note , void > ( unknown , session , { } ) ;
138
147
assertEquals ( unknownMessage . visibility , "unknown" ) ;
139
148
} ) ;
140
149
@@ -152,7 +161,13 @@ Deno.test("AuthorizedMessageImpl.delete()", async () => {
152
161
to : PUBLIC_COLLECTION ,
153
162
cc : new URL ( "https://example.com/ap/actor/bot/followers" ) ,
154
163
} ) ;
155
- const msg = await createMessage < Note , void > ( note , session , undefined , true ) ;
164
+ const msg = await createMessage < Note , void > (
165
+ note ,
166
+ session ,
167
+ { } ,
168
+ undefined ,
169
+ true ,
170
+ ) ;
156
171
await kv . set (
157
172
bot . kvPrefixes . messages ,
158
173
[ "c1c792ce-a0be-4685-b396-e59e5ef8c788" ] ,
@@ -208,7 +223,11 @@ Deno.test("MessageImpl.reply()", async () => {
208
223
to : new URL ( "https://example.com/ap/actor/john/followers" ) ,
209
224
cc : PUBLIC_COLLECTION ,
210
225
} ) ;
211
- const originalMsg = await createMessage < Note , void > ( originalPost , session ) ;
226
+ const originalMsg = await createMessage < Note , void > (
227
+ originalPost ,
228
+ session ,
229
+ { } ,
230
+ ) ;
212
231
const reply = await originalMsg . reply ( text `Hello, John!` ) ;
213
232
const msgIds = await kv . get < string [ ] > ( bot . kvPrefixes . messages ) ;
214
233
assert ( msgIds != null ) ;
@@ -251,7 +270,11 @@ Deno.test("MessageImpl.share()", async (t) => {
251
270
to : new URL ( "https://example.com/ap/actor/john/followers" ) ,
252
271
cc : PUBLIC_COLLECTION ,
253
272
} ) ;
254
- const originalMsg = await createMessage < Note , void > ( originalPost , session ) ;
273
+ const originalMsg = await createMessage < Note , void > (
274
+ originalPost ,
275
+ session ,
276
+ { } ,
277
+ ) ;
255
278
const sharedMsg = await originalMsg . share ( ) ;
256
279
let msgId : string ;
257
280
@@ -307,3 +330,120 @@ Deno.test("MessageImpl.share()", async (t) => {
307
330
assertEquals ( activity . objectId , sharedMsg . id ) ;
308
331
} ) ;
309
332
} ) ;
333
+
334
+ Deno . test ( "AuthorizedMessage.update()" , async ( t ) => {
335
+ const kv = new MemoryKvStore ( ) ;
336
+ const bot = new BotImpl < void > ( { kv, username : "bot" } ) ;
337
+ const ctx = createMockContext ( bot , "https://example.com" ) ;
338
+ const session = new SessionImpl ( bot , ctx ) ;
339
+ const actorA = new Person ( {
340
+ id : new URL ( "https://example.com/ap/actor/john" ) ,
341
+ preferredUsername : "john" ,
342
+ } ) ;
343
+ const actorB = new Person ( {
344
+ id : new URL ( "https://example.com/ap/actor/jane" ) ,
345
+ preferredUsername : "jane" ,
346
+ } ) ;
347
+
348
+ for (
349
+ const visibility of [ "public" , "unlisted" , "followers" , "direct" ] as const
350
+ ) {
351
+ await t . step ( visibility , async ( ) => {
352
+ const msg = await session . publish ( text `Hello, ${ actorA } ` , { visibility } ) ;
353
+ const [ id ] = await kv . get < string [ ] > ( bot . kvPrefixes . messages ) ?? [ ] ;
354
+ const originalRaw = msg . raw ;
355
+ ctx . sentActivities = [ ] ;
356
+ const before = Temporal . Now . instant ( ) ;
357
+ await msg . update ( text `Hello, ${ actorB } ` ) ;
358
+ const after = Temporal . Now . instant ( ) ;
359
+ assertEquals ( msg . text , "Hello, @jane@example.com" ) ;
360
+ assertEquals (
361
+ msg . html ,
362
+ '<p>Hello, <a href="https://example.com/ap/actor/jane" ' +
363
+ 'translate="no" class="h-card u-url mention" target="_blank">' +
364
+ "@<span>jane@example.com</span></a></p>" ,
365
+ ) ;
366
+ assertEquals ( msg . mentions . length , 1 ) ;
367
+ assertEquals ( msg . mentions [ 0 ] . id , actorB . id ) ;
368
+ assertEquals ( msg . hashtags , [ ] ) ;
369
+ assert ( msg . updated != null ) ;
370
+ assert ( msg . updated . epochNanoseconds >= before . epochNanoseconds ) ;
371
+ assert ( msg . updated . epochNanoseconds <= after . epochNanoseconds ) ;
372
+ assertEquals ( msg . raw . content , msg . html ) ;
373
+ if ( visibility === "public" ) {
374
+ assertEquals ( msg . raw . toIds , [ PUBLIC_COLLECTION , actorB . id ] ) ;
375
+ assertEquals ( msg . raw . ccIds , [ ctx . getFollowersUri ( bot . identifier ) ] ) ;
376
+ } else if ( visibility === "unlisted" ) {
377
+ assertEquals ( msg . raw . toIds , [
378
+ ctx . getFollowersUri ( bot . identifier ) ,
379
+ actorB . id ,
380
+ ] ) ;
381
+ assertEquals ( msg . raw . ccIds , [ PUBLIC_COLLECTION ] ) ;
382
+ } else if ( visibility === "followers" ) {
383
+ assertEquals ( msg . raw . toIds , [
384
+ ctx . getFollowersUri ( bot . identifier ) ,
385
+ actorB . id ,
386
+ ] ) ;
387
+ assertEquals ( msg . raw . ccIds , [ ] ) ;
388
+ } else {
389
+ assertEquals ( msg . raw . toIds , [ actorB . id ] ) ;
390
+ assertEquals ( msg . raw . ccIds , [ ] ) ;
391
+ }
392
+ const tags = await Array . fromAsync ( msg . raw . getTags ( ) ) ;
393
+ assertEquals ( tags . length , 1 ) ;
394
+ assertInstanceOf ( tags [ 0 ] , Mention ) ;
395
+ assertEquals ( tags [ 0 ] . name , "@jane@example.com" ) ;
396
+ assertEquals ( tags [ 0 ] . href , actorB . id ) ;
397
+ assertEquals ( msg . raw . published , originalRaw . published ) ;
398
+ assertEquals ( msg . raw . updated , msg . updated ) ;
399
+ const createJson = await kv . get ( [ ...bot . kvPrefixes . messages , id ] ) ;
400
+ assert ( createJson != null ) ;
401
+ const create = await Create . fromJsonLd ( createJson ) ;
402
+ assertEquals (
403
+ await ( await create . getObject ( ) ) ?. toJsonLd ( { format : "compact" } ) ,
404
+ await msg . raw . toJsonLd ( { format : "compact" } ) ,
405
+ ) ;
406
+ assertEquals ( ctx . sentActivities . length , visibility === "direct" ? 1 : 2 ) ;
407
+ const { recipients, activity } = ctx . sentActivities [ 0 ] ;
408
+ assertEquals (
409
+ recipients ,
410
+ visibility === "direct" ? [ actorA , actorB ] : "followers" ,
411
+ ) ;
412
+ assertInstanceOf ( activity , Update ) ;
413
+ assertEquals ( activity . actorId , ctx . getActorUri ( bot . identifier ) ) ;
414
+ if ( visibility === "public" ) {
415
+ assertEquals ( activity . toIds , [ PUBLIC_COLLECTION , actorA . id , actorB . id ] ) ;
416
+ assertEquals ( activity . ccIds , [ ctx . getFollowersUri ( bot . identifier ) ] ) ;
417
+ } else if ( visibility === "unlisted" ) {
418
+ assertEquals ( activity . toIds , [
419
+ ctx . getFollowersUri ( bot . identifier ) ,
420
+ actorA . id ,
421
+ actorB . id ,
422
+ ] ) ;
423
+ assertEquals ( activity . ccIds , [ PUBLIC_COLLECTION ] ) ;
424
+ } else if ( visibility === "followers" ) {
425
+ assertEquals ( activity . toIds , [
426
+ ctx . getFollowersUri ( bot . identifier ) ,
427
+ actorA . id ,
428
+ actorB . id ,
429
+ ] ) ;
430
+ assertEquals ( activity . ccIds , [ ] ) ;
431
+ } else {
432
+ assertEquals ( activity . toIds , [ actorA . id , actorB . id ] ) ;
433
+ assertEquals ( activity . ccIds , [ ] ) ;
434
+ }
435
+ assertEquals ( await activity . getObject ( ) , msg . raw ) ;
436
+ assertEquals ( activity . updated , msg . updated ) ;
437
+ if ( visibility !== "direct" ) {
438
+ const { recipients, activity } = ctx . sentActivities [ 1 ] ;
439
+ assertEquals ( recipients , [ actorA , actorB ] ) ;
440
+ assertInstanceOf ( activity , Update ) ;
441
+ assertEquals ( activity . actorId , ctx . getActorUri ( bot . identifier ) ) ;
442
+ assertEquals ( await activity . getObject ( ) , msg . raw ) ;
443
+ assertEquals ( activity . updated , msg . updated ) ;
444
+ }
445
+ } ) ;
446
+
447
+ await kv . delete ( bot . kvPrefixes . messages ) ;
448
+ }
449
+ } ) ;
0 commit comments