mirror of
https://github.com/kodjodevf/mangayomi-extensions.git
synced 2026-02-14 10:51:17 +00:00
New sources : Torrentio (Torrent) and Torrentio Anime (Torrent)
This commit is contained in:
645
javascript/anime/src/all/torrentio.js
Normal file
645
javascript/anime/src/all/torrentio.js
Normal file
@@ -0,0 +1,645 @@
|
|||||||
|
const mangayomiSources = [{
|
||||||
|
"name": "Torrentio (Torrent)",
|
||||||
|
"lang": "all",
|
||||||
|
"baseUrl": "https://torrentio.strem.fun",
|
||||||
|
"apiUrl": "",
|
||||||
|
"iconUrl": "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/javascript/icon/all.torrentio.png",
|
||||||
|
"typeSource": "torrent",
|
||||||
|
"isManga": false,
|
||||||
|
"version": "0.0.1",
|
||||||
|
"appMinVerReq": "0.3.75",
|
||||||
|
"pkgPath": "anime/src/all/torrentio.js"
|
||||||
|
}];
|
||||||
|
|
||||||
|
class DefaultExtension extends MProvider {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.client = new Client();
|
||||||
|
}
|
||||||
|
|
||||||
|
justWatchQuery() {
|
||||||
|
return `
|
||||||
|
query GetPopularTitles(
|
||||||
|
$country: Country!,
|
||||||
|
$first: Int!,
|
||||||
|
$language: Language!,
|
||||||
|
$offset: Int,
|
||||||
|
$searchQuery: String,
|
||||||
|
$packages: [String!]!,
|
||||||
|
$objectTypes: [ObjectType!]!,
|
||||||
|
$popularTitlesSortBy: PopularTitlesSorting!,
|
||||||
|
$releaseYear: IntFilter
|
||||||
|
) {
|
||||||
|
popularTitles(
|
||||||
|
country: $country
|
||||||
|
first: $first
|
||||||
|
offset: $offset
|
||||||
|
sortBy: $popularTitlesSortBy
|
||||||
|
filter: {
|
||||||
|
objectTypes: $objectTypes,
|
||||||
|
searchQuery: $searchQuery,
|
||||||
|
packages: $packages,
|
||||||
|
genres: [],
|
||||||
|
excludeGenres: [],
|
||||||
|
releaseYear: $releaseYear
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
objectType
|
||||||
|
content(country: $country, language: $language) {
|
||||||
|
fullPath
|
||||||
|
title
|
||||||
|
shortDescription
|
||||||
|
externalIds {
|
||||||
|
imdbId
|
||||||
|
}
|
||||||
|
posterUrl
|
||||||
|
genres {
|
||||||
|
translation(language: $language)
|
||||||
|
}
|
||||||
|
credits {
|
||||||
|
name
|
||||||
|
role
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pageInfo {
|
||||||
|
hasPreviousPage
|
||||||
|
hasNextPage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`.trim();
|
||||||
|
}
|
||||||
|
async makeGraphQLRequest(query, variables) {
|
||||||
|
const res = await this.client.post("https://apis.justwatch.com/graphql", { "Content-Type": "application/json" },
|
||||||
|
{
|
||||||
|
query: query,
|
||||||
|
variables
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
async searchAnimeRequest(page, query) {
|
||||||
|
const preferences = new SharedPreferences();
|
||||||
|
const country = preferences.get("jw_region");
|
||||||
|
const language = preferences.get("jw_lang");
|
||||||
|
const perPage = 40;
|
||||||
|
const year = 0;
|
||||||
|
|
||||||
|
const searchQueryRegex = /[^a-zA-Z0-9 ]/g;
|
||||||
|
const sanitizedQuery = query.replace(searchQueryRegex, "").trim();
|
||||||
|
|
||||||
|
const variables = {
|
||||||
|
first: perPage,
|
||||||
|
offset: (page - 1) * perPage,
|
||||||
|
platform: "WEB",
|
||||||
|
country: country,
|
||||||
|
language: language,
|
||||||
|
searchQuery: sanitizedQuery,
|
||||||
|
packages: [],
|
||||||
|
objectTypes: [],
|
||||||
|
popularTitlesSortBy: "TRENDING",
|
||||||
|
releaseYear: {
|
||||||
|
min: year,
|
||||||
|
max: year
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return await this.makeGraphQLRequest(this.justWatchQuery(), variables);
|
||||||
|
}
|
||||||
|
parseSearchJson(jsonLine) {
|
||||||
|
|
||||||
|
const popularTitlesResponse = JSON.parse(jsonLine);
|
||||||
|
|
||||||
|
const edges = popularTitlesResponse?.data?.popularTitles?.edges || [];
|
||||||
|
const hasNextPage = popularTitlesResponse?.data?.popularTitles?.pageInfo?.hasNextPage || false;
|
||||||
|
|
||||||
|
const animeList = edges
|
||||||
|
.map(edge => {
|
||||||
|
const node = edge?.node;
|
||||||
|
const content = node?.content;
|
||||||
|
if (!node || !content) return null;
|
||||||
|
return {
|
||||||
|
link: `${content.externalIds?.imdbId || ""},${node.objectType || ""},${content.fullPath || ""}`,
|
||||||
|
name: content.title || "",
|
||||||
|
imageUrl: `https://images.justwatch.com${content.posterUrl?.replace("{profile}", "s276")?.replace("{format}", "webp")}`,
|
||||||
|
description: content.shortDescription || "",
|
||||||
|
genre: content.genres?.map(genre => genre.translation).filter(Boolean) || [],
|
||||||
|
author: (content.credits?.filter(credit => credit.role === "DIRECTOR").map(credit => credit.name) || []).join(", "),
|
||||||
|
artist: (content.credits?.filter(credit => credit.role === "ACTOR").slice(0, 4).map(credit => credit.name) || []).join(", "),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
return { "list": animeList, hasNextPage };
|
||||||
|
}
|
||||||
|
get supportsLatest() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
async getPopular(page) {
|
||||||
|
return this.parseSearchJson((await this.searchAnimeRequest(page, "")).body);
|
||||||
|
}
|
||||||
|
async getLatestUpdates(page) {
|
||||||
|
|
||||||
|
}
|
||||||
|
async search(query, page, filters) {
|
||||||
|
return this.parseSearchJson((await this.searchAnimeRequest(page, query)).body);
|
||||||
|
}
|
||||||
|
async getDetail(url) {
|
||||||
|
const anime = {};
|
||||||
|
const parts = url.split(",");
|
||||||
|
const type = parts[1].toLowerCase();
|
||||||
|
const imdbId = parts[0];
|
||||||
|
const response = await this.client.get(`https://cinemeta-live.strem.io/meta/${type}/${imdbId}.json`);
|
||||||
|
const meta = JSON.parse(response.body).meta;
|
||||||
|
if (!meta) return anime;
|
||||||
|
anime.episodes = (() => {
|
||||||
|
switch (meta.type) {
|
||||||
|
case "show":
|
||||||
|
const videos = meta.videos || [];
|
||||||
|
return videos
|
||||||
|
.map(video => {
|
||||||
|
const firstAired = video.firstAired ? new Date(video.firstAired) : new Date();
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: `/stream/series/${video.id}.json`,
|
||||||
|
dateUpload: firstAired.valueOf().toString(),
|
||||||
|
name: `S${(video.season || "").toString().trim()}:E${(video.number || "").toString()} - ${video.name || ""}`,
|
||||||
|
scanlator: firstAired > Date.now() ? "Upcoming" : ""
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.sort((a, b) => {
|
||||||
|
const seasonA = parseInt(a.name.substringAfter("S").substringBefore(":"), 10);
|
||||||
|
const seasonB = parseInt(b.name.substringAfter("S").substringBefore(":"), 10);
|
||||||
|
const episodeA = parseInt(a.name.substringAfter("E").substringBefore(" -"), 10);
|
||||||
|
const episodeB = parseInt(b.name.substringAfter("E").substringBefore(" -"), 10);
|
||||||
|
|
||||||
|
return seasonA - seasonB || episodeA - episodeB;
|
||||||
|
})
|
||||||
|
.reverse();
|
||||||
|
|
||||||
|
case "movie":
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
url: `/stream/movie/${meta.id}.json`,
|
||||||
|
name: "Movie"
|
||||||
|
}
|
||||||
|
].reverse();
|
||||||
|
|
||||||
|
default:
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
return anime;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getVideoList(url) {
|
||||||
|
const preferences = new SharedPreferences();
|
||||||
|
|
||||||
|
let mainURL = `${this.source.baseUrl}/`;
|
||||||
|
|
||||||
|
const appendQueryParam = (key, values) => {
|
||||||
|
if (values && values.size > 0) {
|
||||||
|
const filteredValues = Array.from(values).filter(value => value.trim() !== "").join(",");
|
||||||
|
mainURL += `${key}=${filteredValues}|`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
appendQueryParam("providers", preferences.get("provider_selection"));
|
||||||
|
appendQueryParam("language", preferences.get("lang_selection"));
|
||||||
|
appendQueryParam("qualityfilter", preferences.get("quality_selection"));
|
||||||
|
appendQueryParam("sort", new Set([preferences.get("sorting_link")]));
|
||||||
|
|
||||||
|
|
||||||
|
mainURL += url;
|
||||||
|
mainURL = mainURL.replace(/\|$/, "");
|
||||||
|
const responseEpisodes = await this.client.get(mainURL);
|
||||||
|
const streamList = JSON.parse(responseEpisodes.body);
|
||||||
|
|
||||||
|
const animeTrackers = `
|
||||||
|
http://nyaa.tracker.wf:7777/announce,
|
||||||
|
http://anidex.moe:6969/announce,http://tracker.anirena.com:80/announce,
|
||||||
|
udp://tracker.uw0.xyz:6969/announce,
|
||||||
|
http://share.camoe.cn:8080/announce,
|
||||||
|
http://t.nyaatracker.com:80/announce,
|
||||||
|
udp://47.ip-51-68-199.eu:6969/announce,
|
||||||
|
udp://9.rarbg.me:2940,
|
||||||
|
udp://9.rarbg.to:2820,
|
||||||
|
udp://exodus.desync.com:6969/announce,
|
||||||
|
udp://explodie.org:6969/announce,
|
||||||
|
udp://ipv4.tracker.harry.lu:80/announce,
|
||||||
|
udp://open.stealth.si:80/announce,
|
||||||
|
udp://opentor.org:2710/announce,
|
||||||
|
udp://opentracker.i2p.rocks:6969/announce,
|
||||||
|
udp://retracker.lanta-net.ru:2710/announce,
|
||||||
|
udp://tracker.cyberia.is:6969/announce,
|
||||||
|
udp://tracker.dler.org:6969/announce,
|
||||||
|
udp://tracker.ds.is:6969/announce,
|
||||||
|
udp://tracker.internetwarriors.net:1337,
|
||||||
|
udp://tracker.openbittorrent.com:6969/announce,
|
||||||
|
udp://tracker.opentrackr.org:1337/announce,
|
||||||
|
udp://tracker.tiny-vps.com:6969/announce,
|
||||||
|
udp://tracker.torrent.eu.org:451/announce,
|
||||||
|
udp://valakas.rollo.dnsabr.com:2710/announce,
|
||||||
|
udp://www.torrent.eu.org:451/announce
|
||||||
|
`.split(",").map(tracker => tracker.trim()).filter(tracker => tracker);
|
||||||
|
|
||||||
|
const videos = this.sortVideos((streamList.streams || []).map(stream => {
|
||||||
|
const hash = `magnet:?xt=urn:btih:${stream.infoHash}&dn=${stream.infoHash}&tr=${animeTrackers.join("&tr=")}&index=${stream.fileIdx}`;
|
||||||
|
const videoTitle = `${(stream.name || "").replace("Torrentio\n", "")}\n${stream.title || ""}`.trim();
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: hash,
|
||||||
|
originalUrl: hash,
|
||||||
|
quality: videoTitle,
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
const numberOfLinks = preferences.get("number_of_links");
|
||||||
|
if (numberOfLinks == "all") {
|
||||||
|
return videos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return videos.slice(0, parseInt(numberOfLinks))
|
||||||
|
}
|
||||||
|
|
||||||
|
sortVideos(videos) {
|
||||||
|
const preferences = new SharedPreferences();
|
||||||
|
|
||||||
|
const isDub = preferences.get("dubbed");
|
||||||
|
const isEfficient = preferences.get("efficient");
|
||||||
|
|
||||||
|
return videos.sort((a, b) => {
|
||||||
|
const regexMatchA = /\[(.+?) download\]/.test(a.quality);
|
||||||
|
const regexMatchB = /\[(.+?) download\]/.test(b.quality);
|
||||||
|
|
||||||
|
const isDubA = isDub && !a.quality.toLowerCase().includes("dubbed");
|
||||||
|
const isDubB = isDub && !b.quality.toLowerCase().includes("dubbed");
|
||||||
|
|
||||||
|
const isEfficientA = isEfficient && !["hevc", "265", "av1"].some(q => a.quality.toLowerCase().includes(q));
|
||||||
|
const isEfficientB = isEfficient && !["hevc", "265", "av1"].some(q => b.quality.toLowerCase().includes(q));
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
regexMatchA - regexMatchB ||
|
||||||
|
isDubA - isDubB ||
|
||||||
|
isEfficientA - isEfficientB
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
getSourcePreferences() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"key": "number_of_links",
|
||||||
|
"listPreference": {
|
||||||
|
"title": "Number of links to load for video list",
|
||||||
|
"summary": "⚠️ Increasing the number of links will increase the loading time of the video list",
|
||||||
|
"valueIndex": 1,
|
||||||
|
"entries": [
|
||||||
|
"2",
|
||||||
|
"4",
|
||||||
|
"8",
|
||||||
|
"12",
|
||||||
|
"all"],
|
||||||
|
"entryValues": [
|
||||||
|
"2",
|
||||||
|
"4",
|
||||||
|
"8",
|
||||||
|
"12",
|
||||||
|
"all"],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "provider_selection",
|
||||||
|
"multiSelectListPreference": {
|
||||||
|
"title": "Enable/Disable Providers",
|
||||||
|
"summary": "",
|
||||||
|
"entries": [
|
||||||
|
"YTS",
|
||||||
|
"EZTV",
|
||||||
|
"RARBG",
|
||||||
|
"1337x",
|
||||||
|
"ThePirateBay",
|
||||||
|
"KickassTorrents",
|
||||||
|
"TorrentGalaxy",
|
||||||
|
"MagnetDL",
|
||||||
|
"HorribleSubs",
|
||||||
|
"NyaaSi",
|
||||||
|
"TokyoTosho",
|
||||||
|
"AniDex",
|
||||||
|
"🇷🇺 Rutor",
|
||||||
|
"🇷🇺 Rutracker",
|
||||||
|
"🇵🇹 Comando",
|
||||||
|
"🇵🇹 BluDV",
|
||||||
|
"🇫🇷 Torrent9",
|
||||||
|
"🇪🇸 MejorTorrent",
|
||||||
|
"🇲🇽 Cinecalidad"],
|
||||||
|
"entryValues": [
|
||||||
|
"yts",
|
||||||
|
"eztv",
|
||||||
|
"rarbg",
|
||||||
|
"1337x",
|
||||||
|
"thepiratebay",
|
||||||
|
"kickasstorrents",
|
||||||
|
"torrentgalaxy",
|
||||||
|
"magnetdl",
|
||||||
|
"horriblesubs",
|
||||||
|
"nyaasi",
|
||||||
|
"tokyotosho",
|
||||||
|
"anidex",
|
||||||
|
"rutor",
|
||||||
|
"rutracker",
|
||||||
|
"comando",
|
||||||
|
"bludv",
|
||||||
|
"torrent9",
|
||||||
|
"mejortorrent",
|
||||||
|
"cinecalidad"],
|
||||||
|
"values": [
|
||||||
|
"nyaasi",]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "quality_selection",
|
||||||
|
"multiSelectListPreference": {
|
||||||
|
"title": "Exclude Qualities/Resolutions",
|
||||||
|
"summary": "",
|
||||||
|
"entries": [
|
||||||
|
"BluRay REMUX",
|
||||||
|
"HDR/HDR10+/Dolby Vision",
|
||||||
|
"Dolby Vision",
|
||||||
|
"4k",
|
||||||
|
"1080p",
|
||||||
|
"720p",
|
||||||
|
"480p",
|
||||||
|
"Other (DVDRip/HDRip/BDRip...)",
|
||||||
|
"Screener",
|
||||||
|
"Cam",
|
||||||
|
"Unknown"],
|
||||||
|
"entryValues": [
|
||||||
|
"brremux",
|
||||||
|
"hdrall",
|
||||||
|
"dolbyvision",
|
||||||
|
"4k",
|
||||||
|
"1080p",
|
||||||
|
"720p",
|
||||||
|
"480p",
|
||||||
|
"other",
|
||||||
|
"scr",
|
||||||
|
"cam",
|
||||||
|
"unknown"],
|
||||||
|
"values": [
|
||||||
|
"720p",
|
||||||
|
"480p",
|
||||||
|
"other",
|
||||||
|
"scr",
|
||||||
|
"cam",
|
||||||
|
"unknown"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "lang_selection",
|
||||||
|
"multiSelectListPreference": {
|
||||||
|
"title": "Priority foreign language",
|
||||||
|
"summary": "",
|
||||||
|
"entries": [
|
||||||
|
"🇯🇵 Japanese",
|
||||||
|
"🇷🇺 Russian",
|
||||||
|
"🇮🇹 Italian",
|
||||||
|
"🇵🇹 Portuguese",
|
||||||
|
"🇪🇸 Spanish",
|
||||||
|
"🇲🇽 Latino",
|
||||||
|
"🇰🇷 Korean",
|
||||||
|
"🇨🇳 Chinese",
|
||||||
|
"🇹🇼 Taiwanese",
|
||||||
|
"🇫🇷 French",
|
||||||
|
"🇩🇪 German",
|
||||||
|
"🇳🇱 Dutch",
|
||||||
|
"🇮🇳 Hindi",
|
||||||
|
"🇮🇳 Telugu",
|
||||||
|
"🇮🇳 Tamil",
|
||||||
|
"🇵🇱 Polish",
|
||||||
|
"🇱🇹 Lithuanian",
|
||||||
|
"🇱🇻 Latvian",
|
||||||
|
"🇪🇪 Estonian",
|
||||||
|
"🇨🇿 Czech",
|
||||||
|
"🇸🇰 Slovakian",
|
||||||
|
"🇸🇮 Slovenian",
|
||||||
|
"🇭🇺 Hungarian",
|
||||||
|
"🇷🇴 Romanian",
|
||||||
|
"🇧🇬 Bulgarian",
|
||||||
|
"🇷🇸 Serbian",
|
||||||
|
"🇭🇷 Croatian",
|
||||||
|
"🇺🇦 Ukrainian",
|
||||||
|
"🇬🇷 Greek",
|
||||||
|
"🇩🇰 Danish",
|
||||||
|
"🇫🇮 Finnish",
|
||||||
|
"🇸🇪 Swedish",
|
||||||
|
"🇳🇴 Norwegian",
|
||||||
|
"🇹🇷 Turkish",
|
||||||
|
"🇸🇦 Arabic",
|
||||||
|
"🇮🇷 Persian",
|
||||||
|
"🇮🇱 Hebrew",
|
||||||
|
"🇻🇳 Vietnamese",
|
||||||
|
"🇮🇩 Indonesian",
|
||||||
|
"🇲🇾 Malay",
|
||||||
|
"🇹🇭 Thai",],
|
||||||
|
"entryValues": [
|
||||||
|
"japanese",
|
||||||
|
"russian",
|
||||||
|
"italian",
|
||||||
|
"portuguese",
|
||||||
|
"spanish",
|
||||||
|
"latino",
|
||||||
|
"korean",
|
||||||
|
"chinese",
|
||||||
|
"taiwanese",
|
||||||
|
"french",
|
||||||
|
"german",
|
||||||
|
"dutch",
|
||||||
|
"hindi",
|
||||||
|
"telugu",
|
||||||
|
"tamil",
|
||||||
|
"polish",
|
||||||
|
"lithuanian",
|
||||||
|
"latvian",
|
||||||
|
"estonian",
|
||||||
|
"czech",
|
||||||
|
"slovakian",
|
||||||
|
"slovenian",
|
||||||
|
"hungarian",
|
||||||
|
"romanian",
|
||||||
|
"bulgarian",
|
||||||
|
"serbian",
|
||||||
|
"croatian",
|
||||||
|
"ukrainian",
|
||||||
|
"greek",
|
||||||
|
"danish",
|
||||||
|
"finnish",
|
||||||
|
"swedish",
|
||||||
|
"norwegian",
|
||||||
|
"turkish",
|
||||||
|
"arabic",
|
||||||
|
"persian",
|
||||||
|
"hebrew",
|
||||||
|
"vietnamese",
|
||||||
|
"indonesian",
|
||||||
|
"malay",
|
||||||
|
"thai"],
|
||||||
|
"values": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "sorting_link",
|
||||||
|
"listPreference": {
|
||||||
|
"title": "Sorting",
|
||||||
|
"summary": "",
|
||||||
|
"valueIndex": 0,
|
||||||
|
"entries": [
|
||||||
|
"By quality then seeders",
|
||||||
|
"By quality then size",
|
||||||
|
"By seeders",
|
||||||
|
"By size"],
|
||||||
|
"entryValues": [
|
||||||
|
"quality",
|
||||||
|
"qualitysize",
|
||||||
|
"seeders",
|
||||||
|
"size"],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "dubbed",
|
||||||
|
"switchPreferenceCompat": {
|
||||||
|
"title": "Dubbed Video Priority",
|
||||||
|
"summary": "",
|
||||||
|
"value": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "efficient",
|
||||||
|
"switchPreferenceCompat": {
|
||||||
|
"title": "Efficient Video Priority",
|
||||||
|
"summary": "Codec: (HEVC / x265) & AV1. High-quality video with less data usage.",
|
||||||
|
"value": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "jw_region",
|
||||||
|
"listPreference": {
|
||||||
|
"title": "Catalogue Region",
|
||||||
|
"summary": "Region based catalogue recommendation.",
|
||||||
|
"valueIndex": 133,
|
||||||
|
"entries": [
|
||||||
|
"Albania", "Algeria", "Androrra", "Angola", "Antigua and Barbuda", "Argentina", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Barbados", "Belarus", "Belgium", "Belize", "Bermuda", "Bolivia", "Bosnia and Herzegovina", "Brazil", "Bulgaria", "Burkina Faso", "Cameroon", "Canada", "Cape Verde", "Chad", "Chile", "Colombia", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic", "DR Congo", "Denmark", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Estonia", "Fiji", "Finland", "France", "French Guiana", "French Polynesia", "Germany", "Ghana", "Gibraltar", "Greece", "Guatemala", "Guernsey", "Guyana", "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iraq", "Ireland", "Israel", "Italy", "Ivory Coast", "Jamaica", "Japan", "Jordan", "Kenya", "Kosovo", "Kuwait", "Latvia", "Lebanon", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macedonia", "Madagascar", "Malawi", "Malaysia", "Mali", "Malta", "Mauritius", "Mexico", "Moldova", "Monaco", "Montenegro", "Morocco", "Mozambique", "Netherlands", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Norway", "Oman", "Pakistan", "Palestine", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal", "Qatar", "Romania", "Russia", "Saint Lucia", "San Marino", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Singapore", "Slovakia", "Slovenia", "South Africa", "South Korea", "Spain", "Sweden", "Switzerland", "Taiwan", "Tanzania", "Thailand", "Trinidad and Tobago", "Tunisia", "Turkey", "Turks and Caicos Islands", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Vatican City", "Venezuela", "Yemen", "Zambia", "Zimbabwe"],
|
||||||
|
"entryValues": [
|
||||||
|
"AL", "DZ", "AD", "AO", "AG", "AR", "AU", "AT", "AZ", "BS", "BH", "BB", "BY", "BE", "BZ", "BM", "BO", "BA", "BR", "BG", "BF", "CM", "CA", "CV", "TD", "CL", "CO", "CR", "HR", "CU", "CY", "CZ", "CD", "DK", "DO", "EC", "EG", "SV", "GQ", "EE", "FJ", "FI", "FR", "GF", "PF", "DE", "GH", "GI", "GR", "GT", "GG", "GY", "HN", "HK", "HU", "IS", "IN", "ID", "IQ", "IE", "IL", "IT", "CI", "JM", "JP", "JO", "KE", "XK", "KW", "LV", "LB", "LY", "LI", "LT", "LU", "MK", "MG", "MW", "MY", "ML", "MT", "MU", "MX", "MD", "MC", "ME", "MA", "MZ", "NL", "NZ", "NI", "NE", "NG", "NO", "OM", "PK", "PS", "PA", "PG", "PY", "PE", "PH", "PL", "PT", "QA", "RO", "RU", "LC", "SM", "SA", "SN", "RS", "SC", "SG", "SK", "SI", "ZA", "KR", "ES", "SE", "CH", "TW", "TZ", "TH", "TT", "TN", "TR", "TC", "UG", "UA", "AE", "UK", "US", "UY", "VA", "VE", "YE", "ZM", "ZW"],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "jw_lang",
|
||||||
|
"listPreference": {
|
||||||
|
"title": "Poster and Titles Language",
|
||||||
|
"summary": "",
|
||||||
|
"valueIndex": 9,
|
||||||
|
"entries": [
|
||||||
|
"Arabic",
|
||||||
|
"Azerbaijani",
|
||||||
|
"Belarusian",
|
||||||
|
"Bulgarian",
|
||||||
|
"Bosnian",
|
||||||
|
"Catalan",
|
||||||
|
"Czech",
|
||||||
|
"German",
|
||||||
|
"Greek",
|
||||||
|
"English",
|
||||||
|
"English (U.S.A.)",
|
||||||
|
"Spanish",
|
||||||
|
"Spanish (Spain)",
|
||||||
|
"Spanish (Latinamerican)",
|
||||||
|
"Estonian",
|
||||||
|
"Finnish",
|
||||||
|
"French",
|
||||||
|
"French (Canada)",
|
||||||
|
"Hebrew",
|
||||||
|
"Croatian",
|
||||||
|
"Hungarian",
|
||||||
|
"Icelandic",
|
||||||
|
"Italian",
|
||||||
|
"Japanese",
|
||||||
|
"Korean",
|
||||||
|
"Lithuanian",
|
||||||
|
"Latvian",
|
||||||
|
"Macedonian",
|
||||||
|
"Maltese",
|
||||||
|
"Polish",
|
||||||
|
"Portuguese",
|
||||||
|
"Portuguese (Portugal)",
|
||||||
|
"Portuguese (Brazil)",
|
||||||
|
"Romanian",
|
||||||
|
"Russian",
|
||||||
|
"Slovakian",
|
||||||
|
"Slovenian",
|
||||||
|
"Albanian",
|
||||||
|
"Serbian",
|
||||||
|
"Swedish",
|
||||||
|
"Swahili",
|
||||||
|
"Turkish",
|
||||||
|
"Ukrainian",
|
||||||
|
"Urdu",
|
||||||
|
"Chinese"],
|
||||||
|
"entryValues": [
|
||||||
|
"ar",
|
||||||
|
"az",
|
||||||
|
"be",
|
||||||
|
"bg",
|
||||||
|
"bs",
|
||||||
|
"ca",
|
||||||
|
"cs",
|
||||||
|
"de",
|
||||||
|
"el",
|
||||||
|
"en",
|
||||||
|
"en-US",
|
||||||
|
"es",
|
||||||
|
"es-ES",
|
||||||
|
"es-LA",
|
||||||
|
"et",
|
||||||
|
"fi",
|
||||||
|
"fr",
|
||||||
|
"fr-CA",
|
||||||
|
"he",
|
||||||
|
"hr",
|
||||||
|
"hu",
|
||||||
|
"is",
|
||||||
|
"it",
|
||||||
|
"ja",
|
||||||
|
"ko",
|
||||||
|
"lt",
|
||||||
|
"lv",
|
||||||
|
"mk",
|
||||||
|
"mt",
|
||||||
|
"pl",
|
||||||
|
"pt",
|
||||||
|
"pt-PT",
|
||||||
|
"pt-BR",
|
||||||
|
"ro",
|
||||||
|
"ru",
|
||||||
|
"sk",
|
||||||
|
"sl",
|
||||||
|
"sq",
|
||||||
|
"sr",
|
||||||
|
"sv",
|
||||||
|
"sw",
|
||||||
|
"tr",
|
||||||
|
"uk",
|
||||||
|
"ur",
|
||||||
|
"zh"],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
636
javascript/anime/src/all/torrentioanime.js
Normal file
636
javascript/anime/src/all/torrentioanime.js
Normal file
@@ -0,0 +1,636 @@
|
|||||||
|
const mangayomiSources = [{
|
||||||
|
"name": "Torrentio Anime (Torrent)",
|
||||||
|
"lang": "all",
|
||||||
|
"baseUrl": "https://torrentio.strem.fun",
|
||||||
|
"apiUrl": "",
|
||||||
|
"iconUrl": "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/javascript/icon/all.torrentio.png",
|
||||||
|
"typeSource": "torrent",
|
||||||
|
"isManga": false,
|
||||||
|
"version": "0.0.1",
|
||||||
|
"appMinVerReq": "0.3.75",
|
||||||
|
"pkgPath": "anime/src/all/torrentioanime.js"
|
||||||
|
}];
|
||||||
|
|
||||||
|
class DefaultExtension extends MProvider {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.client = new Client();
|
||||||
|
}
|
||||||
|
|
||||||
|
anilistQuery() {
|
||||||
|
return `
|
||||||
|
query ($page: Int, $perPage: Int, $sort: [MediaSort], $search: String) {
|
||||||
|
Page(page: $page, perPage: $perPage) {
|
||||||
|
pageInfo {
|
||||||
|
currentPage
|
||||||
|
hasNextPage
|
||||||
|
}
|
||||||
|
media(type: ANIME, sort: $sort, search: $search, status_in: [RELEASING, FINISHED, NOT_YET_RELEASED]) {
|
||||||
|
id
|
||||||
|
title {
|
||||||
|
romaji
|
||||||
|
english
|
||||||
|
native
|
||||||
|
}
|
||||||
|
coverImage {
|
||||||
|
extraLarge
|
||||||
|
large
|
||||||
|
}
|
||||||
|
description
|
||||||
|
status
|
||||||
|
tags {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
genres
|
||||||
|
studios {
|
||||||
|
nodes {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
countryOfOrigin
|
||||||
|
isAdult
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`.trim();
|
||||||
|
}
|
||||||
|
anilistLatestQuery() {
|
||||||
|
const currentTimeInSeconds = Math.floor(Date.now() / 1000);
|
||||||
|
return `
|
||||||
|
query ($page: Int, $perPage: Int, $sort: [AiringSort]) {
|
||||||
|
Page(page: $page, perPage: $perPage) {
|
||||||
|
pageInfo {
|
||||||
|
currentPage
|
||||||
|
hasNextPage
|
||||||
|
}
|
||||||
|
airingSchedules(
|
||||||
|
airingAt_greater: 0
|
||||||
|
airingAt_lesser: ${currentTimeInSeconds - 10000}
|
||||||
|
sort: $sort
|
||||||
|
) {
|
||||||
|
media {
|
||||||
|
id
|
||||||
|
title {
|
||||||
|
romaji
|
||||||
|
english
|
||||||
|
native
|
||||||
|
}
|
||||||
|
coverImage {
|
||||||
|
extraLarge
|
||||||
|
large
|
||||||
|
}
|
||||||
|
description
|
||||||
|
status
|
||||||
|
tags {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
genres
|
||||||
|
studios {
|
||||||
|
nodes {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
countryOfOrigin
|
||||||
|
isAdult
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`.trim();
|
||||||
|
}
|
||||||
|
async makeGraphQLRequest(query, variables) {
|
||||||
|
const res = await this.client.post("https://graphql.anilist.co", {},
|
||||||
|
{
|
||||||
|
query, variables
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
parseSearchJson(jsonLine, isLatestQuery = false) {
|
||||||
|
const jsonData = JSON.parse(jsonLine);
|
||||||
|
jsonData.type = isLatestQuery ? "AnilistMetaLatest" : "AnilistMeta";
|
||||||
|
const metaData = jsonData;
|
||||||
|
|
||||||
|
const mediaList = metaData.type == "AnilistMeta"
|
||||||
|
? metaData.data?.Page?.media || []
|
||||||
|
: metaData.data?.Page?.airingSchedules.map(schedule => schedule.media) || [];
|
||||||
|
|
||||||
|
const hasNextPage = metaData.type == "AnilistMeta" || metaData.type == "AnilistMetaLatest"
|
||||||
|
? metaData.data?.Page?.pageInfo?.hasNextPage || false
|
||||||
|
: false;
|
||||||
|
|
||||||
|
const animeList = mediaList
|
||||||
|
.filter(media => !((media?.countryOfOrigin === "CN" || media?.isAdult) && isLatestQuery))
|
||||||
|
.map(media => {
|
||||||
|
const anime = {};
|
||||||
|
anime.link = media?.id?.toString() || "";
|
||||||
|
anime.name = (() => {
|
||||||
|
const preferenceTitle = new SharedPreferences().get("pref_title")
|
||||||
|
switch (preferenceTitle) {
|
||||||
|
case "romaji":
|
||||||
|
return media?.title?.romaji || "";
|
||||||
|
case "english":
|
||||||
|
return media?.title?.english?.trim() || media?.title?.romaji || "";
|
||||||
|
case "native":
|
||||||
|
return media?.title?.native || "";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
anime.imageUrl = media?.coverImage?.extraLarge || "";
|
||||||
|
|
||||||
|
return anime;
|
||||||
|
});
|
||||||
|
|
||||||
|
return { "list": animeList, "hasNextPage": hasNextPage };
|
||||||
|
}
|
||||||
|
async getPopular(page) {
|
||||||
|
const variables = JSON.stringify({
|
||||||
|
page: page,
|
||||||
|
perPage: 30,
|
||||||
|
sort: "TRENDING_DESC"
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await this.makeGraphQLRequest(this.anilistQuery(), variables);
|
||||||
|
|
||||||
|
return this.parseSearchJson(res.body)
|
||||||
|
}
|
||||||
|
async getLatestUpdates(page) {
|
||||||
|
const variables = JSON.stringify({
|
||||||
|
page: page,
|
||||||
|
perPage: 30,
|
||||||
|
sort: "TIME_DESC"
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await this.makeGraphQLRequest(this.anilistLatestQuery(), variables);
|
||||||
|
|
||||||
|
return this.parseSearchJson(res.body, true)
|
||||||
|
}
|
||||||
|
async search(query, page, filters) {
|
||||||
|
const variables = JSON.stringify({
|
||||||
|
page: page,
|
||||||
|
perPage: 30,
|
||||||
|
sort: "POPULARITY_DESC",
|
||||||
|
search: query
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await this.makeGraphQLRequest(this.anilistQuery(), variables);
|
||||||
|
|
||||||
|
return this.parseSearchJson(res.body)
|
||||||
|
}
|
||||||
|
async getDetail(url) {
|
||||||
|
const query = `
|
||||||
|
query($id: Int){
|
||||||
|
Media(id: $id){
|
||||||
|
id
|
||||||
|
title {
|
||||||
|
romaji
|
||||||
|
english
|
||||||
|
native
|
||||||
|
}
|
||||||
|
coverImage {
|
||||||
|
extraLarge
|
||||||
|
large
|
||||||
|
}
|
||||||
|
description
|
||||||
|
status
|
||||||
|
tags {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
genres
|
||||||
|
studios {
|
||||||
|
nodes {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
countryOfOrigin
|
||||||
|
isAdult
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`.trim();
|
||||||
|
|
||||||
|
const variables = JSON.stringify({ id: url });
|
||||||
|
|
||||||
|
const res = await this.makeGraphQLRequest(query, variables);
|
||||||
|
const media = JSON.parse(res.body).data.Media;
|
||||||
|
const anime = {};
|
||||||
|
anime.imageUrl = media?.coverImage?.extraLarge || "";
|
||||||
|
anime.description = (media?.description || "No Description")
|
||||||
|
.replace(/<br><br>/g, "\n")
|
||||||
|
.replace(/<.*?>/g, "");
|
||||||
|
|
||||||
|
anime.status = (() => {
|
||||||
|
switch (media?.status) {
|
||||||
|
case "RELEASING":
|
||||||
|
return 0;
|
||||||
|
case "FINISHED":
|
||||||
|
return 1;
|
||||||
|
case "HIATUS":
|
||||||
|
return 2;
|
||||||
|
case "NOT_YET_RELEASED":
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
const tagsList = media?.tags?.map(tag => tag.name).filter(Boolean) || [];
|
||||||
|
const genresList = media?.genres || [];
|
||||||
|
anime.genre = [...new Set([...tagsList, ...genresList])].sort();
|
||||||
|
const studiosList = media?.studios?.nodes?.map(node => node.name).filter(Boolean) || [];
|
||||||
|
anime.author = studiosList.sort().join(", ");
|
||||||
|
const response = await this.client.get(`https://api.ani.zip/mappings?anilist_id=${url}`);
|
||||||
|
const kitsuId = JSON.parse(response.body).mappings.kitsu_id.toString();
|
||||||
|
const responseEpisodes = await this.client.get(`https://anime-kitsu.strem.fun/meta/series/kitsu%3A${kitsuId}.json`);
|
||||||
|
const episodeList = JSON.parse(responseEpisodes.body);
|
||||||
|
anime.episodes = (() => {
|
||||||
|
switch (episodeList.meta?.type) {
|
||||||
|
case "series": {
|
||||||
|
const videos = episodeList.meta.videos;
|
||||||
|
return videos
|
||||||
|
.filter(video => video.thumbnail !== null)
|
||||||
|
.map(video => {
|
||||||
|
const releaseDate = video.released ? new Date(video.released) : Date.now();
|
||||||
|
const upcoming = releaseDate > Date.now() ? "Upcoming" : "";
|
||||||
|
return {
|
||||||
|
url: `/stream/series/${video.id}.json`,
|
||||||
|
dateUpload: releaseDate.valueOf().toString(),
|
||||||
|
name: `Episode ${video.episode} : ${video.title
|
||||||
|
?.replace(/^Episode /, "")
|
||||||
|
?.replace(/^\d+\s*/, "")
|
||||||
|
?.trim()}`,
|
||||||
|
scanlator: upcoming,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
case "movie": {
|
||||||
|
const kitsuId = episodeList.meta.kitsuId;
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
url: `/stream/movie/${kitsuId}.json`,
|
||||||
|
name: "Movie",
|
||||||
|
},
|
||||||
|
].reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
|
||||||
|
return anime;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getVideoList(url) {
|
||||||
|
const preferences = new SharedPreferences();
|
||||||
|
|
||||||
|
let mainURL = `${this.source.baseUrl}/`;
|
||||||
|
|
||||||
|
const appendQueryParam = (key, values) => {
|
||||||
|
if (values && values.size > 0) {
|
||||||
|
const filteredValues = Array.from(values).filter(value => value.trim() !== "").join(",");
|
||||||
|
mainURL += `${key}=${filteredValues}|`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
appendQueryParam("providers", preferences.get("provider_selection"));
|
||||||
|
appendQueryParam("language", preferences.get("lang_selection"));
|
||||||
|
appendQueryParam("qualityfilter", preferences.get("quality_selection"));
|
||||||
|
appendQueryParam("sort", new Set([preferences.get("sorting_link")]));
|
||||||
|
|
||||||
|
|
||||||
|
mainURL += url;
|
||||||
|
mainURL = mainURL.replace(/\|$/, "");
|
||||||
|
const responseEpisodes = await this.client.get(mainURL);
|
||||||
|
const streamList = JSON.parse(responseEpisodes.body);
|
||||||
|
|
||||||
|
const animeTrackers = `
|
||||||
|
http://nyaa.tracker.wf:7777/announce,
|
||||||
|
http://anidex.moe:6969/announce,http://tracker.anirena.com:80/announce,
|
||||||
|
udp://tracker.uw0.xyz:6969/announce,
|
||||||
|
http://share.camoe.cn:8080/announce,
|
||||||
|
http://t.nyaatracker.com:80/announce,
|
||||||
|
udp://47.ip-51-68-199.eu:6969/announce,
|
||||||
|
udp://9.rarbg.me:2940,
|
||||||
|
udp://9.rarbg.to:2820,
|
||||||
|
udp://exodus.desync.com:6969/announce,
|
||||||
|
udp://explodie.org:6969/announce,
|
||||||
|
udp://ipv4.tracker.harry.lu:80/announce,
|
||||||
|
udp://open.stealth.si:80/announce,
|
||||||
|
udp://opentor.org:2710/announce,
|
||||||
|
udp://opentracker.i2p.rocks:6969/announce,
|
||||||
|
udp://retracker.lanta-net.ru:2710/announce,
|
||||||
|
udp://tracker.cyberia.is:6969/announce,
|
||||||
|
udp://tracker.dler.org:6969/announce,
|
||||||
|
udp://tracker.ds.is:6969/announce,
|
||||||
|
udp://tracker.internetwarriors.net:1337,
|
||||||
|
udp://tracker.openbittorrent.com:6969/announce,
|
||||||
|
udp://tracker.opentrackr.org:1337/announce,
|
||||||
|
udp://tracker.tiny-vps.com:6969/announce,
|
||||||
|
udp://tracker.torrent.eu.org:451/announce,
|
||||||
|
udp://valakas.rollo.dnsabr.com:2710/announce,
|
||||||
|
udp://www.torrent.eu.org:451/announce
|
||||||
|
`.split(",").map(tracker => tracker.trim()).filter(tracker => tracker);
|
||||||
|
|
||||||
|
const videos = this.sortVideos((streamList.streams || []).map(stream => {
|
||||||
|
const hash = `magnet:?xt=urn:btih:${stream.infoHash}&dn=${stream.infoHash}&tr=${animeTrackers.join("&tr=")}&index=${stream.fileIdx}`;
|
||||||
|
const videoTitle = `${(stream.name || "").replace("Torrentio\n", "")}\n${stream.title || ""}`.trim();
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: hash,
|
||||||
|
originalUrl: hash,
|
||||||
|
quality: videoTitle,
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
const numberOfLinks = preferences.get("number_of_links");
|
||||||
|
if (numberOfLinks == "all") {
|
||||||
|
return videos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return videos.slice(0, parseInt(numberOfLinks))
|
||||||
|
}
|
||||||
|
|
||||||
|
sortVideos(videos) {
|
||||||
|
const preferences = new SharedPreferences();
|
||||||
|
|
||||||
|
const isDub = preferences.get("dubbed");
|
||||||
|
const isEfficient = preferences.get("efficient");
|
||||||
|
|
||||||
|
return videos.sort((a, b) => {
|
||||||
|
const regexMatchA = /\[(.+?) download\]/.test(a.quality);
|
||||||
|
const regexMatchB = /\[(.+?) download\]/.test(b.quality);
|
||||||
|
|
||||||
|
const isDubA = isDub && !a.quality.toLowerCase().includes("dubbed");
|
||||||
|
const isDubB = isDub && !b.quality.toLowerCase().includes("dubbed");
|
||||||
|
|
||||||
|
const isEfficientA = isEfficient && !["hevc", "265", "av1"].some(q => a.quality.toLowerCase().includes(q));
|
||||||
|
const isEfficientB = isEfficient && !["hevc", "265", "av1"].some(q => b.quality.toLowerCase().includes(q));
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
regexMatchA - regexMatchB ||
|
||||||
|
isDubA - isDubB ||
|
||||||
|
isEfficientA - isEfficientB
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
getSourcePreferences() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"key": "number_of_links",
|
||||||
|
"listPreference": {
|
||||||
|
"title": "Number of links to load for video list",
|
||||||
|
"summary": "⚠️ Increasing the number of links will increase the loading time of the video list",
|
||||||
|
"valueIndex": 1,
|
||||||
|
"entries": [
|
||||||
|
"2",
|
||||||
|
"4",
|
||||||
|
"8",
|
||||||
|
"12",
|
||||||
|
"all"],
|
||||||
|
"entryValues": [
|
||||||
|
"2",
|
||||||
|
"4",
|
||||||
|
"8",
|
||||||
|
"12",
|
||||||
|
"all"],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "provider_selection",
|
||||||
|
"multiSelectListPreference": {
|
||||||
|
"title": "Enable/Disable Providers",
|
||||||
|
"summary": "",
|
||||||
|
"entries": [
|
||||||
|
"YTS",
|
||||||
|
"EZTV",
|
||||||
|
"RARBG",
|
||||||
|
"1337x",
|
||||||
|
"ThePirateBay",
|
||||||
|
"KickassTorrents",
|
||||||
|
"TorrentGalaxy",
|
||||||
|
"MagnetDL",
|
||||||
|
"HorribleSubs",
|
||||||
|
"NyaaSi",
|
||||||
|
"TokyoTosho",
|
||||||
|
"AniDex",
|
||||||
|
"🇷🇺 Rutor",
|
||||||
|
"🇷🇺 Rutracker",
|
||||||
|
"🇵🇹 Comando",
|
||||||
|
"🇵🇹 BluDV",
|
||||||
|
"🇫🇷 Torrent9",
|
||||||
|
"🇪🇸 MejorTorrent",
|
||||||
|
"🇲🇽 Cinecalidad"],
|
||||||
|
"entryValues": [
|
||||||
|
"yts",
|
||||||
|
"eztv",
|
||||||
|
"rarbg",
|
||||||
|
"1337x",
|
||||||
|
"thepiratebay",
|
||||||
|
"kickasstorrents",
|
||||||
|
"torrentgalaxy",
|
||||||
|
"magnetdl",
|
||||||
|
"horriblesubs",
|
||||||
|
"nyaasi",
|
||||||
|
"tokyotosho",
|
||||||
|
"anidex",
|
||||||
|
"rutor",
|
||||||
|
"rutracker",
|
||||||
|
"comando",
|
||||||
|
"bludv",
|
||||||
|
"torrent9",
|
||||||
|
"mejortorrent",
|
||||||
|
"cinecalidad"],
|
||||||
|
"values": [
|
||||||
|
"nyaasi",]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "quality_selection",
|
||||||
|
"multiSelectListPreference": {
|
||||||
|
"title": "Exclude Qualities/Resolutions",
|
||||||
|
"summary": "",
|
||||||
|
"entries": [
|
||||||
|
"BluRay REMUX",
|
||||||
|
"HDR/HDR10+/Dolby Vision",
|
||||||
|
"Dolby Vision",
|
||||||
|
"4k",
|
||||||
|
"1080p",
|
||||||
|
"720p",
|
||||||
|
"480p",
|
||||||
|
"Other (DVDRip/HDRip/BDRip...)",
|
||||||
|
"Screener",
|
||||||
|
"Cam",
|
||||||
|
"Unknown"],
|
||||||
|
"entryValues": [
|
||||||
|
"brremux",
|
||||||
|
"hdrall",
|
||||||
|
"dolbyvision",
|
||||||
|
"4k",
|
||||||
|
"1080p",
|
||||||
|
"720p",
|
||||||
|
"480p",
|
||||||
|
"other",
|
||||||
|
"scr",
|
||||||
|
"cam",
|
||||||
|
"unknown"],
|
||||||
|
"values": [
|
||||||
|
"720p",
|
||||||
|
"480p",
|
||||||
|
"other",
|
||||||
|
"scr",
|
||||||
|
"cam",
|
||||||
|
"unknown"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "lang_selection",
|
||||||
|
"multiSelectListPreference": {
|
||||||
|
"title": "Priority foreign language",
|
||||||
|
"summary": "",
|
||||||
|
"entries": [
|
||||||
|
"🇯🇵 Japanese",
|
||||||
|
"🇷🇺 Russian",
|
||||||
|
"🇮🇹 Italian",
|
||||||
|
"🇵🇹 Portuguese",
|
||||||
|
"🇪🇸 Spanish",
|
||||||
|
"🇲🇽 Latino",
|
||||||
|
"🇰🇷 Korean",
|
||||||
|
"🇨🇳 Chinese",
|
||||||
|
"🇹🇼 Taiwanese",
|
||||||
|
"🇫🇷 French",
|
||||||
|
"🇩🇪 German",
|
||||||
|
"🇳🇱 Dutch",
|
||||||
|
"🇮🇳 Hindi",
|
||||||
|
"🇮🇳 Telugu",
|
||||||
|
"🇮🇳 Tamil",
|
||||||
|
"🇵🇱 Polish",
|
||||||
|
"🇱🇹 Lithuanian",
|
||||||
|
"🇱🇻 Latvian",
|
||||||
|
"🇪🇪 Estonian",
|
||||||
|
"🇨🇿 Czech",
|
||||||
|
"🇸🇰 Slovakian",
|
||||||
|
"🇸🇮 Slovenian",
|
||||||
|
"🇭🇺 Hungarian",
|
||||||
|
"🇷🇴 Romanian",
|
||||||
|
"🇧🇬 Bulgarian",
|
||||||
|
"🇷🇸 Serbian",
|
||||||
|
"🇭🇷 Croatian",
|
||||||
|
"🇺🇦 Ukrainian",
|
||||||
|
"🇬🇷 Greek",
|
||||||
|
"🇩🇰 Danish",
|
||||||
|
"🇫🇮 Finnish",
|
||||||
|
"🇸🇪 Swedish",
|
||||||
|
"🇳🇴 Norwegian",
|
||||||
|
"🇹🇷 Turkish",
|
||||||
|
"🇸🇦 Arabic",
|
||||||
|
"🇮🇷 Persian",
|
||||||
|
"🇮🇱 Hebrew",
|
||||||
|
"🇻🇳 Vietnamese",
|
||||||
|
"🇮🇩 Indonesian",
|
||||||
|
"🇲🇾 Malay",
|
||||||
|
"🇹🇭 Thai",],
|
||||||
|
"entryValues": [
|
||||||
|
"japanese",
|
||||||
|
"russian",
|
||||||
|
"italian",
|
||||||
|
"portuguese",
|
||||||
|
"spanish",
|
||||||
|
"latino",
|
||||||
|
"korean",
|
||||||
|
"chinese",
|
||||||
|
"taiwanese",
|
||||||
|
"french",
|
||||||
|
"german",
|
||||||
|
"dutch",
|
||||||
|
"hindi",
|
||||||
|
"telugu",
|
||||||
|
"tamil",
|
||||||
|
"polish",
|
||||||
|
"lithuanian",
|
||||||
|
"latvian",
|
||||||
|
"estonian",
|
||||||
|
"czech",
|
||||||
|
"slovakian",
|
||||||
|
"slovenian",
|
||||||
|
"hungarian",
|
||||||
|
"romanian",
|
||||||
|
"bulgarian",
|
||||||
|
"serbian",
|
||||||
|
"croatian",
|
||||||
|
"ukrainian",
|
||||||
|
"greek",
|
||||||
|
"danish",
|
||||||
|
"finnish",
|
||||||
|
"swedish",
|
||||||
|
"norwegian",
|
||||||
|
"turkish",
|
||||||
|
"arabic",
|
||||||
|
"persian",
|
||||||
|
"hebrew",
|
||||||
|
"vietnamese",
|
||||||
|
"indonesian",
|
||||||
|
"malay",
|
||||||
|
"thai"],
|
||||||
|
"values": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "sorting_link",
|
||||||
|
"listPreference": {
|
||||||
|
"title": "Sorting",
|
||||||
|
"summary": "",
|
||||||
|
"valueIndex": 0,
|
||||||
|
"entries": [
|
||||||
|
"By quality then seeders",
|
||||||
|
"By quality then size",
|
||||||
|
"By seeders",
|
||||||
|
"By size"],
|
||||||
|
"entryValues": [
|
||||||
|
"quality",
|
||||||
|
"qualitysize",
|
||||||
|
"seeders",
|
||||||
|
"size"],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "pref_title",
|
||||||
|
"listPreference": {
|
||||||
|
"title": "Preferred Title",
|
||||||
|
"summary": "",
|
||||||
|
"valueIndex": 0,
|
||||||
|
"entries": [
|
||||||
|
"Romaji",
|
||||||
|
"English",
|
||||||
|
"Native"],
|
||||||
|
"entryValues": [
|
||||||
|
"romaji",
|
||||||
|
"english",
|
||||||
|
"native"],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "dubbed",
|
||||||
|
"switchPreferenceCompat": {
|
||||||
|
"title": "Dubbed Video Priority",
|
||||||
|
"summary": "",
|
||||||
|
"value": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "efficient",
|
||||||
|
"switchPreferenceCompat": {
|
||||||
|
"title": "Efficient Video Priority",
|
||||||
|
"summary": "Codec: (HEVC / x265) & AV1. High-quality video with less data usage.",
|
||||||
|
"value": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
javascript/icon/all.torrentio.png
Normal file
BIN
javascript/icon/all.torrentio.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
@@ -58,7 +58,8 @@ List<Source> _searchJsSources(Directory dir) {
|
|||||||
final langs = sourceJson["langs"] as List?;
|
final langs = sourceJson["langs"] as List?;
|
||||||
Source source = Source.fromJson(sourceJson)
|
Source source = Source.fromJson(sourceJson)
|
||||||
..sourceCodeLanguage = 1
|
..sourceCodeLanguage = 1
|
||||||
..appMinVerReq = defaultSource.appMinVerReq
|
..appMinVerReq =
|
||||||
|
sourceJson["appMinVerReq"] ?? defaultSource.appMinVerReq
|
||||||
..sourceCodeUrl =
|
..sourceCodeUrl =
|
||||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/javascript/${sourceJson["pkgPath"] ?? sourceJson["pkgName"]}";
|
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/javascript/${sourceJson["pkgPath"] ?? sourceJson["pkgName"]}";
|
||||||
if (sourceJson["id"] != null) {
|
if (sourceJson["id"] != null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user