322 lines
14 KiB
Markdown
322 lines
14 KiB
Markdown
# TamaBox 命令行操作手册(站方运维)
|
||
|
||
本项目**没有管理后台**:站方的全部运营动作只落在三类操作上 —— **CLI 命令 / 邮件告警 / 改配置后重启**。
|
||
这份文档只讲 CLI,覆盖处置、举报取证、批量隐藏与账号管理。
|
||
|
||
---
|
||
|
||
## 0. 前置
|
||
|
||
### 二进制从哪里来
|
||
|
||
```bash
|
||
# 仓库根目录构建(与 Dockerfile 是两条不同入口,命令列表必须双向同步)
|
||
go build -o tamabox .
|
||
|
||
# Docker 用的是这一条
|
||
go build -o NekoBox ./cmd/
|
||
```
|
||
|
||
两处都注册在同一份 `app.Commands` 列表中。**新增命令时必须同时改 `tamabox.go` 和 `cmd/tamabox.go`**,
|
||
否则会出现「本机二进制有、线上没有」(或反之),典型报错是 `No help topic for '<cmd>'`。
|
||
|
||
确认手头二进制包含全部命令:
|
||
|
||
```bash
|
||
./tamabox --help | sed -n '/COMMANDS/,/GLOBAL/p'
|
||
# web / censor / uid / ban / restore / reports / restrict / unrestrict / hide-public
|
||
```
|
||
|
||
### 配置文件
|
||
|
||
CLI 与 `web` 读同一份配置,路径由环境变量指定:
|
||
|
||
```bash
|
||
NEKOBOX_CONFIG_PATH=/path/to/app.ini ./tamabox reports --domain xxx
|
||
```
|
||
|
||
必要条件(缺失会直接启动失败):
|
||
|
||
- `app.external_url`
|
||
- `server.salt`、`server.xsrf_key`
|
||
- `[database]` 段的 type / host / port / user / password / name
|
||
|
||
⚠️ CLI 启动时会跑 **AutoMigrate**(与 web 相同)。这是特性也是风险:迁移有问题时连只读的
|
||
`reports` 都跑不起来。做重要操作前先 `pg_dump`。
|
||
|
||
### 操作前先备份
|
||
|
||
```bash
|
||
pg_dump -Fc <dbname> > before-$(date +%F-%H%M).dump
|
||
```
|
||
|
||
---
|
||
|
||
## 1. 命令总览
|
||
|
||
| 命令 | 作用 | 是否改数据 | 典型用途 |
|
||
|---|---|---|---|
|
||
| `reports` | 举报取证 / 待处理列表 / 全站统计 | 否 | 处置前看证据 |
|
||
| `restrict` | 施加处置(L1–L4) | 是 | 停止分发、冻结发布、停用页面 |
|
||
| `unrestrict` | 撤销全部生效中处置 | 是 | 解封、误操作回滚 |
|
||
| `hide-public` | 批量把公开回答转为私密 | 是 | 清理存量挂人内容 |
|
||
| `ban` | 永久封禁(删用户+内容) | 是(不可逆) | 严重违规账号 |
|
||
| `restore` | 恢复已停用账号 | 是 | 用户申诉后恢复 |
|
||
| `censor` | 重新审核历史内容 | 是 | 审核规则变更后复检 |
|
||
| `uid` | 为用户生成/补齐 uid | 是 | 数据修复 |
|
||
| `web` | 启动 Web 服务 | — | 生产入口 |
|
||
|
||
除 `reports` 外,所有写操作都要求交互式输入大写 `YES` 确认;脚本化时加 `--yes`。
|
||
|
||
---
|
||
|
||
## 2. `reports` —— 处置前的取证
|
||
|
||
三种互斥用法(`--stats` / `--pending` 优先于 `--email/--domain`)。
|
||
|
||
### 2.1 单个箱主的证据包
|
||
|
||
```bash
|
||
./tamabox reports --domain 52mxtx1314
|
||
./tamabox reports --email [email protected] --days 90 --limit 50
|
||
```
|
||
|
||
输出包含:
|
||
|
||
- **当前处置**:级别、到期时间、原因
|
||
- **近 N 天:被举报 X 条 / 公开回答 Y 条(累计,Z%);举报 W 次,其中待处理 V 次**
|
||
- **被举报条目**:按举报数降序,带题号、内容前 48 字与状态(`待处理 N` / `已处理`)
|
||
- **历史处置**:每条的时间、级别、原因、状态(生效中 / 已撤销 / 已到期)
|
||
|
||
口径(容易误读,务必看清):
|
||
|
||
- 分子 = 窗口内**被举报的条目数**(不是举报次数)。同一条被 5 个人举报只算 1 条。
|
||
- 分母 = 该箱主**当前累计**的公开回答数,**不是**窗口内产出。
|
||
所以 L2 收窄公开之后,分母会变小,比例可能超过 100% —— 这不是 bug,是分母口径问题。
|
||
判断「组织化挂人」时优先看**绝对条数**与**指涉对象分布**,比例只作参考。
|
||
- 已删除的提问不计入(`deleted_at IS NULL`)。
|
||
|
||
### 2.2 全站待处理举报
|
||
|
||
```bash
|
||
./tamabox reports --pending --limit 50
|
||
```
|
||
|
||
按箱主分组列出所有 `status = pending` 的举报(不受 30 天窗口限制,方便清理积压)。
|
||
|
||
### 2.3 全站维度统计(识别「举报被武器化」)
|
||
|
||
```bash
|
||
./tamabox reports --stats --days 7
|
||
```
|
||
|
||
输出两个 Top 10:
|
||
|
||
- **被举报最多的箱主**(含 domain / 昵称 / 待处理举报数)
|
||
- **举报来源 IP 最多**(同一 IP 反复举报同一批内容)
|
||
|
||
怎么读:
|
||
|
||
| 现象 | 更可能是 |
|
||
|---|---|
|
||
| 多个 IP 打同一个箱主,且内容指向多个不同对象 | 组织化挂人 |
|
||
| 少量 IP 打多个不同箱主 | 举报被武器化(报复性举报) |
|
||
| 同一 IP 单点爆发 | 脚本刷量(已由验证码 + 唯一索引限制) |
|
||
|
||
⚠️ 统计只覆盖**待处理**举报,且最长回溯 30 天(超期未处理的举报会自动退出统计池)。
|
||
|
||
### 2.4 举报计数的前提:客户端 IP
|
||
|
||
举报去重键是 `(question_id, reporter_ip)`,计数与统计全部依赖真实客户端 IP。
|
||
|
||
- 站点在反向代理 / CDN 之后时,**必须**在 `[security]` 配置 `trust_proxy = true`,
|
||
并按需配置 `trusted_proxies`。
|
||
- 若 `trust_proxy = false` 而站点实际在代理后,所有访客会被识别成同一个代理 IP →
|
||
每条内容最多只有 1 条举报,阈值告警永远不会触发。
|
||
- 验证方法:从两个不同网络各举报一次,然后 `reports --pending` 看是否出现两个不同 IP。
|
||
|
||
---
|
||
|
||
## 3. `restrict` —— 分级处置
|
||
|
||
```bash
|
||
./tamabox restrict --domain <domain> --level L1 --days 7 --reason "组织挂人投稿"
|
||
./tamabox restrict --email <email> --level L3 --days 14 --reason "复发" --yes
|
||
```
|
||
|
||
参数:
|
||
|
||
| 参数 | 说明 |
|
||
|---|---|
|
||
| `--domain` / `--email` | 二选一;都填时按 email 查 |
|
||
| `--level` | `L1` / `L2` / `L3` / `L4`,默认 L1,大小写敏感 |
|
||
| `--days` | 生效天数,从当前时间起算,必须 > 0 |
|
||
| `--reason` | **必填**,写入审计记录(**不会展示给用户**,只用于内部留痕) |
|
||
| `--yes` | 跳过 `YES` 确认 |
|
||
| `--force` | `--days` 超过 90 天时**必须**加,否则直接拒绝执行 |
|
||
| `--no-notify` | 不给箱主发处置通知邮件(默认发) |
|
||
|
||
### 异常时长与二次确认
|
||
|
||
`--days` 不设硬上限(长期封禁是真实需求),但超过 **90 天**时:
|
||
|
||
- 不加 `--force` → 直接报错退出(多打一个 0 不会被执行)
|
||
- 交互模式下还要**再输入一次级别名**(如 `L3`)才继续
|
||
- 脚本里 `--force --yes` 两个显式开关即构成两次确认
|
||
|
||
### 处置通知
|
||
|
||
处置生效后会自动给箱主发一封邮件(按箱主自己的界面语言,四语言齐全),内容只有:
|
||
|
||
- 级别与级别名称(如 L3 冻结发布)
|
||
- 到期时间
|
||
- 社区规则链接
|
||
- 申诉渠道(页脚「找站长」)
|
||
|
||
**邮件里不包含 `--reason` 原文,也不引用被举报内容** —— 沿用公告模板的口径:只写级别、期限、依据。
|
||
|
||
需要「静默止血」(不惊动对方、避免其转移阵地)时加 `--no-notify`。
|
||
|
||
邮件发送失败**不会回滚处置**:只打一条 warn 并在终端提示,处置仍然生效。
|
||
|
||
### 级别语义
|
||
|
||
| 级别 | 名称 | 实际效果 | 生效点 |
|
||
|---|---|---|---|
|
||
| **L1** | 停止分发 | 单题/整箱分享卡不可生成;从首页、探索、标签检索、随机位摘除;热门标签不再出现 | `share.go`、`users.go` |
|
||
| **L2** | 收窄公开 | L1 全部 + 新回答强制私密(单条 UPDATE 同时写回答与 `is_private`)+ 禁止「设为公开」+ 禁止回答追问 | `question.go`、`follow_up.go` |
|
||
| **L3** | 冻结发布 | L2 全部 + 禁止回答(**仍可收信**) | `question.go` |
|
||
| **L4** | 页面停用 | 整个 `/_/{domain}` 全部 302 到 `/restricted`(单题、私聊、分享卡、JSON 列表接口一并挡住) | `page.go` Pager + `ListAPI` |
|
||
|
||
设计要点:
|
||
|
||
- **L3 不禁收信**。伤害来自「发布」,剥夺收信能力没有治理收益,还会给对方「平台封口」的说法。
|
||
- **到期自动解除**:判定是 `expires_at > now()`,没有定时任务,也不需要手工解封。
|
||
- **替换语义**:同一用户再次 `restrict` 会先撤销旧的生效记录再写新的,任何时刻只有一条生效。
|
||
升级(L1→L3)与降级(L3→L1)都走这条路径。
|
||
- **处置期间审核严格度锁定为最高档**(`strict`),箱主无法自行改档;解禁后自动恢复他原本的设置
|
||
(`users.moderation_strictness` 全程未被改写)。
|
||
|
||
### 副作用(需要提前知道)
|
||
|
||
- 处置期间箱主在自己后台能看到橙色条幅(级别 + 到期日 + 规则页链接)。
|
||
- **L1 就强制 strict**:L1 只停分发、内容仍能发布,但审核已按最严处理,
|
||
正常的吐槽式提问也可能被拦。若线上发现大面积误拒,把 `moderation.EffectiveStrictness`
|
||
改成「L1 沿用原设置」即可(一行)。
|
||
- **处置会给箱主发通知邮件**(见上)。若用 `--no-notify` 跳过,箱主只剩登录后的橙色条幅。
|
||
- 邮件发送依赖 `[mail]` 段的 SMTP 配置;未配置时处置仍会生效,但终端会提示发送失败。
|
||
|
||
---
|
||
|
||
## 4. `unrestrict` —— 撤销
|
||
|
||
```bash
|
||
./tamabox unrestrict --domain <domain>
|
||
./tamabox unrestrict --email <email>
|
||
```
|
||
|
||
- 把该用户**所有生效中**的处置写 `revoked_at`(保留记录,不删除,审计可追溯)。
|
||
- 幂等:没有生效中处置时输出「没有生效中的处置,无需操作」。
|
||
- 撤销后:页面/发布/分享卡立即恢复;`hide-public` 已经转为私密的内容**不会**自动变回公开,
|
||
需要箱主自己逐条「设为公开」。
|
||
|
||
---
|
||
|
||
## 5. `hide-public` —— 清理存量内容
|
||
|
||
```bash
|
||
# 最推荐:只隐藏「有未处理举报」的公开回答
|
||
./tamabox hide-public --domain <domain> --only-reported
|
||
|
||
# 全部公开回答(激进的兜底)
|
||
./tamabox hide-public --domain <domain>
|
||
|
||
# 只处理最近 30 天
|
||
./tamabox hide-public --domain <domain> --only-reported --since 30
|
||
```
|
||
|
||
| 参数 | 说明 |
|
||
|---|---|
|
||
| `--only-reported` | 只处理有 `pending` 举报的题目 |
|
||
| `--since N` | 只处理最近 N 天创建的题目;0 = 不限 |
|
||
| `--yes` | 跳过确认 |
|
||
|
||
行为:
|
||
|
||
- 只动「公开且已回答」的题(`answer != '' AND is_private = false`),不碰私密与未回答。
|
||
- 执行前打印总数 + 最新 10 条预览。
|
||
- **可逆**:只改可见性,箱主可逐条改回公开(但该箱主处于 L2 及以上时改不回去)。
|
||
- 隐藏成功后自动把相关 `pending` 举报标记为 `accepted`,让它们退出告警统计池。
|
||
- 单独用它不足以「停止分发」,建议配合 `restrict --level L1`。
|
||
|
||
---
|
||
|
||
## 6. 账号管理(`ban` / `restore`)
|
||
|
||
```bash
|
||
# 永久封禁:物理删除用户与其内容,邮箱释放。不可恢复。
|
||
./tamabox ban --email [email protected] --yes
|
||
./tamabox ban --domain xxx --yes
|
||
|
||
# 恢复「自助停用」的账号(软删除行),可同时重置密码
|
||
./tamabox restore --email [email protected]
|
||
./tamabox restore --email [email protected] --password 'NewPassw0rd' --yes
|
||
```
|
||
|
||
两者的区别(涉及唯一索引,容易踩):
|
||
|
||
- **停用(可恢复)**:内容物理删除 + **用户行软删除**。邮箱/域名继续被占用是**有意为之**,
|
||
恢复靠 `restore`。
|
||
- **封禁(不可恢复)**:内容物理删除 + **用户行物理删除**,邮箱立即可重新注册。
|
||
- `restore --password` 必须在恢复之后执行,否则改不到(普通作用域查不到软删除行)。
|
||
|
||
---
|
||
|
||
## 7. 典型处置流程
|
||
|
||
1. **发现**:收到告警邮件(同一箱主 24h ≥ 8 条 或 7d ≥ 20 条)→ 或箱主后台出现「被举报 N 次」。
|
||
2. **取证**:`reports --domain <domain>` 看条目、占比、历史处置。
|
||
3. **冷静期**:举报后 24 小时内不作判定(避免被集中举报推着走,也避免情绪化处置)。
|
||
4. **止血**:`restrict --level L1 --days 7 --reason "..."`。默认会通知箱主;
|
||
若判断通知会导致其转移阵地、需要先静默收口,加 `--no-notify`。
|
||
5. **清存量**:`hide-public --domain <domain> --only-reported`。
|
||
6. **观察**:7 天内复发 → 升 L2/L3;双方互挂 → **两边同级别处理,不选边**。
|
||
7. **收尾**:到期自动解除;需要提前解封用 `unrestrict`。
|
||
8. **留痕**:`reports --domain <domain>` 的历史处置段落就是处置记录(谁、何时、级别、原因)。
|
||
|
||
判定「挂人」的三要件(同时成立才处理):
|
||
|
||
- **可识别性**:能让圈内人定位到具体账号/作品/主页(昵称、代称、@、外链、作品标签)
|
||
- **贬损或号召规避**:带「避雷/挂/别信/辱骂」这类定性,而不是中性描述
|
||
- **无公共利益**:纯私人纠纷、粉籍立场之争
|
||
|
||
只成立一两条 → 不处理或仅提示。
|
||
|
||
---
|
||
|
||
## 8. 排错
|
||
|
||
| 现象 | 原因 | 处理 |
|
||
|---|---|---|
|
||
| `No help topic for 'xxx'` | 构建入口不同步(根 `tamabox.go` vs `cmd/tamabox.go`) | 两处都注册后重新编译 |
|
||
| `find user: record not found` | `--domain` 填了昵称/登录名 | domain 是 URL 里的那一段,`/_/{domain}` |
|
||
| 处置后页面无变化 | 二进制是旧的 / 服务没重启 | `--help` 看命令在不在;抓线上 HTML 比对标记 |
|
||
| 待处理列表是空的 | 举报已被箱主处理(自动 accepted)或超过 30 天 | 正常;必要时直接查库 |
|
||
| 告警邮件一直没收到 | `[security] security_alert_email` 为空(静默跳过,无日志) | 配好并**重启** |
|
||
| 举报数始终是 1 | `trust_proxy` 未按部署环境配置,全部识别为代理 IP | 见 §2.4 |
|
||
| 箱主说「我改了但没生效」 | 处置期内严格度被锁定 / L2 禁止设为公开 | 看后台条幅;`reports` 查当前处置 |
|
||
| `--days 超过 90 天` 被拒绝 | 防手误设计,需要 `--force` | 确认时长后重试,或改用常规天数 |
|
||
| 处置成功但箱主说没收到邮件 | SMTP 未配 / 发送失败 / 用了 `--no-notify` | 看终端 warn;`[mail]` 配好后可 `restrict` 重发(同级别重设会替换记录) |
|
||
|
||
改完配置**必须重启**才生效(配置只在启动时读取一次)。
|
||
|
||
---
|
||
|
||
## 9. 明确不做的事
|
||
|
||
- **不做自动处置**:举报数达标只发邮件,不自动封禁。这个场景里举报本身就是攻击武器。
|
||
- **不做申诉后台**:申诉走邮件,处置结果由 CLI 写入。
|
||
- **不用配置文件当黑名单**:无法表达「N 天后自动解除」,最终会变成手工维护灾难。
|
||
- **不要在 CLI 之外直接改库**:`user_restrictions` 的写入必须带 `revoked_at` 语义,
|
||
手工 UPDATE 容易留下多条同时生效的记录(读取端会取最高级别,但不便于审计)。
|