MessageWeave/docs/quickstart.zh-CN.md

9.5 KiB
Raw Blame History

1. 快速上手

英文:quickstart.md

本文是为人类运维者准备的从零开始指南:创建 Telegram bot、部署一个后端、填写配置页、注册回调、 收到第一条通知。只包含步骤与决策。字段语义、默认值、TTL 与错误码在 reference.md; 生产、扩展、网关运维在 deployment.md。

1.1 你需要准备什么

  • 一个你管理的 JMAP 邮箱(本指南以 Stalwart 为例),必须 HTTPS。
  • 一个 Telegram 账号。
  • 一个带持久化的 Redis 实例(Upstash 免费版可用;它是纯 TLS 的,URL 以 rediss:// 开头)。
  • 一台能跑容器并暴露一个 HTTP 端口的机器或平台。
  • 一个能接收 webhook 的公网 HTTPS 域名——自有域名、隧道或 Cloudflare 路由都行。Telegram 与 Stalwart 都要求 HTTPS。
  • 可选:OpenAI 兼容的 LLM 密钥;想要网关的话再来一个 Cloudflare 账号。

不需要别的:没有 Postgres、没有消息队列、没有 Kubernetes。

1.2 创建 Telegram bot

  1. 在 Telegram 中打开 @BotFather 的对话,发送 /newbot。
  2. 选一个显示名,再选一个以 bot 或 _bot 结尾的用户名。
  3. BotFather 会回复一串 token,形如 1234567890:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw1。 这就是 bot token。当成密码对待:拿到它的人能读取你的 webhook 流量、以你的 bot 身份发消息。 一旦保存,API 不再回显它。
  4. 用应当接收通知的账号或群给新 bot 发任意一条消息(例如 /start)。在此之前 Telegram 没有可投递 的对话。

1.3 找到 chat id

  1. 在浏览器打开 https://api.telegram.org/bot<TOKEN>/getUpdates,把 <TOKEN> 替换为第 3 步拿到的 token。
  2. 在 JSON 中找 result[].message.chat.id。私聊是正数,例如 123456789;群与超级群是负数,例如 -1001234567890。
  3. 如果是群:先把 bot 拉进群,再在群里发一条消息,然后才调 getUpdates。bot 在群里只有在关闭隐私模式 后才能看到非命令消息:@BotFather → /setprivacy → Disable。

这个 id 在第 7 步要用两次:一次当通知目标,一次放进入站白名单。白名单必须至少一个 id——空名单会被 判为非法配置而拒绝,不会当成「允许所有人」。

1.4 拿到 JMAP 凭据

  1. 在 Stalwart 管理端为邮箱创建一个应用密码——是应用密码,不是账号登录密码。后端用 HTTP Basic 走 JMAP。
  2. session URL 就是你的邮箱源站:https://mail.example.com。也可以粘贴 https://mail.example.com/.well-known/jmap;后端会把两者都折叠成源站,并拒绝带凭据、查询串或片段 的 URL。
  3. JMAP account id 是可选的。留空:首次保存成功后后端会从服务器读回,页面会显示出来。

1.5 跑起后端

容器只需要两个环境变量:

# .env — 不要提交这个文件
REDIS_URL=rediss://default:<password>@<host>:6379
CONFIG_ENCRYPTION_KEY=<64 位十六进制,用:openssl rand -hex 32>
  • REDIS_URL 是你唯一的状态存储。像数据库一样备份它。
  • CONFIG_ENCRYPTION_KEY 兼作 SPA 管理员凭据与已存业务密钥的加密密钥。丢了它,你既登不上配置页, 也解不开已存密钥;轮换它,之前存的密钥全部不可读。

然后构建并启动:

docker build -t messageweave .
docker run --rm --env-file .env -p 8080:8080 messageweave
curl localhost:8080/healthz   # → ok

GET /healthz 是静态存活回复,不碰 Redis。就绪报告是 GET /ready:在配置存在且所有已配置上游可达 之前回答 503,之后回答 200 并带一份 JSON 组件报告。现在把你的 HTTPS 反代或隧道指向这个端口——第 8、 9 步需要一个公网 HTTPS 域名。

1.6 登录配置页

  1. 在浏览器打开页面。如果后端带着所需变量启动,第一张卡是 Create admin session。
  2. 粘贴 CONFIG_ENCRYPTION_KEY——不是 Redis 密码。这会签发一个管理员会话,只活在页面内存里,有效期 30 分钟;刷新页面即登出。

1.7 填写业务配置

表单是整存整换,不是增量补丁:你提交的就是整份存储配置。各节:

  • 01 JMAP mailbox——session URL、用户名,以及第 4 步的应用密码。
  • 02 Telegram and access auth——bot token、通知 chat id、白名单,加上你自己生成的三个密钥:webhook 密钥、reconcile token 与 worker token。各自用 openssl rand -hex 32 生成。webhook 密钥之后要在 Telegram 侧对得上;reconcile 与 worker token 保护调度端点。
  • 03 LLM service——可选。不需要 AI 摘要就别开;一旦开启,HTTPS base URL、模型名与 API key 三者都 变成必填。
  • 04 Notification display——通知里收信时间的渲染时区。

然后按顺序:

  1. 点 Test connection。它预检凭据但不保存任何东西。
  2. 点 Save business config and hot-reload。首次保存必须包含所有必填字段,否则服务器回答 422 且 什么也不存。
  3. 读按钮下方那行结果:runtime_applied: true 表示新运行时已在本后端装配;false 表示存了但运行时未 装配,warnings 数组会指出失败的组件——最常见是 jmap_session_url 不可达。改字段再存一次;/ready 会一直 503 直到它变绿。
  4. 如果保存回答 409 conflict,说明有人(另一个标签页、第二个运维者)在中间也存了。刷新页面拿到 他们的值,再把你的改动重新套上去。

密钥是只写的:页面永不再显示已存密钥,提交空的密钥字段会保留之前的值——要清密钥就在单独一次编辑里 故意留空。

1.8 注册回调

仍在同一页,External callbacks 区:

  1. 粘贴能到达本后端的公网 HTTPS 源站,只写 scheme + host,不带路径——例如 https://mw.example.com。 如果你把 Cloudflare 网关放在前面,就填网关的源站,不是后端的:回调要能在后端重启后仍然可达,而 网关才是那个不掉线的。
  2. 点 Register callbacks。一次点击注册双向:Telegram webhook 注册到 /webhook/tg,Stalwart push 订阅注册到 /push/jmap。验证自动完成,页面上报结果。

注册是显式的、可重复的。注册新源站会取消上一个订阅,于是旧源站不再收到 push。失败的注册绝不会删掉 旧订阅——如果连不上 Telegram,上一个 webhook 原样留着;如果连上了 Telegram 但没连上 Stalwart,页面会 报部分失败并让你再点一次。

在终端验证:

curl -s "https://api.telegram.org/bot<TOKEN>/getWebhookInfo"
# 期望 "url": "https://mw.example.com/webhook/tg" 且 "pending_update_count": 0

1.9 打开处理开关

把页面顶部的 Enable business processing 拨开。这是总开关:关着时 webhook 照收,但 /worker 与 /reconcile 拒绝排空,所以什么也到不了 Telegram。打开后,入站邮件与消息才会进队列、由 worker 排空。

1.10 端到端验证

  1. 给自己发一封邮件。几秒内 bot 应当贴出一条通知,含发件人、主题与收信时间——绝不包含正文。这一条 路径同时证明 JMAP 入站、Redis、队列与 Telegram 发送全通。
  2. 在 Telegram 里试 /search 发票。注意:搜索触发词是中文 搜索、查找、检索,外加 /search 命令——search invoice 这类英文关键词不会被识别为触发。
  3. 从通知里的 email id 试 /summary <email_id>。首次调用会请求确认;只有你确认之后、且 LLM 节开启时, 摘要才会发出。

1.11 排程排空

Push 投递可能延迟或丢失;外部调度器是兜底。在任意一台能访问你源站的机器上,每 5–10 分钟跑一次:

MW_APP_URL=https://mw.example.com \
MW_WORKER_TOKEN=<worker token> \
MW_RECONCILE_TOKEN=<reconcile token> \
scripts/cron-drain.sh

脚本会排空队列(/worker)并重扫漏掉的 push(/reconcile);两者成功都回答 204 空 body。如果你把网关放 在前面,/worker 必须直达后端源站——原因见 deployment.md。

1.12 可选:Cloudflare 网关

除非你想跨两个后端做负载均衡,否则跳过。Worker 是可选的,给免费层 Cloudflare 用户提供一组负载均衡器, 不是安全层:无论用不用它,后端源站都保持可直接访问。安装见 cloudflare-worker/README.md;用时把第 8 步 的回调源站对准网关。

1.13 出问题时

  • 保存后什么也没到。 查处理开关(第 9 步),再查 getWebhookInfo(第 8 步)。last_error_message 里提到 401,说明 webhook 密钥与 Telegram 发来的不一致——重存 02 节并重新注册。
  • /ready 回 503。 503 的 body 只是一个错误码,不会指名是哪个组件挂了。/ready 回 200 时,JSON 里有逐组件布尔值(jmap、telegram、redis)。常见原因:jmap_session_url 不可达、应用密码错、或 上次保存 runtime_applied: false。
  • 表单提示冲突。 两个会话同时存了;刷新重做(第 7.3 步)。
  • bot 在群里不理你。 隐私模式开着;去 @BotFather 关掉(第 3 步)。
  • /search 回的是帮助提示。 你的查询以拉丁词开头;触发词是 搜索 / 查找 / 检索。

字段级错误、TTL、Redis 键与路由表:reference.md。 扩展、密钥轮换、网关与 cron 在线上的细节:deployment.md。