diff --git a/definitions/labels.json b/definitions/labels.json new file mode 100644 index 0000000000..7252f40633 --- /dev/null +++ b/definitions/labels.json @@ -0,0 +1,170 @@ +[ + { + "identifier": "!hide", + "configurable": false, + "defaultSetting": "hide", + "flags": ["no-override", "no-self"], + "severity": "alert", + "blurs": "content", + "behaviors": { + "account": { + "profileList": "blur", + "profileView": "blur", + "avatar": "blur", + "banner": "blur", + "displayName": "blur", + "contentList": "blur", + "contentView": "blur" + }, + "profile": { + "avatar": "blur", + "banner": "blur", + "displayName": "blur" + }, + "content": { + "contentList": "blur", + "contentView": "blur" + } + } + }, + { + "identifier": "!warn", + "configurable": false, + "defaultSetting": "warn", + "flags": ["no-self"], + "severity": "none", + "blurs": "content", + "behaviors": { + "account": { + "profileList": "blur", + "profileView": "blur", + "avatar": "blur", + "banner": "blur", + "contentList": "blur", + "contentView": "blur" + }, + "profile": { + "avatar": "blur", + "banner": "blur", + "displayName": "blur" + }, + "content": { + "contentList": "blur", + "contentView": "blur" + } + } + }, + { + "identifier": "!no-unauthenticated", + "configurable": false, + "defaultSetting": "hide", + "flags": ["no-override", "unauthed"], + "severity": "none", + "blurs": "content", + "behaviors": { + "account": { + "profileList": "blur", + "profileView": "blur", + "avatar": "blur", + "banner": "blur", + "displayName": "blur", + "contentList": "blur", + "contentView": "blur" + }, + "profile": { + "avatar": "blur", + "banner": "blur", + "displayName": "blur" + }, + "content": { + "contentList": "blur", + "contentView": "blur" + } + } + }, + { + "identifier": "porn", + "configurable": true, + "defaultSetting": "hide", + "flags": ["adult"], + "severity": "none", + "blurs": "media", + "behaviors": { + "account": { + "avatar": "blur", + "banner": "blur" + }, + "profile": { + "avatar": "blur", + "banner": "blur" + }, + "content": { + "contentMedia": "blur" + } + } + }, + { + "identifier": "sexual", + "configurable": true, + "defaultSetting": "warn", + "flags": ["adult"], + "severity": "none", + "blurs": "media", + "behaviors": { + "account": { + "avatar": "blur", + "banner": "blur" + }, + "profile": { + "avatar": "blur", + "banner": "blur" + }, + "content": { + "contentMedia": "blur" + } + } + }, + { + "identifier": "nudity", + "configurable": true, + "defaultSetting": "ignore", + "flags": [], + "severity": "none", + "blurs": "media", + "behaviors": { + "account": { + "avatar": "blur", + "banner": "blur" + }, + "profile": { + "avatar": "blur", + "banner": "blur" + }, + "content": { + "contentMedia": "blur" + } + } + }, + { + "identifier": "graphic-media", + "alias": ["gore"], + "flags": ["adult"], + "configurable": true, + "defaultSetting": "warn", + "severity": "none", + "blurs": "media", + "behaviors": { + "account": { + "avatar": "blur", + "banner": "blur" + }, + "profile": { + "avatar": "blur", + "banner": "blur" + }, + "content": { + "contentMedia": "blur" + } + } + } +] diff --git a/package.json b/package.json index 0a8a4a642f..12ab82d8f5 100644 --- a/package.json +++ b/package.json @@ -56,11 +56,15 @@ "generate-webpack-stats-file": "EXPO_PUBLIC_GENERATE_STATS=1 yarn build-web", "open-analyzer": "EXPO_PUBLIC_OPEN_ANALYZER=1 yarn build-web", "icons:optimize": "svgo -f ./assets/icons", - "lexicons:sync": "rm -rf lexicons && degit bluesky-social/atproto/lexicons#main lexicons", - "lexicons:codegen": "lex gen-api --yes ./src/agent ./lexicons/com/atproto/*/* ./lexicons/app/bsky/*/* ./lexicons/chat/bsky/*/* ./lexicons/tools/ozone/*/* && prettier -w ./src/agent/**/*.*" + "lexicons:sync": "rm -rf lexicons definitions scripts/code scripts/generate-code.mjs && degit bluesky-social/atproto/lexicons#main lexicons && degit bluesky-social/atproto/packages/api/scripts#main scripts --force && degit bluesky-social/atproto/packages/api/definitions#main definitions", + "lexicons:codegen": "node node ./scripts/generate-code.mjs && lex gen-api --yes ./src/agent ./lexicons/com/atproto/*/* ./lexicons/app/bsky/*/* ./lexicons/chat/bsky/*/* ./lexicons/tools/ozone/*/* && eslint --fix && prettier -w ./src/agent/**/*.*" }, "dependencies": { "@atproto/api": "^0.15.3", + "@atproto/common-web": "^0.4.1", + "@atproto/lexicon": "^0.4.10", + "@atproto/syntax": "^0.4.0", + "@atproto/xrpc": "^0.6.12", "@bitdrift/react-native": "^0.6.8", "@braintree/sanitize-url": "^6.0.2", "@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet", diff --git a/scripts/code/labels.mjs b/scripts/code/labels.mjs new file mode 100644 index 0000000000..163589c1ff --- /dev/null +++ b/scripts/code/labels.mjs @@ -0,0 +1,74 @@ +import * as url from 'url' +import { readFileSync, writeFileSync } from 'fs' +import { join } from 'path' +import * as prettier from 'prettier' + +const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) + +const labelsDef = JSON.parse( + readFileSync( + join(__dirname, '..', '..', 'definitions', 'labels.json'), + 'utf8', + ), +) + +writeFileSync( + join(__dirname, '..', '..', 'src', 'moderation', 'const', 'labels.ts'), + await gen(), + 'utf8', +) + +async function gen() { + const knownValues = new Set() + const flattenedLabelDefs = [] + + for (const { alias: aliases, ...label } of labelsDef) { + knownValues.add(label.identifier) + flattenedLabelDefs.push([label.identifier, { ...label, locales: [] }]) + + if (aliases) { + for (const alias of aliases) { + knownValues.add(alias) + flattenedLabelDefs.push([ + alias, + { + ...label, + identifier: alias, + locales: [], + comment: `@deprecated alias for \`${label.identifier}\``, + }, + ]) + } + } + } + + let labelDefsStr = `{` + for (const [key, { comment, ...value }] of flattenedLabelDefs) { + const commentStr = comment ? `\n/** ${comment} */\n` : '' + labelDefsStr += `${commentStr}'${key}': ${JSON.stringify(value, null, 2)},` + } + labelDefsStr += `}` + + return prettier.format( + `/** this doc is generated by ./scripts/code/labels.mjs **/ + import {InterpretedLabelValueDefinition, LabelPreference} from '../types' + + export type KnownLabelValue = ${Array.from(knownValues) + .map((value) => `"${value}"`) + .join(' | ')} + + export const DEFAULT_LABEL_SETTINGS: Record = ${JSON.stringify( + Object.fromEntries( + labelsDef + .filter((label) => label.configurable) + .map((label) => [label.identifier, label.defaultSetting]), + ), + )} + + export const LABELS: Record = ${labelDefsStr} + `, + { semi: false, parser: 'typescript', singleQuote: true }, + ) +} + +export {} diff --git a/scripts/generate-code.mjs b/scripts/generate-code.mjs new file mode 100644 index 0000000000..bf182eb777 --- /dev/null +++ b/scripts/generate-code.mjs @@ -0,0 +1,3 @@ +import './code/labels.mjs' + +export {}