Mass Block [bsky] Reposts [and more]
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: util.parseArgs + slingshot actorResolver, drop 2 deps

- replace hand-rolled if-else CLI parser with node:util parseArgs
- replace identity-resolver packages with inline slingshot actorResolver
- drop @atcute/identity-resolver and @atcute/identity-resolver-node
- remove unused SCOPE constant

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Winter 0aca493a 1fc55d4c

+219 -49
+36 -47
index.js
··· 1 1 import { fileURLToPath } from "node:url"; 2 + import { parseArgs as nodeParseArgs } from "node:util"; 2 3 import { OAuthClient, MemoryStore } from "@atcute/oauth-node-client"; 3 - import { 4 - LocalActorResolver, 5 - CompositeDidDocumentResolver, 6 - PlcDidDocumentResolver, 7 - WebDidDocumentResolver, 8 - } from "@atcute/identity-resolver"; 9 - import { NodeDnsHandleResolver } from "@atcute/identity-resolver-node"; 10 4 import { Prompt } from "@clack/core"; 11 5 import * as p from "@clack/prompts"; 12 6 import color from "picocolors"; ··· 25 19 const BATCH_SIZE = 200; 26 20 const PAGE_SIZE = 100; 27 21 const PROFILE_BATCH_SIZE = 25; 28 - const SCOPE = "atproto repo:app.bsky.graph.block?action=create"; 29 22 30 23 const POST_CATEGORIES = /** @type {const} */ (["reposts", "replies", "likes", "quotes", "followers"]); 31 24 const PROFILE_CATEGORIES = /** @type {const} */ (["followers", "following"]); 32 25 const DUPLICATE_PATTERNS = ["duplicate", "already exists"]; 33 26 34 27 // ── CLI parsing ───────────────────────────────────────────────────── 35 - function getArgv() { 36 - if (IS_BUN) { 37 - const scriptIdx = Bun.argv.findIndex((a) => 38 - a.endsWith(".js") || a.endsWith(".ts") 39 - ); 40 - if (scriptIdx >= 0) return Bun.argv.slice(scriptIdx + 1); 41 - } 42 - return process.argv.slice(2); 43 - } 44 - 45 28 function parseArgs() { 46 - const args = getArgv(); 47 - const flags = {}; 48 - for (let i = 0; i < args.length; i++) { 49 - if (args[i] === "--delay" && args[i + 1]) { 50 - flags.delay = parseInt(args[++i], 10); 51 - } else if (args[i] === "--batch" && args[i + 1]) { 52 - flags.batch = parseInt(args[++i], 10); 53 - } else if (args[i] === "--dry-run") { 54 - flags.dryRun = true; 55 - } else if (args[i] === "--no-block-target") { 56 - flags.noBlockTarget = true; 57 - } else if (args[i] === "--output" && args[i + 1]) { 58 - flags.output = args[++i]; 59 - } else if (args[i] === "--unblock") { 60 - flags.unblock = true; 61 - } else if (args[i] === "--help" || args[i] === "-h") { 62 - flags.help = true; 63 - } 64 - } 65 - return { flags }; 29 + const argv = IS_BUN 30 + ? (() => { const i = Bun.argv.findIndex((a) => a.endsWith(".js") || a.endsWith(".ts")); return i >= 0 ? Bun.argv.slice(i + 1) : Bun.argv.slice(2); })() 31 + : process.argv.slice(2); 32 + 33 + const { values } = nodeParseArgs({ 34 + args: argv, 35 + options: { 36 + delay: { type: "string" }, 37 + batch: { type: "string" }, 38 + "dry-run": { type: "boolean" }, 39 + "no-block-target": { type: "boolean" }, 40 + output: { type: "string" }, 41 + unblock: { type: "boolean" }, 42 + help: { type: "boolean", short: "h" }, 43 + }, 44 + strict: false, 45 + }); 46 + 47 + return { 48 + flags: { 49 + delay: values.delay != null ? parseInt(values.delay, 10) : undefined, 50 + batch: values.batch != null ? parseInt(values.batch, 10) : undefined, 51 + dryRun: values["dry-run"], 52 + noBlockTarget: values["no-block-target"], 53 + output: values.output, 54 + unblock: values.unblock, 55 + help: values.help, 56 + }, 57 + }; 66 58 } 67 59 68 60 function printUsage() { ··· 540 532 redirect_uris: [REDIRECT_URI], 541 533 scope, 542 534 }, 543 - actorResolver: new LocalActorResolver({ 544 - handleResolver: new NodeDnsHandleResolver(), 545 - didDocumentResolver: new CompositeDidDocumentResolver({ 546 - methods: { 547 - plc: new PlcDidDocumentResolver(), 548 - web: new WebDidDocumentResolver(), 549 - }, 550 - }), 551 - }), 535 + actorResolver: { 536 + resolve: async (actor) => { 537 + const doc = await resolveMiniDoc(actor); 538 + return { did: doc.did, handle: doc.handle, pds: doc.pds }; 539 + }, 540 + }, 552 541 stores: { 553 542 sessions: new MemoryStore(), 554 543 states: new MemoryStore({ ttl: 600_000 }),
+183
package-lock.json
··· 1 + { 2 + "name": "block-reposters", 3 + "version": "1.0.0", 4 + "lockfileVersion": 3, 5 + "requires": true, 6 + "packages": { 7 + "": { 8 + "name": "block-reposters", 9 + "version": "1.0.0", 10 + "dependencies": { 11 + "@atcute/oauth-node-client": "^1.1.0", 12 + "@clack/core": "^0.4.1", 13 + "@clack/prompts": "^0.10.0" 14 + } 15 + }, 16 + "node_modules/@atcute/client": { 17 + "version": "4.2.1", 18 + "license": "0BSD", 19 + "dependencies": { 20 + "@atcute/identity": "^1.1.3", 21 + "@atcute/lexicons": "^1.2.6" 22 + } 23 + }, 24 + "node_modules/@atcute/identity": { 25 + "version": "1.1.4", 26 + "license": "0BSD", 27 + "dependencies": { 28 + "@atcute/lexicons": "^1.2.9", 29 + "@badrap/valita": "^0.4.6" 30 + } 31 + }, 32 + "node_modules/@atcute/identity-resolver": { 33 + "version": "1.2.2", 34 + "license": "0BSD", 35 + "dependencies": { 36 + "@atcute/lexicons": "^1.2.6", 37 + "@atcute/util-fetch": "^1.0.5", 38 + "@badrap/valita": "^0.4.6" 39 + }, 40 + "peerDependencies": { 41 + "@atcute/identity": "^1.0.0" 42 + } 43 + }, 44 + "node_modules/@atcute/lexicons": { 45 + "version": "1.3.0", 46 + "license": "0BSD", 47 + "dependencies": { 48 + "@atcute/uint8array": "^1.1.1", 49 + "@atcute/util-text": "^1.2.0", 50 + "@standard-schema/spec": "^1.1.0", 51 + "esm-env": "^1.2.2" 52 + } 53 + }, 54 + "node_modules/@atcute/multibase": { 55 + "version": "1.2.0", 56 + "license": "0BSD", 57 + "dependencies": { 58 + "@atcute/uint8array": "^1.1.1" 59 + } 60 + }, 61 + "node_modules/@atcute/oauth-crypto": { 62 + "version": "0.1.0", 63 + "license": "0BSD", 64 + "dependencies": { 65 + "@atcute/multibase": "^1.1.7", 66 + "@atcute/uint8array": "^1.1.0", 67 + "@badrap/valita": "^0.4.6", 68 + "nanoid": "^5.1.6" 69 + } 70 + }, 71 + "node_modules/@atcute/oauth-keyset": { 72 + "version": "0.1.0", 73 + "license": "0BSD", 74 + "dependencies": { 75 + "@atcute/oauth-crypto": "^0.1.0" 76 + } 77 + }, 78 + "node_modules/@atcute/oauth-node-client": { 79 + "version": "1.1.0", 80 + "license": "0BSD", 81 + "dependencies": { 82 + "@atcute/client": "^4.2.1", 83 + "@atcute/identity": "^1.1.3", 84 + "@atcute/identity-resolver": "^1.2.2", 85 + "@atcute/lexicons": "^1.2.7", 86 + "@atcute/oauth-crypto": "^0.1.0", 87 + "@atcute/oauth-keyset": "^0.1.0", 88 + "@atcute/oauth-types": "^0.1.1", 89 + "@atcute/util-fetch": "^1.0.5", 90 + "@badrap/valita": "^0.4.6", 91 + "nanoid": "^5.1.6" 92 + } 93 + }, 94 + "node_modules/@atcute/oauth-types": { 95 + "version": "0.1.1", 96 + "license": "0BSD", 97 + "dependencies": { 98 + "@atcute/identity": "^1.1.3", 99 + "@atcute/lexicons": "^1.2.7", 100 + "@atcute/oauth-keyset": "^0.1.0", 101 + "@badrap/valita": "^0.4.6" 102 + } 103 + }, 104 + "node_modules/@atcute/uint8array": { 105 + "version": "1.1.1", 106 + "license": "0BSD" 107 + }, 108 + "node_modules/@atcute/util-fetch": { 109 + "version": "1.0.5", 110 + "license": "0BSD", 111 + "dependencies": { 112 + "@badrap/valita": "^0.4.6" 113 + } 114 + }, 115 + "node_modules/@atcute/util-text": { 116 + "version": "1.2.0", 117 + "license": "0BSD", 118 + "dependencies": { 119 + "unicode-segmenter": "^0.14.5" 120 + } 121 + }, 122 + "node_modules/@badrap/valita": { 123 + "version": "0.4.6", 124 + "license": "MIT", 125 + "engines": { 126 + "node": ">= 18" 127 + } 128 + }, 129 + "node_modules/@clack/core": { 130 + "version": "0.4.2", 131 + "license": "MIT", 132 + "dependencies": { 133 + "picocolors": "^1.0.0", 134 + "sisteransi": "^1.0.5" 135 + } 136 + }, 137 + "node_modules/@clack/prompts": { 138 + "version": "0.10.1", 139 + "license": "MIT", 140 + "dependencies": { 141 + "@clack/core": "0.4.2", 142 + "picocolors": "^1.0.0", 143 + "sisteransi": "^1.0.5" 144 + } 145 + }, 146 + "node_modules/@standard-schema/spec": { 147 + "version": "1.1.0", 148 + "license": "MIT" 149 + }, 150 + "node_modules/esm-env": { 151 + "version": "1.2.2", 152 + "license": "MIT" 153 + }, 154 + "node_modules/nanoid": { 155 + "version": "5.1.7", 156 + "funding": [ 157 + { 158 + "type": "github", 159 + "url": "https://github.com/sponsors/ai" 160 + } 161 + ], 162 + "license": "MIT", 163 + "bin": { 164 + "nanoid": "bin/nanoid.js" 165 + }, 166 + "engines": { 167 + "node": "^18 || >=20" 168 + } 169 + }, 170 + "node_modules/picocolors": { 171 + "version": "1.1.1", 172 + "license": "ISC" 173 + }, 174 + "node_modules/sisteransi": { 175 + "version": "1.0.5", 176 + "license": "MIT" 177 + }, 178 + "node_modules/unicode-segmenter": { 179 + "version": "0.14.5", 180 + "license": "MIT" 181 + } 182 + } 183 + }
-2
package.json
··· 6 6 "start": "node index.js" 7 7 }, 8 8 "dependencies": { 9 - "@atcute/identity-resolver": "^1.2.2", 10 - "@atcute/identity-resolver-node": "^1.0.3", 11 9 "@atcute/oauth-node-client": "^1.1.0", 12 10 "@clack/core": "^0.4.1", 13 11 "@clack/prompts": "^0.10.0"