Files
vps-management-bot/aff-monitor/README.md
2026-03-21 01:10:53 +08:00

355 lines
14 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.
# VPS补货监控 — 商家产品库存监控 + Telegram 推送
前台公开浏览 + 后台登录管理。轻量级库存监控系统,支持自动检测 VPS/独服库存变化并通过 Telegram 推送通知。
## 架构概览
```
前台(公开) 后台(需登录)
/ → 首页 /admin → 管理仪表盘
/plans → 产品列表 /admin/merchants → 商家管理
/plans/:slug → 产品详情 /admin/products → 产品管理(含编辑)
/plans/:id → 兼容旧链接 /admin/aff-links → Aff 链接管理
(301→slug) /admin/channels → TG 频道配置
/admin/tasks → 监控任务 & 检测
/admin/settings → 系统设置TG Token 等)
/admin/login → 登录页
/admin/logout → 退出登录
```
## 技术栈
| 组件 | 选型 | 说明 |
|------|------|------|
| 运行时 | Node.js 18+ | 部署到 Debian 13 兼容 |
| Web 框架 | Express 4 | 最省心的 Node 后台框架 |
| 模板引擎 | EJS | 服务端渲染,无需构建步骤 |
| 数据库 | SQLite (better-sqlite3) | 单文件、零配置 |
| 认证 | express-session | 轻量 session 登录 |
| 配置 | dotenv | .env 文件管理 |
## 项目结构
```
aff-monitor/
├── db/
│ ├── init.js # 建表 + 种子数据
│ ├── migrate-add-product-fields.js # 迁移 001: 产品扩展字段
│ ├── migrate-002-checker-fields.js # 迁移 002: 检测相关字段
│ ├── migrate-003-public-fields.js # 迁移 003: 前台展示字段
│ ├── migrate-004-pid-slug.js # 迁移 004: PID & Slug 字段
│ ├── migrate-005-aff-code.js # 迁移 005: Aff Code 字段
│ ├── migrate-006-settings.js # 迁移 006: Settings 表 & generated_aff_url
│ └── monitor.sqlite # 数据库文件 (运行后生成)
├── scripts/
│ └── run-task.js # CLI: 手动执行/列出任务
├── src/
│ ├── app.js # Express 入口(含 session + 路由挂载)
│ ├── db.js # 数据库单例
│ ├── routes/
│ │ ├── public.js # 前台公开路由(首页/产品列表/详情)
│ │ ├── auth.js # 登录/登出路由
│ │ ├── admin.js # 后台仪表盘
│ │ ├── merchants.js # 商家 CRUD
│ │ ├── products.js # 产品 CRUD + 编辑
│ │ ├── channels.js # TG 频道 CRUD
│ │ ├── affLinks.js # Aff 链接 CRUD
│ │ ├── tasks.js # 监控任务 + 检测 + 推送 + 调度
│ │ └── settings.js # 系统设置TG Token 等)
│ ├── utils/
│ │ ├── checker.js # 库存检测器
│ │ ├── telegram.js # Telegram Bot 推送
│ │ ├── taskRunner.js # 任务执行器
│ │ ├── scheduler.js # 轻量调度器
│ │ ├── pushTemplate.js # 推送消息模板
│ │ ├── pidHelper.js # PID & Slug 自动生成/解析
│ │ ├── affHelper.js # Aff 链接解析/生成
│ │ └── settings.js # 系统设置工具DB优先.env兜底
│ ├── views/
│ │ ├── login.ejs # 登录页
│ │ ├── admin/ # 后台模板
│ │ │ ├── index.ejs # 仪表盘
│ │ │ ├── merchants.ejs # 商家管理
│ │ │ ├── products.ejs # 产品管理
│ │ │ ├── product-edit.ejs # 产品编辑
│ │ │ ├── channels.ejs # 频道配置
│ │ │ ├── affLinks.ejs # Aff 链接
│ │ │ ├── tasks.ejs # 监控任务
│ │ │ └── settings.ejs # 系统设置
│ │ ├── public/ # 前台模板
│ │ │ ├── home.ejs # 首页
│ │ │ ├── plans.ejs # 产品列表
│ │ │ ├── detail.ejs # 产品详情
│ │ │ └── 404.ejs # 404 页面
│ │ └── partials/
│ │ ├── admin-header.ejs # 后台导航
│ │ ├── public-header.ejs # 前台导航
│ │ └── footer.ejs # 统一页脚
│ └── public/ # 静态资源
├── .env.example
├── .gitignore
├── package.json
└── README.md
```
## 环境变量
| 变量 | 必填 | 默认值 | 说明 |
|------|------|--------|------|
| `PORT` | 否 | `3900` | Web 服务端口 |
| `DB_PATH` | 否 | `db/monitor.sqlite` | SQLite 数据库路径 |
| `ADMIN_USERNAME` | 否 | `admin` | 后台登录用户名 |
| `ADMIN_PASSWORD` | 否 | `admin` | 后台登录密码 |
| `SESSION_SECRET` | **建议设置** | 内置默认值 | Session 签名密钥,生产环境请换成随机长字符串 |
| `TG_BOT_TOKEN` | 推送时必填 | - | Telegram Bot Token可在后台「系统设置」页面配置数据库优先 |
| `TG_DEFAULT_CHANNEL_ID` | 否 | - | 默认推送频道的 chat_id可在后台「系统设置」页面配置 |
| `MONITOR_INTERVAL` | 否 | `300` | 调度器检测间隔(秒) |
| `SCHEDULER_ENABLED` | 否 | `false` | 启动时是否自动开启调度器 |
> **配置优先级**TG_BOT_TOKEN、TG_DEFAULT_CHANNEL_ID、SITE_NAME、SITE_TG_URL 等配置项,优先从数据库 `settings` 表读取,数据库没有则回退到 .env 文件。推荐在后台「系统设置」页面直接配置。
## 本地启动
```bash
# 1. 安装依赖
cd aff-monitor
npm install
# 2. 复制环境变量(首次)
cp .env.example .env
# 编辑 .env至少设置 ADMIN_PASSWORD 和 SESSION_SECRET
# 3. 初始化数据库 + 运行迁移
npm run db:init
npm run db:migrate
# 4. 启动
npm run dev # 开发模式 (--watch 自动重载)
# 或
npm start # 生产模式
# 5. 打开
# 前台http://localhost:3900
# 后台http://localhost:3900/admin/login
```
## 前台功能
- **首页 `/`**Landing Page 风格Hero 区展示品牌、刷新状态、Telegram 频道入口;产品卡片流展示推荐和最新产品,移动端友好设计
- **产品列表 `/plans`**:按商家、地区筛选,支持关键词搜索
- **产品详情 `/plans/:slug`**:查看产品配置、价格、购买链接、同商家其他产品(也兼容 `/plans/:id`,自动 301 重定向到 slug
前台只展示 `is_public = 1` 的产品。
## 产品 PID & Slug
每个产品有三个标识字段:
| 字段 | 说明 | 示例 |
|------|------|------|
| `internal_pid` | 系统内部编号,自动生成,不可改 | `VPS-000001` |
| `provider_pid` | 商家产品 ID从购买链接自动解析 | `28`(来自 `pid=28` |
| `slug` | 前台友好 URL自动生成可手改 | `gomami-hkgpulsemini` |
### 自动解析规则
当用户填写购买链接(`buy_url`)时,系统自动从 URL 中解析 `provider_pid`
- **高优先级参数**`pid``product``product_id``plan``plan_id``package``package_id`
- **谨慎参数**`id`(仅当 URL 路径含 product/plan/cart/aff/billing 等关键词时才识别)
- **路径模式**`/product/28``/plan/28`
示例:`https://console.po0.com/aff.php?aff=5&pid=28``provider_pid = 28`
## Aff 链接自动生成
系统支持用户设置自己的 aff 标识,自动生成最终推广链接。
### 工作流程
1. **录入产品时**填写基础购买链接(`buy_url`)和你的 aff 值(`aff_code`
2. 系统自动生成最终 aff 链接:`buy_url` + `aff_param=aff_code`
3. 生成的链接会自动出现在产品管理页和 Aff 链接页
### 三种使用方式
| 方式 | 操作 | 效果 |
|------|------|------|
| **直接粘贴 aff 链接** | buy_url 填 `https://example.com/aff.php?aff=5&pid=28` | 自动识别 `aff_code=5``provider_pid=28` |
| **分开填写** | buy_url 填干净链接aff 值填 `5` | 自动生成完整 aff 链接 |
| **批量生成** | 在 Aff 链接页点"批量生成" | 为所有有 aff_code 但没有 aff_link 的产品一键生成 |
### 字段说明
| 字段 | 说明 | 示例 |
|------|------|------|
| `aff_code` | 你的 aff 标识值 | `5` |
| `aff_param` | aff 参数名(默认 `aff` | `aff``ref``affiliate` |
支持识别的 aff 参数名:`aff``affid``aff_id``ref``refid``ref_id``referral``partner``affiliate`
## 系统设置(后台)
访问 `/admin/settings` 可在网页中配置:
- **TG_BOT_TOKEN**Telegram Bot Token用于推送消息
- **TG_DEFAULT_CHANNEL_ID**:默认推送频道 ID
- **SITE_NAME**:站点名称
- **DEFAULT_AFF_CODE**:新产品默认 aff 值
配置保存到数据库 `settings` 表,优先级高于 .env 文件。页面支持:
- 保存配置
- 测试 Telegram 连接(发送测试消息到指定频道)
## 推送链接优先级
补货推送时,系统按以下优先级选择链接:
1. **产品生成的 Aff 链接**`products.generated_aff_url`,由 buy_url + aff_code 自动生成)
2. **Aff 链接表**`aff_links` 表中的链接,支持手工添加或批量生成)
3. **产品的 buy_url**(原始购买链接)
4. **产品的 url**(产品页链接)
在产品编辑页可以看到"推送用的 Aff 链接",明确标识哪个链接会被用于推送。
## 后台功能
访问 `/admin/login` 登录后进入管理后台:
- 仪表盘、商家/产品/Aff 链接/频道/任务的增删改
- 产品支持完整编辑(名称、价格、地区、配置、流量、优惠码、检测模式等)
- 产品可设置"前台展示"、"推荐"、"排序值"来控制前台展示
## 手动执行检测
### Web 界面
后台「监控任务」页面,点击任务行的 **▶ 执行** 按钮。
### CLI
```bash
npm run task:list # 列出所有任务
npm run task:run -- 1 # 执行指定任务
npm run task:run-all # 执行所有启用的任务
```
### API
```bash
curl -X POST http://localhost:3900/admin/tasks/api/1/run
```
## 部署到 Debian 13 服务器
```bash
# 1. 安装 Node.js
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash -
sudo apt-get install -y nodejs
# 2. 上传代码
rsync -avz --exclude node_modules --exclude 'db/*.sqlite*' aff-monitor/ root@your-server:~/aff-monitor/
# 3. 服务器上安装 + 初始化
cd ~/aff-monitor
npm install --production
cp .env.example .env
# 编辑 .env设置 ADMIN_PASSWORD, SESSION_SECRET, TG_BOT_TOKEN 等
npm run db:init
npm run db:migrate
# 4. 用 systemd 管理进程
sudo tee /etc/systemd/system/aff-monitor.service << 'EOF'
[Unit]
Description=VPS补货监控
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/root/aff-monitor
ExecStart=/usr/bin/node src/app.js
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now aff-monitor
```
## 数据表概览
| 表名 | 用途 |
|------|------|
| `merchants` | 商家信息 |
| `products` | 产品 + 检测配置 + 前台展示控制 |
| `aff_links` | Aff 推广链接 |
| `tg_channels` | Telegram 频道配置 |
| `monitor_tasks` | 监控任务 |
| `check_logs` | 每次检测的记录 |
| `settings` | 系统配置TG_BOT_TOKEN 等) |
### products 表关键字段
| 字段 | 类型 | 默认 | 说明 |
|------|------|------|------|
| `internal_pid` | TEXT | 自动生成 | 系统内部编号VPS-000001 |
| `provider_pid` | TEXT | 自动解析 | 商家产品 ID |
| `slug` | TEXT | 自动生成 | 前台友好 URL |
| `aff_code` | TEXT | 自动解析 | 用户的 aff 标识值 |
| `aff_param` | TEXT | `aff` | aff 参数名 |
| `generated_aff_url` | TEXT | 自动生成 | 自动生成的 aff 链接(推送优先使用) |
| `is_public` | INTEGER | 1 | 是否在前台展示 |
| `is_featured` | INTEGER | 0 | 是否推荐(首页推荐区) |
| `sort_order` | INTEGER | 100 | 排序值(越小越靠前) |
### settings 表
| 字段 | 类型 | 说明 |
|------|------|------|
| `key` | TEXT | 配置键名(主键) |
| `value` | TEXT | 配置值 |
| `updated_at` | TEXT | 更新时间 |
## Changelog
### v0.5.0
- ✅ 新增后台「系统设置」页面,支持网页配置 TG_BOT_TOKEN / TG_DEFAULT_CHANNEL_ID / SITE_NAME
- ✅ 配置优先级:数据库优先,.env 兜底
- ✅ 设置页支持测试 Telegram 连接
- ✅ 产品表新增 `generated_aff_url` 字段,缓存自动生成的 aff 链接
- ✅ 产品编辑页显示"推送用的 Aff 链接",明确标识推送时使用哪个链接
- ✅ 推送链接优先级generated_aff_url → aff_links 表 → buy_url → url
- ✅ Aff 链接页显示链接来源(系统生成/手工添加)
### v0.4.0
- ✅ 新增 internal_pid系统内部编号自动生成 VPS-000001
- ✅ 新增 provider_pid商家产品 ID从购买链接自动解析
- ✅ 新增 slug前台友好 URL自动生成
- ✅ 前台详情路由支持 `/plans/:slug`,旧数字 ID 自动 301 重定向
- ✅ 后台产品表单增加 PID/Slug 字段展示与编辑
- ✅ 购买链接输入时实时解析 provider_pid前端 AJAX
- ✅ 迁移脚本自动回填已有产品的三个字段
- ✅ 新增 aff_code / aff_param 字段,支持设置用户自己的 aff 标识
- ✅ 购买链接粘贴时自动识别 aff 参数aff/ref/affiliate 等)
- ✅ 基础购买链接 + aff 值 → 自动生成最终 aff 推广链接
- ✅ Aff 链接页支持批量为所有有 aff_code 的产品一键生成
- ✅ 产品列表展示 aff 状态和生成的链接
- ✅ 前端实时预览生成的 aff 链接
### v0.3.0
- ✅ 新增前台公开页面(首页、产品列表、产品详情)
- ✅ 后台登录保护express-session + .env 账号密码)
- ✅ 后台路由统一移到 /admin 前缀
- ✅ 产品编辑功能
- ✅ 新增 is_public / is_featured / sort_order 字段
- ✅ 前后台导航分离
### v0.2.0
- 库存检测HTTP + 关键词匹配)
- Telegram 推送
- 定时调度器
- 推送文案模板
### v0.1.0
- 基础 CRUD商家、产品、Aff 链接、频道、任务)