/ clis / tiktok / unlike.js
unlike.js
 1  import { cli } from '@jackwener/opencli/registry';
 2  cli({
 3      site: 'tiktok',
 4      name: 'unlike',
 5      description: 'Unlike a TikTok video',
 6      domain: 'www.tiktok.com',
 7      args: [
 8          { name: 'url', required: true, positional: true, help: 'TikTok video URL' },
 9      ],
10      columns: ['status', 'likes', 'url'],
11      pipeline: [
12          { navigate: { url: '${{ args.url }}', settleMs: 6000 } },
13          { evaluate: `(async () => {
14    const url = \${{ args.url | json }};
15    const btn = document.querySelector('[data-e2e="like-icon"]');
16    if (!btn) throw new Error('Like button not found - make sure you are logged in');
17    const container = btn.closest('button') || btn.closest('[role="button"]') || btn;
18    const aria = (container.getAttribute('aria-label') || '').toLowerCase();
19    const color = window.getComputedStyle(btn).color;
20    const isLiked = aria.includes('unlike') || aria.includes('取消点赞') ||
21                    (color && (color.includes('255, 65') || color.includes('fe2c55')));
22    if (!isLiked) {
23      const count = document.querySelector('[data-e2e="like-count"]');
24      return [{ status: 'Not liked', likes: count ? count.textContent.trim() : '-', url: url }];
25    }
26    container.click();
27    await new Promise(r => setTimeout(r, 2000));
28    const count = document.querySelector('[data-e2e="like-count"]');
29    return [{ status: 'Unliked', likes: count ? count.textContent.trim() : '-', url: url }];
30  })()
31  ` },
32      ],
33  });