unblock.js
1 import { CommandExecutionError } from '@jackwener/opencli/errors'; 2 import { cli, Strategy } from '@jackwener/opencli/registry'; 3 cli({ 4 site: 'twitter', 5 name: 'unblock', 6 description: 'Unblock a Twitter user', 7 domain: 'x.com', 8 strategy: Strategy.UI, 9 browser: true, 10 args: [ 11 { name: 'username', type: 'string', positional: true, required: true, help: 'Twitter screen name (without @)' }, 12 ], 13 columns: ['status', 'message'], 14 func: async (page, kwargs) => { 15 if (!page) 16 throw new CommandExecutionError('Browser session required for twitter unblock'); 17 const username = kwargs.username.replace(/^@/, ''); 18 await page.goto(`https://x.com/${username}`); 19 await page.wait({ selector: '[data-testid="primaryColumn"]' }); 20 const result = await page.evaluate(`(async () => { 21 try { 22 let attempts = 0; 23 let unblockBtn = null; 24 25 while (attempts < 20) { 26 // Check if not blocked (follow button visible means not blocked) 27 const followBtn = document.querySelector('[data-testid$="-follow"]'); 28 if (followBtn) { 29 return { ok: true, message: 'Not blocking @${username} (already unblocked).' }; 30 } 31 32 unblockBtn = document.querySelector('[data-testid$="-unblock"]'); 33 if (unblockBtn) break; 34 35 await new Promise(r => setTimeout(r, 500)); 36 attempts++; 37 } 38 39 if (!unblockBtn) { 40 return { ok: false, message: 'Could not find Unblock button. Are you logged in?' }; 41 } 42 43 // Click the unblock button — this opens a confirmation dialog 44 unblockBtn.click(); 45 await new Promise(r => setTimeout(r, 1000)); 46 47 // Confirm the unblock in the dialog 48 const confirmBtn = document.querySelector('[data-testid="confirmationSheetConfirm"]'); 49 if (confirmBtn) { 50 confirmBtn.click(); 51 await new Promise(r => setTimeout(r, 1000)); 52 } 53 54 // Verify 55 const verify = document.querySelector('[data-testid$="-follow"]'); 56 if (verify) { 57 return { ok: true, message: 'Successfully unblocked @${username}.' }; 58 } else { 59 return { ok: false, message: 'Unblock action initiated but UI did not update.' }; 60 } 61 } catch (e) { 62 return { ok: false, message: e.toString() }; 63 } 64 })()`); 65 if (result.ok) 66 await page.wait(2); 67 return [{ 68 status: result.ok ? 'success' : 'failed', 69 message: result.message 70 }]; 71 } 72 });