Files
DbusSmsForward/docs-debian-web-plan.md

372 lines
10 KiB
Markdown
Raw Permalink 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.
# DbusSmsForward Debian Web 版实施计划
> **For Hermes:** Use subagent-driven-development skill to implement this plan task-by-task.
**Goal:** 把当前 Debian 版 DbusSmsForward 改造成“带 Web 管理界面、可直接在 Debian 上运行、默认不要求本地编译”的版本。
**Architecture:** 保留现有 Generic Host + Worker 的短信转发核心,补一层 ASP.NET Core Minimal API 与静态 `wwwroot` 页面;运行形态改为 `dotnet DbusSmsForward.dll web` 或发布后的自包含目录直接运行。通过配置文件和环境变量驱动,不再依赖交互式初始化。
**Tech Stack:** .NET 8, ASP.NET Core Minimal API, Generic Host, Static Files, JSON config, systemd-friendly hosting.
---
## 0. 当前仓库真实状态(已核实)
**已存在:**
- `DbusTest/Program.cs`:已经是 Generic Host 风格入口。
- `DbusTest/appsettingsModel.cs`:已引入 `DbusSmsForwardOptions` / `DaemonConfig` / `AutmanPushConfig`
- `DbusTest/Services/SmsForwardWorker.cs`:已有后台转发 worker。
- `DbusTest/Notifications/*`:已拆分通知发送器。
- `DbusTest/Helper/ConfigHelper.cs`:已支持 `/etc/dbussmsforward/appsettings.json` 优先加载。
**缺失:**
- `wwwroot/` 不存在。
- 没有任何 Web API。
- `DbusSmsForward.csproj` 仍是 `Microsoft.NET.Sdk.Worker`,不是 Web SDK。
- `Program.cs` 里引用了若干当前仓库中不存在的类型:
- `SampleConfigFactory`
- `LegacyConfigurationBridge`
- `CommandLineConfigurationApplier`
- `ConfigurationValidator`
- 本机当前 `dotnet` 命令不存在,无法本地编译验证;因此本阶段要优先完成“代码落地 + 文档化运行路径”。
---
## 1. 目标运行方式
### 目标 A:Debian 上直接运行(不在目标机编译)
推荐两种:
1. **Framework-dependent**
- 目标机只安装 .NET 8 runtime / aspnetcore runtime
- 直接运行:
- `dotnet DbusSmsForward.dll web --urls http://0.0.0.0:8080`
2. **Self-contained 发布包**
- 预先在别处发布好 Linux x64 / arm64 包
- 目标机无需装 dotnet
- 直接运行发布目录中的可执行文件
**注意:** 当前用户要求“最好不需要编译,直接运行在 Debian 上”,因此仓库要优先支持 **运行已发布产物**,而不是要求 Debian 机器安装 SDK 编译源码。
---
## 2. 代码实施任务
### Task 1: 切换项目为 Web 宿主
**Objective:** 让项目具备 Minimal API + Static Files 能力。
**Files:**
- Modify: `DbusTest/DbusSmsForward.csproj`
**Step 1: 修改 SDK**
把:
```xml
<Project Sdk="Microsoft.NET.Sdk.Worker">
```
改成:
```xml
<Project Sdk="Microsoft.NET.Sdk.Web">
```
**Step 2: 保留现有依赖,继续复制配置文件**
保留现有 `PackageReference``appsettings*.json` 输出策略。
**Step 3: 增加 Web 静态资源复制规则(如需要)**
确认 `wwwroot/**` 默认由 Web SDK 处理。
**Verification:**
- 代码层面确认 csproj 已切到 Web SDK。
---
### Task 2: 补齐缺失的配置与兼容辅助类
**Objective:** 解决 `Program.cs` 当前引用缺失导致的不可编译问题。
**Files:**
- Create: `DbusTest/Helper/SampleConfigFactory.cs`
- Create: `DbusTest/Helper/LegacyConfigurationBridge.cs`
- Create: `DbusTest/Helper/CommandLineConfigurationApplier.cs`
- Create: `DbusTest/Helper/ConfigurationValidator.cs`
**Step 1: `SampleConfigFactory`**
- 返回一个最小可用的 `DbusSmsForwardOptions` 示例对象。
-`Daemon/Modem/Forwarding/Notifications/LegacyCompatibility` 基本结构。
**Step 2: `LegacyConfigurationBridge`**
- 从旧格式 `appSettings` 节点读取值,映射到新 `DbusSmsForwardOptions`
- 至少映射:
- `DeviceName`
- `SmsCodeKey`
- `ForwardIgnoreStorageType`
- Email / PushPlus / DingTalk / Bark / WeCom / TG / Shell
**Step 3: `CommandLineConfigurationApplier`**
-`AppCommand.EnabledChannels` 写入 `options.Forwarding.EnabledChannels`
- 如果旧 flags 指定了渠道,则同步将对应 `options.Notifications.*.Enabled = true`
**Step 4: `ConfigurationValidator`**
- 做最小校验:
- `Daemon.Mode` 合法值:`forward` / `web` / `both`
- 若启用 email,必须有 host / sender / receiver
- 若启用 autmanpush,必须有 ApiUrl
- 校验失败抛 `InvalidOperationException`
**Verification:**
- `Program.cs` 的缺失引用都能对应到真实文件。
---
### Task 3: 扩展命令模型支持 web/both 与 HTTP 端口
**Objective:** 让启动命令能表达 Web 模式。
**Files:**
- Modify: `DbusTest/Models/AppCommand.cs`
- Modify: `DbusTest/Services/CommandLineParser.cs`
**Step 1: 扩展 `AppCommand` 字段**
新增:
- `bool WebMode`
- `bool ForwardMode`
- `string Urls`
- `int Port`
- `string ConfigPath`
**Step 2: 解析新参数**
新增支持:
- `web`
- `both`
- `--urls http://0.0.0.0:8080`
- `--port 8080`
- `--config /etc/dbussmsforward/appsettings.json`
**Step 3: 默认策略**
- `run` = 仅 forward
- `web` = 仅 web
- `both` = forward + web
- 当只传 `--urls` / `--port` 时,默认仍按 `web` 理解更合理;若保持兼容性,也可要求显式 `web`
**Verification:**
- 参数设计能清晰表达三种启动形态。
---
### Task 4: 建立 Web API 服务层
**Objective:** 把 Web 层依赖从 `Program.cs` 抽出来,避免一团乱。
**Files:**
- Create: `DbusTest/Services/SystemStatusService.cs`
- Create: `DbusTest/Services/SmsWebService.cs`
- Create: `DbusTest/Web/WebDtos.cs`
**Step 1: `SystemStatusService`**
- 复用 `ModemManagerHelper` 暴露:
- `GetStatusAsync()`
- 返回 modem path / qmi path / device / manufacturer / model / revision / operator / signal
**Step 2: `SmsWebService`**
- 封装:
- `SendAsync(phone, content)`
- `GetMessagesAsync(limit, phoneFilter, keyword, sort)`
- `GetSettings()`
- `SaveSettings()`
-`ModemManagerHelper` 尚无历史短信读取能力,则先补最小方法;至少支持列表读取。
**Step 3: DTO**
- 请求与响应 DTO
- `SendSmsRequest`
- `SettingsResponse`
- `SmsMessageItem`
- `ApiEnvelope<T>`
**Verification:**
- Web API 调用不直接散落访问底层 helper。
---
### Task 5: 在 `ModemManagerHelper` 中补历史短信列表接口
**Objective:** 支持 Web 历史短信页。
**Files:**
- Modify: `DbusTest/ModemManagerHelper.cs`
- Create: `DbusTest/Web/SmsMessageRecord.cs`(如 DTO 不想放 helper 内)
**Step 1: 新增异步方法**
建议新增:
```csharp
Task<IReadOnlyList<SmsMessageRecord>> ListMessagesAsync(CancellationToken cancellationToken = default)
```
**Step 2: 实现逻辑**
- 使用现有 `CreateMessaging(_modemObjectPathNowUse)`
- 枚举 DBus message path
- 读取:
- Number
- Text
- Timestamp
- Storage
- State
- 做时间转换与空值兜底
**Step 3: 不破坏现有 forward 逻辑**
- 保持现有短信监听逻辑不变
- 新增方法只做读取
**Verification:**
- 代码上已经有明确的历史短信读取入口。
---
### Task 6: 重写 `Program.cs` 为“单进程双模式入口”
**Objective:** 同一个程序既能跑后台转发,也能跑 Web。
**Files:**
- Modify: `DbusTest/Program.cs`
**Step 1: 统一宿主构建**
- 注册:
- `ModemManagerHelper`
- `NotificationDispatcher`
- 各通知 sender
- `SystemStatusService`
- `SmsWebService`
- 仅在 forward 模式下注册 `SmsForwardWorker`
**Step 2: Web 模式构建**
- 使用 `WebApplication.CreateBuilder(args)` 或在现有 host 上兼容 Web host
- 开启:
- `UseDefaultFiles()`
- `UseStaticFiles()`
**Step 3: Minimal API 路由**
- `GET /api/system/status`
- `GET /api/sms/messages`
- `POST /api/sms/send`
- `GET /api/settings`
- `POST /api/settings`
- `GET /api/health`
**Step 4: 启动逻辑**
- `send`:一次性发短信后退出
- `run`:只跑后台 worker
- `web`:只跑 Web
- `both`Web + worker 同时运行
**Verification:**
- `Program.cs` 不再只会 `host.RunAsync()` 一条路。
---
### Task 7: 增加最小可用 Web UI
**Objective:** 让 BOSS 在浏览器里直接看效果。
**Files:**
- Create: `DbusTest/wwwroot/index.html`
- Create: `DbusTest/wwwroot/app.js`
- Create: `DbusTest/wwwroot/app.css`
**Step 1: 页面结构**
- 菜单:
- 仪表盘
- 历史短信
- 发送短信
- 系统配置
**Step 2: 页面能力**
- 仪表盘:加载 `/api/system/status`
- 历史短信:加载 `/api/sms/messages`
- 发送短信:调用 `/api/sms/send`
- 配置:读写 `/api/settings`
**Step 3: 保持纯静态实现**
- 原生 HTML/CSS/JS
- 不引入前端构建工具
- 保证部署简单
**Verification:**
- 浏览器打开根路径 `/` 能直接进入管理页。
---
### Task 8: 提供 Debian 直接运行所需文件
**Objective:** 让“直接运行在 Debian 上”真正落地。
**Files:**
- Create: `DbusTest/appsettings.example.json`
- Create: `DbusTest/dbussmsforward.service`
- Modify: `README.md`
**Step 1: 示例配置**
- 提供新结构 JSON 样例
- 默认 `Daemon.Mode = "both"`
- 默认 `urls` 示例写到 README,不强绑进配置
**Step 2: systemd unit**
- 示例:
- `WorkingDirectory=/opt/dbussmsforward`
- `ExecStart=/usr/bin/dotnet /opt/dbussmsforward/DbusSmsForward.dll both --urls http://0.0.0.0:8080`
- `Environment=DBUSSMSFORWARD_CONFIG_PATH=/etc/dbussmsforward/appsettings.json`
**Step 3: README 更新重点**
- 明确区分:
- 运行源码需要 SDK
- 运行发布产物只需 runtime 或无需 runtimeself-contained
- 给出 Debian 直接运行命令
- 给出 systemd 安装步骤
**Verification:**
- 文档能支撑“别人拿到发布包就在 Debian 跑起来”。
---
## 3. 本次实施优先级
1. 先修复仓库当前“缺失类导致不可编译”的问题
2. 再补 Web API 骨架
3. 再补 `wwwroot` 管理页
4. 最后补 README / example config / systemd
---
## 4. 运行验收标准
满足以下即视为达到目标:
- 可用命令:
- `dotnet DbusSmsForward.dll run`
- `dotnet DbusSmsForward.dll web --urls http://0.0.0.0:8080`
- `dotnet DbusSmsForward.dll both --urls http://0.0.0.0:8080`
- `dotnet DbusSmsForward.dll send --to 13800138000 --text "测试短信"`
- 根路径 `/` 可打开 Web UI
- `/api/health` 返回成功
- `/api/system/status` 返回 modem 状态
- `/api/sms/messages` 返回历史短信列表
- `/api/settings` 可读写配置
- 提供 Debian 的 systemd unit 示例
---
## 5. 当前阻塞说明
- 本机没有 `dotnet`,所以暂时不能做本地编译/运行验证。
- 但仓库代码改造、文件补齐、运行文档和 Debian 部署入口可以现在直接完成。