mirror of
https://github.com/kodjodevf/mangayomi-extensions.git
synced 2026-02-15 19:30:29 +00:00
Merge pull request #259 from Swakshan/fix/repo
fix: Refresh contain issue
This commit is contained in:
@@ -1,39 +1,45 @@
|
|||||||
const mangayomiSources = [{
|
const mangayomiSources = [
|
||||||
|
{
|
||||||
"name": "Autoembed",
|
"name": "Autoembed",
|
||||||
"lang": "all",
|
"lang": "all",
|
||||||
"baseUrl": "https://watch.autoembed.cc",
|
"baseUrl": "https://watch.autoembed.cc",
|
||||||
"apiUrl": "https://tom.autoembed.cc",
|
"apiUrl": "https://tom.autoembed.cc",
|
||||||
"iconUrl": "https://www.google.com/s2/favicons?sz=64&domain=https://autoembed.cc/",
|
"iconUrl":
|
||||||
|
"https://www.google.com/s2/favicons?sz=64&domain=https://autoembed.cc/",
|
||||||
"typeSource": "multi",
|
"typeSource": "multi",
|
||||||
"isManga": false,
|
"isManga": false,
|
||||||
"itemType": 1,
|
"itemType": 1,
|
||||||
"version": "1.2.6",
|
"version": "1.2.7",
|
||||||
"dateFormat": "",
|
"dateFormat": "",
|
||||||
"dateFormatLocale": "",
|
"dateFormatLocale": "",
|
||||||
"pkgPath": "anime/src/all/autoembed.js"
|
"pkgPath": "anime/src/all/autoembed.js"
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
class DefaultExtension extends MProvider {
|
class DefaultExtension extends MProvider {
|
||||||
decodeBase64 = function (f) {
|
decodeBase64 = function (f) {
|
||||||
var g = {},
|
var g = {},
|
||||||
b = 65,
|
b = 65,
|
||||||
d = 0,
|
d = 0,
|
||||||
a, c = 0,
|
a,
|
||||||
h, e = "",
|
c = 0,
|
||||||
|
h,
|
||||||
|
e = "",
|
||||||
k = String.fromCharCode,
|
k = String.fromCharCode,
|
||||||
l = f.length;
|
l = f.length;
|
||||||
for (a = ""; 91 > b;) a += k(b++);
|
for (a = ""; 91 > b; ) a += k(b++);
|
||||||
a += a.toLowerCase() + "0123456789+/";
|
a += a.toLowerCase() + "0123456789+/";
|
||||||
for (b = 0; 64 > b; b++) g[a.charAt(b)] = b;
|
for (b = 0; 64 > b; b++) g[a.charAt(b)] = b;
|
||||||
for (a = 0; a < l; a++)
|
for (a = 0; a < l; a++)
|
||||||
for (b = g[f.charAt(a)], d = (d << 6) + b, c += 6; 8 <= c;)((h = d >>> (c -= 8) & 255) || a < l - 2) && (e += k(h));
|
for (b = g[f.charAt(a)], d = (d << 6) + b, c += 6; 8 <= c; )
|
||||||
return e
|
((h = (d >>> (c -= 8)) & 255) || a < l - 2) && (e += k(h));
|
||||||
|
return e;
|
||||||
};
|
};
|
||||||
getHeaders(url) {
|
getHeaders(url) {
|
||||||
return {
|
return {
|
||||||
Referer: url,
|
Referer: url,
|
||||||
Origin: url
|
Origin: url,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getPreference(key) {
|
getPreference(key) {
|
||||||
@@ -42,7 +48,7 @@ class DefaultExtension extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async tmdbRequest(slug) {
|
async tmdbRequest(slug) {
|
||||||
var api = `https://94c8cb9f702d-tmdb-addon.baby-beamup.club/${slug}`
|
var api = `https://94c8cb9f702d-tmdb-addon.baby-beamup.club/${slug}`;
|
||||||
var response = await new Client().get(api);
|
var response = await new Client().get(api);
|
||||||
var body = JSON.parse(response.body);
|
var body = JSON.parse(response.body);
|
||||||
return body;
|
return body;
|
||||||
@@ -53,25 +59,22 @@ class DefaultExtension extends MProvider {
|
|||||||
var results = body.metas;
|
var results = body.metas;
|
||||||
for (let i in results) {
|
for (let i in results) {
|
||||||
var result = results[i];
|
var result = results[i];
|
||||||
var id = result.id
|
var id = result.id;
|
||||||
var media_type = result.type;
|
var media_type = result.type;
|
||||||
items.push({
|
items.push({
|
||||||
name: result.name,
|
name: result.name,
|
||||||
imageUrl: result.poster,
|
imageUrl: result.poster,
|
||||||
link: `${media_type}||${id}`,
|
link: `${media_type}||${id}`,
|
||||||
description: result.description,
|
description: result.description,
|
||||||
genre: result.genre
|
genre: result.genre,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
|
|
||||||
}
|
}
|
||||||
async getSearchInfo(slug) {
|
async getSearchInfo(slug) {
|
||||||
|
|
||||||
var body = await this.tmdbRequest(`catalog/movie/${slug}`);
|
var body = await this.tmdbRequest(`catalog/movie/${slug}`);
|
||||||
var popMovie = await this.getSearchItems(body);
|
var popMovie = await this.getSearchItems(body);
|
||||||
|
|
||||||
|
|
||||||
body = await this.tmdbRequest(`catalog/series/${slug}`);
|
body = await this.tmdbRequest(`catalog/series/${slug}`);
|
||||||
var popSeries = await this.getSearchItems(body);
|
var popSeries = await this.getSearchItems(body);
|
||||||
|
|
||||||
@@ -81,17 +84,15 @@ class DefaultExtension extends MProvider {
|
|||||||
if (priority === "series") {
|
if (priority === "series") {
|
||||||
fullList = [...popSeries, ...popMovie];
|
fullList = [...popSeries, ...popMovie];
|
||||||
} else {
|
} else {
|
||||||
fullList = [...popMovie, ...popSeries]
|
fullList = [...popMovie, ...popSeries];
|
||||||
}
|
}
|
||||||
var hasNextPage = slug.indexOf("search=") > -1 ? false : true;
|
var hasNextPage = slug.indexOf("search=") > -1 ? false : true;
|
||||||
return {
|
return {
|
||||||
list: fullList,
|
list: fullList,
|
||||||
hasNextPage
|
hasNextPage,
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async getPopular(page) {
|
async getPopular(page) {
|
||||||
var skip = (page - 1) * 20;
|
var skip = (page - 1) * 20;
|
||||||
return await this.getSearchInfo(`tmdb.popular/skip=${skip}.json`);
|
return await this.getSearchInfo(`tmdb.popular/skip=${skip}.json`);
|
||||||
@@ -102,56 +103,72 @@ class DefaultExtension extends MProvider {
|
|||||||
async getLatestUpdates(page) {
|
async getLatestUpdates(page) {
|
||||||
var trend_window = this.getPreference("pref_latest_time_window");
|
var trend_window = this.getPreference("pref_latest_time_window");
|
||||||
var skip = (page - 1) * 20;
|
var skip = (page - 1) * 20;
|
||||||
return await this.getSearchInfo(`tmdb.trending/genre=${trend_window}&skip=${skip}.json`);
|
return await this.getSearchInfo(
|
||||||
|
`tmdb.trending/genre=${trend_window}&skip=${skip}.json`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
async search(query, page, filters) {
|
async search(query, page, filters) {
|
||||||
return await this.getSearchInfo(`tmdb.popular/search=${query}.json`);
|
return await this.getSearchInfo(`tmdb.popular/search=${query}.json`);
|
||||||
}
|
}
|
||||||
async getDetail(url) {
|
async getDetail(url) {
|
||||||
|
var baseUrl = this.source.baseUrl;
|
||||||
|
var linkSlug = `${baseUrl}/title/`;
|
||||||
|
|
||||||
|
if (url.includes(linkSlug)) {
|
||||||
|
url = url.replace(linkSlug, "");
|
||||||
|
var id = url.replace("t", "");
|
||||||
|
if (url.includes("t")) {
|
||||||
|
url = `series||tmdb:${id}`;
|
||||||
|
} else {
|
||||||
|
url = `movie||tmdb:${id}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var parts = url.split("||");
|
var parts = url.split("||");
|
||||||
var media_type = parts[0];
|
var media_type = parts[0];
|
||||||
var id = parts[1];
|
var id = parts[1];
|
||||||
var body = await this.tmdbRequest(`meta/${media_type}/${id}.json`)
|
var body = await this.tmdbRequest(`meta/${media_type}/${id}.json`);
|
||||||
var result = body.meta;
|
var result = body.meta;
|
||||||
|
|
||||||
var tmdb_id = id.substring(5,)
|
var tmdb_id = id.substring(5);
|
||||||
media_type = media_type == "series" ? "tv" : media_type;
|
media_type = media_type == "series" ? "tv" : media_type;
|
||||||
|
|
||||||
var dateNow = Date.now().valueOf();
|
var dateNow = Date.now().valueOf();
|
||||||
var release = result.released ? new Date(result.released).valueOf() : dateNow
|
var release = result.released
|
||||||
|
? new Date(result.released).valueOf()
|
||||||
|
: dateNow;
|
||||||
var chaps = [];
|
var chaps = [];
|
||||||
|
|
||||||
var item = {
|
var item = {
|
||||||
name: result.name,
|
name: result.name,
|
||||||
imageUrl: result.poster,
|
imageUrl: result.poster,
|
||||||
link: `${this.source.baseUrl}/${media_type}/${tmdb_id}`,
|
link: `${linkSlug}${linkCode}`,
|
||||||
description: result.description,
|
description: result.description,
|
||||||
genre: result.genre,
|
genre: result.genre,
|
||||||
};
|
};
|
||||||
|
|
||||||
var link = `${media_type}||${tmdb_id}`
|
var link = `${media_type}||${tmdb_id}`;
|
||||||
|
|
||||||
if (media_type == "tv") {
|
if (media_type == "tv") {
|
||||||
|
var videos = result.videos;
|
||||||
var videos = result.videos
|
|
||||||
for (var i in videos) {
|
for (var i in videos) {
|
||||||
var video = videos[i];
|
var video = videos[i];
|
||||||
var seasonNum = video.season;
|
var seasonNum = video.season;
|
||||||
|
|
||||||
if (!seasonNum) continue;
|
if (!seasonNum) continue;
|
||||||
|
|
||||||
release = video.released ? new Date(video.released).valueOf() : dateNow
|
release = video.released ? new Date(video.released).valueOf() : dateNow;
|
||||||
|
|
||||||
if (release < dateNow) {
|
if (release < dateNow) {
|
||||||
var episodeNum = video.episode
|
var episodeNum = video.episode;
|
||||||
var name = `S${seasonNum}:E${episodeNum} - ${video.name}`
|
var name = `S${seasonNum}:E${episodeNum} - ${video.name}`;
|
||||||
var eplink = `${link}||${seasonNum}||${episodeNum}`
|
var eplink = `${link}||${seasonNum}||${episodeNum}`;
|
||||||
|
|
||||||
chaps.push({
|
chaps.push({
|
||||||
name: name,
|
name: name,
|
||||||
url: eplink,
|
url: eplink,
|
||||||
dateUpload: release.toString(),
|
dateUpload: release.toString(),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -160,7 +177,7 @@ class DefaultExtension extends MProvider {
|
|||||||
name: "Movie",
|
name: "Movie",
|
||||||
url: link,
|
url: link,
|
||||||
dateUpload: release.toString(),
|
dateUpload: release.toString(),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,67 +188,68 @@ class DefaultExtension extends MProvider {
|
|||||||
|
|
||||||
// Extracts the streams url for different resolutions from a hls stream.
|
// Extracts the streams url for different resolutions from a hls stream.
|
||||||
async extractStreams(url, lang = "", hdr = {}, host = "") {
|
async extractStreams(url, lang = "", hdr = {}, host = "") {
|
||||||
var streams = [{
|
var streams = [
|
||||||
|
{
|
||||||
url: url,
|
url: url,
|
||||||
originalUrl: url,
|
originalUrl: url,
|
||||||
quality: `${lang} Auto`,
|
quality: `${lang} Auto`,
|
||||||
headers: hdr
|
headers: hdr,
|
||||||
}];
|
},
|
||||||
|
];
|
||||||
|
|
||||||
var pref = this.getPreference("autoembed_split_stream_quality");
|
var pref = this.getPreference("autoembed_split_stream_quality");
|
||||||
if (!pref) return streams
|
if (!pref) return streams;
|
||||||
|
|
||||||
|
|
||||||
const response = await new Client().get(url, hdr);
|
const response = await new Client().get(url, hdr);
|
||||||
const body = response.body;
|
const body = response.body;
|
||||||
const lines = body.split('\n');
|
const lines = body.split("\n");
|
||||||
|
|
||||||
for (let i = 0; i < lines.length; i++) {
|
for (let i = 0; i < lines.length; i++) {
|
||||||
if (lines[i].startsWith('#EXT-X-STREAM-INF:')) {
|
if (lines[i].startsWith("#EXT-X-STREAM-INF:")) {
|
||||||
var resolution = lines[i].match(/RESOLUTION=(\d+x\d+)/)[1];
|
var resolution = lines[i].match(/RESOLUTION=(\d+x\d+)/)[1];
|
||||||
resolution = `${lang} ${resolution}`
|
resolution = `${lang} ${resolution}`;
|
||||||
var m3u8Url = lines[i + 1].trim();
|
var m3u8Url = lines[i + 1].trim();
|
||||||
m3u8Url = m3u8Url.replace("./", `${url}/`)
|
m3u8Url = m3u8Url.replace("./", `${url}/`);
|
||||||
if (host.length > 0) {
|
if (host.length > 0) {
|
||||||
m3u8Url = `${host}${m3u8Url}`
|
m3u8Url = `${host}${m3u8Url}`;
|
||||||
}
|
}
|
||||||
streams.push({
|
streams.push({
|
||||||
url: m3u8Url,
|
url: m3u8Url,
|
||||||
originalUrl: m3u8Url,
|
originalUrl: m3u8Url,
|
||||||
quality: resolution,
|
quality: resolution,
|
||||||
headers: hdr
|
headers: hdr,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return streams
|
return streams;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For some streams, we can form stream url using a default template.
|
// For some streams, we can form stream url using a default template.
|
||||||
async splitStreams(url, lang = "", hdr = {}) {
|
async splitStreams(url, lang = "", hdr = {}) {
|
||||||
var streams = [{
|
var streams = [
|
||||||
|
{
|
||||||
url: url,
|
url: url,
|
||||||
originalUrl: url,
|
originalUrl: url,
|
||||||
quality: `${lang} - Auto`,
|
quality: `${lang} - Auto`,
|
||||||
headers: hdr
|
headers: hdr,
|
||||||
}];
|
},
|
||||||
|
];
|
||||||
|
|
||||||
var pref = this.getPreference("autoembed_split_stream_quality");
|
var pref = this.getPreference("autoembed_split_stream_quality");
|
||||||
if (!pref) return streams
|
if (!pref) return streams;
|
||||||
|
|
||||||
|
var quality = ["360", "480", "720", "1080"];
|
||||||
var quality = ["360", "480", "720", "1080"]
|
|
||||||
for (var q of quality) {
|
for (var q of quality) {
|
||||||
var link = url
|
var link = url;
|
||||||
if (q != "auto") {
|
if (q != "auto") {
|
||||||
link = link.replace("index.m3u8", `${q}/index.m3u8`)
|
link = link.replace("index.m3u8", `${q}/index.m3u8`);
|
||||||
q = `${q}p`
|
q = `${q}p`;
|
||||||
}
|
}
|
||||||
streams.push({
|
streams.push({
|
||||||
url: link,
|
url: link,
|
||||||
originalUrl: link,
|
originalUrl: link,
|
||||||
quality: `${lang} - ${q}`,
|
quality: `${lang} - ${q}`,
|
||||||
headers: hdr
|
headers: hdr,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return streams;
|
return streams;
|
||||||
@@ -241,7 +259,7 @@ class DefaultExtension extends MProvider {
|
|||||||
async sortStreams(streams) {
|
async sortStreams(streams) {
|
||||||
var sortedStreams = [];
|
var sortedStreams = [];
|
||||||
|
|
||||||
var copyStreams = streams.slice()
|
var copyStreams = streams.slice();
|
||||||
var pref = this.getPreference("pref_video_resolution");
|
var pref = this.getPreference("pref_video_resolution");
|
||||||
for (var i in streams) {
|
for (var i in streams) {
|
||||||
var stream = streams[i];
|
var stream = streams[i];
|
||||||
@@ -254,70 +272,74 @@ class DefaultExtension extends MProvider {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [...sortedStreams, ...copyStreams]
|
return [...sortedStreams, ...copyStreams];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets subtitles based on TMDB id.
|
// Gets subtitles based on TMDB id.
|
||||||
async getSubtitleList(id, s, e) {
|
async getSubtitleList(id, s, e) {
|
||||||
var subPref = parseInt(this.getPreference("autoembed_pref_subtitle_source"));
|
var subPref = parseInt(
|
||||||
|
this.getPreference("autoembed_pref_subtitle_source")
|
||||||
|
);
|
||||||
|
|
||||||
var api = `https://sub.wyzie.ru/search?id=${id}`
|
var api = `https://sub.wyzie.ru/search?id=${id}`;
|
||||||
var hdr = {}
|
var hdr = {};
|
||||||
|
|
||||||
if (subPref === 2) {
|
if (subPref === 2) {
|
||||||
api = `https://sources.hexa.watch/subs/${id}`
|
api = `https://sources.hexa.watch/subs/${id}`;
|
||||||
hdr = { "Origin": "https://api.hexa.watch" }
|
hdr = { "Origin": "https://api.hexa.watch" };
|
||||||
if (s != "0") api = `${api}/${s}/${e}`
|
if (s != "0") api = `${api}/${s}/${e}`;
|
||||||
} else {
|
} else {
|
||||||
if (s != "0") api = `${api}&season=${s}&episode=${e}`
|
if (s != "0") api = `${api}&season=${s}&episode=${e}`;
|
||||||
}
|
}
|
||||||
var response = await new Client().get(api, hdr);
|
var response = await new Client().get(api, hdr);
|
||||||
var body = JSON.parse(response.body);
|
var body = JSON.parse(response.body);
|
||||||
|
|
||||||
var subs = []
|
var subs = [];
|
||||||
for (var sub of body) {
|
for (var sub of body) {
|
||||||
subs.push({
|
subs.push({
|
||||||
file: sub.url,
|
file: sub.url,
|
||||||
label: sub.display
|
label: sub.display,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return subs
|
return subs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For anime episode video list
|
// For anime episode video list
|
||||||
async getVideoList(url) {
|
async getVideoList(url) {
|
||||||
var streamAPI = parseInt(this.getPreference("autoembed_stream_source_3"))
|
var streamAPI = parseInt(this.getPreference("autoembed_stream_source_3"));
|
||||||
var nativeSubs = this.getPreference("autoembed_pref_navtive_subtitle")
|
var nativeSubs = this.getPreference("autoembed_pref_navtive_subtitle");
|
||||||
|
|
||||||
var parts = url.split("||");
|
var parts = url.split("||");
|
||||||
var media_type = parts[0];
|
var media_type = parts[0];
|
||||||
var id = parts[1];
|
var id = parts[1];
|
||||||
|
|
||||||
var s = "0"
|
var s = "0";
|
||||||
var e = "0"
|
var e = "0";
|
||||||
if (media_type == "tv") {
|
if (media_type == "tv") {
|
||||||
s = parts[2]
|
s = parts[2];
|
||||||
e = parts[3]
|
e = parts[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
var tmdb = id
|
var tmdb = id;
|
||||||
var streams = []
|
var streams = [];
|
||||||
var subtitles = []
|
var subtitles = [];
|
||||||
switch (streamAPI) {
|
switch (streamAPI) {
|
||||||
case 2: {
|
case 2: {
|
||||||
if (media_type == "tv") {
|
if (media_type == "tv") {
|
||||||
id = `${id}/${s}/${e}`
|
id = `${id}/${s}/${e}`;
|
||||||
}
|
}
|
||||||
var api = `https://play2.123embed.net/server/3?path=/${media_type}/${id}`
|
var api = `https://play2.123embed.net/server/3?path=/${media_type}/${id}`;
|
||||||
var response = await new Client().get(api);
|
var response = await new Client().get(api);
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw new Error("play2.123embed.net unavailable\nPlease choose a different server");
|
throw new Error(
|
||||||
|
"play2.123embed.net unavailable\nPlease choose a different server"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var body = JSON.parse(response.body);
|
var body = JSON.parse(response.body);
|
||||||
var link = body.playlist[0].file
|
var link = body.playlist[0].file;
|
||||||
streams.push({
|
streams.push({
|
||||||
url: link,
|
url: link,
|
||||||
originalUrl: link,
|
originalUrl: link,
|
||||||
@@ -328,97 +350,112 @@ class DefaultExtension extends MProvider {
|
|||||||
}
|
}
|
||||||
case 3: {
|
case 3: {
|
||||||
if (media_type == "tv") {
|
if (media_type == "tv") {
|
||||||
id = `${id}&s=${s}&e=${e}`
|
id = `${id}&s=${s}&e=${e}`;
|
||||||
}
|
}
|
||||||
var api = `https://autoembed.cc/embed/player.php?id=${id}`
|
var api = `https://autoembed.cc/embed/player.php?id=${id}`;
|
||||||
|
|
||||||
var response = await new Client().get(api);
|
var response = await new Client().get(api);
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw new Error("autoembed.cc unavailable\nPlease choose a different server");
|
throw new Error(
|
||||||
|
"autoembed.cc unavailable\nPlease choose a different server"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
var body = response.body
|
var body = response.body;
|
||||||
var sKey = '"file": '
|
var sKey = '"file": ';
|
||||||
var eKey = "]});"
|
var eKey = "]});";
|
||||||
var start = body.indexOf(sKey)
|
var start = body.indexOf(sKey);
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
throw new Error("autoembed.cc videos unavailable\nPlease choose a different server");
|
throw new Error(
|
||||||
|
"autoembed.cc videos unavailable\nPlease choose a different server"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
start += sKey.length
|
start += sKey.length;
|
||||||
|
|
||||||
var end = body.substring(start,).indexOf(eKey) + start - 1
|
var end = body.substring(start).indexOf(eKey) + start - 1;
|
||||||
var strms = JSON.parse(body.substring(start, end) + "]")
|
var strms = JSON.parse(body.substring(start, end) + "]");
|
||||||
for (var strm of strms) {
|
for (var strm of strms) {
|
||||||
var link = strm.file
|
var link = strm.file;
|
||||||
var lang = strm.title
|
var lang = strm.title;
|
||||||
var streamSplit = await this.splitStreams(link, lang);
|
var streamSplit = await this.splitStreams(link, lang);
|
||||||
streams = [...streams, ...streamSplit]
|
streams = [...streams, ...streamSplit];
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: {
|
case 4: {
|
||||||
if (media_type == "tv") {
|
if (media_type == "tv") {
|
||||||
id = `${id}&season=${s}&episode=${e}`
|
id = `${id}&season=${s}&episode=${e}`;
|
||||||
}
|
}
|
||||||
var api = `https://flicky.host/player/desi.php?id=${id}`
|
var api = `https://flicky.host/player/desi.php?id=${id}`;
|
||||||
var response = await new Client().get(api, { "Referer": "https://flicky.host/", "sec-fetch-dest": "iframe" });
|
var response = await new Client().get(api, {
|
||||||
|
"Referer": "https://flicky.host/",
|
||||||
|
"sec-fetch-dest": "iframe",
|
||||||
|
});
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw new Error("flicky.host unavailable\nPlease choose a different server");
|
throw new Error(
|
||||||
|
"flicky.host unavailable\nPlease choose a different server"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
var body = response.body
|
var body = response.body;
|
||||||
var sKey = 'streams = '
|
var sKey = "streams = ";
|
||||||
var eKey = "];"
|
var eKey = "];";
|
||||||
var start = body.indexOf(sKey)
|
var start = body.indexOf(sKey);
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
throw new Error("flicky.host videos unavailable\nPlease choose a different server");
|
throw new Error(
|
||||||
|
"flicky.host videos unavailable\nPlease choose a different server"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
start += sKey.length
|
start += sKey.length;
|
||||||
|
|
||||||
var end = body.substring(start,).indexOf(eKey) + start + 1
|
var end = body.substring(start).indexOf(eKey) + start + 1;
|
||||||
var strms = JSON.parse(body.substring(start, end))
|
var strms = JSON.parse(body.substring(start, end));
|
||||||
|
|
||||||
for (var strm of strms) {
|
for (var strm of strms) {
|
||||||
var link = strm.url
|
var link = strm.url;
|
||||||
var lang = strm.language
|
var lang = strm.language;
|
||||||
var streamSplit = await this.splitStreams(link, lang);
|
var streamSplit = await this.splitStreams(link, lang);
|
||||||
streams = [...streams, ...streamSplit]
|
streams = [...streams, ...streamSplit];
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 5: {
|
case 5: {
|
||||||
if (media_type == "tv") {
|
if (media_type == "tv") {
|
||||||
id = `${id}/${s}/${e}`
|
id = `${id}/${s}/${e}`;
|
||||||
}
|
}
|
||||||
var api = `https://vidapi.click/api/video/${media_type}/${id}`
|
var api = `https://vidapi.click/api/video/${media_type}/${id}`;
|
||||||
var response = await new Client().get(api);
|
var response = await new Client().get(api);
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw new Error("vidapi.click unavailable\nPlease choose a different server");
|
throw new Error(
|
||||||
|
"vidapi.click unavailable\nPlease choose a different server"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var body = JSON.parse(response.body);
|
var body = JSON.parse(response.body);
|
||||||
var link = body.sources[0].file
|
var link = body.sources[0].file;
|
||||||
if(nativeSubs) subtitles = body.tracks
|
if (nativeSubs) subtitles = body.tracks;
|
||||||
streams = await this.extractStreams(link);
|
streams = await this.extractStreams(link);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 6: {
|
case 6: {
|
||||||
if (media_type == "tv") {
|
if (media_type == "tv") {
|
||||||
id = `${id}/${s}/${e}`
|
id = `${id}/${s}/${e}`;
|
||||||
}
|
}
|
||||||
var api = `https://sources.hexa.watch/plsdontscrapemeuwu/${id}`
|
var api = `https://sources.hexa.watch/plsdontscrapemeuwu/${id}`;
|
||||||
var hdr = { "Origin": "https://api.hexa.watch" }
|
var hdr = { "Origin": "https://api.hexa.watch" };
|
||||||
var response = await new Client().get(api, hdr);
|
var response = await new Client().get(api, hdr);
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw new Error("hexa.watch unavailable\nPlease choose a different server");
|
throw new Error(
|
||||||
|
"hexa.watch unavailable\nPlease choose a different server"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var body = JSON.parse(response.body);
|
var body = JSON.parse(response.body);
|
||||||
var strms = body.streams
|
var strms = body.streams;
|
||||||
for (var strm of strms) {
|
for (var strm of strms) {
|
||||||
var streamLink = strm.url;
|
var streamLink = strm.url;
|
||||||
if (streamLink.length > 0) {
|
if (streamLink.length > 0) {
|
||||||
@@ -426,7 +463,7 @@ class DefaultExtension extends MProvider {
|
|||||||
url: strm.url,
|
url: strm.url,
|
||||||
originalUrl: strm.url,
|
originalUrl: strm.url,
|
||||||
quality: `${strm.label} - Auto`,
|
quality: `${strm.label} - Auto`,
|
||||||
headers: strm.headers
|
headers: strm.headers,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -434,35 +471,39 @@ class DefaultExtension extends MProvider {
|
|||||||
}
|
}
|
||||||
case 7: {
|
case 7: {
|
||||||
if (media_type == "tv") {
|
if (media_type == "tv") {
|
||||||
id = `${id}/${s}/${e}`
|
id = `${id}/${s}/${e}`;
|
||||||
}
|
}
|
||||||
var api = `https://vidsrc.su/embed/${media_type}/${id}`
|
var api = `https://vidsrc.su/embed/${media_type}/${id}`;
|
||||||
var response = await new Client().get(api);
|
var response = await new Client().get(api);
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw new Error("vidsrc.su unavailable\nPlease choose a different server");
|
throw new Error(
|
||||||
|
"vidsrc.su unavailable\nPlease choose a different server"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
var body = response.body
|
var body = response.body;
|
||||||
var sKey = 'fixedServers = '
|
var sKey = "fixedServers = ";
|
||||||
var eKey = "];"
|
var eKey = "];";
|
||||||
var start = body.indexOf(sKey)
|
var start = body.indexOf(sKey);
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
throw new Error("vidsrc.su videos unavailable\nPlease choose a different server");
|
throw new Error(
|
||||||
|
"vidsrc.su videos unavailable\nPlease choose a different server"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
start += sKey.length
|
start += sKey.length;
|
||||||
|
|
||||||
var end = body.substring(start,).indexOf(eKey) + start + 1
|
var end = body.substring(start).indexOf(eKey) + start + 1;
|
||||||
var strms = body.substring(start, end)
|
var strms = body.substring(start, end);
|
||||||
|
|
||||||
// Split the data into lines
|
// Split the data into lines
|
||||||
var lines = strms.split('\n');
|
var lines = strms.split("\n");
|
||||||
|
|
||||||
// Regex to match URLs in quotes that start with https://
|
// Regex to match URLs in quotes that start with https://
|
||||||
var regex = /url:\s*'(https:\/\/[^']+)'/;
|
var regex = /url:\s*'(https:\/\/[^']+)'/;
|
||||||
var availableStreams = [];
|
var availableStreams = [];
|
||||||
|
|
||||||
// Process each line
|
// Process each line
|
||||||
lines.forEach(line => {
|
lines.forEach((line) => {
|
||||||
var match = line.match(regex);
|
var match = line.match(regex);
|
||||||
if (match && match[1]) {
|
if (match && match[1]) {
|
||||||
// Extract the label from the line
|
// Extract the label from the line
|
||||||
@@ -478,93 +519,108 @@ class DefaultExtension extends MProvider {
|
|||||||
|
|
||||||
for (var stream of availableStreams) {
|
for (var stream of availableStreams) {
|
||||||
var streamSplit = await this.extractStreams(stream.url, stream.label);
|
var streamSplit = await this.extractStreams(stream.url, stream.label);
|
||||||
streams = [...streams, ...streamSplit]
|
streams = [...streams, ...streamSplit];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nativeSubs) {
|
if (nativeSubs) {
|
||||||
// subtitles
|
// subtitles
|
||||||
sKey = 'const subtitles = '
|
sKey = "const subtitles = ";
|
||||||
eKey = "];"
|
eKey = "];";
|
||||||
start = body.indexOf(sKey)
|
start = body.indexOf(sKey);
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
break; // no need for native subtitle if not found.
|
break; // no need for native subtitle if not found.
|
||||||
}
|
}
|
||||||
start += sKey.length
|
start += sKey.length;
|
||||||
|
|
||||||
end = body.substring(start,).indexOf(eKey) + start + 1
|
end = body.substring(start).indexOf(eKey) + start + 1;
|
||||||
var natSubs = JSON.parse(body.substring(start, end))
|
var natSubs = JSON.parse(body.substring(start, end));
|
||||||
natSubs.forEach(sub=>{
|
natSubs.forEach((sub) => {
|
||||||
subtitles.push({
|
subtitles.push({
|
||||||
file: sub.url,
|
file: sub.url,
|
||||||
label: sub.display
|
label: sub.display,
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 8: {
|
case 8: {
|
||||||
function reverse(str) {
|
function reverse(str) {
|
||||||
return str.split("").reverse().join("")
|
return str.split("").reverse().join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (media_type == "tv") {
|
if (media_type == "tv") {
|
||||||
id = `${id}/${s}/${e}`
|
id = `${id}/${s}/${e}`;
|
||||||
}
|
}
|
||||||
var baseUrl = "https://embed.su"
|
var baseUrl = "https://embed.su";
|
||||||
var embedUrl = `${baseUrl}/embed/${media_type}/${id}`
|
var embedUrl = `${baseUrl}/embed/${media_type}/${id}`;
|
||||||
var response = await new Client().get(embedUrl, this.getHeaders(baseUrl));
|
var response = await new Client().get(
|
||||||
|
embedUrl,
|
||||||
|
this.getHeaders(baseUrl)
|
||||||
|
);
|
||||||
|
|
||||||
var body = response.body
|
var body = response.body;
|
||||||
var sKey = "JSON.parse(atob(`";
|
var sKey = "JSON.parse(atob(`";
|
||||||
var start = body.indexOf(sKey) + sKey.length;
|
var start = body.indexOf(sKey) + sKey.length;
|
||||||
var end = body.substring(start,).indexOf("`") + start
|
var end = body.substring(start).indexOf("`") + start;
|
||||||
var configHash = body.substring(start, end)
|
var configHash = body.substring(start, end);
|
||||||
|
|
||||||
|
|
||||||
var config = JSON.parse(this.decodeBase64(configHash));
|
var config = JSON.parse(this.decodeBase64(configHash));
|
||||||
var encodedHash = this.decodeBase64(config.hash);
|
var encodedHash = this.decodeBase64(config.hash);
|
||||||
var decodeHash = reverse(encodedHash.split(".").map((item) => reverse(item)).join(""))
|
var decodeHash = reverse(
|
||||||
encodedHash = JSON.parse(this.decodeBase64(decodeHash))
|
encodedHash
|
||||||
var serverHash = encodedHash[0].hash
|
.split(".")
|
||||||
|
.map((item) => reverse(item))
|
||||||
|
.join("")
|
||||||
|
);
|
||||||
|
encodedHash = JSON.parse(this.decodeBase64(decodeHash));
|
||||||
|
var serverHash = encodedHash[0].hash;
|
||||||
|
|
||||||
var api = `${baseUrl}/api/e/${serverHash}`
|
var api = `${baseUrl}/api/e/${serverHash}`;
|
||||||
response = await new Client().get(api, this.getHeaders(baseUrl));
|
response = await new Client().get(api, this.getHeaders(baseUrl));
|
||||||
var jsonRes = JSON.parse(response.body);
|
var jsonRes = JSON.parse(response.body);
|
||||||
|
|
||||||
streams = await this.extractStreams(jsonRes.source, "", this.getHeaders(baseUrl), baseUrl);
|
streams = await this.extractStreams(
|
||||||
if (nativeSubs) subtitles = jsonRes.subtitles
|
jsonRes.source,
|
||||||
|
"",
|
||||||
|
this.getHeaders(baseUrl),
|
||||||
|
baseUrl
|
||||||
|
);
|
||||||
|
if (nativeSubs) subtitles = jsonRes.subtitles;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
if (media_type == "tv") {
|
if (media_type == "tv") {
|
||||||
id = `${id}/${s}/${e}`
|
id = `${id}/${s}/${e}`;
|
||||||
}
|
}
|
||||||
var api = `${this.source.apiUrl}/api/getVideoSource?type=${media_type}&id=${id}`
|
var api = `${this.source.apiUrl}/api/getVideoSource?type=${media_type}&id=${id}`;
|
||||||
var response = await new Client().get(api, this.getHeaders(this.source.apiUrl));
|
var response = await new Client().get(
|
||||||
|
api,
|
||||||
|
this.getHeaders(this.source.apiUrl)
|
||||||
|
);
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
throw new Error("tom.autoembed.cc unavailable\nPlease choose a different server");
|
throw new Error(
|
||||||
|
"tom.autoembed.cc unavailable\nPlease choose a different server"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var body = JSON.parse(response.body);
|
var body = JSON.parse(response.body);
|
||||||
var link = body.videoSource
|
var link = body.videoSource;
|
||||||
if (nativeSubs) subtitles = body.subtitles
|
if (nativeSubs) subtitles = body.subtitles;
|
||||||
streams = await this.extractStreams(link);
|
streams = await this.extractStreams(link);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (streams.length < 1) {
|
if (streams.length < 1) {
|
||||||
throw new Error("No streams unavailable\nPlease choose a different server");
|
throw new Error(
|
||||||
|
"No streams unavailable\nPlease choose a different server"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiSubs = await this.getSubtitleList(tmdb, s, e)
|
var apiSubs = await this.getSubtitleList(tmdb, s, e);
|
||||||
streams[0].subtitles = [...subtitles, ...apiSubs]
|
streams[0].subtitles = [...subtitles, ...apiSubs];
|
||||||
|
|
||||||
return await this.sortStreams(streams)
|
return await this.sortStreams(streams);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For manga chapter pages
|
// For manga chapter pages
|
||||||
@@ -576,71 +632,83 @@ class DefaultExtension extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSourcePreferences() {
|
getSourcePreferences() {
|
||||||
return [{
|
return [
|
||||||
key: 'pref_latest_time_window',
|
{
|
||||||
|
key: "pref_latest_time_window",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred latest trend time window',
|
title: "Preferred latest trend time window",
|
||||||
summary: '',
|
summary: "",
|
||||||
valueIndex: 0,
|
valueIndex: 0,
|
||||||
entries: ["Day", "Week"],
|
entries: ["Day", "Week"],
|
||||||
entryValues: ["day", "week"]
|
entryValues: ["day", "week"],
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
key: 'pref_video_resolution',
|
{
|
||||||
|
key: "pref_video_resolution",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred video resolution',
|
title: "Preferred video resolution",
|
||||||
summary: '',
|
summary: "",
|
||||||
valueIndex: 0,
|
valueIndex: 0,
|
||||||
entries: ["Auto", "1080p", "720p", "360p"],
|
entries: ["Auto", "1080p", "720p", "360p"],
|
||||||
entryValues: ["auto", "1080", "720", "360"]
|
entryValues: ["auto", "1080", "720", "360"],
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
key: 'pref_content_priority',
|
{
|
||||||
|
key: "pref_content_priority",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred content priority',
|
title: "Preferred content priority",
|
||||||
summary: 'Choose which type of content to show first',
|
summary: "Choose which type of content to show first",
|
||||||
valueIndex: 0,
|
valueIndex: 0,
|
||||||
entries: ["Movies", "Series"],
|
entries: ["Movies", "Series"],
|
||||||
entryValues: ["movies", "series"]
|
entryValues: ["movies", "series"],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'autoembed_split_stream_quality',
|
key: "autoembed_split_stream_quality",
|
||||||
"switchPreferenceCompat": {
|
"switchPreferenceCompat": {
|
||||||
'title': 'Split stream into different quality streams',
|
"title": "Split stream into different quality streams",
|
||||||
"summary": "Split stream Auto into 360p/720p/1080p",
|
"summary": "Split stream Auto into 360p/720p/1080p",
|
||||||
"value": true
|
"value": true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'autoembed_stream_source_3',
|
key: "autoembed_stream_source_3",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred stream source',
|
title: "Preferred stream source",
|
||||||
summary: '',
|
summary: "",
|
||||||
valueIndex: 0,
|
valueIndex: 0,
|
||||||
entries: ["tom.autoembed.cc", "123embed.net", "autoembed.cc - Indian languages", "flicky.host - Indian languages", "vidapi.click", "hexa.watch", "vidsrc.su", "embed.su"],
|
entries: [
|
||||||
entryValues: ["1", "2", "3", "4", "5", "6", "7", "8"]
|
"tom.autoembed.cc",
|
||||||
}
|
"123embed.net",
|
||||||
|
"autoembed.cc - Indian languages",
|
||||||
|
"flicky.host - Indian languages",
|
||||||
|
"vidapi.click",
|
||||||
|
"hexa.watch",
|
||||||
|
"vidsrc.su",
|
||||||
|
"embed.su",
|
||||||
|
],
|
||||||
|
entryValues: ["1", "2", "3", "4", "5", "6", "7", "8"],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'autoembed_pref_navtive_subtitle',
|
key: "autoembed_pref_navtive_subtitle",
|
||||||
"switchPreferenceCompat": {
|
"switchPreferenceCompat": {
|
||||||
'title': 'Use native subtitles as well',
|
"title": "Use native subtitles as well",
|
||||||
"summary": "Use subtitles provided by the source along with subtitle API",
|
"summary":
|
||||||
"value": true
|
"Use subtitles provided by the source along with subtitle API",
|
||||||
}
|
"value": true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'autoembed_pref_subtitle_source',
|
key: "autoembed_pref_subtitle_source",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred subtitle source',
|
title: "Preferred subtitle source",
|
||||||
summary: '',
|
summary: "",
|
||||||
valueIndex: 0,
|
valueIndex: 0,
|
||||||
entries: ["sub.wyzie.ru", "hexa.watch"],
|
entries: ["sub.wyzie.ru", "hexa.watch"],
|
||||||
entryValues: ["1", "2"]
|
entryValues: ["1", "2"],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,29 @@
|
|||||||
const mangayomiSources = [{
|
const mangayomiSources = [
|
||||||
|
{
|
||||||
"name": "Soaper",
|
"name": "Soaper",
|
||||||
|
"id": 764093578,
|
||||||
"lang": "all",
|
"lang": "all",
|
||||||
"baseUrl": "https://soaper.cc",
|
"baseUrl": "https://soaper.cc",
|
||||||
"apiUrl": "",
|
"apiUrl": "",
|
||||||
"iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://soaper.cc/",
|
"iconUrl":
|
||||||
|
"https://www.google.com/s2/favicons?sz=128&domain=https://soaper.cc/",
|
||||||
"typeSource": "multi",
|
"typeSource": "multi",
|
||||||
"version": "1.0.4",
|
"version": "1.0.5",
|
||||||
"itemType": 1,
|
"itemType": 1,
|
||||||
"dateFormat": "",
|
"dateFormat": "",
|
||||||
"dateFormatLocale": "",
|
"dateFormatLocale": "",
|
||||||
"pkgPath": "anime/src/all/soaper.js"
|
"pkgPath": "anime/src/all/soaper.js"
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Authors: - Swakshan, kodjodevf
|
||||||
|
|
||||||
class DefaultExtension extends MProvider {
|
class DefaultExtension extends MProvider {
|
||||||
getHeaders(url) {
|
getHeaders(url) {
|
||||||
return {
|
return {
|
||||||
"Referer": url,
|
Referer: url,
|
||||||
"Origin": url
|
Origin: url,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getPreference(key) {
|
getPreference(key) {
|
||||||
@@ -25,56 +31,56 @@ class DefaultExtension extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getBasueUrl() {
|
getBasueUrl() {
|
||||||
return this.getPreference("soaper_override_base_url")
|
return this.getPreference("soaper_override_base_url");
|
||||||
}
|
}
|
||||||
|
|
||||||
async request(slug) {
|
async request(slug) {
|
||||||
const baseUrl = this.getBasueUrl()
|
const baseUrl = this.getBasueUrl();
|
||||||
var url = `${baseUrl}/${slug}`
|
var url = `${baseUrl}/${slug}`;
|
||||||
var res = await new Client().get(url, this.getHeaders(baseUrl));
|
var res = await new Client().get(url, this.getHeaders(baseUrl));
|
||||||
var doc = new Document(res.body);
|
var doc = new Document(res.body);
|
||||||
return doc
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
async requestJSON(slug, data) {
|
async requestJSON(slug, data) {
|
||||||
const baseUrl = this.getBasueUrl()
|
const baseUrl = this.getBasueUrl();
|
||||||
var url = `${baseUrl}/${slug}`
|
var url = `${baseUrl}/${slug}`;
|
||||||
var res = await new Client().post(url, this.getHeaders(baseUrl), data);
|
var res = await new Client().post(url, this.getHeaders(baseUrl), data);
|
||||||
return JSON.parse(res.body);
|
return JSON.parse(res.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
async formatList(slug, page) {
|
async formatList(slug, page) {
|
||||||
const baseUrl = this.getPreference("soaper_override_base_url")
|
const baseUrl = this.getPreference("soaper_override_base_url");
|
||||||
slug = parseInt(page) > 1 ? `${slug}?page=${page}` : slug
|
slug = parseInt(page) > 1 ? `${slug}?page=${page}` : slug;
|
||||||
var doc = await this.request(slug);
|
var doc = await this.request(slug);
|
||||||
var list = [];
|
var list = [];
|
||||||
var movies = doc.select(".thumbnail.text-center")
|
var movies = doc.select(".thumbnail.text-center");
|
||||||
|
|
||||||
for (var movie of movies) {
|
for (var movie of movies) {
|
||||||
var linkSection = movie.selectFirst("div.img-group > a")
|
var linkSection = movie.selectFirst("div.img-group > a");
|
||||||
var link = linkSection.getHref.substring(1,);
|
var link = linkSection.getHref.substring(1);
|
||||||
var poster = linkSection.selectFirst("img").getSrc
|
var poster = linkSection.selectFirst("img").getSrc;
|
||||||
var imageUrl = `${baseUrl}${poster}`
|
var imageUrl = `${baseUrl}${poster}`;
|
||||||
var name = movie.selectFirst("h5").selectFirst("a").text;
|
var name = movie.selectFirst("h5").selectFirst("a").text;
|
||||||
|
|
||||||
list.push({ name, imageUrl, link });
|
list.push({ name, imageUrl, link });
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasNextPage = false
|
var hasNextPage = false;
|
||||||
if (slug.indexOf("search.html?") == -1) {
|
if (slug.indexOf("search.html?") == -1) {
|
||||||
var pagination = doc.select("ul.pagination > li")
|
var pagination = doc.select("ul.pagination > li");
|
||||||
var last_page_num = parseInt(pagination[pagination.length - 2].text);
|
var last_page_num = parseInt(pagination[pagination.length - 2].text);
|
||||||
hasNextPage = page < last_page_num ? true : false;
|
hasNextPage = page < last_page_num ? true : false;
|
||||||
}
|
}
|
||||||
return { list, hasNextPage }
|
return { list, hasNextPage };
|
||||||
}
|
}
|
||||||
|
|
||||||
async filterList(year = "all", genre = "all", sort = "new", page = 1) {
|
async filterList(year = "all", genre = "all", sort = "new", page = 1) {
|
||||||
year = year == "all" ? "" : `/year/${year}`
|
year = year == "all" ? "" : `/year/${year}`;
|
||||||
genre = genre == "all" ? "" : `/cat/${genre}`
|
genre = genre == "all" ? "" : `/cat/${genre}`;
|
||||||
sort = sort == "new" ? "" : `/sort/${sort}`
|
sort = sort == "new" ? "" : `/sort/${sort}`;
|
||||||
|
|
||||||
var slug = `${sort}${year}${genre}`
|
var slug = `${sort}${year}${genre}`;
|
||||||
var movieList = await this.formatList(`movielist${slug}`, page);
|
var movieList = await this.formatList(`movielist${slug}`, page);
|
||||||
var seriesList = await this.formatList(`tvlist${slug}`, page);
|
var seriesList = await this.formatList(`tvlist${slug}`, page);
|
||||||
|
|
||||||
@@ -88,7 +94,7 @@ class DefaultExtension extends MProvider {
|
|||||||
|
|
||||||
var hasNextPage = seriesList.hasNextPage || movieList.hasNextPage;
|
var hasNextPage = seriesList.hasNextPage || movieList.hasNextPage;
|
||||||
|
|
||||||
return { list, hasNextPage }
|
return { list, hasNextPage };
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPopular(page) {
|
async getPopular(page) {
|
||||||
@@ -102,15 +108,15 @@ class DefaultExtension extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async search(query, page, filters) {
|
async search(query, page, filters) {
|
||||||
var seriesList = []
|
var seriesList = [];
|
||||||
var movieList = []
|
var movieList = [];
|
||||||
var list = [];
|
var list = [];
|
||||||
|
|
||||||
var res = await this.formatList(`search.html?keyword=${query}`, 1)
|
var res = await this.formatList(`search.html?keyword=${query}`, 1);
|
||||||
var movies = res["list"]
|
var movies = res["list"];
|
||||||
|
|
||||||
for (var movie of movies) {
|
for (var movie of movies) {
|
||||||
var link = movie.link
|
var link = movie.link;
|
||||||
if (link.indexOf("tv_") != -1) {
|
if (link.indexOf("tv_") != -1) {
|
||||||
seriesList.push(movie);
|
seriesList.push(movie);
|
||||||
} else {
|
} else {
|
||||||
@@ -125,62 +131,66 @@ class DefaultExtension extends MProvider {
|
|||||||
list = [...movieList, ...seriesList];
|
list = [...movieList, ...seriesList];
|
||||||
}
|
}
|
||||||
|
|
||||||
return { list, hasNextPage: false }
|
return { list, hasNextPage: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDetail(url) {
|
async getDetail(url) {
|
||||||
var doc = await this.request(url);
|
const baseUrl = this.getPreference("soaper_override_base_url");
|
||||||
|
var slug = url.replace(`${baseUrl}/`,'')
|
||||||
|
var doc = await this.request(slug);
|
||||||
|
var name = doc
|
||||||
|
.selectFirst(".col-sm-12.col-lg-12.text-center")
|
||||||
|
.selectFirst("h4")
|
||||||
|
.text.trim();
|
||||||
|
var poster = doc
|
||||||
|
.selectFirst(".thumbnail.text-center")
|
||||||
|
.selectFirst("img").getSrc;
|
||||||
|
var imageUrl = `${baseUrl}${poster}`;
|
||||||
|
|
||||||
const baseUrl = this.getPreference("soaper_override_base_url")
|
var description = doc.selectFirst("p#wrap").text.trim();
|
||||||
var name = doc.selectFirst(".col-sm-12.col-lg-12.text-center").selectFirst("h4").text.trim()
|
var link = `${baseUrl}/${slug}`;
|
||||||
var poster = doc.selectFirst(".thumbnail.text-center").selectFirst("img").getSrc
|
|
||||||
var imageUrl = `${baseUrl}${poster}`
|
|
||||||
|
|
||||||
var description = doc.selectFirst("p#wrap").text.trim()
|
var chapters = [];
|
||||||
var link = `${baseUrl}/${url}`
|
if (slug.indexOf("tv_") != -1) {
|
||||||
|
var seasonList = doc.select(".alert.alert-info-ex.col-sm-12");
|
||||||
var chapters = []
|
var seasonCount = seasonList.length;
|
||||||
if (url.indexOf("tv_") != -1) {
|
|
||||||
var seasonList = doc.select(".alert.alert-info-ex.col-sm-12")
|
|
||||||
var seasonCount = seasonList.length
|
|
||||||
for (var season of seasonList) {
|
for (var season of seasonList) {
|
||||||
var eps = season.select(".col-sm-12.col-md-6.col-lg-4.myp1")
|
var eps = season.select(".col-sm-12.col-md-6.col-lg-4.myp1");
|
||||||
for (var ep of eps) {
|
for (var ep of eps) {
|
||||||
var epLinkSection = ep.selectFirst("a")
|
var epLinkSection = ep.selectFirst("a");
|
||||||
var epLink = epLinkSection.getHref.substring(1)
|
var epLink = epLinkSection.getHref.substring(1);
|
||||||
var epName = epLinkSection.text
|
var epName = epLinkSection.text;
|
||||||
|
|
||||||
chapters.push({
|
chapters.push({
|
||||||
name: `S${seasonCount}E${epName}`,
|
name: `S${seasonCount}E${epName}`,
|
||||||
url: epLink,
|
url: epLink,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
seasonCount--;
|
seasonCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
chapters.push({
|
chapters.push({
|
||||||
name: "Movie",
|
name: "Movie",
|
||||||
url: url,
|
url: slug,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return { name, imageUrl, description, link, chapters }
|
return { name, imageUrl, description, link, chapters };
|
||||||
}
|
}
|
||||||
// For anime episode video list
|
// For anime episode video list
|
||||||
async getVideoList(url) {
|
async getVideoList(url) {
|
||||||
var body = await this.request(url)
|
var body = await this.request(url);
|
||||||
var baseUrl = this.getBasueUrl()
|
var baseUrl = this.getBasueUrl();
|
||||||
var streams = []
|
var streams = [];
|
||||||
|
|
||||||
// Traditional servers
|
// Traditional servers
|
||||||
var eId = body.selectFirst("#hId").attr('value')
|
var eId = body.selectFirst("#hId").attr("value");
|
||||||
var hIsW = body.selectFirst("#hIsW").attr('value')
|
var hIsW = body.selectFirst("#hIsW").attr("value");
|
||||||
var apiType = url[0].toUpperCase()
|
var apiType = url[0].toUpperCase();
|
||||||
|
|
||||||
var servers = [0, 1]
|
var servers = [0, 1];
|
||||||
for (var serverNum of servers) {
|
for (var serverNum of servers) {
|
||||||
var serverName = body.selectFirst(`#server_button_${serverNum}`).text
|
var serverName = body.selectFirst(`#server_button_${serverNum}`).text;
|
||||||
if (serverName.length < 1) continue;
|
if (serverName.length < 1) continue;
|
||||||
var data = {
|
var data = {
|
||||||
pass: eId,
|
pass: eId,
|
||||||
@@ -188,40 +198,42 @@ class DefaultExtension extends MProvider {
|
|||||||
extra: "1",
|
extra: "1",
|
||||||
e2: hIsW,
|
e2: hIsW,
|
||||||
server: "" + serverNum,
|
server: "" + serverNum,
|
||||||
}
|
};
|
||||||
var res = await this.requestJSON(`home/index/Get${apiType}InfoAjax`, data)
|
var res = await this.requestJSON(
|
||||||
|
`home/index/Get${apiType}InfoAjax`,
|
||||||
|
data
|
||||||
|
);
|
||||||
|
|
||||||
var streamUrl = baseUrl + res.val
|
var streamUrl = baseUrl + res.val;
|
||||||
var subs = []
|
var subs = [];
|
||||||
var vidSubs = res.subs
|
var vidSubs = res.subs;
|
||||||
if (vidSubs != null && vidSubs.length > 0) {
|
if (vidSubs != null && vidSubs.length > 0) {
|
||||||
for (var sub of vidSubs) {
|
for (var sub of vidSubs) {
|
||||||
subs.push({
|
subs.push({
|
||||||
file: baseUrl + sub.path,
|
file: baseUrl + sub.path,
|
||||||
label: sub.name
|
label: sub.name,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
streams.push({
|
streams.push({
|
||||||
url: streamUrl,
|
url: streamUrl,
|
||||||
originalUrl: streamUrl,
|
originalUrl: streamUrl,
|
||||||
quality: serverName,
|
quality: serverName,
|
||||||
subtitles: subs
|
subtitles: subs,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download servers
|
// Download servers
|
||||||
var modal_footer = body.select(".modal-footer > a")
|
var modal_footer = body.select(".modal-footer > a");
|
||||||
if (modal_footer.length > 0) {
|
if (modal_footer.length > 0) {
|
||||||
|
modal_footer.reverse();
|
||||||
modal_footer.reverse()
|
|
||||||
for (var item of modal_footer) {
|
for (var item of modal_footer) {
|
||||||
var dSlug = item.getHref
|
var dSlug = item.getHref;
|
||||||
var dBody = await this.request(dSlug)
|
var dBody = await this.request(dSlug);
|
||||||
|
|
||||||
var res = dBody.selectFirst("#res").attr('value')
|
var res = dBody.selectFirst("#res").attr("value");
|
||||||
var mb = dBody.selectFirst("#mb").attr('value')
|
var mb = dBody.selectFirst("#mb").attr("value");
|
||||||
var streamLink = dBody.selectFirst("#link").attr('value')
|
var streamLink = dBody.selectFirst("#link").attr("value");
|
||||||
|
|
||||||
streams.push({
|
streams.push({
|
||||||
url: streamLink,
|
url: streamLink,
|
||||||
@@ -230,8 +242,7 @@ class DefaultExtension extends MProvider {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return streams
|
return streams;
|
||||||
|
|
||||||
}
|
}
|
||||||
// For manga chapter pages
|
// For manga chapter pages
|
||||||
async getPageList() {
|
async getPageList() {
|
||||||
@@ -242,24 +253,26 @@ class DefaultExtension extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSourcePreferences() {
|
getSourcePreferences() {
|
||||||
return [{
|
return [
|
||||||
"key": "soaper_override_base_url",
|
{
|
||||||
|
key: "soaper_override_base_url",
|
||||||
editTextPreference: {
|
editTextPreference: {
|
||||||
title: "Override base url",
|
title: "Override base url",
|
||||||
summary: "Default: https://soaper.cc",
|
summary: "Default: https://soaper.cc",
|
||||||
value: "https://soaper.cc",
|
value: "https://soaper.cc",
|
||||||
dialogTitle: "Override base url",
|
dialogTitle: "Override base url",
|
||||||
dialogMessage: "",
|
dialogMessage: "",
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
key: 'soaper_content_priority',
|
{
|
||||||
|
key: "soaper_content_priority",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred content priority',
|
title: "Preferred content priority",
|
||||||
summary: 'Choose which type of content to show first',
|
summary: "Choose which type of content to show first",
|
||||||
valueIndex: 0,
|
valueIndex: 0,
|
||||||
entries: ["Movies", "Series"],
|
entries: ["Movies", "Series"],
|
||||||
entryValues: ["movies", "series"]
|
entryValues: ["movies", "series"],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
const mangayomiSources = [{
|
const mangayomiSources = [
|
||||||
|
{
|
||||||
"name": "AnimeGG",
|
"name": "AnimeGG",
|
||||||
"lang": "en",
|
"lang": "en",
|
||||||
|
"id": 209614032,
|
||||||
"baseUrl": "https://www.animegg.org",
|
"baseUrl": "https://www.animegg.org",
|
||||||
"apiUrl": "",
|
"apiUrl": "",
|
||||||
"iconUrl": "https://www.google.com/s2/favicons?sz=256&domain=https://www.animegg.org/",
|
"iconUrl":
|
||||||
|
"https://www.google.com/s2/favicons?sz=256&domain=https://www.animegg.org/",
|
||||||
"typeSource": "single",
|
"typeSource": "single",
|
||||||
"itemType": 1,
|
"itemType": 1,
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"pkgPath": "anime/src/en/animegg.js"
|
"pkgPath": "anime/src/en/animegg.js"
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
class DefaultExtension extends MProvider {
|
class DefaultExtension extends MProvider {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.client = new Client();
|
this.client = new Client();
|
||||||
@@ -19,9 +22,9 @@ class DefaultExtension extends MProvider {
|
|||||||
|
|
||||||
getHeaders(url) {
|
getHeaders(url) {
|
||||||
return {
|
return {
|
||||||
"Referer": this.source.baseUrl,
|
Referer: this.source.baseUrl,
|
||||||
"Origin": this.source.baseUrl
|
Origin: this.source.baseUrl,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getPreference(key) {
|
getPreference(key) {
|
||||||
@@ -29,7 +32,7 @@ class DefaultExtension extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async requestText(slug) {
|
async requestText(slug) {
|
||||||
var url = `${this.source.baseUrl}${slug}`
|
var url = `${this.source.baseUrl}${slug}`;
|
||||||
var res = await this.client.get(url, this.getHeaders());
|
var res = await this.client.get(url, this.getHeaders());
|
||||||
return res.body;
|
return res.body;
|
||||||
}
|
}
|
||||||
@@ -38,36 +41,34 @@ class DefaultExtension extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fetchPopularnLatest(slug) {
|
async fetchPopularnLatest(slug) {
|
||||||
var body = await this.request(slug)
|
var body = await this.request(slug);
|
||||||
var items = body.select("li.fea")
|
var items = body.select("li.fea");
|
||||||
var list = []
|
var list = [];
|
||||||
var hasNextPage = true
|
var hasNextPage = true;
|
||||||
if (items.length > 0) {
|
if (items.length > 0) {
|
||||||
for (var item of items) {
|
for (var item of items) {
|
||||||
var imageUrl = item.selectFirst('img').getSrc
|
var imageUrl = item.selectFirst("img").getSrc;
|
||||||
var linkSection = item.selectFirst('.rightpop').selectFirst('a')
|
var linkSection = item.selectFirst(".rightpop").selectFirst("a");
|
||||||
var link = linkSection.getHref
|
var link = linkSection.getHref;
|
||||||
var name = linkSection.text
|
var name = linkSection.text;
|
||||||
list.push({
|
list.push({
|
||||||
name,
|
name,
|
||||||
imageUrl,
|
imageUrl,
|
||||||
link
|
link,
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
hasNextPage = false;
|
||||||
}
|
}
|
||||||
else {
|
return { list, hasNextPage };
|
||||||
hasNextPage = false
|
|
||||||
}
|
|
||||||
return { list, hasNextPage }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPopular(page) {
|
async getPopular(page) {
|
||||||
var start = (page - 1) * 25;
|
var start = (page - 1) * 25;
|
||||||
var limit = start + 25;
|
var limit = start + 25;
|
||||||
|
|
||||||
var category = ""
|
var category = "";
|
||||||
var pop = this.getPreference("animegg_popular_category")
|
var pop = this.getPreference("animegg_popular_category");
|
||||||
switch (pop) {
|
switch (pop) {
|
||||||
case 1: {
|
case 1: {
|
||||||
category = "sortBy=createdAt&sortDirection=DESC&";
|
category = "sortBy=createdAt&sortDirection=DESC&";
|
||||||
@@ -85,12 +86,9 @@ class DefaultExtension extends MProvider {
|
|||||||
category = "sortBy=sortLetter&sortDirection=ASC&";
|
category = "sortBy=sortLetter&sortDirection=ASC&";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
var slug = `/popular-series?${category}start=${start}&limit=${limit}`
|
var slug = `/popular-series?${category}start=${start}&limit=${limit}`;
|
||||||
return await this.fetchPopularnLatest(slug)
|
return await this.fetchPopularnLatest(slug);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
get supportsLatest() {
|
get supportsLatest() {
|
||||||
throw new Error("supportsLatest not implemented");
|
throw new Error("supportsLatest not implemented");
|
||||||
@@ -99,104 +97,99 @@ class DefaultExtension extends MProvider {
|
|||||||
var start = (page - 1) * 25;
|
var start = (page - 1) * 25;
|
||||||
var limit = start + 25;
|
var limit = start + 25;
|
||||||
|
|
||||||
var slug = `/releases?start=${start}&limit=${limit}`
|
var slug = `/releases?start=${start}&limit=${limit}`;
|
||||||
return await this.fetchPopularnLatest(slug)
|
return await this.fetchPopularnLatest(slug);
|
||||||
|
|
||||||
}
|
}
|
||||||
async search(query, page, filters) {
|
async search(query, page, filters) {
|
||||||
var slug = `/search?q=${query}`
|
var slug = `/search?q=${query}`;
|
||||||
var body = await this.request(slug)
|
var body = await this.request(slug);
|
||||||
var items = body.select(".moose.page > a")
|
var items = body.select(".moose.page > a");
|
||||||
var list = []
|
var list = [];
|
||||||
for (var item of items) {
|
for (var item of items) {
|
||||||
var imageUrl = item.selectFirst('img').getSrc
|
var imageUrl = item.selectFirst("img").getSrc;
|
||||||
var link = item.getHref
|
var link = item.getHref;
|
||||||
var name = item.selectFirst("h2").text
|
var name = item.selectFirst("h2").text;
|
||||||
list.push({
|
list.push({
|
||||||
name,
|
name,
|
||||||
imageUrl,
|
imageUrl,
|
||||||
link
|
link,
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return { list, hasNextPage: false }
|
return { list, hasNextPage: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
statusCode(status) {
|
statusCode(status) {
|
||||||
return {
|
return (
|
||||||
"Ongoing": 0,
|
{
|
||||||
"Completed": 1,
|
Ongoing: 0,
|
||||||
}[status] ?? 5;
|
Completed: 1,
|
||||||
|
}[status] ?? 5
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDetail(url) {
|
async getDetail(url) {
|
||||||
var link = this.source.baseUrl + url;
|
var baseUrl = this.source.baseUrl;
|
||||||
|
var slug = url.replace(baseUrl, "");
|
||||||
|
var link = baseUrl + slug;
|
||||||
|
|
||||||
var body = await this.request(url)
|
var body = await this.request(slug);
|
||||||
|
|
||||||
var media = body.selectFirst(".media")
|
var media = body.selectFirst(".media");
|
||||||
var title = media.selectFirst("h1").text
|
var title = media.selectFirst("h1").text;
|
||||||
var spans = media.selectFirst("p.infoami").select("span")
|
var spans = media.selectFirst("p.infoami").select("span");
|
||||||
var statusText = spans[spans.length - 1].text.replace("Status: ", '')
|
var statusText = spans[spans.length - 1].text.replace("Status: ", "");
|
||||||
var status = this.statusCode(statusText)
|
var status = this.statusCode(statusText);
|
||||||
|
|
||||||
|
var tagscat = media.select(".tagscat > li");
|
||||||
|
var genre = [];
|
||||||
|
tagscat.forEach((tag) => genre.push(tag.text));
|
||||||
|
var description = body.selectFirst("p.ptext").text;
|
||||||
|
var chapters = [];
|
||||||
|
|
||||||
var tagscat = media.select(".tagscat > li")
|
var episodesList = body.select(".newmanga > li");
|
||||||
var genre = []
|
episodesList.forEach((ep) => {
|
||||||
tagscat.forEach(tag => genre.push(tag.text))
|
var epTitle = ep.selectFirst("i.anititle").text;
|
||||||
var description = body.selectFirst("p.ptext").text
|
var epNumber = ep.selectFirst("strong").text.replace(title, "Episode");
|
||||||
var chapters = []
|
var epName = epNumber == epTitle ? epNumber : `${epNumber} - ${epTitle}`;
|
||||||
|
var epUrl = ep.selectFirst("a").getHref;
|
||||||
var episodesList = body.select(".newmanga > li")
|
|
||||||
episodesList.forEach(ep => {
|
|
||||||
var epTitle = ep.selectFirst('i.anititle').text
|
|
||||||
var epNumber = ep.selectFirst('strong').text.replace(title, "Episode")
|
|
||||||
var epName = epNumber == epTitle ? epNumber : `${epNumber} - ${epTitle}`
|
|
||||||
var epUrl = ep.selectFirst("a").getHref
|
|
||||||
|
|
||||||
var scanlator = "";
|
var scanlator = "";
|
||||||
var type = ep.select("span.btn-xs")
|
var type = ep.select("span.btn-xs");
|
||||||
type.forEach(t => {
|
type.forEach((t) => {
|
||||||
scanlator += t.text + ", ";
|
scanlator += t.text + ", ";
|
||||||
|
});
|
||||||
})
|
|
||||||
scanlator = scanlator.slice(0, -2);
|
scanlator = scanlator.slice(0, -2);
|
||||||
|
|
||||||
chapters.push({ name: epName, url: epUrl, scanlator })
|
chapters.push({ name: epName, url: epUrl, scanlator });
|
||||||
})
|
});
|
||||||
|
|
||||||
|
|
||||||
return { description, status, genre, chapters, link }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return { description, status, genre, chapters, link };
|
||||||
}
|
}
|
||||||
|
|
||||||
async exxtractStreams(div,audio){
|
async exxtractStreams(div, audio) {
|
||||||
|
var slug = div.selectFirst("iframe").getSrc;
|
||||||
var slug = div.selectFirst("iframe").getSrc
|
var streams = [];
|
||||||
var streams = []
|
if (slug.length < 1) {
|
||||||
if(slug.length < 1){
|
|
||||||
return streams;
|
return streams;
|
||||||
}
|
}
|
||||||
var body = await this.requestText(slug)
|
var body = await this.requestText(slug);
|
||||||
var sKey = "var videoSources = "
|
var sKey = "var videoSources = ";
|
||||||
var eKey = "var httpProtocol"
|
var eKey = "var httpProtocol";
|
||||||
var start = body.indexOf(sKey) + sKey.length
|
var start = body.indexOf(sKey) + sKey.length;
|
||||||
var end = body.indexOf(eKey) - 8
|
var end = body.indexOf(eKey) - 8;
|
||||||
var videoSourcesStr = body.substring(start, end)
|
var videoSourcesStr = body.substring(start, end);
|
||||||
let videoSources = eval("(" + videoSourcesStr + ")");
|
let videoSources = eval("(" + videoSourcesStr + ")");
|
||||||
var headers = this.getHeaders();
|
var headers = this.getHeaders();
|
||||||
videoSources.forEach(videoSource => {
|
videoSources.forEach((videoSource) => {
|
||||||
var url = this.source.baseUrl +videoSource.file
|
var url = this.source.baseUrl + videoSource.file;
|
||||||
var quality = `${videoSource.label} - ${audio}`
|
var quality = `${videoSource.label} - ${audio}`;
|
||||||
|
|
||||||
streams.push({
|
streams.push({
|
||||||
url,
|
url,
|
||||||
originalUrl: url,
|
originalUrl: url,
|
||||||
quality,
|
quality,
|
||||||
headers
|
headers,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return streams.reverse();
|
return streams.reverse();
|
||||||
@@ -204,31 +197,28 @@ class DefaultExtension extends MProvider {
|
|||||||
|
|
||||||
// For anime episode video list
|
// For anime episode video list
|
||||||
async getVideoList(url) {
|
async getVideoList(url) {
|
||||||
var body = await this.request(url)
|
var body = await this.request(url);
|
||||||
|
|
||||||
var sub = body.selectFirst("#subbed-Animegg")
|
var sub = body.selectFirst("#subbed-Animegg");
|
||||||
var subStreams = await this.exxtractStreams(sub,"Sub")
|
var subStreams = await this.exxtractStreams(sub, "Sub");
|
||||||
|
|
||||||
var dub = body.selectFirst("#dubbed-Animegg")
|
var dub = body.selectFirst("#dubbed-Animegg");
|
||||||
var dubStreams = await this.exxtractStreams(dub,"Dub")
|
var dubStreams = await this.exxtractStreams(dub, "Dub");
|
||||||
|
|
||||||
var raw = body.selectFirst("#raw-Animegg")
|
var raw = body.selectFirst("#raw-Animegg");
|
||||||
var rawStreams = await this.exxtractStreams(raw,"Raw")
|
var rawStreams = await this.exxtractStreams(raw, "Raw");
|
||||||
|
|
||||||
|
var pref = this.getPreference("animegg_stream_type_1");
|
||||||
|
|
||||||
var pref = this.getPreference("animegg_stream_type_1")
|
|
||||||
var streams = [];
|
var streams = [];
|
||||||
if(pref == 0){
|
if (pref == 0) {
|
||||||
streams = [...subStreams,...dubStreams, ...rawStreams]
|
streams = [...subStreams, ...dubStreams, ...rawStreams];
|
||||||
}else if(pref == 1){
|
} else if (pref == 1) {
|
||||||
streams = [...dubStreams,...subStreams, ...rawStreams]
|
streams = [...dubStreams, ...subStreams, ...rawStreams];
|
||||||
}else{
|
} else {
|
||||||
streams = [...rawStreams,...subStreams, ...dubStreams]
|
streams = [...rawStreams, ...subStreams, ...dubStreams];
|
||||||
}
|
}
|
||||||
|
|
||||||
return streams
|
return streams;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getSourcePreferences() {
|
getSourcePreferences() {
|
||||||
@@ -236,23 +226,29 @@ class DefaultExtension extends MProvider {
|
|||||||
{
|
{
|
||||||
key: "animegg_popular_category",
|
key: "animegg_popular_category",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred popular category',
|
title: "Preferred popular category",
|
||||||
summary: '',
|
summary: "",
|
||||||
valueIndex: 0,
|
valueIndex: 0,
|
||||||
entries: ["Popular", "Newest", "Ongoing", "Completed", "Alphabetical"],
|
entries: [
|
||||||
entryValues: ["0", "1", "2", "3", "4"]
|
"Popular",
|
||||||
}
|
"Newest",
|
||||||
|
"Ongoing",
|
||||||
|
"Completed",
|
||||||
|
"Alphabetical",
|
||||||
|
],
|
||||||
|
entryValues: ["0", "1", "2", "3", "4"],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "animegg_stream_type_1",
|
key: "animegg_stream_type_1",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred stream type',
|
title: "Preferred stream type",
|
||||||
summary: '',
|
summary: "",
|
||||||
valueIndex: 0,
|
valueIndex: 0,
|
||||||
entries: ["Sub","Dub","Raw"],
|
entries: ["Sub", "Dub", "Raw"],
|
||||||
entryValues: ["0", "1", "2"]
|
entryValues: ["0", "1", "2"],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const mangayomiSources = [{
|
|||||||
"iconUrl": "https://www.google.com/s2/favicons?sz=256&domain=https://www.animeonsen.xyz",
|
"iconUrl": "https://www.google.com/s2/favicons?sz=256&domain=https://www.animeonsen.xyz",
|
||||||
"typeSource": "single",
|
"typeSource": "single",
|
||||||
"itemType": 1,
|
"itemType": 1,
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"pkgPath": "anime/src/all/animeonsen.js"
|
"pkgPath": "anime/src/all/animeonsen.js"
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@@ -143,7 +143,9 @@ class DefaultExtension extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getDetail(url) {
|
async getDetail(url) {
|
||||||
var link = `${this.source.baseUrl}/details/${url}`
|
var linkSlug = `${this.source.baseUrl}/details/`
|
||||||
|
url = url.replace(linkSlug, "")
|
||||||
|
var link = `${linkSlug}${url}`
|
||||||
var detailsApiSlug = `/${url}/extensive`
|
var detailsApiSlug = `/${url}/extensive`
|
||||||
var animeDetails = await this.request(detailsApiSlug);
|
var animeDetails = await this.request(detailsApiSlug);
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
const mangayomiSources = [{
|
const mangayomiSources = [
|
||||||
|
{
|
||||||
"name": "AnimeParadise",
|
"name": "AnimeParadise",
|
||||||
"lang": "en",
|
"lang": "en",
|
||||||
"baseUrl": "https://animeparadise.moe",
|
"baseUrl": "https://animeparadise.moe",
|
||||||
"apiUrl": "https://api.animeparadise.moe",
|
"apiUrl": "https://api.animeparadise.moe",
|
||||||
"iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://animeparadise.moe",
|
"iconUrl":
|
||||||
|
"https://www.google.com/s2/favicons?sz=128&domain=https://animeparadise.moe",
|
||||||
"typeSource": "single",
|
"typeSource": "single",
|
||||||
"itemType": 1,
|
"itemType": 1,
|
||||||
"version": "0.0.1",
|
"version": "0.0.2",
|
||||||
"pkgPath": "anime/src/en/animeparadise.js"
|
"pkgPath": "anime/src/en/animeparadise.js"
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
class DefaultExtension extends MProvider {
|
class DefaultExtension extends MProvider {
|
||||||
|
|
||||||
getPreference(key) {
|
getPreference(key) {
|
||||||
const preferences = new SharedPreferences();
|
const preferences = new SharedPreferences();
|
||||||
return preferences.get(key);
|
return preferences.get(key);
|
||||||
@@ -20,12 +22,12 @@ class DefaultExtension extends MProvider {
|
|||||||
async extractFromUrl(url) {
|
async extractFromUrl(url) {
|
||||||
var res = await new Client().get(this.source.baseUrl + url);
|
var res = await new Client().get(this.source.baseUrl + url);
|
||||||
var doc = new Document(res.body);
|
var doc = new Document(res.body);
|
||||||
var jsonData = doc.selectFirst("#__NEXT_DATA__").text
|
var jsonData = doc.selectFirst("#__NEXT_DATA__").text;
|
||||||
return JSON.parse(jsonData).props.pageProps
|
return JSON.parse(jsonData).props.pageProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
async requestAPI(slug) {
|
async requestAPI(slug) {
|
||||||
var api = `${this.source.apiUrl}/${slug}`
|
var api = `${this.source.apiUrl}/${slug}`;
|
||||||
var response = await new Client().get(api);
|
var response = await new Client().get(api);
|
||||||
var body = JSON.parse(response.body);
|
var body = JSON.parse(response.body);
|
||||||
return body;
|
return body;
|
||||||
@@ -35,89 +37,91 @@ class DefaultExtension extends MProvider {
|
|||||||
var jsonData = await this.requestAPI(slug);
|
var jsonData = await this.requestAPI(slug);
|
||||||
var list = [];
|
var list = [];
|
||||||
if ("episodes" in jsonData) {
|
if ("episodes" in jsonData) {
|
||||||
jsonData.episodes.forEach(item => {
|
jsonData.episodes.forEach((item) => {
|
||||||
list.push({
|
list.push({
|
||||||
"name": item.origin.title,
|
"name": item.origin.title,
|
||||||
"link": item.origin.link,
|
"link": item.origin.link,
|
||||||
"imageUrl": item.image
|
"imageUrl": item.image,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
jsonData.data.forEach(item => {
|
jsonData.data.forEach((item) => {
|
||||||
list.push({
|
list.push({
|
||||||
"name": item.title,
|
"name": item.title,
|
||||||
"link": item.link,
|
"link": item.link,
|
||||||
"imageUrl": item.posterImage.original
|
"imageUrl": item.posterImage.original,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"list": list,
|
"list": list,
|
||||||
"hasNextPage": false
|
"hasNextPage": false,
|
||||||
}
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPopular(page) {
|
async getPopular(page) {
|
||||||
return await this.formList('?sort={"rate": -1 }')
|
return await this.formList('?sort={"rate": -1 }');
|
||||||
}
|
}
|
||||||
|
|
||||||
async getLatestUpdates(page) {
|
async getLatestUpdates(page) {
|
||||||
var slug = '?sort={"postDate": -1 }';
|
var slug = '?sort={"postDate": -1 }';
|
||||||
|
|
||||||
var choice = this.getPreference("animeparadise_pref_latest_tab");
|
var choice = this.getPreference("animeparadise_pref_latest_tab");
|
||||||
if (choice === "recent_ep") slug = 'ep/recently-added';
|
if (choice === "recent_ep") slug = "ep/recently-added";
|
||||||
|
|
||||||
return await this.formList(slug)
|
return await this.formList(slug);
|
||||||
}
|
}
|
||||||
async search(query, page, filters) {
|
async search(query, page, filters) {
|
||||||
var season = filters[0].values[filters[0].state].value
|
var season = filters[0].values[filters[0].state].value;
|
||||||
var year = filters[1].values[filters[1].state].value
|
var year = filters[1].values[filters[1].state].value;
|
||||||
|
|
||||||
var genre = "genre[]="
|
var genre = "genre[]=";
|
||||||
for (var filter of filters[2].state) {
|
for (var filter of filters[2].state) {
|
||||||
if (filter.state == true)
|
if (filter.state == true) genre += `${filter.value}&genre[]=`;
|
||||||
genre += `${filter.value}&genre[]=`
|
|
||||||
}
|
}
|
||||||
var slug = `search?q=${query}&year=${year}&season=${season}&${genre}`
|
var slug = `search?q=${query}&year=${year}&season=${season}&${genre}`;
|
||||||
return await this.formList(slug);
|
return await this.formList(slug);
|
||||||
}
|
}
|
||||||
statusCode(status) {
|
statusCode(status) {
|
||||||
return {
|
return (
|
||||||
|
{
|
||||||
"current": 0,
|
"current": 0,
|
||||||
"finished": 1,
|
"finished": 1,
|
||||||
}[status] ?? 5;
|
}[status] ?? 5
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDetail(url) {
|
async getDetail(url) {
|
||||||
var link = this.source.baseUrl + `/anime/${url}`
|
var linkSlug = this.source.baseUrl + `/anime/`;
|
||||||
var jsonData = await this.extractFromUrl(`/anime/${url}`)
|
if (url.includes(linkSlug)) url = url.replace(linkSlug, "");
|
||||||
jsonData = jsonData.data
|
|
||||||
var details = {}
|
var jsonData = await this.extractFromUrl(`/anime/${url}`);
|
||||||
var chapters = []
|
jsonData = jsonData.data;
|
||||||
details.imageUrl = jsonData.posterImage.original
|
var details = {};
|
||||||
details.description = jsonData.synopsys
|
var chapters = [];
|
||||||
details.genre = jsonData.genres
|
details.imageUrl = jsonData.posterImage.original;
|
||||||
details.status = this.statusCode(jsonData.status)
|
details.description = jsonData.synopsys;
|
||||||
var id = jsonData._id
|
details.genre = jsonData.genres;
|
||||||
var epAPI = await this.requestAPI(`anime/${id}/episode`)
|
details.status = this.statusCode(jsonData.status);
|
||||||
epAPI.data.forEach(ep => {
|
var id = jsonData._id;
|
||||||
|
var epAPI = await this.requestAPI(`anime/${id}/episode`);
|
||||||
|
epAPI.data.forEach((ep) => {
|
||||||
var epName = `E${ep.number}: ${ep.title}`;
|
var epName = `E${ep.number}: ${ep.title}`;
|
||||||
var epUrl = `${ep.uid}?origin=${ep.origin}`
|
var epUrl = `${ep.uid}?origin=${ep.origin}`;
|
||||||
chapters.push({ name: epName, url: epUrl })
|
chapters.push({ name: epName, url: epUrl });
|
||||||
})
|
});
|
||||||
|
details.link = `${linkSlug}${url}`;
|
||||||
details.chapters = chapters.reverse();
|
details.chapters = chapters.reverse();
|
||||||
return details;
|
return details;
|
||||||
}
|
}
|
||||||
// Sorts streams based on user preference.
|
// Sorts streams based on user preference.
|
||||||
async sortStreams(streams) {
|
async sortStreams(streams) {
|
||||||
var sortedStreams = [];
|
var sortedStreams = [];
|
||||||
var copyStreams = streams.slice()
|
var copyStreams = streams.slice();
|
||||||
|
|
||||||
var pref = await this.getPreference("animeparadise_pref_video_resolution");
|
var pref = await this.getPreference("animeparadise_pref_video_resolution");
|
||||||
for (var stream of streams) {
|
for (var stream of streams) {
|
||||||
|
|
||||||
if (stream.quality.indexOf(pref) > -1) {
|
if (stream.quality.indexOf(pref) > -1) {
|
||||||
sortedStreams.push(stream);
|
sortedStreams.push(stream);
|
||||||
var index = copyStreams.indexOf(stream);
|
var index = copyStreams.indexOf(stream);
|
||||||
@@ -127,115 +131,140 @@ class DefaultExtension extends MProvider {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [...sortedStreams, ...copyStreams]
|
return [...sortedStreams, ...copyStreams];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extracts the streams url for different resolutions from a hls stream.
|
// Extracts the streams url for different resolutions from a hls stream.
|
||||||
async extractStreams(url) {
|
async extractStreams(url) {
|
||||||
const response = await new Client().get(url);
|
const response = await new Client().get(url);
|
||||||
const body = response.body;
|
const body = response.body;
|
||||||
const lines = body.split('\n');
|
const lines = body.split("\n");
|
||||||
var streams = [{
|
var streams = [
|
||||||
|
{
|
||||||
url: url,
|
url: url,
|
||||||
originalUrl: url,
|
originalUrl: url,
|
||||||
quality: `Auto`,
|
quality: `Auto`,
|
||||||
}];
|
},
|
||||||
|
];
|
||||||
|
|
||||||
for (let i = 0; i < lines.length; i++) {
|
for (let i = 0; i < lines.length; i++) {
|
||||||
if (lines[i].startsWith('#EXT-X-STREAM-INF:')) {
|
if (lines[i].startsWith("#EXT-X-STREAM-INF:")) {
|
||||||
var resolution = lines[i].match(/RESOLUTION=(\d+x\d+)/)[1];
|
var resolution = lines[i].match(/RESOLUTION=(\d+x\d+)/)[1];
|
||||||
var m3u8Url = lines[i + 1].trim();
|
var m3u8Url = lines[i + 1].trim();
|
||||||
m3u8Url = url.replace("master.m3u8", m3u8Url)
|
m3u8Url = url.replace("master.m3u8", m3u8Url);
|
||||||
|
|
||||||
streams.push({
|
streams.push({
|
||||||
url: m3u8Url,
|
url: m3u8Url,
|
||||||
originalUrl: m3u8Url,
|
originalUrl: m3u8Url,
|
||||||
quality: resolution
|
quality: resolution,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return streams
|
return streams;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For anime episode video list
|
// For anime episode video list
|
||||||
async getVideoList(url) {
|
async getVideoList(url) {
|
||||||
var streams = []
|
var streams = [];
|
||||||
var jsonData = await this.extractFromUrl(`/watch/${url}`);
|
var jsonData = await this.extractFromUrl(`/watch/${url}`);
|
||||||
var epData = jsonData.episode
|
var epData = jsonData.episode;
|
||||||
streams = await this.extractStreams(epData.streamLink)
|
streams = await this.extractStreams(epData.streamLink);
|
||||||
|
|
||||||
var subtitles = []
|
var subtitles = [];
|
||||||
epData.subData.forEach(sub => {
|
epData.subData.forEach((sub) => {
|
||||||
subtitles.push({
|
subtitles.push({
|
||||||
"label": sub.label,
|
"label": sub.label,
|
||||||
"file": `${this.source.apiUrl}/stream/file/${sub.src}`,
|
"file": `${this.source.apiUrl}/stream/file/${sub.src}`,
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
streams[0].subtitles = subtitles
|
streams[0].subtitles = subtitles;
|
||||||
|
|
||||||
return streams
|
|
||||||
|
|
||||||
|
return streams;
|
||||||
}
|
}
|
||||||
|
|
||||||
addCatogory(arr, typ) {
|
addCatogory(arr, typ) {
|
||||||
arr = arr.map(x => ({ type_name: typ, name: x, value: x }))
|
arr = arr.map((x) => ({ type_name: typ, name: x, value: x }));
|
||||||
arr.unshift({
|
arr.unshift({
|
||||||
type_name: typ,
|
type_name: typ,
|
||||||
name: 'All',
|
name: "All",
|
||||||
value: ''
|
value: "",
|
||||||
})
|
});
|
||||||
return arr
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFilterList() {
|
getFilterList() {
|
||||||
var seasons = ["Winter", "Spring", "Summer", "Fall"]
|
var seasons = ["Winter", "Spring", "Summer", "Fall"];
|
||||||
|
|
||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
var years = Array.from({ length: currentYear - 1939 }, (_, i) => (i + 1940).toString()).reverse()
|
var years = Array.from({ length: currentYear - 1939 }, (_, i) =>
|
||||||
|
(i + 1940).toString()
|
||||||
|
).reverse();
|
||||||
|
|
||||||
var genres = ["Action", "Adventure", "Comedy", "Drama", "Ecchi", "Fantasy", "Horror", "Mahou Shojo", "Mecha", "Music", "Mystery", "Psychological", "Romance", "Sci-Fi", "Slice of Life", "Sports", "Supernatural", "Thriller"].map(x => ({ type_name: "CheckBox", name: x, value: x }))
|
var genres = [
|
||||||
|
"Action",
|
||||||
|
"Adventure",
|
||||||
|
"Comedy",
|
||||||
|
"Drama",
|
||||||
|
"Ecchi",
|
||||||
|
"Fantasy",
|
||||||
|
"Horror",
|
||||||
|
"Mahou Shojo",
|
||||||
|
"Mecha",
|
||||||
|
"Music",
|
||||||
|
"Mystery",
|
||||||
|
"Psychological",
|
||||||
|
"Romance",
|
||||||
|
"Sci-Fi",
|
||||||
|
"Slice of Life",
|
||||||
|
"Sports",
|
||||||
|
"Supernatural",
|
||||||
|
"Thriller",
|
||||||
|
].map((x) => ({ type_name: "CheckBox", name: x, value: x }));
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
type_name: "SelectFilter",
|
type_name: "SelectFilter",
|
||||||
name: "Season",
|
name: "Season",
|
||||||
state: 0,
|
state: 0,
|
||||||
values: this.addCatogory(seasons, "SelectOption")
|
values: this.addCatogory(seasons, "SelectOption"),
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
type_name: "SelectFilter",
|
type_name: "SelectFilter",
|
||||||
name: "Year",
|
name: "Year",
|
||||||
state: 0,
|
state: 0,
|
||||||
values: this.addCatogory(years, "SelectOption")
|
values: this.addCatogory(years, "SelectOption"),
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
type_name: "GroupFilter",
|
type_name: "GroupFilter",
|
||||||
name: "Genres",
|
name: "Genres",
|
||||||
state: genres
|
state: genres,
|
||||||
}
|
},
|
||||||
]
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
getSourcePreferences() {
|
getSourcePreferences() {
|
||||||
return [{
|
return [
|
||||||
key: 'animeparadise_pref_latest_tab',
|
{
|
||||||
|
key: "animeparadise_pref_latest_tab",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Latest tab category',
|
title: "Latest tab category",
|
||||||
summary: 'Anime list to be shown in latest tab',
|
summary: "Anime list to be shown in latest tab",
|
||||||
valueIndex: 0,
|
valueIndex: 0,
|
||||||
entries: ["Recently added anime", "Recently added episode"],
|
entries: ["Recently added anime", "Recently added episode"],
|
||||||
entryValues: ["recent_ani", "recent_ep"]
|
entryValues: ["recent_ani", "recent_ep"],
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
key: 'animeparadise_pref_video_resolution',
|
{
|
||||||
|
key: "animeparadise_pref_video_resolution",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred video resolution',
|
title: "Preferred video resolution",
|
||||||
summary: '',
|
summary: "",
|
||||||
valueIndex: 0,
|
valueIndex: 0,
|
||||||
entries: ["Auto", "1080p", "720p", "360p"],
|
entries: ["Auto", "1080p", "720p", "360p"],
|
||||||
entryValues: ["auto", "1080", "720", "360"]
|
entryValues: ["auto", "1080", "720", "360"],
|
||||||
}
|
|
||||||
},
|
},
|
||||||
]
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
const mangayomiSources = [{
|
const mangayomiSources = [
|
||||||
|
{
|
||||||
"name": "AnimeZ",
|
"name": "AnimeZ",
|
||||||
"lang": "en",
|
"lang": "en",
|
||||||
"baseUrl": "https://animez.org",
|
"baseUrl": "https://animez.org",
|
||||||
"apiUrl": "",
|
"apiUrl": "",
|
||||||
"iconUrl": "https://www.google.com/s2/favicons?sz=256&domain=https://animez.org/",
|
"iconUrl":
|
||||||
|
"https://www.google.com/s2/favicons?sz=256&domain=https://animez.org/",
|
||||||
"typeSource": "multi",
|
"typeSource": "multi",
|
||||||
"itemType": 1,
|
"itemType": 1,
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"pkgPath": "anime/src/en/animez.js"
|
"pkgPath": "anime/src/en/animez.js"
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
class DefaultExtension extends MProvider {
|
class DefaultExtension extends MProvider {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -19,7 +22,7 @@ class DefaultExtension extends MProvider {
|
|||||||
getHeaders(url) {
|
getHeaders(url) {
|
||||||
return {
|
return {
|
||||||
"Referer": this.source.baseUrl,
|
"Referer": this.source.baseUrl,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getPreference(key) {
|
getPreference(key) {
|
||||||
@@ -27,161 +30,168 @@ class DefaultExtension extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async request(slug) {
|
async request(slug) {
|
||||||
var url = this.source.baseUrl + slug
|
var url = this.source.baseUrl + slug;
|
||||||
var res = await this.client.get(url, this.getHeaders());
|
var res = await this.client.get(url, this.getHeaders());
|
||||||
return new Document(res.body);
|
return new Document(res.body);
|
||||||
}
|
}
|
||||||
async page(slug) {
|
async page(slug) {
|
||||||
var body = await this.request(slug)
|
var body = await this.request(slug);
|
||||||
var list = []
|
var list = [];
|
||||||
var hasNextPage = false;
|
var hasNextPage = false;
|
||||||
|
|
||||||
var animes = body.select("li.TPostMv")
|
var animes = body.select("li.TPostMv");
|
||||||
animes.forEach(anime => {
|
animes.forEach((anime) => {
|
||||||
var link = anime.selectFirst("a").getHref
|
var link = anime.selectFirst("a").getHref;
|
||||||
var name = anime.selectFirst('h2.Title').text;
|
var name = anime.selectFirst("h2.Title").text;
|
||||||
var imageUrl = this.source.baseUrl +"/"+ anime.selectFirst('img').getSrc;
|
var imageUrl =
|
||||||
|
this.source.baseUrl + "/" + anime.selectFirst("img").getSrc;
|
||||||
|
|
||||||
list.push({ name, link, imageUrl });
|
list.push({ name, link, imageUrl });
|
||||||
});
|
});
|
||||||
|
|
||||||
var paginations = body.select(".pagination > li")
|
var paginations = body.select(".pagination > li");
|
||||||
hasNextPage = paginations[paginations.length - 1].text == "Last" ? true : false
|
hasNextPage =
|
||||||
|
paginations[paginations.length - 1].text == "Last" ? true : false;
|
||||||
|
|
||||||
return { list, hasNextPage }
|
return { list, hasNextPage };
|
||||||
}
|
}
|
||||||
|
|
||||||
sortByPref(key) {
|
sortByPref(key) {
|
||||||
var sort = parseInt(this.getPreference(key))
|
var sort = parseInt(this.getPreference(key));
|
||||||
var sortBy = "hot"
|
var sortBy = "hot";
|
||||||
switch (sort) {
|
switch (sort) {
|
||||||
case 1: {
|
case 1: {
|
||||||
sortBy = "lastest-chap"
|
sortBy = "lastest-chap";
|
||||||
break;
|
break;
|
||||||
} case 2: {
|
}
|
||||||
sortBy = "hot"
|
case 2: {
|
||||||
|
sortBy = "hot";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: {
|
case 3: {
|
||||||
sortBy = "lastest-manga"
|
sortBy = "lastest-manga";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: {
|
case 4: {
|
||||||
sortBy = "top-manga"
|
sortBy = "top-manga";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 5: {
|
case 5: {
|
||||||
sortBy = "top-month"
|
sortBy = "top-month";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 6: {
|
case 6: {
|
||||||
sortBy = "top-week"
|
sortBy = "top-week";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 7: {
|
case 7: {
|
||||||
sortBy = "top-day"
|
sortBy = "top-day";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 8: {
|
case 8: {
|
||||||
sortBy = "follow"
|
sortBy = "follow";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 9: {
|
case 9: {
|
||||||
sortBy = "comment"
|
sortBy = "comment";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 10: {
|
case 10: {
|
||||||
sortBy = "num-chap"
|
sortBy = "num-chap";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sortBy;
|
return sortBy;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPopular(page) {
|
async getPopular(page) {
|
||||||
var sortBy = this.sortByPref("animez_pref_popular_section")
|
var sortBy = this.sortByPref("animez_pref_popular_section");
|
||||||
var slug = `/?act=search&f[status]=all&f[sortby]=${sortBy}&&pageNum=${page}`
|
var slug = `/?act=search&f[status]=all&f[sortby]=${sortBy}&&pageNum=${page}`;
|
||||||
return await this.page(slug)
|
return await this.page(slug);
|
||||||
|
|
||||||
}
|
}
|
||||||
get supportsLatest() {
|
get supportsLatest() {
|
||||||
throw new Error("supportsLatest not implemented");
|
throw new Error("supportsLatest not implemented");
|
||||||
}
|
}
|
||||||
async getLatestUpdates(page) {
|
async getLatestUpdates(page) {
|
||||||
var sortBy = this.sortByPref("animez_pref_latest_section")
|
var sortBy = this.sortByPref("animez_pref_latest_section");
|
||||||
var slug = `/?act=search&f[status]=all&f[sortby]=${sortBy}&&pageNum=${page}`
|
var slug = `/?act=search&f[status]=all&f[sortby]=${sortBy}&&pageNum=${page}`;
|
||||||
return await this.page(slug)
|
return await this.page(slug);
|
||||||
}
|
}
|
||||||
async search(query, page, filters) {
|
async search(query, page, filters) {
|
||||||
var slug = `/?act=search&f[status]=all&f[keyword]=${query}&&pageNum=${page}`
|
var slug = `/?act=search&f[status]=all&f[keyword]=${query}&&pageNum=${page}`;
|
||||||
return await this.page(slug)
|
return await this.page(slug);
|
||||||
}
|
}
|
||||||
async getDetail(url) {
|
async getDetail(url) {
|
||||||
var link = this.source.baseUrl + url;
|
var baseUrl = this.source.baseUrl;
|
||||||
|
if (url.includes(baseUrl)) url = url.replace(baseUrl, "");
|
||||||
|
var link = +url;
|
||||||
var body = await this.request(url);
|
var body = await this.request(url);
|
||||||
var name = body.selectFirst("#title-detail-manga").text
|
var name = body.selectFirst("#title-detail-manga").text;
|
||||||
var animeId = body.selectFirst("#title-detail-manga").attr("data-manga")
|
var animeId = body.selectFirst("#title-detail-manga").attr("data-manga");
|
||||||
var genre = []
|
var genre = [];
|
||||||
body.select("li.AAIco-adjust")[3].select("a").forEach(g => genre.push(g.text))
|
body
|
||||||
var description = body.selectFirst("#summary_shortened").text
|
.select("li.AAIco-adjust")[3]
|
||||||
|
.select("a")
|
||||||
|
.forEach((g) => genre.push(g.text));
|
||||||
|
var description = body.selectFirst("#summary_shortened").text;
|
||||||
|
|
||||||
|
var chapters = [];
|
||||||
var chapters = []
|
var chapLen = 0;
|
||||||
var chapLen = 0
|
var pageNum = 1;
|
||||||
var pageNum = 1
|
|
||||||
var hasNextPage = true;
|
var hasNextPage = true;
|
||||||
while(hasNextPage) {
|
while (hasNextPage) {
|
||||||
var pageSlug = `?act=ajax&code=load_list_chapter&manga_id=${animeId}&page_num=${pageNum}&chap_id=0&keyword=`
|
var pageSlug = `?act=ajax&code=load_list_chapter&manga_id=${animeId}&page_num=${pageNum}&chap_id=0&keyword=`;
|
||||||
var pageBody = await this.request(pageSlug);
|
var pageBody = await this.request(pageSlug);
|
||||||
var parsedBody = JSON.parse(pageBody.html);
|
var parsedBody = JSON.parse(pageBody.html);
|
||||||
var nav = parsedBody.nav
|
var nav = parsedBody.nav;
|
||||||
if(nav==null){ // if "nav" doesnt exists there is no next page
|
if (nav == null) {
|
||||||
|
// if "nav" doesnt exists there is no next page
|
||||||
hasNextPage = false;
|
hasNextPage = false;
|
||||||
|
} else {
|
||||||
}else{
|
var navLi = new Document(nav).select(".page-link.next").length;
|
||||||
var navLi = new Document(nav).select(".page-link.next").length
|
if (navLi > 0) {
|
||||||
if(navLi>0){ // if "nav" exists and has li.next then there is next page
|
// if "nav" exists and has li.next then there is next page
|
||||||
pageNum++;
|
pageNum++;
|
||||||
}else{// if "nav" exists and doesn't have li.next then there is no next page
|
} else {
|
||||||
|
// if "nav" exists and doesn't have li.next then there is no next page
|
||||||
hasNextPage = false;
|
hasNextPage = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var list_chap = new Document(parsedBody.list_chap).select(
|
||||||
|
"li.wp-manga-chapter"
|
||||||
|
);
|
||||||
|
|
||||||
var list_chap = new Document(parsedBody.list_chap).select('li.wp-manga-chapter')
|
list_chap.forEach((chapter) => {
|
||||||
|
var a = chapter.selectFirst("a");
|
||||||
list_chap.forEach(chapter => {
|
var title = a.text;
|
||||||
var a = chapter.selectFirst("a")
|
var epLink = a.getHref;
|
||||||
var title = a.text
|
var scanlator = "Sub";
|
||||||
var epLink = a.getHref
|
if (title.indexOf("Dub") > 0) {
|
||||||
var scanlator = "Sub"
|
title = title.replace("-Dub", "");
|
||||||
if(title.indexOf("Dub")>0){
|
scanlator = "Dub";
|
||||||
title = title.replace("-Dub","")
|
|
||||||
scanlator = "Dub"
|
|
||||||
|
|
||||||
}
|
}
|
||||||
title = title.indexOf("Movie") > -1? title : `Episode ${title}`
|
title = title.indexOf("Movie") > -1 ? title : `Episode ${title}`;
|
||||||
var epData = {
|
var epData = {
|
||||||
name:title,
|
name: title,
|
||||||
url:epLink,
|
url: epLink,
|
||||||
scanlator
|
scanlator,
|
||||||
}
|
};
|
||||||
if(chapLen>0){
|
if (chapLen > 0) {
|
||||||
var pos = chapLen -1
|
var pos = chapLen - 1;
|
||||||
var lastEntry = chapters[pos]
|
var lastEntry = chapters[pos];
|
||||||
if(lastEntry.name == epData.name){ // if last entries name is same then append url and scanlator to last entry
|
if (lastEntry.name == epData.name) {
|
||||||
chapters.pop() // remove the last entry
|
// if last entries name is same then append url and scanlator to last entry
|
||||||
epData.url = `${epData.url}||${lastEntry.url}`
|
chapters.pop(); // remove the last entry
|
||||||
epData.scanlator = `${lastEntry.scanlator}, ${epData.scanlator}`
|
epData.url = `${epData.url}||${lastEntry.url}`;
|
||||||
|
epData.scanlator = `${lastEntry.scanlator}, ${epData.scanlator}`;
|
||||||
chapLen = pos; // since the last entry is removed the chapLen will decrease
|
chapLen = pos; // since the last entry is removed the chapLen will decrease
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chapters.push(epData)
|
chapters.push(epData);
|
||||||
chapLen++;
|
chapLen++;
|
||||||
})
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -196,7 +206,7 @@ class DefaultExtension extends MProvider {
|
|||||||
sortStreams(streams) {
|
sortStreams(streams) {
|
||||||
var sortedStreams = [];
|
var sortedStreams = [];
|
||||||
|
|
||||||
var copyStreams = streams.slice()
|
var copyStreams = streams.slice();
|
||||||
var pref = this.getPreference("animez_pref_stream_audio");
|
var pref = this.getPreference("animez_pref_stream_audio");
|
||||||
for (var stream of streams) {
|
for (var stream of streams) {
|
||||||
if (stream.quality.indexOf(pref) > -1) {
|
if (stream.quality.indexOf(pref) > -1) {
|
||||||
@@ -208,60 +218,83 @@ class DefaultExtension extends MProvider {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [...sortedStreams, ...copyStreams]
|
return [...sortedStreams, ...copyStreams];
|
||||||
}
|
}
|
||||||
|
|
||||||
// For anime episode video list
|
// For anime episode video list
|
||||||
async getVideoList(url) {
|
async getVideoList(url) {
|
||||||
var linkSlugs = url.split("||")
|
var linkSlugs = url.split("||");
|
||||||
var streams = [];
|
var streams = [];
|
||||||
for(var slug of linkSlugs){
|
for (var slug of linkSlugs) {
|
||||||
var body = await this.request(slug)
|
var body = await this.request(slug);
|
||||||
var iframeSrc = body.selectFirst("iframe").getSrc
|
var iframeSrc = body.selectFirst("iframe").getSrc;
|
||||||
var streamLink = iframeSrc.replace("/embed/","/anime/")
|
var streamLink = iframeSrc.replace("/embed/", "/anime/");
|
||||||
var audio = slug.indexOf("dub-") > -1 ? "Dub" : "Sub"
|
var audio = slug.indexOf("dub-") > -1 ? "Dub" : "Sub";
|
||||||
|
|
||||||
streams.push({
|
streams.push({
|
||||||
url: streamLink,
|
url: streamLink,
|
||||||
originalUrl: streamLink,
|
originalUrl: streamLink,
|
||||||
quality: audio,
|
quality: audio,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return sortStreams(streams);
|
return sortStreams(streams);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getSourcePreferences() {
|
getSourcePreferences() {
|
||||||
return [{
|
return [
|
||||||
key: 'animez_pref_popular_section',
|
{
|
||||||
|
key: "animez_pref_popular_section",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred popular content',
|
title: "Preferred popular content",
|
||||||
summary: '',
|
summary: "",
|
||||||
valueIndex: 1,
|
valueIndex: 1,
|
||||||
entries: ["Latest update", "Hot", "New releases", "Top all", "Top month", "Top week", "Top day", "Top follow", "Top comments", "Number of episodes"],
|
entries: [
|
||||||
entryValues: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
|
"Latest update",
|
||||||
}
|
"Hot",
|
||||||
}, {
|
"New releases",
|
||||||
key: 'animez_pref_latest_section',
|
"Top all",
|
||||||
|
"Top month",
|
||||||
|
"Top week",
|
||||||
|
"Top day",
|
||||||
|
"Top follow",
|
||||||
|
"Top comments",
|
||||||
|
"Number of episodes",
|
||||||
|
],
|
||||||
|
entryValues: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "animez_pref_latest_section",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred latest content',
|
title: "Preferred latest content",
|
||||||
summary: '',
|
summary: "",
|
||||||
valueIndex: 0,
|
valueIndex: 0,
|
||||||
entries: ["Latest update", "Hot", "New releases", "Top all", "Top month", "Top week", "Top day", "Top follow", "Top comments", "Number of episodes"],
|
entries: [
|
||||||
entryValues: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
|
"Latest update",
|
||||||
}
|
"Hot",
|
||||||
}, {
|
"New releases",
|
||||||
key: 'animez_pref_stream_audio',
|
"Top all",
|
||||||
|
"Top month",
|
||||||
|
"Top week",
|
||||||
|
"Top day",
|
||||||
|
"Top follow",
|
||||||
|
"Top comments",
|
||||||
|
"Number of episodes",
|
||||||
|
],
|
||||||
|
entryValues: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "animez_pref_stream_audio",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred stream audio',
|
title: "Preferred stream audio",
|
||||||
summary: '',
|
summary: "",
|
||||||
valueIndex: 0,
|
valueIndex: 0,
|
||||||
entries: ["Sub","Dub"],
|
entries: ["Sub", "Dub"],
|
||||||
entryValues: ["Sub","Dub"],
|
entryValues: ["Sub", "Dub"],
|
||||||
}
|
},
|
||||||
},]
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const mangayomiSources = [{
|
|||||||
"iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://gojo.wtf/",
|
"iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://gojo.wtf/",
|
||||||
"typeSource": "multi",
|
"typeSource": "multi",
|
||||||
"itemType": 1,
|
"itemType": 1,
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"pkgPath": "anime/src/en/gojo.js"
|
"pkgPath": "anime/src/en/gojo.js"
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@@ -103,6 +103,9 @@ class DefaultExtension extends MProvider {
|
|||||||
|
|
||||||
|
|
||||||
async getDetail(url) {
|
async getDetail(url) {
|
||||||
|
var linkSlug = `${this.source.baseUrl}/watch/`
|
||||||
|
if (url.includes(linkSlug)) url = url.replace(linkSlug, "");
|
||||||
|
|
||||||
var anilistId = url
|
var anilistId = url
|
||||||
var res = await this.gojoAPI(`/info/${anilistId}`)
|
var res = await this.gojoAPI(`/info/${anilistId}`)
|
||||||
if (res == null) {
|
if (res == null) {
|
||||||
@@ -111,7 +114,7 @@ class DefaultExtension extends MProvider {
|
|||||||
var name = this.getTitle(res.title)
|
var name = this.getTitle(res.title)
|
||||||
var imageUrl = res.coverImage.large
|
var imageUrl = res.coverImage.large
|
||||||
var description = res.description;
|
var description = res.description;
|
||||||
var link = `${this.source.baseUrl}/watch/${anilistId}`
|
var link = `${linkSlug}${anilistId}`
|
||||||
var genres = res.genres
|
var genres = res.genres
|
||||||
var status = (() => {
|
var status = (() => {
|
||||||
switch (res.status) {
|
switch (res.status) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const mangayomiSources = [{
|
|||||||
"apiUrl": "",
|
"apiUrl": "",
|
||||||
"iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://sudatchi.com",
|
"iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://sudatchi.com",
|
||||||
"typeSource": "single",
|
"typeSource": "single",
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"dateFormat": "",
|
"dateFormat": "",
|
||||||
"dateFormatLocale": "",
|
"dateFormatLocale": "",
|
||||||
"itemType": 1,
|
"itemType": 1,
|
||||||
@@ -148,8 +148,11 @@ class DefaultExtension extends MProvider {
|
|||||||
|
|
||||||
|
|
||||||
async getDetail(url) {
|
async getDetail(url) {
|
||||||
|
var linkSlug = "https://sudatchi.com/anime/"
|
||||||
|
if (url.includes(linkSlug)) url = url.replace(linkSlug, "");
|
||||||
|
|
||||||
var lang = this.getPreference("sudatchi_pref_lang")
|
var lang = this.getPreference("sudatchi_pref_lang")
|
||||||
var link = `https://sudatchi.com/anime/${url}`
|
var link = `${linkSlug}${url}`
|
||||||
var details = await this.requestApi(`/anime/${url}`);
|
var details = await this.requestApi(`/anime/${url}`);
|
||||||
var titles = details.title
|
var titles = details.title
|
||||||
var name = titles.romaji
|
var name = titles.romaji
|
||||||
|
|||||||
@@ -1,81 +1,89 @@
|
|||||||
const mangayomiSources = [{
|
const mangayomiSources = [
|
||||||
|
{
|
||||||
"name": "Mangapill",
|
"name": "Mangapill",
|
||||||
"lang": "en",
|
"lang": "en",
|
||||||
"baseUrl": "https://mangapill.com",
|
"baseUrl": "https://mangapill.com",
|
||||||
"apiUrl": "",
|
"apiUrl": "",
|
||||||
"iconUrl": "https://www.google.com/s2/favicons?sz=64&domain=https://mangapill.com/",
|
"iconUrl":
|
||||||
|
"https://www.google.com/s2/favicons?sz=64&domain=https://mangapill.com/",
|
||||||
"typeSource": "single",
|
"typeSource": "single",
|
||||||
"isManga": true,
|
"isManga": true,
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"dateFormat": "",
|
"dateFormat": "",
|
||||||
"dateFormatLocale": "",
|
"dateFormatLocale": "",
|
||||||
"pkgPath": "manga/src/en/mangapill.js"
|
"pkgPath": "manga/src/en/mangapill.js"
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
class DefaultExtension extends MProvider {
|
class DefaultExtension extends MProvider {
|
||||||
getHeaders(url) {
|
getHeaders(url) {
|
||||||
return {
|
return {
|
||||||
"Referer": this.source.baseUrl
|
"Referer": this.source.baseUrl,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
statusCode(status) {
|
statusCode(status) {
|
||||||
return {
|
return (
|
||||||
|
{
|
||||||
"publishing": 0,
|
"publishing": 0,
|
||||||
"finished": 1,
|
"finished": 1,
|
||||||
"on hiatus": 2,
|
"on hiatus": 2,
|
||||||
"discontinued": 3,
|
"discontinued": 3,
|
||||||
"not yet published": 4,
|
"not yet published": 4,
|
||||||
}[status] ?? 5;
|
}[status] ?? 5
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPreference(key) {
|
async getPreference(key) {
|
||||||
const preferences = new SharedPreferences();
|
const preferences = new SharedPreferences();
|
||||||
return parseInt(preferences.get(key))
|
return parseInt(preferences.get(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMangaList(slug) {
|
async getMangaList(slug) {
|
||||||
var lang = await this.getPreference("pref_title_lang");
|
var lang = await this.getPreference("pref_title_lang");
|
||||||
|
|
||||||
var url = `${this.source.baseUrl}/${slug}`
|
var url = `${this.source.baseUrl}/${slug}`;
|
||||||
var res = await new Client().get(url, this.getHeaders());
|
var res = await new Client().get(url, this.getHeaders());
|
||||||
var doc = new Document(res.body);
|
var doc = new Document(res.body);
|
||||||
var list = [];
|
var list = [];
|
||||||
var mangaElements = doc.select("div.grid.gap-3.lg > div")
|
var mangaElements = doc.select("div.grid.gap-3.lg > div");
|
||||||
for (var manga of mangaElements) {
|
for (var manga of mangaElements) {
|
||||||
var details = manga.selectFirst('div').select('a');
|
var details = manga.selectFirst("div").select("a");
|
||||||
var detLen = details.length
|
var detLen = details.length;
|
||||||
details = details[detLen - 1]
|
details = details[detLen - 1];
|
||||||
|
|
||||||
var imageUrl = manga.selectFirst("img").getSrc;
|
var imageUrl = manga.selectFirst("img").getSrc;
|
||||||
var link = details.getHref;
|
var link = details.getHref;
|
||||||
var nameSection = details.select('div');
|
var nameSection = details.select("div");
|
||||||
|
|
||||||
var name = (nameSection[1] && lang == 2) ? nameSection[1].text : nameSection[0].text
|
var name =
|
||||||
|
nameSection[1] && lang == 2 ? nameSection[1].text : nameSection[0].text;
|
||||||
|
|
||||||
list.push({ name, imageUrl, link });
|
list.push({ name, imageUrl, link });
|
||||||
}
|
}
|
||||||
var hasNextPage = false;
|
var hasNextPage = false;
|
||||||
if (slug.includes("search?q")) {
|
if (slug.includes("search?q")) {
|
||||||
hasNextPage = doc.selectFirst(".container.py-3 a.btn.btn-sm").className ? true : false
|
hasNextPage = doc.selectFirst(".container.py-3 a.btn.btn-sm").className
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
}
|
}
|
||||||
return { list, hasNextPage }
|
return { list, hasNextPage };
|
||||||
}
|
}
|
||||||
|
|
||||||
async getNavPage(prefKey) {
|
async getNavPage(prefKey) {
|
||||||
var val = await this.getPreference(prefKey);
|
var val = await this.getPreference(prefKey);
|
||||||
var slug = ''
|
var slug = "";
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case 1: {
|
case 1: {
|
||||||
slug = 'mangas/new'
|
slug = "mangas/new";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2: {
|
case 2: {
|
||||||
slug = 'chapters'
|
slug = "chapters";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return await this.getMangaList(slug)
|
return await this.getMangaList(slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPopular(page) {
|
async getPopular(page) {
|
||||||
@@ -90,53 +98,68 @@ class DefaultExtension extends MProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async searchManga(query, status, type, genre, page) {
|
async searchManga(query, status, type, genre, page) {
|
||||||
var slug = `search?q=${query}&status=${status}&type=${type}${genre}&page=${page}`
|
var slug = `search?q=${query}&status=${status}&type=${type}${genre}&page=${page}`;
|
||||||
return await this.getMangaList(slug)
|
return await this.getMangaList(slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
async search(query, page, filters) {
|
async search(query, page, filters) {
|
||||||
var type = filters[0].values[filters[0].state].value
|
var type = filters[0].values[filters[0].state].value;
|
||||||
var status = filters[1].values[filters[1].state].value
|
var status = filters[1].values[filters[1].state].value;
|
||||||
|
|
||||||
var genre = ""
|
var genre = "";
|
||||||
for (var filter of filters[2].state) {
|
for (var filter of filters[2].state) {
|
||||||
if (filter.state == true)
|
if (filter.state == true) genre += `&genre=${filter.value}`;
|
||||||
genre += `&genre=${filter.value}`
|
|
||||||
}
|
}
|
||||||
return await this.searchManga(query, status, type, genre, page);
|
return await this.searchManga(query, status, type, genre, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMangaDetail(slug) {
|
async getMangaDetail(slug) {
|
||||||
var lang = await this.getPreference("pref_title_lang");
|
var lang = await this.getPreference("pref_title_lang");
|
||||||
|
var baseUrl = this.source.baseUrl;
|
||||||
|
if (slug.includes(baseUrl)) slug = slug.replace(baseUrl, "");
|
||||||
|
|
||||||
var link = `${this.source.baseUrl}${slug}`
|
var link = `${baseUrl}${slug}`;
|
||||||
var res = await new Client().get(link, this.getHeaders());
|
var res = await new Client().get(link, this.getHeaders());
|
||||||
var doc = new Document(res.body);
|
var doc = new Document(res.body);
|
||||||
|
|
||||||
var mangaName = doc.selectFirst(".mb-3 .font-bold.text-lg").text
|
var mangaName = doc.selectFirst(".mb-3 .font-bold.text-lg").text;
|
||||||
if (doc.selectFirst(".mb-3 .text-sm.text-secondary") && lang == 2) mangaName = doc.selectFirst(".mb-3 .text-sm.text-secondary").text
|
if (doc.selectFirst(".mb-3 .text-sm.text-secondary") && lang == 2)
|
||||||
var description = doc.selectFirst("meta[name='description']").attr("content")
|
mangaName = doc.selectFirst(".mb-3 .text-sm.text-secondary").text;
|
||||||
var imageUrl = doc.selectFirst(".w-full.h-full").getSrc
|
var description = doc
|
||||||
var statusText = doc.select(".grid.grid-cols-1 > div")[1].selectFirst("div").text
|
.selectFirst("meta[name='description']")
|
||||||
var status = this.statusCode(statusText)
|
.attr("content");
|
||||||
|
var imageUrl = doc.selectFirst(".w-full.h-full").getSrc;
|
||||||
|
var statusText = doc
|
||||||
|
.select(".grid.grid-cols-1 > div")[1]
|
||||||
|
.selectFirst("div").text;
|
||||||
|
var status = this.statusCode(statusText);
|
||||||
|
|
||||||
var genre = []
|
var genre = [];
|
||||||
var genreList = doc.select("a.mr-1")
|
var genreList = doc.select("a.mr-1");
|
||||||
for (var gen of genreList) { genre.push(gen.text) }
|
for (var gen of genreList) {
|
||||||
|
genre.push(gen.text);
|
||||||
var chapters = []
|
|
||||||
var chapList = doc.select("div.my-3.grid > a")
|
|
||||||
for (var chap of chapList) {
|
|
||||||
var name = chap.text
|
|
||||||
var url = chap.getHref
|
|
||||||
chapters.push({ name, url })
|
|
||||||
}
|
}
|
||||||
return { name: mangaName, description, link, imageUrl, status, genre, chapters }
|
|
||||||
|
var chapters = [];
|
||||||
|
var chapList = doc.select("div.my-3.grid > a");
|
||||||
|
for (var chap of chapList) {
|
||||||
|
var name = chap.text;
|
||||||
|
var url = chap.getHref;
|
||||||
|
chapters.push({ name, url });
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
name: mangaName,
|
||||||
|
description,
|
||||||
|
link,
|
||||||
|
imageUrl,
|
||||||
|
status,
|
||||||
|
genre,
|
||||||
|
chapters,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDetail(url) {
|
async getDetail(url) {
|
||||||
return await this.getMangaDetail(url);
|
return await this.getMangaDetail(url);
|
||||||
|
|
||||||
}
|
}
|
||||||
// For anime episode video list
|
// For anime episode video list
|
||||||
async getVideoList(url) {
|
async getVideoList(url) {
|
||||||
@@ -145,20 +168,20 @@ class DefaultExtension extends MProvider {
|
|||||||
|
|
||||||
// For manga chapter pages
|
// For manga chapter pages
|
||||||
async getPageList(url) {
|
async getPageList(url) {
|
||||||
var link = `${this.source.baseUrl}${url}`
|
var link = `${this.source.baseUrl}${url}`;
|
||||||
|
|
||||||
var res = await new Client().get(link, this.getHeaders());
|
var res = await new Client().get(link, this.getHeaders());
|
||||||
var doc = new Document(res.body);
|
var doc = new Document(res.body);
|
||||||
|
|
||||||
var urls = [];
|
var urls = [];
|
||||||
|
|
||||||
var pages = doc.select("chapter-page")
|
var pages = doc.select("chapter-page");
|
||||||
for (var page of pages) {
|
for (var page of pages) {
|
||||||
var img = page.selectFirst("img").getSrc
|
var img = page.selectFirst("img").getSrc;
|
||||||
if (img != null) urls.push(img);
|
if (img != null) urls.push(img);
|
||||||
}
|
}
|
||||||
|
|
||||||
return urls
|
return urls;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFilterList() {
|
getFilterList() {
|
||||||
@@ -175,8 +198,8 @@ class DefaultExtension extends MProvider {
|
|||||||
["Doujinshi", "doujinshi"],
|
["Doujinshi", "doujinshi"],
|
||||||
["Manhwa", "manhwa"],
|
["Manhwa", "manhwa"],
|
||||||
["Manhua", "manhua"],
|
["Manhua", "manhua"],
|
||||||
["Oel", "oel"]
|
["Oel", "oel"],
|
||||||
].map(x => ({ type_name: 'SelectOption', name: x[0], value: x[1] }))
|
].map((x) => ({ type_name: "SelectOption", name: x[0], value: x[1] })),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type_name: "SelectFilter",
|
type_name: "SelectFilter",
|
||||||
@@ -188,9 +211,10 @@ class DefaultExtension extends MProvider {
|
|||||||
["Finished", "finished"],
|
["Finished", "finished"],
|
||||||
["On hiatus", "on hiatus"],
|
["On hiatus", "on hiatus"],
|
||||||
["Discontinued", "discontinued"],
|
["Discontinued", "discontinued"],
|
||||||
["Not yet published", "not yet published"]
|
["Not yet published", "not yet published"],
|
||||||
].map(x => ({ type_name: 'SelectOption', name: x[0], value: x[1] }))
|
].map((x) => ({ type_name: "SelectOption", name: x[0], value: x[1] })),
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
type_name: "GroupFilter",
|
type_name: "GroupFilter",
|
||||||
name: "Genre",
|
name: "Genre",
|
||||||
state: [
|
state: [
|
||||||
@@ -239,42 +263,44 @@ class DefaultExtension extends MProvider {
|
|||||||
["Tragedy", "Tragedy"],
|
["Tragedy", "Tragedy"],
|
||||||
["Vampire", "Vampire"],
|
["Vampire", "Vampire"],
|
||||||
["Yaoi", "Yaoi"],
|
["Yaoi", "Yaoi"],
|
||||||
["Yuri", "Yuri"]
|
["Yuri", "Yuri"],
|
||||||
].map(x => ({ type_name: 'CheckBox', name: x[0], value: x[1] }))
|
].map((x) => ({ type_name: "CheckBox", name: x[0], value: x[1] })),
|
||||||
}
|
},
|
||||||
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
getSourcePreferences() {
|
getSourcePreferences() {
|
||||||
return [{
|
return [
|
||||||
key: 'pref_popular_content',
|
{
|
||||||
|
key: "pref_popular_content",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred popular content',
|
title: "Preferred popular content",
|
||||||
summary: '',
|
summary: "",
|
||||||
valueIndex: 0,
|
valueIndex: 0,
|
||||||
entries: ["New Mangas", "Recent Chapters"],
|
entries: ["New Mangas", "Recent Chapters"],
|
||||||
entryValues: ["1", "2"]
|
entryValues: ["1", "2"],
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
key: 'pref_latest_content',
|
{
|
||||||
|
key: "pref_latest_content",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred latest content',
|
title: "Preferred latest content",
|
||||||
summary: '',
|
summary: "",
|
||||||
valueIndex: 1,
|
valueIndex: 1,
|
||||||
entries: ["New Mangas", "Recent Chapters"],
|
entries: ["New Mangas", "Recent Chapters"],
|
||||||
entryValues: ["1", "2"]
|
entryValues: ["1", "2"],
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
key: 'pref_title_lang',
|
{
|
||||||
|
key: "pref_title_lang",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred title language',
|
title: "Preferred title language",
|
||||||
summary: '',
|
summary: "",
|
||||||
valueIndex: 0,
|
valueIndex: 0,
|
||||||
entries: ["Romaji", "English"],
|
entries: ["Romaji", "English"],
|
||||||
entryValues: ["1", "2"]
|
entryValues: ["1", "2"],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
const mangayomiSources = [{
|
const mangayomiSources = [
|
||||||
|
{
|
||||||
"name": "ReadComicOnline",
|
"name": "ReadComicOnline",
|
||||||
"lang": "en",
|
"lang": "en",
|
||||||
"baseUrl": "https://readcomiconline.li",
|
"baseUrl": "https://readcomiconline.li",
|
||||||
"apiUrl": "",
|
"apiUrl": "",
|
||||||
"iconUrl": "https://www.google.com/s2/favicons?sz=256&domain=https://readcomiconline.li/",
|
"iconUrl":
|
||||||
|
"https://www.google.com/s2/favicons?sz=256&domain=https://readcomiconline.li/",
|
||||||
"typeSource": "single",
|
"typeSource": "single",
|
||||||
"itemType": 0,
|
"itemType": 0,
|
||||||
"version": "0.1.2",
|
"version": "0.1.3",
|
||||||
"pkgPath": "manga/src/en/readcomiconline.js"
|
"pkgPath": "manga/src/en/readcomiconline.js"
|
||||||
}];
|
}
|
||||||
|
];
|
||||||
|
|
||||||
class DefaultExtension extends MProvider {
|
class DefaultExtension extends MProvider {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -22,165 +25,192 @@ class DefaultExtension extends MProvider {
|
|||||||
|
|
||||||
getHeaders() {
|
getHeaders() {
|
||||||
return {
|
return {
|
||||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6832.64 Safari/537.36",
|
"User-Agent":
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6832.64 Safari/537.36",
|
||||||
"Referer": this.source.baseUrl,
|
"Referer": this.source.baseUrl,
|
||||||
"Origin": this.source.baseUrl,
|
"Origin": this.source.baseUrl,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async request(slug) {
|
async request(slug) {
|
||||||
var url = slug
|
var url = slug;
|
||||||
var baseUrl = this.source.baseUrl
|
var baseUrl = this.source.baseUrl;
|
||||||
if (!slug.includes(baseUrl)) url = baseUrl + slug;
|
if (!slug.includes(baseUrl)) url = baseUrl + slug;
|
||||||
var res = await this.client.get(url, this.getHeaders());
|
var res = await this.client.get(url, this.getHeaders());
|
||||||
return new Document(res.body);
|
return new Document(res.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getListPage(slug, page) {
|
async getListPage(slug, page) {
|
||||||
var url = `${slug}page=${page}`
|
var url = `${slug}page=${page}`;
|
||||||
var doc = await this.request(url);
|
var doc = await this.request(url);
|
||||||
var baseUrl = this.source.baseUrl
|
var baseUrl = this.source.baseUrl;
|
||||||
var list = []
|
var list = [];
|
||||||
|
|
||||||
var comicList = doc.select(".list-comic > .item")
|
var comicList = doc.select(".list-comic > .item");
|
||||||
comicList.forEach(item => {
|
comicList.forEach((item) => {
|
||||||
var name = item.selectFirst(".title").text;
|
var name = item.selectFirst(".title").text;
|
||||||
var link = item.selectFirst("a").getHref
|
var link = item.selectFirst("a").getHref;
|
||||||
var imageSlug = item.selectFirst("img").getSrc
|
var imageSlug = item.selectFirst("img").getSrc;
|
||||||
var imageUrl = imageSlug.includes("http") ? imageSlug : `${baseUrl}${imageSlug}`;
|
var imageUrl = imageSlug.includes("http")
|
||||||
|
? imageSlug
|
||||||
|
: `${baseUrl}${imageSlug}`;
|
||||||
list.push({ name, link, imageUrl });
|
list.push({ name, link, imageUrl });
|
||||||
});
|
});
|
||||||
|
|
||||||
var pager = doc.select("ul.pager > li")
|
var pager = doc.select("ul.pager > li");
|
||||||
|
|
||||||
var hasNextPage = false
|
var hasNextPage = false;
|
||||||
if (pager.length > 0) hasNextPage = pager[pager.length - 1].text.includes("Last") ? true : false;
|
if (pager.length > 0)
|
||||||
|
hasNextPage = pager[pager.length - 1].text.includes("Last")
|
||||||
return { list, hasNextPage }
|
? true
|
||||||
|
: false;
|
||||||
|
|
||||||
|
return { list, hasNextPage };
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPopular(page) {
|
async getPopular(page) {
|
||||||
return await this.getListPage("/ComicList/MostPopular?", page)
|
return await this.getListPage("/ComicList/MostPopular?", page);
|
||||||
}
|
}
|
||||||
get supportsLatest() {
|
get supportsLatest() {
|
||||||
throw new Error("supportsLatest not implemented");
|
throw new Error("supportsLatest not implemented");
|
||||||
}
|
}
|
||||||
async getLatestUpdates(page) {
|
async getLatestUpdates(page) {
|
||||||
return await this.getListPage("/ComicList/LatestUpdate?", page)
|
return await this.getListPage("/ComicList/LatestUpdate?", page);
|
||||||
}
|
}
|
||||||
async search(query, page, filters) {
|
async search(query, page, filters) {
|
||||||
function getFilter(state) {
|
function getFilter(state) {
|
||||||
var rd = ""
|
var rd = "";
|
||||||
state.forEach(item => {
|
state.forEach((item) => {
|
||||||
if (item.state) {
|
if (item.state) {
|
||||||
rd += `${item.value},`
|
rd += `${item.value},`;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
return rd.slice(0, -1)
|
return rd.slice(0, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
var isFiltersAvailable = !filters || filters.length != 0
|
var isFiltersAvailable = !filters || filters.length != 0;
|
||||||
var genre = isFiltersAvailable ? getFilter(filters[0].state): []
|
var genre = isFiltersAvailable ? getFilter(filters[0].state) : [];
|
||||||
var status = isFiltersAvailable ? filters[1].values[filters[1].state].value: ""
|
var status = isFiltersAvailable
|
||||||
var year = isFiltersAvailable ? filters[2].values[filters[2].state].value: ""
|
? filters[1].values[filters[1].state].value
|
||||||
|
: "";
|
||||||
|
var year = isFiltersAvailable
|
||||||
|
? filters[2].values[filters[2].state].value
|
||||||
|
: "";
|
||||||
|
|
||||||
|
var slug = `/AdvanceSearch?comicName=${query}&ig=${encodeURIComponent(
|
||||||
|
genre
|
||||||
|
)}&status=${status}&pubDate=${year}&`;
|
||||||
|
|
||||||
var slug = `/AdvanceSearch?comicName=${query}&ig=${encodeURIComponent(genre)}&status=${status}&pubDate=${year}&`
|
return await this.getListPage(slug, page);
|
||||||
|
|
||||||
return await this.getListPage(slug, page)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDetail(url) {
|
async getDetail(url) {
|
||||||
function statusCode(status) {
|
function statusCode(status) {
|
||||||
return {
|
return (
|
||||||
|
{
|
||||||
"Ongoing": 0,
|
"Ongoing": 0,
|
||||||
"Completed": 1,
|
"Completed": 1,
|
||||||
}[status] ?? 5;
|
}[status] ?? 5
|
||||||
|
);
|
||||||
}
|
}
|
||||||
var link = this.source.baseUrl + url
|
|
||||||
var doc = await this.request(url)
|
|
||||||
|
|
||||||
var detailsSection = doc.selectFirst(".barContent")
|
var baseUrl = this.source.baseUrl;
|
||||||
var name = detailsSection.selectFirst("a").text
|
if (url.includes(baseUrl)) url = url.replace(baseUrl, "");
|
||||||
var imageSlug = doc.selectFirst(".rightBox").selectFirst("img").getSrc
|
|
||||||
var imageUrl = imageSlug.includes("http") ? imageSlug : `${this.source.baseUrl}${imageSlug}`;
|
|
||||||
var pTag = detailsSection.select("p")
|
|
||||||
|
|
||||||
var description = pTag[pTag.length - 2].text
|
var doc = await this.request(url);
|
||||||
|
|
||||||
var status = 5
|
var detailsSection = doc.selectFirst(".barContent");
|
||||||
var genre = []
|
var name = detailsSection.selectFirst("a").text;
|
||||||
var author = ""
|
var imageSlug = doc.selectFirst(".rightBox").selectFirst("img").getSrc;
|
||||||
var artist = ""
|
var imageUrl = imageSlug.includes("http")
|
||||||
|
? imageSlug
|
||||||
|
: `${this.source.baseUrl}${imageSlug}`;
|
||||||
|
var pTag = detailsSection.select("p");
|
||||||
|
|
||||||
pTag.forEach(p => {
|
var description = pTag[pTag.length - 2].text;
|
||||||
var itemText = p.text.trim()
|
|
||||||
|
var status = 5;
|
||||||
|
var genre = [];
|
||||||
|
var author = "";
|
||||||
|
var artist = "";
|
||||||
|
|
||||||
|
pTag.forEach((p) => {
|
||||||
|
var itemText = p.text.trim();
|
||||||
|
|
||||||
if (itemText.includes("Genres")) {
|
if (itemText.includes("Genres")) {
|
||||||
genre = itemText.replace("Genres:", "").trim().split(", ")
|
genre = itemText.replace("Genres:", "").trim().split(", ");
|
||||||
} else if (itemText.includes("Status")) {
|
} else if (itemText.includes("Status")) {
|
||||||
var sts = itemText.replace("Status: ", "").trim().split("\n")[0]
|
var sts = itemText.replace("Status: ", "").trim().split("\n")[0];
|
||||||
status = statusCode(sts)
|
status = statusCode(sts);
|
||||||
} else if (itemText.includes("Writer")) {
|
} else if (itemText.includes("Writer")) {
|
||||||
author = itemText.replace("Writer: ", "")
|
author = itemText.replace("Writer: ", "");
|
||||||
} else if (itemText.includes("Artist")) {
|
} else if (itemText.includes("Artist")) {
|
||||||
artist = itemText.replace("Artist: ", "")
|
artist = itemText.replace("Artist: ", "");
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
var chapters = [];
|
||||||
|
var tr = doc.selectFirst("table").select("tr");
|
||||||
|
tr.splice(0, 2); // 1st item in the table is headers & 2nd item is a line break
|
||||||
|
tr.forEach((item) => {
|
||||||
|
var tds = item.select("td");
|
||||||
|
var aTag = tds[0].selectFirst("a");
|
||||||
|
var chapLink = aTag.getHref;
|
||||||
|
|
||||||
})
|
var chapTitle = aTag.text.trim().replace(`${name} `, "");
|
||||||
var chapters = []
|
chapTitle = chapTitle[0] == "_" ? chapTitle.substring(1) : chapTitle;
|
||||||
var tr = doc.selectFirst("table").select("tr")
|
|
||||||
tr.splice(0, 2) // 1st item in the table is headers & 2nd item is a line break
|
|
||||||
tr.forEach(item => {
|
|
||||||
var tds = item.select("td")
|
|
||||||
var aTag = tds[0].selectFirst("a")
|
|
||||||
var chapLink = aTag.getHref
|
|
||||||
|
|
||||||
var chapTitle = aTag.text.trim().replace(`${name} `, "")
|
var uploadDate = tds[1].text.trim();
|
||||||
chapTitle = chapTitle[0] == "_" ? chapTitle.substring(1,) : chapTitle
|
|
||||||
|
|
||||||
var uploadDate = tds[1].text.trim()
|
|
||||||
var date = new Date(uploadDate);
|
var date = new Date(uploadDate);
|
||||||
var dateUpload = date.getTime().toString();
|
var dateUpload = date.getTime().toString();
|
||||||
|
|
||||||
|
chapters.push({ url: chapLink, name: chapTitle, dateUpload });
|
||||||
|
});
|
||||||
|
var link = baseUrl + url;
|
||||||
|
|
||||||
chapters.push({ url: chapLink, name: chapTitle, dateUpload })
|
return {
|
||||||
|
name,
|
||||||
})
|
link,
|
||||||
|
imageUrl,
|
||||||
return { name, link, imageUrl, description, genre, status, author, artist, chapters }
|
description,
|
||||||
|
genre,
|
||||||
|
status,
|
||||||
|
author,
|
||||||
|
artist,
|
||||||
|
chapters,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// For manga chapter pages
|
// For manga chapter pages
|
||||||
async getPageList(url) {
|
async getPageList(url) {
|
||||||
var pages = [];
|
var pages = [];
|
||||||
var hdr = this.getHeaders()
|
var hdr = this.getHeaders();
|
||||||
let match;
|
let match;
|
||||||
var imageQuality = this.getPreference("readcomiconline_page_quality");
|
var imageQuality = this.getPreference("readcomiconline_page_quality");
|
||||||
|
|
||||||
var doc = await this.request(url)
|
var doc = await this.request(url);
|
||||||
var html = doc.html
|
var html = doc.html;
|
||||||
|
|
||||||
// Find host url for images
|
// Find host url for images
|
||||||
var baseUrlOverride = ""
|
var baseUrlOverride = "";
|
||||||
const hostRegex = /return\s+baeu\s*\(\s*l\s*,\s*'([^']+?)'\s*\);?/g;
|
const hostRegex = /return\s+baeu\s*\(\s*l\s*,\s*'([^']+?)'\s*\);?/g;
|
||||||
match = hostRegex.exec(html)
|
match = hostRegex.exec(html);
|
||||||
if (match.length > 0) {
|
if (match.length > 0) {
|
||||||
baseUrlOverride = match[1]
|
baseUrlOverride = match[1];
|
||||||
if (baseUrlOverride.slice(-1) != "/") baseUrlOverride += "/"
|
if (baseUrlOverride.slice(-1) != "/") baseUrlOverride += "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const pageRegex = /pht\s*=\s*'([^']+?)';?/g;
|
const pageRegex = /pht\s*=\s*'([^']+?)';?/g;
|
||||||
while ((match = pageRegex.exec(html)) !== null) {
|
while ((match = pageRegex.exec(html)) !== null) {
|
||||||
var encodedImageUrl = match[1]
|
var encodedImageUrl = match[1];
|
||||||
var decodedImageUrl = this.decodeImageUrl(encodedImageUrl, imageQuality, baseUrlOverride)
|
var decodedImageUrl = this.decodeImageUrl(
|
||||||
|
encodedImageUrl,
|
||||||
|
imageQuality,
|
||||||
|
baseUrlOverride
|
||||||
|
);
|
||||||
pages.push({
|
pages.push({
|
||||||
url: decodedImageUrl,
|
url: decodedImageUrl,
|
||||||
headers: hdr,
|
headers: hdr,
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
return pages;
|
return pages;
|
||||||
}
|
}
|
||||||
@@ -188,7 +218,7 @@ class DefaultExtension extends MProvider {
|
|||||||
function formateState(type_name, items, values) {
|
function formateState(type_name, items, values) {
|
||||||
var state = [];
|
var state = [];
|
||||||
for (var i = 0; i < items.length; i++) {
|
for (var i = 0; i < items.length; i++) {
|
||||||
state.push({ type_name: type_name, name: items[i], value: values[i] })
|
state.push({ type_name: type_name, name: items[i], value: values[i] });
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@@ -197,29 +227,115 @@ class DefaultExtension extends MProvider {
|
|||||||
|
|
||||||
// Genre
|
// Genre
|
||||||
var items = [
|
var items = [
|
||||||
"Action", "Adventure", "Anthology", "Anthropomorphic", "Biography", "Children", "Comedy",
|
"Action",
|
||||||
"Crime", "Drama", "Family", "Fantasy", "Fighting", "Graphic Novels", "Historical", "Horror",
|
"Adventure",
|
||||||
"Leading Ladies", "LGBTQ", "Literature", "Manga", "Martial Arts", "Mature", "Military",
|
"Anthology",
|
||||||
"Mini-Series", "Movies & TV", "Music", "Mystery", "Mythology", "Personal", "Political",
|
"Anthropomorphic",
|
||||||
"Post-Apocalyptic", "Psychological", "Pulp", "Religious", "Robots", "Romance", "School Life",
|
"Biography",
|
||||||
"Sci-Fi", "Slice of Life", "Sport", "Spy", "Superhero", "Supernatural", "Suspense", "Teen",
|
"Children",
|
||||||
"Thriller", "Vampires", "Video Games", "War", "Western", "Zombies"
|
"Comedy",
|
||||||
|
"Crime",
|
||||||
|
"Drama",
|
||||||
|
"Family",
|
||||||
|
"Fantasy",
|
||||||
|
"Fighting",
|
||||||
|
"Graphic Novels",
|
||||||
|
"Historical",
|
||||||
|
"Horror",
|
||||||
|
"Leading Ladies",
|
||||||
|
"LGBTQ",
|
||||||
|
"Literature",
|
||||||
|
"Manga",
|
||||||
|
"Martial Arts",
|
||||||
|
"Mature",
|
||||||
|
"Military",
|
||||||
|
"Mini-Series",
|
||||||
|
"Movies & TV",
|
||||||
|
"Music",
|
||||||
|
"Mystery",
|
||||||
|
"Mythology",
|
||||||
|
"Personal",
|
||||||
|
"Political",
|
||||||
|
"Post-Apocalyptic",
|
||||||
|
"Psychological",
|
||||||
|
"Pulp",
|
||||||
|
"Religious",
|
||||||
|
"Robots",
|
||||||
|
"Romance",
|
||||||
|
"School Life",
|
||||||
|
"Sci-Fi",
|
||||||
|
"Slice of Life",
|
||||||
|
"Sport",
|
||||||
|
"Spy",
|
||||||
|
"Superhero",
|
||||||
|
"Supernatural",
|
||||||
|
"Suspense",
|
||||||
|
"Teen",
|
||||||
|
"Thriller",
|
||||||
|
"Vampires",
|
||||||
|
"Video Games",
|
||||||
|
"War",
|
||||||
|
"Western",
|
||||||
|
"Zombies",
|
||||||
];
|
];
|
||||||
|
|
||||||
var values = [
|
var values = [
|
||||||
"1", "2", "38", "46", "41", "49", "3",
|
"1",
|
||||||
"17", "19", "25", "20", "31", "5", "28", "15",
|
"2",
|
||||||
"35", "51", "44", "40", "4", "8", "33",
|
"38",
|
||||||
"56", "47", "55", "23", "21", "48", "42",
|
"46",
|
||||||
"43", "27", "39", "53", "9", "32", "52",
|
"41",
|
||||||
"16", "50", "54", "30", "22", "24", "29", "57",
|
"49",
|
||||||
"18", "34", "37", "26", "45", "36"
|
"3",
|
||||||
|
"17",
|
||||||
|
"19",
|
||||||
|
"25",
|
||||||
|
"20",
|
||||||
|
"31",
|
||||||
|
"5",
|
||||||
|
"28",
|
||||||
|
"15",
|
||||||
|
"35",
|
||||||
|
"51",
|
||||||
|
"44",
|
||||||
|
"40",
|
||||||
|
"4",
|
||||||
|
"8",
|
||||||
|
"33",
|
||||||
|
"56",
|
||||||
|
"47",
|
||||||
|
"55",
|
||||||
|
"23",
|
||||||
|
"21",
|
||||||
|
"48",
|
||||||
|
"42",
|
||||||
|
"43",
|
||||||
|
"27",
|
||||||
|
"39",
|
||||||
|
"53",
|
||||||
|
"9",
|
||||||
|
"32",
|
||||||
|
"52",
|
||||||
|
"16",
|
||||||
|
"50",
|
||||||
|
"54",
|
||||||
|
"30",
|
||||||
|
"22",
|
||||||
|
"24",
|
||||||
|
"29",
|
||||||
|
"57",
|
||||||
|
"18",
|
||||||
|
"34",
|
||||||
|
"37",
|
||||||
|
"26",
|
||||||
|
"45",
|
||||||
|
"36",
|
||||||
];
|
];
|
||||||
filters.push({
|
filters.push({
|
||||||
type_name: "GroupFilter",
|
type_name: "GroupFilter",
|
||||||
name: "Genres",
|
name: "Genres",
|
||||||
state: formateState("CheckBox", items, values)
|
state: formateState("CheckBox", items, values),
|
||||||
})
|
});
|
||||||
|
|
||||||
// Status
|
// Status
|
||||||
items = ["Any", "Ongoing", "Completed"];
|
items = ["Any", "Ongoing", "Completed"];
|
||||||
@@ -228,20 +344,22 @@ class DefaultExtension extends MProvider {
|
|||||||
type_name: "SelectFilter",
|
type_name: "SelectFilter",
|
||||||
name: "Status",
|
name: "Status",
|
||||||
state: 0,
|
state: 0,
|
||||||
values: formateState("SelectOption", items, values)
|
values: formateState("SelectOption", items, values),
|
||||||
})
|
});
|
||||||
|
|
||||||
// Years
|
// Years
|
||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
items = Array.from({ length: currentYear - 1919 }, (_, i) => (1920 + i).toString()).reverse()
|
items = Array.from({ length: currentYear - 1919 }, (_, i) =>
|
||||||
items = ["All", ...items]
|
(1920 + i).toString()
|
||||||
values = ["", ...items]
|
).reverse();
|
||||||
|
items = ["All", ...items];
|
||||||
|
values = ["", ...items];
|
||||||
filters.push({
|
filters.push({
|
||||||
type_name: "SelectFilter",
|
type_name: "SelectFilter",
|
||||||
name: "Year",
|
name: "Year",
|
||||||
state: 0,
|
state: 0,
|
||||||
values: formateState("SelectOption", items, values)
|
values: formateState("SelectOption", items, values),
|
||||||
})
|
});
|
||||||
|
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
@@ -250,29 +368,28 @@ class DefaultExtension extends MProvider {
|
|||||||
{
|
{
|
||||||
key: "readcomiconline_page_quality",
|
key: "readcomiconline_page_quality",
|
||||||
listPreference: {
|
listPreference: {
|
||||||
title: 'Preferred image quality',
|
title: "Preferred image quality",
|
||||||
summary: '',
|
summary: "",
|
||||||
valueIndex: 2,
|
valueIndex: 2,
|
||||||
entries: ["Low", "Medium", "High", "Highest"],
|
entries: ["Low", "Medium", "High", "Highest"],
|
||||||
entryValues: ["l", "m", "h", "vh"]
|
entryValues: ["l", "m", "h", "vh"],
|
||||||
}
|
|
||||||
},
|
},
|
||||||
]
|
},
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- ReadComicOnline Image Decoder --------
|
// -------- ReadComicOnline Image Decoder --------
|
||||||
// Source:- https://readcomiconline.li/Scripts/rguard.min.js
|
// Source:- https://readcomiconline.li/Scripts/rguard.min.js
|
||||||
|
|
||||||
base64UrlDecode(input) {
|
base64UrlDecode(input) {
|
||||||
let base64 = input
|
let base64 = input.replace(/-/g, "+").replace(/_/g, "/");
|
||||||
.replace(/-/g, "+")
|
|
||||||
.replace(/_/g, "/");
|
|
||||||
|
|
||||||
while (base64.length % 4 !== 0) {
|
while (base64.length % 4 !== 0) {
|
||||||
base64 += "=";
|
base64 += "=";
|
||||||
}
|
}
|
||||||
|
|
||||||
const base64abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
const base64abc =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
const outputBytes = [];
|
const outputBytes = [];
|
||||||
|
|
||||||
for (let i = 0; i < base64.length; i += 4) {
|
for (let i = 0; i < base64.length; i += 4) {
|
||||||
@@ -283,23 +400,25 @@ class DefaultExtension extends MProvider {
|
|||||||
|
|
||||||
const triplet = (c1 << 18) | (c2 << 12) | ((c3 & 63) << 6) | (c4 & 63);
|
const triplet = (c1 << 18) | (c2 << 12) | ((c3 & 63) << 6) | (c4 & 63);
|
||||||
|
|
||||||
outputBytes.push((triplet >> 16) & 0xFF);
|
outputBytes.push((triplet >> 16) & 0xff);
|
||||||
if (base64[i + 2] !== "=") outputBytes.push((triplet >> 8) & 0xFF);
|
if (base64[i + 2] !== "=") outputBytes.push((triplet >> 8) & 0xff);
|
||||||
if (base64[i + 3] !== "=") outputBytes.push(triplet & 0xFF);
|
if (base64[i + 3] !== "=") outputBytes.push(triplet & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert bytes to ISO-8859-1 string
|
// Convert bytes to ISO-8859-1 string
|
||||||
return String.fromCharCode(...outputBytes);
|
return String.fromCharCode(...outputBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extractBeforeDecode(url) {
|
extractBeforeDecode(url) {
|
||||||
return url.substring(15, 33) + url.substring(50);
|
return url.substring(15, 33) + url.substring(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
finalizeDecodedString(decoded) {
|
finalizeDecodedString(decoded) {
|
||||||
return decoded.substring(0, decoded.length - 11) + decoded[decoded.length - 2] + decoded[decoded.length - 1];
|
return (
|
||||||
|
decoded.substring(0, decoded.length - 11) +
|
||||||
|
decoded[decoded.length - 2] +
|
||||||
|
decoded[decoded.length - 1]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
decoderFunction(encodedUrl) {
|
decoderFunction(encodedUrl) {
|
||||||
@@ -307,34 +426,34 @@ class DefaultExtension extends MProvider {
|
|||||||
decodedUrl = this.finalizeDecodedString(decodedUrl);
|
decodedUrl = this.finalizeDecodedString(decodedUrl);
|
||||||
decodedUrl = decodeURIComponent(this.base64UrlDecode(decodedUrl));
|
decodedUrl = decodeURIComponent(this.base64UrlDecode(decodedUrl));
|
||||||
decodedUrl = decodedUrl.substring(0, 13) + decodedUrl.substring(17);
|
decodedUrl = decodedUrl.substring(0, 13) + decodedUrl.substring(17);
|
||||||
return decodedUrl.slice(0, -2) + "=s1600"
|
return decodedUrl.slice(0, -2) + "=s1600";
|
||||||
}
|
}
|
||||||
|
|
||||||
decodeImageUrl(encodedImageUrl, imageQuality, baseUrlOverride) {
|
decodeImageUrl(encodedImageUrl, imageQuality, baseUrlOverride) {
|
||||||
// Default image qualities
|
// Default image qualities
|
||||||
var IMAGEQUALITY = [
|
var IMAGEQUALITY = [
|
||||||
{ "l": "900", "m": "0", "h": "1600", "vh": "2041" },
|
{ "l": "900", "m": "0", "h": "1600", "vh": "2041" },
|
||||||
{ "l": "900", "m": "1600", "h": "2041", "vh": "0" }
|
{ "l": "900", "m": "1600", "h": "2041", "vh": "0" },
|
||||||
]
|
];
|
||||||
|
|
||||||
let finalUrl;
|
let finalUrl;
|
||||||
var qType = 0
|
var qType = 0;
|
||||||
// Check if the url starts with https, if not then decode the url
|
// Check if the url starts with https, if not then decode the url
|
||||||
if (!encodedImageUrl.startsWith("https")) {
|
if (!encodedImageUrl.startsWith("https")) {
|
||||||
encodedImageUrl = encodedImageUrl
|
encodedImageUrl = encodedImageUrl
|
||||||
.replace(/6UUQS__ACd__/g, 'b')
|
.replace(/6UUQS__ACd__/g, "b")
|
||||||
.replace(/pw_.g28x/g, "b")
|
.replace(/pw_.g28x/g, "b");
|
||||||
|
|
||||||
var encodedUrl = encodedImageUrl.split("=s")[0]
|
var encodedUrl = encodedImageUrl.split("=s")[0];
|
||||||
var decodedUrl = this.decoderFunction(encodedUrl);
|
var decodedUrl = this.decoderFunction(encodedUrl);
|
||||||
|
|
||||||
var queryParams = encodedImageUrl.substring(encodedImageUrl.indexOf("?"));
|
var queryParams = encodedImageUrl.substring(encodedImageUrl.indexOf("?"));
|
||||||
finalUrl = baseUrlOverride + decodedUrl + queryParams
|
finalUrl = baseUrlOverride + decodedUrl + queryParams;
|
||||||
} else {
|
} else {
|
||||||
// If the url starts with https, then just override the base url
|
// If the url starts with https, then just override the base url
|
||||||
qType = 1
|
qType = 1;
|
||||||
finalUrl = baseUrlOverride + encodedImageUrl.split(".com/")[1]
|
finalUrl = baseUrlOverride + encodedImageUrl.split(".com/")[1];
|
||||||
}
|
}
|
||||||
return finalUrl.replace("s1600", `s${IMAGEQUALITY[qType][imageQuality]}`)
|
return finalUrl.replace("s1600", `s${IMAGEQUALITY[qType][imageQuality]}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user