mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-12 23:33:43 +08:00
Merge pull request #128 from mayziran/fix/danmaku-runtime-env
docker弹幕环境变量修复
This commit is contained in:
@@ -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 | - |
|
||||
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user