4.0 KiB
TG Forwarder 排查+修复: 硬编码黑名单误杀 + chat_id 提取 bug + 频道切换 (2026-09-22 ~ 2026-09-24)
症状
用户报"监听频道要更新 / 现在交易信号都没转发了吗" → 排查发现 forwarder 一直在跑, 但日志显示:
[用户] 消息命中硬编码黑名单, 跳过转发
最终决定: 不转发
或
Got difference for channel 2651333064 updates (但 0 处理规则/消息内容日志)
根因 1: 硬编码黑名单误杀 (2026-09-22)
/app/handlers/user_handler.py 的 HARD_BLACKLIST_PATTERNS 含
r'(?i)usdt|cny|套现' 和裸 带单|指导|喊单|牛牛老师、\bVIP\b|\b老师\b。
所有信号都带 USDT (【币种】:BTCUSDT 永续) → 每条都命中 → 信号时有时无。
修复 (收窄正则):
# 修复前 (误杀)
r'(?i)usdt|cny|套现',
r'(?i)带单|指导|喊单|牛牛老师',
r'(?i)\bVIP\b|\b老师\b',
# 修复后
r'(?i)(usdt|cny)(?!永续|usdt).{0,4}套现|套现',
r'(?i)牛牛老师|喊单指导',
r'(?i)\bVIP群\b|付费指导',
改完必须 docker restart telegram-forwarder。
根因 2: chat_id 提取 bug (2026-09-24)
切换 source 到新频道 @shipan_jiankong 后, forwarder 收到 Got difference for channel 2651333064 updates (每15分钟轮询一次), 但完全没"消息内容/处理规则"日志。
/app/message_listener.py line 75-76:
chat = await event.get_chat()
chat_id = abs(chat.id) # 错! 剥掉了 -100 前缀
实际 telethon:
event.chat.id= 正数2651333064(Channel 对象剥了 -100)event.chat_id= 完整-1002651333064← 正确
DB 存 Chat.telegram_chat_id == '-1002651333064' 字符串, str(2651333064) 永远匹配不上 → Chat 查询 None → 早 return → 无日志。
后续 int(f"100{chat_id}") 二次覆盖更错 (应是 -100{...}), 但只在 state_manager.check_state() 为真时触发。
修复:
chat = await event.get_chat()
chat_id = event.chat_id # 用完整 -100xxxxxxxxxx
同时 Chat 查询加防御, 兼容两种格式 (防御性, 防止 chat_id 来源不一致时再次错):
_chat_id_str = str(chat_id)
if abs(chat_id) > 1e10 and not _chat_id_str.startswith('-100'):
_alt_id_str = f'-100{abs(chat_id) - 1e12}' if abs(chat_id) > 1e12 else f'-100{_chat_id_str}'
else:
_alt_id_str = f'100{_chat_id_str.lstrip("-")}'
source_chat = session.query(Chat).filter(
Chat.telegram_chat_id.in_([_chat_id_str, _alt_id_str, f'-100{_chat_id_str.lstrip("100")}'])
).first()
修改后必须 docker restart telegram-forwarder。
双频道区分 (易混, 别再装错)
| 频道 | chat_id | 标题 | 当前状态 |
|---|---|---|---|
| @shipan_jiankong | -1002651333064 | 币圈实盘监控 | 熬鹰 风寻 | ✅ 当前 source (chats.id=4) |
| @jiankongshipan | 3805472665 | 实盘监控 | ❌ 已停用, 记录保留 (chats.id=1) |
频道切换 SQL:
INSERT INTO chats (telegram_chat_id, name, current_add_id) VALUES ('-1002651333064', '币圈实盘监控 熬鹰 风寻', NULL);
UPDATE forward_rules SET source_chat_id = (SELECT id FROM chats WHERE telegram_chat_id='-1002651333064') WHERE id=1;
双白名单 AND 校验 (v4.5.4, 未动)
消息必须同时含交易员关键词 (麻吉/魏神/熬鹰/风寻/狙击手/百发百胜) + 信号类型 (开仓/平仓/加仓/减仓) 才转发。
排查手法 (套路)
- 规则库: 容器内
python3 -c "import sqlite3; ..."读/app/db/forward.db(chats/forward_rules/keywords 表) - session 被主进程锁 →
cp /app/sessions/user.session /tmp/xx.session再连 - 容器内连 TG 必带
proxy=('socks5','127.0.0.1',7891),request_retries=1+ timeout 防挂 - 容器内无 sqlite3 CLI, 用 python sqlite3 模块
- 验证消息实体存在:
async for m in c.iter_messages(username, limit=10) - 验证 chat.id vs chat_id 区别:
print(event.chat.id, event.chat_id) - 区分 telethon.channel.get_difference (轮询 update) vs message.NewMessage (新消息事件)
- 复现信号让用户从实际频道发一条, 看 docker logs --since 1m | grep 处理规则 是否命中