Files

145 lines
5.5 KiB
Markdown

# TG Forwarder Operations 2026-09-21
## 容器挂载配置 (v4.5.4 修复后)
`/home/openclaw/TelegramForwarder/docker-compose.yml` 必须挂载两个目录:
```yaml
volumes:
- ./filters:/app/filters # 启用 is_original_time 修改生效
- ./handlers:/app/handlers # 修改 user_handler.py 生效 (转发+时间戳)
```
**背景**: 之前只挂了 `db`, `.env`, `logs`, `sessions`, `temp`, `config` 等, 没挂 `filters/` 和 `handlers/`。
容器内的 Python 文件是镜像内置, 不挂载 = 改主机版本无效。
## SOCKS5 代理坑 (v4.5.4 修复)
Mihomo 在主机监听:
- 7890 = **mixed-port** (HTTP/HTTPS only, 不接受 SOCKS5 握手)
- 7891 = **socks-port** (SOCKS5 raw TCP)
**Forwarder `main.py` 解析逻辑**: `HTTP_PROXY=http://127.0.0.1:7890` → 正则提取 host=127.0.0.1, port=7890 → **用 SOCKS5 协议连 7890** → 失败 (mixed-port 不识别 SOCKS5 握手) → `GeneralProxyError: Socket error: timed out`。
**修复**: 把所有 `HTTP_PROXY` / `HTTPS_PROXY` 改为 `127.0.0.1:7891` (SOCKS5 端口)。
```yaml
environment:
- HTTP_PROXY=http://127.0.0.1:7891
- HTTPS_PROXY=http://127.0.0.1:7891
- http_proxy=http://127.0.0.1:7891
- https_proxy=http://127.0.0.1:7891
```
**诊断命令** (容器内):
```bash
docker exec telegram-forwarder python3 -c "
import socks, socket
s = socks.socksocket()
s.set_proxy(socks.SOCKS5, '127.0.0.1', 7891)
s.settimeout(10)
try:
s.connect(('91.108.56.137', 443))
print('✅ SOCKS5 OK')
except Exception as e:
print(f'❌ {e}')
"
```
## 转发流程真相 (2026-09-21 验证)
**forwarder 实际不走 filter_chain**, 走 `handlers/user_handler.py:process_forward_rule()`:
1. `await check_keywords(rule, check_message_text)` — 用 keywords 表
2. `await client.forward_messages(target_chat_id, message_id, chat_id)` — **TG 原生转发**
3. (v4.5.4 后) `await client.send_message(target_chat_id, '⏱信号时间: ...')` — **追加时间戳**
⚠️ **`/app/filters/` 下的所有 filter (InfoFilter, KeywordFilter, SenderFilter...) 都是死代码** — `filter_chain` 是空链 (0 filter), 没人调用。要改转发行为只能改 `user_handler.py`。
⚠️ **`forward_messages()` 不支持附加文本** — TG API 限制, 只能转发原消息。要加文本必须**在转发后另外 send_message** (这就是 v4.5.4 的做法)。
## 时间戳方案 (v4.5.4)
用户偏好: 转发群每条消息后**追加 `⏱信号时间: {接收时刻}`**, 用 forwarder 接收时刻不用原消息时间。
**实现** (`/home/openclaw/TelegramForwarder/handlers/user_handler.py`):
```python
_TZ_SH = ZoneInfo("Asia/Shanghai")
def _build_time_stamp() -> str:
return datetime.now(_TZ_SH).strftime("%Y-%m-%d %H:%M:%S")
async def _send_time_stamp(client, target_chat_id, time_template):
ts = _build_time_stamp()
template = time_template or '⏱信号时间: {time}'
msg = template.replace("{time}", ts)
await client.send_message(target_chat_id, msg)
```
在 `forward_messages()` 成功**之后**调用 (不是之前, 否则发不出):
```python
await client.forward_messages(target_chat_id, event.message.id, event.chat_id)
if getattr(rule, 'is_original_time', False):
time_template = getattr(rule, 'time_template', None)
await _send_time_stamp(client, target_chat_id, time_template)
```
## 硬编码黑名单 (v4.5.4)
规则 1 是 `WHITELIST + .*` (匹配所有), `keywords` 表的黑名单条目在 WHITELIST 模式下**被忽略** (代码逻辑反转)。
要在不破坏现有规则下加广告过滤, 只能**硬编码**在 `user_handler.py`:
```python
HARD_BLACKLIST_PATTERNS = [
r'(?i)\bhttps?://(?!t\.me/)\S+', # 非 t.me 外链
r'(?i)加我私聊', # 拉私
r'(?i)进群(?!信号)', # 拉群
r'(?i)联系(我|客服|助理)',
r'(?i)带单|指导|喊单|牛牛老师',
r'(?i)免费(送|领|试用)',
r'(?i)代购|代充|充值优惠',
r'(?i)usdt\|cny\|套现',
r'(?i)\bVIP\b|\b老师\b',
]
def _hard_blacklist_hit(text: str) -> bool:
if not text: return False
for pattern in HARD_BLACKLIST_PATTERNS:
if re.search(pattern, text): return True
return False
```
**调用位置**: `check_keywords(rule, ...)` 通过后, 再 `_hard_blacklist_hit(message_text)` 二次过滤, 命中即跳过转发。
## 改完生效流程
```bash
# 1. 改主机文件
vim /home/openclaw/TelegramForwarder/handlers/user_handler.py
# 2. 重启容器 (自动用挂载的主机版)
cd /home/openclaw/TelegramForwarder
docker compose down && docker compose up -d
# 或: docker compose restart
# 3. 验证生效
docker exec telegram-forwarder grep "新代码关键字" /app/handlers/user_handler.py
```
## 不要做的
- ❌ 改 `info_filter.py` 期望生效 — filter_chain 没装载它
- ❌ 改 `keywords` 表加普通黑名单 — WHITELIST 模式忽略
- ❌ 用 `forward_messages()` 时附加文本 — TG API 不支持, 必用 send_message 单独发
- ❌ 把 SOCKS5 proxy 设为 7890 — mixed-port 不接 SOCKS5 握手, 必用 7891
- ❌ 假设 `is_filter_user_info=True` 时 check_message_text 包含发送者信息 — 它会变, 但不影响主流程
## 已废弃的做法 (历史)
| 做法 | 状态 | 原因 |
|------|------|------|
| filter_chain.InfoFilter 加时间戳 | ❌ 死代码 | filter_chain 0 filter |
| filter_chain.KeywordFilter 黑名单 | ❌ 死代码 | 同上 |
| 改 keywords 表加黑名单 | ❌ 被忽略 | WHITELIST 模式 |
| forward_messages 附加文本 | ❌ API 不支持 | 改用 send_message |
| HTTP_PROXY=7890 让 forwarder 出网 | ❌ SOCKS5 握手失败 | 改用 7891 |