增加客户端去广告配置
This commit is contained in:
@@ -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}`,
|
||||
|
||||
Reference in New Issue
Block a user