Merge pull request #128 from mayziran/fix/danmaku-runtime-env

docker弹幕环境变量修复
This commit is contained in:
Kuek Hao Yang
2026-04-02 19:39:38 +08:00
committed by GitHub
4 changed files with 40 additions and 4 deletions
+3 -3
View File
@@ -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 | - |
+2
View File
@@ -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,
});
}
+17 -1
View File
@@ -3,7 +3,7 @@
import { useState, useEffect } from 'react';
import { getSession, setSession } from '@/lib/store/auth-store';
import { useSubscriptionSync } from '@/lib/hooks/useSubscriptionSync';
import { settingsStore } from '@/lib/store/settings-store';
import { hasStoredAppSetting, settingsStore } from '@/lib/store/settings-store';
import { useIPTVStore } from '@/lib/store/iptv-store';
import { Lock } from 'lucide-react';
@@ -53,6 +53,18 @@ function syncMergeSources(rawValue: string) {
}
}
function syncDanmakuApiUrl(rawValue: string) {
if (!rawValue || hasStoredAppSetting('danmakuApiUrl')) return;
const settings = settingsStore.getSettings();
if (settings.danmakuApiUrl !== rawValue) {
settingsStore.saveSettings({
...settings,
danmakuApiUrl: rawValue,
});
}
}
export function PasswordGate({ children, hasAuth: initialHasAuth }: { children: React.ReactNode, hasAuth: boolean }) {
// Enable background subscription syncing globally
useSubscriptionSync();
@@ -106,6 +118,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);
+18
View File
@@ -139,6 +139,24 @@ function getDefaultAppSettings(): AppSettings {
};
}
export function hasStoredAppSetting(key: keyof AppSettings): boolean {
if (typeof window === 'undefined') {
return false;
}
const stored = localStorage.getItem(SETTINGS_KEY);
if (!stored) {
return false;
}
try {
const parsed = JSON.parse(stored);
return Object.prototype.hasOwnProperty.call(parsed, key);
} catch {
return false;
}
}
export const settingsStore = {
getSettings(): AppSettings {
// SSR: Return defaults