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

Configure Feed

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

feat: add profile mode to interactive flow, merge followers into category selector

Winter 825eecf3 7dcbaa1f

+14 -13
+14 -13
index.js
··· 24 24 const PROFILE_BATCH_SIZE = 25; 25 25 const SCOPE = "atproto repo:app.bsky.graph.block?action=create"; 26 26 27 - const CATEGORIES = /** @type {const} */ (["reposts", "replies", "likes"]); 27 + const POST_CATEGORIES = /** @type {const} */ (["reposts", "replies", "likes", "followers"]); 28 + const PROFILE_CATEGORIES = /** @type {const} */ (["followers", "following"]); 28 29 const DUPLICATE_PATTERNS = ["duplicate", "already exists"]; 29 30 30 31 // ── CLI parsing ───────────────────────────────────────────────────── ··· 432 433 433 434 // ── interactive flow ──────────────────────────────────────────────── 434 435 async function runInteractiveFlow() { 435 - p.intro(color.inverse(" bluesky post blocker ")); 436 + p.intro(color.inverse(" bluesky blocker ")); 436 437 437 - const postUrl = exitIfCancelled(await p.text({ 438 - message: "paste the post URL or at:// URI", 438 + const url = exitIfCancelled(await p.text({ 439 + message: "paste a post URL, profile URL, or at:// URI", 439 440 placeholder: "https://bsky.app/profile/someone.bsky.social/post/abc123", 440 441 validate: (v) => { 441 442 if (!v) return "url is required"; 442 - if (!v.includes("/post/") && !v.startsWith("at://")) 443 - return "doesn't look like a post url"; 443 + if (v.startsWith("at://")) return; 444 + if (v.includes("/post/")) return; 445 + if (v.includes("/profile/")) return; 446 + return "paste a post URL (…/post/…), a profile URL (…/profile/…), or an at:// URI"; 444 447 }, 445 448 })); 446 449 450 + const mode = isProfileUrl(url) ? "profile" : "post"; 451 + const categoryList = mode === "post" ? POST_CATEGORIES : PROFILE_CATEGORIES; 452 + 447 453 const categories = exitIfCancelled(await inlineMultiSelect({ 448 454 message: "what do you want to block?", 449 - options: CATEGORIES.map((c) => ({ value: c, label: c })), 450 - })); 451 - 452 - const blockAuthorFollowers = exitIfCancelled(await p.confirm({ 453 - message: "also block the post author's followers?", 454 - initialValue: false, 455 + options: categoryList.map((c) => ({ value: c, label: c })), 455 456 })); 456 457 457 458 const blockFollowing = exitIfCancelled(await p.confirm({ ··· 465 466 validate: (v) => { if (!v) return "handle is required"; }, 466 467 })); 467 468 468 - return { postUrl, categories, blockAuthorFollowers, blockFollowing, handle }; 469 + return { url, mode, categories, blockFollowing, handle }; 469 470 } 470 471 471 472 // ── data fetching ───────────────────────────────────────────────────