Compare commits

..
2 Commits
Author SHA1 Message Date
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 21eca10ee2 docs: 同步策略迁移至 Gitea(origin), Gitee 停用并加钩子拦截 2026-09-11 22:57:42 +08:00
10 changed files with 47 additions and 37 deletions
+25 -20
View File
@@ -2,33 +2,38 @@
> 本文件供后续开发(含 AI 助手会话)遵循,优先级高于默认习惯。 > 本文件供后续开发(含 AI 助手会话)遵循,优先级高于默认习惯。
## 一、代码同步策略(重要,2026-09-11 起生效 ## 一、代码同步策略(2026-09-11 更新
**自动推送 Gitee:已禁用。** **代码主仓库已迁移至 Giteahttps://gitea.kasugano.cn/zijunchiang/maidong-ktv**
- ✅ 允许:本地 `git add` / `git commit`(保留本地提交历史,便于回滚与对比) | 远端 | 地址 | 状态 |
- ❌ 禁止:**自动执行 `git push`**(包括"完成改动后顺手推送"这类默认动作) |---|---|---|
- ⏸ 仅在用户**明确指示**(例如"推送到 Gitee"/"同步代码")时,才执行推送 | `origin` | `https://gitea.kasugano.cn/zijunchiang/maidong-ktv.git` | ✅ 主仓库,**同步目标** |
| `gitee` | `https://gitee.com/zijunchiang/maidong-ktv.git` | ⛔ 已停用(推送被钩子拦截) |
### 手动启用/推送方式 - ✅ 预期动作:完成改动 → 本地 `git commit``git push origin master`(同步到 Gitea
- ⛔ 禁止:推送到 Gitee`pre-push` 钩子会拦截,避免误推送)
- 凭据:Gitea 访问令牌 `dsh-sync`(可在 Gitea「设置 → 应用 → 访问令牌」随时吊销),
存放于 `~/.git-credentials-gitea`(权限 600),由本仓库级 `credential.helper` 引用;
账号密码不写入仓库配置。
已安装 `pre-push` 钩子做拦截(防止误推送)。启用推送二选一: ### 推送方式
```bash ```bash
# 方式 1:创建启用标记(推荐,推送后建议删除标记恢复拦截) cd /home/zijun/dsh/maidongktv/maidong-ktv
touch .git/ALLOW_GITEE_PUSH git push origin master # origin = Gitea(主仓库)
git push origin master git push --no-verify gitee master # 仅在确需回推 Gitee 时使用
rm -f .git/ALLOW_GITEE_PUSH
# 方式 2:临时绕过钩子
git push --no-verify origin master
``` ```
### 远端信息 ### 运行时端点(已全部迁移到 Gitea
- 仓库:https://gitee.com/zijunchiang/maidong-ktv (公开) App 内部两处端点已指向 Gitea(随本版 APK 生效):
- 分支:`master`
- 发布:Gitee Releasetag 形如 `v1.2.5`,需附 `.apk` 附件,供 App 内检查更新) - `AppUpdateManager.kt``gitea.kasugano.cn/api/v1/repos/zijunchiang/maidong-ktv/releases/latest`App 内检查更新)
- `KtvJsBridge.kt``gitea.kasugano.cn/zijunchiang/maidong-ktv/raw/branch/master/app/src/main/assets/mobile/ktv_api.js`JS 热更新)
> 注意:Gitea 的 raw 规范路径是 `/raw/branch/<分支>/<文件>``/raw/<分支>/<文件>` 会 303 跳转。
> 发布新版本时需在 Gitea 创建 Release 并上传 `.apk` 附件(Gitea Release API 的 `assets[].browser_download_url` 供 App 下载)。
## 二、构建与产物 ## 二、构建与产物
@@ -66,6 +71,6 @@ $BT/apksigner verify 目标名.apk
- **歌曲源**`app/src/main/assets/mobile/ktv_api.js``CONFIG.HOSTS`(多源自动排序,失败源沉底) - **歌曲源**`app/src/main/assets/mobile/ktv_api.js``CONFIG.HOSTS`(多源自动排序,失败源沉底)
- **JS 热更新**:改动 `ktv_api.js` 必须同步提升 `KTV_BRIDGE_API: N` 标记(JS 与 `KtvJsBridge.kt` 两处校验),否则设备仍用缓存旧脚本 - **JS 热更新**:改动 `ktv_api.js` 必须同步提升 `KTV_BRIDGE_API: N` 标记(JS 与 `KtvJsBridge.kt` 两处校验),否则设备仍用缓存旧脚本
- **曲库**:只走官方 Muse 同步(`MuseDbSync`),不再依赖 Gitee 数据库文件 - **曲库**:只走官方 Muse 同步(`MuseDbSync`),不再依赖代码仓库数据库文件
- **麦克风**`MicActivator` 常驻占用输入通道(TV/投影需占用后才有演唱声音输出),外接设备热插拔会自动重建 - **麦克风**`MicActivator` 常驻占用输入通道(TV/投影需占用后才有演唱声音输出),外接设备热插拔会自动重建
- **发布**Gitee 仓库必须保持 **public**,否则 App 内检查更新/下载会 403 - **仓库可见性**Gitea 仓库保持 **public**(若后续把 App 更新/热更新端点迁到 Gitea,非 public 会导致 403
+3 -1
View File
@@ -59,6 +59,8 @@
## Project Notice ## Project Notice
> **This repository**: [https://gitea.kasugano.cn/zijunchiang/maidong-ktv](https://gitea.kasugano.cn/zijunchiang/maidong-ktv)
>
> **UI/feature framework credit**: [https://gitee.com/yangyachao-X/maidong-ktv](https://gitee.com/yangyachao-X/maidong-ktv) > **UI/feature framework credit**: [https://gitee.com/yangyachao-X/maidong-ktv](https://gitee.com/yangyachao-X/maidong-ktv)
> >
> This repository reworks the upstream "Maidong KTV" UI and feature framework, and the core/data layer was > This repository reworks the upstream "Maidong KTV" UI and feature framework, and the core/data layer was
@@ -68,7 +70,7 @@
Highlights of the reworked data layer: Highlights of the reworked data layer:
- **Library**: synced exclusively from the official Muse service - **Library**: synced exclusively from the official Muse service
(`mconn.cherryonline.cn` `mls-api/v1/sqlite/sync`); Gitee hosts code only, no database files. (`mconn.cherryonline.cn` `mls-api/v1/sqlite/sync`); the code host carries source only, no database files.
- **Song source**: `w.w345.my` (`i.php` token → `do.php` playback URL) with fixed device identity and - **Song source**: `w.w345.my` (`i.php` token → `do.php` playback URL) with fixed device identity and
reproduced signing; ad/mismatched resources (e.g. `wb66.cn/.../719.ts`) are blocked and retried. reproduced signing; ad/mismatched resources (e.g. `wb66.cn/.../719.ts`) are blocked and retried.
- **JS hot-update**: `app/src/main/assets/mobile/ktv_api.js`, requires the `KTV_BRIDGE_API: 7` marker. - **JS hot-update**: `app/src/main/assets/mobile/ktv_api.js`, requires the `KTV_BRIDGE_API: 7` marker.
+4 -2
View File
@@ -10,6 +10,8 @@
## 📌 项目说明 ## 📌 项目说明
> **本仓库**[https://gitea.kasugano.cn/zijunchiang/maidong-ktv](https://gitea.kasugano.cn/zijunchiang/maidong-ktv)
>
> **内容框架来源**[https://gitee.com/yangyachao-X/maidong-ktv](https://gitee.com/yangyachao-X/maidong-ktv) > **内容框架来源**[https://gitee.com/yangyachao-X/maidong-ktv](https://gitee.com/yangyachao-X/maidong-ktv)
> >
> 本仓库基于上游「麦动 KTV」的界面与功能框架进行改造,并使用 **DSHDeepSeek Harness** 重写内核与数据源:重新实现曲库同步、歌曲源接入、设备认证、风控应对、远程日志与广告屏蔽等底层逻辑。上游框架的版权归原作者所有,本项目仅作学习与技术交流。 > 本仓库基于上游「麦动 KTV」的界面与功能框架进行改造,并使用 **DSHDeepSeek Harness** 重写内核与数据源:重新实现曲库同步、歌曲源接入、设备认证、风控应对、远程日志与广告屏蔽等底层逻辑。上游框架的版权归原作者所有,本项目仅作学习与技术交流。
@@ -46,11 +48,11 @@
## 内核与数据源(DSH 重写部分) ## 内核与数据源(DSH 重写部分)
- **曲库**:统一走**官方 Muse 同步**`mconn.cherryonline.cn` `mls-api/v1/sqlite/sync`,RSA 登录 + 增量文件校验),不再依赖 Gitee 承载数据库;Gitee 仓库仅存代码。 - **曲库**:统一走**官方 Muse 同步**`mconn.cherryonline.cn` `mls-api/v1/sqlite/sync`,RSA 登录 + 增量文件校验),不再依赖代码托管仓库承载数据库
- **歌曲源**:接入 `w.w345.my``i.php` 取 token → `do.php` 解析播放地址),固定设备标识并复刻签名算法;广告/错号资源(如返回 `wb66.cn/.../719.ts` 或文件名与 musicno 不一致)会被拦截并重试。 - **歌曲源**:接入 `w.w345.my``i.php` 取 token → `do.php` 解析播放地址),固定设备标识并复刻签名算法;广告/错号资源(如返回 `wb66.cn/.../719.ts` 或文件名与 musicno 不一致)会被拦截并重试。
- **风控应对**:源对陌生出口 IP 存在试用窗口(约 10 分钟,403"检测到异常行为"),App 检测到 403 后弹窗提示更换公网 IP;同 token 退避重试,不放大请求量。 - **风控应对**:源对陌生出口 IP 存在试用窗口(约 10 分钟,403"检测到异常行为"),App 检测到 403 后弹窗提示更换公网 IP;同 token 退避重试,不放大请求量。
- **JS 热更新**:歌曲接口逻辑在 `app/src/main/assets/mobile/ktv_api.js`,安装后从本仓库自动拉取兼容版本(须保留 `KTV_BRIDGE_API: 7` 标记)。 - **JS 热更新**:歌曲接口逻辑在 `app/src/main/assets/mobile/ktv_api.js`,安装后从本仓库自动拉取兼容版本(须保留 `KTV_BRIDGE_API: 7` 标记)。
- **应用更新**:以 Gitee Release 标签作为版本号(如 `1.2.5`),Release 需附带一个 `.apk` 附件;仅当标签高于当前 `BuildConfig.VERSION_NAME` 时提示下载。 - **应用更新**:以 Gitea Release 标签作为版本号(如 `1.2.5`),Release 需附带一个 `.apk` 附件;仅当标签高于当前 `BuildConfig.VERSION_NAME` 时提示下载。
## 🔧 编译教程 ## 🔧 编译教程
+1 -1
View File
@@ -1,7 +1,7 @@
/** /**
* KTV Song API - JS Hot Update Module * KTV Song API - JS Hot Update Module
* ==================================== * ====================================
* 从 Gitee 热更新, App 无需发版即可修复 API 变更 * 从 Gitea 热更新, App 无需发版即可修复 API 变更
* *
* 用法: * 用法:
* const api = new KtvApi({proxy: 'http://127.0.0.1:7897'}) * const api = new KtvApi({proxy: 'http://127.0.0.1:7897'})
@@ -11,10 +11,10 @@ import java.io.FileOutputStream
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.net.URL import java.net.URL
/** Gitee Release based in-app updater. */ /** Gitea Release based in-app updater. */
object AppUpdateManager { object AppUpdateManager {
private const val LATEST_RELEASE_API = private const val LATEST_RELEASE_API =
"https://gitee.com/api/v5/repos/zijunchiang/maidong-ktv/releases/latest" "https://gitea.kasugano.cn/api/v1/repos/zijunchiang/maidong-ktv/releases/latest"
data class Release( data class Release(
val version: String, val version: String,
@@ -54,7 +54,7 @@ object AppUpdateManager {
apkName = apkName, apkName = apkName,
) )
}) })
}, "gitee-update-check").start() }, "gitea-update-check").start()
} }
fun download( fun download(
@@ -105,7 +105,7 @@ object AppUpdateManager {
require(partial.renameTo(target)) { "无法保存安装包" } require(partial.renameTo(target)) { "无法保存安装包" }
target target
}) })
}, "gitee-update-download").start() }, "gitea-update-download").start()
} }
/** /**
@@ -7,8 +7,8 @@ import java.util.Locale
/** /**
* 曲库下载引导(仅官方 Muse 同步源)。 * 曲库下载引导(仅官方 Muse 同步源)。
* *
* 说明:已移除 Gitee 数据库分片/镜像下载路径(database_publish 不再发布到 Gitee * 说明:已移除分片/镜像数据库下载路径(database_publish 不再发布到代码仓库
* Gitee 仓库此后只存代码)。曲库统一从官方 Muse 服务(mconn.cherryonline.cn mls-api * 代码仓库此后只存代码)。曲库统一从官方 Muse 服务(mconn.cherryonline.cn mls-api
* 同步,由 [MuseDbSync] 负责登录、同步、校验与安装;本类只做版本文件与可读错误包装。 * 同步,由 [MuseDbSync] 负责登录、同步、校验与安装;本类只做版本文件与可读错误包装。
*/ */
object DatabaseBootstrapper { object DatabaseBootstrapper {
@@ -30,15 +30,16 @@ import javax.crypto.Cipher
* 在隐藏 WebView 中运行可热更新的歌曲接口脚本。 * 在隐藏 WebView 中运行可热更新的歌曲接口脚本。
* *
* JS 决定接口地址、参数、签名和响应解析;Android 只提供 HTTP 与 RSA 这两个 * JS 决定接口地址、参数、签名和响应解析;Android 只提供 HTTP 与 RSA 这两个
* WebView 中不可靠的底层能力。这样接口变化时只需更新 Gitee 上的 ktv_api.js。 * WebView 中不可靠的底层能力。这样接口变化时只需更新 Gitea 上的 ktv_api.js。
*/ */
class KtvJsBridge(context: Context) { class KtvJsBridge(context: Context) {
companion object { companion object {
private const val TAG = "KtvJsBridge" private const val TAG = "KtvJsBridge"
private const val JS_FILE = "mobile/ktv_api.js" private const val JS_FILE = "mobile/ktv_api.js"
private const val CACHE_FILE = "ktv_api_cache.js" private const val CACHE_FILE = "ktv_api_cache.js"
// 热更新脚本地址(Gitea 主仓库; raw 规范路径为 /raw/branch/<分支>/<文件>)
private const val REMOTE_JS_URL = private const val REMOTE_JS_URL =
"https://gitee.com/zijunchiang/maidong-ktv/raw/master/app/src/main/assets/mobile/ktv_api.js" "https://gitea.kasugano.cn/zijunchiang/maidong-ktv/raw/branch/master/app/src/main/assets/mobile/ktv_api.js"
private const val MAX_RESPONSE_BYTES = 2 * 1024 * 1024 private const val MAX_RESPONSE_BYTES = 2 * 1024 * 1024
private const val JS_REQUEST_TIMEOUT_MS = 180_000 private const val JS_REQUEST_TIMEOUT_MS = 180_000
// 当前歌曲源 w.w345.my 使用的设备标识(mac + sn)。与用户抓包示例一致, // 当前歌曲源 w.w345.my 使用的设备标识(mac + sn)。与用户抓包示例一致,
@@ -250,7 +251,7 @@ class KtvJsBridge(context: Context) {
cacheFile.writeText(script, Charsets.UTF_8) cacheFile.writeText(script, Charsets.UTF_8)
tempFile.delete() tempFile.delete()
} }
Log.i(TAG, "JS cache updated from Gitee (${script.length} chars)") Log.i(TAG, "JS cache updated from Gitea (${script.length} chars)")
// 启动后刚拉到的新版本直接生效;若已有请求在执行,则留到下次启动。 // 启动后刚拉到的新版本直接生效;若已有请求在执行,则留到下次启动。
mainHandler.post { mainHandler.post {
if (ready && callbacks.isEmpty() && !destroyed) { if (ready && callbacks.isEmpty() && !destroyed) {
@@ -8232,7 +8232,7 @@ class MainActivity : AppCompatActivity() {
SettingsEntry( SettingsEntry(
R.drawable.ott_ic_data_upgrade, R.drawable.ott_ic_data_upgrade,
"应用更新", "应用更新",
"当前版本 ${BuildConfig.VERSION_NAME},更新来源:Gitee Release", "当前版本 ${BuildConfig.VERSION_NAME},更新来源:Gitea Release",
"检查更新", "检查更新",
) { checkAppUpdate(true) }, ) { checkAppUpdate(true) },
SettingsEntry(R.drawable.ott_ic_about_us, "关于", actionText = "查看") { showAboutDialog() }, SettingsEntry(R.drawable.ott_ic_about_us, "关于", actionText = "查看") { showAboutDialog() },
@@ -20,7 +20,7 @@ import javax.crypto.Cipher
/** /**
* 官方曲库同步:login → cookie → sqlite/sync → 下载 gz → 解压安装。 * 官方曲库同步:login → cookie → sqlite/sync → 下载 gz → 解压安装。
* *
* 这是原版「时光KTV / 麦动」的曲库分发方式,取代此前临时使用的 Gitee 分片方案。 * 这是原版「时光KTV / 麦动」的曲库分发方式,取代此前临时使用的分片分发方案。
* 授权门控发生在服务端(未授权设备 sync 返回空 files),本地只负责完整复刻请求协议。 * 授权门控发生在服务端(未授权设备 sync 返回空 files),本地只负责完整复刻请求协议。
*/ */
object MuseDbSync { object MuseDbSync {
@@ -10,8 +10,8 @@ import java.util.concurrent.atomic.AtomicReference
/** /**
* 歌曲 API 客户端 —— JS 热更新桥接 * 歌曲 API 客户端 —— JS 热更新桥接
* ================================= * =================================
* - 通过 KtvJsBridge 调用 Gitee 上的 JS 脚本 * - 通过 KtvJsBridge 调用 Gitea 上的 JS 脚本
* - API 变更时只需更新 Gitee JS 文件,App 无需发版 * - API 变更时只需更新 Gitea JS 文件,App 无需发版
* - 首次播放时实时获取 URL,不存在过期问题 * - 首次播放时实时获取 URL,不存在过期问题
*/ */
object SongApiClient { object SongApiClient {