# 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 |