From fe6390337fe445d92f91c4ef9a845f10bc6afcbf Mon Sep 17 00:00:00 2001 From: Song <168455@qq.com> Date: Wed, 8 Jul 2026 19:37:20 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20silence=20Mijia=20"=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E7=8A=B6=E6=80=81"=20notices,=20keep=20door-lock=20alerts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit com.xiaomi.smarthome posts both generic status updates (title=米家, content=设备状态) and concrete events (e.g. 智能门锁开锁). Silence only the generic "设备状态" ones; door-lock/security alerts still forward. Filtered silently before the blacklist. CLAUDE.md synced. Co-Authored-By: Claude Opus 4.8 (1M context) --- CLAUDE.md | 4 ++-- .../main/java/com/a2i/forwarder/core/NotificationProcessor.kt | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index bc69e87..30c98f7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -71,7 +71,7 @@ NotifyListenerService (系统通知入口) |---|---| | `A2iApp.kt` | `Application` 单例;持有全局 `appScope`(`SupervisorJob+Dispatchers.Default`)与全局组件:三个 Store(`settings`/`appRules`/`logStore`)+ 监听类(`phoneCallMonitor`/`connectivityMonitor`/`carrierBalanceQuery`/`smsForwarder`/`updateChecker`)。全部经 `A2iApp.instance.xxx` 访问,`onCreate` 构造并 `start()`。UI 通过 `collectAsState()` 订阅 Store 的 `StateFlow`。 | | `service/NotifyListenerService.kt` | `NotificationListenerService` 实现;每条通知调 `processor.process()`,过滤后推送。 | -| `core/NotificationProcessor.kt` | **核心决策点**。包含 LRU 去重缓存(5s)、脱敏检测(`*****` → 回退到 `tickerText`)、持续性通知 + VPN/代理客户端常驻通知(`silentPackages`)静默过滤、系统状态消息过滤、广告过滤、验证码提取、特殊 App 解析。返回 `Decision(message?, reason, appLabel, code, silent)`。 | +| `core/NotificationProcessor.kt` | **核心决策点**。包含 LRU 去重缓存(5s)、脱敏检测(`*****` → 回退到 `tickerText`)、持续性通知 + VPN/代理客户端常驻通知(`silentPackages`)静默过滤、米家「设备状态」泛化通知静默(保留门锁告警)、系统状态消息过滤、广告过滤、验证码提取、特殊 App 解析。返回 `Decision(message?, reason, appLabel, code, silent)`。 | | `core/CodeExtractor.kt` | 三段正则:关键词+数字、数字+关键词、纯数字 4-8 位。检测到全 `*****` 时直接返回 null。 | | `core/AdFilter.kt` | 内置营销关键词 + 用户自定义关键词(`settings.adKeywords`)。 | | `core/AppParsers.kt` | 微信/QQ/Telegram 的 `clickUrl` 映射 + 重要消息关键词(@我、验证码、通话等)。 | @@ -97,7 +97,7 @@ NotifyListenerService (系统通知入口) - **Store 全局单例**:所有 Store 通过 `A2iApp.instance.xxx` 访问。**不要**在 Compose 中创建新的 Store 实例。 - **协程作用域**:跨屏调用用 `app.appScope.launch { ... }`(Application 级别的 `SupervisorJob + Dispatchers.Default`)。 - **过滤流水线**(顺序很重要,在 `NotificationProcessor.process` 中): - 1. 全局开关 → 2. ongoing 过滤(静默)→ 2b. VPN/代理常驻通知静默过滤(silentPackages)→ 3. App 黑/白名单 → 4. 空内容/脱敏 → 5. 噪音包名 → 6. 系统状态消息 → 7. 近空内容 → 8. 广告过滤 → 9. 已发短信(仅收不发)→ 10. 运营商余额回执拦截 → **11. 去重检查(5s 窗口)** → 12. 验证码提取 → 13. 特殊 App 解析 → 14. 构造 BarkMessage + 1. 全局开关 → 2. ongoing 过滤(静默)→ 2b. VPN/代理常驻通知静默过滤(silentPackages)→ 2c. 米家「设备状态」静默 → 3. App 黑/白名单 → 4. 空内容/脱敏 → 5. 噪音包名 → 6. 系统状态消息 → 7. 近空内容 → 8. 广告过滤 → 9. 已发短信(仅收不发)→ 10. 运营商余额回执拦截 → **11. 去重检查(5s 窗口)** → 12. 验证码提取 → 13. 特殊 App 解析 → 14. 构造 BarkMessage - **Bark API** 字段映射在 `BarkMessage.kt`(`@SerialName`):`device_key`/`autoCopy`/`isArchive` 用下划线/驼峰别名,其他用蛇形。 - **版本号**:`app/build.gradle.kts` 的 `versionCode`/`versionName`,运行时通过 `appVersionName(context)` 读取,首页底部居中显示 `v{version}`。**改完代码同步递增 versionCode/versionName,并更新本文档「版本与发布」一节的当前版本。** diff --git a/app/src/main/java/com/a2i/forwarder/core/NotificationProcessor.kt b/app/src/main/java/com/a2i/forwarder/core/NotificationProcessor.kt index 64225e3..5b15239 100644 --- a/app/src/main/java/com/a2i/forwarder/core/NotificationProcessor.kt +++ b/app/src/main/java/com/a2i/forwarder/core/NotificationProcessor.kt @@ -106,6 +106,10 @@ class NotificationProcessor(private val context: Context) { if (pkg in silentPackages) return Decision(null, "常驻通知静默", appLabel, null, silent = true) + // ---- 米家泛化状态通知静默("设备状态"等概览;门锁/告警等具体事件保留)---- + if (pkg == "com.xiaomi.smarthome" && content.contains("设备状态")) + return Decision(null, "米家状态通知静默", appLabel, null, silent = true) + // ---- App 黑白名单 ---- if (!rules.isForwardingOn(pkg)) return Decision(null, "此 App 已关", appLabel, null)