docs: 添加 README — 项目介绍、构建、配置、架构
This commit is contained in:
@@ -0,0 +1,202 @@
|
|||||||
|
# Windows Gotify Agent
|
||||||
|
|
||||||
|
> Gotify → Windows 原生通知 · 应用内按应用分类查看历史 · 系统托盘常驻
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
一个轻量级 Windows 桌面端,把 [Gotify](https://gotify.net/) 推送的消息以 **Windows 原生通知** 呈现,并在应用内按 **应用名** 分类查看历史。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ 功能
|
||||||
|
|
||||||
|
| 模块 | 说明 |
|
||||||
|
|---|---|
|
||||||
|
| 🔔 实时通知 | WebSocket 长连接(`/stream?token=`),Gotify 一推消息就弹 Windows 原生 toast,优先级 ≥ 8 走告警音 |
|
||||||
|
| 📜 历史查看 | 主窗左栏 ListView 显示最近 50 条,TextWrapping 不被截断;实时新消息插到最前 |
|
||||||
|
| 🏷️ 按应用分类 | 启动时拉 `GET /application` 缓存到 `ApplicationCache`,历史每行显示应用名(自动按名字 hash 出固定颜色);不是"App 12345"那种无意义编号 |
|
||||||
|
| 🌗 浅色 / 深色主题 | 主窗右上角 `☼ 浅色 / ☾ 深色` 按钮一键切换,所有颜色走 `DynamicResource` 实时刷新,选择自动存 `config.json` |
|
||||||
|
| 📋 复制 | 详情面板"消息正文"右侧 `[复制]` 按钮,一键把 `[应用名] 标题 / 时间 / 优先级 / 正文 / URL` 整段写进剪贴板 |
|
||||||
|
| 🛡️ 复制兜底 | 剪贴板被 UU远程 / RDP / 杀软长期占着时,自动弹一个预填 + 全选的小窗口,让你直接 Ctrl+C(绕开 OLE 锁) |
|
||||||
|
| 🖱️ 详情可选中 | 详情面板的标题 / 正文 / URL 全部用 `TextBox IsReadOnly`,鼠标拉黑、Ctrl+A、Ctrl+C 都能用 |
|
||||||
|
| 🧲 托盘常驻 | 关闭主窗只 Hide,进程留托盘;右键菜单:打开设置 / 测试通知 / 重新连接 / 退出 |
|
||||||
|
| 🚀 开机自启动 | 设置区 CheckBox 勾选后写 `HKCU\...\Run`(只当前用户,不需管理员);取消勾选会立刻从注册表删 |
|
||||||
|
| 🔗 通知跳链接 | 消息 `extras.client::notification.click.url` 透传到通知,点 toast 直接用默认浏览器打开 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📸 截图
|
||||||
|
|
||||||
|
| 主窗(深色模式) | 主窗(浅色模式) |
|
||||||
|
|---|---|
|
||||||
|
| 托盘 + 应用内历史 + 详情面板 | 同上但浅色配色 |
|
||||||
|
| 优先级徽章彩色,应用名按名字分色 | 通知 hover 显示 |
|
||||||
|
|
||||||
|
> 截图占位 —— 跑起来后自行截图替换。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ 环境要求
|
||||||
|
|
||||||
|
- **OS**: Windows 10 (19041+) / Windows 11
|
||||||
|
- **运行时**: .NET 8 Desktop Runtime(开发用 SDK,运行用 Runtime)
|
||||||
|
- **依赖**: Windows App Runtime(`Microsoft.WindowsAppSDK 2.4.0` 同版本,本仓库 `dotnet publish --self-contained` 已自带)
|
||||||
|
- **Gotify**: 任意 v2.x server,需要创建一个 **Client**(不是 Application,本程序只消费消息不发送)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 快速开始
|
||||||
|
|
||||||
|
### 方式 1:下载 Release(推荐普通用户)
|
||||||
|
|
||||||
|
1. 去 [Releases 页面](https://gitea.kennethcheng.cc/KennethCheng/Windows-Gotify-Client/releases) 下载最新 zip
|
||||||
|
2. 解压到任意目录(比如 `C:\Program Files\WindowsGotify\`)
|
||||||
|
3. 双击 `WindowsGotify.exe` 启动 → 托盘出现鸟图标
|
||||||
|
4. 右键托盘 → **打开设置 / 查看历史**
|
||||||
|
5. 填 `Gotify URL` + `Client Token` → **保存并重连**
|
||||||
|
6. 默认勾选 **开机自动启动**,登录 Windows 自动起
|
||||||
|
|
||||||
|
> ⚠️ 整个目录拷走,别只拷 EXE(WindowsAppSDK unpackaged 需要同一目录的 native DLLs)。
|
||||||
|
|
||||||
|
### 方式 2:源码编译(开发者)
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
git clone https://gitea.kennethcheng.cc/KennethCheng/Windows-Gotify-Client.git
|
||||||
|
cd Windows-Gotify-Client
|
||||||
|
|
||||||
|
# 编译 + 跑 dev 版
|
||||||
|
dotnet restore
|
||||||
|
dotnet build -c Release
|
||||||
|
dotnet run -c Release
|
||||||
|
|
||||||
|
# 自包含发布(拷整个 bin\Release\net8.0-windows10.0.19041.0\win-x64\publish\ 目录)
|
||||||
|
dotnet publish -c Release -r win-x64 --self-contained true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ 配置
|
||||||
|
|
||||||
|
配置文件:`%LOCALAPPDATA%\WindowsGotify\config.json`
|
||||||
|
|
||||||
|
首次启动自动用默认值生成,主窗 GUI 编辑后实时落盘。
|
||||||
|
|
||||||
|
| 字段 | 类型 | 默认 | 说明 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `Gotify.Url` | string | `http://127.0.0.1:8080` | Gotify server URL,**不要带尾部斜杠** |
|
||||||
|
| `Gotify.ClientToken` | string | (空) | Gotify 后台 **Clients** 标签里那个 `Cxxxx...` token(不是 Application Token) |
|
||||||
|
| `Notification.Enabled` | bool | `true` | 总开关,关掉就不弹 toast |
|
||||||
|
| `Notification.Sound` | bool | `true` | 是否带声音(优先级 ≥ 8 强制告警音) |
|
||||||
|
| `Notification.MaxMessageLength` | int | `2000` | 通知正文最大字符数,超出截断 |
|
||||||
|
| `Reconnect.InitialDelaySeconds` | int | `2` | WebSocket 断开首次重连延迟(秒) |
|
||||||
|
| `Reconnect.MaxDelaySeconds` | int | `60` | 指数退避上限(2 → 4 → 8 → ... → 60) |
|
||||||
|
| `History.Enabled` | bool | `true` | 启动时拉 `since=lastMessageId` 补齐离线期间消息 |
|
||||||
|
| `History.StartupSyncCount` | int | `20` | 启动时一次拉多少条增量 |
|
||||||
|
| `History.ViewerLimit` | int | `50` | 主窗历史列表最多显示多少条(UI 硬上限 200) |
|
||||||
|
| `Startup.Enabled` | bool | `true` | 开机自启动(写 `HKCU\...\Run`) |
|
||||||
|
| `Ui.Theme` | string | `System` | `Light` / `Dark` / `System`(System 等同 Light) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏗️ 架构
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─ App.xaml.cs ──────────┐
|
||||||
|
│ 单实例 Mutex │
|
||||||
|
│ AppNotificationManager │ ← Windows App SDK
|
||||||
|
│ 主题加载 │
|
||||||
|
└────────────┬─────────┘
|
||||||
|
│
|
||||||
|
┌─────────┴──────────┐
|
||||||
|
│ │
|
||||||
|
┌──▼─────────┐ ┌─────▼──────────┐
|
||||||
|
│ TrayIcon │ │ MainWindow │
|
||||||
|
│ (WinForms) │ │ (WPF) │
|
||||||
|
└────────────┘ └─┬─────────┬────┘
|
||||||
|
│ │
|
||||||
|
┌───────────┘ └────────────┐
|
||||||
|
│ │
|
||||||
|
┌───────▼─────────┐ ┌─────────▼────────┐
|
||||||
|
│ GotifyWebSocket │ │ GotifyApi │
|
||||||
|
│ Service │ │ Service │
|
||||||
|
│ - 自动重连 │ │ - GetMessages │
|
||||||
|
│ - 去重(lastId) │ │ - GetRecentMsg │
|
||||||
|
│ - History 补偿 │ │ - GetApplications│
|
||||||
|
└─────────────────┘ └──────────────────┘
|
||||||
|
│ │
|
||||||
|
│ ┌───────────────────┘
|
||||||
|
│ │
|
||||||
|
│ ┌──────▼──────┐ ┌──────────────┐
|
||||||
|
│ │ Application │ │ StateService │
|
||||||
|
└──────►│ Cache │ │ - lastId │
|
||||||
|
└─────────────┘ └──────────────┘
|
||||||
|
|
||||||
|
┌──────────────┐ ┌──────────────────┐
|
||||||
|
│ Notification │ │ ConfigService │
|
||||||
|
│ Service │ │ (config.json) │
|
||||||
|
└──────────────┘ └──────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
模块清单(参见 `AGENTS.md` 完整说明):
|
||||||
|
|
||||||
|
- `Models/` — `AppConfig` / `GotifyMessage` / `GotifyApplication`
|
||||||
|
- `Services/` — `ConfigService` / `Logger` / `StateService` / `GotifyApiService` / `GotifyWebSocketService` / `NotificationService` / `ApplicationCache` / `ThemeService`
|
||||||
|
- `Utils/StartupManager.cs` — 注册表 Run 项
|
||||||
|
- `Tray/TrayIconService.cs` — WinForms `NotifyIcon`
|
||||||
|
- `Themes/Light.xaml` / `Dark.xaml` — 主题资源
|
||||||
|
- `Converters/ValueConverters.cs` — 优先级色 / 应用名 hash 出色
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐛 已知问题
|
||||||
|
|
||||||
|
- **WindowsAppSDK 2.4.0 self-contained 打包漏 `Microsoft.WindowsAppRuntime.Insights.Resource.dll`** —— `dotnet build/publish` 输出目录里少了这个 DLL,首次启动 `AppNotificationManager.Register()` 会抛 `0x8007007E`。**修法**:
|
||||||
|
- **dev**:从已装 WindowsAppSDK 的程序(本机如 `C:\Program Files\WSL\wslsettings\`)拷贝 5 个 DLL 到 build 目录:
|
||||||
|
- `Microsoft.WindowsAppRuntime.Bootstrap.dll`、`Bootstrap.Net.dll`、`Microsoft.WindowsAppRuntime.dll`、`Insights.Resource.dll`、`Microsoft.WindowsAppRuntime.pri`
|
||||||
|
- **prod**:`winget install Microsoft.WindowsAppRuntime.2`(或目标机器装 system-wide WindowsAppRuntime)
|
||||||
|
- 详细见 `AGENTS.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛣️ 路线图 (V2)
|
||||||
|
|
||||||
|
- 多 Gotify Server(同时连 NAS / 云的多个 instance)
|
||||||
|
- 按应用 / 优先级过滤历史(下拉框)
|
||||||
|
- 通知分类(Do Not Disturb 时段、白名单)
|
||||||
|
- 自定义通知图标(每个 app 一个图标)
|
||||||
|
- MSI / MSIX 安装器
|
||||||
|
- Gitea Actions CI:`push` tag 时自动 build + publish release
|
||||||
|
- 通知消息聚合(同一应用 1 分钟内多条合并为"X 条新消息")
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📜 协议
|
||||||
|
|
||||||
|
- **Gotify 消息流**:通过 `/stream?token=<Client Token>` WebSocket 订阅
|
||||||
|
- **HTTP API**:`/application`(应用列表)、`/message?limit=&since=`(历史)
|
||||||
|
- **点击链接**:Gotify 消息 `extras.client::notification.click.url`,被透传到 toast 的 `AddArgument("url", ...)`,点击时用默认浏览器打开
|
||||||
|
- **本地状态**:`%LOCALAPPDATA%\WindowsGotify\state.json` 记录 `LastMessageId` 防止重启后重复通知
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔒 安全
|
||||||
|
|
||||||
|
- **只读 Client Token**:本程序只向 Gotify 订阅消息,不需要 Application Token;请勿在配置或日志里泄露任何 Application Token
|
||||||
|
- **当前用户 Run 项**:开机启动走 `HKCU`,不写 `HKLM`,不需要管理员权限,不影响其他用户
|
||||||
|
- **Token 日志脱敏**:WebSocket 连接日志把 `?token=***` 段打码,不输出完整 token
|
||||||
|
- **HTTPS / wss**:公网部署请用 HTTPS + wss;ws / http 仅适合内网
|
||||||
|
- **通知链接白名单**:通知点击只能打开 Gotify `extras` 显式声明的 URL,不会自动从消息文本里抓链接
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📄 License
|
||||||
|
|
||||||
|
TBD
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🙏 致谢
|
||||||
|
|
||||||
|
- [Gotify](https://gotify.net/) — 简单好用的自托管消息推送 server
|
||||||
|
- [Windows App SDK](https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/) — 现代 Windows 原生通知 API
|
||||||
|
- Ducker(Gotify 吉祥物)—— 萌
|
||||||
Reference in New Issue
Block a user