feat: AI 余额监控服务(平台/账号 CRUD、并发轮询、Telegram 阈值提醒)

This commit is contained in:
2026-08-04 23:51:06 +08:00
commit 17d2496a65
20 changed files with 2690 additions and 0 deletions
+108
View File
@@ -0,0 +1,108 @@
# AI Balance Monitor
纯 Python 的多平台 AI 余额监控服务。自定义平台、自定义账号、Telegram 阈值提醒。
## 功能
- **自定义平台**HTTP 请求(GET/POST)、URL / Headers / Body 模板、`{{apiKey}}` 占位符嵌入、JSON 余额提取路径(支持 `data.balance``data[0].balance`)、货币单位、图标(@lobehub/icons 键)、监控间隔覆盖
- **账号管理**:每个平台下任意账号,API Key 以 Base64 存储
- **监控调度**:全局默认间隔 + 平台级覆盖,线程池并发轮询
- **失败处理**:网络错误/5xx 自动重试(默认 2 次),仍失败则跳过并记录;401/403 自动禁用该账号并通知
- **Telegram 提醒**:余额低于阈值提醒一次,恢复到阈值以上发恢复消息后重新武装;认证失败禁用也通知
- **余额历史**:每次拉取自动记录,界面可查看趋势
- **完整增删改**:平台 / 账号 / 设置均可通过界面或 REST API 管理
- **面板登录**:单密码保护,Token 有效期 7 天
## 快速开始
```bash
# 1. 安装依赖
python -m venv .venv
.venv\Scripts\pip install -r requirements.txt
# 2. 修改配置(可选)
# config.json:端口、密码、全局间隔、Telegram
# 3. 启动
.venv\Scripts\python main.py
# 浏览器打开 http://127.0.0.1:8000
```
## 配置(config.json
| 字段 | 说明 | 默认 |
| --- | --- | --- |
| `port` | 服务端口 | 8000 |
| `password` | 面板登录密码 | admin123(请修改) |
| `global_interval_seconds` | 全局监控间隔(秒) | 300 |
| `retry_count` | 网络错误默认重试次数 | 2 |
| `timeout_seconds` | 请求默认超时(秒) | 10 |
| `max_workers` | 并发轮询线程数 | 8 |
| `telegram_bot_token` | Telegram Bot Token | 空 |
| `telegram_chat_id` | 接收提醒的 Chat ID | 空 |
> 除 `port` 外,其余均可在界面「设置」页修改并即时生效。改端口需重启。
## 平台配置说明
- **URL / Headers / Body** 中统一用 `{{apiKey}}` 占位,添加账号后自动替换为该账号的 API Key
- **余额提取路径**:点路径或数组索引,如 `data.balance``data[0].balance``$.data.balance`
- **Headers / Body** 为 JSON 格式;Body 仅在 POST 时发送
- **间隔 / 重试 / 超时** 留空则使用全局默认值
- **图标**:填 @lobehub/icons 的键(如 `OpenAI``DeepSeek``Anthropic`),前端内置品牌色映射,未识别时显示平台首字母
示例(OpenAI 余额接口):
```
URL: https://api.openai.com/v1/dashboard/billing/credit_grants?api_key={{apiKey}}
Headers: {"Authorization": "Bearer {{apiKey}}"}
路径: data.total_granted
```
## 提醒机制
- 余额 **<** 阈值 → 发送「余额不足」提醒(一次),此后不再重复
- 余额 **≥** 阈值 → 发送「已恢复」提醒,并重新武装(下次再低于阈值会再次提醒)
- 提醒发送成功才更新状态;Telegram 未配置或发送失败时只记录日志,不会误发
- 401/403 → 自动禁用该账号并发送通知;修复后可在界面重新启用
## REST API 摘要
认证:`POST /api/login` 获取 token,之后请求带 `Authorization: Bearer <token>`
| 方法 | 路径 | 说明 |
| --- | --- | --- |
| POST | `/api/login` / `/api/logout` | 登录 / 登出 |
| GET/POST | `/api/platforms` | 平台列表 / 创建 |
| PUT/DELETE | `/api/platforms/{id}` | 更新 / 删除(级联删账号) |
| GET/POST | `/api/accounts` | 账号列表 / 创建 |
| PUT/DELETE | `/api/accounts/{id}` | 更新 / 删除 |
| POST | `/api/accounts/{id}/check` | 立即检查 |
| GET | `/api/accounts/{id}/history` | 余额历史(`?limit=` |
| GET/PUT | `/api/settings` | 设置读取 / 更新 |
| POST | `/api/settings/password` | 修改密码 |
## 测试
```bash
.venv\Scripts\python -m pytest tests -q
```
## 目录结构
```
main.py 入口
config.json 配置
app/
api.py FastAPI 路由 + 认证
config.py 配置加载/保存
db.py SQLite 数据层
models.py Pydantic 模型
fetcher.py 请求执行 + 重试 + 路径提取
alert.py 阈值提醒状态机
monitor.py 并发调度器
telegram.py Telegram 发送
static/ 前端(HTML/CSS/JS
tests/ pytest 测试
data/ 运行时生成 SQLitegitignore
```