@atproto/ozone 0.1.52 → 0.1.54
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 +21 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +6 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/moderation/queryStatuses.d.ts.map +1 -1
- package/dist/api/moderation/queryStatuses.js +6 -1
- package/dist/api/moderation/queryStatuses.js.map +1 -1
- package/dist/api/setting/listOptions.d.ts +4 -0
- package/dist/api/setting/listOptions.d.ts.map +1 -0
- package/dist/api/setting/listOptions.js +38 -0
- package/dist/api/setting/listOptions.js.map +1 -0
- package/dist/api/setting/removeOptions.d.ts +4 -0
- package/dist/api/setting/removeOptions.d.ts.map +1 -0
- package/dist/api/setting/removeOptions.js +55 -0
- package/dist/api/setting/removeOptions.js.map +1 -0
- package/dist/api/setting/upsertOption.d.ts +4 -0
- package/dist/api/setting/upsertOption.d.ts.map +1 -0
- package/dist/api/setting/upsertOption.js +109 -0
- package/dist/api/setting/upsertOption.js.map +1 -0
- package/dist/api/util.d.ts.map +1 -1
- package/dist/api/util.js +3 -1
- package/dist/api/util.js.map +1 -1
- package/dist/context.d.ts +3 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +6 -0
- package/dist/context.js.map +1 -1
- package/dist/db/migrations/20241018T205730722Z-setting.d.ts +4 -0
- package/dist/db/migrations/20241018T205730722Z-setting.d.ts.map +1 -0
- package/dist/db/migrations/20241018T205730722Z-setting.js +26 -0
- package/dist/db/migrations/20241018T205730722Z-setting.js.map +1 -0
- package/dist/db/migrations/20241026T205730722Z-add-hosting-status-to-subject-status.d.ts +4 -0
- package/dist/db/migrations/20241026T205730722Z-add-hosting-status-to-subject-status.d.ts.map +1 -0
- package/dist/db/migrations/20241026T205730722Z-add-hosting-status-to-subject-status.js +57 -0
- package/dist/db/migrations/20241026T205730722Z-add-hosting-status-to-subject-status.js.map +1 -0
- package/dist/db/migrations/index.d.ts +2 -0
- package/dist/db/migrations/index.d.ts.map +1 -1
- package/dist/db/migrations/index.js +3 -1
- package/dist/db/migrations/index.js.map +1 -1
- package/dist/db/schema/index.d.ts +2 -1
- package/dist/db/schema/index.d.ts.map +1 -1
- package/dist/db/schema/moderation_event.d.ts +1 -1
- package/dist/db/schema/moderation_event.d.ts.map +1 -1
- package/dist/db/schema/moderation_subject_status.d.ts +6 -0
- package/dist/db/schema/moderation_subject_status.d.ts.map +1 -1
- package/dist/db/schema/setting.d.ts +21 -0
- package/dist/db/schema/setting.d.ts.map +1 -0
- package/dist/db/schema/setting.js +5 -0
- package/dist/db/schema/setting.js.map +1 -0
- package/dist/lexicon/index.d.ts +13 -0
- package/dist/lexicon/index.d.ts.map +1 -1
- package/dist/lexicon/index.js +36 -1
- package/dist/lexicon/index.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +396 -0
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +439 -3
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/getConfig.d.ts +34 -0
- package/dist/lexicon/types/app/bsky/unspecced/getConfig.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/unspecced/getConfig.js +3 -0
- package/dist/lexicon/types/app/bsky/unspecced/getConfig.js.map +1 -0
- package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts +60 -2
- package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/defs.js +50 -0
- package/dist/lexicon/types/tools/ozone/moderation/defs.js.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/emitEvent.d.ts +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/emitEvent.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/queryStatuses.d.ts +10 -0
- package/dist/lexicon/types/tools/ozone/moderation/queryStatuses.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/setting/defs.d.ts +20 -0
- package/dist/lexicon/types/tools/ozone/setting/defs.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/setting/defs.js +15 -0
- package/dist/lexicon/types/tools/ozone/setting/defs.js.map +1 -0
- package/dist/lexicon/types/tools/ozone/setting/listOptions.d.ts +43 -0
- package/dist/lexicon/types/tools/ozone/setting/listOptions.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/setting/listOptions.js +3 -0
- package/dist/lexicon/types/tools/ozone/setting/listOptions.js.map +1 -0
- package/dist/lexicon/types/tools/ozone/setting/removeOptions.d.ts +40 -0
- package/dist/lexicon/types/tools/ozone/setting/removeOptions.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/setting/removeOptions.js +3 -0
- package/dist/lexicon/types/tools/ozone/setting/removeOptions.js.map +1 -0
- package/dist/lexicon/types/tools/ozone/setting/upsertOption.d.ts +45 -0
- package/dist/lexicon/types/tools/ozone/setting/upsertOption.d.ts.map +1 -0
- package/dist/lexicon/types/tools/ozone/setting/upsertOption.js +3 -0
- package/dist/lexicon/types/tools/ozone/setting/upsertOption.js.map +1 -0
- package/dist/mod-service/index.d.ts +19 -2
- package/dist/mod-service/index.d.ts.map +1 -1
- package/dist/mod-service/index.js +37 -1
- package/dist/mod-service/index.js.map +1 -1
- package/dist/mod-service/status.d.ts +2 -22
- package/dist/mod-service/status.d.ts.map +1 -1
- package/dist/mod-service/status.js +91 -1
- package/dist/mod-service/status.js.map +1 -1
- package/dist/mod-service/types.d.ts +19 -1
- package/dist/mod-service/types.d.ts.map +1 -1
- package/dist/mod-service/views.d.ts.map +1 -1
- package/dist/mod-service/views.js +36 -1
- package/dist/mod-service/views.js.map +1 -1
- package/dist/setting/service.d.ts +33 -0
- package/dist/setting/service.d.ts.map +1 -0
- package/dist/setting/service.js +101 -0
- package/dist/setting/service.js.map +1 -0
- package/package.json +6 -6
- package/src/api/index.ts +6 -0
- package/src/api/moderation/queryStatuses.ts +10 -0
- package/src/api/setting/listOptions.ts +44 -0
- package/src/api/setting/removeOptions.ts +63 -0
- package/src/api/setting/upsertOption.ts +142 -0
- package/src/api/util.ts +3 -0
- package/src/context.ts +8 -0
- package/src/db/migrations/20241018T205730722Z-setting.ts +27 -0
- package/src/db/migrations/20241026T205730722Z-add-hosting-status-to-subject-status.ts +57 -0
- package/src/db/migrations/index.ts +2 -0
- package/src/db/schema/index.ts +3 -1
- package/src/db/schema/moderation_event.ts +3 -0
- package/src/db/schema/moderation_subject_status.ts +6 -0
- package/src/db/schema/setting.ts +24 -0
- package/src/lexicon/index.ts +58 -0
- package/src/lexicon/lexicons.ts +449 -3
- package/src/lexicon/types/app/bsky/unspecced/getConfig.ts +43 -0
- package/src/lexicon/types/tools/ozone/moderation/defs.ts +132 -0
- package/src/lexicon/types/tools/ozone/moderation/emitEvent.ts +3 -0
- package/src/lexicon/types/tools/ozone/moderation/queryStatuses.ts +10 -0
- package/src/lexicon/types/tools/ozone/setting/defs.ts +37 -0
- package/src/lexicon/types/tools/ozone/setting/listOptions.ts +53 -0
- package/src/lexicon/types/tools/ozone/setting/removeOptions.ts +49 -0
- package/src/lexicon/types/tools/ozone/setting/upsertOption.ts +58 -0
- package/src/mod-service/index.ts +52 -0
- package/src/mod-service/status.ts +114 -2
- package/src/mod-service/types.ts +25 -0
- package/src/mod-service/views.ts +45 -2
- package/src/setting/service.ts +148 -0
- package/tests/__snapshots__/get-record.test.ts.snap +8 -0
- package/tests/__snapshots__/get-records.test.ts.snap +4 -0
- package/tests/__snapshots__/get-repo.test.ts.snap +4 -0
- package/tests/__snapshots__/get-repos.test.ts.snap +4 -0
- package/tests/__snapshots__/moderation-events.test.ts.snap +4 -0
- package/tests/__snapshots__/moderation-statuses.test.ts.snap +24 -0
- package/tests/__snapshots__/settings.test.ts.snap +52 -0
- package/tests/record-and-account-events.test.ts +185 -0
- package/tests/settings.test.ts +310 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/tsconfig.tests.tsbuildinfo +1 -1
|
@@ -30,6 +30,9 @@ export interface ModEventView {
|
|
|
30
30
|
| ModEventResolveAppeal
|
|
31
31
|
| ModEventDivert
|
|
32
32
|
| ModEventTag
|
|
33
|
+
| AccountEvent
|
|
34
|
+
| IdentityEvent
|
|
35
|
+
| RecordEvent
|
|
33
36
|
| { $type: string; [k: string]: unknown }
|
|
34
37
|
subject:
|
|
35
38
|
| ComAtprotoAdminDefs.RepoRef
|
|
@@ -74,6 +77,9 @@ export interface ModEventViewDetail {
|
|
|
74
77
|
| ModEventResolveAppeal
|
|
75
78
|
| ModEventDivert
|
|
76
79
|
| ModEventTag
|
|
80
|
+
| AccountEvent
|
|
81
|
+
| IdentityEvent
|
|
82
|
+
| RecordEvent
|
|
77
83
|
| { $type: string; [k: string]: unknown }
|
|
78
84
|
subject:
|
|
79
85
|
| RepoView
|
|
@@ -105,6 +111,10 @@ export interface SubjectStatusView {
|
|
|
105
111
|
| ComAtprotoAdminDefs.RepoRef
|
|
106
112
|
| ComAtprotoRepoStrongRef.Main
|
|
107
113
|
| { $type: string; [k: string]: unknown }
|
|
114
|
+
hosting?:
|
|
115
|
+
| AccountHosting
|
|
116
|
+
| RecordHosting
|
|
117
|
+
| { $type: string; [k: string]: unknown }
|
|
108
118
|
subjectBlobCids?: string[]
|
|
109
119
|
subjectRepoHandle?: string
|
|
110
120
|
/** Timestamp referencing when the last update was made to the moderation status of the subject */
|
|
@@ -472,6 +482,78 @@ export function validateModEventTag(v: unknown): ValidationResult {
|
|
|
472
482
|
return lexicons.validate('tools.ozone.moderation.defs#modEventTag', v)
|
|
473
483
|
}
|
|
474
484
|
|
|
485
|
+
/** Logs account status related events on a repo subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking. */
|
|
486
|
+
export interface AccountEvent {
|
|
487
|
+
comment?: string
|
|
488
|
+
/** Indicates that the account has a repository which can be fetched from the host that emitted this event. */
|
|
489
|
+
active: boolean
|
|
490
|
+
status?:
|
|
491
|
+
| 'unknown'
|
|
492
|
+
| 'deactivated'
|
|
493
|
+
| 'deleted'
|
|
494
|
+
| 'takendown'
|
|
495
|
+
| 'suspended'
|
|
496
|
+
| 'tombstoned'
|
|
497
|
+
| (string & {})
|
|
498
|
+
timestamp: string
|
|
499
|
+
[k: string]: unknown
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
export function isAccountEvent(v: unknown): v is AccountEvent {
|
|
503
|
+
return (
|
|
504
|
+
isObj(v) &&
|
|
505
|
+
hasProp(v, '$type') &&
|
|
506
|
+
v.$type === 'tools.ozone.moderation.defs#accountEvent'
|
|
507
|
+
)
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
export function validateAccountEvent(v: unknown): ValidationResult {
|
|
511
|
+
return lexicons.validate('tools.ozone.moderation.defs#accountEvent', v)
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/** Logs identity related events on a repo subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking. */
|
|
515
|
+
export interface IdentityEvent {
|
|
516
|
+
comment?: string
|
|
517
|
+
handle?: string
|
|
518
|
+
pdsHost?: string
|
|
519
|
+
tombstone?: boolean
|
|
520
|
+
timestamp: string
|
|
521
|
+
[k: string]: unknown
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
export function isIdentityEvent(v: unknown): v is IdentityEvent {
|
|
525
|
+
return (
|
|
526
|
+
isObj(v) &&
|
|
527
|
+
hasProp(v, '$type') &&
|
|
528
|
+
v.$type === 'tools.ozone.moderation.defs#identityEvent'
|
|
529
|
+
)
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
export function validateIdentityEvent(v: unknown): ValidationResult {
|
|
533
|
+
return lexicons.validate('tools.ozone.moderation.defs#identityEvent', v)
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/** Logs lifecycle event on a record subject. Normally captured by automod from the firehose and emitted to ozone for historical tracking. */
|
|
537
|
+
export interface RecordEvent {
|
|
538
|
+
comment?: string
|
|
539
|
+
op: 'create' | 'update' | 'delete' | (string & {})
|
|
540
|
+
cid?: string
|
|
541
|
+
timestamp: string
|
|
542
|
+
[k: string]: unknown
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
export function isRecordEvent(v: unknown): v is RecordEvent {
|
|
546
|
+
return (
|
|
547
|
+
isObj(v) &&
|
|
548
|
+
hasProp(v, '$type') &&
|
|
549
|
+
v.$type === 'tools.ozone.moderation.defs#recordEvent'
|
|
550
|
+
)
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
export function validateRecordEvent(v: unknown): ValidationResult {
|
|
554
|
+
return lexicons.validate('tools.ozone.moderation.defs#recordEvent', v)
|
|
555
|
+
}
|
|
556
|
+
|
|
475
557
|
export interface RepoView {
|
|
476
558
|
did: string
|
|
477
559
|
handle: string
|
|
@@ -483,6 +565,7 @@ export interface RepoView {
|
|
|
483
565
|
invitesDisabled?: boolean
|
|
484
566
|
inviteNote?: string
|
|
485
567
|
deactivatedAt?: string
|
|
568
|
+
threatSignatures?: ComAtprotoAdminDefs.ThreatSignature[]
|
|
486
569
|
[k: string]: unknown
|
|
487
570
|
}
|
|
488
571
|
|
|
@@ -512,6 +595,7 @@ export interface RepoViewDetail {
|
|
|
512
595
|
inviteNote?: string
|
|
513
596
|
emailConfirmedAt?: string
|
|
514
597
|
deactivatedAt?: string
|
|
598
|
+
threatSignatures?: ComAtprotoAdminDefs.ThreatSignature[]
|
|
515
599
|
[k: string]: unknown
|
|
516
600
|
}
|
|
517
601
|
|
|
@@ -703,3 +787,51 @@ export function isVideoDetails(v: unknown): v is VideoDetails {
|
|
|
703
787
|
export function validateVideoDetails(v: unknown): ValidationResult {
|
|
704
788
|
return lexicons.validate('tools.ozone.moderation.defs#videoDetails', v)
|
|
705
789
|
}
|
|
790
|
+
|
|
791
|
+
export interface AccountHosting {
|
|
792
|
+
status:
|
|
793
|
+
| 'takendown'
|
|
794
|
+
| 'suspended'
|
|
795
|
+
| 'deleted'
|
|
796
|
+
| 'deactivated'
|
|
797
|
+
| 'unknown'
|
|
798
|
+
| (string & {})
|
|
799
|
+
updatedAt?: string
|
|
800
|
+
createdAt?: string
|
|
801
|
+
deletedAt?: string
|
|
802
|
+
deactivatedAt?: string
|
|
803
|
+
reactivatedAt?: string
|
|
804
|
+
[k: string]: unknown
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
export function isAccountHosting(v: unknown): v is AccountHosting {
|
|
808
|
+
return (
|
|
809
|
+
isObj(v) &&
|
|
810
|
+
hasProp(v, '$type') &&
|
|
811
|
+
v.$type === 'tools.ozone.moderation.defs#accountHosting'
|
|
812
|
+
)
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
export function validateAccountHosting(v: unknown): ValidationResult {
|
|
816
|
+
return lexicons.validate('tools.ozone.moderation.defs#accountHosting', v)
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
export interface RecordHosting {
|
|
820
|
+
status: 'deleted' | 'unknown' | (string & {})
|
|
821
|
+
updatedAt?: string
|
|
822
|
+
createdAt?: string
|
|
823
|
+
deletedAt?: string
|
|
824
|
+
[k: string]: unknown
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
export function isRecordHosting(v: unknown): v is RecordHosting {
|
|
828
|
+
return (
|
|
829
|
+
isObj(v) &&
|
|
830
|
+
hasProp(v, '$type') &&
|
|
831
|
+
v.$type === 'tools.ozone.moderation.defs#recordHosting'
|
|
832
|
+
)
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
export function validateRecordHosting(v: unknown): ValidationResult {
|
|
836
|
+
return lexicons.validate('tools.ozone.moderation.defs#recordHosting', v)
|
|
837
|
+
}
|
|
@@ -29,6 +29,9 @@ export interface InputSchema {
|
|
|
29
29
|
| ToolsOzoneModerationDefs.ModEventResolveAppeal
|
|
30
30
|
| ToolsOzoneModerationDefs.ModEventEmail
|
|
31
31
|
| ToolsOzoneModerationDefs.ModEventTag
|
|
32
|
+
| ToolsOzoneModerationDefs.AccountEvent
|
|
33
|
+
| ToolsOzoneModerationDefs.IdentityEvent
|
|
34
|
+
| ToolsOzoneModerationDefs.RecordEvent
|
|
32
35
|
| { $type: string; [k: string]: unknown }
|
|
33
36
|
subject:
|
|
34
37
|
| ComAtprotoAdminDefs.RepoRef
|
|
@@ -22,6 +22,16 @@ export interface QueryParams {
|
|
|
22
22
|
reportedBefore?: string
|
|
23
23
|
/** Search subjects reviewed after a given timestamp */
|
|
24
24
|
reviewedAfter?: string
|
|
25
|
+
/** Search subjects where the associated record/account was deleted after a given timestamp */
|
|
26
|
+
hostingDeletedAfter?: string
|
|
27
|
+
/** Search subjects where the associated record/account was deleted before a given timestamp */
|
|
28
|
+
hostingDeletedBefore?: string
|
|
29
|
+
/** Search subjects where the associated record/account was updated after a given timestamp */
|
|
30
|
+
hostingUpdatedAfter?: string
|
|
31
|
+
/** Search subjects where the associated record/account was updated before a given timestamp */
|
|
32
|
+
hostingUpdatedBefore?: string
|
|
33
|
+
/** Search subjects by the status of the associated record/account */
|
|
34
|
+
hostingStatuses?: string[]
|
|
25
35
|
/** Search subjects reviewed before a given timestamp */
|
|
26
36
|
reviewedBefore?: string
|
|
27
37
|
/** By default, we don't include muted subjects in the results. Set this to true to include them. */
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
5
|
+
import { lexicons } from '../../../../lexicons'
|
|
6
|
+
import { isObj, hasProp } from '../../../../util'
|
|
7
|
+
import { CID } from 'multiformats/cid'
|
|
8
|
+
|
|
9
|
+
export interface Option {
|
|
10
|
+
key: string
|
|
11
|
+
did: string
|
|
12
|
+
value: {}
|
|
13
|
+
description?: string
|
|
14
|
+
createdAt?: string
|
|
15
|
+
updatedAt?: string
|
|
16
|
+
managerRole?:
|
|
17
|
+
| 'tools.ozone.team.defs#roleModerator'
|
|
18
|
+
| 'tools.ozone.team.defs#roleTriage'
|
|
19
|
+
| 'tools.ozone.team.defs#roleAdmin'
|
|
20
|
+
| (string & {})
|
|
21
|
+
scope: 'instance' | 'personal' | (string & {})
|
|
22
|
+
createdBy: string
|
|
23
|
+
lastUpdatedBy: string
|
|
24
|
+
[k: string]: unknown
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function isOption(v: unknown): v is Option {
|
|
28
|
+
return (
|
|
29
|
+
isObj(v) &&
|
|
30
|
+
hasProp(v, '$type') &&
|
|
31
|
+
v.$type === 'tools.ozone.setting.defs#option'
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function validateOption(v: unknown): ValidationResult {
|
|
36
|
+
return lexicons.validate('tools.ozone.setting.defs#option', v)
|
|
37
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import express from 'express'
|
|
5
|
+
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
6
|
+
import { lexicons } from '../../../../lexicons'
|
|
7
|
+
import { isObj, hasProp } from '../../../../util'
|
|
8
|
+
import { CID } from 'multiformats/cid'
|
|
9
|
+
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
|
10
|
+
import * as ToolsOzoneSettingDefs from './defs'
|
|
11
|
+
|
|
12
|
+
export interface QueryParams {
|
|
13
|
+
limit: number
|
|
14
|
+
cursor?: string
|
|
15
|
+
scope: 'instance' | 'personal' | (string & {})
|
|
16
|
+
/** Filter keys by prefix */
|
|
17
|
+
prefix?: string
|
|
18
|
+
/** Filter for only the specified keys. Ignored if prefix is provided */
|
|
19
|
+
keys?: string[]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type InputSchema = undefined
|
|
23
|
+
|
|
24
|
+
export interface OutputSchema {
|
|
25
|
+
cursor?: string
|
|
26
|
+
options: ToolsOzoneSettingDefs.Option[]
|
|
27
|
+
[k: string]: unknown
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type HandlerInput = undefined
|
|
31
|
+
|
|
32
|
+
export interface HandlerSuccess {
|
|
33
|
+
encoding: 'application/json'
|
|
34
|
+
body: OutputSchema
|
|
35
|
+
headers?: { [key: string]: string }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface HandlerError {
|
|
39
|
+
status: number
|
|
40
|
+
message?: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
|
44
|
+
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
|
45
|
+
auth: HA
|
|
46
|
+
params: QueryParams
|
|
47
|
+
input: HandlerInput
|
|
48
|
+
req: express.Request
|
|
49
|
+
res: express.Response
|
|
50
|
+
}
|
|
51
|
+
export type Handler<HA extends HandlerAuth = never> = (
|
|
52
|
+
ctx: HandlerReqCtx<HA>,
|
|
53
|
+
) => Promise<HandlerOutput> | HandlerOutput
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import express from 'express'
|
|
5
|
+
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
6
|
+
import { lexicons } from '../../../../lexicons'
|
|
7
|
+
import { isObj, hasProp } from '../../../../util'
|
|
8
|
+
import { CID } from 'multiformats/cid'
|
|
9
|
+
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
|
10
|
+
|
|
11
|
+
export interface QueryParams {}
|
|
12
|
+
|
|
13
|
+
export interface InputSchema {
|
|
14
|
+
keys: string[]
|
|
15
|
+
scope: 'instance' | 'personal' | (string & {})
|
|
16
|
+
[k: string]: unknown
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface OutputSchema {
|
|
20
|
+
[k: string]: unknown
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface HandlerInput {
|
|
24
|
+
encoding: 'application/json'
|
|
25
|
+
body: InputSchema
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface HandlerSuccess {
|
|
29
|
+
encoding: 'application/json'
|
|
30
|
+
body: OutputSchema
|
|
31
|
+
headers?: { [key: string]: string }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface HandlerError {
|
|
35
|
+
status: number
|
|
36
|
+
message?: string
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
|
40
|
+
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
|
41
|
+
auth: HA
|
|
42
|
+
params: QueryParams
|
|
43
|
+
input: HandlerInput
|
|
44
|
+
req: express.Request
|
|
45
|
+
res: express.Response
|
|
46
|
+
}
|
|
47
|
+
export type Handler<HA extends HandlerAuth = never> = (
|
|
48
|
+
ctx: HandlerReqCtx<HA>,
|
|
49
|
+
) => Promise<HandlerOutput> | HandlerOutput
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED CODE - DO NOT MODIFY
|
|
3
|
+
*/
|
|
4
|
+
import express from 'express'
|
|
5
|
+
import { ValidationResult, BlobRef } from '@atproto/lexicon'
|
|
6
|
+
import { lexicons } from '../../../../lexicons'
|
|
7
|
+
import { isObj, hasProp } from '../../../../util'
|
|
8
|
+
import { CID } from 'multiformats/cid'
|
|
9
|
+
import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
|
|
10
|
+
import * as ToolsOzoneSettingDefs from './defs'
|
|
11
|
+
|
|
12
|
+
export interface QueryParams {}
|
|
13
|
+
|
|
14
|
+
export interface InputSchema {
|
|
15
|
+
key: string
|
|
16
|
+
scope: 'instance' | 'personal' | (string & {})
|
|
17
|
+
value: {}
|
|
18
|
+
description?: string
|
|
19
|
+
managerRole?:
|
|
20
|
+
| 'tools.ozone.team.defs#roleModerator'
|
|
21
|
+
| 'tools.ozone.team.defs#roleTriage'
|
|
22
|
+
| 'tools.ozone.team.defs#roleAdmin'
|
|
23
|
+
| (string & {})
|
|
24
|
+
[k: string]: unknown
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface OutputSchema {
|
|
28
|
+
option: ToolsOzoneSettingDefs.Option
|
|
29
|
+
[k: string]: unknown
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface HandlerInput {
|
|
33
|
+
encoding: 'application/json'
|
|
34
|
+
body: InputSchema
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface HandlerSuccess {
|
|
38
|
+
encoding: 'application/json'
|
|
39
|
+
body: OutputSchema
|
|
40
|
+
headers?: { [key: string]: string }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface HandlerError {
|
|
44
|
+
status: number
|
|
45
|
+
message?: string
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
|
|
49
|
+
export type HandlerReqCtx<HA extends HandlerAuth = never> = {
|
|
50
|
+
auth: HA
|
|
51
|
+
params: QueryParams
|
|
52
|
+
input: HandlerInput
|
|
53
|
+
req: express.Request
|
|
54
|
+
res: express.Response
|
|
55
|
+
}
|
|
56
|
+
export type Handler<HA extends HandlerAuth = never> = (
|
|
57
|
+
ctx: HandlerReqCtx<HA>,
|
|
58
|
+
) => Promise<HandlerOutput> | HandlerOutput
|
package/src/mod-service/index.ts
CHANGED
|
@@ -18,6 +18,9 @@ import {
|
|
|
18
18
|
isModEventTakedown,
|
|
19
19
|
isModEventEmail,
|
|
20
20
|
isModEventTag,
|
|
21
|
+
isAccountEvent,
|
|
22
|
+
isIdentityEvent,
|
|
23
|
+
isRecordEvent,
|
|
21
24
|
REVIEWESCALATED,
|
|
22
25
|
REVIEWOPEN,
|
|
23
26
|
} from '../lexicon/types/tools/ozone/moderation/defs'
|
|
@@ -386,6 +389,25 @@ export class ModerationService {
|
|
|
386
389
|
}
|
|
387
390
|
}
|
|
388
391
|
|
|
392
|
+
if (isAccountEvent(event)) {
|
|
393
|
+
meta.active = event.active
|
|
394
|
+
meta.timestamp = event.timestamp
|
|
395
|
+
if (event.status) meta.status = event.status
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (isIdentityEvent(event)) {
|
|
399
|
+
meta.timestamp = event.timestamp
|
|
400
|
+
if (event.handle) meta.handle = event.handle
|
|
401
|
+
if (event.pdsHost) meta.pdsHost = event.pdsHost
|
|
402
|
+
if (event.tombstone) meta.tombstone = event.tombstone
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (isRecordEvent(event)) {
|
|
406
|
+
meta.timestamp = event.timestamp
|
|
407
|
+
meta.op = event.op
|
|
408
|
+
if (event.cid) meta.cid = event.cid
|
|
409
|
+
}
|
|
410
|
+
|
|
389
411
|
if (isModEventTakedown(event) && event.acknowledgeAccountSubjects) {
|
|
390
412
|
meta.acknowledgeAccountSubjects = true
|
|
391
413
|
}
|
|
@@ -758,6 +780,11 @@ export class ModerationService {
|
|
|
758
780
|
reportedAfter,
|
|
759
781
|
reportedBefore,
|
|
760
782
|
includeMuted,
|
|
783
|
+
hostingDeletedBefore,
|
|
784
|
+
hostingDeletedAfter,
|
|
785
|
+
hostingUpdatedBefore,
|
|
786
|
+
hostingUpdatedAfter,
|
|
787
|
+
hostingStatuses,
|
|
761
788
|
onlyMuted,
|
|
762
789
|
ignoreSubjects,
|
|
763
790
|
sortDirection,
|
|
@@ -780,6 +807,11 @@ export class ModerationService {
|
|
|
780
807
|
reportedAfter?: string
|
|
781
808
|
reportedBefore?: string
|
|
782
809
|
includeMuted?: boolean
|
|
810
|
+
hostingDeletedBefore?: string
|
|
811
|
+
hostingDeletedAfter?: string
|
|
812
|
+
hostingUpdatedBefore?: string
|
|
813
|
+
hostingUpdatedAfter?: string
|
|
814
|
+
hostingStatuses?: string[]
|
|
783
815
|
onlyMuted?: boolean
|
|
784
816
|
subject?: string
|
|
785
817
|
ignoreSubjects?: string[]
|
|
@@ -847,6 +879,26 @@ export class ModerationService {
|
|
|
847
879
|
builder = builder.where('lastReviewedAt', '<', reviewedBefore)
|
|
848
880
|
}
|
|
849
881
|
|
|
882
|
+
if (hostingUpdatedAfter) {
|
|
883
|
+
builder = builder.where('hostingUpdatedAt', '>', hostingUpdatedAfter)
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
if (hostingUpdatedBefore) {
|
|
887
|
+
builder = builder.where('hostingUpdatedAt', '<', hostingUpdatedBefore)
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
if (hostingDeletedAfter) {
|
|
891
|
+
builder = builder.where('hostingDeletedAt', '>', hostingDeletedAfter)
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
if (hostingDeletedBefore) {
|
|
895
|
+
builder = builder.where('hostingDeletedAt', '<', hostingDeletedBefore)
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
if (hostingStatuses?.length) {
|
|
899
|
+
builder = builder.where('hostingStatus', 'in', hostingStatuses)
|
|
900
|
+
}
|
|
901
|
+
|
|
850
902
|
if (reportedAfter) {
|
|
851
903
|
builder = builder.where('lastReviewedAt', '>', reportedAfter)
|
|
852
904
|
}
|
|
@@ -126,6 +126,83 @@ const getSubjectStatusForModerationEvent = ({
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
const hostingEvents = [
|
|
130
|
+
'tools.ozone.moderation.defs#accountEvent',
|
|
131
|
+
'tools.ozone.moderation.defs#identityEvent',
|
|
132
|
+
'tools.ozone.moderation.defs#recordEvent',
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
const getSubjectStatusForRecordEvent = ({
|
|
136
|
+
event,
|
|
137
|
+
currentStatus,
|
|
138
|
+
}: {
|
|
139
|
+
event: ModerationEventRow
|
|
140
|
+
currentStatus?: ModerationSubjectStatusRow
|
|
141
|
+
}): Partial<ModerationSubjectStatusRow> => {
|
|
142
|
+
const timestamp =
|
|
143
|
+
typeof event.meta?.timestamp === 'string'
|
|
144
|
+
? event.meta?.timestamp
|
|
145
|
+
: event.createdAt
|
|
146
|
+
|
|
147
|
+
if (event.action === 'tools.ozone.moderation.defs#recordEvent') {
|
|
148
|
+
if (event.meta?.op === 'delete') {
|
|
149
|
+
return {
|
|
150
|
+
hostingStatus: 'deleted',
|
|
151
|
+
hostingDeletedAt: timestamp,
|
|
152
|
+
}
|
|
153
|
+
} else if (event.meta?.op === 'update') {
|
|
154
|
+
return {
|
|
155
|
+
hostingStatus: 'active',
|
|
156
|
+
hostingUpdatedAt: timestamp,
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return {}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (event.action === 'tools.ozone.moderation.defs#accountEvent') {
|
|
163
|
+
const status: Partial<ModerationSubjectStatusRow> = {
|
|
164
|
+
hostingUpdatedAt: timestamp,
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (event.meta?.status) {
|
|
168
|
+
status.hostingStatus = `${event.meta?.status}`
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (event.meta?.status === 'deleted') {
|
|
172
|
+
status.hostingDeletedAt = timestamp
|
|
173
|
+
} else if (event.meta?.status === 'deactivated') {
|
|
174
|
+
status.hostingDeactivatedAt = timestamp
|
|
175
|
+
} else {
|
|
176
|
+
// When deactivated accounts are re-activated, we receive the event with just the active flag set to true
|
|
177
|
+
// so we want to make sure that the hostingStatus is not set to an outdated value
|
|
178
|
+
if (
|
|
179
|
+
currentStatus?.hostingStatus === 'deactivated' &&
|
|
180
|
+
event.meta?.active
|
|
181
|
+
) {
|
|
182
|
+
status.hostingStatus = 'active'
|
|
183
|
+
status.hostingReactivatedAt = timestamp
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return status
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (event.action === 'tools.ozone.moderation.defs#identityEvent') {
|
|
191
|
+
const status: Partial<ModerationSubjectStatusRow> = {
|
|
192
|
+
hostingUpdatedAt: timestamp,
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (event.meta?.tombstone) {
|
|
196
|
+
status.hostingStatus = 'tombstoned'
|
|
197
|
+
status.hostingDeletedAt = timestamp
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return status
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return {}
|
|
204
|
+
}
|
|
205
|
+
|
|
129
206
|
// Based on a given moderation action event, this function will update the moderation status of the subject
|
|
130
207
|
// If there's no existing status, it will create one
|
|
131
208
|
// If the action event does not affect the status, it will do nothing
|
|
@@ -133,7 +210,7 @@ export const adjustModerationSubjectStatus = async (
|
|
|
133
210
|
db: Database,
|
|
134
211
|
moderationEvent: ModerationEventRow,
|
|
135
212
|
blobCids?: string[],
|
|
136
|
-
) => {
|
|
213
|
+
): Promise<ModerationSubjectStatusRow | null> => {
|
|
137
214
|
const {
|
|
138
215
|
action,
|
|
139
216
|
subjectDid,
|
|
@@ -152,6 +229,7 @@ export const adjustModerationSubjectStatus = async (
|
|
|
152
229
|
|
|
153
230
|
db.assertTransaction()
|
|
154
231
|
|
|
232
|
+
const now = new Date().toISOString()
|
|
155
233
|
const currentStatus = await db.db
|
|
156
234
|
.selectFrom('moderation_subject_status')
|
|
157
235
|
.where('did', '=', identifier.did)
|
|
@@ -161,6 +239,41 @@ export const adjustModerationSubjectStatus = async (
|
|
|
161
239
|
.selectAll()
|
|
162
240
|
.executeTakeFirst()
|
|
163
241
|
|
|
242
|
+
if (hostingEvents.includes(action)) {
|
|
243
|
+
const newStatus = getSubjectStatusForRecordEvent({
|
|
244
|
+
event: moderationEvent,
|
|
245
|
+
currentStatus,
|
|
246
|
+
})
|
|
247
|
+
if (!Object.keys(newStatus).length) {
|
|
248
|
+
return currentStatus || null
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const status = await db.db
|
|
252
|
+
.insertInto('moderation_subject_status')
|
|
253
|
+
.values({
|
|
254
|
+
...identifier,
|
|
255
|
+
...newStatus,
|
|
256
|
+
// newStatus doesn't contain a reviewState or takendown so in case this is a new entry
|
|
257
|
+
// we need to set a default values so that the insert doesn't fail
|
|
258
|
+
reviewState: currentStatus ? currentStatus.reviewState : REVIEWNONE,
|
|
259
|
+
// @TODO: should we try to update this based on status property of account event?
|
|
260
|
+
// For now we're the only one emitting takedowns so i don't think it makes too much of a difference
|
|
261
|
+
takendown: currentStatus ? currentStatus.takendown : false,
|
|
262
|
+
createdAt: now,
|
|
263
|
+
updatedAt: now,
|
|
264
|
+
})
|
|
265
|
+
.onConflict((oc) =>
|
|
266
|
+
oc.constraint('moderation_status_unique_idx').doUpdateSet({
|
|
267
|
+
...newStatus,
|
|
268
|
+
updatedAt: now,
|
|
269
|
+
}),
|
|
270
|
+
)
|
|
271
|
+
.returningAll()
|
|
272
|
+
.executeTakeFirst()
|
|
273
|
+
|
|
274
|
+
return status || null
|
|
275
|
+
}
|
|
276
|
+
|
|
164
277
|
// If reporting is muted for this reporter, we don't want to update the subject status
|
|
165
278
|
if (meta?.isReporterMuted) {
|
|
166
279
|
return currentStatus || null
|
|
@@ -178,7 +291,6 @@ export const adjustModerationSubjectStatus = async (
|
|
|
178
291
|
durationInHours: moderationEvent.durationInHours,
|
|
179
292
|
})
|
|
180
293
|
|
|
181
|
-
const now = new Date().toISOString()
|
|
182
294
|
if (
|
|
183
295
|
currentStatus?.reviewState === REVIEWESCALATED &&
|
|
184
296
|
subjectStatus.reviewState !== REVIEWCLOSED
|
package/src/mod-service/types.ts
CHANGED
|
@@ -31,3 +31,28 @@ export type ModEventType =
|
|
|
31
31
|
| ToolsOzoneModerationDefs.ModEventMute
|
|
32
32
|
| ToolsOzoneModerationDefs.ModEventReverseTakedown
|
|
33
33
|
| ToolsOzoneModerationDefs.ModEventTag
|
|
34
|
+
| ToolsOzoneModerationDefs.AccountEvent
|
|
35
|
+
| ToolsOzoneModerationDefs.IdentityEvent
|
|
36
|
+
| ToolsOzoneModerationDefs.RecordEvent
|
|
37
|
+
|
|
38
|
+
type AccountHostingView = {
|
|
39
|
+
$type: 'tools.ozone.moderation.defs#accountHosting'
|
|
40
|
+
status: 'active' | 'takendown' | 'suspended' | 'deleted' | 'deactivated'
|
|
41
|
+
createdAt?: Date
|
|
42
|
+
updatedAt?: Date
|
|
43
|
+
deletedAt?: Date
|
|
44
|
+
deactivatedAt?: Date
|
|
45
|
+
reactivatedAt?: Date
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
type RecordHostingView = {
|
|
49
|
+
$type: 'tools.ozone.moderation.defs#recordHosting'
|
|
50
|
+
status: 'active' | 'deleted'
|
|
51
|
+
createdAt?: Date
|
|
52
|
+
updatedAt?: Date
|
|
53
|
+
deletedAt?: Date
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type ModerationSubjectHostingView =
|
|
57
|
+
| AccountHostingView
|
|
58
|
+
| RecordHostingView
|