@@ -39,6 +39,7 @@ import { unescape } from "@std/html/entities";
39
39
import { generate as uuidv7 } from "@std/uuid/unstable-v7" ;
40
40
import { FilterXSS , getDefaultWhiteList } from "xss" ;
41
41
import type {
42
+ AuthorizedMessage ,
42
43
Message ,
43
44
MessageClass ,
44
45
MessageShareOptions ,
@@ -91,88 +92,20 @@ export class MessageImpl<T extends MessageClass, TContextData>
91
92
this . updated = message . updated ;
92
93
}
93
94
94
- async delete ( ) : Promise < void > {
95
- const parsed = this . session . context . parseUri ( this . id ) ;
96
- if (
97
- parsed ?. type !== "object" ||
98
- ! messageClasses . some ( ( cls ) => parsed . class === cls )
99
- ) {
100
- return ;
101
- }
102
- const { id } = parsed . values ;
103
- const kv = this . session . bot . kv ;
104
- const listKey : KvKey = this . session . bot . kvPrefixes . messages ;
105
- const lockKey : KvKey = [ ...listKey , "lock" ] ;
106
- const lockId = `${ id } :delete` ;
107
- do {
108
- await kv . set ( lockKey , lockId ) ;
109
- const set = new Set ( await kv . get < string [ ] > ( listKey ) ?? [ ] ) ;
110
- set . delete ( id ) ;
111
- const list = [ ...set ] ;
112
- list . sort ( ( a , b ) => a < b ? - 1 : a > b ? 1 : 0 ) ;
113
- await kv . set ( listKey , list ) ;
114
- } while ( await kv . get ( lockKey ) !== lockId ) ;
115
- const messageKey : KvKey = [ ...listKey , id ] ;
116
- const createJson = await kv . get ( messageKey ) ;
117
- if ( createJson == null ) return ;
118
- await kv . delete ( messageKey ) ;
119
- const create = await Create . fromJsonLd ( createJson , this . session . context ) ;
120
- const message = await create . getObject ( this . session . context ) ;
121
- if ( message == null ) return ;
122
- const mentionedActorIds : Set < string > = new Set ( ) ;
123
- for await ( const tag of message . getTags ( this . session . context ) ) {
124
- if ( tag instanceof Mention && tag . href != null ) {
125
- mentionedActorIds . add ( tag . href . href ) ;
126
- }
127
- }
128
- const promises : Promise < Object | null > [ ] = [ ] ;
129
- const documentLoader = await this . session . context . getDocumentLoader (
130
- this . session . bot ,
131
- ) ;
132
- for ( const uri of mentionedActorIds ) {
133
- promises . push ( this . session . context . lookupObject ( uri , { documentLoader } ) ) ;
134
- }
135
- const mentionedActors = ( await Promise . all ( promises ) ) . filter ( isActor ) ;
136
- const activity = new Delete ( {
137
- id : new URL ( "#delete" , this . id ) ,
138
- actor : this . session . context . getActorUri ( this . session . bot . identifier ) ,
139
- tos : create . toIds ,
140
- ccs : create . ccIds ,
141
- object : new Tombstone ( {
142
- id : this . id ,
143
- } ) ,
144
- } ) ;
145
- const excludeBaseUris = [ new URL ( this . session . context . origin ) ] ;
146
- await this . session . context . sendActivity (
147
- this . session . bot ,
148
- "followers" ,
149
- activity ,
150
- { preferSharedInbox : true , excludeBaseUris } ,
151
- ) ;
152
- for ( const actor of mentionedActors ) {
153
- await this . session . context . sendActivity (
154
- this . session . bot ,
155
- actor ,
156
- activity ,
157
- { preferSharedInbox : true , excludeBaseUris } ,
158
- ) ;
159
- }
160
- }
161
-
162
95
reply (
163
96
text : Text < "block" , TContextData > ,
164
97
options ?: SessionPublishOptions ,
165
- ) : Promise < Message < Note , TContextData > > ;
98
+ ) : Promise < AuthorizedMessage < Note , TContextData > > ;
166
99
reply < T extends MessageClass > (
167
100
text : Text < "block" , TContextData > ,
168
101
options ?: SessionPublishOptionsWithClass < T > | undefined ,
169
- ) : Promise < Message < T , TContextData > > ;
102
+ ) : Promise < AuthorizedMessage < T , TContextData > > ;
170
103
reply (
171
104
text : Text < "block" , TContextData > ,
172
105
options ?:
173
106
| SessionPublishOptions
174
107
| SessionPublishOptionsWithClass < MessageClass > ,
175
- ) : Promise < Message < MessageClass , TContextData > > {
108
+ ) : Promise < AuthorizedMessage < MessageClass , TContextData > > {
176
109
return this . session . publish ( text , {
177
110
visibility : this . visibility === "unknown" ? "direct" : this . visibility ,
178
111
...options ,
@@ -274,6 +207,78 @@ export class MessageImpl<T extends MessageClass, TContextData>
274
207
}
275
208
}
276
209
210
+ export class AuthorizedMessageImpl < T extends MessageClass , TContextData >
211
+ extends MessageImpl < T , TContextData >
212
+ implements AuthorizedMessage < T , TContextData > {
213
+ async delete ( ) : Promise < void > {
214
+ const parsed = this . session . context . parseUri ( this . id ) ;
215
+ if (
216
+ parsed ?. type !== "object" ||
217
+ ! messageClasses . some ( ( cls ) => parsed . class === cls )
218
+ ) {
219
+ return ;
220
+ }
221
+ const { id } = parsed . values ;
222
+ const kv = this . session . bot . kv ;
223
+ const listKey : KvKey = this . session . bot . kvPrefixes . messages ;
224
+ const lockKey : KvKey = [ ...listKey , "lock" ] ;
225
+ const lockId = `${ id } :delete` ;
226
+ do {
227
+ await kv . set ( lockKey , lockId ) ;
228
+ const set = new Set ( await kv . get < string [ ] > ( listKey ) ?? [ ] ) ;
229
+ set . delete ( id ) ;
230
+ const list = [ ...set ] ;
231
+ list . sort ( ( a , b ) => a < b ? - 1 : a > b ? 1 : 0 ) ;
232
+ await kv . set ( listKey , list ) ;
233
+ } while ( await kv . get ( lockKey ) !== lockId ) ;
234
+ const messageKey : KvKey = [ ...listKey , id ] ;
235
+ const createJson = await kv . get ( messageKey ) ;
236
+ if ( createJson == null ) return ;
237
+ await kv . delete ( messageKey ) ;
238
+ const create = await Create . fromJsonLd ( createJson , this . session . context ) ;
239
+ const message = await create . getObject ( this . session . context ) ;
240
+ if ( message == null ) return ;
241
+ const mentionedActorIds : Set < string > = new Set ( ) ;
242
+ for await ( const tag of message . getTags ( this . session . context ) ) {
243
+ if ( tag instanceof Mention && tag . href != null ) {
244
+ mentionedActorIds . add ( tag . href . href ) ;
245
+ }
246
+ }
247
+ const promises : Promise < Object | null > [ ] = [ ] ;
248
+ const documentLoader = await this . session . context . getDocumentLoader (
249
+ this . session . bot ,
250
+ ) ;
251
+ for ( const uri of mentionedActorIds ) {
252
+ promises . push ( this . session . context . lookupObject ( uri , { documentLoader } ) ) ;
253
+ }
254
+ const mentionedActors = ( await Promise . all ( promises ) ) . filter ( isActor ) ;
255
+ const activity = new Delete ( {
256
+ id : new URL ( "#delete" , this . id ) ,
257
+ actor : this . session . context . getActorUri ( this . session . bot . identifier ) ,
258
+ tos : create . toIds ,
259
+ ccs : create . ccIds ,
260
+ object : new Tombstone ( {
261
+ id : this . id ,
262
+ } ) ,
263
+ } ) ;
264
+ const excludeBaseUris = [ new URL ( this . session . context . origin ) ] ;
265
+ await this . session . context . sendActivity (
266
+ this . session . bot ,
267
+ "followers" ,
268
+ activity ,
269
+ { preferSharedInbox : true , excludeBaseUris } ,
270
+ ) ;
271
+ for ( const actor of mentionedActors ) {
272
+ await this . session . context . sendActivity (
273
+ this . session . bot ,
274
+ actor ,
275
+ activity ,
276
+ { preferSharedInbox : true , excludeBaseUris } ,
277
+ ) ;
278
+ }
279
+ }
280
+ }
281
+
277
282
const allowList = getDefaultWhiteList ( ) ;
278
283
const htmlXss = new FilterXSS ( {
279
284
allowList : {
@@ -290,6 +295,19 @@ export async function createMessage<T extends MessageClass, TContextData>(
290
295
raw : T ,
291
296
session : SessionImpl < TContextData > ,
292
297
replyTarget ?: Message < MessageClass , TContextData > ,
298
+ authorized ?: true ,
299
+ ) : Promise < AuthorizedMessage < T , TContextData > > ;
300
+ export async function createMessage < T extends MessageClass , TContextData > (
301
+ raw : T ,
302
+ session : SessionImpl < TContextData > ,
303
+ replyTarget ?: Message < MessageClass , TContextData > ,
304
+ authorized ?: boolean ,
305
+ ) : Promise < Message < T , TContextData > > ;
306
+ export async function createMessage < T extends MessageClass , TContextData > (
307
+ raw : T ,
308
+ session : SessionImpl < TContextData > ,
309
+ replyTarget ?: Message < MessageClass , TContextData > ,
310
+ authorized : boolean = false ,
293
311
) : Promise < Message < T , TContextData > > {
294
312
if ( raw . id == null ) throw new TypeError ( "The raw.id is required." ) ;
295
313
else if ( raw . content == null ) {
@@ -352,7 +370,7 @@ export async function createMessage<T extends MessageClass, TContextData>(
352
370
replyTarget = await createMessage ( rt , session ) ;
353
371
}
354
372
}
355
- return new MessageImpl ( session , {
373
+ return new ( authorized ? AuthorizedMessageImpl : MessageImpl ) ( session , {
356
374
raw,
357
375
id : raw . id ,
358
376
actor,
0 commit comments