zijunchiang
|
c7f8224a73
|
点歌延迟优化:终态失败不退避 + 上游 i.php token 缓存 + 后台预热 + 分阶段耗时日志(V1.6.3/46,未发布)
|
2026-10-14 19:25:43 +08:00 |
|
zijunchiang
|
d01269e917
|
取址改为官方源优先+自建源兜底,只有官方源成功才上报(V1.6.2/45,未发布)
需求一:流程反转 + 上报绑定官方源成功
- 默认 sourceHosts 反转为 ["http://zk.ktv1.top:6677", "https://mdmuse.kasugano.cn"];
SourceHosts.DEFAULT / SongUrlResolver.DEFAULT_HOSTS(收敛为引用前者)/ ktv_api.js
CONFIG.HOSTS+HOST 三处一致。
- 取址结果改为 SourcedSongUrl(url, sourceHost)(**显式来源标志**,不靠 URL 猜):
新增 SongSourceFlow(回落链 firstAvailable / 上报判定 shouldReportToSelfHost /
全失败信号);JS 侧新增 android.onSongSource(requestId, host) 回传命中的源。
- 汇合点 SongApiClient.getSongDownloadUrl 只在"地址来自官方源"时才 POST /push_download;
自建源自己给的地址与 DB 回落都不上报。
- 推送默认目标改为"从歌曲源列表里找第一个自建源"(自建源不再排第一,旧写法会直接关掉推送)。
- 1.6.1 落盘的旧默认顺序(自建源优先)在 KtvStore.load() 里一次性迁移;自定义列表不动。
- 业务码 404(自建源没有这首歌)仍只当"该源没地址",不置 sawForbidden、不进冷却、不污染受限统计。
需求二:6 条隐患
1) 设置页改源对 JS 立即生效:KtvJsBridge.applySourceSettingsNow 重新注入 KtvApiConfig.*
并把已构造实例的 window.api.sourceOrder 重置为新列表;SongApiClient.applySourceSettings 接线。
2) JS 路径识别业务码 403:新增 KtvJsBridge.riskForbidden(status, body)(纯函数,手写判定
避免 org.json 在单测里是空壳),HTTP 403 与 HTTP 200+{"code":403} 都算风控,与原生 sawForbidden 同口径。
3) isTrustedDownloadUrl 移除广告域名 ac16.vip 白名单,并改为黑名单优先(不再依赖调用顺序)。
4) MainActivity.download(song)(第五条地址消费点)补 AdVideoFilter.isTrustedSongUrl 闸门,
不可信按"源失效"处理(Eac19WindowGuard.noteAllSourcesFailed),不再静默下载。
5) SongApiClient.fetchFromDb 不再静默吞异常:曲库打不开/查询异常各记一条 MiliLog.localWarn(含编号与异常)。
6) 删除死代码 streamDownloadAndPlay(全仓 grep 无调用点,且内部取址不过最终闸门)。
需求三:死代码/漂移清理(均先全仓搜索确认无引用)
- AdVideoFilter.replacementUrl 无任何写入点(恒为 null)→ 删除,resolve() 只保留"屏蔽"语义。
- ktv_api.js CONFIG.VER/VN 由"从不生效的死值"改为实际使用值 2.0 / 4.1.3.03281430。
- CONFIG.HOST 改为被 getToken 真正读取(不再"注入但从未被读")。
- KTV_BRIDGE_API 14 → 15(JS 两处 + KtvJsBridge 两处校验);AGENTS.md / README.md / README.en.md
的陈旧标记统一到 15。
- do.php 的 limit 与 i.php 的 retry/ordertype/end_date/heart_time 确认无消费方 → 不新增解析(保持现状)。
需求四:测试与打包
- 新增 SourceOrderConsistencyTest / SongSourceFlowTest / JsBridgeGateTest / DownloadEntryGateTest,
更新 SourceHostsTest / AdVideoFilterTest;app/build.gradle 打开 unitTests.returnDefaultValues。
- testReleaseUnitTest --rerun-tasks --offline:12 个测试类 / 87 例全过。
- assembleRelease --offline 通过(lintVital NewApi 0 条);版本 1.6.1/44 → 1.6.2/45。
不发布:未推 Gitea/Gitee、未动 Release/tag。
|
2026-10-14 03:45:07 +08:00 |
|
zijunchiang
|
e00a1ace79
|
接入自建歌曲源服务器:源列表自建优先 + App 令牌 + 媒体地址允许清单 + 推送默认目标(V1.6.1/44,未发布)
源列表(自建源优先、官方源兜底)
- SongUrlResolver.DEFAULT_HOSTS 与 ktv_api.js 的 CONFIG.HOSTS/HOST 改为
https://mdmuse.kasugano.cn + http://zk.ktv1.top:6677;
- 新增设置项 KtvStore.sourceHosts(一行一个可编辑)与纯 JVM SourceHosts(解析/归一化/
自建源判定),App 与 JS 都以它为准(JS 走既有配置注入:KtvJsBridge 覆写 window.KtvApiConfig)。
App 令牌(自适应,不破坏官方源/老服务端)
- 新增纯 JVM AppToken/AppTokenSession(取/缓存/404-405 记忆不支持/401 清缓存重试一次)
与胶水 AppTokenClient(同一条干净裸 Socket、8 秒超时、失败只写 MiliLog.local*);
- /music/do.php 与 /push_download 前先对当前源 GET /token,取到即带 X-App-Token
(expires_in 提前 30 秒过期);官方源 404/405 记住后不再尝试;401 只重试一次;
- /i.php、/music/do.php 的参数与签名算法一个字未改(令牌只加一个请求头);
- JS 侧同步:android.appToken(host)/invalidateAppToken(host) + 401 立即重试一次。
媒体地址闸门(自建源适配)
- 新增设置项 KtvStore.allowedMediaHosts(默认 md.kasugano.cn + 192.168.100.232);
- AdVideoFilter.isTrustedSongUrl(url, musicno, allowedHosts) 只对命中主机放行"非域名"
限制(裸 IP);黑名单 wb66/demo/ac16.vip/ad_files/my_ad_video/pub-*.r2.dev/ss 与
".ts 文件名必须等于编号"一律不变且优先级更高(命中清单也拒);
- 四处调用点同口径:KtvJsBridge.isTrustedDownloadUrl、SongApiClient.isLikelyDemoUrl、
JS isDemoUrl、下载兜底。
点歌推送默认目标
- PushDownload.effectiveServerUrl:显式配置优先;留空且首源是自建源则默认用它;
off/none/关闭 等显式关闭;pushToken 逻辑不变(服务端接受 X-App-Token 或 push_token)。
版本与测试
- versionName 1.6.1 / versionCode 44;KTV_BRIDGE_API 13 -> 14(JS 两处 + KtvJsBridge 两处);
- 设置页「数据设置」新增「歌曲源」「媒体地址允许清单」两项;
- 新增单测 AppTokenTest(11)/SourceHostsTest(7)/MediaHostAllowlistTest(8),共 65 例全过。
|
2026-10-14 02:46:23 +08:00 |
|
zijunchiang
|
87aa979abd
|
合并自建歌曲源支线(selfhost-source)+ 版本号按约定修正为 1.6.0
版本号:
- 1.5.11 越界(规则 3 规定 patch ≤ 10)→ 修正为 1.6.0(进位到 minor、patch 归 0)
- versionCode 43 不变:43 从未对外发布,本次修正只是把命名拉回约定
合并支线(原在工作区根目录、App 仓库之外,DESIGN.md 自称"支线"):
- selfhost-source/server/ 自建歌曲源服务器(纯 Python 标准库、零 pip 依赖)
- selfhost-source/deploy/、DESIGN.md、LIBRARY.md、build_inventory.py
- selfhost-source/inventory/ 小清单(playlists.csv、song-stats.md 等)
- ⚠️ inventory 生成物(songs-*.csv / singers-top.csv,共 84MB)不入库,
已写入 .gitignore;需要时用 build_inventory.py 依据 muse.db 重新生成
同时入库的 App 侧支线改动(此前为工作树未提交状态):
- Whoami.kt(whoami 设备心跳)、DeviceIdentity.kt(设备身份伪装)
- PushDownload.kt / PushDownloadClient.kt(点歌推送)
- AdVideoFilter 带 query/fragment 的地址闸门;KTV_BRIDGE_API 11 → 13
- 修 ktv_api.js 的 global.KtvBridgeApiVersion(12 → 13,与注释及 Kotlin 两处校验一致)
- 对应单测:WhoamiTest / DeviceIdentityTest / PushDownloadTest / AdVideoFilterTest(共 39 例)
文档:
- DESIGN.md 的"在 App 仓库之外"约定改为"已并入仓库统一版本化"
- AGENTS.md 版本号行更新为 1.6.0/43,并新增支线并入说明
验证:assembleRelease + testReleaseUnitTest 全过(39 例)
|
2026-10-14 02:06:28 +08:00 |
|
zijunchiang
|
e060ae5ebe
|
源列表只保留 zk.ktv1.top:6677, 删除其余全部源
实测(同一出口 IP, 编号 7009126, 三节点同时刻对照):
zk.ktv1.top:6677 → i.php 200(与 e.ac19.cn 逐字段一致) + do.php 真源 7009126.ts / 7303235.ts ✅
e.ac19.cn → 同款 i.php + 真源 7009126.ts ✅
124.223.20.123:58→ 同款 i.php, 但 do.php 返回 0021.ts(非本曲) ❌
三者同一后台; 昨日 e.ac19.cn/124.223.20.123:58 的 HTTP 403 空响应为临时额度/风控, 今日已恢复
改动:
- SongUrlResolver.DEFAULT_HOSTS 与 ktv_api.js CONFIG.HOSTS(含 HOST) 均只留 http://zk.ktv1.top:6677
- KTV_BRIDGE_API 11 → 12 (ktv_api.js 两处 + KtvJsBridge.kt 两处校验)
- ensureConfig(): api.php 失败也写负缓存(该节点无 api.php, 否则每首歌白请求一次)
- MainActivity 日志不再写死旧源名, 改用 SongUrlResolver.lastHost
- AdVideoFilter.AD_HOSTS 不变(管"返回地址"的 host, 与"取址入口"无关)
版本号按规则 3: 1.5.9(41) → 1.5.10(42); 本地打包(未发布)
验证: assembleRelease + 单元测试(9 例全过); 解包确认 APK 内 ktv_api.js 只含新源且标记为 12
|
2026-10-09 21:42:27 +08:00 |
|
zijunchiang
|
97ca1ae28e
|
V1.5.5: 加入源 a.ktv8.my;"所有源失效"改为明确弹窗提示
一、加入歌曲源 a.ktv8.my(置于 gz.ac16.vip 之后)
实测(代理修复后,DNS 直连真实 IP 20~42ms):
- 真实 IP 154.219.102.181 —— 与 w345.my **同一台服务器**(同一后台的兄弟入口);
- GET / → 200(917B,主机面板默认占位页);
- i.php → 200,170B,与其它 5 个入口响应**逐字节一致**:
code=200 / msg=ok / ordertype=0 / end_date=2026-10-05 14:58:21 / retry=5 / heart_time=5400,token 正常下发;
- 自身媒体路径 /<编号>.ts 与 /ad_files/my_ad_video.ts 均 404(138B,与 e.ac19.cn 的 404 逐字节相同)
→ 它不托管广告媒体;
- ⚠️ do.php 取址行为未能定性: 测试期间本机出口 IP(与门店设备同一个 188.253.112.231)
的配额被反复探测耗尽,表现为"成功一两次后长时间静默丢包"(与代码里记录的
trial_times:2 × trial_duration:5 吻合)。故置于次位,由运行时升降序自动调整。
KTV_BRIDGE_API 10 → 11(ktv_api.js 两处标记 + KtvJsBridge 两处校验)。
二、"所有源都取不到地址"给出明确提示
新增 Eac19WindowGuard.onAllFailed ← noteAllSourcesFailed(),由 SongUrlResolver.resolve()
在**本轮彻底失败**时调用(403 / 只返回广告 / 网络异常都算),弹窗文案:
「远程源已全部失效,等待新版本修复」
- 与既有的 onBlocked(风控 403 → "换公网 IP")常常同时触发,因此在 onBlocked 处理器里
用 lastAllFailedAt() 做 60 秒去重,不会同时弹两个框;两者均 15 分钟节流。
- 以前这里只有一句"无法生成下载地址"的 toast,用户看起来像界面没反应。
版本 1.5.4(36) → 1.5.5(37);签名证书不变。测试 9 例全通过。
|
2026-10-07 07:53:48 +08:00 |
|
zijunchiang
|
c1fd0fa319
|
V1.5.4: 新增可用源 gz.ac16.vip;修复"点歌失败不入下载列表";下载列表删除按状态区分
一、新增歌曲源 gz.ac16.vip(置于源列表首位)
实测(DoH 取真实 IP 154.222.26.244,绕开本机网关 fake-IP 干扰):
- i.php: HTTP 200,下发 token,end_date=2027-10-05(比现用镜像源的 2026-10-05 更晚);
- music/do.php: 对 7303235/7200188/8614960 分别返回各自不同的真源地址
(http://txog.ktvsky.com/.../<编号>.ts?token=... / http://download.origjoy.com/.../<编号>.ts?sign=...),
文件名均等于点歌编号;
- 这些地址能真实下载:HTTP 206 video/MP2T,逐曲内容各不相同,
TS 流同步字节按 188 字节对齐(41/43 包同步);
- 对照:其余 7 个入口对每首歌(含不存在的编号)统一返回同一段
https://wb66.cn/f/d/7b7c9/10188555.ts(广告/测试资源),主源 w.w345.my/i.php 直接 403。
因此把 gz.ac16.vip 加入源列表:ktv_api.js 的 CONFIG.HOSTS 与
SongUrlResolver.DEFAULT_HOSTS 各一处(均置于首位)。
⚠️ 边界:该域名**自己**的 /<编号>.ts 永远是同一段广告,所以它继续留在
AdVideoFilter.AD_HOSTS(媒体层拦截);广告黑名单只作用于"返回地址的 host",
不作用于"取址入口的 host",两者不可混淆,否则会误杀唯一可用源。
KTV_BRIDGE_API 9 → 10(ktv_api.js 两处标记 + KtvJsBridge 两处校验),保证设备热更新到新脚本。
二、修复"点歌失败时歌曲不出现在下载列表"
根因:DownloadTask 只在 onDownloadStart 里创建,所以"取址失败(无法生成下载地址)"这类
还没真正开始下载的失败**不会留下任何记录**,下载列表里什么都没有。
修复:downloadSong() 在**发起下载之前**就登记任务(状态「排队中」),
失败时由既有回调就地改成「失败:原因」,条目保留在列表里,可看原因、可重试、可清理。
三、下载列表删除功能(按状态区分语义)
- 有本地文件 → 「删除文件」(confirmDeleteLocalFile,同时清掉下载记录);
- 失败/进行中(无文件)→ 「移出下载列表」(confirmRemoveDownloadEntry):
只删记录 + stateDatabase.removeDownload,**绝不动任何歌曲文件**
(历史上"顺手清缓存"删光公放曲库的教训见 AGENTS);
- 「更多」菜单在下载列表内额外提供「移出列表」;
- SongListAdapter 的「更多」图标由装饰改为**可点/可聚焦**(遥控器可达,不再只能长按)。
版本 1.5.3(35) → 1.5.4(36);签名证书不变。测试 9 例全通过。
|
2026-10-04 00:04:20 +08:00 |
|
zijunchiang
|
669766ba60
|
V1.4.10: 修复广告过滤失效(gz.ac16.vip 广告被当成歌曲下载播放)
现场事故(新设备 SM-S9180 / Android 16,WebView 正常 → 走 JS 取址):
277 JS [KtvApi] URL OK: 7303235 ls=1 via http://w.w345.my
278 点歌编号=7303235 标题=情歌(HD) 请求源=http://w.w345.my 状态=成功 urlHost=gz.ac16.vip
279 PLAY id=7303235 title=情歌(HD) src=local
即 gz.ac16.vip 的广告视频被当成歌曲下载、缓存并播放。
三处漏洞叠加:
1. ktv_api.js 的 isDemoUrl 不认识广告域名;且"ts 文件名与编号比对"用的是
/\/(\d+)\.ts/,只匹配纯数字名 —— my_ad_video.ts 这类非数字名字直接放行;
2. SongOkDownloadManager.buildDownloadUrl 的**成功分支完全没有广告校验**
(AdVideoFilter.isAdVideo 全项目只在"缓存地址"与"原生解析"两处被调用);
3. SongApiClient.fetchFromDb 只做 isLikelyDemoUrl(纯 IP / r2.dev),挡不住广告域名。
且**内容校验挡不住广告**: 该广告通过 SongFileValidator(≥6MB/≥60s/TS 包完整),
被 isDownloaded() 一直复用,广告会反复播。
修复(单一闸门,全链路把关):
- AdVideoFilter 新增 isTrustedSongUrl(url, musicno):非 http(s)、命中广告特征
(路径 /ad_files/、my_ad_video、**域名 *.ac16.vip**)、或 URL 里 .ts 文件名不等于
点歌编号 → 一律不可信。真源恒为 /<musicno>.ts(已实测 txog.ktvsky.com 与
download.origjoy.com 两个 CDN 域共 6 首全部相符)。
- 该闸门接入全部出入口: JS isDemoUrl(同步加固 + KTV_BRIDGE_API 8→9)、
SongUrlResolver.isValidSongUrl、SongApiClient.fetchFromDb、
以及最终兜底 SongOkDownloadManager.buildDownloadUrl(成功/缓存两条分支)。
- 判定不可信时**同时删除已落盘的歌曲文件**(purgeCachedSongFile),
否则 isDownloaded() 会一直复用那个广告文件。
- 新增 SongOkDownloadManager.purgeLegacySongCacheOnce(): 升级后一次性清理历史遗留的
可疑歌曲缓存(marker: filesDir/song_cache_purged_v1)。只是让歌曲重新下载,不动用户数据。
- 新增回归测试 AdVideoFilterTest(6 例,用日志里的真实 URL 形态,含两个真源 CDN 域);
该测试当场抓到本修复自身的一个 bug:正则把扩展名也捕获进去导致真源被误杀,已修正。
版本 1.4.9(29) 到 1.4.10(30);签名证书不变。
|
2026-09-26 21:17:04 +08:00 |
|
zijunchiang
|
ba31caaa38
|
全量迁移到 Gitea: App更新检查/JS热更新端点上链 Gitea, 文档同步
- AppUpdateManager: releases/latest 改用 gitea.kasugano.cn API
- KtvJsBridge: JS 热更新改用 Gitea raw(/raw/branch/master/...)
- MainActivity/SongApiClient/DatabaseBootstrapper/MuseDbSync: 文案与注释更新
- README.md/README.en.md: 标注本仓库地址(Gitea), 保留上游框架归属链接
- AGENTS.md: 运行时端点迁移状态
|
2026-09-11 23:08:46 +08:00 |
|
zijunchiang
|
2d3751064f
|
歌曲源: 新增6源(desktok.top/mm.kk456.top/w.w345.my:66/z.w345.my/b.sktv.top/w345.my) + 多源自动排序
- ktv_api.js: HOSTS 扩为 7 源(同后台多入口), 缓存标记 7→8
- 自动排序: 解析失败的源 demote 到队尾, 成功源 promote 到队首(sourceOrder 运行时可变)
- JS→Kotlin 上报实际命中源(reportSongResult), 远程日志请求源不再写死
- SongApiClient/KtvJsBridge: lastSongSourceHost 供日志使用
|
2026-09-04 23:06:05 +08:00 |
|
zijunchiang
|
0c26f6da68
|
麦动KTV: 移除Gitee数据库(改官方Muse同步), 歌曲源切w.w345.my, 远程日志+广告屏蔽
- DatabaseBootstrapper: 删除 Gitee 分片/manifest/blob 下载逻辑, 曲库只走官方 MuseDbSync
- build.gradle: 移除 GITEE_DATABASE_* 构建参数
- MainActivity: 重置数据库文案改为官方同步
- ktv_api.js: 歌曲源仅 w.w345.my, 缓存标记 7, 广告/错号资源拦截+重试
- 远程日志: 点歌记录 编号/标题/请求源/状态
|
2026-09-04 21:23:21 +08:00 |
|