diff --git a/README.md b/README.md index 165e3b4..4d33cfd 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ - **播放器联动**:暂停时弹幕冻结,跳转时自动清除,全屏模式下正常显示 - **多 API 管理**:每个用户可添加多个弹幕 API,选择当前使用的 API - **优先级规则**:用户选择的弹幕 API 优先于系统默认配置 -- **环境变量预设**:可通过 `NEXT_PUBLIC_DANMAKU_API_URL` 为所有用户预设弹幕 API 地址 +- **环境变量预设**:可通过 `DANMAKU_API_URL` 或 `NEXT_PUBLIC_DANMAKU_API_URL` 为所有用户预设弹幕 API 地址 ### 广告过滤 @@ -456,7 +456,7 @@ docker run -d -p 3000:3000 \ | 变量名 | 说明 | 默认值 | |--------|------|--------| -| `NEXT_PUBLIC_DANMAKU_API_URL` | 弹幕聚合 API 地址 | - | +| `DANMAKU_API_URL` / `NEXT_PUBLIC_DANMAKU_API_URL` | 弹幕聚合 API 地址 | - | 需要自建或使用兼容 [danmu_api](https://github.com/huangxd-/danmu_api) 格式的弹幕聚合服务。 @@ -611,7 +611,7 @@ docker run -e PORT=8080 -p 8080:8080 --name kvideo kuekhaoyang/kvideo:latest | `MERGE_SOURCES` / `NEXT_PUBLIC_MERGE_SOURCES` | 启用合并同名源显示(`true`/`1`) | - | | `AD_KEYWORDS` / `NEXT_PUBLIC_AD_KEYWORDS` | 广告过滤关键词 | - | | `AD_KEYWORDS_FILE` | 广告关键词文件路径 | - | -| `NEXT_PUBLIC_DANMAKU_API_URL` | 弹幕聚合 API 地址 | - | +| `DANMAKU_API_URL` / `NEXT_PUBLIC_DANMAKU_API_URL` | 弹幕聚合 API 地址 | - | | `UPSTASH_REDIS_REST_URL` | Upstash Redis REST URL(跨设备同步:配置、历史、收藏) | - | | `UPSTASH_REDIS_REST_TOKEN` | Upstash Redis REST Token | - | diff --git a/app/api/auth/route.ts b/app/api/auth/route.ts index eae7d08..c9f7c5c 100644 --- a/app/api/auth/route.ts +++ b/app/api/auth/route.ts @@ -15,6 +15,7 @@ const PERSIST_SESSION = process.env.PERSIST_SESSION !== 'false'; // default true const SUBSCRIPTION_SOURCES = process.env.SUBSCRIPTION_SOURCES || process.env.NEXT_PUBLIC_SUBSCRIPTION_SOURCES || ''; const IPTV_SOURCES = process.env.IPTV_SOURCES || process.env.NEXT_PUBLIC_IPTV_SOURCES || ''; const MERGE_SOURCES = process.env.MERGE_SOURCES || process.env.NEXT_PUBLIC_MERGE_SOURCES || ''; +const DANMAKU_API_URL = process.env.DANMAKU_API_URL || process.env.NEXT_PUBLIC_DANMAKU_API_URL || ''; // Backward compat: ACCESS_PASSWORD acts as ADMIN_PASSWORD if ADMIN_PASSWORD is not set const effectiveAdminPassword = ADMIN_PASSWORD || ACCESS_PASSWORD; @@ -73,6 +74,7 @@ export async function GET() { subscriptionSources: SUBSCRIPTION_SOURCES, iptvSources: IPTV_SOURCES, mergeSources: MERGE_SOURCES, + danmakuApiUrl: DANMAKU_API_URL, }); } diff --git a/components/PasswordGate.tsx b/components/PasswordGate.tsx index ae62ad9..ddb476e 100644 --- a/components/PasswordGate.tsx +++ b/components/PasswordGate.tsx @@ -53,6 +53,20 @@ function syncMergeSources(rawValue: string) { } } +function syncDanmakuApiUrl(rawValue: string) { + if (!rawValue) return; + + const buildTimeValue = process.env.NEXT_PUBLIC_DANMAKU_API_URL || ''; + + const settings = settingsStore.getSettings(); + if (!settings.danmakuApiUrl || settings.danmakuApiUrl === buildTimeValue) { + settingsStore.saveSettings({ + ...settings, + danmakuApiUrl: rawValue, + }); + } +} + export function PasswordGate({ children, hasAuth: initialHasAuth }: { children: React.ReactNode, hasAuth: boolean }) { // Enable background subscription syncing globally useSubscriptionSync(); @@ -106,6 +120,10 @@ export function PasswordGate({ children, hasAuth: initialHasAuth }: { children: syncMergeSources(data.mergeSources); } + if (data.danmakuApiUrl) { + syncDanmakuApiUrl(data.danmakuApiUrl); + } + // Re-evaluate lock status with confirmed server state const confirmLocked = data.hasAuth && !isAuthenticated; setIsLocked(confirmLocked);