Try alternate provider episode sources

This commit is contained in:
Dymas
2026-09-05 09:27:21 +02:00
parent 5718e5fe91
commit a29affd9be
6 changed files with 182 additions and 52 deletions
+41 -13
View File
@@ -76,20 +76,39 @@ function qualityScore(source, wanted) {
return -Math.abs(target - value);
}
function sourceMatchesMode(source, mode) {
const requested = String(mode || "sub").toLowerCase();
const type = String(source?.type || source?.lang || requested).toLowerCase();
if (requested === "dub") return type === "dub";
if (requested === "sub") return type === "sub" || type === "softsub" || type === "hsub" || type === "hardsub";
return type === requested;
}
async function resolve(provider, episodeId, mode, quality) {
let sourcesPayload = await provider.fetchEpisodeSources(episodeId, mode);
let sources = Array.isArray(sourcesPayload?.sources) ? sourcesPayload.sources : [];
if (!sources.length && mode === "dub") {
sourcesPayload = await provider.fetchEpisodeSources(episodeId, "sub");
sources = Array.isArray(sourcesPayload?.sources) ? sourcesPayload.sources : [];
}
const candidates = await resolveAll(provider, episodeId, mode, quality);
if (candidates.length) return candidates[0];
throw new Error("Could not resolve a playable source.");
}
async function resolveAll(provider, episodeId, mode, quality) {
const sourcesPayload = await provider.fetchEpisodeSources(episodeId, mode);
const sources = Array.isArray(sourcesPayload?.sources) ? sourcesPayload.sources : [];
if (!sources.length) throw new Error("No episode sources were returned.");
sources.sort((a, b) => qualityScore(b, quality) - qualityScore(a, quality));
const resolvedSources = [];
for (const source of sources) {
const resolved = source.isUnresolved && provider.processServer
? await provider.processServer(source.rawServer || source)
: source;
let resolved = null;
try {
resolved = source.isUnresolved && provider.processServer
? await provider.processServer(source.rawServer || source)
: source;
} catch (err) {
process.stderr.write(`Source ${source.name || source.quality || "server"} failed to resolve: ${err?.message || err}\n`);
continue;
}
if (resolved?.url) {
const sourceType = resolved.type || resolved.lang || source.type || source.lang || mode;
if (!sourceMatchesMode({ type: sourceType }, mode)) continue;
const headers = Object.assign({}, resolved.headers || {});
try {
const host = new URL(resolved.url).hostname;
@@ -98,17 +117,18 @@ async function resolve(provider, episodeId, mode, quality) {
}
} catch (_) {}
if (!headers.Referer && fallbackReferer) headers.Referer = fallbackReferer;
return {
resolvedSources.push({
url: resolved.url,
isM3U8: Boolean(resolved.isM3U8 || String(resolved.url).includes(".m3u8")),
quality: resolved.quality || source.quality || source.name || "auto",
type: resolved.type || source.type || mode,
type: sourceType,
headers,
subtitles: resolved.subtitles || sourcesPayload.subtitles || [],
};
server: source.name || resolved.name || resolved.quality || "server",
});
}
}
throw new Error("Could not resolve a playable source.");
return resolvedSources;
}
async function main() {
@@ -166,6 +186,14 @@ async function main() {
return;
}
if (command === "resolve-all") {
const mode = rest[1] || "sub";
const quality = rest[2] || "best";
const data = await resolveAll(provider, id, mode, quality);
console.log(JSON.stringify({ sources: data }));
return;
}
fail(`Unknown command: ${command}`);
}