精简线路

This commit is contained in:
mtvpls
2026-03-22 16:31:47 +08:00
parent 2e7f43becf
commit 52905f8bdc
4 changed files with 42 additions and 44 deletions
+12 -8
View File
@@ -42,8 +42,6 @@ return {
{ {
sourceId, sourceId,
sourceName: '默认源', sourceName: '默认源',
lineId: 'default',
lineName: '默认线路',
episodes: [], episodes: [],
episodes_titles: [] episodes_titles: []
} }
@@ -51,7 +49,7 @@ return {
}; };
}, },
async resolvePlayUrl(ctx, { playUrl, sourceId, lineId, episodeIndex }) { async resolvePlayUrl(ctx, { playUrl, sourceId, episodeIndex }) {
return { return {
url: playUrl, url: playUrl,
type: 'auto', type: 'auto',
@@ -71,7 +69,7 @@ return {
推荐 推荐
4. `detail({ id, sourceId })` 4. `detail({ id, sourceId })`
详情 详情
5. `resolvePlayUrl({ playUrl, sourceId, lineId, episodeIndex })` 5. `resolvePlayUrl({ playUrl, sourceId, episodeIndex })`
播放前解析最终地址 播放前解析最终地址
## `ctx` 里能用什么 ## `ctx` 里能用什么
@@ -128,11 +126,12 @@ return {
{ {
sourceId: 'default', sourceId: 'default',
sourceName: '默认源', sourceName: '默认源',
lineId: 'line1',
lineName: '线路1',
episodes: [ episodes: [
'https://example.com/play/1', 'https://example.com/play/1',
'https://example.com/play/2' {
playUrl: 'https://example.com/play/2',
needResolve: false
}
], ],
episodes_titles: ['第1集', '第2集'] episodes_titles: ['第1集', '第2集']
} }
@@ -140,6 +139,12 @@ return {
} }
``` ```
说明:
- `episodes` 可以是字符串,默认等价于 `{ playUrl: '...', needResolve: true }`
- `needResolve` 默认为 `true`
- 显式写 `needResolve: false` 时,播放页会直接使用该地址,不再调用 `resolvePlayUrl`
## `resolvePlayUrl` 返回格式 ## `resolvePlayUrl` 返回格式
```js ```js
@@ -196,4 +201,3 @@ async resolvePlayUrl(ctx, { playUrl }) {
"code": "return { ... }" "code": "return { ... }"
} }
``` ```
+1 -2
View File
@@ -6278,7 +6278,6 @@ const VideoSourceScriptLab = () => {
: JSON.stringify( : JSON.stringify(
{ {
sourceId: 'main', sourceId: 'main',
lineId: 'default',
playUrl: 'https://example.com/video.m3u8', playUrl: 'https://example.com/video.m3u8',
episodeIndex: 0, episodeIndex: 0,
}, },
@@ -6469,7 +6468,7 @@ const VideoSourceScriptLab = () => {
</select> </select>
</div> </div>
<p className='text-xs text-gray-500 dark:text-gray-400'> <p className='text-xs text-gray-500 dark:text-gray-400'>
线 `sourceId``lineId` `sourceId`
</p> </p>
<textarea <textarea
value={testPayload} value={testPayload}
+1 -3
View File
@@ -9,7 +9,7 @@ import {
export const runtime = 'nodejs'; export const runtime = 'nodejs';
/** /**
* GET /api/source-script/play?key=xxx&sourceId=xxx&lineId=xxx&episodeIndex=0&playUrl=base64url&format=json * GET /api/source-script/play?key=xxx&sourceId=xxx&episodeIndex=0&playUrl=base64url&format=json
* format=json: 返回 JSON 格式(用于 play 页面) * format=json: 返回 JSON 格式(用于 play 页面)
* 默认: 返回重定向(用于播放器或外部调用) * 默认: 返回重定向(用于播放器或外部调用)
*/ */
@@ -23,7 +23,6 @@ export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url); const { searchParams } = new URL(request.url);
const key = searchParams.get('key'); const key = searchParams.get('key');
const sourceId = searchParams.get('sourceId'); const sourceId = searchParams.get('sourceId');
const lineId = searchParams.get('lineId') || 'default';
const episodeIndexRaw = searchParams.get('episodeIndex'); const episodeIndexRaw = searchParams.get('episodeIndex');
const playUrlEncoded = searchParams.get('playUrl'); const playUrlEncoded = searchParams.get('playUrl');
const format = searchParams.get('format'); const format = searchParams.get('format');
@@ -45,7 +44,6 @@ export async function GET(request: NextRequest) {
const result = await resolveSavedScriptPlayUrl({ const result = await resolveSavedScriptPlayUrl({
key, key,
sourceId, sourceId,
lineId,
episodeIndex, episodeIndex,
playUrl, playUrl,
}); });
+28 -31
View File
@@ -122,8 +122,6 @@ const DEFAULT_SCRIPT_TEMPLATE = `return {
{ {
sourceId: sourceId || 'main', sourceId: sourceId || 'main',
sourceName: '主站', sourceName: '主站',
lineId: 'default',
lineName: '默认线路',
episodes: [], episodes: [],
episodes_titles: [] episodes_titles: []
} }
@@ -131,8 +129,8 @@ const DEFAULT_SCRIPT_TEMPLATE = `return {
}; };
}, },
async resolvePlayUrl(ctx, { playUrl, sourceId, lineId, episodeIndex }) { async resolvePlayUrl(ctx, { playUrl, sourceId, episodeIndex }) {
ctx.log.info('resolvePlayUrl', sourceId, lineId, episodeIndex, playUrl); ctx.log.info('resolvePlayUrl', sourceId, episodeIndex, playUrl);
return { return {
url: playUrl, url: playUrl,
type: 'auto', type: 'auto',
@@ -746,13 +744,19 @@ export function normalizeScriptSearchResults(input: {
typeof episode === 'string' typeof episode === 'string'
? episode ? episode
: String(episode?.playUrl || episode?.url || ''); : String(episode?.playUrl || episode?.url || '');
return buildScriptPlayUrl({ const needResolve =
scriptKey: input.scriptKey, typeof episode === 'object' && episode
sourceId: input.sourceId, ? episode.needResolve !== false
lineId: String(episode?.lineId || item?.lineId || 'default'), : true;
episodeIndex: index,
playUrl, return needResolve
}); ? buildScriptPlayUrl({
scriptKey: input.scriptKey,
sourceId: input.sourceId,
episodeIndex: index,
playUrl,
})
: playUrl;
}) })
: []; : [];
@@ -788,8 +792,6 @@ export function normalizeScriptDetailResult(input: {
{ {
sourceId: input.sourceId, sourceId: input.sourceId,
sourceName: input.sourceName, sourceName: input.sourceName,
lineId: 'default',
lineName: '默认线路',
episodes: input.result?.episodes || [], episodes: input.result?.episodes || [],
episodes_titles: input.result?.episodes_titles || [], episodes_titles: input.result?.episodes_titles || [],
}, },
@@ -800,7 +802,6 @@ export function normalizeScriptDetailResult(input: {
playbacks.forEach((playback: any) => { playbacks.forEach((playback: any) => {
const playbackSourceName = String(playback.sourceName || input.sourceName); const playbackSourceName = String(playback.sourceName || input.sourceName);
const lineName = String(playback.lineName || '默认线路');
const titles = Array.isArray(playback.episodes_titles) const titles = Array.isArray(playback.episodes_titles)
? playback.episodes_titles ? playback.episodes_titles
: []; : [];
@@ -817,17 +818,21 @@ export function normalizeScriptDetailResult(input: {
: String(titles[index] || `${index + 1}`); : String(titles[index] || `${index + 1}`);
const playbackSourceId = String(playback.sourceId || input.sourceId); const playbackSourceId = String(playback.sourceId || input.sourceId);
const lineId = String(playback.lineId || 'default'); const needResolve =
const playUrl = buildScriptPlayUrl({ typeof episode === 'object' && episode
scriptKey: input.scriptKey, ? episode.needResolve !== false
sourceId: playbackSourceId, : true;
lineId, const playUrl = needResolve
episodeIndex: index, ? buildScriptPlayUrl({
playUrl: rawPlayUrl, scriptKey: input.scriptKey,
}); sourceId: playbackSourceId,
episodeIndex: index,
playUrl: rawPlayUrl,
})
: rawPlayUrl;
flattenedEpisodes.push(playUrl); flattenedEpisodes.push(playUrl);
flattenedTitles.push(`${playbackSourceName} / ${lineName} / ${episodeTitle}`); flattenedTitles.push(`${playbackSourceName} / ${episodeTitle}`);
}); });
}); });
@@ -861,8 +866,6 @@ export async function resolveScriptDetailPlaybacks(input: {
{ {
sourceId: input.sourceId, sourceId: input.sourceId,
sourceName: input.sourceId, sourceName: input.sourceId,
lineId: 'default',
lineName: '默认线路',
episodes: input.result?.episodes || [], episodes: input.result?.episodes || [],
episodes_titles: input.result?.episodes_titles || [], episodes_titles: input.result?.episodes_titles || [],
}, },
@@ -882,7 +885,6 @@ export async function resolveScriptDetailPlaybacks(input: {
const resolvedPlaybacks = await Promise.all( const resolvedPlaybacks = await Promise.all(
playbacks.map(async (playback: any) => { playbacks.map(async (playback: any) => {
const playbackSourceId = String(playback.sourceId || input.sourceId); const playbackSourceId = String(playback.sourceId || input.sourceId);
const lineId = String(playback.lineId || 'default');
const episodes = Array.isArray(playback.episodes) ? playback.episodes : []; const episodes = Array.isArray(playback.episodes) ? playback.episodes : [];
const resolvedEpisodes = await Promise.all( const resolvedEpisodes = await Promise.all(
@@ -898,7 +900,6 @@ export async function resolveScriptDetailPlaybacks(input: {
compiled.resolvePlayUrl(ctx, { compiled.resolvePlayUrl(ctx, {
playUrl, playUrl,
sourceId: playbackSourceId, sourceId: playbackSourceId,
lineId,
episodeIndex: index, episodeIndex: index,
}) })
), ),
@@ -941,14 +942,12 @@ function decodeBase64Url(value: string) {
export function buildScriptPlayUrl(input: { export function buildScriptPlayUrl(input: {
scriptKey: string; scriptKey: string;
sourceId: string; sourceId: string;
lineId: string;
episodeIndex: number; episodeIndex: number;
playUrl: string; playUrl: string;
}) { }) {
const searchParams = new URLSearchParams({ const searchParams = new URLSearchParams({
key: input.scriptKey, key: input.scriptKey,
sourceId: input.sourceId, sourceId: input.sourceId,
lineId: input.lineId,
episodeIndex: String(input.episodeIndex), episodeIndex: String(input.episodeIndex),
playUrl: encodeBase64Url(input.playUrl), playUrl: encodeBase64Url(input.playUrl),
}); });
@@ -962,7 +961,6 @@ export function parseScriptPlayUrlValue(value: string) {
export async function resolveSavedScriptPlayUrl(input: { export async function resolveSavedScriptPlayUrl(input: {
key: string; key: string;
sourceId: string; sourceId: string;
lineId: string;
episodeIndex: number; episodeIndex: number;
playUrl: string; playUrl: string;
configValues?: Record<string, string>; configValues?: Record<string, string>;
@@ -983,7 +981,6 @@ export async function resolveSavedScriptPlayUrl(input: {
compiled.resolvePlayUrl(ctx, { compiled.resolvePlayUrl(ctx, {
playUrl: input.playUrl, playUrl: input.playUrl,
sourceId: input.sourceId, sourceId: input.sourceId,
lineId: input.lineId,
episodeIndex: input.episodeIndex, episodeIndex: input.episodeIndex,
}) })
), ),