UNPKG

auron

Version:

Interact with your ATProto labeler from your terminal

158 lines (144 loc) 4.58 kB
import { Command } from "commander"; import { database } from "../services/db"; import { withLoader } from "../utils/loader"; import { fetchProfilesForSubjects, fetchQueueItems, fetchRecordsForSubjects, fetchReposForSubjects, processSubjects, saveQueueItems, } from "../controllers/queue"; import { writeCsvFile, writeJsonFile } from "../services/file"; export const queueCommand = new Command("queue"); queueCommand .command("sync") .option( "-n, --count <number>", "Max number of items from the queue to sync", (value) => parseInt(value, 10), 100 ) .option("--cursor <string>", "Cursor to start fetching from") .option("-t, --takendown", "Only sync takendown subjects") .option( "--reviewState <string>", "Items in specific review state to be synced" ) .option( "--data-only", "Only fetch record and repo data, without syncing queue items" ) .description("Fetch your ozone queue and store it in the local database") .action( async (options: { count: number; cursor?: string; dataOnly?: boolean; reviewState?: string; takendown?: boolean; }) => { if (!options.dataOnly) { const subjects = await fetchQueueItems(options); await saveQueueItems(subjects); } await fetchReposForSubjects(); await fetchRecordsForSubjects(); // await fetchProfilesForSubjects(); } ); const addSubjectListOptions = (command: Command): Command => { return command .option( "-n, --count <number>", "Max number of items from the queue", (value) => parseInt(value, 10) ) .option( "-t, --type <type>", "Subject type filter, account or record", (value) => { if (value && value !== "account" && value !== "record") { throw new Error( 'Invalid type. Allowed values are "account" or "record".' ); } return value; } ) .option( "--bio <keyword/text>", "Keyword to be matched in profile bio of subject" ) .option( "--keyword <keyword/text>", "Keyword to be matched anywhere in the profile bio/record content etc." ) .option( "--email <text/regex>", "Text or regex to be matched anywhere in the email address of the author." ) .option( "--columns <string>", "Comma separated names of columns to include in the output" ) .option( "--riskScore <number>", "Risk Score from threat signature filter", (value) => parseFloat(value) ) .option("--lastCountry <string...>", "Last signin country of the user") .option("-td, --takendown", "Only use takendown subjects") .option("--cursor <string>", "Cursor to start fetching from"); }; addSubjectListOptions(queueCommand.command("export")) .description("Export queue from your local database") .requiredOption("-f, --file <file>", "Export file path") // Make the file option required .action(async (options) => { withLoader(`Exporting queue items...`, async (updateMessage) => { const subjects = await processSubjects(options); if (subjects.length === 0) { updateMessage(`No queue items found`); return; } updateMessage( `Found ${subjects.length} queue items. Exporting to ${options.file}` ); if (options.file.endsWith(".csv")) { const mapped = subjects.map((sub) => { const { profile, ...rest } = sub; return { ...rest, name: sub.profile?.displayName || "", }; }); await writeCsvFile(options.file, mapped); } else { await writeJsonFile(options.file, subjects); } const lastItem = subjects[subjects.length - 1]; updateMessage( `${subjects.length} queue items exported to ${options.file}. Cursor: ${lastItem.lastReportedAt}` ); }); }); addSubjectListOptions(queueCommand.command("pipe")) .description("Output 1 item at a time from your queue to stdout") .action(async (options) => { const subjects = await processSubjects(options); if (subjects.length === 0) { return; } for (const subject of subjects) { console.log(JSON.stringify(subject)); } }); queueCommand .command("clear") .description("Clear your locally stored queue") .action(async () => { withLoader(`Clearing queue items...`, async (logMessage) => { await database.clearSubjects(); logMessage("Queue items cleared from the database"); }); });