5.5 KiB
TG Forwarder Operations 2026-09-21
容器挂载配置 (v4.5.4 修复后)
/home/openclaw/TelegramForwarder/docker-compose.yml 必须挂载两个目录:
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 端口)。
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
诊断命令 (容器内):
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():
await check_keywords(rule, check_message_text)— 用 keywords 表await client.forward_messages(target_chat_id, message_id, chat_id)— TG 原生转发- (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):
_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() 成功之后调用 (不是之前, 否则发不出):
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:
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) 二次过滤, 命中即跳过转发。
改完生效流程
# 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 |