@atproto/ozone 0.0.7 → 0.0.8
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 +7 -0
- package/LICENSE.txt +1 -1
- package/dist/db/index.js +15 -1
- package/dist/db/index.js.map +3 -3
- package/dist/db/migrations/20240201T051104136Z-mod-event-blobs.d.ts +3 -0
- package/dist/db/migrations/index.d.ts +1 -0
- package/dist/db/schema/moderation_event.d.ts +1 -0
- package/dist/db/types.d.ts +1 -0
- package/dist/index.js +276 -202
- package/dist/index.js.map +3 -3
- package/dist/lexicon/index.d.ts +0 -2
- package/dist/lexicon/lexicons.d.ts +38 -47
- package/dist/lexicon/types/com/atproto/admin/defs.d.ts +2 -2
- package/dist/lexicon/types/com/atproto/admin/queryModerationEvents.d.ts +7 -0
- package/dist/mod-service/index.d.ts +13 -4
- package/dist/mod-service/subject.d.ts +3 -0
- package/dist/mod-service/types.d.ts +2 -0
- package/package.json +5 -5
- package/src/api/admin/emitModerationEvent.ts +9 -6
- package/src/api/admin/queryModerationEvents.ts +14 -0
- package/src/api/moderation/util.ts +1 -0
- package/src/api/temp/fetchLabels.ts +36 -21
- package/src/context.ts +1 -0
- package/src/daemon/context.ts +1 -0
- package/src/db/migrations/20240201T051104136Z-mod-event-blobs.ts +15 -0
- package/src/db/migrations/index.ts +1 -0
- package/src/db/schema/moderation_event.ts +1 -0
- package/src/db/types.ts +6 -1
- package/src/lexicon/index.ts +0 -12
- package/src/lexicon/lexicons.ts +43 -50
- package/src/lexicon/types/com/atproto/admin/defs.ts +2 -0
- package/src/lexicon/types/com/atproto/admin/queryModerationEvents.ts +13 -0
- package/src/mod-service/index.ts +142 -64
- package/src/mod-service/status.ts +3 -2
- package/src/mod-service/subject.ts +9 -2
- package/src/mod-service/types.ts +4 -0
- package/src/mod-service/views.ts +1 -1
- package/tests/__snapshots__/get-record.test.ts.snap +16 -0
- package/tests/__snapshots__/get-repo.test.ts.snap +9 -1
- package/tests/moderation-appeals.test.ts +1 -1
- package/tests/moderation-events.test.ts +161 -8
- package/tests/moderation-statuses.test.ts +55 -0
- package/tests/moderation.test.ts +133 -34
- package/dist/lexicon/types/app/bsky/unspecced/getTimelineSkeleton.d.ts +0 -35
- package/src/lexicon/types/app/bsky/unspecced/getTimelineSkeleton.ts +0 -49
package/dist/lexicon/index.d.ts
CHANGED
|
@@ -117,7 +117,6 @@ import * as AppBskyNotificationRegisterPush from './types/app/bsky/notification/
|
|
|
117
117
|
import * as AppBskyNotificationUpdateSeen from './types/app/bsky/notification/updateSeen';
|
|
118
118
|
import * as AppBskyUnspeccedGetPopularFeedGenerators from './types/app/bsky/unspecced/getPopularFeedGenerators';
|
|
119
119
|
import * as AppBskyUnspeccedGetTaggedSuggestions from './types/app/bsky/unspecced/getTaggedSuggestions';
|
|
120
|
-
import * as AppBskyUnspeccedGetTimelineSkeleton from './types/app/bsky/unspecced/getTimelineSkeleton';
|
|
121
120
|
import * as AppBskyUnspeccedSearchActorsSkeleton from './types/app/bsky/unspecced/searchActorsSkeleton';
|
|
122
121
|
import * as AppBskyUnspeccedSearchPostsSkeleton from './types/app/bsky/unspecced/searchPostsSkeleton';
|
|
123
122
|
export declare const COM_ATPROTO_ADMIN: {
|
|
@@ -355,7 +354,6 @@ export declare class AppBskyUnspeccedNS {
|
|
|
355
354
|
constructor(server: Server);
|
|
356
355
|
getPopularFeedGenerators<AV extends AuthVerifier>(cfg: ConfigOf<AV, AppBskyUnspeccedGetPopularFeedGenerators.Handler<ExtractAuth<AV>>, AppBskyUnspeccedGetPopularFeedGenerators.HandlerReqCtx<ExtractAuth<AV>>>): void;
|
|
357
356
|
getTaggedSuggestions<AV extends AuthVerifier>(cfg: ConfigOf<AV, AppBskyUnspeccedGetTaggedSuggestions.Handler<ExtractAuth<AV>>, AppBskyUnspeccedGetTaggedSuggestions.HandlerReqCtx<ExtractAuth<AV>>>): void;
|
|
358
|
-
getTimelineSkeleton<AV extends AuthVerifier>(cfg: ConfigOf<AV, AppBskyUnspeccedGetTimelineSkeleton.Handler<ExtractAuth<AV>>, AppBskyUnspeccedGetTimelineSkeleton.HandlerReqCtx<ExtractAuth<AV>>>): void;
|
|
359
357
|
searchActorsSkeleton<AV extends AuthVerifier>(cfg: ConfigOf<AV, AppBskyUnspeccedSearchActorsSkeleton.Handler<ExtractAuth<AV>>, AppBskyUnspeccedSearchActorsSkeleton.HandlerReqCtx<ExtractAuth<AV>>>): void;
|
|
360
358
|
searchPostsSkeleton<AV extends AuthVerifier>(cfg: ConfigOf<AV, AppBskyUnspeccedSearchPostsSkeleton.Handler<ExtractAuth<AV>>, AppBskyUnspeccedSearchPostsSkeleton.HandlerReqCtx<ExtractAuth<AV>>>): void;
|
|
361
359
|
}
|
|
@@ -1296,6 +1296,16 @@ export declare const schemaDict: {
|
|
|
1296
1296
|
enum: string[];
|
|
1297
1297
|
description: string;
|
|
1298
1298
|
};
|
|
1299
|
+
createdAfter: {
|
|
1300
|
+
type: string;
|
|
1301
|
+
format: string;
|
|
1302
|
+
description: string;
|
|
1303
|
+
};
|
|
1304
|
+
createdBefore: {
|
|
1305
|
+
type: string;
|
|
1306
|
+
format: string;
|
|
1307
|
+
description: string;
|
|
1308
|
+
};
|
|
1299
1309
|
subject: {
|
|
1300
1310
|
type: string;
|
|
1301
1311
|
format: string;
|
|
@@ -1311,6 +1321,34 @@ export declare const schemaDict: {
|
|
|
1311
1321
|
maximum: number;
|
|
1312
1322
|
default: number;
|
|
1313
1323
|
};
|
|
1324
|
+
hasComment: {
|
|
1325
|
+
type: string;
|
|
1326
|
+
description: string;
|
|
1327
|
+
};
|
|
1328
|
+
comment: {
|
|
1329
|
+
type: string;
|
|
1330
|
+
description: string;
|
|
1331
|
+
};
|
|
1332
|
+
addedLabels: {
|
|
1333
|
+
type: string;
|
|
1334
|
+
items: {
|
|
1335
|
+
type: string;
|
|
1336
|
+
};
|
|
1337
|
+
description: string;
|
|
1338
|
+
};
|
|
1339
|
+
removedLabels: {
|
|
1340
|
+
type: string;
|
|
1341
|
+
items: {
|
|
1342
|
+
type: string;
|
|
1343
|
+
};
|
|
1344
|
+
description: string;
|
|
1345
|
+
};
|
|
1346
|
+
reportTypes: {
|
|
1347
|
+
type: string;
|
|
1348
|
+
items: {
|
|
1349
|
+
type: string;
|
|
1350
|
+
};
|
|
1351
|
+
};
|
|
1314
1352
|
cursor: {
|
|
1315
1353
|
type: string;
|
|
1316
1354
|
};
|
|
@@ -7602,52 +7640,6 @@ export declare const schemaDict: {
|
|
|
7602
7640
|
};
|
|
7603
7641
|
};
|
|
7604
7642
|
};
|
|
7605
|
-
AppBskyUnspeccedGetTimelineSkeleton: {
|
|
7606
|
-
lexicon: number;
|
|
7607
|
-
id: string;
|
|
7608
|
-
defs: {
|
|
7609
|
-
main: {
|
|
7610
|
-
type: string;
|
|
7611
|
-
description: string;
|
|
7612
|
-
parameters: {
|
|
7613
|
-
type: string;
|
|
7614
|
-
properties: {
|
|
7615
|
-
limit: {
|
|
7616
|
-
type: string;
|
|
7617
|
-
minimum: number;
|
|
7618
|
-
maximum: number;
|
|
7619
|
-
default: number;
|
|
7620
|
-
};
|
|
7621
|
-
cursor: {
|
|
7622
|
-
type: string;
|
|
7623
|
-
};
|
|
7624
|
-
};
|
|
7625
|
-
};
|
|
7626
|
-
output: {
|
|
7627
|
-
encoding: string;
|
|
7628
|
-
schema: {
|
|
7629
|
-
type: string;
|
|
7630
|
-
required: string[];
|
|
7631
|
-
properties: {
|
|
7632
|
-
cursor: {
|
|
7633
|
-
type: string;
|
|
7634
|
-
};
|
|
7635
|
-
feed: {
|
|
7636
|
-
type: string;
|
|
7637
|
-
items: {
|
|
7638
|
-
type: string;
|
|
7639
|
-
ref: string;
|
|
7640
|
-
};
|
|
7641
|
-
};
|
|
7642
|
-
};
|
|
7643
|
-
};
|
|
7644
|
-
};
|
|
7645
|
-
errors: {
|
|
7646
|
-
name: string;
|
|
7647
|
-
}[];
|
|
7648
|
-
};
|
|
7649
|
-
};
|
|
7650
|
-
};
|
|
7651
7643
|
AppBskyUnspeccedSearchActorsSkeleton: {
|
|
7652
7644
|
lexicon: number;
|
|
7653
7645
|
id: string;
|
|
@@ -7911,7 +7903,6 @@ export declare const ids: {
|
|
|
7911
7903
|
AppBskyUnspeccedDefs: string;
|
|
7912
7904
|
AppBskyUnspeccedGetPopularFeedGenerators: string;
|
|
7913
7905
|
AppBskyUnspeccedGetTaggedSuggestions: string;
|
|
7914
|
-
AppBskyUnspeccedGetTimelineSkeleton: string;
|
|
7915
7906
|
AppBskyUnspeccedSearchActorsSkeleton: string;
|
|
7916
7907
|
AppBskyUnspeccedSearchPostsSkeleton: string;
|
|
7917
7908
|
};
|
|
@@ -12,7 +12,7 @@ export declare function isStatusAttr(v: unknown): v is StatusAttr;
|
|
|
12
12
|
export declare function validateStatusAttr(v: unknown): ValidationResult;
|
|
13
13
|
export interface ModEventView {
|
|
14
14
|
id: number;
|
|
15
|
-
event: ModEventTakedown | ModEventReverseTakedown | ModEventComment | ModEventReport | ModEventLabel | ModEventAcknowledge | ModEventEscalate | ModEventMute | ModEventEmail | {
|
|
15
|
+
event: ModEventTakedown | ModEventReverseTakedown | ModEventComment | ModEventReport | ModEventLabel | ModEventAcknowledge | ModEventEscalate | ModEventMute | ModEventEmail | ModEventResolveAppeal | {
|
|
16
16
|
$type: string;
|
|
17
17
|
[k: string]: unknown;
|
|
18
18
|
};
|
|
@@ -31,7 +31,7 @@ export declare function isModEventView(v: unknown): v is ModEventView;
|
|
|
31
31
|
export declare function validateModEventView(v: unknown): ValidationResult;
|
|
32
32
|
export interface ModEventViewDetail {
|
|
33
33
|
id: number;
|
|
34
|
-
event: ModEventTakedown | ModEventReverseTakedown | ModEventComment | ModEventReport | ModEventLabel | ModEventAcknowledge | ModEventEscalate | ModEventMute | ModEventResolveAppeal | {
|
|
34
|
+
event: ModEventTakedown | ModEventReverseTakedown | ModEventComment | ModEventReport | ModEventLabel | ModEventAcknowledge | ModEventEscalate | ModEventMute | ModEventEmail | ModEventResolveAppeal | {
|
|
35
35
|
$type: string;
|
|
36
36
|
[k: string]: unknown;
|
|
37
37
|
};
|
|
@@ -5,9 +5,16 @@ export interface QueryParams {
|
|
|
5
5
|
types?: string[];
|
|
6
6
|
createdBy?: string;
|
|
7
7
|
sortDirection: 'asc' | 'desc';
|
|
8
|
+
createdAfter?: string;
|
|
9
|
+
createdBefore?: string;
|
|
8
10
|
subject?: string;
|
|
9
11
|
includeAllUserRecords: boolean;
|
|
10
12
|
limit: number;
|
|
13
|
+
hasComment?: boolean;
|
|
14
|
+
comment?: string;
|
|
15
|
+
addedLabels?: string[];
|
|
16
|
+
removedLabels?: string[];
|
|
17
|
+
reportTypes?: string[];
|
|
11
18
|
cursor?: string;
|
|
12
19
|
}
|
|
13
20
|
export type InputSchema = undefined;
|
|
@@ -18,8 +18,9 @@ export declare class ModerationService {
|
|
|
18
18
|
eventPusher: EventPusher;
|
|
19
19
|
appviewAgent: AtpAgent;
|
|
20
20
|
private appviewAuth;
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
serverDid: string;
|
|
22
|
+
constructor(db: Database, backgroundQueue: BackgroundQueue, eventPusher: EventPusher, appviewAgent: AtpAgent, appviewAuth: AppviewAuth, serverDid: string);
|
|
23
|
+
static creator(backgroundQueue: BackgroundQueue, eventPusher: EventPusher, appviewAgent: AtpAgent, appviewAuth: AppviewAuth, serverDid: string): (db: Database) => ModerationService;
|
|
23
24
|
views: ModerationViews;
|
|
24
25
|
getEvent(id: number): Promise<ModerationEventRow | undefined>;
|
|
25
26
|
getEventOrThrow(id: number): Promise<ModerationEventRow>;
|
|
@@ -31,6 +32,13 @@ export declare class ModerationService {
|
|
|
31
32
|
includeAllUserRecords: boolean;
|
|
32
33
|
types: ModerationEvent['action'][];
|
|
33
34
|
sortDirection?: 'asc' | 'desc';
|
|
35
|
+
hasComment?: boolean;
|
|
36
|
+
comment?: string;
|
|
37
|
+
createdAfter?: string;
|
|
38
|
+
createdBefore?: string;
|
|
39
|
+
addedLabels: string[];
|
|
40
|
+
removedLabels: string[];
|
|
41
|
+
reportTypes?: string[];
|
|
34
42
|
}): Promise<{
|
|
35
43
|
cursor?: string;
|
|
36
44
|
events: ModerationEventRow[];
|
|
@@ -69,6 +77,7 @@ export declare class ModerationService {
|
|
|
69
77
|
}): Promise<ModerationEventRow>;
|
|
70
78
|
getLastReversibleEventForSubject(subject: ReversalSubject): Promise<{
|
|
71
79
|
id: number;
|
|
80
|
+
subjectBlobCids: string[] | null;
|
|
72
81
|
createdBy: string;
|
|
73
82
|
createdAt: string;
|
|
74
83
|
comment: string | null;
|
|
@@ -137,8 +146,8 @@ export declare class ModerationService {
|
|
|
137
146
|
}[];
|
|
138
147
|
cursor: string | undefined;
|
|
139
148
|
}>;
|
|
140
|
-
|
|
141
|
-
formatAndCreateLabels(
|
|
149
|
+
getStatus(subject: ModSubject): Promise<ModerationSubjectStatusRow | null>;
|
|
150
|
+
formatAndCreateLabels(uri: string, cid: string | null, labels: {
|
|
142
151
|
create?: string[];
|
|
143
152
|
negate?: string[];
|
|
144
153
|
}): Promise<Label[]>;
|
|
@@ -13,6 +13,7 @@ type SubjectInfo = {
|
|
|
13
13
|
subjectDid: string;
|
|
14
14
|
subjectUri: string | null;
|
|
15
15
|
subjectCid: string | null;
|
|
16
|
+
subjectBlobCids: string[] | null;
|
|
16
17
|
};
|
|
17
18
|
export interface ModSubject {
|
|
18
19
|
did: string;
|
|
@@ -35,6 +36,7 @@ export declare class RepoSubject implements ModSubject {
|
|
|
35
36
|
subjectDid: string;
|
|
36
37
|
subjectUri: null;
|
|
37
38
|
subjectCid: null;
|
|
39
|
+
subjectBlobCids: null;
|
|
38
40
|
};
|
|
39
41
|
lex(): RepoRef;
|
|
40
42
|
}
|
|
@@ -53,6 +55,7 @@ export declare class RecordSubject implements ModSubject {
|
|
|
53
55
|
subjectDid: string;
|
|
54
56
|
subjectUri: string;
|
|
55
57
|
subjectCid: string;
|
|
58
|
+
subjectBlobCids: string[];
|
|
56
59
|
};
|
|
57
60
|
lex(): StrongRef;
|
|
58
61
|
}
|
|
@@ -17,3 +17,5 @@ export type ModerationSubjectStatusRowWithHandle = ModerationSubjectStatusRow &
|
|
|
17
17
|
handle: string | null;
|
|
18
18
|
};
|
|
19
19
|
export type ModEventType = ComAtprotoAdminDefs.ModEventTakedown | ComAtprotoAdminDefs.ModEventAcknowledge | ComAtprotoAdminDefs.ModEventEscalate | ComAtprotoAdminDefs.ModEventComment | ComAtprotoAdminDefs.ModEventLabel | ComAtprotoAdminDefs.ModEventReport | ComAtprotoAdminDefs.ModEventMute | ComAtprotoAdminDefs.ModEventReverseTakedown;
|
|
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.0.8",
|
|
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.9.
|
|
33
|
+
"@atproto/api": "^0.9.6",
|
|
34
34
|
"@atproto/common": "^0.3.3",
|
|
35
35
|
"@atproto/crypto": "^0.3.0",
|
|
36
36
|
"@atproto/syntax": "^0.1.5",
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
"@types/pg": "^8.6.6",
|
|
47
47
|
"@types/qs": "^6.9.7",
|
|
48
48
|
"axios": "^0.27.2",
|
|
49
|
-
"@atproto/api": "^0.9.
|
|
50
|
-
"@atproto/dev-env": "^0.2.
|
|
49
|
+
"@atproto/api": "^0.9.6",
|
|
50
|
+
"@atproto/dev-env": "^0.2.29",
|
|
51
51
|
"@atproto/lex-cli": "^0.3.0",
|
|
52
|
-
"@atproto/pds": "^0.3.
|
|
52
|
+
"@atproto/pds": "^0.3.17",
|
|
53
53
|
"@atproto/xrpc": "^0.4.1"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
@@ -51,17 +51,21 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
if (isTakedownEvent || isReverseTakedownEvent) {
|
|
54
|
-
const
|
|
55
|
-
subject,
|
|
56
|
-
)
|
|
54
|
+
const status = await moderationService.getStatus(subject)
|
|
57
55
|
|
|
58
|
-
if (
|
|
56
|
+
if (status?.takendown && isTakedownEvent) {
|
|
59
57
|
throw new InvalidRequestError(`Subject is already taken down`)
|
|
60
58
|
}
|
|
61
59
|
|
|
62
|
-
if (!
|
|
60
|
+
if (!status?.takendown && isReverseTakedownEvent) {
|
|
63
61
|
throw new InvalidRequestError(`Subject is not taken down`)
|
|
64
62
|
}
|
|
63
|
+
|
|
64
|
+
if (status?.takendown && isReverseTakedownEvent && subject.isRecord()) {
|
|
65
|
+
// due to the way blob status is modeled, we should reverse takedown on all
|
|
66
|
+
// blobs for the record being restored, which aren't taken down on another record.
|
|
67
|
+
subject.blobCids = status.blobCids ?? []
|
|
68
|
+
}
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
const moderationEvent = await db.transaction(async (dbTxn) => {
|
|
@@ -92,7 +96,6 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
92
96
|
|
|
93
97
|
if (isLabelEvent) {
|
|
94
98
|
await moderationTxn.formatAndCreateLabels(
|
|
95
|
-
ctx.cfg.service.did,
|
|
96
99
|
result.subjectUri ?? result.subjectDid,
|
|
97
100
|
result.subjectCid,
|
|
98
101
|
{
|
|
@@ -13,7 +13,14 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
13
13
|
sortDirection = 'desc',
|
|
14
14
|
types,
|
|
15
15
|
includeAllUserRecords = false,
|
|
16
|
+
hasComment,
|
|
17
|
+
comment,
|
|
16
18
|
createdBy,
|
|
19
|
+
createdAfter,
|
|
20
|
+
createdBefore,
|
|
21
|
+
addedLabels = [],
|
|
22
|
+
removedLabels = [],
|
|
23
|
+
reportTypes,
|
|
17
24
|
} = params
|
|
18
25
|
const db = ctx.db
|
|
19
26
|
const modService = ctx.modService(db)
|
|
@@ -25,6 +32,13 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
25
32
|
cursor,
|
|
26
33
|
sortDirection,
|
|
27
34
|
includeAllUserRecords,
|
|
35
|
+
hasComment,
|
|
36
|
+
comment,
|
|
37
|
+
createdAfter,
|
|
38
|
+
createdBefore,
|
|
39
|
+
addedLabels,
|
|
40
|
+
removedLabels,
|
|
41
|
+
reportTypes,
|
|
28
42
|
})
|
|
29
43
|
return {
|
|
30
44
|
encoding: 'application/json',
|
|
@@ -1,29 +1,44 @@
|
|
|
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'
|
|
3
7
|
|
|
4
8
|
export default function (server: Server, ctx: AppContext) {
|
|
5
|
-
server.com.atproto.temp.fetchLabels(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
server.com.atproto.temp.fetchLabels({
|
|
10
|
+
auth: ctx.authOptionalAccessOrRoleVerifier,
|
|
11
|
+
handler: async ({ auth, params }) => {
|
|
12
|
+
const { limit } = params
|
|
13
|
+
const since =
|
|
14
|
+
params.since !== undefined ? new Date(params.since).toISOString() : ''
|
|
15
|
+
const includeUnspeccedTakedowns =
|
|
16
|
+
auth.credentials.type === 'role' && auth.credentials.admin
|
|
17
|
+
const labelRes = await ctx.db.db
|
|
18
|
+
.selectFrom('label')
|
|
19
|
+
.selectAll()
|
|
20
|
+
.orderBy('label.cts', 'asc')
|
|
21
|
+
.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
|
+
.limit(limit)
|
|
29
|
+
.execute()
|
|
16
30
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
31
|
+
const labels = labelRes.map((l) => ({
|
|
32
|
+
...l,
|
|
33
|
+
cid: l.cid === '' ? undefined : l.cid,
|
|
34
|
+
}))
|
|
21
35
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
36
|
+
return {
|
|
37
|
+
encoding: 'application/json',
|
|
38
|
+
body: {
|
|
39
|
+
labels,
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
},
|
|
28
43
|
})
|
|
29
44
|
}
|
package/src/context.ts
CHANGED
package/src/daemon/context.ts
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Kysely } from 'kysely'
|
|
2
|
+
|
|
3
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
4
|
+
await db.schema
|
|
5
|
+
.alterTable('moderation_event')
|
|
6
|
+
.addColumn('subjectBlobCids', 'jsonb')
|
|
7
|
+
.execute()
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
11
|
+
await db.schema
|
|
12
|
+
.alterTable('moderation_event')
|
|
13
|
+
.dropColumn('subjectBlobCids')
|
|
14
|
+
.execute()
|
|
15
|
+
}
|
package/src/db/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Pool as PgPool } from 'pg'
|
|
2
|
-
import { DynamicModule, RawBuilder, SelectQueryBuilder } from 'kysely'
|
|
2
|
+
import { DynamicModule, RawBuilder, SelectQueryBuilder, sql } from 'kysely'
|
|
3
3
|
|
|
4
4
|
export type DbRef = RawBuilder | ReturnType<DynamicModule['ref']>
|
|
5
5
|
|
|
@@ -13,3 +13,8 @@ export type PgOptions = {
|
|
|
13
13
|
poolMaxUses?: number
|
|
14
14
|
poolIdleTimeoutMs?: number
|
|
15
15
|
}
|
|
16
|
+
|
|
17
|
+
export const jsonb = <T>(val: T) => {
|
|
18
|
+
if (val === null) return sql<T>`null`
|
|
19
|
+
return sql<T>`${JSON.stringify(val)}::jsonb`
|
|
20
|
+
}
|
package/src/lexicon/index.ts
CHANGED
|
@@ -127,7 +127,6 @@ import * as AppBskyNotificationRegisterPush from './types/app/bsky/notification/
|
|
|
127
127
|
import * as AppBskyNotificationUpdateSeen from './types/app/bsky/notification/updateSeen'
|
|
128
128
|
import * as AppBskyUnspeccedGetPopularFeedGenerators from './types/app/bsky/unspecced/getPopularFeedGenerators'
|
|
129
129
|
import * as AppBskyUnspeccedGetTaggedSuggestions from './types/app/bsky/unspecced/getTaggedSuggestions'
|
|
130
|
-
import * as AppBskyUnspeccedGetTimelineSkeleton from './types/app/bsky/unspecced/getTimelineSkeleton'
|
|
131
130
|
import * as AppBskyUnspeccedSearchActorsSkeleton from './types/app/bsky/unspecced/searchActorsSkeleton'
|
|
132
131
|
import * as AppBskyUnspeccedSearchPostsSkeleton from './types/app/bsky/unspecced/searchPostsSkeleton'
|
|
133
132
|
|
|
@@ -1649,17 +1648,6 @@ export class AppBskyUnspeccedNS {
|
|
|
1649
1648
|
return this._server.xrpc.method(nsid, cfg)
|
|
1650
1649
|
}
|
|
1651
1650
|
|
|
1652
|
-
getTimelineSkeleton<AV extends AuthVerifier>(
|
|
1653
|
-
cfg: ConfigOf<
|
|
1654
|
-
AV,
|
|
1655
|
-
AppBskyUnspeccedGetTimelineSkeleton.Handler<ExtractAuth<AV>>,
|
|
1656
|
-
AppBskyUnspeccedGetTimelineSkeleton.HandlerReqCtx<ExtractAuth<AV>>
|
|
1657
|
-
>,
|
|
1658
|
-
) {
|
|
1659
|
-
const nsid = 'app.bsky.unspecced.getTimelineSkeleton' // @ts-ignore
|
|
1660
|
-
return this._server.xrpc.method(nsid, cfg)
|
|
1661
|
-
}
|
|
1662
|
-
|
|
1663
1651
|
searchActorsSkeleton<AV extends AuthVerifier>(
|
|
1664
1652
|
cfg: ConfigOf<
|
|
1665
1653
|
AV,
|
package/src/lexicon/lexicons.ts
CHANGED
|
@@ -91,6 +91,7 @@ export const schemaDict = {
|
|
|
91
91
|
'lex:com.atproto.admin.defs#modEventEscalate',
|
|
92
92
|
'lex:com.atproto.admin.defs#modEventMute',
|
|
93
93
|
'lex:com.atproto.admin.defs#modEventEmail',
|
|
94
|
+
'lex:com.atproto.admin.defs#modEventResolveAppeal',
|
|
94
95
|
],
|
|
95
96
|
},
|
|
96
97
|
subject: {
|
|
@@ -147,6 +148,7 @@ export const schemaDict = {
|
|
|
147
148
|
'lex:com.atproto.admin.defs#modEventAcknowledge',
|
|
148
149
|
'lex:com.atproto.admin.defs#modEventEscalate',
|
|
149
150
|
'lex:com.atproto.admin.defs#modEventMute',
|
|
151
|
+
'lex:com.atproto.admin.defs#modEventEmail',
|
|
150
152
|
'lex:com.atproto.admin.defs#modEventResolveAppeal',
|
|
151
153
|
],
|
|
152
154
|
},
|
|
@@ -1450,6 +1452,16 @@ export const schemaDict = {
|
|
|
1450
1452
|
description:
|
|
1451
1453
|
'Sort direction for the events. Defaults to descending order of created at timestamp.',
|
|
1452
1454
|
},
|
|
1455
|
+
createdAfter: {
|
|
1456
|
+
type: 'string',
|
|
1457
|
+
format: 'datetime',
|
|
1458
|
+
description: 'Retrieve events created after a given timestamp',
|
|
1459
|
+
},
|
|
1460
|
+
createdBefore: {
|
|
1461
|
+
type: 'string',
|
|
1462
|
+
format: 'datetime',
|
|
1463
|
+
description: 'Retrieve events created before a given timestamp',
|
|
1464
|
+
},
|
|
1453
1465
|
subject: {
|
|
1454
1466
|
type: 'string',
|
|
1455
1467
|
format: 'uri',
|
|
@@ -1466,6 +1478,37 @@ export const schemaDict = {
|
|
|
1466
1478
|
maximum: 100,
|
|
1467
1479
|
default: 50,
|
|
1468
1480
|
},
|
|
1481
|
+
hasComment: {
|
|
1482
|
+
type: 'boolean',
|
|
1483
|
+
description: 'If true, only events with comments are returned',
|
|
1484
|
+
},
|
|
1485
|
+
comment: {
|
|
1486
|
+
type: 'string',
|
|
1487
|
+
description:
|
|
1488
|
+
'If specified, only events with comments containing the keyword are returned',
|
|
1489
|
+
},
|
|
1490
|
+
addedLabels: {
|
|
1491
|
+
type: 'array',
|
|
1492
|
+
items: {
|
|
1493
|
+
type: 'string',
|
|
1494
|
+
},
|
|
1495
|
+
description:
|
|
1496
|
+
'If specified, only events where all of these labels were added are returned',
|
|
1497
|
+
},
|
|
1498
|
+
removedLabels: {
|
|
1499
|
+
type: 'array',
|
|
1500
|
+
items: {
|
|
1501
|
+
type: 'string',
|
|
1502
|
+
},
|
|
1503
|
+
description:
|
|
1504
|
+
'If specified, only events where all of these labels were removed are returned',
|
|
1505
|
+
},
|
|
1506
|
+
reportTypes: {
|
|
1507
|
+
type: 'array',
|
|
1508
|
+
items: {
|
|
1509
|
+
type: 'string',
|
|
1510
|
+
},
|
|
1511
|
+
},
|
|
1469
1512
|
cursor: {
|
|
1470
1513
|
type: 'string',
|
|
1471
1514
|
},
|
|
@@ -8100,55 +8143,6 @@ export const schemaDict = {
|
|
|
8100
8143
|
},
|
|
8101
8144
|
},
|
|
8102
8145
|
},
|
|
8103
|
-
AppBskyUnspeccedGetTimelineSkeleton: {
|
|
8104
|
-
lexicon: 1,
|
|
8105
|
-
id: 'app.bsky.unspecced.getTimelineSkeleton',
|
|
8106
|
-
defs: {
|
|
8107
|
-
main: {
|
|
8108
|
-
type: 'query',
|
|
8109
|
-
description:
|
|
8110
|
-
'DEPRECATED: a skeleton of a timeline. Unspecced and will be unavailable soon.',
|
|
8111
|
-
parameters: {
|
|
8112
|
-
type: 'params',
|
|
8113
|
-
properties: {
|
|
8114
|
-
limit: {
|
|
8115
|
-
type: 'integer',
|
|
8116
|
-
minimum: 1,
|
|
8117
|
-
maximum: 100,
|
|
8118
|
-
default: 50,
|
|
8119
|
-
},
|
|
8120
|
-
cursor: {
|
|
8121
|
-
type: 'string',
|
|
8122
|
-
},
|
|
8123
|
-
},
|
|
8124
|
-
},
|
|
8125
|
-
output: {
|
|
8126
|
-
encoding: 'application/json',
|
|
8127
|
-
schema: {
|
|
8128
|
-
type: 'object',
|
|
8129
|
-
required: ['feed'],
|
|
8130
|
-
properties: {
|
|
8131
|
-
cursor: {
|
|
8132
|
-
type: 'string',
|
|
8133
|
-
},
|
|
8134
|
-
feed: {
|
|
8135
|
-
type: 'array',
|
|
8136
|
-
items: {
|
|
8137
|
-
type: 'ref',
|
|
8138
|
-
ref: 'lex:app.bsky.feed.defs#skeletonFeedPost',
|
|
8139
|
-
},
|
|
8140
|
-
},
|
|
8141
|
-
},
|
|
8142
|
-
},
|
|
8143
|
-
},
|
|
8144
|
-
errors: [
|
|
8145
|
-
{
|
|
8146
|
-
name: 'UnknownFeed',
|
|
8147
|
-
},
|
|
8148
|
-
],
|
|
8149
|
-
},
|
|
8150
|
-
},
|
|
8151
|
-
},
|
|
8152
8146
|
AppBskyUnspeccedSearchActorsSkeleton: {
|
|
8153
8147
|
lexicon: 1,
|
|
8154
8148
|
id: 'app.bsky.unspecced.searchActorsSkeleton',
|
|
@@ -8438,7 +8432,6 @@ export const ids = {
|
|
|
8438
8432
|
'app.bsky.unspecced.getPopularFeedGenerators',
|
|
8439
8433
|
AppBskyUnspeccedGetTaggedSuggestions:
|
|
8440
8434
|
'app.bsky.unspecced.getTaggedSuggestions',
|
|
8441
|
-
AppBskyUnspeccedGetTimelineSkeleton: 'app.bsky.unspecced.getTimelineSkeleton',
|
|
8442
8435
|
AppBskyUnspeccedSearchActorsSkeleton:
|
|
8443
8436
|
'app.bsky.unspecced.searchActorsSkeleton',
|
|
8444
8437
|
AppBskyUnspeccedSearchPostsSkeleton: 'app.bsky.unspecced.searchPostsSkeleton',
|
|
@@ -40,6 +40,7 @@ export interface ModEventView {
|
|
|
40
40
|
| ModEventEscalate
|
|
41
41
|
| ModEventMute
|
|
42
42
|
| ModEventEmail
|
|
43
|
+
| ModEventResolveAppeal
|
|
43
44
|
| { $type: string; [k: string]: unknown }
|
|
44
45
|
subject:
|
|
45
46
|
| RepoRef
|
|
@@ -76,6 +77,7 @@ export interface ModEventViewDetail {
|
|
|
76
77
|
| ModEventAcknowledge
|
|
77
78
|
| ModEventEscalate
|
|
78
79
|
| ModEventMute
|
|
80
|
+
| ModEventEmail
|
|
79
81
|
| ModEventResolveAppeal
|
|
80
82
|
| { $type: string; [k: string]: unknown }
|
|
81
83
|
subject:
|