Files
Hermes-Skills/okx-auto-position/references/tg-forwarder-troubleshoot-2026-09-22-to-24.md

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 处理规则 是否命中