# Windows Gotify Agent > Gotify → Windows 原生通知 · 应用内按应用分类查看历史 · 系统托盘常驻 ![icon](Assets/gotify-mascot.png) 一个轻量级 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=` 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 吉祥物)—— 萌