@atproto/ozone 0.0.17 → 0.1.0
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 +11 -0
- package/dist/index.js +47 -56
- package/dist/index.js.map +3 -3
- package/dist/lexicon/lexicons.d.ts +13 -0
- package/dist/lexicon/types/com/atproto/server/describeServer.d.ts +7 -0
- package/dist/mod-service/index.d.ts +2 -0
- package/dist/mod-service/types.d.ts +0 -2
- package/package.json +5 -5
- package/src/api/label/fetchLabels.ts +1 -13
- package/src/lexicon/lexicons.ts +13 -0
- package/src/lexicon/types/com/atproto/server/describeServer.ts +18 -0
- package/src/mod-service/index.ts +26 -68
- package/src/mod-service/types.ts +0 -4
- package/src/mod-service/util.ts +1 -1
- package/src/mod-service/views.ts +1 -1
- package/tests/__snapshots__/get-record.test.ts.snap +2 -6
- package/tests/__snapshots__/get-repo.test.ts.snap +1 -2
- package/tests/moderation.test.ts +4 -103
- package/tests/query-labels.test.ts +0 -6
- package/tests/sequencer.test.ts +1 -0
|
@@ -2206,6 +2206,11 @@ export declare const schemaDict: {
|
|
|
2206
2206
|
description: string;
|
|
2207
2207
|
ref: string;
|
|
2208
2208
|
};
|
|
2209
|
+
contact: {
|
|
2210
|
+
type: string;
|
|
2211
|
+
description: string;
|
|
2212
|
+
ref: string;
|
|
2213
|
+
};
|
|
2209
2214
|
did: {
|
|
2210
2215
|
type: string;
|
|
2211
2216
|
format: string;
|
|
@@ -2225,6 +2230,14 @@ export declare const schemaDict: {
|
|
|
2225
2230
|
};
|
|
2226
2231
|
};
|
|
2227
2232
|
};
|
|
2233
|
+
contact: {
|
|
2234
|
+
type: string;
|
|
2235
|
+
properties: {
|
|
2236
|
+
email: {
|
|
2237
|
+
type: string;
|
|
2238
|
+
};
|
|
2239
|
+
};
|
|
2240
|
+
};
|
|
2228
2241
|
};
|
|
2229
2242
|
};
|
|
2230
2243
|
ComAtprotoServerGetAccountInviteCodes: {
|
|
@@ -9,6 +9,7 @@ export interface OutputSchema {
|
|
|
9
9
|
phoneVerificationRequired?: boolean;
|
|
10
10
|
availableUserDomains: string[];
|
|
11
11
|
links?: Links;
|
|
12
|
+
contact?: Contact;
|
|
12
13
|
did: string;
|
|
13
14
|
[k: string]: unknown;
|
|
14
15
|
}
|
|
@@ -40,3 +41,9 @@ export interface Links {
|
|
|
40
41
|
}
|
|
41
42
|
export declare function isLinks(v: unknown): v is Links;
|
|
42
43
|
export declare function validateLinks(v: unknown): ValidationResult;
|
|
44
|
+
export interface Contact {
|
|
45
|
+
email?: string;
|
|
46
|
+
[k: string]: unknown;
|
|
47
|
+
}
|
|
48
|
+
export declare function isContact(v: unknown): v is Contact;
|
|
49
|
+
export declare function validateContact(v: unknown): ValidationResult;
|
|
@@ -180,6 +180,8 @@ export declare class ModerationService {
|
|
|
180
180
|
subject: string;
|
|
181
181
|
}): Promise<void>;
|
|
182
182
|
}
|
|
183
|
+
export declare const TAKEDOWN_LABEL = "!takedown";
|
|
184
|
+
export declare const SUSPEND_LABEL = "!suspend";
|
|
183
185
|
export type TakedownSubjects = {
|
|
184
186
|
did: string;
|
|
185
187
|
subjects: (RepoRef | RepoBlobRef | StrongRef)[];
|
|
@@ -17,5 +17,3 @@ export type ModerationSubjectStatusRowWithHandle = ModerationSubjectStatusRow &
|
|
|
17
17
|
handle: string | null;
|
|
18
18
|
};
|
|
19
19
|
export type ModEventType = ToolsOzoneModerationDefs.ModEventTakedown | ToolsOzoneModerationDefs.ModEventAcknowledge | ToolsOzoneModerationDefs.ModEventEscalate | ToolsOzoneModerationDefs.ModEventComment | ToolsOzoneModerationDefs.ModEventLabel | ToolsOzoneModerationDefs.ModEventReport | ToolsOzoneModerationDefs.ModEventMute | ToolsOzoneModerationDefs.ModEventReverseTakedown | ToolsOzoneModerationDefs.ModEventTag;
|
|
20
|
-
export declare const UNSPECCED_TAKEDOWN_LABEL = "!unspecced-takedown";
|
|
21
|
-
export declare const UNSPECCED_TAKEDOWN_BLOBS_LABEL = "!unspecced-takedown-blobs";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/ozone",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Backend service for moderating the Bluesky network.",
|
|
6
6
|
"keywords": [
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"pino-http": "^8.2.1",
|
|
31
31
|
"typed-emitter": "^2.1.0",
|
|
32
32
|
"uint8arrays": "3.0.0",
|
|
33
|
-
"@atproto/api": "^0.11.
|
|
33
|
+
"@atproto/api": "^0.11.1",
|
|
34
34
|
"@atproto/common": "^0.3.4",
|
|
35
35
|
"@atproto/crypto": "^0.3.0",
|
|
36
36
|
"@atproto/identity": "^0.3.3",
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"@types/qs": "^6.9.7",
|
|
48
48
|
"axios": "^0.27.2",
|
|
49
49
|
"nodemailer": "^6.8.0",
|
|
50
|
-
"@atproto/api": "^0.11.
|
|
51
|
-
"@atproto/dev-env": "^0.2.
|
|
50
|
+
"@atproto/api": "^0.11.1",
|
|
51
|
+
"@atproto/dev-env": "^0.2.39",
|
|
52
52
|
"@atproto/lex-cli": "^0.3.2",
|
|
53
|
-
"@atproto/pds": "^0.4.
|
|
53
|
+
"@atproto/pds": "^0.4.7",
|
|
54
54
|
"@atproto/xrpc": "^0.4.3"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
@@ -1,30 +1,18 @@
|
|
|
1
1
|
import { Server } from '../../lexicon'
|
|
2
2
|
import AppContext from '../../context'
|
|
3
|
-
import {
|
|
4
|
-
UNSPECCED_TAKEDOWN_BLOBS_LABEL,
|
|
5
|
-
UNSPECCED_TAKEDOWN_LABEL,
|
|
6
|
-
} from '../../mod-service/types'
|
|
7
3
|
|
|
8
4
|
export default function (server: Server, ctx: AppContext) {
|
|
9
5
|
server.com.atproto.temp.fetchLabels({
|
|
10
6
|
auth: ctx.authVerifier.standardOptionalOrAdminToken,
|
|
11
|
-
handler: async ({
|
|
7
|
+
handler: async ({ params }) => {
|
|
12
8
|
const { limit } = params
|
|
13
9
|
const since =
|
|
14
10
|
params.since !== undefined ? new Date(params.since).toISOString() : ''
|
|
15
|
-
const includeUnspeccedTakedowns =
|
|
16
|
-
auth.credentials.type === 'none' ? false : auth.credentials.isAdmin
|
|
17
11
|
const labelRes = await ctx.db.db
|
|
18
12
|
.selectFrom('label')
|
|
19
13
|
.selectAll()
|
|
20
14
|
.orderBy('label.cts', 'asc')
|
|
21
15
|
.where('cts', '>', since)
|
|
22
|
-
.if(!includeUnspeccedTakedowns, (q) =>
|
|
23
|
-
q.where('label.val', 'not in', [
|
|
24
|
-
UNSPECCED_TAKEDOWN_LABEL,
|
|
25
|
-
UNSPECCED_TAKEDOWN_BLOBS_LABEL,
|
|
26
|
-
]),
|
|
27
|
-
)
|
|
28
16
|
.limit(limit)
|
|
29
17
|
.execute()
|
|
30
18
|
|
package/src/lexicon/lexicons.ts
CHANGED
|
@@ -2420,6 +2420,11 @@ export const schemaDict = {
|
|
|
2420
2420
|
description: 'URLs of service policy documents.',
|
|
2421
2421
|
ref: 'lex:com.atproto.server.describeServer#links',
|
|
2422
2422
|
},
|
|
2423
|
+
contact: {
|
|
2424
|
+
type: 'ref',
|
|
2425
|
+
description: 'Contact information',
|
|
2426
|
+
ref: 'lex:com.atproto.server.describeServer#contact',
|
|
2427
|
+
},
|
|
2423
2428
|
did: {
|
|
2424
2429
|
type: 'string',
|
|
2425
2430
|
format: 'did',
|
|
@@ -2439,6 +2444,14 @@ export const schemaDict = {
|
|
|
2439
2444
|
},
|
|
2440
2445
|
},
|
|
2441
2446
|
},
|
|
2447
|
+
contact: {
|
|
2448
|
+
type: 'object',
|
|
2449
|
+
properties: {
|
|
2450
|
+
email: {
|
|
2451
|
+
type: 'string',
|
|
2452
|
+
},
|
|
2453
|
+
},
|
|
2454
|
+
},
|
|
2442
2455
|
},
|
|
2443
2456
|
},
|
|
2444
2457
|
ComAtprotoServerGetAccountInviteCodes: {
|
|
@@ -20,6 +20,7 @@ export interface OutputSchema {
|
|
|
20
20
|
/** List of domain suffixes that can be used in account handles. */
|
|
21
21
|
availableUserDomains: string[]
|
|
22
22
|
links?: Links
|
|
23
|
+
contact?: Contact
|
|
23
24
|
did: string
|
|
24
25
|
[k: string]: unknown
|
|
25
26
|
}
|
|
@@ -66,3 +67,20 @@ export function isLinks(v: unknown): v is Links {
|
|
|
66
67
|
export function validateLinks(v: unknown): ValidationResult {
|
|
67
68
|
return lexicons.validate('com.atproto.server.describeServer#links', v)
|
|
68
69
|
}
|
|
70
|
+
|
|
71
|
+
export interface Contact {
|
|
72
|
+
email?: string
|
|
73
|
+
[k: string]: unknown
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function isContact(v: unknown): v is Contact {
|
|
77
|
+
return (
|
|
78
|
+
isObj(v) &&
|
|
79
|
+
hasProp(v, '$type') &&
|
|
80
|
+
v.$type === 'com.atproto.server.describeServer#contact'
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function validateContact(v: unknown): ValidationResult {
|
|
85
|
+
return lexicons.validate('com.atproto.server.describeServer#contact', v)
|
|
86
|
+
}
|
package/src/mod-service/index.ts
CHANGED
|
@@ -29,8 +29,6 @@ import {
|
|
|
29
29
|
ModerationEventRow,
|
|
30
30
|
ModerationSubjectStatusRow,
|
|
31
31
|
ReversibleModerationEvent,
|
|
32
|
-
UNSPECCED_TAKEDOWN_BLOBS_LABEL,
|
|
33
|
-
UNSPECCED_TAKEDOWN_LABEL,
|
|
34
32
|
} from './types'
|
|
35
33
|
import { ModerationEvent } from '../db/schema/moderation_event'
|
|
36
34
|
import { StatusKeyset, TimeIdKeyset, paginate } from '../db/pagination'
|
|
@@ -480,8 +478,10 @@ export class ModerationService {
|
|
|
480
478
|
)
|
|
481
479
|
.returning('id')
|
|
482
480
|
.execute()
|
|
481
|
+
|
|
482
|
+
const takedownLabel = isSuspend ? SUSPEND_LABEL : TAKEDOWN_LABEL
|
|
483
483
|
await this.formatAndCreateLabels(subject.did, null, {
|
|
484
|
-
create: [
|
|
484
|
+
create: [takedownLabel],
|
|
485
485
|
})
|
|
486
486
|
|
|
487
487
|
this.db.onCommit(() => {
|
|
@@ -506,8 +506,18 @@ export class ModerationService {
|
|
|
506
506
|
})
|
|
507
507
|
.returning('id')
|
|
508
508
|
.execute()
|
|
509
|
+
|
|
510
|
+
const existingTakedownLabels = await this.db.db
|
|
511
|
+
.selectFrom('label')
|
|
512
|
+
.where('label.uri', '=', subject.did)
|
|
513
|
+
.where('label.val', 'in', [TAKEDOWN_LABEL, SUSPEND_LABEL])
|
|
514
|
+
.where('neg', '=', false)
|
|
515
|
+
.selectAll()
|
|
516
|
+
.execute()
|
|
517
|
+
|
|
518
|
+
const takedownVals = existingTakedownLabels.map((row) => row.val)
|
|
509
519
|
await this.formatAndCreateLabels(subject.did, null, {
|
|
510
|
-
negate:
|
|
520
|
+
negate: takedownVals,
|
|
511
521
|
})
|
|
512
522
|
|
|
513
523
|
this.db.onCommit(() => {
|
|
@@ -521,44 +531,12 @@ export class ModerationService {
|
|
|
521
531
|
|
|
522
532
|
async takedownRecord(subject: RecordSubject, takedownId: number) {
|
|
523
533
|
this.db.assertTransaction()
|
|
524
|
-
const takedownRef = `BSKY-TAKEDOWN-${takedownId}`
|
|
525
|
-
const values = this.eventPusher.takedowns.map((eventType) => ({
|
|
526
|
-
eventType,
|
|
527
|
-
subjectDid: subject.did,
|
|
528
|
-
subjectUri: subject.uri,
|
|
529
|
-
subjectCid: subject.cid,
|
|
530
|
-
takedownRef,
|
|
531
|
-
}))
|
|
532
|
-
const blobCids = subject.blobCids
|
|
533
|
-
const labels: string[] = [UNSPECCED_TAKEDOWN_LABEL]
|
|
534
|
-
if (blobCids && blobCids.length > 0) {
|
|
535
|
-
labels.push(UNSPECCED_TAKEDOWN_BLOBS_LABEL)
|
|
536
|
-
}
|
|
537
|
-
const recordEvts = await this.db.db
|
|
538
|
-
.insertInto('record_push_event')
|
|
539
|
-
.values(values)
|
|
540
|
-
.onConflict((oc) =>
|
|
541
|
-
oc.columns(['subjectUri', 'eventType']).doUpdateSet({
|
|
542
|
-
takedownRef,
|
|
543
|
-
confirmedAt: null,
|
|
544
|
-
attempts: 0,
|
|
545
|
-
lastAttempted: null,
|
|
546
|
-
}),
|
|
547
|
-
)
|
|
548
|
-
.returning('id')
|
|
549
|
-
.execute()
|
|
550
534
|
await this.formatAndCreateLabels(subject.uri, subject.cid, {
|
|
551
|
-
create:
|
|
552
|
-
})
|
|
553
|
-
|
|
554
|
-
this.db.onCommit(() => {
|
|
555
|
-
this.backgroundQueue.add(async () => {
|
|
556
|
-
await Promise.all(
|
|
557
|
-
recordEvts.map((evt) => this.eventPusher.attemptRecordEvent(evt.id)),
|
|
558
|
-
)
|
|
559
|
-
})
|
|
535
|
+
create: [TAKEDOWN_LABEL],
|
|
560
536
|
})
|
|
561
537
|
|
|
538
|
+
const takedownRef = `BSKY-TAKEDOWN-${takedownId}`
|
|
539
|
+
const blobCids = subject.blobCids
|
|
562
540
|
if (blobCids && blobCids.length > 0) {
|
|
563
541
|
const blobValues: Insertable<BlobPushEvent>[] = []
|
|
564
542
|
for (const eventType of this.eventPusher.takedowns) {
|
|
@@ -613,37 +591,11 @@ export class ModerationService {
|
|
|
613
591
|
|
|
614
592
|
async reverseTakedownRecord(subject: RecordSubject) {
|
|
615
593
|
this.db.assertTransaction()
|
|
616
|
-
const labels: string[] = [UNSPECCED_TAKEDOWN_LABEL]
|
|
617
|
-
const blobCids = subject.blobCids
|
|
618
|
-
if (blobCids && blobCids.length > 0) {
|
|
619
|
-
labels.push(UNSPECCED_TAKEDOWN_BLOBS_LABEL)
|
|
620
|
-
}
|
|
621
|
-
const recordEvts = await this.db.db
|
|
622
|
-
.updateTable('record_push_event')
|
|
623
|
-
.where('eventType', 'in', TAKEDOWNS)
|
|
624
|
-
.where('subjectDid', '=', subject.did)
|
|
625
|
-
.where('subjectUri', '=', subject.uri)
|
|
626
|
-
.set({
|
|
627
|
-
takedownRef: null,
|
|
628
|
-
confirmedAt: null,
|
|
629
|
-
attempts: 0,
|
|
630
|
-
lastAttempted: null,
|
|
631
|
-
})
|
|
632
|
-
.returning('id')
|
|
633
|
-
.execute()
|
|
634
594
|
await this.formatAndCreateLabels(subject.uri, subject.cid, {
|
|
635
|
-
negate:
|
|
636
|
-
})
|
|
637
|
-
this.db.onCommit(() => {
|
|
638
|
-
this.backgroundQueue.add(async () => {
|
|
639
|
-
await Promise.all(
|
|
640
|
-
recordEvts.map((evt) =>
|
|
641
|
-
this.eventPusher.attemptRecordEvent(evt.id),
|
|
642
|
-
),
|
|
643
|
-
)
|
|
644
|
-
})
|
|
645
|
-
})
|
|
595
|
+
negate: [TAKEDOWN_LABEL],
|
|
596
|
+
})
|
|
646
597
|
|
|
598
|
+
const blobCids = subject.blobCids
|
|
647
599
|
if (blobCids && blobCids.length > 0) {
|
|
648
600
|
const blobEvts = await this.db.db
|
|
649
601
|
.updateTable('blob_push_event')
|
|
@@ -907,6 +859,9 @@ export class ModerationService {
|
|
|
907
859
|
id: sql`${excluded('id')}`,
|
|
908
860
|
neg: sql`${excluded('neg')}`,
|
|
909
861
|
cts: sql`${excluded('cts')}`,
|
|
862
|
+
exp: sql`${excluded('exp')}`,
|
|
863
|
+
sig: sql`${excluded('sig')}`,
|
|
864
|
+
signingKeyId: sql`${excluded('signingKeyId')}`,
|
|
910
865
|
}),
|
|
911
866
|
)
|
|
912
867
|
.returningAll()
|
|
@@ -960,6 +915,9 @@ const isSafeUrl = (url: URL) => {
|
|
|
960
915
|
|
|
961
916
|
const TAKEDOWNS = ['pds_takedown' as const, 'appview_takedown' as const]
|
|
962
917
|
|
|
918
|
+
export const TAKEDOWN_LABEL = '!takedown'
|
|
919
|
+
export const SUSPEND_LABEL = '!suspend'
|
|
920
|
+
|
|
963
921
|
export type TakedownSubjects = {
|
|
964
922
|
did: string
|
|
965
923
|
subjects: (RepoRef | RepoBlobRef | StrongRef)[]
|
package/src/mod-service/types.ts
CHANGED
|
@@ -31,7 +31,3 @@ export type ModEventType =
|
|
|
31
31
|
| ToolsOzoneModerationDefs.ModEventMute
|
|
32
32
|
| ToolsOzoneModerationDefs.ModEventReverseTakedown
|
|
33
33
|
| ToolsOzoneModerationDefs.ModEventTag
|
|
34
|
-
|
|
35
|
-
export const UNSPECCED_TAKEDOWN_LABEL = '!unspecced-takedown'
|
|
36
|
-
|
|
37
|
-
export const UNSPECCED_TAKEDOWN_BLOBS_LABEL = '!unspecced-takedown-blobs'
|
package/src/mod-service/util.ts
CHANGED
|
@@ -12,7 +12,7 @@ export const formatLabel = (row: LabelRow): Label => {
|
|
|
12
12
|
uri: row.uri,
|
|
13
13
|
cid: row.cid === '' ? undefined : row.cid,
|
|
14
14
|
val: row.val,
|
|
15
|
-
neg: row.neg,
|
|
15
|
+
neg: row.neg === true ? true : undefined,
|
|
16
16
|
cts: row.cts,
|
|
17
17
|
exp: row.exp ?? undefined,
|
|
18
18
|
sig: row.sig ? new Uint8Array(row.sig) : undefined,
|
package/src/mod-service/views.ts
CHANGED
|
@@ -573,6 +573,6 @@ export function getSelfLabels(details: {
|
|
|
573
573
|
? normalizeDatetimeAlways(record.createdAt)
|
|
574
574
|
: new Date(0).toISOString()
|
|
575
575
|
return record.labels.values.map(({ val }) => {
|
|
576
|
-
return { src, uri, cid, val, cts
|
|
576
|
+
return { src, uri, cid, val, cts }
|
|
577
577
|
})
|
|
578
578
|
}
|
|
@@ -10,19 +10,17 @@ Object {
|
|
|
10
10
|
Object {
|
|
11
11
|
"cid": "cids(0)",
|
|
12
12
|
"cts": "1970-01-01T00:00:00.000Z",
|
|
13
|
-
"neg": false,
|
|
14
13
|
"sig": Object {
|
|
15
14
|
"$bytes": "sig(0)",
|
|
16
15
|
},
|
|
17
16
|
"src": "user(2)",
|
|
18
17
|
"uri": "record(0)",
|
|
19
|
-
"val": "!
|
|
18
|
+
"val": "!takedown",
|
|
20
19
|
"ver": 1,
|
|
21
20
|
},
|
|
22
21
|
Object {
|
|
23
22
|
"cid": "cids(0)",
|
|
24
23
|
"cts": "1970-01-01T00:00:00.000Z",
|
|
25
|
-
"neg": false,
|
|
26
24
|
"src": "user(0)",
|
|
27
25
|
"uri": "record(0)",
|
|
28
26
|
"val": "self-label",
|
|
@@ -111,19 +109,17 @@ Object {
|
|
|
111
109
|
Object {
|
|
112
110
|
"cid": "cids(0)",
|
|
113
111
|
"cts": "1970-01-01T00:00:00.000Z",
|
|
114
|
-
"neg": false,
|
|
115
112
|
"sig": Object {
|
|
116
113
|
"$bytes": "sig(0)",
|
|
117
114
|
},
|
|
118
115
|
"src": "user(2)",
|
|
119
116
|
"uri": "record(0)",
|
|
120
|
-
"val": "!
|
|
117
|
+
"val": "!takedown",
|
|
121
118
|
"ver": 1,
|
|
122
119
|
},
|
|
123
120
|
Object {
|
|
124
121
|
"cid": "cids(0)",
|
|
125
122
|
"cts": "1970-01-01T00:00:00.000Z",
|
|
126
|
-
"neg": false,
|
|
127
123
|
"src": "user(0)",
|
|
128
124
|
"uri": "record(0)",
|
|
129
125
|
"val": "self-label",
|
|
@@ -11,13 +11,12 @@ Object {
|
|
|
11
11
|
"labels": Array [
|
|
12
12
|
Object {
|
|
13
13
|
"cts": "1970-01-01T00:00:00.000Z",
|
|
14
|
-
"neg": false,
|
|
15
14
|
"sig": Object {
|
|
16
15
|
"$bytes": "sig(0)",
|
|
17
16
|
},
|
|
18
17
|
"src": "user(2)",
|
|
19
18
|
"uri": "user(0)",
|
|
20
|
-
"val": "!
|
|
19
|
+
"val": "!takedown",
|
|
21
20
|
"ver": 1,
|
|
22
21
|
},
|
|
23
22
|
],
|
package/tests/moderation.test.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TestNetwork,
|
|
3
|
+
TestOzone,
|
|
3
4
|
ImageRef,
|
|
4
5
|
RecordRef,
|
|
5
6
|
SeedClient,
|
|
@@ -20,12 +21,8 @@ import {
|
|
|
20
21
|
REVIEWESCALATED,
|
|
21
22
|
} from '../src/lexicon/types/tools/ozone/moderation/defs'
|
|
22
23
|
import { EventReverser } from '../src'
|
|
23
|
-
import { TestOzone } from '@atproto/dev-env/src/ozone'
|
|
24
24
|
import { ImageInvalidator } from '../src/image-invalidator'
|
|
25
|
-
import {
|
|
26
|
-
UNSPECCED_TAKEDOWN_BLOBS_LABEL,
|
|
27
|
-
UNSPECCED_TAKEDOWN_LABEL,
|
|
28
|
-
} from '../src/mod-service/types'
|
|
25
|
+
import { TAKEDOWN_LABEL } from '../src/mod-service'
|
|
29
26
|
|
|
30
27
|
describe('moderation', () => {
|
|
31
28
|
let network: TestNetwork
|
|
@@ -542,10 +539,7 @@ describe('moderation', () => {
|
|
|
542
539
|
)
|
|
543
540
|
expect(bskyRes1.data.takedown?.applied).toBe(true)
|
|
544
541
|
|
|
545
|
-
const takedownLabel1 = await getLabel(
|
|
546
|
-
sc.dids.bob,
|
|
547
|
-
UNSPECCED_TAKEDOWN_LABEL,
|
|
548
|
-
)
|
|
542
|
+
const takedownLabel1 = await getLabel(sc.dids.bob, TAKEDOWN_LABEL)
|
|
549
543
|
expect(takedownLabel1).toBeDefined()
|
|
550
544
|
|
|
551
545
|
// cleanup
|
|
@@ -570,52 +564,7 @@ describe('moderation', () => {
|
|
|
570
564
|
)
|
|
571
565
|
expect(bskyRes2.data.takedown?.applied).toBe(false)
|
|
572
566
|
|
|
573
|
-
const takedownLabel2 = await getLabel(
|
|
574
|
-
sc.dids.bob,
|
|
575
|
-
UNSPECCED_TAKEDOWN_LABEL,
|
|
576
|
-
)
|
|
577
|
-
expect(takedownLabel2).toBeUndefined()
|
|
578
|
-
})
|
|
579
|
-
|
|
580
|
-
it('fans out record takedowns', async () => {
|
|
581
|
-
const post = sc.posts[sc.dids.bob][0].ref
|
|
582
|
-
const uri = post.uriStr
|
|
583
|
-
await modClient.performTakedown({
|
|
584
|
-
subject: recordSubject(post),
|
|
585
|
-
})
|
|
586
|
-
await ozone.processAll()
|
|
587
|
-
|
|
588
|
-
const pdsRes1 = await pdsAgent.api.com.atproto.admin.getSubjectStatus(
|
|
589
|
-
{ uri },
|
|
590
|
-
{ headers: network.pds.adminAuthHeaders() },
|
|
591
|
-
)
|
|
592
|
-
expect(pdsRes1.data.takedown?.applied).toBe(true)
|
|
593
|
-
|
|
594
|
-
const bskyRes1 = await bskyAgent.api.com.atproto.admin.getSubjectStatus(
|
|
595
|
-
{ uri },
|
|
596
|
-
{ headers: network.bsky.adminAuthHeaders() },
|
|
597
|
-
)
|
|
598
|
-
expect(bskyRes1.data.takedown?.applied).toBe(true)
|
|
599
|
-
|
|
600
|
-
const takedownLabel1 = await getLabel(uri, UNSPECCED_TAKEDOWN_LABEL)
|
|
601
|
-
expect(takedownLabel1).toBeDefined()
|
|
602
|
-
|
|
603
|
-
// cleanup
|
|
604
|
-
await modClient.performReverseTakedown({ subject: recordSubject(post) })
|
|
605
|
-
await ozone.processAll()
|
|
606
|
-
|
|
607
|
-
const pdsRes2 = await pdsAgent.api.com.atproto.admin.getSubjectStatus(
|
|
608
|
-
{ uri },
|
|
609
|
-
{ headers: network.pds.adminAuthHeaders() },
|
|
610
|
-
)
|
|
611
|
-
expect(pdsRes2.data.takedown?.applied).toBe(false)
|
|
612
|
-
const bskyRes2 = await bskyAgent.api.com.atproto.admin.getSubjectStatus(
|
|
613
|
-
{ uri },
|
|
614
|
-
{ headers: network.bsky.adminAuthHeaders() },
|
|
615
|
-
)
|
|
616
|
-
expect(bskyRes2.data.takedown?.applied).toBe(false)
|
|
617
|
-
|
|
618
|
-
const takedownLabel2 = await getLabel(uri, UNSPECCED_TAKEDOWN_LABEL)
|
|
567
|
+
const takedownLabel2 = await getLabel(sc.dids.bob, TAKEDOWN_LABEL)
|
|
619
568
|
expect(takedownLabel2).toBeUndefined()
|
|
620
569
|
})
|
|
621
570
|
|
|
@@ -713,22 +662,6 @@ describe('moderation', () => {
|
|
|
713
662
|
})
|
|
714
663
|
})
|
|
715
664
|
|
|
716
|
-
it('serves label when authed', async () => {
|
|
717
|
-
const { data: unauthed } = await agent.api.com.atproto.temp.fetchLabels(
|
|
718
|
-
{},
|
|
719
|
-
)
|
|
720
|
-
expect(unauthed.labels.map((l) => l.val)).not.toContain(
|
|
721
|
-
UNSPECCED_TAKEDOWN_LABEL,
|
|
722
|
-
)
|
|
723
|
-
const { data: authed } = await agent.api.com.atproto.temp.fetchLabels(
|
|
724
|
-
{},
|
|
725
|
-
{ headers: network.bsky.adminAuthHeaders() },
|
|
726
|
-
)
|
|
727
|
-
expect(authed.labels.map((l) => l.val)).toContain(
|
|
728
|
-
UNSPECCED_TAKEDOWN_LABEL,
|
|
729
|
-
)
|
|
730
|
-
})
|
|
731
|
-
|
|
732
665
|
async function emitLabelEvent(
|
|
733
666
|
opts: Partial<ToolsOzoneModerationEmitEvent.InputSchema> & {
|
|
734
667
|
subject: ToolsOzoneModerationEmitEvent.InputSchema['subject']
|
|
@@ -860,14 +793,6 @@ describe('moderation', () => {
|
|
|
860
793
|
expect(res.data.takedown?.applied).toBe(true)
|
|
861
794
|
})
|
|
862
795
|
|
|
863
|
-
it('creates a takedown blobs label', async () => {
|
|
864
|
-
const label = await getLabel(
|
|
865
|
-
post.ref.uriStr,
|
|
866
|
-
UNSPECCED_TAKEDOWN_BLOBS_LABEL,
|
|
867
|
-
)
|
|
868
|
-
expect(label).toBeDefined()
|
|
869
|
-
})
|
|
870
|
-
|
|
871
796
|
it('restores blob when action is reversed.', async () => {
|
|
872
797
|
await modClient.performReverseTakedown({
|
|
873
798
|
subject: recordSubject(post.ref),
|
|
@@ -898,30 +823,6 @@ describe('moderation', () => {
|
|
|
898
823
|
)
|
|
899
824
|
expect(res.data.takedown?.applied).toBe(false)
|
|
900
825
|
})
|
|
901
|
-
|
|
902
|
-
it('serves label when authed', async () => {
|
|
903
|
-
const { data: unauthed } = await agent.api.com.atproto.temp.fetchLabels(
|
|
904
|
-
{},
|
|
905
|
-
)
|
|
906
|
-
expect(unauthed.labels.map((l) => l.val)).not.toContain(
|
|
907
|
-
UNSPECCED_TAKEDOWN_BLOBS_LABEL,
|
|
908
|
-
)
|
|
909
|
-
const { data: authed } = await agent.api.com.atproto.temp.fetchLabels(
|
|
910
|
-
{},
|
|
911
|
-
{ headers: network.bsky.adminAuthHeaders() },
|
|
912
|
-
)
|
|
913
|
-
expect(authed.labels.map((l) => l.val)).toContain(
|
|
914
|
-
UNSPECCED_TAKEDOWN_BLOBS_LABEL,
|
|
915
|
-
)
|
|
916
|
-
})
|
|
917
|
-
|
|
918
|
-
it('negates takedown blobs label on reversal', async () => {
|
|
919
|
-
const label = await getLabel(
|
|
920
|
-
post.ref.uriStr,
|
|
921
|
-
UNSPECCED_TAKEDOWN_BLOBS_LABEL,
|
|
922
|
-
)
|
|
923
|
-
expect(label).toBeUndefined()
|
|
924
|
-
})
|
|
925
826
|
})
|
|
926
827
|
})
|
|
927
828
|
|
|
@@ -30,42 +30,36 @@ describe('ozone query labels', () => {
|
|
|
30
30
|
src: EXAMPLE_LABELER,
|
|
31
31
|
uri: 'did:example:blah',
|
|
32
32
|
val: 'spam',
|
|
33
|
-
neg: false,
|
|
34
33
|
cts: new Date().toISOString(),
|
|
35
34
|
},
|
|
36
35
|
{
|
|
37
36
|
src: EXAMPLE_LABELER,
|
|
38
37
|
uri: 'did:example:blah',
|
|
39
38
|
val: 'impersonation',
|
|
40
|
-
neg: false,
|
|
41
39
|
cts: new Date().toISOString(),
|
|
42
40
|
},
|
|
43
41
|
{
|
|
44
42
|
src: EXAMPLE_LABELER,
|
|
45
43
|
uri: 'at://did:example:blah/app.bsky.feed.post/1234abcde',
|
|
46
44
|
val: 'spam',
|
|
47
|
-
neg: false,
|
|
48
45
|
cts: new Date().toISOString(),
|
|
49
46
|
},
|
|
50
47
|
{
|
|
51
48
|
src: EXAMPLE_LABELER,
|
|
52
49
|
uri: 'at://did:example:blah/app.bsky.feed.post/1234abcfg',
|
|
53
50
|
val: 'spam',
|
|
54
|
-
neg: false,
|
|
55
51
|
cts: new Date().toISOString(),
|
|
56
52
|
},
|
|
57
53
|
{
|
|
58
54
|
src: EXAMPLE_LABELER,
|
|
59
55
|
uri: 'at://did:example:blah/app.bsky.actor.profile/self',
|
|
60
56
|
val: 'spam',
|
|
61
|
-
neg: false,
|
|
62
57
|
cts: new Date().toISOString(),
|
|
63
58
|
},
|
|
64
59
|
{
|
|
65
60
|
src: EXAMPLE_LABELER,
|
|
66
61
|
uri: 'did:example:thing',
|
|
67
62
|
val: 'spam',
|
|
68
|
-
neg: false,
|
|
69
63
|
cts: new Date().toISOString(),
|
|
70
64
|
},
|
|
71
65
|
]
|