第七章 多平台消息网关
Hermes 不只是一个 CLI 工具——它还是一个消息路由平台,能同时对接 Telegram、Discord、Slack、WhatsApp 等 10+ 消息平台。核心是通过适配器模式实现统一的消息收发。
7.1 网关架构总览
gateway/run.py 是网关的中央调度器:
消息生命周期
7.2 平台适配器设计模式
所有平台适配器继承 BasePlatformAdapter(gateway/platforms/base.py):
MessageEvent 统一格式
python
@dataclass
class MessageEvent:
platform: str # "telegram", "discord", ...
chat_id: str # 平台特定的聊天 ID
user_id: str # 发送者 ID
content: str # 文本内容
media: List[MediaFile] # 附件(图片、音频、视频)
reply_to: str # 回复的消息 ID
thread_id: str # 线程/话题 IDSendResult 统一响应
python
@dataclass
class SendResult:
message_id: str # 发送后的消息 ID
success: bool # 是否成功
error: Optional[str] # 错误信息7.3 会话管理
gateway/session.py 负责跨平台的会话持久化。
SessionKey 构建
python
def build_session_key(source: SessionSource) -> str:
"""确定性的 session key: platform:chat_id[:thread_id]"""
parts = [source.platform, source.chat_id]
if source.thread_id:
parts.append(source.thread_id)
return ":".join(parts)示例:
- Telegram 群聊:
telegram:-1001234567890 - Discord 线程:
discord:123456:789012 - Slack DM:
slack:U12345
过期策略
| 策略 | 说明 |
|---|---|
| idle | 空闲 N 分钟后过期 |
| daily | 每日零点重置 |
| manual | 仅用户手动 /new 重置 |
PII 保护
支持的平台上,用户 ID 和聊天 ID 会被哈希处理:
python
def _redact_id(raw_id: str, platform: str) -> str:
"""哈希敏感 ID,避免日志泄露"""
if platform in ("telegram", "discord", "slack"):
return hashlib.sha256(raw_id.encode()).hexdigest()[:12]
return raw_id7.4 已支持平台详解
Telegram
- 格式化:MarkdownV2(自动转义特殊字符
_*[]()~等) - 特殊功能:照片连拍、内联键盘(Inline Keyboard)、语音备忘录自动转录
- Bot 菜单:自动从 COMMAND_REGISTRY 生成 BotCommand 列表
Discord
- 线程支持:回复到指定线程中
- Rich Embeds:代码块用 Embed 包裹,语法高亮
- Bot Mentions:
@Hermes触发处理
Slack
- 线程回复:在原消息线程中回复
- channel_skill_bindings:不同频道绑定不同技能
- Ephemeral 消息:系统提示只对用户可见
WhatsApp
- 多设备会话:支持 WhatsApp Web 协议
- 电话号码规范化:自动处理国际号码格式
- 媒体缓存:图片、语音、视频本地缓存后交给工具处理
企业平台
| 平台 | 适配器 | 特色功能 |
|---|---|---|
| 钉钉 (DingTalk) | dingtalk.py | Stream 模式、消息卡片 |
| 飞书 (Feishu) | feishu.py | 文档集成、消息卡片、事件订阅 |
| 企业微信 (WeCom) | wecom.py | 回调验证、加密消息、应用消息 |
| 微信 (WeChat) | weixin.py | 公众号消息 |
其他
- Signal:端到端加密,signal-cli 集成
- Matrix:支持 E2E 加密(mautrix)
- Email:IMAP 收件 + SMTP 发件
- SMS:通过 HTTP API 收发
- Home Assistant:智能家居控制
- Mattermost:开源 Slack 替代
7.5 添加新平台
以创建一个新平台 "MyChat" 为例:
步骤 1:创建适配器
python
# gateway/platforms/mychat.py
from gateway.platforms.base import BasePlatformAdapter, MessageEvent, SendResult
class MyChatAdapter(BasePlatformAdapter):
async def connect(self) -> bool:
"""连接到 MyChat API"""
# 初始化 SDK/WebSocket 连接
return True
async def disconnect(self) -> None:
"""断开连接"""
pass
async def send(self, chat_id: str, content: str, **kwargs) -> SendResult:
"""发送消息"""
# 调用 MyChat API 发送
return SendResult(message_id="...", success=True)
async def get_chat_info(self, chat_id: str) -> dict:
"""获取聊天信息"""
return {}步骤 2:注册消息回调
python
# 在 gateway/run.py 中添加
from gateway.platforms.mychat import MyChatAdapter
# 消息处理
async def on_mychat_message(self, event):
source = SessionSource(platform="mychat", chat_id=event.chat_id, ...)
await self._handle_message(source, event.content)步骤 3:配置
yaml
# ~/.hermes/config.yaml
mychat:
api_key: "..."
webhook_url: "..."源码导航:
- 网关主循环 →
gateway/run.py - 适配器基类 →
gateway/platforms/base.py - 会话管理 →
gateway/session.py - 平台实现 →
gateway/platforms/telegram.py、discord.py、slack.py等
下一章:第八章 TUI 终端界面