增加客户端去广告配置

This commit is contained in:
mtvpls
2026-07-17 19:14:01 +08:00
parent bd779b237c
commit 1bbea13c62
5 changed files with 332 additions and 46 deletions
+96
View File
@@ -70,6 +70,78 @@ import {
export const runtime = 'nodejs';
/**
* 解析站点 origin。
* 优先级:SITE_BASE(站点 url 环境变量)> NEXT_PUBLIC_SITE_URL > 请求头 Host。
*/
function getRequestSiteOrigin(request: NextRequest): string {
const fromEnv =
(process.env.SITE_BASE || '').trim() ||
(process.env.NEXT_PUBLIC_SITE_URL || '').trim();
if (fromEnv) {
return fromEnv.replace(/\/$/, '');
}
let host =
request.headers.get('host') || request.headers.get('x-forwarded-host');
if (host && !/^[a-zA-Z0-9.-]+(:\d+)?$/.test(host)) {
host = null;
}
if (!host) {
try {
host = new URL(request.url).host;
} catch {
host = 'localhost';
}
}
const proto =
request.headers.get('x-forwarded-proto') ||
(host.includes('localhost') || host.includes('127.0.0.1')
? 'http'
: 'https');
return `${proto}://${host}`.replace(/\/$/, '');
}
/**
* MoonTVPlus APP / OrionTV 客户端:对配置的视频源 m3u8 套一层去广告代理。
* UA 小写包含 "moontvplus app" 或 "oriontv" 时生效(不匹配仅含 moontvplus 的其它客户端)。
*/
function applyClientAdProxyToEpisodes(
request: NextRequest,
sourceCode: string,
episodes: string[] | undefined,
clientAdSourceApis: string[] | undefined
): string[] | undefined {
if (!episodes || episodes.length === 0) return episodes;
if (!clientAdSourceApis || !clientAdSourceApis.includes(sourceCode)) {
return episodes;
}
const ua = (request.headers.get('user-agent') || '').toLowerCase();
if (!ua.includes('moontvplus app') && !ua.includes('oriontv')) {
return episodes;
}
const origin = getRequestSiteOrigin(request);
return episodes.map((episode) => {
if (!episode || typeof episode !== 'string') return episode;
if (
episode.includes('/api/proxy-m3u8') ||
episode.includes('/api/proxy/vod/m3u8')
) {
return episode;
}
// 仅处理 http(s) 直链 m3u8,站内相对播放地址不改写
if (!/^https?:\/\//i.test(episode)) return episode;
return `${origin}/api/proxy-m3u8?url=${encodeURIComponent(episode)}`;
});
}
function formatNetdiskEpisodeTitle(
parsed: {
season?: number;
@@ -1215,8 +1287,32 @@ export async function GET(request: NextRequest) {
proxyMode: apiSite.proxyMode || false,
};
// 客户端广告配置:指定源 + APP/OrionTV UA 时 m3u8 套 proxy-m3u8
const adminConfig = await getConfig();
const clientAdEnabled = (adminConfig.ClientAdSourceApis || []).includes(
sourceCode
);
resultWithProxy.episodes =
applyClientAdProxyToEpisodes(
request,
sourceCode,
resultWithProxy.episodes,
adminConfig.ClientAdSourceApis
) || resultWithProxy.episodes;
const cacheTime = await getCacheTime();
// 同一源在不同 UA 下 episodes 可能不同,避免 CDN/共享缓存串号
if (clientAdEnabled) {
return NextResponse.json(resultWithProxy, {
headers: {
'Cache-Control': 'private, no-store',
Vary: 'User-Agent',
'Netlify-Vary': 'query',
},
});
}
return NextResponse.json(resultWithProxy, {
headers: {
'Cache-Control': `public, max-age=${cacheTime}, s-maxage=${cacheTime}`,