MessageWeave/docs/quickstart.zh-CN.md

178 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 1. 快速上手
英文:[quickstart.md](quickstart.md)
本文是为人类运维者准备的从零开始指南:创建 Telegram bot、部署一个后端、填写配置页、注册回调、
收到第一条通知。只包含步骤与决策。字段语义、默认值、TTL 与错误码在 [reference.md](reference.md);
生产、扩展、网关运维在 [deployment.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 跑起后端
容器只需要两个环境变量:
```bash
# .env — 不要提交这个文件
REDIS_URL=rediss://default:<password>@<host>:6379
CONFIG_ENCRYPTION_KEY=<64 位十六进制,用:openssl rand -hex 32>
```
- `REDIS_URL` 是你唯一的状态存储。像数据库一样备份它。
- `CONFIG_ENCRYPTION_KEY` 兼作 SPA 管理员凭据与已存业务密钥的加密密钥。丢了它,你既登不上配置页,
也解不开已存密钥;轮换它,之前存的密钥全部不可读。
然后构建并启动:
```bash
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,页面会
报部分失败并让你再点一次。
在终端验证:
```bash
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 分钟跑一次:
```bash
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](reference.md)。
扩展、密钥轮换、网关与 cron 在线上的细节:[deployment.md](deployment.md)。