SuperAPI AI Directory

wjs-cleaning-spam

General & other

View repository

Updated 10-15 23:32

About this skill

wjs-cleaning-spam

Clean up the local-traffic spam replies hanging under Wang Jianshuo's tweets:Hide reply + mute account。

Core Principle

You can't delete someone else's tweet. X only gives the thread owner two weapons: hide reply (removes it from the comment section, invisible to visitors) and mute (no longer appears in notifications).The block endpoint has been taken offline by X from the API(v2 returns code 34, v1.1 requires a higher access level), so if you really want to block, you can only do it manually on the web. "Delete spam" = hide + mute, reaching the API's limit.

Dry-run first, human-review borderline, then apply. The heuristic will misclassify real human comments ("机器人🤖", "저지능🤪") and spam variants ("我在济源呀🌷" + invisible characters) on the wrong side. Flagged ones are handled directly; borderline ones must be looked at one by one by Claude.

Workflow

# 1. dry-run:输出 flagged + borderline 两个名单(JSON)
python3 ~/.claude/skills/wjs-cleaning-spam/scripts/clean_spam.py

# 2. Claude 逐条审 borderline:引流号特征 = 名字带 💕🌸♥ 装饰 / 同城话术 /
#    文本夹隐形字符(U+034F 等)/ 纯 emoji。真人评论(哪怕是骂人)不动。
#    把 borderline 里确认是 spam 的 id 并入名单。
3. apply: hide + mute (by default only handles flagged; after reviewing borderline, use --ids to specify the full set)

python3 ~/.claude/skills/wjs-cleaning-spam/scripts/clean_spam.py --apply python3 ~/.claude/skills/wjs-cleaning-spam/scripts/clean_spam.py --apply --ids id1,id2,...

4. Hit a 429 rate limit (hide is about 50 times/15 minutes) and the script will stop automatically — rerun the same command after 15 minutes, state/cleaned.jsonl records the processed ids, automatically skips them, and resumes.

向用户汇报:隐藏几条、失败几条(及原因)、静音几个号;提醒 block 需网页手动。

## 踩过的坑(2026-06-10 实战)

| 坑 | 现实 |
|----|------|
| raw 查询 401 Unauthorized | query 参数里的 `:` 必须 URL 编码(`to%3Ajianshuo`),不是 auth 问题,别去换 oauth1/oauth2 |
| `xurl block` 报 code 34 | block 端点已从 X API 移除(v2/v1.1 都不行),用 mute 替代,别反复试 |
| hide 报 "Invalid Request" | 该回复所在会话的根推文不是用户的(用户只是参与别人的串),串主才有权隐藏——记为 hide-failed,账号照样静音 |
| hide 报 429 | 限流约 50 次/15 分钟,等窗口刷新重跑脚本即可(状态文件保证幂等) |
| 纯文本 spam 漏网 | "我在济源呀" 这类同城话术靠隐形字符(U+034F/零宽符)混过滤器——脚本已检测,新变体出现时把特征加进 `NAME_KW` / `INVISIBLE` |
| 误伤真人 | emoji 启发式会扫进真人短评——这就是 borderline 名单存在的原因,必须人审 |

## When NOT to use

- spam 超过 7 天:recent-search 接口只覆盖 7 天,更早的要用网页手动
- 用户要删**自己发的**推文:直接 `xurl delete POST_ID`
- 用户要拉黑某个具体账号:API 做不到,告诉他网页操作(账号主页 ⋯ → Block)

## State

`state/cleaned.jsonl` — 每条处理过的回复一行(id / author / status)。重跑跳过已处理;想重头来删掉此文件。