hytranslator / dist /addon /streams.js
no1b4me's picture
Upload 61 files
762fa11 verified
import { searchTorrents, } from "../torrent/search.js";
import { getTorrentInfo } from "../torrent/webtorrent.js";
import { getReadableSize, isSubtitleFile, isVideoFile } from "../utils/file.js";
import { getTitles } from "../utils/imdb.js";
import { guessLanguage } from "../utils/language.js";
import { guessQuality } from "../utils/quality.js";
import { isFileNameMatch, isTorrentNameMatch } from "../utils/shows.js";
export const streamHandler = async ({ type, id, config, req }) => {
let torrents = [];
const categories = [];
if (type === "movie")
categories.push("movie");
if (type === "series")
categories.push("show");
const sources = [];
if (config.enableJackett === "on")
sources.push("jackett");
if (config.enableNcore === "on")
sources.push("ncore");
if (config.enableInsane === "on")
sources.push("insane");
if (config.enableItorrent === "on")
sources.push("itorrent");
if (config.enableYts === "on")
sources.push("yts");
if (config.enableEztv === "on")
sources.push("eztv");
const [imdbId, season, episode] = id.split(":");
const queries = [imdbId];
if (config.searchByTitle === "on")
queries.push(...(await getTitles(imdbId)));
torrents = (await Promise.all(queries.map((query) => searchTorrents(query, {
categories,
sources,
jackett: {
url: config.jackettUrl,
apiKey: config.jackettKey,
},
ncore: {
user: config.nCoreUser,
password: config.nCorePassword,
},
insane: {
user: config.insaneUser,
password: config.insanePassword,
},
})))).flat();
torrents = dedupeTorrents(torrents);
torrents = torrents.filter((torrent) => {
if (!torrent.seeds)
return false;
if (torrent.category?.includes("DVD"))
return false;
if (!isAllowedFormat(config, torrent.name))
return false;
if (!isAllowedQuality(config, guessQuality(torrent.name).quality))
return false;
if (season &&
episode &&
!isTorrentNameMatch(torrent.name, Number(season), Number(episode)))
return false;
return true;
});
let streams = (await Promise.all(torrents.map((torrent) => getStreamsFromTorrent(req, torrent, season, episode)))).flat();
streams = streams.filter((stream) => {
if (!isAllowedFormat(config, stream.fileName))
return false;
if (!isAllowedQuality(config, stream.quality))
return false;
return true;
});
streams.sort((a, b) => b.score - a.score);
return { streams: streams.map((stream) => stream.stream) };
};
const dedupeTorrents = (torrents) => {
const map = new Map(torrents.map((torrent) => [`${torrent.tracker}:${torrent.name}`, torrent]));
return [...map.values()];
};
export const getStreamsFromTorrent = async (req, torrent, season, episode) => {
const uri = torrent.torrent || torrent.magnet;
if (!uri)
return [];
const torrentInfo = await getTorrentInfo(uri);
if (!torrentInfo)
return [];
let videos = torrentInfo.files.filter((file) => isVideoFile(file.name));
if (season && episode) {
videos = videos.filter((file) => isFileNameMatch(file.name, Number(season), Number(episode)));
}
const videosSize = videos.reduce((acc, file) => acc + file.size, 0);
videos = videos.filter((file) => file.size > videosSize / (videos.length + 1));
const subs = torrentInfo.files.filter((file) => isSubtitleFile(file.name));
const torrentQuality = guessQuality(torrent.name);
const language = guessLanguage(torrent.name, torrent.category);
// @ts-ignore
return videos.map((file) => {
const fileQuality = guessQuality(file.name);
const { quality, score } = fileQuality.score > torrentQuality.score ? fileQuality : torrentQuality;
const description = [
...(season && episode ? [torrent.name, file.name] : [torrent.name]),
[
`💾 ${getReadableSize(file.size)}`,
`⬆️ ${torrent.seeds}`,
`⬇️ ${torrent.peers}`,
].join(" "),
[`🔊 ${language}`, `⚙️ ${torrent.tracker}`].join(" "),
].join("\n");
const streamEndpoint = `${req.protocol}://${req.get("host")}/stream`;
const url = [
streamEndpoint,
encodeURIComponent(uri),
encodeURIComponent(file.path),
].join("/");
const subtitles = subs.map((sub, index) => ({
id: index.toString(),
url: [
streamEndpoint,
encodeURIComponent(uri),
encodeURIComponent(sub.path),
].join("/"),
lang: sub.name,
}));
return {
stream: {
name: quality,
description,
url,
subtitles,
behaviorHints: {
bingeGroup: torrent.name,
},
},
torrentName: torrent.name,
fileName: file.name,
quality,
score,
};
});
};
const isAllowedQuality = (config, quality) => {
if (config?.disable4k === "on" && quality.includes("4K"))
return false;
if (config?.disableCam === "on" && quality.includes("CAM"))
return false;
if (config?.disableHdr === "on" &&
(quality.includes("HDR") || quality.includes("Dolby Vision")))
return false;
if (config?.disable3d === "on" && quality.includes("3D"))
return false;
return true;
};
const isAllowedFormat = (config, name) => {
if (config?.disableHevc === "on") {
const str = name.replace(/\W/g, "").toLowerCase();
if (str.includes("x265") || str.includes("h265") || str.includes("hevc"))
return false;
}
return true;
};
//# sourceMappingURL=streams.js.map