Try alternate provider episode sources
This commit is contained in:
+41
-13
@@ -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}`);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user