diff --git a/lexicons/tools/ozone/communication/createTemplate.json b/lexicons/tools/ozone/communication/createTemplate.json new file mode 100644 index 00000000000..175a55f9d03 --- /dev/null +++ b/lexicons/tools/ozone/communication/createTemplate.json @@ -0,0 +1,43 @@ +{ + "lexicon": 1, + "id": "tools.ozone.communication.createTemplate", + "defs": { + "main": { + "type": "procedure", + "description": "Administrative action to create a new, re-usable communication (email for now) template.", + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["subject", "contentMarkdown", "name"], + "properties": { + "name": { + "type": "string", + "description": "Name of the template." + }, + "contentMarkdown": { + "type": "string", + "description": "Content of the template, markdown supported, can contain variable placeholders." + }, + "subject": { + "type": "string", + "description": "Subject of the message, used in emails." + }, + "createdBy": { + "type": "string", + "format": "did", + "description": "DID of the user who is creating the template." + } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "ref", + "ref": "tools.ozone.communication.defs#templateView" + } + } + } + } +} diff --git a/lexicons/tools/ozone/communication/defs.json b/lexicons/tools/ozone/communication/defs.json new file mode 100644 index 00000000000..89d28bdf690 --- /dev/null +++ b/lexicons/tools/ozone/communication/defs.json @@ -0,0 +1,38 @@ +{ + "lexicon": 1, + "id": "tools.ozone.communication.defs", + "defs": { + "templateView": { + "type": "object", + "required": [ + "id", + "name", + "contentMarkdown", + "disabled", + "lastUpdatedBy", + "createdAt", + "updatedAt" + ], + "properties": { + "id": { "type": "string" }, + "name": { "type": "string", "description": "Name of the template." }, + "subject": { + "type": "string", + "description": "Content of the template, can contain markdown and variable placeholders." + }, + "contentMarkdown": { + "type": "string", + "description": "Subject of the message, used in emails." + }, + "disabled": { "type": "boolean" }, + "lastUpdatedBy": { + "type": "string", + "format": "did", + "description": "DID of the user who last updated the template." + }, + "createdAt": { "type": "string", "format": "datetime" }, + "updatedAt": { "type": "string", "format": "datetime" } + } + } + } +} diff --git a/lexicons/tools/ozone/communication/deleteTemplate.json b/lexicons/tools/ozone/communication/deleteTemplate.json new file mode 100644 index 00000000000..c85bd34959b --- /dev/null +++ b/lexicons/tools/ozone/communication/deleteTemplate.json @@ -0,0 +1,20 @@ +{ + "lexicon": 1, + "id": "tools.ozone.communication.deleteTemplate", + "defs": { + "main": { + "type": "procedure", + "description": "Delete a communication template.", + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["id"], + "properties": { + "id": { "type": "string" } + } + } + } + } + } +} diff --git a/lexicons/tools/ozone/communication/listTemplates.json b/lexicons/tools/ozone/communication/listTemplates.json new file mode 100644 index 00000000000..65a24ed7359 --- /dev/null +++ b/lexicons/tools/ozone/communication/listTemplates.json @@ -0,0 +1,26 @@ +{ + "lexicon": 1, + "id": "tools.ozone.communication.listTemplates", + "defs": { + "main": { + "type": "query", + "description": "Get list of all communication templates.", + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["communicationTemplates"], + "properties": { + "communicationTemplates": { + "type": "array", + "items": { + "type": "ref", + "ref": "tools.ozone.communication.defs#templateView" + } + } + } + } + } + } + } +} diff --git a/lexicons/tools/ozone/communication/updateTemplate.json b/lexicons/tools/ozone/communication/updateTemplate.json new file mode 100644 index 00000000000..153453a875e --- /dev/null +++ b/lexicons/tools/ozone/communication/updateTemplate.json @@ -0,0 +1,50 @@ +{ + "lexicon": 1, + "id": "tools.ozone.communication.updateTemplate", + "defs": { + "main": { + "type": "procedure", + "description": "Administrative action to update an existing communication template. Allows passing partial fields to patch specific fields only.", + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["id"], + "properties": { + "id": { + "type": "string", + "description": "ID of the template to be updated." + }, + "name": { + "type": "string", + "description": "Name of the template." + }, + "contentMarkdown": { + "type": "string", + "description": "Content of the template, markdown supported, can contain variable placeholders." + }, + "subject": { + "type": "string", + "description": "Subject of the message, used in emails." + }, + "updatedBy": { + "type": "string", + "format": "did", + "description": "DID of the user who is updating the template." + }, + "disabled": { + "type": "boolean" + } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "ref", + "ref": "tools.ozone.communication.defs#templateView" + } + } + } + } +} diff --git a/lexicons/tools/ozone/moderation/defs.json b/lexicons/tools/ozone/moderation/defs.json new file mode 100644 index 00000000000..e88ac98303e --- /dev/null +++ b/lexicons/tools/ozone/moderation/defs.json @@ -0,0 +1,524 @@ +{ + "lexicon": 1, + "id": "tools.ozone.moderation.defs", + "defs": { + "modEventView": { + "type": "object", + "required": [ + "id", + "event", + "subject", + "subjectBlobCids", + "createdBy", + "createdAt" + ], + "properties": { + "id": { "type": "integer" }, + "event": { + "type": "union", + "refs": [ + "#modEventTakedown", + "#modEventReverseTakedown", + "#modEventComment", + "#modEventReport", + "#modEventLabel", + "#modEventAcknowledge", + "#modEventEscalate", + "#modEventMute", + "#modEventEmail", + "#modEventResolveAppeal", + "#modEventDivert" + ] + }, + "subject": { + "type": "union", + "refs": [ + "com.atproto.admin.defs#repoRef", + "com.atproto.repo.strongRef" + ] + }, + "subjectBlobCids": { "type": "array", "items": { "type": "string" } }, + "createdBy": { "type": "string", "format": "did" }, + "createdAt": { "type": "string", "format": "datetime" }, + "creatorHandle": { "type": "string" }, + "subjectHandle": { "type": "string" } + } + }, + "modEventViewDetail": { + "type": "object", + "required": [ + "id", + "event", + "subject", + "subjectBlobs", + "createdBy", + "createdAt" + ], + "properties": { + "id": { "type": "integer" }, + "event": { + "type": "union", + "refs": [ + "#modEventTakedown", + "#modEventReverseTakedown", + "#modEventComment", + "#modEventReport", + "#modEventLabel", + "#modEventAcknowledge", + "#modEventEscalate", + "#modEventMute", + "#modEventEmail", + "#modEventResolveAppeal", + "#modEventDivert" + ] + }, + "subject": { + "type": "union", + "refs": [ + "#repoView", + "#repoViewNotFound", + "#recordView", + "#recordViewNotFound" + ] + }, + "subjectBlobs": { + "type": "array", + "items": { "type": "ref", "ref": "#blobView" } + }, + "createdBy": { "type": "string", "format": "did" }, + "createdAt": { "type": "string", "format": "datetime" } + } + }, + "subjectStatusView": { + "type": "object", + "required": ["id", "subject", "createdAt", "updatedAt", "reviewState"], + "properties": { + "id": { "type": "integer" }, + "subject": { + "type": "union", + "refs": [ + "com.atproto.admin.defs#repoRef", + "com.atproto.repo.strongRef" + ] + }, + "subjectBlobCids": { + "type": "array", + "items": { "type": "string", "format": "cid" } + }, + "subjectRepoHandle": { "type": "string" }, + "updatedAt": { + "type": "string", + "format": "datetime", + "description": "Timestamp referencing when the last update was made to the moderation status of the subject" + }, + "createdAt": { + "type": "string", + "format": "datetime", + "description": "Timestamp referencing the first moderation status impacting event was emitted on the subject" + }, + "reviewState": { + "type": "ref", + "ref": "#subjectReviewState" + }, + "comment": { + "type": "string", + "description": "Sticky comment on the subject." + }, + "muteUntil": { + "type": "string", + "format": "datetime" + }, + "lastReviewedBy": { + "type": "string", + "format": "did" + }, + "lastReviewedAt": { + "type": "string", + "format": "datetime" + }, + "lastReportedAt": { + "type": "string", + "format": "datetime" + }, + "lastAppealedAt": { + "type": "string", + "format": "datetime", + "description": "Timestamp referencing when the author of the subject appealed a moderation action" + }, + "takendown": { + "type": "boolean" + }, + "appealed": { + "type": "boolean", + "description": "True indicates that the a previously taken moderator action was appealed against, by the author of the content. False indicates last appeal was resolved by moderators." + }, + "suspendUntil": { + "type": "string", + "format": "datetime" + }, + "tags": { + "type": "array", + "items": { "type": "string" } + } + } + }, + "subjectReviewState": { + "type": "string", + "knownValues": [ + "#reviewOpen", + "#reviewEscalated", + "#reviewClosed", + "#reviewNone" + ] + }, + "reviewOpen": { + "type": "token", + "description": "Moderator review status of a subject: Open. Indicates that the subject needs to be reviewed by a moderator" + }, + "reviewEscalated": { + "type": "token", + "description": "Moderator review status of a subject: Escalated. Indicates that the subject was escalated for review by a moderator" + }, + "reviewClosed": { + "type": "token", + "description": "Moderator review status of a subject: Closed. Indicates that the subject was already reviewed and resolved by a moderator" + }, + "reviewNone": { + "type": "token", + "description": "Moderator review status of a subject: Unnecessary. Indicates that the subject does not need a review at the moment but there is probably some moderation related metadata available for it" + }, + "modEventTakedown": { + "type": "object", + "description": "Take down a subject permanently or temporarily", + "properties": { + "comment": { + "type": "string" + }, + "durationInHours": { + "type": "integer", + "description": "Indicates how long the takedown should be in effect before automatically expiring." + } + } + }, + "modEventReverseTakedown": { + "type": "object", + "description": "Revert take down action on a subject", + "properties": { + "comment": { + "type": "string", + "description": "Describe reasoning behind the reversal." + } + } + }, + "modEventResolveAppeal": { + "type": "object", + "description": "Resolve appeal on a subject", + "properties": { + "comment": { + "type": "string", + "description": "Describe resolution." + } + } + }, + "modEventComment": { + "type": "object", + "description": "Add a comment to a subject", + "required": ["comment"], + "properties": { + "comment": { + "type": "string" + }, + "sticky": { + "type": "boolean", + "description": "Make the comment persistent on the subject" + } + } + }, + "modEventReport": { + "type": "object", + "description": "Report a subject", + "required": ["reportType"], + "properties": { + "comment": { + "type": "string" + }, + "reportType": { + "type": "ref", + "ref": "com.atproto.moderation.defs#reasonType" + } + } + }, + "modEventLabel": { + "type": "object", + "description": "Apply/Negate labels on a subject", + "required": ["createLabelVals", "negateLabelVals"], + "properties": { + "comment": { + "type": "string" + }, + "createLabelVals": { + "type": "array", + "items": { "type": "string" } + }, + "negateLabelVals": { + "type": "array", + "items": { "type": "string" } + } + } + }, + "modEventAcknowledge": { + "type": "object", + "properties": { + "comment": { "type": "string" } + } + }, + "modEventEscalate": { + "type": "object", + "properties": { + "comment": { "type": "string" } + } + }, + "modEventMute": { + "type": "object", + "description": "Mute incoming reports on a subject", + "required": ["durationInHours"], + "properties": { + "comment": { "type": "string" }, + "durationInHours": { + "type": "integer", + "description": "Indicates how long the subject should remain muted." + } + } + }, + "modEventUnmute": { + "type": "object", + "description": "Unmute action on a subject", + "properties": { + "comment": { + "type": "string", + "description": "Describe reasoning behind the reversal." + } + } + }, + "modEventEmail": { + "type": "object", + "description": "Keep a log of outgoing email to a user", + "required": ["subjectLine"], + "properties": { + "subjectLine": { + "type": "string", + "description": "The subject line of the email sent to the user." + }, + "content": { + "type": "string", + "description": "The content of the email sent to the user." + }, + "comment": { + "type": "string", + "description": "Additional comment about the outgoing comm." + } + } + }, + "modEventDivert": { + "type": "object", + "description": "Divert a record's blobs to a 3rd party service for further scanning/tagging", + "properties": { + "comment": { "type": "string" } + } + }, + "modEventTag": { + "type": "object", + "description": "Add/Remove a tag on a subject", + "required": ["add", "remove"], + "properties": { + "add": { + "type": "array", + "items": { "type": "string" }, + "description": "Tags to be added to the subject. If already exists, won't be duplicated." + }, + "remove": { + "type": "array", + "items": { "type": "string" }, + "description": "Tags to be removed to the subject. Ignores a tag If it doesn't exist, won't be duplicated." + }, + "comment": { + "type": "string", + "description": "Additional comment about added/removed tags." + } + } + }, + "repoView": { + "type": "object", + "required": [ + "did", + "handle", + "relatedRecords", + "indexedAt", + "moderation" + ], + "properties": { + "did": { "type": "string", "format": "did" }, + "handle": { "type": "string", "format": "handle" }, + "email": { "type": "string" }, + "relatedRecords": { "type": "array", "items": { "type": "unknown" } }, + "indexedAt": { "type": "string", "format": "datetime" }, + "moderation": { "type": "ref", "ref": "#moderation" }, + "invitedBy": { + "type": "ref", + "ref": "com.atproto.server.defs#inviteCode" + }, + "invitesDisabled": { "type": "boolean" }, + "inviteNote": { "type": "string" } + } + }, + "repoViewDetail": { + "type": "object", + "required": [ + "did", + "handle", + "relatedRecords", + "indexedAt", + "moderation" + ], + "properties": { + "did": { "type": "string", "format": "did" }, + "handle": { "type": "string", "format": "handle" }, + "email": { "type": "string" }, + "relatedRecords": { "type": "array", "items": { "type": "unknown" } }, + "indexedAt": { "type": "string", "format": "datetime" }, + "moderation": { "type": "ref", "ref": "#moderationDetail" }, + "labels": { + "type": "array", + "items": { "type": "ref", "ref": "com.atproto.label.defs#label" } + }, + "invitedBy": { + "type": "ref", + "ref": "com.atproto.server.defs#inviteCode" + }, + "invites": { + "type": "array", + "items": { + "type": "ref", + "ref": "com.atproto.server.defs#inviteCode" + } + }, + "invitesDisabled": { "type": "boolean" }, + "inviteNote": { "type": "string" }, + "emailConfirmedAt": { "type": "string", "format": "datetime" } + } + }, + "repoViewNotFound": { + "type": "object", + "required": ["did"], + "properties": { + "did": { "type": "string", "format": "did" } + } + }, + "recordView": { + "type": "object", + "required": [ + "uri", + "cid", + "value", + "blobCids", + "indexedAt", + "moderation", + "repo" + ], + "properties": { + "uri": { "type": "string", "format": "at-uri" }, + "cid": { "type": "string", "format": "cid" }, + "value": { "type": "unknown" }, + "blobCids": { + "type": "array", + "items": { "type": "string", "format": "cid" } + }, + "indexedAt": { "type": "string", "format": "datetime" }, + "moderation": { "type": "ref", "ref": "#moderation" }, + "repo": { "type": "ref", "ref": "#repoView" } + } + }, + "recordViewDetail": { + "type": "object", + "required": [ + "uri", + "cid", + "value", + "blobs", + "indexedAt", + "moderation", + "repo" + ], + "properties": { + "uri": { "type": "string", "format": "at-uri" }, + "cid": { "type": "string", "format": "cid" }, + "value": { "type": "unknown" }, + "blobs": { + "type": "array", + "items": { "type": "ref", "ref": "#blobView" } + }, + "labels": { + "type": "array", + "items": { "type": "ref", "ref": "com.atproto.label.defs#label" } + }, + "indexedAt": { "type": "string", "format": "datetime" }, + "moderation": { "type": "ref", "ref": "#moderationDetail" }, + "repo": { "type": "ref", "ref": "#repoView" } + } + }, + "recordViewNotFound": { + "type": "object", + "required": ["uri"], + "properties": { + "uri": { "type": "string", "format": "at-uri" } + } + }, + "moderation": { + "type": "object", + "properties": { + "subjectStatus": { "type": "ref", "ref": "#subjectStatusView" } + } + }, + "moderationDetail": { + "type": "object", + "properties": { + "subjectStatus": { + "type": "ref", + "ref": "#subjectStatusView" + } + } + }, + "blobView": { + "type": "object", + "required": ["cid", "mimeType", "size", "createdAt"], + "properties": { + "cid": { "type": "string", "format": "cid" }, + "mimeType": { "type": "string" }, + "size": { "type": "integer" }, + "createdAt": { "type": "string", "format": "datetime" }, + "details": { + "type": "union", + "refs": ["#imageDetails", "#videoDetails"] + }, + "moderation": { "type": "ref", "ref": "#moderation" } + } + }, + "imageDetails": { + "type": "object", + "required": ["width", "height"], + "properties": { + "width": { "type": "integer" }, + "height": { "type": "integer" } + } + }, + "videoDetails": { + "type": "object", + "required": ["width", "height", "length"], + "properties": { + "width": { "type": "integer" }, + "height": { "type": "integer" }, + "length": { "type": "integer" } + } + } + } +} diff --git a/lexicons/tools/ozone/moderation/emitEvent.json b/lexicons/tools/ozone/moderation/emitEvent.json new file mode 100644 index 00000000000..32c12065008 --- /dev/null +++ b/lexicons/tools/ozone/moderation/emitEvent.json @@ -0,0 +1,55 @@ +{ + "lexicon": 1, + "id": "tools.ozone.moderation.emitEvent", + "defs": { + "main": { + "type": "procedure", + "description": "Take a moderation action on an actor.", + "input": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["event", "subject", "createdBy"], + "properties": { + "event": { + "type": "union", + "refs": [ + "tools.ozone.moderation.defs#modEventTakedown", + "tools.ozone.moderation.defs#modEventAcknowledge", + "tools.ozone.moderation.defs#modEventEscalate", + "tools.ozone.moderation.defs#modEventComment", + "tools.ozone.moderation.defs#modEventLabel", + "tools.ozone.moderation.defs#modEventReport", + "tools.ozone.moderation.defs#modEventMute", + "tools.ozone.moderation.defs#modEventReverseTakedown", + "tools.ozone.moderation.defs#modEventUnmute", + "tools.ozone.moderation.defs#modEventEmail", + "tools.ozone.moderation.defs#modEventTag" + ] + }, + "subject": { + "type": "union", + "refs": [ + "com.atproto.admin.defs#repoRef", + "com.atproto.repo.strongRef" + ] + }, + "subjectBlobCids": { + "type": "array", + "items": { "type": "string", "format": "cid" } + }, + "createdBy": { "type": "string", "format": "did" } + } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "ref", + "ref": "tools.ozone.moderation.defs#modEventView" + } + }, + "errors": [{ "name": "SubjectHasAction" }] + } + } +} diff --git a/lexicons/tools/ozone/moderation/getEvent.json b/lexicons/tools/ozone/moderation/getEvent.json new file mode 100644 index 00000000000..66d7642eed2 --- /dev/null +++ b/lexicons/tools/ozone/moderation/getEvent.json @@ -0,0 +1,24 @@ +{ + "lexicon": 1, + "id": "tools.ozone.moderation.getEvent", + "defs": { + "main": { + "type": "query", + "description": "Get details about a moderation event.", + "parameters": { + "type": "params", + "required": ["id"], + "properties": { + "id": { "type": "integer" } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "ref", + "ref": "tools.ozone.moderation.defs#modEventViewDetail" + } + } + } + } +} diff --git a/lexicons/tools/ozone/moderation/getRecord.json b/lexicons/tools/ozone/moderation/getRecord.json new file mode 100644 index 00000000000..ca5c480691a --- /dev/null +++ b/lexicons/tools/ozone/moderation/getRecord.json @@ -0,0 +1,26 @@ +{ + "lexicon": 1, + "id": "tools.ozone.moderation.getRecord", + "defs": { + "main": { + "type": "query", + "description": "Get details about a record.", + "parameters": { + "type": "params", + "required": ["uri"], + "properties": { + "uri": { "type": "string", "format": "at-uri" }, + "cid": { "type": "string", "format": "cid" } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "ref", + "ref": "tools.ozone.moderation.defs#recordViewDetail" + } + }, + "errors": [{ "name": "RecordNotFound" }] + } + } +} diff --git a/lexicons/tools/ozone/moderation/getRepo.json b/lexicons/tools/ozone/moderation/getRepo.json new file mode 100644 index 00000000000..b5af1f07f5f --- /dev/null +++ b/lexicons/tools/ozone/moderation/getRepo.json @@ -0,0 +1,25 @@ +{ + "lexicon": 1, + "id": "tools.ozone.moderation.getRepo", + "defs": { + "main": { + "type": "query", + "description": "Get details about a repository.", + "parameters": { + "type": "params", + "required": ["did"], + "properties": { + "did": { "type": "string", "format": "did" } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "ref", + "ref": "tools.ozone.moderation.defs#repoViewDetail" + } + }, + "errors": [{ "name": "RepoNotFound" }] + } + } +} diff --git a/lexicons/tools/ozone/moderation/queryEvents.json b/lexicons/tools/ozone/moderation/queryEvents.json new file mode 100644 index 00000000000..619d400800c --- /dev/null +++ b/lexicons/tools/ozone/moderation/queryEvents.json @@ -0,0 +1,104 @@ +{ + "lexicon": 1, + "id": "tools.ozone.moderation.queryEvents", + "defs": { + "main": { + "type": "query", + "description": "List moderation events related to a subject.", + "parameters": { + "type": "params", + "properties": { + "types": { + "type": "array", + "items": { "type": "string" }, + "description": "The types of events (fully qualified string in the format of tools.ozone.moderation.defs#modEvent) to filter by. If not specified, all events are returned." + }, + "createdBy": { + "type": "string", + "format": "did" + }, + "sortDirection": { + "type": "string", + "default": "desc", + "enum": ["asc", "desc"], + "description": "Sort direction for the events. Defaults to descending order of created at timestamp." + }, + "createdAfter": { + "type": "string", + "format": "datetime", + "description": "Retrieve events created after a given timestamp" + }, + "createdBefore": { + "type": "string", + "format": "datetime", + "description": "Retrieve events created before a given timestamp" + }, + "subject": { "type": "string", "format": "uri" }, + "includeAllUserRecords": { + "type": "boolean", + "default": false, + "description": "If true, events on all record types (posts, lists, profile etc.) owned by the did are returned" + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 50 + }, + "hasComment": { + "type": "boolean", + "description": "If true, only events with comments are returned" + }, + "comment": { + "type": "string", + "description": "If specified, only events with comments containing the keyword are returned" + }, + "addedLabels": { + "type": "array", + "items": { "type": "string" }, + "description": "If specified, only events where all of these labels were added are returned" + }, + "removedLabels": { + "type": "array", + "items": { "type": "string" }, + "description": "If specified, only events where all of these labels were removed are returned" + }, + "addedTags": { + "type": "array", + "items": { "type": "string" }, + "description": "If specified, only events where all of these tags were added are returned" + }, + "removedTags": { + "type": "array", + "items": { "type": "string" }, + "description": "If specified, only events where all of these tags were removed are returned" + }, + "reportTypes": { + "type": "array", + "items": { + "type": "string" + } + }, + "cursor": { "type": "string" } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["events"], + "properties": { + "cursor": { "type": "string" }, + "events": { + "type": "array", + "items": { + "type": "ref", + "ref": "tools.ozone.moderation.defs#modEventView" + } + } + } + } + } + } + } +} diff --git a/lexicons/tools/ozone/moderation/queryStatuses.json b/lexicons/tools/ozone/moderation/queryStatuses.json new file mode 100644 index 00000000000..624ffbbb4ad --- /dev/null +++ b/lexicons/tools/ozone/moderation/queryStatuses.json @@ -0,0 +1,107 @@ +{ + "lexicon": 1, + "id": "tools.ozone.moderation.queryStatuses", + "defs": { + "main": { + "type": "query", + "description": "View moderation statuses of subjects (record or repo).", + "parameters": { + "type": "params", + "properties": { + "subject": { "type": "string", "format": "uri" }, + "comment": { + "type": "string", + "description": "Search subjects by keyword from comments" + }, + "reportedAfter": { + "type": "string", + "format": "datetime", + "description": "Search subjects reported after a given timestamp" + }, + "reportedBefore": { + "type": "string", + "format": "datetime", + "description": "Search subjects reported before a given timestamp" + }, + "reviewedAfter": { + "type": "string", + "format": "datetime", + "description": "Search subjects reviewed after a given timestamp" + }, + "reviewedBefore": { + "type": "string", + "format": "datetime", + "description": "Search subjects reviewed before a given timestamp" + }, + "includeMuted": { + "type": "boolean", + "description": "By default, we don't include muted subjects in the results. Set this to true to include them." + }, + "reviewState": { + "type": "string", + "description": "Specify when fetching subjects in a certain state" + }, + "ignoreSubjects": { + "type": "array", + "items": { "type": "string", "format": "uri" } + }, + "lastReviewedBy": { + "type": "string", + "format": "did", + "description": "Get all subject statuses that were reviewed by a specific moderator" + }, + "sortField": { + "type": "string", + "default": "lastReportedAt", + "enum": ["lastReviewedAt", "lastReportedAt"] + }, + "sortDirection": { + "type": "string", + "default": "desc", + "enum": ["asc", "desc"] + }, + "takendown": { + "type": "boolean", + "description": "Get subjects that were taken down" + }, + "appealed": { + "type": "boolean", + "description": "Get subjects in unresolved appealed status" + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 50 + }, + "tags": { + "type": "array", + "items": { "type": "string" } + }, + "excludeTags": { + "type": "array", + "items": { "type": "string" } + }, + "cursor": { "type": "string" } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["subjectStatuses"], + "properties": { + "cursor": { "type": "string" }, + "subjectStatuses": { + "type": "array", + "items": { + "type": "ref", + "ref": "tools.ozone.moderation.defs#subjectStatusView" + } + } + } + } + } + } + } +} diff --git a/lexicons/tools/ozone/moderation/searchRepos.json b/lexicons/tools/ozone/moderation/searchRepos.json new file mode 100644 index 00000000000..3968b340828 --- /dev/null +++ b/lexicons/tools/ozone/moderation/searchRepos.json @@ -0,0 +1,44 @@ +{ + "lexicon": 1, + "id": "tools.ozone.moderation.searchRepos", + "defs": { + "main": { + "type": "query", + "description": "Find repositories based on a search term.", + "parameters": { + "type": "params", + "properties": { + "term": { + "type": "string", + "description": "DEPRECATED: use 'q' instead" + }, + "q": { "type": "string" }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "default": 50 + }, + "cursor": { "type": "string" } + } + }, + "output": { + "encoding": "application/json", + "schema": { + "type": "object", + "required": ["repos"], + "properties": { + "cursor": { "type": "string" }, + "repos": { + "type": "array", + "items": { + "type": "ref", + "ref": "tools.ozone.moderation.defs#repoView" + } + } + } + } + } + } + } +} diff --git a/packages/api/package.json b/packages/api/package.json index 9bf7c547b19..1b51d60ee35 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -20,7 +20,7 @@ "types": "dist/index.d.ts" }, "scripts": { - "codegen": "pnpm docgen && node ./scripts/generate-code.mjs && lex gen-api ./src/client ../../lexicons/com/atproto/*/* ../../lexicons/app/bsky/*/*", + "codegen": "pnpm docgen && node ./scripts/generate-code.mjs && lex gen-api ./src/client ../../lexicons/com/atproto/*/* ../../lexicons/app/bsky/*/* ../../lexicons/tools/ozone/*/*", "docgen": "node ./scripts/generate-docs.mjs", "build": "node ./build.js", "postbuild": "tsc --build tsconfig.build.json", diff --git a/packages/api/src/client/index.ts b/packages/api/src/client/index.ts index ac0f0be432f..90beb5f6bcf 100644 --- a/packages/api/src/client/index.ts +++ b/packages/api/src/client/index.ts @@ -159,6 +159,19 @@ import * as AppBskyUnspeccedGetTaggedSuggestions from './types/app/bsky/unspecce import * as AppBskyUnspeccedGetTimelineSkeleton from './types/app/bsky/unspecced/getTimelineSkeleton' import * as AppBskyUnspeccedSearchActorsSkeleton from './types/app/bsky/unspecced/searchActorsSkeleton' import * as AppBskyUnspeccedSearchPostsSkeleton from './types/app/bsky/unspecced/searchPostsSkeleton' +import * as ToolsOzoneCommunicationCreateTemplate from './types/tools/ozone/communication/createTemplate' +import * as ToolsOzoneCommunicationDefs from './types/tools/ozone/communication/defs' +import * as ToolsOzoneCommunicationDeleteTemplate from './types/tools/ozone/communication/deleteTemplate' +import * as ToolsOzoneCommunicationListTemplates from './types/tools/ozone/communication/listTemplates' +import * as ToolsOzoneCommunicationUpdateTemplate from './types/tools/ozone/communication/updateTemplate' +import * as ToolsOzoneModerationDefs from './types/tools/ozone/moderation/defs' +import * as ToolsOzoneModerationEmitEvent from './types/tools/ozone/moderation/emitEvent' +import * as ToolsOzoneModerationGetEvent from './types/tools/ozone/moderation/getEvent' +import * as ToolsOzoneModerationGetRecord from './types/tools/ozone/moderation/getRecord' +import * as ToolsOzoneModerationGetRepo from './types/tools/ozone/moderation/getRepo' +import * as ToolsOzoneModerationQueryEvents from './types/tools/ozone/moderation/queryEvents' +import * as ToolsOzoneModerationQueryStatuses from './types/tools/ozone/moderation/queryStatuses' +import * as ToolsOzoneModerationSearchRepos from './types/tools/ozone/moderation/searchRepos' export * as ComAtprotoAdminCreateCommunicationTemplate from './types/com/atproto/admin/createCommunicationTemplate' export * as ComAtprotoAdminDefs from './types/com/atproto/admin/defs' @@ -312,6 +325,19 @@ export * as AppBskyUnspeccedGetTaggedSuggestions from './types/app/bsky/unspecce export * as AppBskyUnspeccedGetTimelineSkeleton from './types/app/bsky/unspecced/getTimelineSkeleton' export * as AppBskyUnspeccedSearchActorsSkeleton from './types/app/bsky/unspecced/searchActorsSkeleton' export * as AppBskyUnspeccedSearchPostsSkeleton from './types/app/bsky/unspecced/searchPostsSkeleton' +export * as ToolsOzoneCommunicationCreateTemplate from './types/tools/ozone/communication/createTemplate' +export * as ToolsOzoneCommunicationDefs from './types/tools/ozone/communication/defs' +export * as ToolsOzoneCommunicationDeleteTemplate from './types/tools/ozone/communication/deleteTemplate' +export * as ToolsOzoneCommunicationListTemplates from './types/tools/ozone/communication/listTemplates' +export * as ToolsOzoneCommunicationUpdateTemplate from './types/tools/ozone/communication/updateTemplate' +export * as ToolsOzoneModerationDefs from './types/tools/ozone/moderation/defs' +export * as ToolsOzoneModerationEmitEvent from './types/tools/ozone/moderation/emitEvent' +export * as ToolsOzoneModerationGetEvent from './types/tools/ozone/moderation/getEvent' +export * as ToolsOzoneModerationGetRecord from './types/tools/ozone/moderation/getRecord' +export * as ToolsOzoneModerationGetRepo from './types/tools/ozone/moderation/getRepo' +export * as ToolsOzoneModerationQueryEvents from './types/tools/ozone/moderation/queryEvents' +export * as ToolsOzoneModerationQueryStatuses from './types/tools/ozone/moderation/queryStatuses' +export * as ToolsOzoneModerationSearchRepos from './types/tools/ozone/moderation/searchRepos' export const COM_ATPROTO_ADMIN = { DefsReviewOpen: 'com.atproto.admin.defs#reviewOpen', @@ -331,6 +357,12 @@ export const APP_BSKY_GRAPH = { DefsModlist: 'app.bsky.graph.defs#modlist', DefsCuratelist: 'app.bsky.graph.defs#curatelist', } +export const TOOLS_OZONE_MODERATION = { + DefsReviewOpen: 'tools.ozone.moderation.defs#reviewOpen', + DefsReviewEscalated: 'tools.ozone.moderation.defs#reviewEscalated', + DefsReviewClosed: 'tools.ozone.moderation.defs#reviewClosed', + DefsReviewNone: 'tools.ozone.moderation.defs#reviewNone', +} export class AtpBaseClient { xrpc: XrpcClient = new XrpcClient() @@ -349,12 +381,14 @@ export class AtpServiceClient { xrpc: XrpcServiceClient com: ComNS app: AppNS + tools: ToolsNS constructor(baseClient: AtpBaseClient, xrpcService: XrpcServiceClient) { this._baseClient = baseClient this.xrpc = xrpcService this.com = new ComNS(this) this.app = new AppNS(this) + this.tools = new ToolsNS(this) } setHeader(key: string, value: string): void { @@ -2663,3 +2697,162 @@ export class AppBskyUnspeccedNS { }) } } + +export class ToolsNS { + _service: AtpServiceClient + ozone: ToolsOzoneNS + + constructor(service: AtpServiceClient) { + this._service = service + this.ozone = new ToolsOzoneNS(service) + } +} + +export class ToolsOzoneNS { + _service: AtpServiceClient + communication: ToolsOzoneCommunicationNS + moderation: ToolsOzoneModerationNS + + constructor(service: AtpServiceClient) { + this._service = service + this.communication = new ToolsOzoneCommunicationNS(service) + this.moderation = new ToolsOzoneModerationNS(service) + } +} + +export class ToolsOzoneCommunicationNS { + _service: AtpServiceClient + + constructor(service: AtpServiceClient) { + this._service = service + } + + createTemplate( + data?: ToolsOzoneCommunicationCreateTemplate.InputSchema, + opts?: ToolsOzoneCommunicationCreateTemplate.CallOptions, + ): Promise { + return this._service.xrpc + .call('tools.ozone.communication.createTemplate', opts?.qp, data, opts) + .catch((e) => { + throw ToolsOzoneCommunicationCreateTemplate.toKnownErr(e) + }) + } + + deleteTemplate( + data?: ToolsOzoneCommunicationDeleteTemplate.InputSchema, + opts?: ToolsOzoneCommunicationDeleteTemplate.CallOptions, + ): Promise { + return this._service.xrpc + .call('tools.ozone.communication.deleteTemplate', opts?.qp, data, opts) + .catch((e) => { + throw ToolsOzoneCommunicationDeleteTemplate.toKnownErr(e) + }) + } + + listTemplates( + params?: ToolsOzoneCommunicationListTemplates.QueryParams, + opts?: ToolsOzoneCommunicationListTemplates.CallOptions, + ): Promise { + return this._service.xrpc + .call('tools.ozone.communication.listTemplates', params, undefined, opts) + .catch((e) => { + throw ToolsOzoneCommunicationListTemplates.toKnownErr(e) + }) + } + + updateTemplate( + data?: ToolsOzoneCommunicationUpdateTemplate.InputSchema, + opts?: ToolsOzoneCommunicationUpdateTemplate.CallOptions, + ): Promise { + return this._service.xrpc + .call('tools.ozone.communication.updateTemplate', opts?.qp, data, opts) + .catch((e) => { + throw ToolsOzoneCommunicationUpdateTemplate.toKnownErr(e) + }) + } +} + +export class ToolsOzoneModerationNS { + _service: AtpServiceClient + + constructor(service: AtpServiceClient) { + this._service = service + } + + emitEvent( + data?: ToolsOzoneModerationEmitEvent.InputSchema, + opts?: ToolsOzoneModerationEmitEvent.CallOptions, + ): Promise { + return this._service.xrpc + .call('tools.ozone.moderation.emitEvent', opts?.qp, data, opts) + .catch((e) => { + throw ToolsOzoneModerationEmitEvent.toKnownErr(e) + }) + } + + getEvent( + params?: ToolsOzoneModerationGetEvent.QueryParams, + opts?: ToolsOzoneModerationGetEvent.CallOptions, + ): Promise { + return this._service.xrpc + .call('tools.ozone.moderation.getEvent', params, undefined, opts) + .catch((e) => { + throw ToolsOzoneModerationGetEvent.toKnownErr(e) + }) + } + + getRecord( + params?: ToolsOzoneModerationGetRecord.QueryParams, + opts?: ToolsOzoneModerationGetRecord.CallOptions, + ): Promise { + return this._service.xrpc + .call('tools.ozone.moderation.getRecord', params, undefined, opts) + .catch((e) => { + throw ToolsOzoneModerationGetRecord.toKnownErr(e) + }) + } + + getRepo( + params?: ToolsOzoneModerationGetRepo.QueryParams, + opts?: ToolsOzoneModerationGetRepo.CallOptions, + ): Promise { + return this._service.xrpc + .call('tools.ozone.moderation.getRepo', params, undefined, opts) + .catch((e) => { + throw ToolsOzoneModerationGetRepo.toKnownErr(e) + }) + } + + queryEvents( + params?: ToolsOzoneModerationQueryEvents.QueryParams, + opts?: ToolsOzoneModerationQueryEvents.CallOptions, + ): Promise { + return this._service.xrpc + .call('tools.ozone.moderation.queryEvents', params, undefined, opts) + .catch((e) => { + throw ToolsOzoneModerationQueryEvents.toKnownErr(e) + }) + } + + queryStatuses( + params?: ToolsOzoneModerationQueryStatuses.QueryParams, + opts?: ToolsOzoneModerationQueryStatuses.CallOptions, + ): Promise { + return this._service.xrpc + .call('tools.ozone.moderation.queryStatuses', params, undefined, opts) + .catch((e) => { + throw ToolsOzoneModerationQueryStatuses.toKnownErr(e) + }) + } + + searchRepos( + params?: ToolsOzoneModerationSearchRepos.QueryParams, + opts?: ToolsOzoneModerationSearchRepos.CallOptions, + ): Promise { + return this._service.xrpc + .call('tools.ozone.moderation.searchRepos', params, undefined, opts) + .catch((e) => { + throw ToolsOzoneModerationSearchRepos.toKnownErr(e) + }) + } +} diff --git a/packages/api/src/client/lexicons.ts b/packages/api/src/client/lexicons.ts index 06beebc7916..c092e98dd58 100644 --- a/packages/api/src/client/lexicons.ts +++ b/packages/api/src/client/lexicons.ts @@ -8786,6 +8786,1383 @@ export const schemaDict = { }, }, }, + ToolsOzoneCommunicationCreateTemplate: { + lexicon: 1, + id: 'tools.ozone.communication.createTemplate', + defs: { + main: { + type: 'procedure', + description: + 'Administrative action to create a new, re-usable communication (email for now) template.', + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['subject', 'contentMarkdown', 'name'], + properties: { + name: { + type: 'string', + description: 'Name of the template.', + }, + contentMarkdown: { + type: 'string', + description: + 'Content of the template, markdown supported, can contain variable placeholders.', + }, + subject: { + type: 'string', + description: 'Subject of the message, used in emails.', + }, + createdBy: { + type: 'string', + format: 'did', + description: 'DID of the user who is creating the template.', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:tools.ozone.communication.defs#templateView', + }, + }, + }, + }, + }, + ToolsOzoneCommunicationDefs: { + lexicon: 1, + id: 'tools.ozone.communication.defs', + defs: { + templateView: { + type: 'object', + required: [ + 'id', + 'name', + 'contentMarkdown', + 'disabled', + 'lastUpdatedBy', + 'createdAt', + 'updatedAt', + ], + properties: { + id: { + type: 'string', + }, + name: { + type: 'string', + description: 'Name of the template.', + }, + subject: { + type: 'string', + description: + 'Content of the template, can contain markdown and variable placeholders.', + }, + contentMarkdown: { + type: 'string', + description: 'Subject of the message, used in emails.', + }, + disabled: { + type: 'boolean', + }, + lastUpdatedBy: { + type: 'string', + format: 'did', + description: 'DID of the user who last updated the template.', + }, + createdAt: { + type: 'string', + format: 'datetime', + }, + updatedAt: { + type: 'string', + format: 'datetime', + }, + }, + }, + }, + }, + ToolsOzoneCommunicationDeleteTemplate: { + lexicon: 1, + id: 'tools.ozone.communication.deleteTemplate', + defs: { + main: { + type: 'procedure', + description: 'Delete a communication template.', + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['id'], + properties: { + id: { + type: 'string', + }, + }, + }, + }, + }, + }, + }, + ToolsOzoneCommunicationListTemplates: { + lexicon: 1, + id: 'tools.ozone.communication.listTemplates', + defs: { + main: { + type: 'query', + description: 'Get list of all communication templates.', + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['communicationTemplates'], + properties: { + communicationTemplates: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:tools.ozone.communication.defs#templateView', + }, + }, + }, + }, + }, + }, + }, + }, + ToolsOzoneCommunicationUpdateTemplate: { + lexicon: 1, + id: 'tools.ozone.communication.updateTemplate', + defs: { + main: { + type: 'procedure', + description: + 'Administrative action to update an existing communication template. Allows passing partial fields to patch specific fields only.', + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['id'], + properties: { + id: { + type: 'string', + description: 'ID of the template to be updated.', + }, + name: { + type: 'string', + description: 'Name of the template.', + }, + contentMarkdown: { + type: 'string', + description: + 'Content of the template, markdown supported, can contain variable placeholders.', + }, + subject: { + type: 'string', + description: 'Subject of the message, used in emails.', + }, + updatedBy: { + type: 'string', + format: 'did', + description: 'DID of the user who is updating the template.', + }, + disabled: { + type: 'boolean', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:tools.ozone.communication.defs#templateView', + }, + }, + }, + }, + }, + ToolsOzoneModerationDefs: { + lexicon: 1, + id: 'tools.ozone.moderation.defs', + defs: { + modEventView: { + type: 'object', + required: [ + 'id', + 'event', + 'subject', + 'subjectBlobCids', + 'createdBy', + 'createdAt', + ], + properties: { + id: { + type: 'integer', + }, + event: { + type: 'union', + refs: [ + 'lex:tools.ozone.moderation.defs#modEventTakedown', + 'lex:tools.ozone.moderation.defs#modEventReverseTakedown', + 'lex:tools.ozone.moderation.defs#modEventComment', + 'lex:tools.ozone.moderation.defs#modEventReport', + 'lex:tools.ozone.moderation.defs#modEventLabel', + 'lex:tools.ozone.moderation.defs#modEventAcknowledge', + 'lex:tools.ozone.moderation.defs#modEventEscalate', + 'lex:tools.ozone.moderation.defs#modEventMute', + 'lex:tools.ozone.moderation.defs#modEventEmail', + 'lex:tools.ozone.moderation.defs#modEventResolveAppeal', + 'lex:tools.ozone.moderation.defs#modEventDivert', + ], + }, + subject: { + type: 'union', + refs: [ + 'lex:com.atproto.admin.defs#repoRef', + 'lex:com.atproto.repo.strongRef', + ], + }, + subjectBlobCids: { + type: 'array', + items: { + type: 'string', + }, + }, + createdBy: { + type: 'string', + format: 'did', + }, + createdAt: { + type: 'string', + format: 'datetime', + }, + creatorHandle: { + type: 'string', + }, + subjectHandle: { + type: 'string', + }, + }, + }, + modEventViewDetail: { + type: 'object', + required: [ + 'id', + 'event', + 'subject', + 'subjectBlobs', + 'createdBy', + 'createdAt', + ], + properties: { + id: { + type: 'integer', + }, + event: { + type: 'union', + refs: [ + 'lex:tools.ozone.moderation.defs#modEventTakedown', + 'lex:tools.ozone.moderation.defs#modEventReverseTakedown', + 'lex:tools.ozone.moderation.defs#modEventComment', + 'lex:tools.ozone.moderation.defs#modEventReport', + 'lex:tools.ozone.moderation.defs#modEventLabel', + 'lex:tools.ozone.moderation.defs#modEventAcknowledge', + 'lex:tools.ozone.moderation.defs#modEventEscalate', + 'lex:tools.ozone.moderation.defs#modEventMute', + 'lex:tools.ozone.moderation.defs#modEventEmail', + 'lex:tools.ozone.moderation.defs#modEventResolveAppeal', + 'lex:tools.ozone.moderation.defs#modEventDivert', + ], + }, + subject: { + type: 'union', + refs: [ + 'lex:tools.ozone.moderation.defs#repoView', + 'lex:tools.ozone.moderation.defs#repoViewNotFound', + 'lex:tools.ozone.moderation.defs#recordView', + 'lex:tools.ozone.moderation.defs#recordViewNotFound', + ], + }, + subjectBlobs: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#blobView', + }, + }, + createdBy: { + type: 'string', + format: 'did', + }, + createdAt: { + type: 'string', + format: 'datetime', + }, + }, + }, + subjectStatusView: { + type: 'object', + required: ['id', 'subject', 'createdAt', 'updatedAt', 'reviewState'], + properties: { + id: { + type: 'integer', + }, + subject: { + type: 'union', + refs: [ + 'lex:com.atproto.admin.defs#repoRef', + 'lex:com.atproto.repo.strongRef', + ], + }, + subjectBlobCids: { + type: 'array', + items: { + type: 'string', + format: 'cid', + }, + }, + subjectRepoHandle: { + type: 'string', + }, + updatedAt: { + type: 'string', + format: 'datetime', + description: + 'Timestamp referencing when the last update was made to the moderation status of the subject', + }, + createdAt: { + type: 'string', + format: 'datetime', + description: + 'Timestamp referencing the first moderation status impacting event was emitted on the subject', + }, + reviewState: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#subjectReviewState', + }, + comment: { + type: 'string', + description: 'Sticky comment on the subject.', + }, + muteUntil: { + type: 'string', + format: 'datetime', + }, + lastReviewedBy: { + type: 'string', + format: 'did', + }, + lastReviewedAt: { + type: 'string', + format: 'datetime', + }, + lastReportedAt: { + type: 'string', + format: 'datetime', + }, + lastAppealedAt: { + type: 'string', + format: 'datetime', + description: + 'Timestamp referencing when the author of the subject appealed a moderation action', + }, + takendown: { + type: 'boolean', + }, + appealed: { + type: 'boolean', + description: + 'True indicates that the a previously taken moderator action was appealed against, by the author of the content. False indicates last appeal was resolved by moderators.', + }, + suspendUntil: { + type: 'string', + format: 'datetime', + }, + tags: { + type: 'array', + items: { + type: 'string', + }, + }, + }, + }, + subjectReviewState: { + type: 'string', + knownValues: [ + 'lex:tools.ozone.moderation.defs#reviewOpen', + 'lex:tools.ozone.moderation.defs#reviewEscalated', + 'lex:tools.ozone.moderation.defs#reviewClosed', + 'lex:tools.ozone.moderation.defs#reviewNone', + ], + }, + reviewOpen: { + type: 'token', + description: + 'Moderator review status of a subject: Open. Indicates that the subject needs to be reviewed by a moderator', + }, + reviewEscalated: { + type: 'token', + description: + 'Moderator review status of a subject: Escalated. Indicates that the subject was escalated for review by a moderator', + }, + reviewClosed: { + type: 'token', + description: + 'Moderator review status of a subject: Closed. Indicates that the subject was already reviewed and resolved by a moderator', + }, + reviewNone: { + type: 'token', + description: + 'Moderator review status of a subject: Unnecessary. Indicates that the subject does not need a review at the moment but there is probably some moderation related metadata available for it', + }, + modEventTakedown: { + type: 'object', + description: 'Take down a subject permanently or temporarily', + properties: { + comment: { + type: 'string', + }, + durationInHours: { + type: 'integer', + description: + 'Indicates how long the takedown should be in effect before automatically expiring.', + }, + }, + }, + modEventReverseTakedown: { + type: 'object', + description: 'Revert take down action on a subject', + properties: { + comment: { + type: 'string', + description: 'Describe reasoning behind the reversal.', + }, + }, + }, + modEventResolveAppeal: { + type: 'object', + description: 'Resolve appeal on a subject', + properties: { + comment: { + type: 'string', + description: 'Describe resolution.', + }, + }, + }, + modEventComment: { + type: 'object', + description: 'Add a comment to a subject', + required: ['comment'], + properties: { + comment: { + type: 'string', + }, + sticky: { + type: 'boolean', + description: 'Make the comment persistent on the subject', + }, + }, + }, + modEventReport: { + type: 'object', + description: 'Report a subject', + required: ['reportType'], + properties: { + comment: { + type: 'string', + }, + reportType: { + type: 'ref', + ref: 'lex:com.atproto.moderation.defs#reasonType', + }, + }, + }, + modEventLabel: { + type: 'object', + description: 'Apply/Negate labels on a subject', + required: ['createLabelVals', 'negateLabelVals'], + properties: { + comment: { + type: 'string', + }, + createLabelVals: { + type: 'array', + items: { + type: 'string', + }, + }, + negateLabelVals: { + type: 'array', + items: { + type: 'string', + }, + }, + }, + }, + modEventAcknowledge: { + type: 'object', + properties: { + comment: { + type: 'string', + }, + }, + }, + modEventEscalate: { + type: 'object', + properties: { + comment: { + type: 'string', + }, + }, + }, + modEventMute: { + type: 'object', + description: 'Mute incoming reports on a subject', + required: ['durationInHours'], + properties: { + comment: { + type: 'string', + }, + durationInHours: { + type: 'integer', + description: 'Indicates how long the subject should remain muted.', + }, + }, + }, + modEventUnmute: { + type: 'object', + description: 'Unmute action on a subject', + properties: { + comment: { + type: 'string', + description: 'Describe reasoning behind the reversal.', + }, + }, + }, + modEventEmail: { + type: 'object', + description: 'Keep a log of outgoing email to a user', + required: ['subjectLine'], + properties: { + subjectLine: { + type: 'string', + description: 'The subject line of the email sent to the user.', + }, + content: { + type: 'string', + description: 'The content of the email sent to the user.', + }, + comment: { + type: 'string', + description: 'Additional comment about the outgoing comm.', + }, + }, + }, + modEventDivert: { + type: 'object', + description: + "Divert a record's blobs to a 3rd party service for further scanning/tagging", + properties: { + comment: { + type: 'string', + }, + }, + }, + modEventTag: { + type: 'object', + description: 'Add/Remove a tag on a subject', + required: ['add', 'remove'], + properties: { + add: { + type: 'array', + items: { + type: 'string', + }, + description: + "Tags to be added to the subject. If already exists, won't be duplicated.", + }, + remove: { + type: 'array', + items: { + type: 'string', + }, + description: + "Tags to be removed to the subject. Ignores a tag If it doesn't exist, won't be duplicated.", + }, + comment: { + type: 'string', + description: 'Additional comment about added/removed tags.', + }, + }, + }, + repoView: { + type: 'object', + required: [ + 'did', + 'handle', + 'relatedRecords', + 'indexedAt', + 'moderation', + ], + properties: { + did: { + type: 'string', + format: 'did', + }, + handle: { + type: 'string', + format: 'handle', + }, + email: { + type: 'string', + }, + relatedRecords: { + type: 'array', + items: { + type: 'unknown', + }, + }, + indexedAt: { + type: 'string', + format: 'datetime', + }, + moderation: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#moderation', + }, + invitedBy: { + type: 'ref', + ref: 'lex:com.atproto.server.defs#inviteCode', + }, + invitesDisabled: { + type: 'boolean', + }, + inviteNote: { + type: 'string', + }, + }, + }, + repoViewDetail: { + type: 'object', + required: [ + 'did', + 'handle', + 'relatedRecords', + 'indexedAt', + 'moderation', + ], + properties: { + did: { + type: 'string', + format: 'did', + }, + handle: { + type: 'string', + format: 'handle', + }, + email: { + type: 'string', + }, + relatedRecords: { + type: 'array', + items: { + type: 'unknown', + }, + }, + indexedAt: { + type: 'string', + format: 'datetime', + }, + moderation: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#moderationDetail', + }, + labels: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:com.atproto.label.defs#label', + }, + }, + invitedBy: { + type: 'ref', + ref: 'lex:com.atproto.server.defs#inviteCode', + }, + invites: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:com.atproto.server.defs#inviteCode', + }, + }, + invitesDisabled: { + type: 'boolean', + }, + inviteNote: { + type: 'string', + }, + emailConfirmedAt: { + type: 'string', + format: 'datetime', + }, + }, + }, + repoViewNotFound: { + type: 'object', + required: ['did'], + properties: { + did: { + type: 'string', + format: 'did', + }, + }, + }, + recordView: { + type: 'object', + required: [ + 'uri', + 'cid', + 'value', + 'blobCids', + 'indexedAt', + 'moderation', + 'repo', + ], + properties: { + uri: { + type: 'string', + format: 'at-uri', + }, + cid: { + type: 'string', + format: 'cid', + }, + value: { + type: 'unknown', + }, + blobCids: { + type: 'array', + items: { + type: 'string', + format: 'cid', + }, + }, + indexedAt: { + type: 'string', + format: 'datetime', + }, + moderation: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#moderation', + }, + repo: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#repoView', + }, + }, + }, + recordViewDetail: { + type: 'object', + required: [ + 'uri', + 'cid', + 'value', + 'blobs', + 'indexedAt', + 'moderation', + 'repo', + ], + properties: { + uri: { + type: 'string', + format: 'at-uri', + }, + cid: { + type: 'string', + format: 'cid', + }, + value: { + type: 'unknown', + }, + blobs: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#blobView', + }, + }, + labels: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:com.atproto.label.defs#label', + }, + }, + indexedAt: { + type: 'string', + format: 'datetime', + }, + moderation: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#moderationDetail', + }, + repo: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#repoView', + }, + }, + }, + recordViewNotFound: { + type: 'object', + required: ['uri'], + properties: { + uri: { + type: 'string', + format: 'at-uri', + }, + }, + }, + moderation: { + type: 'object', + properties: { + subjectStatus: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#subjectStatusView', + }, + }, + }, + moderationDetail: { + type: 'object', + properties: { + subjectStatus: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#subjectStatusView', + }, + }, + }, + blobView: { + type: 'object', + required: ['cid', 'mimeType', 'size', 'createdAt'], + properties: { + cid: { + type: 'string', + format: 'cid', + }, + mimeType: { + type: 'string', + }, + size: { + type: 'integer', + }, + createdAt: { + type: 'string', + format: 'datetime', + }, + details: { + type: 'union', + refs: [ + 'lex:tools.ozone.moderation.defs#imageDetails', + 'lex:tools.ozone.moderation.defs#videoDetails', + ], + }, + moderation: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#moderation', + }, + }, + }, + imageDetails: { + type: 'object', + required: ['width', 'height'], + properties: { + width: { + type: 'integer', + }, + height: { + type: 'integer', + }, + }, + }, + videoDetails: { + type: 'object', + required: ['width', 'height', 'length'], + properties: { + width: { + type: 'integer', + }, + height: { + type: 'integer', + }, + length: { + type: 'integer', + }, + }, + }, + }, + }, + ToolsOzoneModerationEmitEvent: { + lexicon: 1, + id: 'tools.ozone.moderation.emitEvent', + defs: { + main: { + type: 'procedure', + description: 'Take a moderation action on an actor.', + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['event', 'subject', 'createdBy'], + properties: { + event: { + type: 'union', + refs: [ + 'lex:tools.ozone.moderation.defs#modEventTakedown', + 'lex:tools.ozone.moderation.defs#modEventAcknowledge', + 'lex:tools.ozone.moderation.defs#modEventEscalate', + 'lex:tools.ozone.moderation.defs#modEventComment', + 'lex:tools.ozone.moderation.defs#modEventLabel', + 'lex:tools.ozone.moderation.defs#modEventReport', + 'lex:tools.ozone.moderation.defs#modEventMute', + 'lex:tools.ozone.moderation.defs#modEventReverseTakedown', + 'lex:tools.ozone.moderation.defs#modEventUnmute', + 'lex:tools.ozone.moderation.defs#modEventEmail', + 'lex:tools.ozone.moderation.defs#modEventTag', + ], + }, + subject: { + type: 'union', + refs: [ + 'lex:com.atproto.admin.defs#repoRef', + 'lex:com.atproto.repo.strongRef', + ], + }, + subjectBlobCids: { + type: 'array', + items: { + type: 'string', + format: 'cid', + }, + }, + createdBy: { + type: 'string', + format: 'did', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#modEventView', + }, + }, + errors: [ + { + name: 'SubjectHasAction', + }, + ], + }, + }, + }, + ToolsOzoneModerationGetEvent: { + lexicon: 1, + id: 'tools.ozone.moderation.getEvent', + defs: { + main: { + type: 'query', + description: 'Get details about a moderation event.', + parameters: { + type: 'params', + required: ['id'], + properties: { + id: { + type: 'integer', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#modEventViewDetail', + }, + }, + }, + }, + }, + ToolsOzoneModerationGetRecord: { + lexicon: 1, + id: 'tools.ozone.moderation.getRecord', + defs: { + main: { + type: 'query', + description: 'Get details about a record.', + parameters: { + type: 'params', + required: ['uri'], + properties: { + uri: { + type: 'string', + format: 'at-uri', + }, + cid: { + type: 'string', + format: 'cid', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#recordViewDetail', + }, + }, + errors: [ + { + name: 'RecordNotFound', + }, + ], + }, + }, + }, + ToolsOzoneModerationGetRepo: { + lexicon: 1, + id: 'tools.ozone.moderation.getRepo', + defs: { + main: { + type: 'query', + description: 'Get details about a repository.', + parameters: { + type: 'params', + required: ['did'], + properties: { + did: { + type: 'string', + format: 'did', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#repoViewDetail', + }, + }, + errors: [ + { + name: 'RepoNotFound', + }, + ], + }, + }, + }, + ToolsOzoneModerationQueryEvents: { + lexicon: 1, + id: 'tools.ozone.moderation.queryEvents', + defs: { + main: { + type: 'query', + description: 'List moderation events related to a subject.', + parameters: { + type: 'params', + properties: { + types: { + type: 'array', + items: { + type: 'string', + }, + description: + 'The types of events (fully qualified string in the format of tools.ozone.moderation.defs#modEvent) to filter by. If not specified, all events are returned.', + }, + createdBy: { + type: 'string', + format: 'did', + }, + sortDirection: { + type: 'string', + default: 'desc', + enum: ['asc', 'desc'], + description: + 'Sort direction for the events. Defaults to descending order of created at timestamp.', + }, + createdAfter: { + type: 'string', + format: 'datetime', + description: 'Retrieve events created after a given timestamp', + }, + createdBefore: { + type: 'string', + format: 'datetime', + description: 'Retrieve events created before a given timestamp', + }, + subject: { + type: 'string', + format: 'uri', + }, + includeAllUserRecords: { + type: 'boolean', + default: false, + description: + 'If true, events on all record types (posts, lists, profile etc.) owned by the did are returned', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + hasComment: { + type: 'boolean', + description: 'If true, only events with comments are returned', + }, + comment: { + type: 'string', + description: + 'If specified, only events with comments containing the keyword are returned', + }, + addedLabels: { + type: 'array', + items: { + type: 'string', + }, + description: + 'If specified, only events where all of these labels were added are returned', + }, + removedLabels: { + type: 'array', + items: { + type: 'string', + }, + description: + 'If specified, only events where all of these labels were removed are returned', + }, + addedTags: { + type: 'array', + items: { + type: 'string', + }, + description: + 'If specified, only events where all of these tags were added are returned', + }, + removedTags: { + type: 'array', + items: { + type: 'string', + }, + description: + 'If specified, only events where all of these tags were removed are returned', + }, + reportTypes: { + type: 'array', + items: { + type: 'string', + }, + }, + cursor: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['events'], + properties: { + cursor: { + type: 'string', + }, + events: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#modEventView', + }, + }, + }, + }, + }, + }, + }, + }, + ToolsOzoneModerationQueryStatuses: { + lexicon: 1, + id: 'tools.ozone.moderation.queryStatuses', + defs: { + main: { + type: 'query', + description: 'View moderation statuses of subjects (record or repo).', + parameters: { + type: 'params', + properties: { + subject: { + type: 'string', + format: 'uri', + }, + comment: { + type: 'string', + description: 'Search subjects by keyword from comments', + }, + reportedAfter: { + type: 'string', + format: 'datetime', + description: 'Search subjects reported after a given timestamp', + }, + reportedBefore: { + type: 'string', + format: 'datetime', + description: 'Search subjects reported before a given timestamp', + }, + reviewedAfter: { + type: 'string', + format: 'datetime', + description: 'Search subjects reviewed after a given timestamp', + }, + reviewedBefore: { + type: 'string', + format: 'datetime', + description: 'Search subjects reviewed before a given timestamp', + }, + includeMuted: { + type: 'boolean', + description: + "By default, we don't include muted subjects in the results. Set this to true to include them.", + }, + reviewState: { + type: 'string', + description: 'Specify when fetching subjects in a certain state', + }, + ignoreSubjects: { + type: 'array', + items: { + type: 'string', + format: 'uri', + }, + }, + lastReviewedBy: { + type: 'string', + format: 'did', + description: + 'Get all subject statuses that were reviewed by a specific moderator', + }, + sortField: { + type: 'string', + default: 'lastReportedAt', + enum: ['lastReviewedAt', 'lastReportedAt'], + }, + sortDirection: { + type: 'string', + default: 'desc', + enum: ['asc', 'desc'], + }, + takendown: { + type: 'boolean', + description: 'Get subjects that were taken down', + }, + appealed: { + type: 'boolean', + description: 'Get subjects in unresolved appealed status', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + tags: { + type: 'array', + items: { + type: 'string', + }, + }, + excludeTags: { + type: 'array', + items: { + type: 'string', + }, + }, + cursor: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['subjectStatuses'], + properties: { + cursor: { + type: 'string', + }, + subjectStatuses: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#subjectStatusView', + }, + }, + }, + }, + }, + }, + }, + }, + ToolsOzoneModerationSearchRepos: { + lexicon: 1, + id: 'tools.ozone.moderation.searchRepos', + defs: { + main: { + type: 'query', + description: 'Find repositories based on a search term.', + parameters: { + type: 'params', + properties: { + term: { + type: 'string', + description: "DEPRECATED: use 'q' instead", + }, + q: { + type: 'string', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + cursor: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['repos'], + properties: { + cursor: { + type: 'string', + }, + repos: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#repoView', + }, + }, + }, + }, + }, + }, + }, + }, } export const schemas: LexiconDoc[] = Object.values(schemaDict) as LexiconDoc[] export const lexicons: Lexicons = new Lexicons(schemas) @@ -8960,4 +10337,21 @@ export const ids = { AppBskyUnspeccedSearchActorsSkeleton: 'app.bsky.unspecced.searchActorsSkeleton', AppBskyUnspeccedSearchPostsSkeleton: 'app.bsky.unspecced.searchPostsSkeleton', + ToolsOzoneCommunicationCreateTemplate: + 'tools.ozone.communication.createTemplate', + ToolsOzoneCommunicationDefs: 'tools.ozone.communication.defs', + ToolsOzoneCommunicationDeleteTemplate: + 'tools.ozone.communication.deleteTemplate', + ToolsOzoneCommunicationListTemplates: + 'tools.ozone.communication.listTemplates', + ToolsOzoneCommunicationUpdateTemplate: + 'tools.ozone.communication.updateTemplate', + ToolsOzoneModerationDefs: 'tools.ozone.moderation.defs', + ToolsOzoneModerationEmitEvent: 'tools.ozone.moderation.emitEvent', + ToolsOzoneModerationGetEvent: 'tools.ozone.moderation.getEvent', + ToolsOzoneModerationGetRecord: 'tools.ozone.moderation.getRecord', + ToolsOzoneModerationGetRepo: 'tools.ozone.moderation.getRepo', + ToolsOzoneModerationQueryEvents: 'tools.ozone.moderation.queryEvents', + ToolsOzoneModerationQueryStatuses: 'tools.ozone.moderation.queryStatuses', + ToolsOzoneModerationSearchRepos: 'tools.ozone.moderation.searchRepos', } diff --git a/packages/api/src/client/types/tools/ozone/communication/createTemplate.ts b/packages/api/src/client/types/tools/ozone/communication/createTemplate.ts new file mode 100644 index 00000000000..0aba76123c6 --- /dev/null +++ b/packages/api/src/client/types/tools/ozone/communication/createTemplate.ts @@ -0,0 +1,43 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { Headers, XRPCError } from '@atproto/xrpc' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' +import * as ToolsOzoneCommunicationDefs from './defs' + +export interface QueryParams {} + +export interface InputSchema { + /** Name of the template. */ + name: string + /** Content of the template, markdown supported, can contain variable placeholders. */ + contentMarkdown: string + /** Subject of the message, used in emails. */ + subject: string + /** DID of the user who is creating the template. */ + createdBy?: string + [k: string]: unknown +} + +export type OutputSchema = ToolsOzoneCommunicationDefs.TemplateView + +export interface CallOptions { + headers?: Headers + qp?: QueryParams + encoding: 'application/json' +} + +export interface Response { + success: boolean + headers: Headers + data: OutputSchema +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + } + return e +} diff --git a/packages/api/src/client/types/tools/ozone/communication/defs.ts b/packages/api/src/client/types/tools/ozone/communication/defs.ts new file mode 100644 index 00000000000..9384d63664d --- /dev/null +++ b/packages/api/src/client/types/tools/ozone/communication/defs.ts @@ -0,0 +1,35 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' + +export interface TemplateView { + id: string + /** Name of the template. */ + name: string + /** Content of the template, can contain markdown and variable placeholders. */ + subject?: string + /** Subject of the message, used in emails. */ + contentMarkdown: string + disabled: boolean + /** DID of the user who last updated the template. */ + lastUpdatedBy: string + createdAt: string + updatedAt: string + [k: string]: unknown +} + +export function isTemplateView(v: unknown): v is TemplateView { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.communication.defs#templateView' + ) +} + +export function validateTemplateView(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.communication.defs#templateView', v) +} diff --git a/packages/api/src/client/types/tools/ozone/communication/deleteTemplate.ts b/packages/api/src/client/types/tools/ozone/communication/deleteTemplate.ts new file mode 100644 index 00000000000..a5c4d55fdeb --- /dev/null +++ b/packages/api/src/client/types/tools/ozone/communication/deleteTemplate.ts @@ -0,0 +1,32 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { Headers, XRPCError } from '@atproto/xrpc' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' + +export interface QueryParams {} + +export interface InputSchema { + id: string + [k: string]: unknown +} + +export interface CallOptions { + headers?: Headers + qp?: QueryParams + encoding: 'application/json' +} + +export interface Response { + success: boolean + headers: Headers +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + } + return e +} diff --git a/packages/api/src/client/types/tools/ozone/communication/listTemplates.ts b/packages/api/src/client/types/tools/ozone/communication/listTemplates.ts new file mode 100644 index 00000000000..116f79f1c9c --- /dev/null +++ b/packages/api/src/client/types/tools/ozone/communication/listTemplates.ts @@ -0,0 +1,34 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { Headers, XRPCError } from '@atproto/xrpc' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' +import * as ToolsOzoneCommunicationDefs from './defs' + +export interface QueryParams {} + +export type InputSchema = undefined + +export interface OutputSchema { + communicationTemplates: ToolsOzoneCommunicationDefs.TemplateView[] + [k: string]: unknown +} + +export interface CallOptions { + headers?: Headers +} + +export interface Response { + success: boolean + headers: Headers + data: OutputSchema +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + } + return e +} diff --git a/packages/api/src/client/types/tools/ozone/communication/updateTemplate.ts b/packages/api/src/client/types/tools/ozone/communication/updateTemplate.ts new file mode 100644 index 00000000000..2f39d9e9b32 --- /dev/null +++ b/packages/api/src/client/types/tools/ozone/communication/updateTemplate.ts @@ -0,0 +1,46 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { Headers, XRPCError } from '@atproto/xrpc' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' +import * as ToolsOzoneCommunicationDefs from './defs' + +export interface QueryParams {} + +export interface InputSchema { + /** ID of the template to be updated. */ + id: string + /** Name of the template. */ + name?: string + /** Content of the template, markdown supported, can contain variable placeholders. */ + contentMarkdown?: string + /** Subject of the message, used in emails. */ + subject?: string + /** DID of the user who is updating the template. */ + updatedBy?: string + disabled?: boolean + [k: string]: unknown +} + +export type OutputSchema = ToolsOzoneCommunicationDefs.TemplateView + +export interface CallOptions { + headers?: Headers + qp?: QueryParams + encoding: 'application/json' +} + +export interface Response { + success: boolean + headers: Headers + data: OutputSchema +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + } + return e +} diff --git a/packages/api/src/client/types/tools/ozone/moderation/defs.ts b/packages/api/src/client/types/tools/ozone/moderation/defs.ts new file mode 100644 index 00000000000..f6f546b6bef --- /dev/null +++ b/packages/api/src/client/types/tools/ozone/moderation/defs.ts @@ -0,0 +1,641 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' +import * as ComAtprotoAdminDefs from '../../../com/atproto/admin/defs' +import * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef' +import * as ComAtprotoModerationDefs from '../../../com/atproto/moderation/defs' +import * as ComAtprotoServerDefs from '../../../com/atproto/server/defs' +import * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs' + +export interface ModEventView { + id: number + event: + | ModEventTakedown + | ModEventReverseTakedown + | ModEventComment + | ModEventReport + | ModEventLabel + | ModEventAcknowledge + | ModEventEscalate + | ModEventMute + | ModEventEmail + | ModEventResolveAppeal + | ModEventDivert + | { $type: string; [k: string]: unknown } + subject: + | ComAtprotoAdminDefs.RepoRef + | ComAtprotoRepoStrongRef.Main + | { $type: string; [k: string]: unknown } + subjectBlobCids: string[] + createdBy: string + createdAt: string + creatorHandle?: string + subjectHandle?: string + [k: string]: unknown +} + +export function isModEventView(v: unknown): v is ModEventView { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventView' + ) +} + +export function validateModEventView(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventView', v) +} + +export interface ModEventViewDetail { + id: number + event: + | ModEventTakedown + | ModEventReverseTakedown + | ModEventComment + | ModEventReport + | ModEventLabel + | ModEventAcknowledge + | ModEventEscalate + | ModEventMute + | ModEventEmail + | ModEventResolveAppeal + | ModEventDivert + | { $type: string; [k: string]: unknown } + subject: + | RepoView + | RepoViewNotFound + | RecordView + | RecordViewNotFound + | { $type: string; [k: string]: unknown } + subjectBlobs: BlobView[] + createdBy: string + createdAt: string + [k: string]: unknown +} + +export function isModEventViewDetail(v: unknown): v is ModEventViewDetail { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventViewDetail' + ) +} + +export function validateModEventViewDetail(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventViewDetail', v) +} + +export interface SubjectStatusView { + id: number + subject: + | ComAtprotoAdminDefs.RepoRef + | ComAtprotoRepoStrongRef.Main + | { $type: string; [k: string]: unknown } + subjectBlobCids?: string[] + subjectRepoHandle?: string + /** Timestamp referencing when the last update was made to the moderation status of the subject */ + updatedAt: string + /** Timestamp referencing the first moderation status impacting event was emitted on the subject */ + createdAt: string + reviewState: SubjectReviewState + /** Sticky comment on the subject. */ + comment?: string + muteUntil?: string + lastReviewedBy?: string + lastReviewedAt?: string + lastReportedAt?: string + /** Timestamp referencing when the author of the subject appealed a moderation action */ + lastAppealedAt?: string + takendown?: boolean + /** True indicates that the a previously taken moderator action was appealed against, by the author of the content. False indicates last appeal was resolved by moderators. */ + appealed?: boolean + suspendUntil?: string + tags?: string[] + [k: string]: unknown +} + +export function isSubjectStatusView(v: unknown): v is SubjectStatusView { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#subjectStatusView' + ) +} + +export function validateSubjectStatusView(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#subjectStatusView', v) +} + +export type SubjectReviewState = + | 'lex:tools.ozone.moderation.defs#reviewOpen' + | 'lex:tools.ozone.moderation.defs#reviewEscalated' + | 'lex:tools.ozone.moderation.defs#reviewClosed' + | 'lex:tools.ozone.moderation.defs#reviewNone' + | (string & {}) + +/** Moderator review status of a subject: Open. Indicates that the subject needs to be reviewed by a moderator */ +export const REVIEWOPEN = 'tools.ozone.moderation.defs#reviewOpen' +/** Moderator review status of a subject: Escalated. Indicates that the subject was escalated for review by a moderator */ +export const REVIEWESCALATED = 'tools.ozone.moderation.defs#reviewEscalated' +/** Moderator review status of a subject: Closed. Indicates that the subject was already reviewed and resolved by a moderator */ +export const REVIEWCLOSED = 'tools.ozone.moderation.defs#reviewClosed' +/** Moderator review status of a subject: Unnecessary. Indicates that the subject does not need a review at the moment but there is probably some moderation related metadata available for it */ +export const REVIEWNONE = 'tools.ozone.moderation.defs#reviewNone' + +/** Take down a subject permanently or temporarily */ +export interface ModEventTakedown { + comment?: string + /** Indicates how long the takedown should be in effect before automatically expiring. */ + durationInHours?: number + [k: string]: unknown +} + +export function isModEventTakedown(v: unknown): v is ModEventTakedown { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventTakedown' + ) +} + +export function validateModEventTakedown(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventTakedown', v) +} + +/** Revert take down action on a subject */ +export interface ModEventReverseTakedown { + /** Describe reasoning behind the reversal. */ + comment?: string + [k: string]: unknown +} + +export function isModEventReverseTakedown( + v: unknown, +): v is ModEventReverseTakedown { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventReverseTakedown' + ) +} + +export function validateModEventReverseTakedown(v: unknown): ValidationResult { + return lexicons.validate( + 'tools.ozone.moderation.defs#modEventReverseTakedown', + v, + ) +} + +/** Resolve appeal on a subject */ +export interface ModEventResolveAppeal { + /** Describe resolution. */ + comment?: string + [k: string]: unknown +} + +export function isModEventResolveAppeal( + v: unknown, +): v is ModEventResolveAppeal { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventResolveAppeal' + ) +} + +export function validateModEventResolveAppeal(v: unknown): ValidationResult { + return lexicons.validate( + 'tools.ozone.moderation.defs#modEventResolveAppeal', + v, + ) +} + +/** Add a comment to a subject */ +export interface ModEventComment { + comment: string + /** Make the comment persistent on the subject */ + sticky?: boolean + [k: string]: unknown +} + +export function isModEventComment(v: unknown): v is ModEventComment { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventComment' + ) +} + +export function validateModEventComment(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventComment', v) +} + +/** Report a subject */ +export interface ModEventReport { + comment?: string + reportType: ComAtprotoModerationDefs.ReasonType + [k: string]: unknown +} + +export function isModEventReport(v: unknown): v is ModEventReport { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventReport' + ) +} + +export function validateModEventReport(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventReport', v) +} + +/** Apply/Negate labels on a subject */ +export interface ModEventLabel { + comment?: string + createLabelVals: string[] + negateLabelVals: string[] + [k: string]: unknown +} + +export function isModEventLabel(v: unknown): v is ModEventLabel { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventLabel' + ) +} + +export function validateModEventLabel(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventLabel', v) +} + +export interface ModEventAcknowledge { + comment?: string + [k: string]: unknown +} + +export function isModEventAcknowledge(v: unknown): v is ModEventAcknowledge { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventAcknowledge' + ) +} + +export function validateModEventAcknowledge(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventAcknowledge', v) +} + +export interface ModEventEscalate { + comment?: string + [k: string]: unknown +} + +export function isModEventEscalate(v: unknown): v is ModEventEscalate { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventEscalate' + ) +} + +export function validateModEventEscalate(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventEscalate', v) +} + +/** Mute incoming reports on a subject */ +export interface ModEventMute { + comment?: string + /** Indicates how long the subject should remain muted. */ + durationInHours: number + [k: string]: unknown +} + +export function isModEventMute(v: unknown): v is ModEventMute { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventMute' + ) +} + +export function validateModEventMute(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventMute', v) +} + +/** Unmute action on a subject */ +export interface ModEventUnmute { + /** Describe reasoning behind the reversal. */ + comment?: string + [k: string]: unknown +} + +export function isModEventUnmute(v: unknown): v is ModEventUnmute { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventUnmute' + ) +} + +export function validateModEventUnmute(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventUnmute', v) +} + +/** Keep a log of outgoing email to a user */ +export interface ModEventEmail { + /** The subject line of the email sent to the user. */ + subjectLine: string + /** The content of the email sent to the user. */ + content?: string + /** Additional comment about the outgoing comm. */ + comment?: string + [k: string]: unknown +} + +export function isModEventEmail(v: unknown): v is ModEventEmail { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventEmail' + ) +} + +export function validateModEventEmail(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventEmail', v) +} + +/** Divert a record's blobs to a 3rd party service for further scanning/tagging */ +export interface ModEventDivert { + comment?: string + [k: string]: unknown +} + +export function isModEventDivert(v: unknown): v is ModEventDivert { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventDivert' + ) +} + +export function validateModEventDivert(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventDivert', v) +} + +/** Add/Remove a tag on a subject */ +export interface ModEventTag { + /** Tags to be added to the subject. If already exists, won't be duplicated. */ + add: string[] + /** Tags to be removed to the subject. Ignores a tag If it doesn't exist, won't be duplicated. */ + remove: string[] + /** Additional comment about added/removed tags. */ + comment?: string + [k: string]: unknown +} + +export function isModEventTag(v: unknown): v is ModEventTag { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventTag' + ) +} + +export function validateModEventTag(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventTag', v) +} + +export interface RepoView { + did: string + handle: string + email?: string + relatedRecords: {}[] + indexedAt: string + moderation: Moderation + invitedBy?: ComAtprotoServerDefs.InviteCode + invitesDisabled?: boolean + inviteNote?: string + [k: string]: unknown +} + +export function isRepoView(v: unknown): v is RepoView { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#repoView' + ) +} + +export function validateRepoView(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#repoView', v) +} + +export interface RepoViewDetail { + did: string + handle: string + email?: string + relatedRecords: {}[] + indexedAt: string + moderation: ModerationDetail + labels?: ComAtprotoLabelDefs.Label[] + invitedBy?: ComAtprotoServerDefs.InviteCode + invites?: ComAtprotoServerDefs.InviteCode[] + invitesDisabled?: boolean + inviteNote?: string + emailConfirmedAt?: string + [k: string]: unknown +} + +export function isRepoViewDetail(v: unknown): v is RepoViewDetail { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#repoViewDetail' + ) +} + +export function validateRepoViewDetail(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#repoViewDetail', v) +} + +export interface RepoViewNotFound { + did: string + [k: string]: unknown +} + +export function isRepoViewNotFound(v: unknown): v is RepoViewNotFound { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#repoViewNotFound' + ) +} + +export function validateRepoViewNotFound(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#repoViewNotFound', v) +} + +export interface RecordView { + uri: string + cid: string + value: {} + blobCids: string[] + indexedAt: string + moderation: Moderation + repo: RepoView + [k: string]: unknown +} + +export function isRecordView(v: unknown): v is RecordView { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#recordView' + ) +} + +export function validateRecordView(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#recordView', v) +} + +export interface RecordViewDetail { + uri: string + cid: string + value: {} + blobs: BlobView[] + labels?: ComAtprotoLabelDefs.Label[] + indexedAt: string + moderation: ModerationDetail + repo: RepoView + [k: string]: unknown +} + +export function isRecordViewDetail(v: unknown): v is RecordViewDetail { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#recordViewDetail' + ) +} + +export function validateRecordViewDetail(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#recordViewDetail', v) +} + +export interface RecordViewNotFound { + uri: string + [k: string]: unknown +} + +export function isRecordViewNotFound(v: unknown): v is RecordViewNotFound { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#recordViewNotFound' + ) +} + +export function validateRecordViewNotFound(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#recordViewNotFound', v) +} + +export interface Moderation { + subjectStatus?: SubjectStatusView + [k: string]: unknown +} + +export function isModeration(v: unknown): v is Moderation { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#moderation' + ) +} + +export function validateModeration(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#moderation', v) +} + +export interface ModerationDetail { + subjectStatus?: SubjectStatusView + [k: string]: unknown +} + +export function isModerationDetail(v: unknown): v is ModerationDetail { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#moderationDetail' + ) +} + +export function validateModerationDetail(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#moderationDetail', v) +} + +export interface BlobView { + cid: string + mimeType: string + size: number + createdAt: string + details?: + | ImageDetails + | VideoDetails + | { $type: string; [k: string]: unknown } + moderation?: Moderation + [k: string]: unknown +} + +export function isBlobView(v: unknown): v is BlobView { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#blobView' + ) +} + +export function validateBlobView(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#blobView', v) +} + +export interface ImageDetails { + width: number + height: number + [k: string]: unknown +} + +export function isImageDetails(v: unknown): v is ImageDetails { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#imageDetails' + ) +} + +export function validateImageDetails(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#imageDetails', v) +} + +export interface VideoDetails { + width: number + height: number + length: number + [k: string]: unknown +} + +export function isVideoDetails(v: unknown): v is VideoDetails { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#videoDetails' + ) +} + +export function validateVideoDetails(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#videoDetails', v) +} diff --git a/packages/api/src/client/types/tools/ozone/moderation/emitEvent.ts b/packages/api/src/client/types/tools/ozone/moderation/emitEvent.ts new file mode 100644 index 00000000000..49ad72d208c --- /dev/null +++ b/packages/api/src/client/types/tools/ozone/moderation/emitEvent.ts @@ -0,0 +1,63 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { Headers, XRPCError } from '@atproto/xrpc' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' +import * as ToolsOzoneModerationDefs from './defs' +import * as ComAtprotoAdminDefs from '../../../com/atproto/admin/defs' +import * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef' + +export interface QueryParams {} + +export interface InputSchema { + event: + | ToolsOzoneModerationDefs.ModEventTakedown + | ToolsOzoneModerationDefs.ModEventAcknowledge + | ToolsOzoneModerationDefs.ModEventEscalate + | ToolsOzoneModerationDefs.ModEventComment + | ToolsOzoneModerationDefs.ModEventLabel + | ToolsOzoneModerationDefs.ModEventReport + | ToolsOzoneModerationDefs.ModEventMute + | ToolsOzoneModerationDefs.ModEventReverseTakedown + | ToolsOzoneModerationDefs.ModEventUnmute + | ToolsOzoneModerationDefs.ModEventEmail + | ToolsOzoneModerationDefs.ModEventTag + | { $type: string; [k: string]: unknown } + subject: + | ComAtprotoAdminDefs.RepoRef + | ComAtprotoRepoStrongRef.Main + | { $type: string; [k: string]: unknown } + subjectBlobCids?: string[] + createdBy: string + [k: string]: unknown +} + +export type OutputSchema = ToolsOzoneModerationDefs.ModEventView + +export interface CallOptions { + headers?: Headers + qp?: QueryParams + encoding: 'application/json' +} + +export interface Response { + success: boolean + headers: Headers + data: OutputSchema +} + +export class SubjectHasActionError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'SubjectHasAction') return new SubjectHasActionError(e) + } + return e +} diff --git a/packages/api/src/client/types/tools/ozone/moderation/getEvent.ts b/packages/api/src/client/types/tools/ozone/moderation/getEvent.ts new file mode 100644 index 00000000000..fef7068170e --- /dev/null +++ b/packages/api/src/client/types/tools/ozone/moderation/getEvent.ts @@ -0,0 +1,32 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { Headers, XRPCError } from '@atproto/xrpc' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' +import * as ToolsOzoneModerationDefs from './defs' + +export interface QueryParams { + id: number +} + +export type InputSchema = undefined +export type OutputSchema = ToolsOzoneModerationDefs.ModEventViewDetail + +export interface CallOptions { + headers?: Headers +} + +export interface Response { + success: boolean + headers: Headers + data: OutputSchema +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + } + return e +} diff --git a/packages/api/src/client/types/tools/ozone/moderation/getRecord.ts b/packages/api/src/client/types/tools/ozone/moderation/getRecord.ts new file mode 100644 index 00000000000..9a1168033c5 --- /dev/null +++ b/packages/api/src/client/types/tools/ozone/moderation/getRecord.ts @@ -0,0 +1,40 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { Headers, XRPCError } from '@atproto/xrpc' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' +import * as ToolsOzoneModerationDefs from './defs' + +export interface QueryParams { + uri: string + cid?: string +} + +export type InputSchema = undefined +export type OutputSchema = ToolsOzoneModerationDefs.RecordViewDetail + +export interface CallOptions { + headers?: Headers +} + +export interface Response { + success: boolean + headers: Headers + data: OutputSchema +} + +export class RecordNotFoundError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'RecordNotFound') return new RecordNotFoundError(e) + } + return e +} diff --git a/packages/api/src/client/types/tools/ozone/moderation/getRepo.ts b/packages/api/src/client/types/tools/ozone/moderation/getRepo.ts new file mode 100644 index 00000000000..6df65f90aa7 --- /dev/null +++ b/packages/api/src/client/types/tools/ozone/moderation/getRepo.ts @@ -0,0 +1,39 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { Headers, XRPCError } from '@atproto/xrpc' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' +import * as ToolsOzoneModerationDefs from './defs' + +export interface QueryParams { + did: string +} + +export type InputSchema = undefined +export type OutputSchema = ToolsOzoneModerationDefs.RepoViewDetail + +export interface CallOptions { + headers?: Headers +} + +export interface Response { + success: boolean + headers: Headers + data: OutputSchema +} + +export class RepoNotFoundError extends XRPCError { + constructor(src: XRPCError) { + super(src.status, src.error, src.message, src.headers) + } +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + if (e.error === 'RepoNotFound') return new RepoNotFoundError(e) + } + return e +} diff --git a/packages/api/src/client/types/tools/ozone/moderation/queryEvents.ts b/packages/api/src/client/types/tools/ozone/moderation/queryEvents.ts new file mode 100644 index 00000000000..268c570e607 --- /dev/null +++ b/packages/api/src/client/types/tools/ozone/moderation/queryEvents.ts @@ -0,0 +1,63 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { Headers, XRPCError } from '@atproto/xrpc' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' +import * as ToolsOzoneModerationDefs from './defs' + +export interface QueryParams { + /** The types of events (fully qualified string in the format of tools.ozone.moderation.defs#modEvent) to filter by. If not specified, all events are returned. */ + types?: string[] + createdBy?: string + /** Sort direction for the events. Defaults to descending order of created at timestamp. */ + sortDirection?: 'asc' | 'desc' + /** Retrieve events created after a given timestamp */ + createdAfter?: string + /** Retrieve events created before a given timestamp */ + createdBefore?: string + subject?: string + /** If true, events on all record types (posts, lists, profile etc.) owned by the did are returned */ + includeAllUserRecords?: boolean + limit?: number + /** If true, only events with comments are returned */ + hasComment?: boolean + /** If specified, only events with comments containing the keyword are returned */ + comment?: string + /** If specified, only events where all of these labels were added are returned */ + addedLabels?: string[] + /** If specified, only events where all of these labels were removed are returned */ + removedLabels?: string[] + /** If specified, only events where all of these tags were added are returned */ + addedTags?: string[] + /** If specified, only events where all of these tags were removed are returned */ + removedTags?: string[] + reportTypes?: string[] + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + events: ToolsOzoneModerationDefs.ModEventView[] + [k: string]: unknown +} + +export interface CallOptions { + headers?: Headers +} + +export interface Response { + success: boolean + headers: Headers + data: OutputSchema +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + } + return e +} diff --git a/packages/api/src/client/types/tools/ozone/moderation/queryStatuses.ts b/packages/api/src/client/types/tools/ozone/moderation/queryStatuses.ts new file mode 100644 index 00000000000..55701ca94d4 --- /dev/null +++ b/packages/api/src/client/types/tools/ozone/moderation/queryStatuses.ts @@ -0,0 +1,64 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { Headers, XRPCError } from '@atproto/xrpc' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' +import * as ToolsOzoneModerationDefs from './defs' + +export interface QueryParams { + subject?: string + /** Search subjects by keyword from comments */ + comment?: string + /** Search subjects reported after a given timestamp */ + reportedAfter?: string + /** Search subjects reported before a given timestamp */ + reportedBefore?: string + /** Search subjects reviewed after a given timestamp */ + reviewedAfter?: string + /** Search subjects reviewed before a given timestamp */ + reviewedBefore?: string + /** By default, we don't include muted subjects in the results. Set this to true to include them. */ + includeMuted?: boolean + /** Specify when fetching subjects in a certain state */ + reviewState?: string + ignoreSubjects?: string[] + /** Get all subject statuses that were reviewed by a specific moderator */ + lastReviewedBy?: string + sortField?: 'lastReviewedAt' | 'lastReportedAt' + sortDirection?: 'asc' | 'desc' + /** Get subjects that were taken down */ + takendown?: boolean + /** Get subjects in unresolved appealed status */ + appealed?: boolean + limit?: number + tags?: string[] + excludeTags?: string[] + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + subjectStatuses: ToolsOzoneModerationDefs.SubjectStatusView[] + [k: string]: unknown +} + +export interface CallOptions { + headers?: Headers +} + +export interface Response { + success: boolean + headers: Headers + data: OutputSchema +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + } + return e +} diff --git a/packages/api/src/client/types/tools/ozone/moderation/searchRepos.ts b/packages/api/src/client/types/tools/ozone/moderation/searchRepos.ts new file mode 100644 index 00000000000..3d56a3876b0 --- /dev/null +++ b/packages/api/src/client/types/tools/ozone/moderation/searchRepos.ts @@ -0,0 +1,41 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { Headers, XRPCError } from '@atproto/xrpc' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { isObj, hasProp } from '../../../../util' +import { lexicons } from '../../../../lexicons' +import { CID } from 'multiformats/cid' +import * as ToolsOzoneModerationDefs from './defs' + +export interface QueryParams { + /** DEPRECATED: use 'q' instead */ + term?: string + q?: string + limit?: number + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + repos: ToolsOzoneModerationDefs.RepoView[] + [k: string]: unknown +} + +export interface CallOptions { + headers?: Headers +} + +export interface Response { + success: boolean + headers: Headers + data: OutputSchema +} + +export function toKnownErr(e: any) { + if (e instanceof XRPCError) { + } + return e +} diff --git a/packages/pds/package.json b/packages/pds/package.json index 146efc228d5..5b38780f864 100644 --- a/packages/pds/package.json +++ b/packages/pds/package.json @@ -20,7 +20,7 @@ }, "bin": "dist/bin.js", "scripts": { - "codegen": "lex gen-server ./src/lexicon ../../lexicons/com/atproto/*/* ../../lexicons/app/bsky/*/*", + "codegen": "lex gen-server ./src/lexicon ../../lexicons/com/atproto/*/* ../../lexicons/app/bsky/*/* ../../lexicons/tools/ozone/*/*", "build": "node ./build.js", "postbuild": "tsc --build tsconfig.build.json", "test": "../dev-infra/with-test-redis-and-db.sh jest", diff --git a/packages/pds/src/api/index.ts b/packages/pds/src/api/index.ts index f0d08cd559e..3d1b54a51e4 100644 --- a/packages/pds/src/api/index.ts +++ b/packages/pds/src/api/index.ts @@ -1,10 +1,12 @@ import { Server } from '../lexicon' import comAtproto from './com/atproto' import appBsky from './app/bsky' +import toolsOzone from './tools/ozone' import AppContext from '../context' export default function (server: Server, ctx: AppContext) { comAtproto(server, ctx) appBsky(server, ctx) + toolsOzone(server, ctx) return server } diff --git a/packages/pds/src/api/tools/ozone/communication/createTemplate.ts b/packages/pds/src/api/tools/ozone/communication/createTemplate.ts new file mode 100644 index 00000000000..0e060ca16a9 --- /dev/null +++ b/packages/pds/src/api/tools/ozone/communication/createTemplate.ts @@ -0,0 +1,20 @@ +import { Server } from '../../../../lexicon' +import AppContext from '../../../../context' +import { authPassthru } from '../../../proxy' + +export default function (server: Server, ctx: AppContext) { + server.tools.ozone.communication.createTemplate({ + auth: ctx.authVerifier.role, + handler: async ({ req, input }) => { + const { data: result } = + await ctx.moderationAgent.api.tools.ozone.communication.createTemplate( + input.body, + authPassthru(req, true), + ) + return { + encoding: 'application/json', + body: result, + } + }, + }) +} diff --git a/packages/pds/src/api/tools/ozone/communication/deleteTemplate.ts b/packages/pds/src/api/tools/ozone/communication/deleteTemplate.ts new file mode 100644 index 00000000000..3f5495953a2 --- /dev/null +++ b/packages/pds/src/api/tools/ozone/communication/deleteTemplate.ts @@ -0,0 +1,15 @@ +import { Server } from '../../../../lexicon' +import AppContext from '../../../../context' +import { authPassthru } from '../../../proxy' + +export default function (server: Server, ctx: AppContext) { + server.tools.ozone.communication.deleteTemplate({ + auth: ctx.authVerifier.role, + handler: async ({ req, input }) => { + await ctx.moderationAgent.api.tools.ozone.communication.deleteTemplate( + input.body, + authPassthru(req, true), + ) + }, + }) +} diff --git a/packages/pds/src/api/tools/ozone/communication/index.ts b/packages/pds/src/api/tools/ozone/communication/index.ts new file mode 100644 index 00000000000..2e7279248dd --- /dev/null +++ b/packages/pds/src/api/tools/ozone/communication/index.ts @@ -0,0 +1,13 @@ +import AppContext from '../../../../context' +import { Server } from '../../../../lexicon' +import createTemplate from './createTemplate' +import deleteTemplate from './deleteTemplate' +import listTemplates from './listTemplates' +import updateTemplate from './updateTemplate' + +export default function (server: Server, ctx: AppContext) { + createTemplate(server, ctx) + deleteTemplate(server, ctx) + listTemplates(server, ctx) + updateTemplate(server, ctx) +} diff --git a/packages/pds/src/api/tools/ozone/communication/listTemplates.ts b/packages/pds/src/api/tools/ozone/communication/listTemplates.ts new file mode 100644 index 00000000000..b17169c5eb8 --- /dev/null +++ b/packages/pds/src/api/tools/ozone/communication/listTemplates.ts @@ -0,0 +1,20 @@ +import { Server } from '../../../../lexicon' +import AppContext from '../../../../context' +import { authPassthru } from '../../../proxy' + +export default function (server: Server, ctx: AppContext) { + server.tools.ozone.communication.listTemplates({ + auth: ctx.authVerifier.role, + handler: async ({ req }) => { + const { data: result } = + await ctx.moderationAgent.api.tools.ozone.communication.listTemplates( + {}, + authPassthru(req, true), + ) + return { + encoding: 'application/json', + body: result, + } + }, + }) +} diff --git a/packages/pds/src/api/tools/ozone/communication/updateTemplate.ts b/packages/pds/src/api/tools/ozone/communication/updateTemplate.ts new file mode 100644 index 00000000000..7a0c62e4f9f --- /dev/null +++ b/packages/pds/src/api/tools/ozone/communication/updateTemplate.ts @@ -0,0 +1,20 @@ +import { Server } from '../../../../lexicon' +import AppContext from '../../../../context' +import { authPassthru } from '../../../proxy' + +export default function (server: Server, ctx: AppContext) { + server.tools.ozone.communication.updateTemplate({ + auth: ctx.authVerifier.role, + handler: async ({ req, input }) => { + const { data: result } = + await ctx.moderationAgent.api.tools.ozone.communication.updateTemplate( + input.body, + authPassthru(req, true), + ) + return { + encoding: 'application/json', + body: result, + } + }, + }) +} diff --git a/packages/pds/src/api/tools/ozone/index.ts b/packages/pds/src/api/tools/ozone/index.ts new file mode 100644 index 00000000000..99ba163e298 --- /dev/null +++ b/packages/pds/src/api/tools/ozone/index.ts @@ -0,0 +1,9 @@ +import AppContext from '../../../context' +import { Server } from '../../../lexicon' +import communication from './communication' +import moderation from './moderation' + +export default function (server: Server, ctx: AppContext) { + communication(server, ctx) + moderation(server, ctx) +} diff --git a/packages/pds/src/api/tools/ozone/moderation/emitEvent.ts b/packages/pds/src/api/tools/ozone/moderation/emitEvent.ts new file mode 100644 index 00000000000..700c798786b --- /dev/null +++ b/packages/pds/src/api/tools/ozone/moderation/emitEvent.ts @@ -0,0 +1,20 @@ +import { Server } from '../../../../lexicon' +import AppContext from '../../../../context' +import { authPassthru } from '../../../proxy' + +export default function (server: Server, ctx: AppContext) { + server.tools.ozone.moderation.emitEvent({ + auth: ctx.authVerifier.role, + handler: async ({ req, input }) => { + const { data: result } = + await ctx.moderationAgent.api.tools.ozone.moderation.emitEvent( + input.body, + authPassthru(req, true), + ) + return { + encoding: 'application/json', + body: result, + } + }, + }) +} diff --git a/packages/pds/src/api/tools/ozone/moderation/getEvent.ts b/packages/pds/src/api/tools/ozone/moderation/getEvent.ts new file mode 100644 index 00000000000..9fb4fc6f453 --- /dev/null +++ b/packages/pds/src/api/tools/ozone/moderation/getEvent.ts @@ -0,0 +1,20 @@ +import { Server } from '../../../../lexicon' +import AppContext from '../../../../context' +import { authPassthru } from '../../../proxy' + +export default function (server: Server, ctx: AppContext) { + server.tools.ozone.moderation.getEvent({ + auth: ctx.authVerifier.role, + handler: async ({ req, params }) => { + const { data } = + await ctx.moderationAgent.api.tools.ozone.moderation.getEvent( + params, + authPassthru(req), + ) + return { + encoding: 'application/json', + body: data, + } + }, + }) +} diff --git a/packages/pds/src/api/tools/ozone/moderation/getRecord.ts b/packages/pds/src/api/tools/ozone/moderation/getRecord.ts new file mode 100644 index 00000000000..10ae7f2a86a --- /dev/null +++ b/packages/pds/src/api/tools/ozone/moderation/getRecord.ts @@ -0,0 +1,20 @@ +import { Server } from '../../../../lexicon' +import AppContext from '../../../../context' +import { authPassthru } from '../../../proxy' + +export default function (server: Server, ctx: AppContext) { + server.tools.ozone.moderation.getRecord({ + auth: ctx.authVerifier.role, + handler: async ({ req, params }) => { + const { data: recordDetailAppview } = + await ctx.moderationAgent.api.tools.ozone.moderation.getRecord( + params, + authPassthru(req), + ) + return { + encoding: 'application/json', + body: recordDetailAppview, + } + }, + }) +} diff --git a/packages/pds/src/api/tools/ozone/moderation/getRepo.ts b/packages/pds/src/api/tools/ozone/moderation/getRepo.ts new file mode 100644 index 00000000000..e3b53b84a01 --- /dev/null +++ b/packages/pds/src/api/tools/ozone/moderation/getRepo.ts @@ -0,0 +1,19 @@ +import { Server } from '../../../../lexicon' +import AppContext from '../../../../context' +import { authPassthru } from '../../../proxy' + +export default function (server: Server, ctx: AppContext) { + server.tools.ozone.moderation.getRepo({ + auth: ctx.authVerifier.role, + handler: async ({ req, params }) => { + const res = await ctx.moderationAgent.api.tools.ozone.moderation.getRepo( + params, + authPassthru(req), + ) + return { + encoding: 'application/json', + body: res.data, + } + }, + }) +} diff --git a/packages/pds/src/api/tools/ozone/moderation/index.ts b/packages/pds/src/api/tools/ozone/moderation/index.ts new file mode 100644 index 00000000000..9b460a41e7d --- /dev/null +++ b/packages/pds/src/api/tools/ozone/moderation/index.ts @@ -0,0 +1,19 @@ +import AppContext from '../../../../context' +import { Server } from '../../../../lexicon' +import emitEvent from './emitEvent' +import getEvent from './getEvent' +import getRecord from './getRecord' +import getRepo from './getRepo' +import queryEvents from './queryEvents' +import queryStatuses from './queryStatuses' +import searchRepos from './searchRepos' + +export default function (server: Server, ctx: AppContext) { + emitEvent(server, ctx) + getEvent(server, ctx) + getRecord(server, ctx) + getRepo(server, ctx) + queryEvents(server, ctx) + queryStatuses(server, ctx) + searchRepos(server, ctx) +} diff --git a/packages/pds/src/api/tools/ozone/moderation/queryEvents.ts b/packages/pds/src/api/tools/ozone/moderation/queryEvents.ts new file mode 100644 index 00000000000..90ffb1837b4 --- /dev/null +++ b/packages/pds/src/api/tools/ozone/moderation/queryEvents.ts @@ -0,0 +1,20 @@ +import { Server } from '../../../../lexicon' +import AppContext from '../../../../context' +import { authPassthru } from '../../../proxy' + +export default function (server: Server, ctx: AppContext) { + server.tools.ozone.moderation.queryEvents({ + auth: ctx.authVerifier.role, + handler: async ({ req, params }) => { + const { data: result } = + await ctx.moderationAgent.api.tools.ozone.moderation.queryEvents( + params, + authPassthru(req), + ) + return { + encoding: 'application/json', + body: result, + } + }, + }) +} diff --git a/packages/pds/src/api/tools/ozone/moderation/queryStatuses.ts b/packages/pds/src/api/tools/ozone/moderation/queryStatuses.ts new file mode 100644 index 00000000000..9601877dfc1 --- /dev/null +++ b/packages/pds/src/api/tools/ozone/moderation/queryStatuses.ts @@ -0,0 +1,20 @@ +import { Server } from '../../../../lexicon' +import AppContext from '../../../../context' +import { authPassthru } from '../../../proxy' + +export default function (server: Server, ctx: AppContext) { + server.tools.ozone.moderation.queryStatuses({ + auth: ctx.authVerifier.role, + handler: async ({ req, params }) => { + const { data } = + await ctx.moderationAgent.api.tools.ozone.moderation.queryStatuses( + params, + authPassthru(req), + ) + return { + encoding: 'application/json', + body: data, + } + }, + }) +} diff --git a/packages/pds/src/api/tools/ozone/moderation/searchRepos.ts b/packages/pds/src/api/tools/ozone/moderation/searchRepos.ts new file mode 100644 index 00000000000..1833c53e879 --- /dev/null +++ b/packages/pds/src/api/tools/ozone/moderation/searchRepos.ts @@ -0,0 +1,22 @@ +import { Server } from '../../../../lexicon' +import AppContext from '../../../../context' +import { authPassthru } from '../../../proxy' + +export default function (server: Server, ctx: AppContext) { + server.tools.ozone.moderation.searchRepos({ + auth: ctx.authVerifier.role, + handler: async ({ req, params }) => { + // @TODO merge invite details to this list view. could also add + // support for invitedBy param, which is not supported by appview. + const { data: result } = + await ctx.moderationAgent.api.tools.ozone.moderation.searchRepos( + params, + authPassthru(req), + ) + return { + encoding: 'application/json', + body: result, + } + }, + }) +} diff --git a/packages/pds/src/lexicon/index.ts b/packages/pds/src/lexicon/index.ts index e2cf30e2be8..16dbb77db6a 100644 --- a/packages/pds/src/lexicon/index.ts +++ b/packages/pds/src/lexicon/index.ts @@ -136,6 +136,17 @@ import * as AppBskyUnspeccedGetTaggedSuggestions from './types/app/bsky/unspecce import * as AppBskyUnspeccedGetTimelineSkeleton from './types/app/bsky/unspecced/getTimelineSkeleton' import * as AppBskyUnspeccedSearchActorsSkeleton from './types/app/bsky/unspecced/searchActorsSkeleton' import * as AppBskyUnspeccedSearchPostsSkeleton from './types/app/bsky/unspecced/searchPostsSkeleton' +import * as ToolsOzoneCommunicationCreateTemplate from './types/tools/ozone/communication/createTemplate' +import * as ToolsOzoneCommunicationDeleteTemplate from './types/tools/ozone/communication/deleteTemplate' +import * as ToolsOzoneCommunicationListTemplates from './types/tools/ozone/communication/listTemplates' +import * as ToolsOzoneCommunicationUpdateTemplate from './types/tools/ozone/communication/updateTemplate' +import * as ToolsOzoneModerationEmitEvent from './types/tools/ozone/moderation/emitEvent' +import * as ToolsOzoneModerationGetEvent from './types/tools/ozone/moderation/getEvent' +import * as ToolsOzoneModerationGetRecord from './types/tools/ozone/moderation/getRecord' +import * as ToolsOzoneModerationGetRepo from './types/tools/ozone/moderation/getRepo' +import * as ToolsOzoneModerationQueryEvents from './types/tools/ozone/moderation/queryEvents' +import * as ToolsOzoneModerationQueryStatuses from './types/tools/ozone/moderation/queryStatuses' +import * as ToolsOzoneModerationSearchRepos from './types/tools/ozone/moderation/searchRepos' export const COM_ATPROTO_ADMIN = { DefsReviewOpen: 'com.atproto.admin.defs#reviewOpen', @@ -155,6 +166,12 @@ export const APP_BSKY_GRAPH = { DefsModlist: 'app.bsky.graph.defs#modlist', DefsCuratelist: 'app.bsky.graph.defs#curatelist', } +export const TOOLS_OZONE_MODERATION = { + DefsReviewOpen: 'tools.ozone.moderation.defs#reviewOpen', + DefsReviewEscalated: 'tools.ozone.moderation.defs#reviewEscalated', + DefsReviewClosed: 'tools.ozone.moderation.defs#reviewClosed', + DefsReviewNone: 'tools.ozone.moderation.defs#reviewNone', +} export function createServer(options?: XrpcOptions): Server { return new Server(options) @@ -164,11 +181,13 @@ export class Server { xrpc: XrpcServer com: ComNS app: AppNS + tools: ToolsNS constructor(options?: XrpcOptions) { this.xrpc = createXrpcServer(schemas, options) this.com = new ComNS(this) this.app = new AppNS(this) + this.tools = new ToolsNS(this) } } @@ -1757,6 +1776,165 @@ export class AppBskyUnspeccedNS { } } +export class ToolsNS { + _server: Server + ozone: ToolsOzoneNS + + constructor(server: Server) { + this._server = server + this.ozone = new ToolsOzoneNS(server) + } +} + +export class ToolsOzoneNS { + _server: Server + communication: ToolsOzoneCommunicationNS + moderation: ToolsOzoneModerationNS + + constructor(server: Server) { + this._server = server + this.communication = new ToolsOzoneCommunicationNS(server) + this.moderation = new ToolsOzoneModerationNS(server) + } +} + +export class ToolsOzoneCommunicationNS { + _server: Server + + constructor(server: Server) { + this._server = server + } + + createTemplate( + cfg: ConfigOf< + AV, + ToolsOzoneCommunicationCreateTemplate.Handler>, + ToolsOzoneCommunicationCreateTemplate.HandlerReqCtx> + >, + ) { + const nsid = 'tools.ozone.communication.createTemplate' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + deleteTemplate( + cfg: ConfigOf< + AV, + ToolsOzoneCommunicationDeleteTemplate.Handler>, + ToolsOzoneCommunicationDeleteTemplate.HandlerReqCtx> + >, + ) { + const nsid = 'tools.ozone.communication.deleteTemplate' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + listTemplates( + cfg: ConfigOf< + AV, + ToolsOzoneCommunicationListTemplates.Handler>, + ToolsOzoneCommunicationListTemplates.HandlerReqCtx> + >, + ) { + const nsid = 'tools.ozone.communication.listTemplates' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + updateTemplate( + cfg: ConfigOf< + AV, + ToolsOzoneCommunicationUpdateTemplate.Handler>, + ToolsOzoneCommunicationUpdateTemplate.HandlerReqCtx> + >, + ) { + const nsid = 'tools.ozone.communication.updateTemplate' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } +} + +export class ToolsOzoneModerationNS { + _server: Server + + constructor(server: Server) { + this._server = server + } + + emitEvent( + cfg: ConfigOf< + AV, + ToolsOzoneModerationEmitEvent.Handler>, + ToolsOzoneModerationEmitEvent.HandlerReqCtx> + >, + ) { + const nsid = 'tools.ozone.moderation.emitEvent' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + getEvent( + cfg: ConfigOf< + AV, + ToolsOzoneModerationGetEvent.Handler>, + ToolsOzoneModerationGetEvent.HandlerReqCtx> + >, + ) { + const nsid = 'tools.ozone.moderation.getEvent' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + getRecord( + cfg: ConfigOf< + AV, + ToolsOzoneModerationGetRecord.Handler>, + ToolsOzoneModerationGetRecord.HandlerReqCtx> + >, + ) { + const nsid = 'tools.ozone.moderation.getRecord' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + getRepo( + cfg: ConfigOf< + AV, + ToolsOzoneModerationGetRepo.Handler>, + ToolsOzoneModerationGetRepo.HandlerReqCtx> + >, + ) { + const nsid = 'tools.ozone.moderation.getRepo' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + queryEvents( + cfg: ConfigOf< + AV, + ToolsOzoneModerationQueryEvents.Handler>, + ToolsOzoneModerationQueryEvents.HandlerReqCtx> + >, + ) { + const nsid = 'tools.ozone.moderation.queryEvents' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + queryStatuses( + cfg: ConfigOf< + AV, + ToolsOzoneModerationQueryStatuses.Handler>, + ToolsOzoneModerationQueryStatuses.HandlerReqCtx> + >, + ) { + const nsid = 'tools.ozone.moderation.queryStatuses' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } + + searchRepos( + cfg: ConfigOf< + AV, + ToolsOzoneModerationSearchRepos.Handler>, + ToolsOzoneModerationSearchRepos.HandlerReqCtx> + >, + ) { + const nsid = 'tools.ozone.moderation.searchRepos' // @ts-ignore + return this._server.xrpc.method(nsid, cfg) + } +} + type SharedRateLimitOpts = { name: string calcKey?: (ctx: T) => string diff --git a/packages/pds/src/lexicon/lexicons.ts b/packages/pds/src/lexicon/lexicons.ts index 06beebc7916..c092e98dd58 100644 --- a/packages/pds/src/lexicon/lexicons.ts +++ b/packages/pds/src/lexicon/lexicons.ts @@ -8786,6 +8786,1383 @@ export const schemaDict = { }, }, }, + ToolsOzoneCommunicationCreateTemplate: { + lexicon: 1, + id: 'tools.ozone.communication.createTemplate', + defs: { + main: { + type: 'procedure', + description: + 'Administrative action to create a new, re-usable communication (email for now) template.', + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['subject', 'contentMarkdown', 'name'], + properties: { + name: { + type: 'string', + description: 'Name of the template.', + }, + contentMarkdown: { + type: 'string', + description: + 'Content of the template, markdown supported, can contain variable placeholders.', + }, + subject: { + type: 'string', + description: 'Subject of the message, used in emails.', + }, + createdBy: { + type: 'string', + format: 'did', + description: 'DID of the user who is creating the template.', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:tools.ozone.communication.defs#templateView', + }, + }, + }, + }, + }, + ToolsOzoneCommunicationDefs: { + lexicon: 1, + id: 'tools.ozone.communication.defs', + defs: { + templateView: { + type: 'object', + required: [ + 'id', + 'name', + 'contentMarkdown', + 'disabled', + 'lastUpdatedBy', + 'createdAt', + 'updatedAt', + ], + properties: { + id: { + type: 'string', + }, + name: { + type: 'string', + description: 'Name of the template.', + }, + subject: { + type: 'string', + description: + 'Content of the template, can contain markdown and variable placeholders.', + }, + contentMarkdown: { + type: 'string', + description: 'Subject of the message, used in emails.', + }, + disabled: { + type: 'boolean', + }, + lastUpdatedBy: { + type: 'string', + format: 'did', + description: 'DID of the user who last updated the template.', + }, + createdAt: { + type: 'string', + format: 'datetime', + }, + updatedAt: { + type: 'string', + format: 'datetime', + }, + }, + }, + }, + }, + ToolsOzoneCommunicationDeleteTemplate: { + lexicon: 1, + id: 'tools.ozone.communication.deleteTemplate', + defs: { + main: { + type: 'procedure', + description: 'Delete a communication template.', + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['id'], + properties: { + id: { + type: 'string', + }, + }, + }, + }, + }, + }, + }, + ToolsOzoneCommunicationListTemplates: { + lexicon: 1, + id: 'tools.ozone.communication.listTemplates', + defs: { + main: { + type: 'query', + description: 'Get list of all communication templates.', + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['communicationTemplates'], + properties: { + communicationTemplates: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:tools.ozone.communication.defs#templateView', + }, + }, + }, + }, + }, + }, + }, + }, + ToolsOzoneCommunicationUpdateTemplate: { + lexicon: 1, + id: 'tools.ozone.communication.updateTemplate', + defs: { + main: { + type: 'procedure', + description: + 'Administrative action to update an existing communication template. Allows passing partial fields to patch specific fields only.', + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['id'], + properties: { + id: { + type: 'string', + description: 'ID of the template to be updated.', + }, + name: { + type: 'string', + description: 'Name of the template.', + }, + contentMarkdown: { + type: 'string', + description: + 'Content of the template, markdown supported, can contain variable placeholders.', + }, + subject: { + type: 'string', + description: 'Subject of the message, used in emails.', + }, + updatedBy: { + type: 'string', + format: 'did', + description: 'DID of the user who is updating the template.', + }, + disabled: { + type: 'boolean', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:tools.ozone.communication.defs#templateView', + }, + }, + }, + }, + }, + ToolsOzoneModerationDefs: { + lexicon: 1, + id: 'tools.ozone.moderation.defs', + defs: { + modEventView: { + type: 'object', + required: [ + 'id', + 'event', + 'subject', + 'subjectBlobCids', + 'createdBy', + 'createdAt', + ], + properties: { + id: { + type: 'integer', + }, + event: { + type: 'union', + refs: [ + 'lex:tools.ozone.moderation.defs#modEventTakedown', + 'lex:tools.ozone.moderation.defs#modEventReverseTakedown', + 'lex:tools.ozone.moderation.defs#modEventComment', + 'lex:tools.ozone.moderation.defs#modEventReport', + 'lex:tools.ozone.moderation.defs#modEventLabel', + 'lex:tools.ozone.moderation.defs#modEventAcknowledge', + 'lex:tools.ozone.moderation.defs#modEventEscalate', + 'lex:tools.ozone.moderation.defs#modEventMute', + 'lex:tools.ozone.moderation.defs#modEventEmail', + 'lex:tools.ozone.moderation.defs#modEventResolveAppeal', + 'lex:tools.ozone.moderation.defs#modEventDivert', + ], + }, + subject: { + type: 'union', + refs: [ + 'lex:com.atproto.admin.defs#repoRef', + 'lex:com.atproto.repo.strongRef', + ], + }, + subjectBlobCids: { + type: 'array', + items: { + type: 'string', + }, + }, + createdBy: { + type: 'string', + format: 'did', + }, + createdAt: { + type: 'string', + format: 'datetime', + }, + creatorHandle: { + type: 'string', + }, + subjectHandle: { + type: 'string', + }, + }, + }, + modEventViewDetail: { + type: 'object', + required: [ + 'id', + 'event', + 'subject', + 'subjectBlobs', + 'createdBy', + 'createdAt', + ], + properties: { + id: { + type: 'integer', + }, + event: { + type: 'union', + refs: [ + 'lex:tools.ozone.moderation.defs#modEventTakedown', + 'lex:tools.ozone.moderation.defs#modEventReverseTakedown', + 'lex:tools.ozone.moderation.defs#modEventComment', + 'lex:tools.ozone.moderation.defs#modEventReport', + 'lex:tools.ozone.moderation.defs#modEventLabel', + 'lex:tools.ozone.moderation.defs#modEventAcknowledge', + 'lex:tools.ozone.moderation.defs#modEventEscalate', + 'lex:tools.ozone.moderation.defs#modEventMute', + 'lex:tools.ozone.moderation.defs#modEventEmail', + 'lex:tools.ozone.moderation.defs#modEventResolveAppeal', + 'lex:tools.ozone.moderation.defs#modEventDivert', + ], + }, + subject: { + type: 'union', + refs: [ + 'lex:tools.ozone.moderation.defs#repoView', + 'lex:tools.ozone.moderation.defs#repoViewNotFound', + 'lex:tools.ozone.moderation.defs#recordView', + 'lex:tools.ozone.moderation.defs#recordViewNotFound', + ], + }, + subjectBlobs: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#blobView', + }, + }, + createdBy: { + type: 'string', + format: 'did', + }, + createdAt: { + type: 'string', + format: 'datetime', + }, + }, + }, + subjectStatusView: { + type: 'object', + required: ['id', 'subject', 'createdAt', 'updatedAt', 'reviewState'], + properties: { + id: { + type: 'integer', + }, + subject: { + type: 'union', + refs: [ + 'lex:com.atproto.admin.defs#repoRef', + 'lex:com.atproto.repo.strongRef', + ], + }, + subjectBlobCids: { + type: 'array', + items: { + type: 'string', + format: 'cid', + }, + }, + subjectRepoHandle: { + type: 'string', + }, + updatedAt: { + type: 'string', + format: 'datetime', + description: + 'Timestamp referencing when the last update was made to the moderation status of the subject', + }, + createdAt: { + type: 'string', + format: 'datetime', + description: + 'Timestamp referencing the first moderation status impacting event was emitted on the subject', + }, + reviewState: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#subjectReviewState', + }, + comment: { + type: 'string', + description: 'Sticky comment on the subject.', + }, + muteUntil: { + type: 'string', + format: 'datetime', + }, + lastReviewedBy: { + type: 'string', + format: 'did', + }, + lastReviewedAt: { + type: 'string', + format: 'datetime', + }, + lastReportedAt: { + type: 'string', + format: 'datetime', + }, + lastAppealedAt: { + type: 'string', + format: 'datetime', + description: + 'Timestamp referencing when the author of the subject appealed a moderation action', + }, + takendown: { + type: 'boolean', + }, + appealed: { + type: 'boolean', + description: + 'True indicates that the a previously taken moderator action was appealed against, by the author of the content. False indicates last appeal was resolved by moderators.', + }, + suspendUntil: { + type: 'string', + format: 'datetime', + }, + tags: { + type: 'array', + items: { + type: 'string', + }, + }, + }, + }, + subjectReviewState: { + type: 'string', + knownValues: [ + 'lex:tools.ozone.moderation.defs#reviewOpen', + 'lex:tools.ozone.moderation.defs#reviewEscalated', + 'lex:tools.ozone.moderation.defs#reviewClosed', + 'lex:tools.ozone.moderation.defs#reviewNone', + ], + }, + reviewOpen: { + type: 'token', + description: + 'Moderator review status of a subject: Open. Indicates that the subject needs to be reviewed by a moderator', + }, + reviewEscalated: { + type: 'token', + description: + 'Moderator review status of a subject: Escalated. Indicates that the subject was escalated for review by a moderator', + }, + reviewClosed: { + type: 'token', + description: + 'Moderator review status of a subject: Closed. Indicates that the subject was already reviewed and resolved by a moderator', + }, + reviewNone: { + type: 'token', + description: + 'Moderator review status of a subject: Unnecessary. Indicates that the subject does not need a review at the moment but there is probably some moderation related metadata available for it', + }, + modEventTakedown: { + type: 'object', + description: 'Take down a subject permanently or temporarily', + properties: { + comment: { + type: 'string', + }, + durationInHours: { + type: 'integer', + description: + 'Indicates how long the takedown should be in effect before automatically expiring.', + }, + }, + }, + modEventReverseTakedown: { + type: 'object', + description: 'Revert take down action on a subject', + properties: { + comment: { + type: 'string', + description: 'Describe reasoning behind the reversal.', + }, + }, + }, + modEventResolveAppeal: { + type: 'object', + description: 'Resolve appeal on a subject', + properties: { + comment: { + type: 'string', + description: 'Describe resolution.', + }, + }, + }, + modEventComment: { + type: 'object', + description: 'Add a comment to a subject', + required: ['comment'], + properties: { + comment: { + type: 'string', + }, + sticky: { + type: 'boolean', + description: 'Make the comment persistent on the subject', + }, + }, + }, + modEventReport: { + type: 'object', + description: 'Report a subject', + required: ['reportType'], + properties: { + comment: { + type: 'string', + }, + reportType: { + type: 'ref', + ref: 'lex:com.atproto.moderation.defs#reasonType', + }, + }, + }, + modEventLabel: { + type: 'object', + description: 'Apply/Negate labels on a subject', + required: ['createLabelVals', 'negateLabelVals'], + properties: { + comment: { + type: 'string', + }, + createLabelVals: { + type: 'array', + items: { + type: 'string', + }, + }, + negateLabelVals: { + type: 'array', + items: { + type: 'string', + }, + }, + }, + }, + modEventAcknowledge: { + type: 'object', + properties: { + comment: { + type: 'string', + }, + }, + }, + modEventEscalate: { + type: 'object', + properties: { + comment: { + type: 'string', + }, + }, + }, + modEventMute: { + type: 'object', + description: 'Mute incoming reports on a subject', + required: ['durationInHours'], + properties: { + comment: { + type: 'string', + }, + durationInHours: { + type: 'integer', + description: 'Indicates how long the subject should remain muted.', + }, + }, + }, + modEventUnmute: { + type: 'object', + description: 'Unmute action on a subject', + properties: { + comment: { + type: 'string', + description: 'Describe reasoning behind the reversal.', + }, + }, + }, + modEventEmail: { + type: 'object', + description: 'Keep a log of outgoing email to a user', + required: ['subjectLine'], + properties: { + subjectLine: { + type: 'string', + description: 'The subject line of the email sent to the user.', + }, + content: { + type: 'string', + description: 'The content of the email sent to the user.', + }, + comment: { + type: 'string', + description: 'Additional comment about the outgoing comm.', + }, + }, + }, + modEventDivert: { + type: 'object', + description: + "Divert a record's blobs to a 3rd party service for further scanning/tagging", + properties: { + comment: { + type: 'string', + }, + }, + }, + modEventTag: { + type: 'object', + description: 'Add/Remove a tag on a subject', + required: ['add', 'remove'], + properties: { + add: { + type: 'array', + items: { + type: 'string', + }, + description: + "Tags to be added to the subject. If already exists, won't be duplicated.", + }, + remove: { + type: 'array', + items: { + type: 'string', + }, + description: + "Tags to be removed to the subject. Ignores a tag If it doesn't exist, won't be duplicated.", + }, + comment: { + type: 'string', + description: 'Additional comment about added/removed tags.', + }, + }, + }, + repoView: { + type: 'object', + required: [ + 'did', + 'handle', + 'relatedRecords', + 'indexedAt', + 'moderation', + ], + properties: { + did: { + type: 'string', + format: 'did', + }, + handle: { + type: 'string', + format: 'handle', + }, + email: { + type: 'string', + }, + relatedRecords: { + type: 'array', + items: { + type: 'unknown', + }, + }, + indexedAt: { + type: 'string', + format: 'datetime', + }, + moderation: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#moderation', + }, + invitedBy: { + type: 'ref', + ref: 'lex:com.atproto.server.defs#inviteCode', + }, + invitesDisabled: { + type: 'boolean', + }, + inviteNote: { + type: 'string', + }, + }, + }, + repoViewDetail: { + type: 'object', + required: [ + 'did', + 'handle', + 'relatedRecords', + 'indexedAt', + 'moderation', + ], + properties: { + did: { + type: 'string', + format: 'did', + }, + handle: { + type: 'string', + format: 'handle', + }, + email: { + type: 'string', + }, + relatedRecords: { + type: 'array', + items: { + type: 'unknown', + }, + }, + indexedAt: { + type: 'string', + format: 'datetime', + }, + moderation: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#moderationDetail', + }, + labels: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:com.atproto.label.defs#label', + }, + }, + invitedBy: { + type: 'ref', + ref: 'lex:com.atproto.server.defs#inviteCode', + }, + invites: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:com.atproto.server.defs#inviteCode', + }, + }, + invitesDisabled: { + type: 'boolean', + }, + inviteNote: { + type: 'string', + }, + emailConfirmedAt: { + type: 'string', + format: 'datetime', + }, + }, + }, + repoViewNotFound: { + type: 'object', + required: ['did'], + properties: { + did: { + type: 'string', + format: 'did', + }, + }, + }, + recordView: { + type: 'object', + required: [ + 'uri', + 'cid', + 'value', + 'blobCids', + 'indexedAt', + 'moderation', + 'repo', + ], + properties: { + uri: { + type: 'string', + format: 'at-uri', + }, + cid: { + type: 'string', + format: 'cid', + }, + value: { + type: 'unknown', + }, + blobCids: { + type: 'array', + items: { + type: 'string', + format: 'cid', + }, + }, + indexedAt: { + type: 'string', + format: 'datetime', + }, + moderation: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#moderation', + }, + repo: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#repoView', + }, + }, + }, + recordViewDetail: { + type: 'object', + required: [ + 'uri', + 'cid', + 'value', + 'blobs', + 'indexedAt', + 'moderation', + 'repo', + ], + properties: { + uri: { + type: 'string', + format: 'at-uri', + }, + cid: { + type: 'string', + format: 'cid', + }, + value: { + type: 'unknown', + }, + blobs: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#blobView', + }, + }, + labels: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:com.atproto.label.defs#label', + }, + }, + indexedAt: { + type: 'string', + format: 'datetime', + }, + moderation: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#moderationDetail', + }, + repo: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#repoView', + }, + }, + }, + recordViewNotFound: { + type: 'object', + required: ['uri'], + properties: { + uri: { + type: 'string', + format: 'at-uri', + }, + }, + }, + moderation: { + type: 'object', + properties: { + subjectStatus: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#subjectStatusView', + }, + }, + }, + moderationDetail: { + type: 'object', + properties: { + subjectStatus: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#subjectStatusView', + }, + }, + }, + blobView: { + type: 'object', + required: ['cid', 'mimeType', 'size', 'createdAt'], + properties: { + cid: { + type: 'string', + format: 'cid', + }, + mimeType: { + type: 'string', + }, + size: { + type: 'integer', + }, + createdAt: { + type: 'string', + format: 'datetime', + }, + details: { + type: 'union', + refs: [ + 'lex:tools.ozone.moderation.defs#imageDetails', + 'lex:tools.ozone.moderation.defs#videoDetails', + ], + }, + moderation: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#moderation', + }, + }, + }, + imageDetails: { + type: 'object', + required: ['width', 'height'], + properties: { + width: { + type: 'integer', + }, + height: { + type: 'integer', + }, + }, + }, + videoDetails: { + type: 'object', + required: ['width', 'height', 'length'], + properties: { + width: { + type: 'integer', + }, + height: { + type: 'integer', + }, + length: { + type: 'integer', + }, + }, + }, + }, + }, + ToolsOzoneModerationEmitEvent: { + lexicon: 1, + id: 'tools.ozone.moderation.emitEvent', + defs: { + main: { + type: 'procedure', + description: 'Take a moderation action on an actor.', + input: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['event', 'subject', 'createdBy'], + properties: { + event: { + type: 'union', + refs: [ + 'lex:tools.ozone.moderation.defs#modEventTakedown', + 'lex:tools.ozone.moderation.defs#modEventAcknowledge', + 'lex:tools.ozone.moderation.defs#modEventEscalate', + 'lex:tools.ozone.moderation.defs#modEventComment', + 'lex:tools.ozone.moderation.defs#modEventLabel', + 'lex:tools.ozone.moderation.defs#modEventReport', + 'lex:tools.ozone.moderation.defs#modEventMute', + 'lex:tools.ozone.moderation.defs#modEventReverseTakedown', + 'lex:tools.ozone.moderation.defs#modEventUnmute', + 'lex:tools.ozone.moderation.defs#modEventEmail', + 'lex:tools.ozone.moderation.defs#modEventTag', + ], + }, + subject: { + type: 'union', + refs: [ + 'lex:com.atproto.admin.defs#repoRef', + 'lex:com.atproto.repo.strongRef', + ], + }, + subjectBlobCids: { + type: 'array', + items: { + type: 'string', + format: 'cid', + }, + }, + createdBy: { + type: 'string', + format: 'did', + }, + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#modEventView', + }, + }, + errors: [ + { + name: 'SubjectHasAction', + }, + ], + }, + }, + }, + ToolsOzoneModerationGetEvent: { + lexicon: 1, + id: 'tools.ozone.moderation.getEvent', + defs: { + main: { + type: 'query', + description: 'Get details about a moderation event.', + parameters: { + type: 'params', + required: ['id'], + properties: { + id: { + type: 'integer', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#modEventViewDetail', + }, + }, + }, + }, + }, + ToolsOzoneModerationGetRecord: { + lexicon: 1, + id: 'tools.ozone.moderation.getRecord', + defs: { + main: { + type: 'query', + description: 'Get details about a record.', + parameters: { + type: 'params', + required: ['uri'], + properties: { + uri: { + type: 'string', + format: 'at-uri', + }, + cid: { + type: 'string', + format: 'cid', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#recordViewDetail', + }, + }, + errors: [ + { + name: 'RecordNotFound', + }, + ], + }, + }, + }, + ToolsOzoneModerationGetRepo: { + lexicon: 1, + id: 'tools.ozone.moderation.getRepo', + defs: { + main: { + type: 'query', + description: 'Get details about a repository.', + parameters: { + type: 'params', + required: ['did'], + properties: { + did: { + type: 'string', + format: 'did', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#repoViewDetail', + }, + }, + errors: [ + { + name: 'RepoNotFound', + }, + ], + }, + }, + }, + ToolsOzoneModerationQueryEvents: { + lexicon: 1, + id: 'tools.ozone.moderation.queryEvents', + defs: { + main: { + type: 'query', + description: 'List moderation events related to a subject.', + parameters: { + type: 'params', + properties: { + types: { + type: 'array', + items: { + type: 'string', + }, + description: + 'The types of events (fully qualified string in the format of tools.ozone.moderation.defs#modEvent) to filter by. If not specified, all events are returned.', + }, + createdBy: { + type: 'string', + format: 'did', + }, + sortDirection: { + type: 'string', + default: 'desc', + enum: ['asc', 'desc'], + description: + 'Sort direction for the events. Defaults to descending order of created at timestamp.', + }, + createdAfter: { + type: 'string', + format: 'datetime', + description: 'Retrieve events created after a given timestamp', + }, + createdBefore: { + type: 'string', + format: 'datetime', + description: 'Retrieve events created before a given timestamp', + }, + subject: { + type: 'string', + format: 'uri', + }, + includeAllUserRecords: { + type: 'boolean', + default: false, + description: + 'If true, events on all record types (posts, lists, profile etc.) owned by the did are returned', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + hasComment: { + type: 'boolean', + description: 'If true, only events with comments are returned', + }, + comment: { + type: 'string', + description: + 'If specified, only events with comments containing the keyword are returned', + }, + addedLabels: { + type: 'array', + items: { + type: 'string', + }, + description: + 'If specified, only events where all of these labels were added are returned', + }, + removedLabels: { + type: 'array', + items: { + type: 'string', + }, + description: + 'If specified, only events where all of these labels were removed are returned', + }, + addedTags: { + type: 'array', + items: { + type: 'string', + }, + description: + 'If specified, only events where all of these tags were added are returned', + }, + removedTags: { + type: 'array', + items: { + type: 'string', + }, + description: + 'If specified, only events where all of these tags were removed are returned', + }, + reportTypes: { + type: 'array', + items: { + type: 'string', + }, + }, + cursor: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['events'], + properties: { + cursor: { + type: 'string', + }, + events: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#modEventView', + }, + }, + }, + }, + }, + }, + }, + }, + ToolsOzoneModerationQueryStatuses: { + lexicon: 1, + id: 'tools.ozone.moderation.queryStatuses', + defs: { + main: { + type: 'query', + description: 'View moderation statuses of subjects (record or repo).', + parameters: { + type: 'params', + properties: { + subject: { + type: 'string', + format: 'uri', + }, + comment: { + type: 'string', + description: 'Search subjects by keyword from comments', + }, + reportedAfter: { + type: 'string', + format: 'datetime', + description: 'Search subjects reported after a given timestamp', + }, + reportedBefore: { + type: 'string', + format: 'datetime', + description: 'Search subjects reported before a given timestamp', + }, + reviewedAfter: { + type: 'string', + format: 'datetime', + description: 'Search subjects reviewed after a given timestamp', + }, + reviewedBefore: { + type: 'string', + format: 'datetime', + description: 'Search subjects reviewed before a given timestamp', + }, + includeMuted: { + type: 'boolean', + description: + "By default, we don't include muted subjects in the results. Set this to true to include them.", + }, + reviewState: { + type: 'string', + description: 'Specify when fetching subjects in a certain state', + }, + ignoreSubjects: { + type: 'array', + items: { + type: 'string', + format: 'uri', + }, + }, + lastReviewedBy: { + type: 'string', + format: 'did', + description: + 'Get all subject statuses that were reviewed by a specific moderator', + }, + sortField: { + type: 'string', + default: 'lastReportedAt', + enum: ['lastReviewedAt', 'lastReportedAt'], + }, + sortDirection: { + type: 'string', + default: 'desc', + enum: ['asc', 'desc'], + }, + takendown: { + type: 'boolean', + description: 'Get subjects that were taken down', + }, + appealed: { + type: 'boolean', + description: 'Get subjects in unresolved appealed status', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + tags: { + type: 'array', + items: { + type: 'string', + }, + }, + excludeTags: { + type: 'array', + items: { + type: 'string', + }, + }, + cursor: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['subjectStatuses'], + properties: { + cursor: { + type: 'string', + }, + subjectStatuses: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#subjectStatusView', + }, + }, + }, + }, + }, + }, + }, + }, + ToolsOzoneModerationSearchRepos: { + lexicon: 1, + id: 'tools.ozone.moderation.searchRepos', + defs: { + main: { + type: 'query', + description: 'Find repositories based on a search term.', + parameters: { + type: 'params', + properties: { + term: { + type: 'string', + description: "DEPRECATED: use 'q' instead", + }, + q: { + type: 'string', + }, + limit: { + type: 'integer', + minimum: 1, + maximum: 100, + default: 50, + }, + cursor: { + type: 'string', + }, + }, + }, + output: { + encoding: 'application/json', + schema: { + type: 'object', + required: ['repos'], + properties: { + cursor: { + type: 'string', + }, + repos: { + type: 'array', + items: { + type: 'ref', + ref: 'lex:tools.ozone.moderation.defs#repoView', + }, + }, + }, + }, + }, + }, + }, + }, } export const schemas: LexiconDoc[] = Object.values(schemaDict) as LexiconDoc[] export const lexicons: Lexicons = new Lexicons(schemas) @@ -8960,4 +10337,21 @@ export const ids = { AppBskyUnspeccedSearchActorsSkeleton: 'app.bsky.unspecced.searchActorsSkeleton', AppBskyUnspeccedSearchPostsSkeleton: 'app.bsky.unspecced.searchPostsSkeleton', + ToolsOzoneCommunicationCreateTemplate: + 'tools.ozone.communication.createTemplate', + ToolsOzoneCommunicationDefs: 'tools.ozone.communication.defs', + ToolsOzoneCommunicationDeleteTemplate: + 'tools.ozone.communication.deleteTemplate', + ToolsOzoneCommunicationListTemplates: + 'tools.ozone.communication.listTemplates', + ToolsOzoneCommunicationUpdateTemplate: + 'tools.ozone.communication.updateTemplate', + ToolsOzoneModerationDefs: 'tools.ozone.moderation.defs', + ToolsOzoneModerationEmitEvent: 'tools.ozone.moderation.emitEvent', + ToolsOzoneModerationGetEvent: 'tools.ozone.moderation.getEvent', + ToolsOzoneModerationGetRecord: 'tools.ozone.moderation.getRecord', + ToolsOzoneModerationGetRepo: 'tools.ozone.moderation.getRepo', + ToolsOzoneModerationQueryEvents: 'tools.ozone.moderation.queryEvents', + ToolsOzoneModerationQueryStatuses: 'tools.ozone.moderation.queryStatuses', + ToolsOzoneModerationSearchRepos: 'tools.ozone.moderation.searchRepos', } diff --git a/packages/pds/src/lexicon/types/tools/ozone/communication/createTemplate.ts b/packages/pds/src/lexicon/types/tools/ozone/communication/createTemplate.ts new file mode 100644 index 00000000000..abdf85e8ade --- /dev/null +++ b/packages/pds/src/lexicon/types/tools/ozone/communication/createTemplate.ts @@ -0,0 +1,54 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server' +import * as ToolsOzoneCommunicationDefs from './defs' + +export interface QueryParams {} + +export interface InputSchema { + /** Name of the template. */ + name: string + /** Content of the template, markdown supported, can contain variable placeholders. */ + contentMarkdown: string + /** Subject of the message, used in emails. */ + subject: string + /** DID of the user who is creating the template. */ + createdBy?: string + [k: string]: unknown +} + +export type OutputSchema = ToolsOzoneCommunicationDefs.TemplateView + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string +} + +export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/pds/src/lexicon/types/tools/ozone/communication/defs.ts b/packages/pds/src/lexicon/types/tools/ozone/communication/defs.ts new file mode 100644 index 00000000000..a46b8c3ce79 --- /dev/null +++ b/packages/pds/src/lexicon/types/tools/ozone/communication/defs.ts @@ -0,0 +1,35 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' + +export interface TemplateView { + id: string + /** Name of the template. */ + name: string + /** Content of the template, can contain markdown and variable placeholders. */ + subject?: string + /** Subject of the message, used in emails. */ + contentMarkdown: string + disabled: boolean + /** DID of the user who last updated the template. */ + lastUpdatedBy: string + createdAt: string + updatedAt: string + [k: string]: unknown +} + +export function isTemplateView(v: unknown): v is TemplateView { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.communication.defs#templateView' + ) +} + +export function validateTemplateView(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.communication.defs#templateView', v) +} diff --git a/packages/pds/src/lexicon/types/tools/ozone/communication/deleteTemplate.ts b/packages/pds/src/lexicon/types/tools/ozone/communication/deleteTemplate.ts new file mode 100644 index 00000000000..c5ae5cd469f --- /dev/null +++ b/packages/pds/src/lexicon/types/tools/ozone/communication/deleteTemplate.ts @@ -0,0 +1,38 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server' + +export interface QueryParams {} + +export interface InputSchema { + id: string + [k: string]: unknown +} + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerError { + status: number + message?: string +} + +export type HandlerOutput = HandlerError | void +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/pds/src/lexicon/types/tools/ozone/communication/listTemplates.ts b/packages/pds/src/lexicon/types/tools/ozone/communication/listTemplates.ts new file mode 100644 index 00000000000..4573ac7bbb9 --- /dev/null +++ b/packages/pds/src/lexicon/types/tools/ozone/communication/listTemplates.ts @@ -0,0 +1,44 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server' +import * as ToolsOzoneCommunicationDefs from './defs' + +export interface QueryParams {} + +export type InputSchema = undefined + +export interface OutputSchema { + communicationTemplates: ToolsOzoneCommunicationDefs.TemplateView[] + [k: string]: unknown +} + +export type HandlerInput = undefined + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string +} + +export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/pds/src/lexicon/types/tools/ozone/communication/updateTemplate.ts b/packages/pds/src/lexicon/types/tools/ozone/communication/updateTemplate.ts new file mode 100644 index 00000000000..38ecc9d91af --- /dev/null +++ b/packages/pds/src/lexicon/types/tools/ozone/communication/updateTemplate.ts @@ -0,0 +1,57 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server' +import * as ToolsOzoneCommunicationDefs from './defs' + +export interface QueryParams {} + +export interface InputSchema { + /** ID of the template to be updated. */ + id: string + /** Name of the template. */ + name?: string + /** Content of the template, markdown supported, can contain variable placeholders. */ + contentMarkdown?: string + /** Subject of the message, used in emails. */ + subject?: string + /** DID of the user who is updating the template. */ + updatedBy?: string + disabled?: boolean + [k: string]: unknown +} + +export type OutputSchema = ToolsOzoneCommunicationDefs.TemplateView + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string +} + +export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/pds/src/lexicon/types/tools/ozone/moderation/defs.ts b/packages/pds/src/lexicon/types/tools/ozone/moderation/defs.ts new file mode 100644 index 00000000000..b150d735f6c --- /dev/null +++ b/packages/pds/src/lexicon/types/tools/ozone/moderation/defs.ts @@ -0,0 +1,641 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import * as ComAtprotoAdminDefs from '../../../com/atproto/admin/defs' +import * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef' +import * as ComAtprotoModerationDefs from '../../../com/atproto/moderation/defs' +import * as ComAtprotoServerDefs from '../../../com/atproto/server/defs' +import * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs' + +export interface ModEventView { + id: number + event: + | ModEventTakedown + | ModEventReverseTakedown + | ModEventComment + | ModEventReport + | ModEventLabel + | ModEventAcknowledge + | ModEventEscalate + | ModEventMute + | ModEventEmail + | ModEventResolveAppeal + | ModEventDivert + | { $type: string; [k: string]: unknown } + subject: + | ComAtprotoAdminDefs.RepoRef + | ComAtprotoRepoStrongRef.Main + | { $type: string; [k: string]: unknown } + subjectBlobCids: string[] + createdBy: string + createdAt: string + creatorHandle?: string + subjectHandle?: string + [k: string]: unknown +} + +export function isModEventView(v: unknown): v is ModEventView { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventView' + ) +} + +export function validateModEventView(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventView', v) +} + +export interface ModEventViewDetail { + id: number + event: + | ModEventTakedown + | ModEventReverseTakedown + | ModEventComment + | ModEventReport + | ModEventLabel + | ModEventAcknowledge + | ModEventEscalate + | ModEventMute + | ModEventEmail + | ModEventResolveAppeal + | ModEventDivert + | { $type: string; [k: string]: unknown } + subject: + | RepoView + | RepoViewNotFound + | RecordView + | RecordViewNotFound + | { $type: string; [k: string]: unknown } + subjectBlobs: BlobView[] + createdBy: string + createdAt: string + [k: string]: unknown +} + +export function isModEventViewDetail(v: unknown): v is ModEventViewDetail { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventViewDetail' + ) +} + +export function validateModEventViewDetail(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventViewDetail', v) +} + +export interface SubjectStatusView { + id: number + subject: + | ComAtprotoAdminDefs.RepoRef + | ComAtprotoRepoStrongRef.Main + | { $type: string; [k: string]: unknown } + subjectBlobCids?: string[] + subjectRepoHandle?: string + /** Timestamp referencing when the last update was made to the moderation status of the subject */ + updatedAt: string + /** Timestamp referencing the first moderation status impacting event was emitted on the subject */ + createdAt: string + reviewState: SubjectReviewState + /** Sticky comment on the subject. */ + comment?: string + muteUntil?: string + lastReviewedBy?: string + lastReviewedAt?: string + lastReportedAt?: string + /** Timestamp referencing when the author of the subject appealed a moderation action */ + lastAppealedAt?: string + takendown?: boolean + /** True indicates that the a previously taken moderator action was appealed against, by the author of the content. False indicates last appeal was resolved by moderators. */ + appealed?: boolean + suspendUntil?: string + tags?: string[] + [k: string]: unknown +} + +export function isSubjectStatusView(v: unknown): v is SubjectStatusView { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#subjectStatusView' + ) +} + +export function validateSubjectStatusView(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#subjectStatusView', v) +} + +export type SubjectReviewState = + | 'lex:tools.ozone.moderation.defs#reviewOpen' + | 'lex:tools.ozone.moderation.defs#reviewEscalated' + | 'lex:tools.ozone.moderation.defs#reviewClosed' + | 'lex:tools.ozone.moderation.defs#reviewNone' + | (string & {}) + +/** Moderator review status of a subject: Open. Indicates that the subject needs to be reviewed by a moderator */ +export const REVIEWOPEN = 'tools.ozone.moderation.defs#reviewOpen' +/** Moderator review status of a subject: Escalated. Indicates that the subject was escalated for review by a moderator */ +export const REVIEWESCALATED = 'tools.ozone.moderation.defs#reviewEscalated' +/** Moderator review status of a subject: Closed. Indicates that the subject was already reviewed and resolved by a moderator */ +export const REVIEWCLOSED = 'tools.ozone.moderation.defs#reviewClosed' +/** Moderator review status of a subject: Unnecessary. Indicates that the subject does not need a review at the moment but there is probably some moderation related metadata available for it */ +export const REVIEWNONE = 'tools.ozone.moderation.defs#reviewNone' + +/** Take down a subject permanently or temporarily */ +export interface ModEventTakedown { + comment?: string + /** Indicates how long the takedown should be in effect before automatically expiring. */ + durationInHours?: number + [k: string]: unknown +} + +export function isModEventTakedown(v: unknown): v is ModEventTakedown { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventTakedown' + ) +} + +export function validateModEventTakedown(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventTakedown', v) +} + +/** Revert take down action on a subject */ +export interface ModEventReverseTakedown { + /** Describe reasoning behind the reversal. */ + comment?: string + [k: string]: unknown +} + +export function isModEventReverseTakedown( + v: unknown, +): v is ModEventReverseTakedown { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventReverseTakedown' + ) +} + +export function validateModEventReverseTakedown(v: unknown): ValidationResult { + return lexicons.validate( + 'tools.ozone.moderation.defs#modEventReverseTakedown', + v, + ) +} + +/** Resolve appeal on a subject */ +export interface ModEventResolveAppeal { + /** Describe resolution. */ + comment?: string + [k: string]: unknown +} + +export function isModEventResolveAppeal( + v: unknown, +): v is ModEventResolveAppeal { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventResolveAppeal' + ) +} + +export function validateModEventResolveAppeal(v: unknown): ValidationResult { + return lexicons.validate( + 'tools.ozone.moderation.defs#modEventResolveAppeal', + v, + ) +} + +/** Add a comment to a subject */ +export interface ModEventComment { + comment: string + /** Make the comment persistent on the subject */ + sticky?: boolean + [k: string]: unknown +} + +export function isModEventComment(v: unknown): v is ModEventComment { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventComment' + ) +} + +export function validateModEventComment(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventComment', v) +} + +/** Report a subject */ +export interface ModEventReport { + comment?: string + reportType: ComAtprotoModerationDefs.ReasonType + [k: string]: unknown +} + +export function isModEventReport(v: unknown): v is ModEventReport { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventReport' + ) +} + +export function validateModEventReport(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventReport', v) +} + +/** Apply/Negate labels on a subject */ +export interface ModEventLabel { + comment?: string + createLabelVals: string[] + negateLabelVals: string[] + [k: string]: unknown +} + +export function isModEventLabel(v: unknown): v is ModEventLabel { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventLabel' + ) +} + +export function validateModEventLabel(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventLabel', v) +} + +export interface ModEventAcknowledge { + comment?: string + [k: string]: unknown +} + +export function isModEventAcknowledge(v: unknown): v is ModEventAcknowledge { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventAcknowledge' + ) +} + +export function validateModEventAcknowledge(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventAcknowledge', v) +} + +export interface ModEventEscalate { + comment?: string + [k: string]: unknown +} + +export function isModEventEscalate(v: unknown): v is ModEventEscalate { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventEscalate' + ) +} + +export function validateModEventEscalate(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventEscalate', v) +} + +/** Mute incoming reports on a subject */ +export interface ModEventMute { + comment?: string + /** Indicates how long the subject should remain muted. */ + durationInHours: number + [k: string]: unknown +} + +export function isModEventMute(v: unknown): v is ModEventMute { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventMute' + ) +} + +export function validateModEventMute(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventMute', v) +} + +/** Unmute action on a subject */ +export interface ModEventUnmute { + /** Describe reasoning behind the reversal. */ + comment?: string + [k: string]: unknown +} + +export function isModEventUnmute(v: unknown): v is ModEventUnmute { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventUnmute' + ) +} + +export function validateModEventUnmute(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventUnmute', v) +} + +/** Keep a log of outgoing email to a user */ +export interface ModEventEmail { + /** The subject line of the email sent to the user. */ + subjectLine: string + /** The content of the email sent to the user. */ + content?: string + /** Additional comment about the outgoing comm. */ + comment?: string + [k: string]: unknown +} + +export function isModEventEmail(v: unknown): v is ModEventEmail { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventEmail' + ) +} + +export function validateModEventEmail(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventEmail', v) +} + +/** Divert a record's blobs to a 3rd party service for further scanning/tagging */ +export interface ModEventDivert { + comment?: string + [k: string]: unknown +} + +export function isModEventDivert(v: unknown): v is ModEventDivert { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventDivert' + ) +} + +export function validateModEventDivert(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventDivert', v) +} + +/** Add/Remove a tag on a subject */ +export interface ModEventTag { + /** Tags to be added to the subject. If already exists, won't be duplicated. */ + add: string[] + /** Tags to be removed to the subject. Ignores a tag If it doesn't exist, won't be duplicated. */ + remove: string[] + /** Additional comment about added/removed tags. */ + comment?: string + [k: string]: unknown +} + +export function isModEventTag(v: unknown): v is ModEventTag { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#modEventTag' + ) +} + +export function validateModEventTag(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#modEventTag', v) +} + +export interface RepoView { + did: string + handle: string + email?: string + relatedRecords: {}[] + indexedAt: string + moderation: Moderation + invitedBy?: ComAtprotoServerDefs.InviteCode + invitesDisabled?: boolean + inviteNote?: string + [k: string]: unknown +} + +export function isRepoView(v: unknown): v is RepoView { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#repoView' + ) +} + +export function validateRepoView(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#repoView', v) +} + +export interface RepoViewDetail { + did: string + handle: string + email?: string + relatedRecords: {}[] + indexedAt: string + moderation: ModerationDetail + labels?: ComAtprotoLabelDefs.Label[] + invitedBy?: ComAtprotoServerDefs.InviteCode + invites?: ComAtprotoServerDefs.InviteCode[] + invitesDisabled?: boolean + inviteNote?: string + emailConfirmedAt?: string + [k: string]: unknown +} + +export function isRepoViewDetail(v: unknown): v is RepoViewDetail { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#repoViewDetail' + ) +} + +export function validateRepoViewDetail(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#repoViewDetail', v) +} + +export interface RepoViewNotFound { + did: string + [k: string]: unknown +} + +export function isRepoViewNotFound(v: unknown): v is RepoViewNotFound { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#repoViewNotFound' + ) +} + +export function validateRepoViewNotFound(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#repoViewNotFound', v) +} + +export interface RecordView { + uri: string + cid: string + value: {} + blobCids: string[] + indexedAt: string + moderation: Moderation + repo: RepoView + [k: string]: unknown +} + +export function isRecordView(v: unknown): v is RecordView { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#recordView' + ) +} + +export function validateRecordView(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#recordView', v) +} + +export interface RecordViewDetail { + uri: string + cid: string + value: {} + blobs: BlobView[] + labels?: ComAtprotoLabelDefs.Label[] + indexedAt: string + moderation: ModerationDetail + repo: RepoView + [k: string]: unknown +} + +export function isRecordViewDetail(v: unknown): v is RecordViewDetail { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#recordViewDetail' + ) +} + +export function validateRecordViewDetail(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#recordViewDetail', v) +} + +export interface RecordViewNotFound { + uri: string + [k: string]: unknown +} + +export function isRecordViewNotFound(v: unknown): v is RecordViewNotFound { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#recordViewNotFound' + ) +} + +export function validateRecordViewNotFound(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#recordViewNotFound', v) +} + +export interface Moderation { + subjectStatus?: SubjectStatusView + [k: string]: unknown +} + +export function isModeration(v: unknown): v is Moderation { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#moderation' + ) +} + +export function validateModeration(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#moderation', v) +} + +export interface ModerationDetail { + subjectStatus?: SubjectStatusView + [k: string]: unknown +} + +export function isModerationDetail(v: unknown): v is ModerationDetail { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#moderationDetail' + ) +} + +export function validateModerationDetail(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#moderationDetail', v) +} + +export interface BlobView { + cid: string + mimeType: string + size: number + createdAt: string + details?: + | ImageDetails + | VideoDetails + | { $type: string; [k: string]: unknown } + moderation?: Moderation + [k: string]: unknown +} + +export function isBlobView(v: unknown): v is BlobView { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#blobView' + ) +} + +export function validateBlobView(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#blobView', v) +} + +export interface ImageDetails { + width: number + height: number + [k: string]: unknown +} + +export function isImageDetails(v: unknown): v is ImageDetails { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#imageDetails' + ) +} + +export function validateImageDetails(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#imageDetails', v) +} + +export interface VideoDetails { + width: number + height: number + length: number + [k: string]: unknown +} + +export function isVideoDetails(v: unknown): v is VideoDetails { + return ( + isObj(v) && + hasProp(v, '$type') && + v.$type === 'tools.ozone.moderation.defs#videoDetails' + ) +} + +export function validateVideoDetails(v: unknown): ValidationResult { + return lexicons.validate('tools.ozone.moderation.defs#videoDetails', v) +} diff --git a/packages/pds/src/lexicon/types/tools/ozone/moderation/emitEvent.ts b/packages/pds/src/lexicon/types/tools/ozone/moderation/emitEvent.ts new file mode 100644 index 00000000000..e3f502bd2eb --- /dev/null +++ b/packages/pds/src/lexicon/types/tools/ozone/moderation/emitEvent.ts @@ -0,0 +1,68 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server' +import * as ToolsOzoneModerationDefs from './defs' +import * as ComAtprotoAdminDefs from '../../../com/atproto/admin/defs' +import * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef' + +export interface QueryParams {} + +export interface InputSchema { + event: + | ToolsOzoneModerationDefs.ModEventTakedown + | ToolsOzoneModerationDefs.ModEventAcknowledge + | ToolsOzoneModerationDefs.ModEventEscalate + | ToolsOzoneModerationDefs.ModEventComment + | ToolsOzoneModerationDefs.ModEventLabel + | ToolsOzoneModerationDefs.ModEventReport + | ToolsOzoneModerationDefs.ModEventMute + | ToolsOzoneModerationDefs.ModEventReverseTakedown + | ToolsOzoneModerationDefs.ModEventUnmute + | ToolsOzoneModerationDefs.ModEventEmail + | ToolsOzoneModerationDefs.ModEventTag + | { $type: string; [k: string]: unknown } + subject: + | ComAtprotoAdminDefs.RepoRef + | ComAtprotoRepoStrongRef.Main + | { $type: string; [k: string]: unknown } + subjectBlobCids?: string[] + createdBy: string + [k: string]: unknown +} + +export type OutputSchema = ToolsOzoneModerationDefs.ModEventView + +export interface HandlerInput { + encoding: 'application/json' + body: InputSchema +} + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'SubjectHasAction' +} + +export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/pds/src/lexicon/types/tools/ozone/moderation/getEvent.ts b/packages/pds/src/lexicon/types/tools/ozone/moderation/getEvent.ts new file mode 100644 index 00000000000..b583510a791 --- /dev/null +++ b/packages/pds/src/lexicon/types/tools/ozone/moderation/getEvent.ts @@ -0,0 +1,41 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server' +import * as ToolsOzoneModerationDefs from './defs' + +export interface QueryParams { + id: number +} + +export type InputSchema = undefined +export type OutputSchema = ToolsOzoneModerationDefs.ModEventViewDetail +export type HandlerInput = undefined + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string +} + +export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/pds/src/lexicon/types/tools/ozone/moderation/getRecord.ts b/packages/pds/src/lexicon/types/tools/ozone/moderation/getRecord.ts new file mode 100644 index 00000000000..a3832cd161c --- /dev/null +++ b/packages/pds/src/lexicon/types/tools/ozone/moderation/getRecord.ts @@ -0,0 +1,43 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server' +import * as ToolsOzoneModerationDefs from './defs' + +export interface QueryParams { + uri: string + cid?: string +} + +export type InputSchema = undefined +export type OutputSchema = ToolsOzoneModerationDefs.RecordViewDetail +export type HandlerInput = undefined + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'RecordNotFound' +} + +export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/pds/src/lexicon/types/tools/ozone/moderation/getRepo.ts b/packages/pds/src/lexicon/types/tools/ozone/moderation/getRepo.ts new file mode 100644 index 00000000000..853d6460e85 --- /dev/null +++ b/packages/pds/src/lexicon/types/tools/ozone/moderation/getRepo.ts @@ -0,0 +1,42 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server' +import * as ToolsOzoneModerationDefs from './defs' + +export interface QueryParams { + did: string +} + +export type InputSchema = undefined +export type OutputSchema = ToolsOzoneModerationDefs.RepoViewDetail +export type HandlerInput = undefined + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string + error?: 'RepoNotFound' +} + +export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/pds/src/lexicon/types/tools/ozone/moderation/queryEvents.ts b/packages/pds/src/lexicon/types/tools/ozone/moderation/queryEvents.ts new file mode 100644 index 00000000000..403e291fc81 --- /dev/null +++ b/packages/pds/src/lexicon/types/tools/ozone/moderation/queryEvents.ts @@ -0,0 +1,73 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server' +import * as ToolsOzoneModerationDefs from './defs' + +export interface QueryParams { + /** The types of events (fully qualified string in the format of tools.ozone.moderation.defs#modEvent) to filter by. If not specified, all events are returned. */ + types?: string[] + createdBy?: string + /** Sort direction for the events. Defaults to descending order of created at timestamp. */ + sortDirection: 'asc' | 'desc' + /** Retrieve events created after a given timestamp */ + createdAfter?: string + /** Retrieve events created before a given timestamp */ + createdBefore?: string + subject?: string + /** If true, events on all record types (posts, lists, profile etc.) owned by the did are returned */ + includeAllUserRecords: boolean + limit: number + /** If true, only events with comments are returned */ + hasComment?: boolean + /** If specified, only events with comments containing the keyword are returned */ + comment?: string + /** If specified, only events where all of these labels were added are returned */ + addedLabels?: string[] + /** If specified, only events where all of these labels were removed are returned */ + removedLabels?: string[] + /** If specified, only events where all of these tags were added are returned */ + addedTags?: string[] + /** If specified, only events where all of these tags were removed are returned */ + removedTags?: string[] + reportTypes?: string[] + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + events: ToolsOzoneModerationDefs.ModEventView[] + [k: string]: unknown +} + +export type HandlerInput = undefined + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string +} + +export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/pds/src/lexicon/types/tools/ozone/moderation/queryStatuses.ts b/packages/pds/src/lexicon/types/tools/ozone/moderation/queryStatuses.ts new file mode 100644 index 00000000000..188749411fc --- /dev/null +++ b/packages/pds/src/lexicon/types/tools/ozone/moderation/queryStatuses.ts @@ -0,0 +1,74 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server' +import * as ToolsOzoneModerationDefs from './defs' + +export interface QueryParams { + subject?: string + /** Search subjects by keyword from comments */ + comment?: string + /** Search subjects reported after a given timestamp */ + reportedAfter?: string + /** Search subjects reported before a given timestamp */ + reportedBefore?: string + /** Search subjects reviewed after a given timestamp */ + reviewedAfter?: string + /** Search subjects reviewed before a given timestamp */ + reviewedBefore?: string + /** By default, we don't include muted subjects in the results. Set this to true to include them. */ + includeMuted?: boolean + /** Specify when fetching subjects in a certain state */ + reviewState?: string + ignoreSubjects?: string[] + /** Get all subject statuses that were reviewed by a specific moderator */ + lastReviewedBy?: string + sortField: 'lastReviewedAt' | 'lastReportedAt' + sortDirection: 'asc' | 'desc' + /** Get subjects that were taken down */ + takendown?: boolean + /** Get subjects in unresolved appealed status */ + appealed?: boolean + limit: number + tags?: string[] + excludeTags?: string[] + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + subjectStatuses: ToolsOzoneModerationDefs.SubjectStatusView[] + [k: string]: unknown +} + +export type HandlerInput = undefined + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string +} + +export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput diff --git a/packages/pds/src/lexicon/types/tools/ozone/moderation/searchRepos.ts b/packages/pds/src/lexicon/types/tools/ozone/moderation/searchRepos.ts new file mode 100644 index 00000000000..7696df54d0f --- /dev/null +++ b/packages/pds/src/lexicon/types/tools/ozone/moderation/searchRepos.ts @@ -0,0 +1,51 @@ +/** + * GENERATED CODE - DO NOT MODIFY + */ +import express from 'express' +import { ValidationResult, BlobRef } from '@atproto/lexicon' +import { lexicons } from '../../../../lexicons' +import { isObj, hasProp } from '../../../../util' +import { CID } from 'multiformats/cid' +import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server' +import * as ToolsOzoneModerationDefs from './defs' + +export interface QueryParams { + /** DEPRECATED: use 'q' instead */ + term?: string + q?: string + limit: number + cursor?: string +} + +export type InputSchema = undefined + +export interface OutputSchema { + cursor?: string + repos: ToolsOzoneModerationDefs.RepoView[] + [k: string]: unknown +} + +export type HandlerInput = undefined + +export interface HandlerSuccess { + encoding: 'application/json' + body: OutputSchema + headers?: { [key: string]: string } +} + +export interface HandlerError { + status: number + message?: string +} + +export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough +export type HandlerReqCtx = { + auth: HA + params: QueryParams + input: HandlerInput + req: express.Request + res: express.Response +} +export type Handler = ( + ctx: HandlerReqCtx, +) => Promise | HandlerOutput