Skip to content

第七章 多平台消息网关

Hermes 不只是一个 CLI 工具——它还是一个消息路由平台,能同时对接 Telegram、Discord、Slack、WhatsApp 等 10+ 消息平台。核心是通过适配器模式实现统一的消息收发。

7.1 网关架构总览

gateway/run.py 是网关的中央调度器:

消息生命周期

7.2 平台适配器设计模式

所有平台适配器继承 BasePlatformAdaptergateway/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         # 线程/话题 ID

SendResult 统一响应

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_id

7.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.pyStream 模式、消息卡片
飞书 (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.pydiscord.pyslack.py

下一章:第八章 TUI 终端界面

基于 MIT 许可发布