Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,11 @@ LOG_LEVEL=INFO
# Optional: generate with `uv run python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"`
# Keep this stable and backed up separately; changing it makes saved API keys unreadable.
AI_ENCRYPTION_KEY=

# Optional: enable the admin Compose profile with Telegram OIDC and these settings.
ADMIN_DATABASE_PATH=data/admin/access.db
ADMIN_TELEGRAM_IDS=
ADMIN_TELEGRAM_CLIENT_ID=
ADMIN_TELEGRAM_CLIENT_SECRET=
ADMIN_TELEGRAM_REDIRECT_URI=
ADMIN_SESSION_SECRET=
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ Remindly 的重要變更會記錄在這裡。

## Unreleased

- 後台人員權限:部署時以 `ADMIN_TELEGRAM_IDS` 指定管理者,登入後可新增/移除維護者;獨立 SQLite 保存白名單,移除後下次請求失效。人員列表顯示登入取得的名稱、管理者備註,以及名稱旁的帳號與 ID 藥丸。
- 群組共用 AI:管理員開放綁定、群組按鈕進私聊選既有 Key 授權、管理員確認啟用;僅引用指定 Key,支援撤銷、刪 Key 失效及群組內建解析降級(schema v10)。
- 解析問題回報:使用者可從提醒確認卡進私聊回報,先確認回報者資訊與選填附件,再送出。維護者可用 Telegram 登入後台,即時篩選並查看回報詳情(schema v12)。

## v0.5.0 - 2026-11-05

Expand Down
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@

- 💬 **缺漏資訊追問**:缺少資訊時主動追問;內建解析在日期明確但缺少時間時,提供 09:00、12:00、15:00、18:00 快捷按鈕。

- 🐛 **解析問題回報**:從確認卡進入 Bot 私聊回報,可選擇附上原句與解析結果;維護者可在後台查閱。

- 🛠️ **互動式提醒管理**:`/list` 依建立者分組,並支援今天、本週、我的、全部篩選。週期性提醒會以 `[重複]` 前綴標示。

- 👥 **群組與多人提醒**:支援私聊與群組,到期時可 mention 相關使用者。
Expand Down Expand Up @@ -196,6 +198,13 @@ Telegram 的指令選單點選 `/groupmode` 時可能會直接送出,這是正

若 BotFather 的 Group Privacy 沒關,bot 仍收不到一般群組訊息。請到 `@BotFather` 執行 `/setprivacy`,選擇 bot 後設為 `Disable`;若原本已在群組,必要時把 bot 移除後重新加入。

### 回報解析問題

在確認卡的「使用 … 解析」旁點「回報問題」,在 Bot 私聊選原因、預覽,再按「送出回報」。
只有草稿建立者可以回報,附件預設不附。附上時會先顯示實際送出的原句及解析結果,過長的欄位會截短。
送出前會提示將記錄 Telegram user ID 與帳號(如有設定 `@username`),供維護者在回報詳情查閱。
回報後仍可回到原聊天確認或取消提醒。請在草稿取消、確認或過期前送出。

## 部署

### 部署檢查清單
Expand Down Expand Up @@ -256,6 +265,32 @@ docker compose up -d --build

SQLite 會存在 named volume `remindly-data`,container 內 DB 路徑固定為 `/app/data/reminders.db`。

### 回報維護後台(選用)

1. 在 BotFather 的 Telegram 登入設定登記後台 HTTPS 網址與回呼 `https://你的後台網域/auth/telegram`,
保留預設 RS256 簽章。將回呼填入 `ADMIN_TELEGRAM_REDIRECT_URI`,並填入
`ADMIN_TELEGRAM_CLIENT_ID` 與 `ADMIN_TELEGRAM_CLIENT_SECRET`。登入密鑰由 BotFather 提供。
2. 將後台管理者的數字 Telegram user ID 以逗號分隔填入 `ADMIN_TELEGRAM_IDS`。
用 `uv run python -c "import secrets; print(secrets.token_urlsafe(32))"` 產生 `ADMIN_SESSION_SECRET`。
3. 用 HTTPS 反向代理將後台網域轉到部署主機的 `127.0.0.1:8081`,再從專案目錄啟動:

```sh
docker compose --profile admin up -d --build
```

維護者用 Telegram 帳號登入後,可依原因、解析來源、模型和 Bot 版本篩選回報,點原因開啟詳情。
後台管理者可在「人員權限」新增或移除維護者、編輯備註名稱;維護者只能查閱回報,不能管理人員。
人員列表顯示本人最近登入取得的 Telegram 名稱與帳號,以及數字 ID;尚未登入時以管理者備註辨識。
移除維護者後,下次請求即失去權限,已登入的 session 也一樣。
管理者只能由部署設定授予或撤銷,更新 `ADMIN_TELEGRAM_IDS` 後執行 `docker compose --profile admin up -d --no-deps --force-recreate remindly-admin`。
移除的管理者在新容器接手後失去管理權限;若也列為維護者,仍可查閱回報。
舊的 `MAINTAINER_TELEGRAM_IDS` 不再使用;既有維護者請由管理者在後台重新加入。
首次部署時若未設定管理者,將沒有人可以授予維護者權限。

人員白名單保存於獨立 SQLite,`ADMIN_DATABASE_PATH` 預設為 `data/admin/access.db`,
Compose 使用 `remindly-admin-data` volume 的 `/app/admin/access.db`,須與提醒資料庫分開備份。
回報資料庫仍唯讀掛載;後台無法透過人員管理修改提醒或 AI Key。

### GHCR 發布映像

正式版本映像使用 `ghcr.io/heitang/remindly`,提供 `linux/amd64` 與 `linux/arm64`。
Expand All @@ -277,6 +312,7 @@ services:

這是替換既有 service 的 `image` 設定;同時移除 `build` 與 `pull_policy: build`,
保留原本環境變數與 `remindly-data` volume。開發用 Compose 仍可從原始碼建置。
若啟用後台,`remindly-admin` 也使用相同的映像 digest,並移除其 `pull_policy: never`。
映像發布不觸發部署;升級前須另行備份資料庫及 AI 主金鑰,回滾也須確認 DB 相容性。

### SQLite 備份
Expand Down Expand Up @@ -347,6 +383,7 @@ Smoke test 會模擬:
| `src/remindly/storage/` | SQLite repository、session stores、versioned migrations。 |
| `src/remindly/telegram/` | Telegram Bot API client 與 DTO。 |
| `src/remindly/app.py` | Composition root,組裝 dependencies 並啟動 polling/scheduler。 |
| `src/remindly/admin.py` | 維護後台、Telegram 登入與回報查詢。 |

### GitOps 流程

Expand All @@ -356,7 +393,7 @@ main -> dev -> feature/<name> -> PR -> dev -> PR -> main

Feature branch 合併到 `dev` 必須開 PR;`dev` 驗證通過後再以 release PR 合併回 `main`。

Runtime 新增 `cryptography` 供 Key 加密。更新 runtime dependencies 後同步 Docker 安裝清單:
更新 runtime dependencies 後同步 Docker 安裝清單:

```sh
uv export --locked --no-dev --no-emit-project --format requirements-txt --output-file requirements.txt
Expand Down
25 changes: 25 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,31 @@ services:
restart: unless-stopped
stop_grace_period: 15s

remindly-admin:
profiles: [admin]
image: remindly:local
pull_policy: never
init: true
depends_on:
- remindly
command: ["gunicorn", "--bind", "0.0.0.0:8081", "remindly.admin:create_app()"]
environment:
DATABASE_PATH: /app/data/reminders.db
ADMIN_DATABASE_PATH: /app/admin/access.db
ADMIN_TELEGRAM_IDS: ${ADMIN_TELEGRAM_IDS:-}
ADMIN_TELEGRAM_CLIENT_ID: ${ADMIN_TELEGRAM_CLIENT_ID:-}
ADMIN_TELEGRAM_CLIENT_SECRET: ${ADMIN_TELEGRAM_CLIENT_SECRET:-}
ADMIN_TELEGRAM_REDIRECT_URI: ${ADMIN_TELEGRAM_REDIRECT_URI:-}
ADMIN_SESSION_SECRET: ${ADMIN_SESSION_SECRET:-}
volumes:
- remindly-data:/app/data:ro
- remindly-admin-data:/app/admin
ports:
- "127.0.0.1:8081:8081"
restart: unless-stopped

volumes:
remindly-admin-data:
name: remindly-admin-data
remindly-data:
name: remindly-data
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ description = "Remindly"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"authlib>=1.7,<2",
"cryptography>=46,<47",
"flask>=3.1,<4",
"gunicorn>=23,<27",
"joserfc>=1.6,<2",
"requests>=2.32.4,<3",
]

[build-system]
Expand Down
Loading
Loading