@atproto/ozone 0.0.9 → 0.0.10
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 +9 -0
- package/dist/api/moderation/util.d.ts +1 -1
- package/dist/db/index.js +20 -1
- package/dist/db/index.js.map +3 -3
- package/dist/db/migrations/20240208T213404429Z-add-tags-column-to-moderation-subject.d.ts +3 -0
- package/dist/db/migrations/index.d.ts +1 -0
- package/dist/db/schema/moderation_event.d.ts +3 -1
- package/dist/db/schema/moderation_subject_status.d.ts +1 -0
- package/dist/index.js +318 -51
- package/dist/index.js.map +3 -3
- package/dist/lexicon/lexicons.d.ts +57 -0
- package/dist/lexicon/types/com/atproto/admin/defs.d.ts +9 -0
- package/dist/lexicon/types/com/atproto/admin/emitModerationEvent.d.ts +1 -1
- package/dist/lexicon/types/com/atproto/admin/queryModerationEvents.d.ts +2 -0
- package/dist/lexicon/types/com/atproto/admin/queryModerationStatuses.d.ts +2 -0
- package/dist/logger.d.ts +1 -0
- package/dist/mod-service/index.d.ts +18 -4
- package/dist/mod-service/lang.d.ts +15 -0
- package/dist/mod-service/status.d.ts +1 -1
- package/dist/mod-service/types.d.ts +1 -1
- package/dist/mod-service/views.d.ts +2 -1
- package/package.json +6 -6
- package/src/api/admin/emitModerationEvent.ts +22 -10
- package/src/api/admin/queryModerationEvents.ts +4 -0
- package/src/api/admin/queryModerationStatuses.ts +4 -0
- package/src/api/moderation/createReport.ts +15 -4
- package/src/api/moderation/util.ts +1 -0
- package/src/db/migrations/20240208T213404429Z-add-tags-column-to-moderation-subject.ts +31 -0
- package/src/db/migrations/index.ts +1 -0
- package/src/db/schema/moderation_event.ts +3 -0
- package/src/db/schema/moderation_subject_status.ts +1 -0
- package/src/lexicon/lexicons.ts +62 -0
- package/src/lexicon/types/com/atproto/admin/defs.ts +24 -0
- package/src/lexicon/types/com/atproto/admin/emitModerationEvent.ts +1 -0
- package/src/lexicon/types/com/atproto/admin/queryModerationEvents.ts +4 -0
- package/src/lexicon/types/com/atproto/admin/queryModerationStatuses.ts +2 -0
- package/src/logger.ts +2 -0
- package/src/mod-service/index.ts +60 -10
- package/src/mod-service/lang.ts +82 -0
- package/src/mod-service/status.ts +18 -4
- package/src/mod-service/types.ts +1 -0
- package/src/mod-service/views.ts +21 -2
- package/tests/__snapshots__/get-record.test.ts.snap +6 -0
- package/tests/__snapshots__/get-repo.test.ts.snap +3 -0
- package/tests/__snapshots__/moderation-events.test.ts.snap +45 -4
- package/tests/__snapshots__/moderation-statuses.test.ts.snap +59 -3
- package/tests/__snapshots__/moderation.test.ts.snap +3 -3
- package/tests/get-record.test.ts +0 -8
- package/tests/moderation-events.test.ts +57 -5
- package/tests/moderation-status-tags.test.ts +92 -0
- package/tests/moderation-statuses.test.ts +20 -3
package/dist/index.js
CHANGED
|
@@ -27864,16 +27864,16 @@ var require_validate = __commonJS({
|
|
|
27864
27864
|
const matches = RELATIVE_JSON_POINTER.exec($data);
|
|
27865
27865
|
if (!matches)
|
|
27866
27866
|
throw new Error(`Invalid JSON-pointer: ${$data}`);
|
|
27867
|
-
const
|
|
27867
|
+
const up5 = +matches[1];
|
|
27868
27868
|
jsonPointer = matches[2];
|
|
27869
27869
|
if (jsonPointer === "#") {
|
|
27870
|
-
if (
|
|
27871
|
-
throw new Error(errorMsg("property/index",
|
|
27872
|
-
return dataPathArr[dataLevel -
|
|
27870
|
+
if (up5 >= dataLevel)
|
|
27871
|
+
throw new Error(errorMsg("property/index", up5));
|
|
27872
|
+
return dataPathArr[dataLevel - up5];
|
|
27873
27873
|
}
|
|
27874
|
-
if (
|
|
27875
|
-
throw new Error(errorMsg("data",
|
|
27876
|
-
data = dataNames[dataLevel -
|
|
27874
|
+
if (up5 > dataLevel)
|
|
27875
|
+
throw new Error(errorMsg("data", up5));
|
|
27876
|
+
data = dataNames[dataLevel - up5];
|
|
27877
27877
|
if (!jsonPointer)
|
|
27878
27878
|
return data;
|
|
27879
27879
|
}
|
|
@@ -27886,8 +27886,8 @@ var require_validate = __commonJS({
|
|
|
27886
27886
|
}
|
|
27887
27887
|
}
|
|
27888
27888
|
return expr;
|
|
27889
|
-
function errorMsg(pointerType,
|
|
27890
|
-
return `Cannot access ${pointerType} ${
|
|
27889
|
+
function errorMsg(pointerType, up5) {
|
|
27890
|
+
return `Cannot access ${pointerType} ${up5} levels up, current level is ${dataLevel}`;
|
|
27891
27891
|
}
|
|
27892
27892
|
}
|
|
27893
27893
|
exports.getData = getData;
|
|
@@ -102188,6 +102188,12 @@ var schemaDict = {
|
|
|
102188
102188
|
suspendUntil: {
|
|
102189
102189
|
type: "string",
|
|
102190
102190
|
format: "datetime"
|
|
102191
|
+
},
|
|
102192
|
+
tags: {
|
|
102193
|
+
type: "array",
|
|
102194
|
+
items: {
|
|
102195
|
+
type: "string"
|
|
102196
|
+
}
|
|
102191
102197
|
}
|
|
102192
102198
|
}
|
|
102193
102199
|
},
|
|
@@ -102779,6 +102785,31 @@ var schemaDict = {
|
|
|
102779
102785
|
}
|
|
102780
102786
|
}
|
|
102781
102787
|
},
|
|
102788
|
+
modEventTag: {
|
|
102789
|
+
type: "object",
|
|
102790
|
+
description: "Add/Remove a tag on a subject",
|
|
102791
|
+
required: ["add", "remove"],
|
|
102792
|
+
properties: {
|
|
102793
|
+
add: {
|
|
102794
|
+
type: "array",
|
|
102795
|
+
items: {
|
|
102796
|
+
type: "string"
|
|
102797
|
+
},
|
|
102798
|
+
description: "Tags to be added to the subject. If already exists, won't be duplicated."
|
|
102799
|
+
},
|
|
102800
|
+
remove: {
|
|
102801
|
+
type: "array",
|
|
102802
|
+
items: {
|
|
102803
|
+
type: "string"
|
|
102804
|
+
},
|
|
102805
|
+
description: "Tags to be removed to the subject. Ignores a tag If it doesn't exist, won't be duplicated."
|
|
102806
|
+
},
|
|
102807
|
+
comment: {
|
|
102808
|
+
type: "string",
|
|
102809
|
+
description: "Additional comment about added/removed tags."
|
|
102810
|
+
}
|
|
102811
|
+
}
|
|
102812
|
+
},
|
|
102782
102813
|
communicationTemplateView: {
|
|
102783
102814
|
type: "object",
|
|
102784
102815
|
required: [
|
|
@@ -102953,7 +102984,8 @@ var schemaDict = {
|
|
|
102953
102984
|
"lex:com.atproto.admin.defs#modEventMute",
|
|
102954
102985
|
"lex:com.atproto.admin.defs#modEventReverseTakedown",
|
|
102955
102986
|
"lex:com.atproto.admin.defs#modEventUnmute",
|
|
102956
|
-
"lex:com.atproto.admin.defs#modEventEmail"
|
|
102987
|
+
"lex:com.atproto.admin.defs#modEventEmail",
|
|
102988
|
+
"lex:com.atproto.admin.defs#modEventTag"
|
|
102957
102989
|
]
|
|
102958
102990
|
},
|
|
102959
102991
|
subject: {
|
|
@@ -103375,6 +103407,20 @@ var schemaDict = {
|
|
|
103375
103407
|
},
|
|
103376
103408
|
description: "If specified, only events where all of these labels were removed are returned"
|
|
103377
103409
|
},
|
|
103410
|
+
addedTags: {
|
|
103411
|
+
type: "array",
|
|
103412
|
+
items: {
|
|
103413
|
+
type: "string"
|
|
103414
|
+
},
|
|
103415
|
+
description: "If specified, only events where all of these tags were added are returned"
|
|
103416
|
+
},
|
|
103417
|
+
removedTags: {
|
|
103418
|
+
type: "array",
|
|
103419
|
+
items: {
|
|
103420
|
+
type: "string"
|
|
103421
|
+
},
|
|
103422
|
+
description: "If specified, only events where all of these tags were removed are returned"
|
|
103423
|
+
},
|
|
103378
103424
|
reportTypes: {
|
|
103379
103425
|
type: "array",
|
|
103380
103426
|
items: {
|
|
@@ -103490,6 +103536,18 @@ var schemaDict = {
|
|
|
103490
103536
|
maximum: 100,
|
|
103491
103537
|
default: 50
|
|
103492
103538
|
},
|
|
103539
|
+
tags: {
|
|
103540
|
+
type: "array",
|
|
103541
|
+
items: {
|
|
103542
|
+
type: "string"
|
|
103543
|
+
}
|
|
103544
|
+
},
|
|
103545
|
+
excludeTags: {
|
|
103546
|
+
type: "array",
|
|
103547
|
+
items: {
|
|
103548
|
+
type: "string"
|
|
103549
|
+
}
|
|
103550
|
+
},
|
|
103493
103551
|
cursor: {
|
|
103494
103552
|
type: "string"
|
|
103495
103553
|
}
|
|
@@ -110190,6 +110248,9 @@ function isModEventMute(v) {
|
|
|
110190
110248
|
function isModEventEmail(v) {
|
|
110191
110249
|
return isObj2(v) && hasProp2(v, "$type") && v.$type === "com.atproto.admin.defs#modEventEmail";
|
|
110192
110250
|
}
|
|
110251
|
+
function isModEventTag(v) {
|
|
110252
|
+
return isObj2(v) && hasProp2(v, "$type") && v.$type === "com.atproto.admin.defs#modEventTag";
|
|
110253
|
+
}
|
|
110193
110254
|
|
|
110194
110255
|
// src/api/moderation/util.ts
|
|
110195
110256
|
var getReasonType = (reasonType) => {
|
|
@@ -110233,7 +110294,8 @@ var eventTypes = /* @__PURE__ */ new Set([
|
|
|
110233
110294
|
"com.atproto.admin.defs#modEventUnmute",
|
|
110234
110295
|
"com.atproto.admin.defs#modEventReverseTakedown",
|
|
110235
110296
|
"com.atproto.admin.defs#modEventEmail",
|
|
110236
|
-
"com.atproto.admin.defs#modEventResolveAppeal"
|
|
110297
|
+
"com.atproto.admin.defs#modEventResolveAppeal",
|
|
110298
|
+
"com.atproto.admin.defs#modEventTag"
|
|
110237
110299
|
]);
|
|
110238
110300
|
|
|
110239
110301
|
// src/mod-service/subject.ts
|
|
@@ -110325,6 +110387,80 @@ var RecordSubject = class {
|
|
|
110325
110387
|
}
|
|
110326
110388
|
};
|
|
110327
110389
|
|
|
110390
|
+
// src/logger.ts
|
|
110391
|
+
var import_pino_http = __toESM(require_logger());
|
|
110392
|
+
var dbLogger = subsystemLogger("ozone:db");
|
|
110393
|
+
var httpLogger = subsystemLogger("ozone");
|
|
110394
|
+
var langLogger = subsystemLogger("ozone:lang");
|
|
110395
|
+
var loggerMiddleware = (0, import_pino_http.default)({
|
|
110396
|
+
logger: httpLogger,
|
|
110397
|
+
serializers: {
|
|
110398
|
+
err: (err) => {
|
|
110399
|
+
return {
|
|
110400
|
+
code: err?.code,
|
|
110401
|
+
message: err?.message
|
|
110402
|
+
};
|
|
110403
|
+
}
|
|
110404
|
+
}
|
|
110405
|
+
});
|
|
110406
|
+
|
|
110407
|
+
// src/mod-service/lang.ts
|
|
110408
|
+
var ModerationLangService = class {
|
|
110409
|
+
constructor(moderationService) {
|
|
110410
|
+
this.moderationService = moderationService;
|
|
110411
|
+
}
|
|
110412
|
+
async tagSubjectWithLang({
|
|
110413
|
+
subject,
|
|
110414
|
+
subjectStatus,
|
|
110415
|
+
createdBy
|
|
110416
|
+
}) {
|
|
110417
|
+
if (subjectStatus && !subjectStatus.tags?.find((tag) => tag.includes("lang:"))) {
|
|
110418
|
+
try {
|
|
110419
|
+
const recordLangs = await this.getRecordLang({
|
|
110420
|
+
subject
|
|
110421
|
+
});
|
|
110422
|
+
await this.moderationService.logEvent({
|
|
110423
|
+
event: {
|
|
110424
|
+
$type: "com.atproto.admin.defs#modEventTag",
|
|
110425
|
+
add: recordLangs ? recordLangs.map((lang) => `lang:${lang}`) : ["lang:und"],
|
|
110426
|
+
remove: []
|
|
110427
|
+
},
|
|
110428
|
+
subject,
|
|
110429
|
+
createdBy
|
|
110430
|
+
});
|
|
110431
|
+
} catch (err) {
|
|
110432
|
+
langLogger.error({ subject, err }, "Error getting record langs");
|
|
110433
|
+
}
|
|
110434
|
+
}
|
|
110435
|
+
}
|
|
110436
|
+
async getRecordLang({
|
|
110437
|
+
subject
|
|
110438
|
+
}) {
|
|
110439
|
+
const isRecord = subject.isRecord();
|
|
110440
|
+
const langs = /* @__PURE__ */ new Set();
|
|
110441
|
+
if (subject.isRepo() || isRecord && subject.uri.endsWith("/app.bsky.actor.profile/self")) {
|
|
110442
|
+
const feed = await this.moderationService.views.fetchAuthorFeed(subject.did);
|
|
110443
|
+
feed.forEach((item) => {
|
|
110444
|
+
const itemLangs = item.post.record["langs"];
|
|
110445
|
+
if (itemLangs?.length) {
|
|
110446
|
+
itemLangs.forEach((lang) => langs.add(lang.split("-")[0]));
|
|
110447
|
+
}
|
|
110448
|
+
});
|
|
110449
|
+
}
|
|
110450
|
+
if (isRecord) {
|
|
110451
|
+
const recordByUri = await this.moderationService.views.fetchRecords([
|
|
110452
|
+
subject
|
|
110453
|
+
]);
|
|
110454
|
+
const record = recordByUri.get(subject.uri);
|
|
110455
|
+
const recordLang = record?.value.langs;
|
|
110456
|
+
if (recordLang?.length) {
|
|
110457
|
+
recordLang.map((lang) => lang.split("-")[0]).forEach((lang) => langs.add(lang));
|
|
110458
|
+
}
|
|
110459
|
+
}
|
|
110460
|
+
return langs.size > 0 ? Array.from(langs) : null;
|
|
110461
|
+
}
|
|
110462
|
+
};
|
|
110463
|
+
|
|
110328
110464
|
// src/api/moderation/createReport.ts
|
|
110329
110465
|
function createReport_default(server, ctx) {
|
|
110330
110466
|
server.com.atproto.moderation.createReport({
|
|
@@ -110339,12 +110475,19 @@ function createReport_default(server, ctx) {
|
|
|
110339
110475
|
const db = ctx.db;
|
|
110340
110476
|
const report = await db.transaction(async (dbTxn) => {
|
|
110341
110477
|
const moderationTxn = ctx.modService(dbTxn);
|
|
110342
|
-
|
|
110478
|
+
const { event: reportEvent, subjectStatus } = await moderationTxn.report({
|
|
110343
110479
|
reasonType: getReasonType(reasonType),
|
|
110344
110480
|
reason,
|
|
110345
110481
|
subject,
|
|
110346
110482
|
reportedBy: requester || ctx.cfg.service.did
|
|
110347
110483
|
});
|
|
110484
|
+
const moderationLangService = new ModerationLangService(moderationTxn);
|
|
110485
|
+
await moderationLangService.tagSubjectWithLang({
|
|
110486
|
+
subject,
|
|
110487
|
+
subjectStatus,
|
|
110488
|
+
createdBy: ctx.cfg.service.did
|
|
110489
|
+
});
|
|
110490
|
+
return reportEvent;
|
|
110348
110491
|
});
|
|
110349
110492
|
const body = ctx.modService(db).views.formatReport(report);
|
|
110350
110493
|
return {
|
|
@@ -110402,28 +110545,34 @@ function emitModerationEvent_default(server, ctx) {
|
|
|
110402
110545
|
subject,
|
|
110403
110546
|
createdBy
|
|
110404
110547
|
});
|
|
110548
|
+
const moderationLangService = new ModerationLangService(moderationTxn);
|
|
110549
|
+
await moderationLangService.tagSubjectWithLang({
|
|
110550
|
+
subject,
|
|
110551
|
+
createdBy: ctx.cfg.service.did,
|
|
110552
|
+
subjectStatus: result.subjectStatus
|
|
110553
|
+
});
|
|
110405
110554
|
if (subject.isRepo()) {
|
|
110406
110555
|
if (isTakedownEvent) {
|
|
110407
|
-
const isSuspend = !!result.durationInHours;
|
|
110408
|
-
await moderationTxn.takedownRepo(subject, result.id, isSuspend);
|
|
110556
|
+
const isSuspend = !!result.event.durationInHours;
|
|
110557
|
+
await moderationTxn.takedownRepo(subject, result.event.id, isSuspend);
|
|
110409
110558
|
} else if (isReverseTakedownEvent) {
|
|
110410
110559
|
await moderationTxn.reverseTakedownRepo(subject);
|
|
110411
110560
|
}
|
|
110412
110561
|
}
|
|
110413
110562
|
if (subject.isRecord()) {
|
|
110414
110563
|
if (isTakedownEvent) {
|
|
110415
|
-
await moderationTxn.takedownRecord(subject, result.id);
|
|
110564
|
+
await moderationTxn.takedownRecord(subject, result.event.id);
|
|
110416
110565
|
} else if (isReverseTakedownEvent) {
|
|
110417
110566
|
await moderationTxn.reverseTakedownRecord(subject);
|
|
110418
110567
|
}
|
|
110419
110568
|
}
|
|
110420
110569
|
if (isLabelEvent) {
|
|
110421
|
-
await moderationTxn.formatAndCreateLabels(result.subjectUri ?? result.subjectDid, result.subjectCid, {
|
|
110422
|
-
create: result.createLabelVals?.length ? result.createLabelVals.split(" ") : void 0,
|
|
110423
|
-
negate: result.negateLabelVals?.length ? result.negateLabelVals.split(" ") : void 0
|
|
110570
|
+
await moderationTxn.formatAndCreateLabels(result.event.subjectUri ?? result.event.subjectDid, result.event.subjectCid, {
|
|
110571
|
+
create: result.event.createLabelVals?.length ? result.event.createLabelVals.split(" ") : void 0,
|
|
110572
|
+
negate: result.event.negateLabelVals?.length ? result.event.negateLabelVals.split(" ") : void 0
|
|
110424
110573
|
});
|
|
110425
110574
|
}
|
|
110426
|
-
return result;
|
|
110575
|
+
return result.event;
|
|
110427
110576
|
});
|
|
110428
110577
|
return {
|
|
110429
110578
|
encoding: "application/json",
|
|
@@ -110579,7 +110728,9 @@ function queryModerationStatuses_default(server, ctx) {
|
|
|
110579
110728
|
sortField = "lastReportedAt",
|
|
110580
110729
|
includeMuted = false,
|
|
110581
110730
|
limit = 50,
|
|
110582
|
-
cursor
|
|
110731
|
+
cursor,
|
|
110732
|
+
tags = [],
|
|
110733
|
+
excludeTags = []
|
|
110583
110734
|
} = params2;
|
|
110584
110735
|
const db = ctx.db;
|
|
110585
110736
|
const modService = ctx.modService(db);
|
|
@@ -110598,7 +110749,9 @@ function queryModerationStatuses_default(server, ctx) {
|
|
|
110598
110749
|
lastReviewedBy,
|
|
110599
110750
|
sortField,
|
|
110600
110751
|
limit,
|
|
110601
|
-
cursor
|
|
110752
|
+
cursor,
|
|
110753
|
+
tags,
|
|
110754
|
+
excludeTags
|
|
110602
110755
|
});
|
|
110603
110756
|
const subjectStatuses = results.statuses.map((status) => modService.views.formatSubjectStatus(status));
|
|
110604
110757
|
return {
|
|
@@ -110631,6 +110784,8 @@ function queryModerationEvents_default(server, ctx) {
|
|
|
110631
110784
|
createdBefore,
|
|
110632
110785
|
addedLabels = [],
|
|
110633
110786
|
removedLabels = [],
|
|
110787
|
+
addedTags = [],
|
|
110788
|
+
removedTags = [],
|
|
110634
110789
|
reportTypes
|
|
110635
110790
|
} = params2;
|
|
110636
110791
|
const db = ctx.db;
|
|
@@ -110648,7 +110803,9 @@ function queryModerationEvents_default(server, ctx) {
|
|
|
110648
110803
|
createdAfter,
|
|
110649
110804
|
createdBefore,
|
|
110650
110805
|
addedLabels,
|
|
110806
|
+
addedTags,
|
|
110651
110807
|
removedLabels,
|
|
110808
|
+
removedTags,
|
|
110652
110809
|
reportTypes
|
|
110653
110810
|
});
|
|
110654
110811
|
return {
|
|
@@ -118419,22 +118576,6 @@ function api_default(server, ctx) {
|
|
|
118419
118576
|
return server;
|
|
118420
118577
|
}
|
|
118421
118578
|
|
|
118422
|
-
// src/logger.ts
|
|
118423
|
-
var import_pino_http = __toESM(require_logger());
|
|
118424
|
-
var dbLogger = subsystemLogger("ozone:db");
|
|
118425
|
-
var httpLogger = subsystemLogger("ozone");
|
|
118426
|
-
var loggerMiddleware = (0, import_pino_http.default)({
|
|
118427
|
-
logger: httpLogger,
|
|
118428
|
-
serializers: {
|
|
118429
|
-
err: (err) => {
|
|
118430
|
-
return {
|
|
118431
|
-
code: err?.code,
|
|
118432
|
-
message: err?.message
|
|
118433
|
-
};
|
|
118434
|
-
}
|
|
118435
|
-
}
|
|
118436
|
-
});
|
|
118437
|
-
|
|
118438
118579
|
// src/error.ts
|
|
118439
118580
|
var handler = (err, _req, res, next) => {
|
|
118440
118581
|
httpLogger.error(err, "unexpected internal server error");
|
|
@@ -119682,6 +119823,12 @@ var schemaDict2 = {
|
|
|
119682
119823
|
suspendUntil: {
|
|
119683
119824
|
type: "string",
|
|
119684
119825
|
format: "datetime"
|
|
119826
|
+
},
|
|
119827
|
+
tags: {
|
|
119828
|
+
type: "array",
|
|
119829
|
+
items: {
|
|
119830
|
+
type: "string"
|
|
119831
|
+
}
|
|
119685
119832
|
}
|
|
119686
119833
|
}
|
|
119687
119834
|
},
|
|
@@ -120273,6 +120420,31 @@ var schemaDict2 = {
|
|
|
120273
120420
|
}
|
|
120274
120421
|
}
|
|
120275
120422
|
},
|
|
120423
|
+
modEventTag: {
|
|
120424
|
+
type: "object",
|
|
120425
|
+
description: "Add/Remove a tag on a subject",
|
|
120426
|
+
required: ["add", "remove"],
|
|
120427
|
+
properties: {
|
|
120428
|
+
add: {
|
|
120429
|
+
type: "array",
|
|
120430
|
+
items: {
|
|
120431
|
+
type: "string"
|
|
120432
|
+
},
|
|
120433
|
+
description: "Tags to be added to the subject. If already exists, won't be duplicated."
|
|
120434
|
+
},
|
|
120435
|
+
remove: {
|
|
120436
|
+
type: "array",
|
|
120437
|
+
items: {
|
|
120438
|
+
type: "string"
|
|
120439
|
+
},
|
|
120440
|
+
description: "Tags to be removed to the subject. Ignores a tag If it doesn't exist, won't be duplicated."
|
|
120441
|
+
},
|
|
120442
|
+
comment: {
|
|
120443
|
+
type: "string",
|
|
120444
|
+
description: "Additional comment about added/removed tags."
|
|
120445
|
+
}
|
|
120446
|
+
}
|
|
120447
|
+
},
|
|
120276
120448
|
communicationTemplateView: {
|
|
120277
120449
|
type: "object",
|
|
120278
120450
|
required: [
|
|
@@ -120447,7 +120619,8 @@ var schemaDict2 = {
|
|
|
120447
120619
|
"lex:com.atproto.admin.defs#modEventMute",
|
|
120448
120620
|
"lex:com.atproto.admin.defs#modEventReverseTakedown",
|
|
120449
120621
|
"lex:com.atproto.admin.defs#modEventUnmute",
|
|
120450
|
-
"lex:com.atproto.admin.defs#modEventEmail"
|
|
120622
|
+
"lex:com.atproto.admin.defs#modEventEmail",
|
|
120623
|
+
"lex:com.atproto.admin.defs#modEventTag"
|
|
120451
120624
|
]
|
|
120452
120625
|
},
|
|
120453
120626
|
subject: {
|
|
@@ -120869,6 +121042,20 @@ var schemaDict2 = {
|
|
|
120869
121042
|
},
|
|
120870
121043
|
description: "If specified, only events where all of these labels were removed are returned"
|
|
120871
121044
|
},
|
|
121045
|
+
addedTags: {
|
|
121046
|
+
type: "array",
|
|
121047
|
+
items: {
|
|
121048
|
+
type: "string"
|
|
121049
|
+
},
|
|
121050
|
+
description: "If specified, only events where all of these tags were added are returned"
|
|
121051
|
+
},
|
|
121052
|
+
removedTags: {
|
|
121053
|
+
type: "array",
|
|
121054
|
+
items: {
|
|
121055
|
+
type: "string"
|
|
121056
|
+
},
|
|
121057
|
+
description: "If specified, only events where all of these tags were removed are returned"
|
|
121058
|
+
},
|
|
120872
121059
|
reportTypes: {
|
|
120873
121060
|
type: "array",
|
|
120874
121061
|
items: {
|
|
@@ -120984,6 +121171,18 @@ var schemaDict2 = {
|
|
|
120984
121171
|
maximum: 100,
|
|
120985
121172
|
default: 50
|
|
120986
121173
|
},
|
|
121174
|
+
tags: {
|
|
121175
|
+
type: "array",
|
|
121176
|
+
items: {
|
|
121177
|
+
type: "string"
|
|
121178
|
+
}
|
|
121179
|
+
},
|
|
121180
|
+
excludeTags: {
|
|
121181
|
+
type: "array",
|
|
121182
|
+
items: {
|
|
121183
|
+
type: "string"
|
|
121184
|
+
}
|
|
121185
|
+
},
|
|
120987
121186
|
cursor: {
|
|
120988
121187
|
type: "string"
|
|
120989
121188
|
}
|
|
@@ -131007,7 +131206,8 @@ var migrations_exports = {};
|
|
|
131007
131206
|
__export(migrations_exports, {
|
|
131008
131207
|
_20231219T205730722Z: () => T205730722Z_init_exports,
|
|
131009
131208
|
_20240116T085607200Z: () => T085607200Z_communication_template_exports,
|
|
131010
|
-
_20240201T051104136Z: () => T051104136Z_mod_event_blobs_exports
|
|
131209
|
+
_20240201T051104136Z: () => T051104136Z_mod_event_blobs_exports,
|
|
131210
|
+
_20240208T213404429Z: () => T213404429Z_add_tags_column_to_moderation_subject_exports
|
|
131011
131211
|
});
|
|
131012
131212
|
|
|
131013
131213
|
// src/db/migrations/20231219T205730722Z-init.ts
|
|
@@ -131078,6 +131278,23 @@ async function down3(db) {
|
|
|
131078
131278
|
await db.schema.alterTable("moderation_event").dropColumn("subjectBlobCids").execute();
|
|
131079
131279
|
}
|
|
131080
131280
|
|
|
131281
|
+
// src/db/migrations/20240208T213404429Z-add-tags-column-to-moderation-subject.ts
|
|
131282
|
+
var T213404429Z_add_tags_column_to_moderation_subject_exports = {};
|
|
131283
|
+
__export(T213404429Z_add_tags_column_to_moderation_subject_exports, {
|
|
131284
|
+
down: () => down4,
|
|
131285
|
+
up: () => up4
|
|
131286
|
+
});
|
|
131287
|
+
async function up4(db) {
|
|
131288
|
+
await db.schema.alterTable("moderation_event").addColumn("addedTags", "jsonb").execute();
|
|
131289
|
+
await db.schema.alterTable("moderation_event").addColumn("removedTags", "jsonb").execute();
|
|
131290
|
+
await db.schema.alterTable("moderation_subject_status").addColumn("tags", "jsonb").execute();
|
|
131291
|
+
}
|
|
131292
|
+
async function down4(db) {
|
|
131293
|
+
await db.schema.alterTable("moderation_event").dropColumn("addedTags").execute();
|
|
131294
|
+
await db.schema.alterTable("moderation_event").dropColumn("removedTags").execute();
|
|
131295
|
+
await db.schema.alterTable("moderation_subject_status").dropColumn("tags").execute();
|
|
131296
|
+
}
|
|
131297
|
+
|
|
131081
131298
|
// src/db/migrations/provider.ts
|
|
131082
131299
|
var CtxMigrationProvider = class {
|
|
131083
131300
|
constructor(migrations, ctx) {
|
|
@@ -131333,6 +131550,10 @@ var ModerationViews = class {
|
|
|
131333
131550
|
if (event.action === "com.atproto.admin.defs#modEventComment" && event.meta?.sticky) {
|
|
131334
131551
|
eventView.event.sticky = true;
|
|
131335
131552
|
}
|
|
131553
|
+
if (event.action === "com.atproto.admin.defs#modEventTag") {
|
|
131554
|
+
eventView.event.add = event.addedTags || [];
|
|
131555
|
+
eventView.event.remove = event.removedTags || [];
|
|
131556
|
+
}
|
|
131336
131557
|
return eventView;
|
|
131337
131558
|
}
|
|
131338
131559
|
async eventDetail(result) {
|
|
@@ -131373,12 +131594,13 @@ var ModerationViews = class {
|
|
|
131373
131594
|
const fetched = await Promise.all(subjects.map(async (subject) => {
|
|
131374
131595
|
const uri2 = new AtUri(subject.uri);
|
|
131375
131596
|
try {
|
|
131376
|
-
|
|
131597
|
+
const record = await this.appviewAgent.api.com.atproto.repo.getRecord({
|
|
131377
131598
|
repo: uri2.hostname,
|
|
131378
131599
|
collection: uri2.collection,
|
|
131379
131600
|
rkey: uri2.rkey,
|
|
131380
131601
|
cid: subject.cid
|
|
131381
131602
|
}, auth);
|
|
131603
|
+
return record;
|
|
131382
131604
|
} catch {
|
|
131383
131605
|
return null;
|
|
131384
131606
|
}
|
|
@@ -131568,9 +131790,19 @@ var ModerationViews = class {
|
|
|
131568
131790
|
appealed: status.appealed ?? void 0,
|
|
131569
131791
|
subjectRepoHandle: status.handle ?? void 0,
|
|
131570
131792
|
subjectBlobCids: status.blobCids || [],
|
|
131793
|
+
tags: status.tags || [],
|
|
131571
131794
|
subject: subjectFromStatusRow(status).lex()
|
|
131572
131795
|
};
|
|
131573
131796
|
}
|
|
131797
|
+
async fetchAuthorFeed(actor) {
|
|
131798
|
+
const auth = await this.appviewAuth();
|
|
131799
|
+
if (!auth)
|
|
131800
|
+
return [];
|
|
131801
|
+
const {
|
|
131802
|
+
data: { feed }
|
|
131803
|
+
} = await this.appviewAgent.api.app.bsky.feed.getAuthorFeed({ actor }, auth);
|
|
131804
|
+
return feed;
|
|
131805
|
+
}
|
|
131574
131806
|
};
|
|
131575
131807
|
function parseSubjectId(subject) {
|
|
131576
131808
|
if (subject.startsWith("did:")) {
|
|
@@ -131672,6 +131904,8 @@ var getSubjectStatusForModerationEvent = ({
|
|
|
131672
131904
|
lastReviewedBy: createdBy,
|
|
131673
131905
|
lastReviewedAt: createdAt
|
|
131674
131906
|
};
|
|
131907
|
+
case "com.atproto.admin.defs#modEventTag":
|
|
131908
|
+
return { tags: [] };
|
|
131675
131909
|
case "com.atproto.admin.defs#modEventResolveAppeal":
|
|
131676
131910
|
return {
|
|
131677
131911
|
appealed: false
|
|
@@ -131688,6 +131922,8 @@ var adjustModerationSubjectStatus = async (db, moderationEvent, blobCids) => {
|
|
|
131688
131922
|
subjectCid,
|
|
131689
131923
|
createdBy,
|
|
131690
131924
|
meta,
|
|
131925
|
+
addedTags,
|
|
131926
|
+
removedTags,
|
|
131691
131927
|
comment,
|
|
131692
131928
|
createdAt
|
|
131693
131929
|
} = moderationEvent;
|
|
@@ -131735,6 +131971,17 @@ var adjustModerationSubjectStatus = async (db, moderationEvent, blobCids) => {
|
|
|
131735
131971
|
newStatus.comment = comment;
|
|
131736
131972
|
subjectStatus.comment = comment;
|
|
131737
131973
|
}
|
|
131974
|
+
if (action === "com.atproto.admin.defs#modEventTag") {
|
|
131975
|
+
let tags = currentStatus?.tags || [];
|
|
131976
|
+
if (addedTags?.length) {
|
|
131977
|
+
tags = tags.concat(addedTags);
|
|
131978
|
+
}
|
|
131979
|
+
if (removedTags?.length) {
|
|
131980
|
+
tags = tags.filter((tag) => !removedTags.includes(tag));
|
|
131981
|
+
}
|
|
131982
|
+
newStatus.tags = jsonb([...new Set(tags)]);
|
|
131983
|
+
subjectStatus.tags = newStatus.tags;
|
|
131984
|
+
}
|
|
131738
131985
|
if (blobCids?.length) {
|
|
131739
131986
|
const newBlobCids = jsonb(blobCids);
|
|
131740
131987
|
newStatus.blobCids = newBlobCids;
|
|
@@ -131749,8 +131996,8 @@ var adjustModerationSubjectStatus = async (db, moderationEvent, blobCids) => {
|
|
|
131749
131996
|
...subjectStatus,
|
|
131750
131997
|
updatedAt: now
|
|
131751
131998
|
}));
|
|
131752
|
-
const status = await insertQuery.executeTakeFirst();
|
|
131753
|
-
return status;
|
|
131999
|
+
const status = await insertQuery.returningAll().executeTakeFirst();
|
|
132000
|
+
return status || null;
|
|
131754
132001
|
};
|
|
131755
132002
|
var getStatusIdentifierFromSubject = (subject) => {
|
|
131756
132003
|
const isSubjectString = typeof subject === "string";
|
|
@@ -131945,8 +132192,11 @@ var ModerationService = class {
|
|
|
131945
132192
|
createdBefore,
|
|
131946
132193
|
addedLabels,
|
|
131947
132194
|
removedLabels,
|
|
132195
|
+
addedTags,
|
|
132196
|
+
removedTags,
|
|
131948
132197
|
reportTypes
|
|
131949
132198
|
} = opts;
|
|
132199
|
+
const { ref } = this.db.db.dynamic;
|
|
131950
132200
|
let builder = this.db.db.selectFrom("moderation_event").selectAll();
|
|
131951
132201
|
if (subject) {
|
|
131952
132202
|
builder = builder.where((qb) => {
|
|
@@ -131993,10 +132243,15 @@ var ModerationService = class {
|
|
|
131993
132243
|
builder = builder.where("negateLabelVals", "ilike", `%${label}%`);
|
|
131994
132244
|
});
|
|
131995
132245
|
}
|
|
132246
|
+
if (addedTags.length) {
|
|
132247
|
+
builder = builder.where(sql`${ref("addedTags")} @> ${jsonb(addedTags)}`);
|
|
132248
|
+
}
|
|
132249
|
+
if (removedTags.length) {
|
|
132250
|
+
builder = builder.where(sql`${ref("removedTags")} @> ${jsonb(removedTags)}`);
|
|
132251
|
+
}
|
|
131996
132252
|
if (reportTypes?.length) {
|
|
131997
132253
|
builder = builder.where(sql`meta->>'reportType'`, "in", reportTypes);
|
|
131998
132254
|
}
|
|
131999
|
-
const { ref } = this.db.db.dynamic;
|
|
132000
132255
|
const keyset = new TimeIdKeyset(ref(`moderation_event.createdAt`), ref("moderation_event.id"));
|
|
132001
132256
|
const paginatedBuilder = paginate(builder, {
|
|
132002
132257
|
limit,
|
|
@@ -132035,6 +132290,8 @@ var ModerationService = class {
|
|
|
132035
132290
|
const createLabelVals = isModEventLabel(event) && event.createLabelVals.length > 0 ? event.createLabelVals.join(" ") : void 0;
|
|
132036
132291
|
const negateLabelVals = isModEventLabel(event) && event.negateLabelVals.length > 0 ? event.negateLabelVals.join(" ") : void 0;
|
|
132037
132292
|
const meta = {};
|
|
132293
|
+
const addedTags = isModEventTag(event) ? jsonb(event.add) : null;
|
|
132294
|
+
const removedTags = isModEventTag(event) ? jsonb(event.remove) : null;
|
|
132038
132295
|
if (isModEventReport(event)) {
|
|
132039
132296
|
meta.reportType = event.reportType;
|
|
132040
132297
|
}
|
|
@@ -132052,6 +132309,8 @@ var ModerationService = class {
|
|
|
132052
132309
|
createdBy,
|
|
132053
132310
|
createLabelVals,
|
|
132054
132311
|
negateLabelVals,
|
|
132312
|
+
addedTags,
|
|
132313
|
+
removedTags,
|
|
132055
132314
|
durationInHours: event.durationInHours ? Number(event.durationInHours) : null,
|
|
132056
132315
|
meta,
|
|
132057
132316
|
expiresAt: (isModEventTakedown(event) || isModEventMute(event)) && event.durationInHours ? addHoursToDate(event.durationInHours, createdAt).toISOString() : void 0,
|
|
@@ -132061,8 +132320,8 @@ var ModerationService = class {
|
|
|
132061
132320
|
subjectCid: subjectInfo.subjectCid,
|
|
132062
132321
|
subjectBlobCids: jsonb(subjectInfo.subjectBlobCids)
|
|
132063
132322
|
}).returningAll().executeTakeFirstOrThrow();
|
|
132064
|
-
await adjustModerationSubjectStatus(this.db, modEvent, subject.blobCids);
|
|
132065
|
-
return modEvent;
|
|
132323
|
+
const subjectStatus = await adjustModerationSubjectStatus(this.db, modEvent, subject.blobCids);
|
|
132324
|
+
return { event: modEvent, subjectStatus };
|
|
132066
132325
|
}
|
|
132067
132326
|
async getLastReversibleEventForSubject(subject) {
|
|
132068
132327
|
if (!subject.reverseMute && !subject.reverseSuspend) {
|
|
@@ -132102,7 +132361,7 @@ var ModerationService = class {
|
|
|
132102
132361
|
}) {
|
|
132103
132362
|
const isRevertingTakedown = action === "com.atproto.admin.defs#modEventTakedown";
|
|
132104
132363
|
this.db.assertTransaction();
|
|
132105
|
-
const
|
|
132364
|
+
const { event } = await this.logEvent({
|
|
132106
132365
|
event: {
|
|
132107
132366
|
$type: isRevertingTakedown ? "com.atproto.admin.defs#modEventReverseTakedown" : "com.atproto.admin.defs#modEventUnmute",
|
|
132108
132367
|
comment: comment ?? void 0
|
|
@@ -132118,7 +132377,7 @@ var ModerationService = class {
|
|
|
132118
132377
|
await this.reverseTakedownRecord(subject);
|
|
132119
132378
|
}
|
|
132120
132379
|
}
|
|
132121
|
-
return
|
|
132380
|
+
return event;
|
|
132122
132381
|
}
|
|
132123
132382
|
async takedownRepo(subject, takedownId, isSuspend = false) {
|
|
132124
132383
|
const takedownRef = `BSKY-${isSuspend ? "SUSPEND" : "TAKEDOWN"}-${takedownId}`;
|
|
@@ -132259,7 +132518,7 @@ var ModerationService = class {
|
|
|
132259
132518
|
createdAt = new Date(),
|
|
132260
132519
|
subject
|
|
132261
132520
|
} = info;
|
|
132262
|
-
const
|
|
132521
|
+
const result = await this.logEvent({
|
|
132263
132522
|
event: {
|
|
132264
132523
|
$type: "com.atproto.admin.defs#modEventReport",
|
|
132265
132524
|
reportType: reasonType,
|
|
@@ -132269,7 +132528,7 @@ var ModerationService = class {
|
|
|
132269
132528
|
subject,
|
|
132270
132529
|
createdAt
|
|
132271
132530
|
});
|
|
132272
|
-
return
|
|
132531
|
+
return result;
|
|
132273
132532
|
}
|
|
132274
132533
|
async getSubjectStatuses({
|
|
132275
132534
|
cursor,
|
|
@@ -132286,9 +132545,12 @@ var ModerationService = class {
|
|
|
132286
132545
|
sortDirection,
|
|
132287
132546
|
lastReviewedBy,
|
|
132288
132547
|
sortField,
|
|
132289
|
-
subject
|
|
132548
|
+
subject,
|
|
132549
|
+
tags,
|
|
132550
|
+
excludeTags
|
|
132290
132551
|
}) {
|
|
132291
132552
|
let builder = this.db.db.selectFrom("moderation_subject_status").selectAll();
|
|
132553
|
+
const { ref } = this.db.db.dynamic;
|
|
132292
132554
|
if (subject) {
|
|
132293
132555
|
const subjectInfo = getStatusIdentifierFromSubject(subject);
|
|
132294
132556
|
builder = builder.where("moderation_subject_status.did", "=", subjectInfo.did).where((qb) => subjectInfo.recordPath ? qb.where("recordPath", "=", subjectInfo.recordPath) : qb.where("recordPath", "=", ""));
|
|
@@ -132323,7 +132585,12 @@ var ModerationService = class {
|
|
|
132323
132585
|
if (!includeMuted) {
|
|
132324
132586
|
builder = builder.where((qb) => qb.where("muteUntil", "<", new Date().toISOString()).orWhere("muteUntil", "is", null));
|
|
132325
132587
|
}
|
|
132326
|
-
|
|
132588
|
+
if (tags.length) {
|
|
132589
|
+
builder = builder.where(sql`${ref("moderation_subject_status.tags")} @> ${jsonb(tags)}`);
|
|
132590
|
+
}
|
|
132591
|
+
if (excludeTags.length) {
|
|
132592
|
+
builder = builder.where((qb) => qb.where(sql`NOT(${ref("moderation_subject_status.tags")} @> ${jsonb(excludeTags)})`).orWhere("tags", "is", null));
|
|
132593
|
+
}
|
|
132327
132594
|
const keyset = new StatusKeyset(ref(`moderation_subject_status.${sortField}`), ref("moderation_subject_status.id"));
|
|
132328
132595
|
const paginatedBuilder = paginate(builder, {
|
|
132329
132596
|
limit,
|