UNPKG

@atproto/ozone

Version:

Backend service for moderating the Bluesky network.

207 lines 11.6 kB
import { CID } from 'multiformats/cid'; import { AtpAgent, ToolsOzoneModerationDefs } from '@atproto/api'; import { Keypair } from '@atproto/crypto'; import { IdResolver } from '@atproto/identity'; import { AtUri } from '@atproto/syntax'; import { BackgroundQueue } from '../background'; import { OzoneConfig } from '../config'; import { EventPusher } from '../daemon'; import { Database } from '../db'; import { ModerationEvent } from '../db/schema/moderation_event'; import { ImageInvalidator } from '../image-invalidator'; import { RepoBlobRef, RepoRef } from '../lexicon/types/com/atproto/admin/defs'; import { Label } from '../lexicon/types/com/atproto/label/defs'; import { ReasonType } from '../lexicon/types/com/atproto/moderation/defs'; import { Main as StrongRef } from '../lexicon/types/com/atproto/repo/strongRef'; import { QueryParams as QueryStatusParams } from '../lexicon/types/tools/ozone/moderation/queryStatuses'; import { StrikeService, StrikeServiceCreator } from './strike'; import { ModSubject, RecordSubject, RepoSubject } from './subject'; import { ModEventType, ModerationEventRow, ModerationSubjectStatusRow, ModerationSubjectStatusRowWithHandle, ReporterStats, ReporterStatsResult, ReversibleModerationEvent } from './types'; import { AuthHeaders, ModerationViews } from './views'; export type ModerationServiceCreator = (db: Database) => ModerationService; export declare class ModerationService { db: Database; signingKey: Keypair; signingKeyId: number; cfg: OzoneConfig; backgroundQueue: BackgroundQueue; idResolver: IdResolver; eventPusher: EventPusher; appviewAgent: AtpAgent; private createAuthHeaders; strikeService: StrikeService; imgInvalidator?: ImageInvalidator | undefined; constructor(db: Database, signingKey: Keypair, signingKeyId: number, cfg: OzoneConfig, backgroundQueue: BackgroundQueue, idResolver: IdResolver, eventPusher: EventPusher, appviewAgent: AtpAgent, createAuthHeaders: (aud: string, method: string) => Promise<AuthHeaders>, strikeService: StrikeService, imgInvalidator?: ImageInvalidator | undefined); static creator(signingKey: Keypair, signingKeyId: number, cfg: OzoneConfig, backgroundQueue: BackgroundQueue, idResolver: IdResolver, eventPusher: EventPusher, appviewAgent: AtpAgent, createAuthHeaders: (aud: string, method: string) => Promise<AuthHeaders>, strikeServiceCreator: StrikeServiceCreator, imgInvalidator?: ImageInvalidator): (db: Database) => ModerationService; views: ModerationViews; getEvent(id: number): Promise<ModerationEventRow | undefined>; getEventOrThrow(id: number): Promise<ModerationEventRow>; getEventByExternalId(eventType: ModerationEvent['action'], externalId: string, subject: ModSubject): Promise<boolean>; getEvents(opts: { subject?: string; createdBy?: string; limit: number; cursor?: string; includeAllUserRecords: boolean; types: ModerationEvent['action'][]; sortDirection?: 'asc' | 'desc'; hasComment?: boolean; comment?: string; createdAfter?: string; createdBefore?: string; addedLabels: string[]; removedLabels: string[]; addedTags: string[]; removedTags: string[]; reportTypes?: string[]; collections: string[]; subjectType?: string; policies?: string[]; modTool?: string[]; ageAssuranceState?: string; batchId?: string; withStrike?: boolean; }): Promise<{ cursor?: string; events: ModerationEventRow[]; }>; getReport(id: number): Promise<ModerationEventRow | undefined>; getCurrentStatus(subject: { did: string; } | { uri: AtUri; } | { cids: CID[]; }): Promise<{ id: number; comment: string | null; createdAt: string; did: string; recordPath: string; blobCids: string[] | null; recordCid: string | null; reviewState: "tools.ozone.moderation.defs#reviewOpen" | "tools.ozone.moderation.defs#reviewEscalated" | "tools.ozone.moderation.defs#reviewClosed" | "tools.ozone.moderation.defs#reviewNone"; muteUntil: string | null; lastReviewedAt: string | null; lastReviewedBy: string | null; lastReportedAt: string | null; lastAppealedAt: string | null; takendown: boolean; suspendUntil: string | null; appealed: boolean | null; updatedAt: string; tags: string[] | null; muteReportingUntil: string | null; hostingStatus: string | null; hostingDeletedAt: string | null; hostingUpdatedAt: string | null; hostingCreatedAt: string | null; hostingDeactivatedAt: string | null; hostingReactivatedAt: string | null; ageAssuranceState: string; priorityScore: number | undefined; ageAssuranceUpdatedBy: string | null | undefined; }[]>; resolveSubjectsForAccount(did: string, createdBy: string, accountEvent: ModerationEventRow): Promise<void>; logEvent(info: { event: ModEventType; subject: ModSubject; createdBy: string; createdAt?: Date; modTool?: ToolsOzoneModerationDefs.ModTool; externalId?: string; }): Promise<{ event: ModerationEventRow; subjectStatus: ModerationSubjectStatusRow | null; }>; getLastReversibleEventForSubject(subject: ReversalSubject): Promise<{ id: number; action: "tools.ozone.moderation.defs#modEventTakedown" | "tools.ozone.moderation.defs#modEventReverseTakedown" | "tools.ozone.moderation.defs#modEventComment" | "tools.ozone.moderation.defs#modEventReport" | "tools.ozone.moderation.defs#modEventLabel" | "tools.ozone.moderation.defs#modEventAcknowledge" | "tools.ozone.moderation.defs#modEventEscalate" | "tools.ozone.moderation.defs#modEventMute" | "tools.ozone.moderation.defs#modEventUnmute" | "tools.ozone.moderation.defs#modEventMuteReporter" | "tools.ozone.moderation.defs#modEventUnmuteReporter" | "tools.ozone.moderation.defs#modEventEmail" | "tools.ozone.moderation.defs#modEventResolveAppeal" | "tools.ozone.moderation.defs#modEventTag" | "tools.ozone.moderation.defs#accountEvent" | "tools.ozone.moderation.defs#identityEvent" | "tools.ozone.moderation.defs#recordEvent" | "tools.ozone.moderation.defs#modEventPriorityScore" | "tools.ozone.moderation.defs#revokeAccountCredentialsEvent" | "tools.ozone.moderation.defs#ageAssuranceEvent" | "tools.ozone.moderation.defs#ageAssuranceOverrideEvent"; subjectType: "com.atproto.repo.strongRef" | "com.atproto.admin.defs#repoRef" | "chat.bsky.convo.defs#messageRef"; subjectDid: string; subjectUri: string | null; subjectCid: string | null; comment: string | null; meta: Record<string, string | number | boolean> | null; createdAt: string; createdBy: string; durationInHours: number | null; expiresAt: string | null; createLabelVals: string | null; negateLabelVals: string | null; legacyRefId: number | null; subjectBlobCids: string[] | null; addedTags: string[] | null; removedTags: string[] | null; subjectMessageId: string | null; modTool: { name: string; meta?: { [_ in string]: unknown; }; } | null; severityLevel: string | null; strikeCount: number | null; strikeExpiresAt: string | null; externalId: string | null; } | null | undefined>; getSubjectsDueForReversal(): Promise<ReversalSubject[]>; isSubjectSuspended(did: string): Promise<boolean>; revertState({ createdBy, createdAt, comment, action, subject, }: ReversibleModerationEvent): Promise<ModerationEventRow>; takedownRepo(subject: RepoSubject, takedownId: number, targetServices: Set<string>, isSuspend?: boolean): Promise<void>; reverseTakedownRepo(subject: RepoSubject): Promise<void>; takedownRecord(subject: RecordSubject, takedownId: number, targetServices: Set<string>): Promise<void>; reverseTakedownRecord(subject: RecordSubject): Promise<void>; report(info: { reasonType: ReasonType; reason?: string; subject: ModSubject; reportedBy: string; createdAt?: Date; modTool?: { name: string; meta?: { [_ in string]: unknown; }; }; }): Promise<{ event: ModerationEventRow; subjectStatus: ModerationSubjectStatusRow | null; }>; getSubjectStatuses({ queueCount, queueIndex, queueSeed, includeAllUserRecords, cursor, limit, takendown, appealed, reviewState, reviewedAfter, reviewedBefore, reportedAfter, reportedBefore, includeMuted, hostingDeletedBefore, hostingDeletedAfter, hostingUpdatedBefore, hostingUpdatedAfter, hostingStatuses, onlyMuted, ignoreSubjects, sortDirection, lastReviewedBy, sortField, subject, tags, excludeTags, collections, subjectType, minAccountSuspendCount, minReportedRecordsCount, minTakendownRecordsCount, minPriorityScore, minStrikeCount, ageAssuranceState, }: QueryStatusParams): Promise<{ statuses: ModerationSubjectStatusRowWithHandle[]; cursor?: string; }>; getStatus(subject: ModSubject): Promise<ModerationSubjectStatusRow | null>; isReportingMutedForSubject(did: string): Promise<boolean>; formatAndCreateLabels(uri: string, cid: string | null, labels: { create?: string[]; negate?: string[]; }, durationInHours?: number): Promise<Label[]>; createLabels(labels: Label[]): Promise<Label[]>; sendEmail(opts: { content: string; recipientDid: string; subject: string; }): Promise<void>; buildModerationQuery(subjectType: 'account' | 'record', createdByDids: string[], isActionQuery: boolean): Promise<(Partial<ReporterStatsResult> & { did: string; })[]>; getReporterStats(dids: string[]): Promise<ReporterStats[]>; getAccountTimeline(did: string): Promise<{ action: "tools.ozone.moderation.defs#modEventTakedown" | "tools.ozone.moderation.defs#modEventReverseTakedown" | "tools.ozone.moderation.defs#modEventComment" | "tools.ozone.moderation.defs#modEventReport" | "tools.ozone.moderation.defs#modEventLabel" | "tools.ozone.moderation.defs#modEventAcknowledge" | "tools.ozone.moderation.defs#modEventEscalate" | "tools.ozone.moderation.defs#modEventMute" | "tools.ozone.moderation.defs#modEventUnmute" | "tools.ozone.moderation.defs#modEventMuteReporter" | "tools.ozone.moderation.defs#modEventUnmuteReporter" | "tools.ozone.moderation.defs#modEventEmail" | "tools.ozone.moderation.defs#modEventResolveAppeal" | "tools.ozone.moderation.defs#modEventTag" | "tools.ozone.moderation.defs#accountEvent" | "tools.ozone.moderation.defs#identityEvent" | "tools.ozone.moderation.defs#recordEvent" | "tools.ozone.moderation.defs#modEventPriorityScore" | "tools.ozone.moderation.defs#revokeAccountCredentialsEvent" | "tools.ozone.moderation.defs#ageAssuranceEvent" | "tools.ozone.moderation.defs#ageAssuranceOverrideEvent"; subjectUri: string | null; count: number; day: string; }[]>; } export declare const TAKEDOWN_LABEL = "!takedown"; export declare const SUSPEND_LABEL = "!suspend"; export type TakedownSubjects = { did: string; subjects: (RepoRef | RepoBlobRef | StrongRef)[]; }; export type ReversalSubject = { subject: ModSubject; reverseSuspend: boolean; reverseMute: boolean; }; //# sourceMappingURL=index.d.ts.map