@atproto/ozone 0.1.155 → 0.1.157
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/CHANGELOG.md +27 -0
- package/dist/api/moderation/emitEvent.d.ts.map +1 -1
- package/dist/api/moderation/emitEvent.js +20 -7
- package/dist/api/moderation/emitEvent.js.map +1 -1
- package/dist/api/util.d.ts +1 -1
- package/dist/api/util.d.ts.map +1 -1
- package/dist/api/util.js +6 -1
- package/dist/api/util.js.map +1 -1
- package/dist/daemon/event-pusher.d.ts +1 -1
- package/dist/daemon/event-pusher.d.ts.map +1 -1
- package/dist/daemon/event-pusher.js +17 -5
- package/dist/daemon/event-pusher.js.map +1 -1
- package/dist/daemon/scheduled-action-processor.d.ts +5 -1
- package/dist/daemon/scheduled-action-processor.d.ts.map +1 -1
- package/dist/daemon/scheduled-action-processor.js +44 -2
- package/dist/daemon/scheduled-action-processor.js.map +1 -1
- package/dist/jetstream/service.d.ts +1 -1
- package/dist/jetstream/service.d.ts.map +1 -1
- package/dist/jetstream/service.js +2 -2
- package/dist/jetstream/service.js.map +1 -1
- package/dist/lexicon/index.d.ts +11 -0
- package/dist/lexicon/index.d.ts.map +1 -1
- package/dist/lexicon/index.js +32 -1
- package/dist/lexicon/index.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +806 -6
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +425 -3
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/app/bsky/ageassurance/begin.d.ts +31 -0
- package/dist/lexicon/types/app/bsky/ageassurance/begin.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/ageassurance/begin.js +7 -0
- package/dist/lexicon/types/app/bsky/ageassurance/begin.js.map +1 -0
- package/dist/lexicon/types/app/bsky/ageassurance/defs.d.ts +138 -0
- package/dist/lexicon/types/app/bsky/ageassurance/defs.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/ageassurance/defs.js +115 -0
- package/dist/lexicon/types/app/bsky/ageassurance/defs.js.map +1 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getConfig.d.ts +18 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getConfig.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getConfig.js +7 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getConfig.js.map +1 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getState.d.ts +24 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getState.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getState.js +7 -0
- package/dist/lexicon/types/app/bsky/ageassurance/getState.js.map +1 -0
- package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts +13 -2
- package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/defs.js.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/queryStatuses.d.ts +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/queryStatuses.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/queryStatuses.js.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/scheduleAction.d.ts +10 -0
- package/dist/lexicon/types/tools/ozone/moderation/scheduleAction.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/scheduleAction.js.map +1 -1
- package/dist/mod-service/index.d.ts +3 -3
- package/dist/mod-service/index.d.ts.map +1 -1
- package/dist/mod-service/index.js +10 -4
- package/dist/mod-service/index.js.map +1 -1
- package/dist/mod-service/status.d.ts +1 -1
- package/dist/mod-service/util.d.ts.map +1 -1
- package/dist/mod-service/util.js +1 -0
- package/dist/mod-service/util.js.map +1 -1
- package/dist/mod-service/views.d.ts.map +1 -1
- package/dist/mod-service/views.js +7 -0
- package/dist/mod-service/views.js.map +1 -1
- package/dist/setting/validators.d.ts.map +1 -1
- package/dist/setting/validators.js +10 -0
- package/dist/setting/validators.js.map +1 -1
- package/package.json +10 -9
- package/src/api/moderation/emitEvent.ts +34 -9
- package/src/api/util.ts +7 -1
- package/src/daemon/event-pusher.ts +22 -5
- package/src/daemon/scheduled-action-processor.ts +59 -1
- package/src/jetstream/service.ts +1 -1
- package/src/lexicon/index.ts +49 -0
- package/src/lexicon/lexicons.ts +458 -3
- package/src/lexicon/types/app/bsky/ageassurance/begin.ts +54 -0
- package/src/lexicon/types/app/bsky/ageassurance/defs.ts +301 -0
- package/src/lexicon/types/app/bsky/ageassurance/getConfig.ts +34 -0
- package/src/lexicon/types/app/bsky/ageassurance/getState.ts +42 -0
- package/src/lexicon/types/tools/ozone/moderation/defs.ts +13 -2
- package/src/lexicon/types/tools/ozone/moderation/queryStatuses.ts +6 -1
- package/src/lexicon/types/tools/ozone/moderation/scheduleAction.ts +10 -0
- package/src/mod-service/index.ts +21 -7
- package/src/mod-service/util.ts +2 -0
- package/src/mod-service/views.ts +10 -0
- package/src/setting/validators.ts +15 -0
- package/tests/query-labels.test.ts +4 -1
- package/tests/scheduled-action-processor.test.ts +30 -6
- package/tests/takedown.test.ts +43 -1
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
5
|
+
import { CID } from 'multiformats/cid'
|
|
6
|
+
import { validate as _validate } from '../../../../lexicons'
|
|
7
|
+
import {
|
|
8
|
+
type $Typed,
|
|
9
|
+
is$typed as _is$typed,
|
|
10
|
+
type OmitKey,
|
|
11
|
+
} from '../../../../util'
|
|
12
|
+
|
|
13
|
+
const is$typed = _is$typed,
|
|
14
|
+
validate = _validate
|
|
15
|
+
const id = 'app.bsky.ageassurance.defs'
|
|
16
|
+
|
|
17
|
+
/** The access level granted based on Age Assurance data we've processed. */
|
|
18
|
+
export type Access = 'unknown' | 'none' | 'safe' | 'full' | (string & {})
|
|
19
|
+
/** The status of the Age Assurance process. */
|
|
20
|
+
export type Status =
|
|
21
|
+
| 'unknown'
|
|
22
|
+
| 'pending'
|
|
23
|
+
| 'assured'
|
|
24
|
+
| 'blocked'
|
|
25
|
+
| (string & {})
|
|
26
|
+
|
|
27
|
+
/** The user's computed Age Assurance state. */
|
|
28
|
+
export interface State {
|
|
29
|
+
$type?: 'app.bsky.ageassurance.defs#state'
|
|
30
|
+
/** The timestamp when this state was last updated. */
|
|
31
|
+
lastInitiatedAt?: string
|
|
32
|
+
status: Status
|
|
33
|
+
access: Access
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const hashState = 'state'
|
|
37
|
+
|
|
38
|
+
export function isState<V>(v: V) {
|
|
39
|
+
return is$typed(v, id, hashState)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function validateState<V>(v: V) {
|
|
43
|
+
return validate<State & V>(v, id, hashState)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Additional metadata needed to compute Age Assurance state client-side. */
|
|
47
|
+
export interface StateMetadata {
|
|
48
|
+
$type?: 'app.bsky.ageassurance.defs#stateMetadata'
|
|
49
|
+
/** The account creation timestamp. */
|
|
50
|
+
accountCreatedAt?: string
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const hashStateMetadata = 'stateMetadata'
|
|
54
|
+
|
|
55
|
+
export function isStateMetadata<V>(v: V) {
|
|
56
|
+
return is$typed(v, id, hashStateMetadata)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function validateStateMetadata<V>(v: V) {
|
|
60
|
+
return validate<StateMetadata & V>(v, id, hashStateMetadata)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface Config {
|
|
64
|
+
$type?: 'app.bsky.ageassurance.defs#config'
|
|
65
|
+
/** The per-region Age Assurance configuration. */
|
|
66
|
+
regions: ConfigRegion[]
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const hashConfig = 'config'
|
|
70
|
+
|
|
71
|
+
export function isConfig<V>(v: V) {
|
|
72
|
+
return is$typed(v, id, hashConfig)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function validateConfig<V>(v: V) {
|
|
76
|
+
return validate<Config & V>(v, id, hashConfig)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** The Age Assurance configuration for a specific region. */
|
|
80
|
+
export interface ConfigRegion {
|
|
81
|
+
$type?: 'app.bsky.ageassurance.defs#configRegion'
|
|
82
|
+
/** The ISO 3166-1 alpha-2 country code this configuration applies to. */
|
|
83
|
+
countryCode: string
|
|
84
|
+
/** The ISO 3166-2 region code this configuration applies to. If omitted, the configuration applies to the entire country. */
|
|
85
|
+
regionCode?: string
|
|
86
|
+
/** The ordered list of Age Assurance rules that apply to this region. Rules should be applied in order, and the first matching rule determines the access level granted. The rules array should always include a default rule as the last item. */
|
|
87
|
+
rules: (
|
|
88
|
+
| $Typed<ConfigRegionRuleDefault>
|
|
89
|
+
| $Typed<ConfigRegionRuleIfDeclaredOverAge>
|
|
90
|
+
| $Typed<ConfigRegionRuleIfDeclaredUnderAge>
|
|
91
|
+
| $Typed<ConfigRegionRuleIfAssuredOverAge>
|
|
92
|
+
| $Typed<ConfigRegionRuleIfAssuredUnderAge>
|
|
93
|
+
| $Typed<ConfigRegionRuleIfAccountNewerThan>
|
|
94
|
+
| $Typed<ConfigRegionRuleIfAccountOlderThan>
|
|
95
|
+
| { $type: string }
|
|
96
|
+
)[]
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const hashConfigRegion = 'configRegion'
|
|
100
|
+
|
|
101
|
+
export function isConfigRegion<V>(v: V) {
|
|
102
|
+
return is$typed(v, id, hashConfigRegion)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function validateConfigRegion<V>(v: V) {
|
|
106
|
+
return validate<ConfigRegion & V>(v, id, hashConfigRegion)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Age Assurance rule that applies by default. */
|
|
110
|
+
export interface ConfigRegionRuleDefault {
|
|
111
|
+
$type?: 'app.bsky.ageassurance.defs#configRegionRuleDefault'
|
|
112
|
+
access: Access
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const hashConfigRegionRuleDefault = 'configRegionRuleDefault'
|
|
116
|
+
|
|
117
|
+
export function isConfigRegionRuleDefault<V>(v: V) {
|
|
118
|
+
return is$typed(v, id, hashConfigRegionRuleDefault)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function validateConfigRegionRuleDefault<V>(v: V) {
|
|
122
|
+
return validate<ConfigRegionRuleDefault & V>(
|
|
123
|
+
v,
|
|
124
|
+
id,
|
|
125
|
+
hashConfigRegionRuleDefault,
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Age Assurance rule that applies if the user has declared themselves equal-to or over a certain age. */
|
|
130
|
+
export interface ConfigRegionRuleIfDeclaredOverAge {
|
|
131
|
+
$type?: 'app.bsky.ageassurance.defs#configRegionRuleIfDeclaredOverAge'
|
|
132
|
+
/** The age threshold as a whole integer. */
|
|
133
|
+
age: number
|
|
134
|
+
access: Access
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const hashConfigRegionRuleIfDeclaredOverAge =
|
|
138
|
+
'configRegionRuleIfDeclaredOverAge'
|
|
139
|
+
|
|
140
|
+
export function isConfigRegionRuleIfDeclaredOverAge<V>(v: V) {
|
|
141
|
+
return is$typed(v, id, hashConfigRegionRuleIfDeclaredOverAge)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function validateConfigRegionRuleIfDeclaredOverAge<V>(v: V) {
|
|
145
|
+
return validate<ConfigRegionRuleIfDeclaredOverAge & V>(
|
|
146
|
+
v,
|
|
147
|
+
id,
|
|
148
|
+
hashConfigRegionRuleIfDeclaredOverAge,
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Age Assurance rule that applies if the user has declared themselves under a certain age. */
|
|
153
|
+
export interface ConfigRegionRuleIfDeclaredUnderAge {
|
|
154
|
+
$type?: 'app.bsky.ageassurance.defs#configRegionRuleIfDeclaredUnderAge'
|
|
155
|
+
/** The age threshold as a whole integer. */
|
|
156
|
+
age: number
|
|
157
|
+
access: Access
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const hashConfigRegionRuleIfDeclaredUnderAge =
|
|
161
|
+
'configRegionRuleIfDeclaredUnderAge'
|
|
162
|
+
|
|
163
|
+
export function isConfigRegionRuleIfDeclaredUnderAge<V>(v: V) {
|
|
164
|
+
return is$typed(v, id, hashConfigRegionRuleIfDeclaredUnderAge)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function validateConfigRegionRuleIfDeclaredUnderAge<V>(v: V) {
|
|
168
|
+
return validate<ConfigRegionRuleIfDeclaredUnderAge & V>(
|
|
169
|
+
v,
|
|
170
|
+
id,
|
|
171
|
+
hashConfigRegionRuleIfDeclaredUnderAge,
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/** Age Assurance rule that applies if the user has been assured to be equal-to or over a certain age. */
|
|
176
|
+
export interface ConfigRegionRuleIfAssuredOverAge {
|
|
177
|
+
$type?: 'app.bsky.ageassurance.defs#configRegionRuleIfAssuredOverAge'
|
|
178
|
+
/** The age threshold as a whole integer. */
|
|
179
|
+
age: number
|
|
180
|
+
access: Access
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const hashConfigRegionRuleIfAssuredOverAge = 'configRegionRuleIfAssuredOverAge'
|
|
184
|
+
|
|
185
|
+
export function isConfigRegionRuleIfAssuredOverAge<V>(v: V) {
|
|
186
|
+
return is$typed(v, id, hashConfigRegionRuleIfAssuredOverAge)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export function validateConfigRegionRuleIfAssuredOverAge<V>(v: V) {
|
|
190
|
+
return validate<ConfigRegionRuleIfAssuredOverAge & V>(
|
|
191
|
+
v,
|
|
192
|
+
id,
|
|
193
|
+
hashConfigRegionRuleIfAssuredOverAge,
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** Age Assurance rule that applies if the user has been assured to be under a certain age. */
|
|
198
|
+
export interface ConfigRegionRuleIfAssuredUnderAge {
|
|
199
|
+
$type?: 'app.bsky.ageassurance.defs#configRegionRuleIfAssuredUnderAge'
|
|
200
|
+
/** The age threshold as a whole integer. */
|
|
201
|
+
age: number
|
|
202
|
+
access: Access
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const hashConfigRegionRuleIfAssuredUnderAge =
|
|
206
|
+
'configRegionRuleIfAssuredUnderAge'
|
|
207
|
+
|
|
208
|
+
export function isConfigRegionRuleIfAssuredUnderAge<V>(v: V) {
|
|
209
|
+
return is$typed(v, id, hashConfigRegionRuleIfAssuredUnderAge)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export function validateConfigRegionRuleIfAssuredUnderAge<V>(v: V) {
|
|
213
|
+
return validate<ConfigRegionRuleIfAssuredUnderAge & V>(
|
|
214
|
+
v,
|
|
215
|
+
id,
|
|
216
|
+
hashConfigRegionRuleIfAssuredUnderAge,
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** Age Assurance rule that applies if the account is equal-to or newer than a certain date. */
|
|
221
|
+
export interface ConfigRegionRuleIfAccountNewerThan {
|
|
222
|
+
$type?: 'app.bsky.ageassurance.defs#configRegionRuleIfAccountNewerThan'
|
|
223
|
+
/** The date threshold as a datetime string. */
|
|
224
|
+
date: string
|
|
225
|
+
access: Access
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const hashConfigRegionRuleIfAccountNewerThan =
|
|
229
|
+
'configRegionRuleIfAccountNewerThan'
|
|
230
|
+
|
|
231
|
+
export function isConfigRegionRuleIfAccountNewerThan<V>(v: V) {
|
|
232
|
+
return is$typed(v, id, hashConfigRegionRuleIfAccountNewerThan)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function validateConfigRegionRuleIfAccountNewerThan<V>(v: V) {
|
|
236
|
+
return validate<ConfigRegionRuleIfAccountNewerThan & V>(
|
|
237
|
+
v,
|
|
238
|
+
id,
|
|
239
|
+
hashConfigRegionRuleIfAccountNewerThan,
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/** Age Assurance rule that applies if the account is older than a certain date. */
|
|
244
|
+
export interface ConfigRegionRuleIfAccountOlderThan {
|
|
245
|
+
$type?: 'app.bsky.ageassurance.defs#configRegionRuleIfAccountOlderThan'
|
|
246
|
+
/** The date threshold as a datetime string. */
|
|
247
|
+
date: string
|
|
248
|
+
access: Access
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const hashConfigRegionRuleIfAccountOlderThan =
|
|
252
|
+
'configRegionRuleIfAccountOlderThan'
|
|
253
|
+
|
|
254
|
+
export function isConfigRegionRuleIfAccountOlderThan<V>(v: V) {
|
|
255
|
+
return is$typed(v, id, hashConfigRegionRuleIfAccountOlderThan)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export function validateConfigRegionRuleIfAccountOlderThan<V>(v: V) {
|
|
259
|
+
return validate<ConfigRegionRuleIfAccountOlderThan & V>(
|
|
260
|
+
v,
|
|
261
|
+
id,
|
|
262
|
+
hashConfigRegionRuleIfAccountOlderThan,
|
|
263
|
+
)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/** Object used to store Age Assurance data in stash. */
|
|
267
|
+
export interface Event {
|
|
268
|
+
$type?: 'app.bsky.ageassurance.defs#event'
|
|
269
|
+
/** The date and time of this write operation. */
|
|
270
|
+
createdAt: string
|
|
271
|
+
/** The unique identifier for this instance of the Age Assurance flow, in UUID format. */
|
|
272
|
+
attemptId: string
|
|
273
|
+
/** The status of the Age Assurance process. */
|
|
274
|
+
status: 'unknown' | 'pending' | 'assured' | 'blocked' | (string & {})
|
|
275
|
+
/** The access level granted based on Age Assurance data we've processed. */
|
|
276
|
+
access: 'unknown' | 'none' | 'safe' | 'full' | (string & {})
|
|
277
|
+
/** The ISO 3166-1 alpha-2 country code provided when beginning the Age Assurance flow. */
|
|
278
|
+
countryCode: string
|
|
279
|
+
/** The ISO 3166-2 region code provided when beginning the Age Assurance flow. */
|
|
280
|
+
regionCode?: string
|
|
281
|
+
/** The email used for Age Assurance. */
|
|
282
|
+
email?: string
|
|
283
|
+
/** The IP address used when initiating the Age Assurance flow. */
|
|
284
|
+
initIp?: string
|
|
285
|
+
/** The user agent used when initiating the Age Assurance flow. */
|
|
286
|
+
initUa?: string
|
|
287
|
+
/** The IP address used when completing the Age Assurance flow. */
|
|
288
|
+
completeIp?: string
|
|
289
|
+
/** The user agent used when completing the Age Assurance flow. */
|
|
290
|
+
completeUa?: string
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const hashEvent = 'event'
|
|
294
|
+
|
|
295
|
+
export function isEvent<V>(v: V) {
|
|
296
|
+
return is$typed(v, id, hashEvent)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export function validateEvent<V>(v: V) {
|
|
300
|
+
return validate<Event & V>(v, id, hashEvent)
|
|
301
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
5
|
+
import { CID } from 'multiformats/cid'
|
|
6
|
+
import { validate as _validate } from '../../../../lexicons'
|
|
7
|
+
import {
|
|
8
|
+
type $Typed,
|
|
9
|
+
is$typed as _is$typed,
|
|
10
|
+
type OmitKey,
|
|
11
|
+
} from '../../../../util'
|
|
12
|
+
import type * as AppBskyAgeassuranceDefs from './defs.js'
|
|
13
|
+
|
|
14
|
+
const is$typed = _is$typed,
|
|
15
|
+
validate = _validate
|
|
16
|
+
const id = 'app.bsky.ageassurance.getConfig'
|
|
17
|
+
|
|
18
|
+
export type QueryParams = {}
|
|
19
|
+
export type InputSchema = undefined
|
|
20
|
+
export type OutputSchema = AppBskyAgeassuranceDefs.Config
|
|
21
|
+
export type HandlerInput = void
|
|
22
|
+
|
|
23
|
+
export interface HandlerSuccess {
|
|
24
|
+
encoding: 'application/json'
|
|
25
|
+
body: OutputSchema
|
|
26
|
+
headers?: { [key: string]: string }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface HandlerError {
|
|
30
|
+
status: number
|
|
31
|
+
message?: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type HandlerOutput = HandlerError | HandlerSuccess
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import { type ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
5
|
+
import { CID } from 'multiformats/cid'
|
|
6
|
+
import { validate as _validate } from '../../../../lexicons'
|
|
7
|
+
import {
|
|
8
|
+
type $Typed,
|
|
9
|
+
is$typed as _is$typed,
|
|
10
|
+
type OmitKey,
|
|
11
|
+
} from '../../../../util'
|
|
12
|
+
import type * as AppBskyAgeassuranceDefs from './defs.js'
|
|
13
|
+
|
|
14
|
+
const is$typed = _is$typed,
|
|
15
|
+
validate = _validate
|
|
16
|
+
const id = 'app.bsky.ageassurance.getState'
|
|
17
|
+
|
|
18
|
+
export type QueryParams = {
|
|
19
|
+
countryCode: string
|
|
20
|
+
regionCode?: string
|
|
21
|
+
}
|
|
22
|
+
export type InputSchema = undefined
|
|
23
|
+
|
|
24
|
+
export interface OutputSchema {
|
|
25
|
+
state: AppBskyAgeassuranceDefs.State
|
|
26
|
+
metadata: AppBskyAgeassuranceDefs.StateMetadata
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type HandlerInput = void
|
|
30
|
+
|
|
31
|
+
export interface HandlerSuccess {
|
|
32
|
+
encoding: 'application/json'
|
|
33
|
+
body: OutputSchema
|
|
34
|
+
headers?: { [key: string]: string }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface HandlerError {
|
|
38
|
+
status: number
|
|
39
|
+
message?: string
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type HandlerOutput = HandlerError | HandlerSuccess
|
|
@@ -13,6 +13,7 @@ import type * as ComAtprotoAdminDefs from '../../../com/atproto/admin/defs.js'
|
|
|
13
13
|
import type * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef.js'
|
|
14
14
|
import type * as ChatBskyConvoDefs from '../../../chat/bsky/convo/defs.js'
|
|
15
15
|
import type * as ComAtprotoModerationDefs from '../../../com/atproto/moderation/defs.js'
|
|
16
|
+
import type * as AppBskyAgeassuranceDefs from '../../../app/bsky/ageassurance/defs.js'
|
|
16
17
|
import type * as ComAtprotoServerDefs from '../../../com/atproto/server/defs.js'
|
|
17
18
|
import type * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs.js'
|
|
18
19
|
|
|
@@ -308,6 +309,8 @@ export interface ModEventTakedown {
|
|
|
308
309
|
policies?: string[]
|
|
309
310
|
/** Severity level of the violation (e.g., 'sev-0', 'sev-1', 'sev-2', etc.). */
|
|
310
311
|
severityLevel?: string
|
|
312
|
+
/** List of services where the takedown should be applied. If empty or not provided, takedown is applied on all configured services. */
|
|
313
|
+
targetServices?: ('appview' | 'pds' | (string & {}))[]
|
|
311
314
|
/** Number of strikes to assign to the user for this violation. */
|
|
312
315
|
strikeCount?: number
|
|
313
316
|
/** When the strike should expire. If not provided, the strike never expires. */
|
|
@@ -447,10 +450,15 @@ export interface AgeAssuranceEvent {
|
|
|
447
450
|
$type?: 'tools.ozone.moderation.defs#ageAssuranceEvent'
|
|
448
451
|
/** The date and time of this write operation. */
|
|
449
452
|
createdAt: string
|
|
450
|
-
/** The status of the age assurance process. */
|
|
451
|
-
status: 'unknown' | 'pending' | 'assured' | (string & {})
|
|
452
453
|
/** The unique identifier for this instance of the age assurance flow, in UUID format. */
|
|
453
454
|
attemptId: string
|
|
455
|
+
/** The status of the Age Assurance process. */
|
|
456
|
+
status: 'unknown' | 'pending' | 'assured' | (string & {})
|
|
457
|
+
access?: AppBskyAgeassuranceDefs.Access
|
|
458
|
+
/** The ISO 3166-1 alpha-2 country code provided when beginning the Age Assurance flow. */
|
|
459
|
+
countryCode?: string
|
|
460
|
+
/** The ISO 3166-2 region code provided when beginning the Age Assurance flow. */
|
|
461
|
+
regionCode?: string
|
|
454
462
|
/** The IP address used when initiating the AA flow. */
|
|
455
463
|
initIp?: string
|
|
456
464
|
/** The user agent used when initiating the AA flow. */
|
|
@@ -476,6 +484,7 @@ export interface AgeAssuranceOverrideEvent {
|
|
|
476
484
|
$type?: 'tools.ozone.moderation.defs#ageAssuranceOverrideEvent'
|
|
477
485
|
/** The status to be set for the user decided by a moderator, overriding whatever value the user had previously. Use reset to default to original state. */
|
|
478
486
|
status: 'assured' | 'reset' | 'blocked' | (string & {})
|
|
487
|
+
access?: AppBskyAgeassuranceDefs.Access
|
|
479
488
|
/** Comment describing the reason for the override. */
|
|
480
489
|
comment: string
|
|
481
490
|
}
|
|
@@ -634,6 +643,8 @@ export interface ModEventEmail {
|
|
|
634
643
|
strikeCount?: number
|
|
635
644
|
/** When the strike should expire. If not provided, the strike never expires. */
|
|
636
645
|
strikeExpiresAt?: string
|
|
646
|
+
/** Indicates whether the email was successfully delivered to the user's inbox. */
|
|
647
|
+
isDelivered?: boolean
|
|
637
648
|
}
|
|
638
649
|
|
|
639
650
|
const hashModEventEmail = 'modEventEmail'
|
|
@@ -51,7 +51,12 @@ export type QueryParams = {
|
|
|
51
51
|
/** When set to true, only muted subjects and reporters will be returned. */
|
|
52
52
|
onlyMuted?: boolean
|
|
53
53
|
/** Specify when fetching subjects in a certain state */
|
|
54
|
-
reviewState?:
|
|
54
|
+
reviewState?:
|
|
55
|
+
| 'tools.ozone.moderation.defs#reviewOpen'
|
|
56
|
+
| 'tools.ozone.moderation.defs#reviewClosed'
|
|
57
|
+
| 'tools.ozone.moderation.defs#reviewEscalated'
|
|
58
|
+
| 'tools.ozone.moderation.defs#reviewNone'
|
|
59
|
+
| (string & {})
|
|
55
60
|
ignoreSubjects?: string[]
|
|
56
61
|
/** Get all subject statuses that were reviewed by a specific moderator */
|
|
57
62
|
lastReviewedBy?: string
|
|
@@ -56,6 +56,16 @@ export interface Takedown {
|
|
|
56
56
|
acknowledgeAccountSubjects?: boolean
|
|
57
57
|
/** Names/Keywords of the policies that drove the decision. */
|
|
58
58
|
policies?: string[]
|
|
59
|
+
/** Severity level of the violation (e.g., 'sev-0', 'sev-1', 'sev-2', etc.). */
|
|
60
|
+
severityLevel?: string
|
|
61
|
+
/** Number of strikes to assign to the user when takedown is applied. */
|
|
62
|
+
strikeCount?: number
|
|
63
|
+
/** When the strike should expire. If not provided, the strike never expires. */
|
|
64
|
+
strikeExpiresAt?: string
|
|
65
|
+
/** Email content to be sent to the user upon takedown. */
|
|
66
|
+
emailContent?: string
|
|
67
|
+
/** Subject of the email to be sent to the user upon takedown. */
|
|
68
|
+
emailSubject?: string
|
|
59
69
|
}
|
|
60
70
|
|
|
61
71
|
const hashTakedown = 'takedown'
|
package/src/mod-service/index.ts
CHANGED
|
@@ -494,6 +494,7 @@ export class ModerationService {
|
|
|
494
494
|
|
|
495
495
|
if (isModEventEmail(event)) {
|
|
496
496
|
meta.subjectLine = event.subjectLine
|
|
497
|
+
meta.isDelivered = !!event.isDelivered
|
|
497
498
|
if (event.content) {
|
|
498
499
|
meta.content = event.content
|
|
499
500
|
}
|
|
@@ -572,6 +573,10 @@ export class ModerationService {
|
|
|
572
573
|
meta.policies = event.policies.join(',')
|
|
573
574
|
}
|
|
574
575
|
|
|
576
|
+
if (isModEventTakedown(event) && event.targetServices?.length) {
|
|
577
|
+
meta.targetServices = event.targetServices.join(',')
|
|
578
|
+
}
|
|
579
|
+
|
|
575
580
|
// Keep trace of reports that came in while the reporter was in muted stated
|
|
576
581
|
if (isModEventReport(event)) {
|
|
577
582
|
const isReportingMuted = await this.isReportingMutedForSubject(createdBy)
|
|
@@ -773,17 +778,20 @@ export class ModerationService {
|
|
|
773
778
|
async takedownRepo(
|
|
774
779
|
subject: RepoSubject,
|
|
775
780
|
takedownId: number,
|
|
781
|
+
targetServices: Set<string>,
|
|
776
782
|
isSuspend = false,
|
|
777
783
|
) {
|
|
778
784
|
const takedownRef = `BSKY-${
|
|
779
785
|
isSuspend ? 'SUSPEND' : 'TAKEDOWN'
|
|
780
786
|
}-${takedownId}`
|
|
781
787
|
|
|
782
|
-
const values = this.eventPusher
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
788
|
+
const values = this.eventPusher
|
|
789
|
+
.getTakedownServices(targetServices)
|
|
790
|
+
.map((eventType) => ({
|
|
791
|
+
eventType,
|
|
792
|
+
subjectDid: subject.did,
|
|
793
|
+
takedownRef,
|
|
794
|
+
}))
|
|
787
795
|
|
|
788
796
|
const repoEvts = await this.db.db
|
|
789
797
|
.insertInto('repo_push_event')
|
|
@@ -849,7 +857,11 @@ export class ModerationService {
|
|
|
849
857
|
})
|
|
850
858
|
}
|
|
851
859
|
|
|
852
|
-
async takedownRecord(
|
|
860
|
+
async takedownRecord(
|
|
861
|
+
subject: RecordSubject,
|
|
862
|
+
takedownId: number,
|
|
863
|
+
targetServices: Set<string>,
|
|
864
|
+
) {
|
|
853
865
|
this.db.assertTransaction()
|
|
854
866
|
await this.formatAndCreateLabels(subject.uri, subject.cid, {
|
|
855
867
|
create: [TAKEDOWN_LABEL],
|
|
@@ -859,7 +871,9 @@ export class ModerationService {
|
|
|
859
871
|
const blobCids = subject.blobCids
|
|
860
872
|
if (blobCids && blobCids.length > 0) {
|
|
861
873
|
const blobValues: Insertable<BlobPushEvent>[] = []
|
|
862
|
-
for (const eventType of this.eventPusher.
|
|
874
|
+
for (const eventType of this.eventPusher.getTakedownServices(
|
|
875
|
+
targetServices,
|
|
876
|
+
)) {
|
|
863
877
|
for (const cid of blobCids) {
|
|
864
878
|
blobValues.push({
|
|
865
879
|
eventType,
|
package/src/mod-service/util.ts
CHANGED
package/src/mod-service/views.ts
CHANGED
|
@@ -195,6 +195,15 @@ export class ModerationViews {
|
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
+
if (isModEventTakedown(event)) {
|
|
199
|
+
if (
|
|
200
|
+
typeof meta.targetServices === 'string' &&
|
|
201
|
+
meta.targetServices.length > 0
|
|
202
|
+
) {
|
|
203
|
+
event.targetServices = meta.targetServices.split(',')
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
198
207
|
if (isModEventLabel(event)) {
|
|
199
208
|
event.createLabelVals = row.createLabelVals?.length
|
|
200
209
|
? row.createLabelVals.split(' ')
|
|
@@ -229,6 +238,7 @@ export class ModerationViews {
|
|
|
229
238
|
if (isModEventEmail(event)) {
|
|
230
239
|
event.content = ifString(meta.content)!
|
|
231
240
|
event.subjectLine = ifString(meta.subjectLine)!
|
|
241
|
+
event.isDelivered = !!meta.isDelivered
|
|
232
242
|
}
|
|
233
243
|
|
|
234
244
|
if (isModEventComment(event) && meta.sticky) {
|
|
@@ -198,6 +198,21 @@ export const settingValidators = new Map<
|
|
|
198
198
|
hasDefault = true
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
|
+
|
|
202
|
+
if (severityVal['targetServices'] !== undefined) {
|
|
203
|
+
if (!Array.isArray(severityVal['targetServices'])) {
|
|
204
|
+
throw new InvalidRequestError(
|
|
205
|
+
`targetServices must be an array for severity level ${severityKey} in policy ${key}`,
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
for (const service of severityVal['targetServices']) {
|
|
209
|
+
if (typeof service !== 'string') {
|
|
210
|
+
throw new InvalidRequestError(
|
|
211
|
+
`Each target service must be a string for severity level ${severityKey} in policy ${key}`,
|
|
212
|
+
)
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
201
216
|
}
|
|
202
217
|
}
|
|
203
218
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
/* eslint-disable import/no-deprecated */
|
|
2
|
+
|
|
1
3
|
import { AtpAgent } from '@atproto/api'
|
|
2
4
|
import { cborEncode } from '@atproto/common'
|
|
3
5
|
import { Secp256k1Keypair, verifySignature } from '@atproto/crypto'
|
|
4
6
|
import { EXAMPLE_LABELER, TestNetwork } from '@atproto/dev-env'
|
|
5
|
-
import { DisconnectError
|
|
7
|
+
import { DisconnectError } from '@atproto/ws-client'
|
|
8
|
+
import { Subscription } from '@atproto/xrpc-server'
|
|
6
9
|
import { ids, lexicons } from '../src/lexicon/lexicons'
|
|
7
10
|
import { Label } from '../src/lexicon/types/com/atproto/label/defs'
|
|
8
11
|
import {
|
|
@@ -19,13 +19,20 @@ describe('scheduled action processor', () => {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
const scheduleTestAction = async (
|
|
22
|
+
const scheduleTestAction = async (
|
|
23
|
+
subject: string,
|
|
24
|
+
scheduling: any,
|
|
25
|
+
emailData?: { emailSubject?: string; emailContent?: string },
|
|
26
|
+
) => {
|
|
23
27
|
return await adminAgent.tools.ozone.moderation.scheduleAction(
|
|
24
28
|
{
|
|
25
29
|
action: {
|
|
26
30
|
$type: 'tools.ozone.moderation.scheduleAction#takedown',
|
|
27
31
|
comment: 'Test scheduled takedown',
|
|
28
32
|
policies: ['spam'],
|
|
33
|
+
severityLevel: 'sev-1',
|
|
34
|
+
strikeCount: 1,
|
|
35
|
+
...emailData,
|
|
29
36
|
},
|
|
30
37
|
subjects: [subject],
|
|
31
38
|
createdBy: 'did:plc:moderator',
|
|
@@ -74,7 +81,14 @@ describe('scheduled action processor', () => {
|
|
|
74
81
|
const testSubject = sc.dids.alice
|
|
75
82
|
|
|
76
83
|
const pastTime = new Date(Date.now() - 1000).toISOString()
|
|
77
|
-
await scheduleTestAction(
|
|
84
|
+
await scheduleTestAction(
|
|
85
|
+
testSubject,
|
|
86
|
+
{ executeAt: pastTime },
|
|
87
|
+
{
|
|
88
|
+
emailSubject: 'Test Email Subject',
|
|
89
|
+
emailContent: 'Test Email Content',
|
|
90
|
+
},
|
|
91
|
+
)
|
|
78
92
|
|
|
79
93
|
const pendingActions = await getScheduledActions(
|
|
80
94
|
['pending'],
|
|
@@ -94,12 +108,20 @@ describe('scheduled action processor', () => {
|
|
|
94
108
|
|
|
95
109
|
const modEvents = await getModerationEvents(testSubject, [
|
|
96
110
|
'tools.ozone.moderation.defs#modEventTakedown',
|
|
111
|
+
'tools.ozone.moderation.defs#modEventEmail',
|
|
97
112
|
])
|
|
98
|
-
expect(modEvents.length).toBe(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
113
|
+
expect(modEvents.length).toBe(2)
|
|
114
|
+
const takedownEvent = modEvents.find(
|
|
115
|
+
(e) => e.event.$type === 'tools.ozone.moderation.defs#modEventTakedown',
|
|
116
|
+
)
|
|
117
|
+
const emailEvent = modEvents.find(
|
|
118
|
+
(e) => e.event.$type === 'tools.ozone.moderation.defs#modEventEmail',
|
|
102
119
|
)
|
|
120
|
+
|
|
121
|
+
expect(takedownEvent?.event['comment']).toBeDefined()
|
|
122
|
+
|
|
123
|
+
expect(emailEvent?.event['subjectLine']).toBe('Test Email Subject')
|
|
124
|
+
expect(emailEvent?.event['content']).toBe('Test Email Content')
|
|
103
125
|
})
|
|
104
126
|
|
|
105
127
|
it('skips actions scheduled for future execution', async () => {
|
|
@@ -202,7 +224,9 @@ describe('scheduled action processor', () => {
|
|
|
202
224
|
// Verify the moderation event has all properties
|
|
203
225
|
const modEvents = await getModerationEvents(testSubject, [
|
|
204
226
|
'tools.ozone.moderation.defs#modEventTakedown',
|
|
227
|
+
'tools.ozone.moderation.defs#modEventEmail',
|
|
205
228
|
])
|
|
229
|
+
// No email was sent
|
|
206
230
|
expect(modEvents.length).toBe(1)
|
|
207
231
|
|
|
208
232
|
const takedownEvent = modEvents[0].event as ModEventTakedown
|