@atproto/ozone
Version:
Backend service for moderating the Bluesky network.
207 lines • 11.6 kB
TypeScript
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