mirror of
https://github.com/kodjodevf/mangayomi-extensions.git
synced 2026-02-14 10:51:17 +00:00
fix: Refresh contain issue
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,266 +1,279 @@
|
||||
const mangayomiSources = [{
|
||||
const mangayomiSources = [
|
||||
{
|
||||
"name": "Soaper",
|
||||
"id": 764093578,
|
||||
"lang": "all",
|
||||
"baseUrl": "https://soaper.cc",
|
||||
"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",
|
||||
"version": "1.0.4",
|
||||
"version": "1.0.5",
|
||||
"itemType": 1,
|
||||
"dateFormat": "",
|
||||
"dateFormatLocale": "",
|
||||
"pkgPath": "anime/src/all/soaper.js"
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
// Authors: - Swakshan, kodjodevf
|
||||
|
||||
class DefaultExtension extends MProvider {
|
||||
getHeaders(url) {
|
||||
return {
|
||||
"Referer": url,
|
||||
"Origin": url
|
||||
getHeaders(url) {
|
||||
return {
|
||||
Referer: url,
|
||||
Origin: url,
|
||||
};
|
||||
}
|
||||
|
||||
getPreference(key) {
|
||||
return new SharedPreferences().get(key);
|
||||
}
|
||||
|
||||
getBasueUrl() {
|
||||
return this.getPreference("soaper_override_base_url");
|
||||
}
|
||||
|
||||
async request(slug) {
|
||||
const baseUrl = this.getBasueUrl();
|
||||
var url = `${baseUrl}/${slug}`;
|
||||
var res = await new Client().get(url, this.getHeaders(baseUrl));
|
||||
var doc = new Document(res.body);
|
||||
return doc;
|
||||
}
|
||||
|
||||
async requestJSON(slug, data) {
|
||||
const baseUrl = this.getBasueUrl();
|
||||
var url = `${baseUrl}/${slug}`;
|
||||
var res = await new Client().post(url, this.getHeaders(baseUrl), data);
|
||||
return JSON.parse(res.body);
|
||||
}
|
||||
|
||||
async formatList(slug, page) {
|
||||
const baseUrl = this.getPreference("soaper_override_base_url");
|
||||
slug = parseInt(page) > 1 ? `${slug}?page=${page}` : slug;
|
||||
var doc = await this.request(slug);
|
||||
var list = [];
|
||||
var movies = doc.select(".thumbnail.text-center");
|
||||
|
||||
for (var movie of movies) {
|
||||
var linkSection = movie.selectFirst("div.img-group > a");
|
||||
var link = linkSection.getHref.substring(1);
|
||||
var poster = linkSection.selectFirst("img").getSrc;
|
||||
var imageUrl = `${baseUrl}${poster}`;
|
||||
var name = movie.selectFirst("h5").selectFirst("a").text;
|
||||
|
||||
list.push({ name, imageUrl, link });
|
||||
}
|
||||
|
||||
var hasNextPage = false;
|
||||
if (slug.indexOf("search.html?") == -1) {
|
||||
var pagination = doc.select("ul.pagination > li");
|
||||
var last_page_num = parseInt(pagination[pagination.length - 2].text);
|
||||
hasNextPage = page < last_page_num ? true : false;
|
||||
}
|
||||
return { list, hasNextPage };
|
||||
}
|
||||
|
||||
async filterList(year = "all", genre = "all", sort = "new", page = 1) {
|
||||
year = year == "all" ? "" : `/year/${year}`;
|
||||
genre = genre == "all" ? "" : `/cat/${genre}`;
|
||||
sort = sort == "new" ? "" : `/sort/${sort}`;
|
||||
|
||||
var slug = `${sort}${year}${genre}`;
|
||||
var movieList = await this.formatList(`movielist${slug}`, page);
|
||||
var seriesList = await this.formatList(`tvlist${slug}`, page);
|
||||
|
||||
var list = [];
|
||||
var priority = this.getPreference("soaper_content_priority");
|
||||
if (priority === "series") {
|
||||
list = [...seriesList.list, ...movieList.list];
|
||||
} else {
|
||||
list = [...movieList.list, ...seriesList.list];
|
||||
}
|
||||
|
||||
var hasNextPage = seriesList.hasNextPage || movieList.hasNextPage;
|
||||
|
||||
return { list, hasNextPage };
|
||||
}
|
||||
|
||||
async getPopular(page) {
|
||||
return await this.filterList("all", "all", "hot", page);
|
||||
}
|
||||
get supportsLatest() {
|
||||
throw new Error("supportsLatest not implemented");
|
||||
}
|
||||
async getLatestUpdates(page) {
|
||||
return await this.filterList("all", "all", "new", page);
|
||||
}
|
||||
|
||||
async search(query, page, filters) {
|
||||
var seriesList = [];
|
||||
var movieList = [];
|
||||
var list = [];
|
||||
|
||||
var res = await this.formatList(`search.html?keyword=${query}`, 1);
|
||||
var movies = res["list"];
|
||||
|
||||
for (var movie of movies) {
|
||||
var link = movie.link;
|
||||
if (link.indexOf("tv_") != -1) {
|
||||
seriesList.push(movie);
|
||||
} else {
|
||||
movieList.push(movie);
|
||||
}
|
||||
}
|
||||
|
||||
var priority = this.getPreference("soaper_content_priority");
|
||||
if (priority === "series") {
|
||||
list = [...seriesList, ...movieList];
|
||||
} else {
|
||||
list = [...movieList, ...seriesList];
|
||||
}
|
||||
|
||||
return { list, hasNextPage: false };
|
||||
}
|
||||
|
||||
async getDetail(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}`;
|
||||
|
||||
var description = doc.selectFirst("p#wrap").text.trim();
|
||||
var link = `${baseUrl}/${slug}`;
|
||||
|
||||
var chapters = [];
|
||||
if (slug.indexOf("tv_") != -1) {
|
||||
var seasonList = doc.select(".alert.alert-info-ex.col-sm-12");
|
||||
var seasonCount = seasonList.length;
|
||||
for (var season of seasonList) {
|
||||
var eps = season.select(".col-sm-12.col-md-6.col-lg-4.myp1");
|
||||
for (var ep of eps) {
|
||||
var epLinkSection = ep.selectFirst("a");
|
||||
var epLink = epLinkSection.getHref.substring(1);
|
||||
var epName = epLinkSection.text;
|
||||
|
||||
chapters.push({
|
||||
name: `S${seasonCount}E${epName}`,
|
||||
url: epLink,
|
||||
});
|
||||
}
|
||||
seasonCount--;
|
||||
}
|
||||
} else {
|
||||
chapters.push({
|
||||
name: "Movie",
|
||||
url: slug,
|
||||
});
|
||||
}
|
||||
|
||||
getPreference(key) {
|
||||
return new SharedPreferences().get(key);
|
||||
}
|
||||
return { name, imageUrl, description, link, chapters };
|
||||
}
|
||||
// For anime episode video list
|
||||
async getVideoList(url) {
|
||||
var body = await this.request(url);
|
||||
var baseUrl = this.getBasueUrl();
|
||||
var streams = [];
|
||||
|
||||
getBasueUrl() {
|
||||
return this.getPreference("soaper_override_base_url")
|
||||
}
|
||||
// Traditional servers
|
||||
var eId = body.selectFirst("#hId").attr("value");
|
||||
var hIsW = body.selectFirst("#hIsW").attr("value");
|
||||
var apiType = url[0].toUpperCase();
|
||||
|
||||
async request(slug) {
|
||||
const baseUrl = this.getBasueUrl()
|
||||
var url = `${baseUrl}/${slug}`
|
||||
var res = await new Client().get(url, this.getHeaders(baseUrl));
|
||||
var doc = new Document(res.body);
|
||||
return doc
|
||||
}
|
||||
var servers = [0, 1];
|
||||
for (var serverNum of servers) {
|
||||
var serverName = body.selectFirst(`#server_button_${serverNum}`).text;
|
||||
if (serverName.length < 1) continue;
|
||||
var data = {
|
||||
pass: eId,
|
||||
param: "",
|
||||
extra: "1",
|
||||
e2: hIsW,
|
||||
server: "" + serverNum,
|
||||
};
|
||||
var res = await this.requestJSON(
|
||||
`home/index/Get${apiType}InfoAjax`,
|
||||
data
|
||||
);
|
||||
|
||||
async requestJSON(slug, data) {
|
||||
const baseUrl = this.getBasueUrl()
|
||||
var url = `${baseUrl}/${slug}`
|
||||
var res = await new Client().post(url, this.getHeaders(baseUrl), data);
|
||||
return JSON.parse(res.body);
|
||||
}
|
||||
|
||||
async formatList(slug, page) {
|
||||
const baseUrl = this.getPreference("soaper_override_base_url")
|
||||
slug = parseInt(page) > 1 ? `${slug}?page=${page}` : slug
|
||||
var doc = await this.request(slug);
|
||||
var list = [];
|
||||
var movies = doc.select(".thumbnail.text-center")
|
||||
|
||||
for (var movie of movies) {
|
||||
var linkSection = movie.selectFirst("div.img-group > a")
|
||||
var link = linkSection.getHref.substring(1,);
|
||||
var poster = linkSection.selectFirst("img").getSrc
|
||||
var imageUrl = `${baseUrl}${poster}`
|
||||
var name = movie.selectFirst("h5").selectFirst("a").text;
|
||||
|
||||
list.push({ name, imageUrl, link });
|
||||
var streamUrl = baseUrl + res.val;
|
||||
var subs = [];
|
||||
var vidSubs = res.subs;
|
||||
if (vidSubs != null && vidSubs.length > 0) {
|
||||
for (var sub of vidSubs) {
|
||||
subs.push({
|
||||
file: baseUrl + sub.path,
|
||||
label: sub.name,
|
||||
});
|
||||
}
|
||||
|
||||
var hasNextPage = false
|
||||
if (slug.indexOf("search.html?") == -1) {
|
||||
var pagination = doc.select("ul.pagination > li")
|
||||
var last_page_num = parseInt(pagination[pagination.length - 2].text);
|
||||
hasNextPage = page < last_page_num ? true : false;
|
||||
}
|
||||
return { list, hasNextPage }
|
||||
}
|
||||
streams.push({
|
||||
url: streamUrl,
|
||||
originalUrl: streamUrl,
|
||||
quality: serverName,
|
||||
subtitles: subs,
|
||||
});
|
||||
}
|
||||
|
||||
async filterList(year = "all", genre = "all", sort = "new", page = 1) {
|
||||
year = year == "all" ? "" : `/year/${year}`
|
||||
genre = genre == "all" ? "" : `/cat/${genre}`
|
||||
sort = sort == "new" ? "" : `/sort/${sort}`
|
||||
// Download servers
|
||||
var modal_footer = body.select(".modal-footer > a");
|
||||
if (modal_footer.length > 0) {
|
||||
modal_footer.reverse();
|
||||
for (var item of modal_footer) {
|
||||
var dSlug = item.getHref;
|
||||
var dBody = await this.request(dSlug);
|
||||
|
||||
var slug = `${sort}${year}${genre}`
|
||||
var movieList = await this.formatList(`movielist${slug}`, page);
|
||||
var seriesList = await this.formatList(`tvlist${slug}`, page);
|
||||
var res = dBody.selectFirst("#res").attr("value");
|
||||
var mb = dBody.selectFirst("#mb").attr("value");
|
||||
var streamLink = dBody.selectFirst("#link").attr("value");
|
||||
|
||||
var list = [];
|
||||
var priority = this.getPreference("soaper_content_priority");
|
||||
if (priority === "series") {
|
||||
list = [...seriesList.list, ...movieList.list];
|
||||
} else {
|
||||
list = [...movieList.list, ...seriesList.list];
|
||||
}
|
||||
|
||||
var hasNextPage = seriesList.hasNextPage || movieList.hasNextPage;
|
||||
|
||||
return { list, hasNextPage }
|
||||
streams.push({
|
||||
url: streamLink,
|
||||
originalUrl: streamLink,
|
||||
quality: `Download Server: ${res} [${mb}]`,
|
||||
});
|
||||
}
|
||||
}
|
||||
return streams;
|
||||
}
|
||||
// For manga chapter pages
|
||||
async getPageList() {
|
||||
throw new Error("getPageList not implemented");
|
||||
}
|
||||
getFilterList() {
|
||||
throw new Error("getFilterList not implemented");
|
||||
}
|
||||
|
||||
async getPopular(page) {
|
||||
return await this.filterList("all", "all", "hot", page);
|
||||
}
|
||||
get supportsLatest() {
|
||||
throw new Error("supportsLatest not implemented");
|
||||
}
|
||||
async getLatestUpdates(page) {
|
||||
return await this.filterList("all", "all", "new", page);
|
||||
}
|
||||
|
||||
async search(query, page, filters) {
|
||||
var seriesList = []
|
||||
var movieList = []
|
||||
var list = [];
|
||||
|
||||
var res = await this.formatList(`search.html?keyword=${query}`, 1)
|
||||
var movies = res["list"]
|
||||
|
||||
for (var movie of movies) {
|
||||
var link = movie.link
|
||||
if (link.indexOf("tv_") != -1) {
|
||||
seriesList.push(movie);
|
||||
} else {
|
||||
movieList.push(movie);
|
||||
}
|
||||
}
|
||||
|
||||
var priority = this.getPreference("soaper_content_priority");
|
||||
if (priority === "series") {
|
||||
list = [...seriesList, ...movieList];
|
||||
} else {
|
||||
list = [...movieList, ...seriesList];
|
||||
}
|
||||
|
||||
return { list, hasNextPage: false }
|
||||
}
|
||||
|
||||
async getDetail(url) {
|
||||
var doc = await this.request(url);
|
||||
|
||||
const baseUrl = this.getPreference("soaper_override_base_url")
|
||||
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}`
|
||||
|
||||
var description = doc.selectFirst("p#wrap").text.trim()
|
||||
var link = `${baseUrl}/${url}`
|
||||
|
||||
var chapters = []
|
||||
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) {
|
||||
var eps = season.select(".col-sm-12.col-md-6.col-lg-4.myp1")
|
||||
for (var ep of eps) {
|
||||
var epLinkSection = ep.selectFirst("a")
|
||||
var epLink = epLinkSection.getHref.substring(1)
|
||||
var epName = epLinkSection.text
|
||||
|
||||
chapters.push({
|
||||
name: `S${seasonCount}E${epName}`,
|
||||
url: epLink,
|
||||
})
|
||||
}
|
||||
seasonCount--;
|
||||
}
|
||||
|
||||
} else {
|
||||
chapters.push({
|
||||
name: "Movie",
|
||||
url: url,
|
||||
})
|
||||
}
|
||||
|
||||
return { name, imageUrl, description, link, chapters }
|
||||
}
|
||||
// For anime episode video list
|
||||
async getVideoList(url) {
|
||||
var body = await this.request(url)
|
||||
var baseUrl = this.getBasueUrl()
|
||||
var streams = []
|
||||
|
||||
// Traditional servers
|
||||
var eId = body.selectFirst("#hId").attr('value')
|
||||
var hIsW = body.selectFirst("#hIsW").attr('value')
|
||||
var apiType = url[0].toUpperCase()
|
||||
|
||||
var servers = [0, 1]
|
||||
for (var serverNum of servers) {
|
||||
var serverName = body.selectFirst(`#server_button_${serverNum}`).text
|
||||
if (serverName.length < 1) continue;
|
||||
var data = {
|
||||
pass: eId,
|
||||
param: "",
|
||||
extra: "1",
|
||||
e2: hIsW,
|
||||
server: "" + serverNum,
|
||||
}
|
||||
var res = await this.requestJSON(`home/index/Get${apiType}InfoAjax`, data)
|
||||
|
||||
var streamUrl = baseUrl + res.val
|
||||
var subs = []
|
||||
var vidSubs = res.subs
|
||||
if (vidSubs != null && vidSubs.length > 0) {
|
||||
for (var sub of vidSubs) {
|
||||
subs.push({
|
||||
file: baseUrl + sub.path,
|
||||
label: sub.name
|
||||
})
|
||||
}
|
||||
}
|
||||
streams.push({
|
||||
url: streamUrl,
|
||||
originalUrl: streamUrl,
|
||||
quality: serverName,
|
||||
subtitles: subs
|
||||
});
|
||||
}
|
||||
|
||||
// Download servers
|
||||
var modal_footer = body.select(".modal-footer > a")
|
||||
if (modal_footer.length > 0) {
|
||||
|
||||
modal_footer.reverse()
|
||||
for (var item of modal_footer) {
|
||||
var dSlug = item.getHref
|
||||
var dBody = await this.request(dSlug)
|
||||
|
||||
var res = dBody.selectFirst("#res").attr('value')
|
||||
var mb = dBody.selectFirst("#mb").attr('value')
|
||||
var streamLink = dBody.selectFirst("#link").attr('value')
|
||||
|
||||
streams.push({
|
||||
url: streamLink,
|
||||
originalUrl: streamLink,
|
||||
quality: `Download Server: ${res} [${mb}]`,
|
||||
});
|
||||
}
|
||||
}
|
||||
return streams
|
||||
|
||||
}
|
||||
// For manga chapter pages
|
||||
async getPageList() {
|
||||
throw new Error("getPageList not implemented");
|
||||
}
|
||||
getFilterList() {
|
||||
throw new Error("getFilterList not implemented");
|
||||
}
|
||||
|
||||
getSourcePreferences() {
|
||||
return [{
|
||||
"key": "soaper_override_base_url",
|
||||
editTextPreference: {
|
||||
title: "Override base url",
|
||||
summary: "Default: https://soaper.cc",
|
||||
value: "https://soaper.cc",
|
||||
dialogTitle: "Override base url",
|
||||
dialogMessage: "",
|
||||
}
|
||||
}, {
|
||||
key: 'soaper_content_priority',
|
||||
listPreference: {
|
||||
title: 'Preferred content priority',
|
||||
summary: 'Choose which type of content to show first',
|
||||
valueIndex: 0,
|
||||
entries: ["Movies", "Series"],
|
||||
entryValues: ["movies", "series"]
|
||||
}
|
||||
getSourcePreferences() {
|
||||
return [
|
||||
{
|
||||
key: "soaper_override_base_url",
|
||||
editTextPreference: {
|
||||
title: "Override base url",
|
||||
summary: "Default: https://soaper.cc",
|
||||
value: "https://soaper.cc",
|
||||
dialogTitle: "Override base url",
|
||||
dialogMessage: "",
|
||||
},
|
||||
];
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "soaper_content_priority",
|
||||
listPreference: {
|
||||
title: "Preferred content priority",
|
||||
summary: "Choose which type of content to show first",
|
||||
valueIndex: 0,
|
||||
entries: ["Movies", "Series"],
|
||||
entryValues: ["movies", "series"],
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,258 +1,254 @@
|
||||
const mangayomiSources = [{
|
||||
const mangayomiSources = [
|
||||
{
|
||||
"name": "AnimeGG",
|
||||
"lang": "en",
|
||||
"id": 209614032,
|
||||
"baseUrl": "https://www.animegg.org",
|
||||
"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",
|
||||
"itemType": 1,
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"pkgPath": "anime/src/en/animegg.js"
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
class DefaultExtension extends MProvider {
|
||||
constructor() {
|
||||
super();
|
||||
this.client = new Client();
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.client = new Client();
|
||||
}
|
||||
getHeaders(url) {
|
||||
return {
|
||||
Referer: this.source.baseUrl,
|
||||
Origin: this.source.baseUrl,
|
||||
};
|
||||
}
|
||||
|
||||
getHeaders(url) {
|
||||
return {
|
||||
"Referer": this.source.baseUrl,
|
||||
"Origin": this.source.baseUrl
|
||||
}
|
||||
}
|
||||
getPreference(key) {
|
||||
return parseInt(new SharedPreferences().get(key));
|
||||
}
|
||||
|
||||
getPreference(key) {
|
||||
return parseInt(new SharedPreferences().get(key));
|
||||
}
|
||||
async requestText(slug) {
|
||||
var url = `${this.source.baseUrl}${slug}`;
|
||||
var res = await this.client.get(url, this.getHeaders());
|
||||
return res.body;
|
||||
}
|
||||
async request(slug) {
|
||||
return new Document(await this.requestText(slug));
|
||||
}
|
||||
|
||||
async requestText(slug) {
|
||||
var url = `${this.source.baseUrl}${slug}`
|
||||
var res = await this.client.get(url, this.getHeaders());
|
||||
return res.body;
|
||||
}
|
||||
async request(slug) {
|
||||
return new Document(await this.requestText(slug));
|
||||
}
|
||||
|
||||
async fetchPopularnLatest(slug) {
|
||||
var body = await this.request(slug)
|
||||
var items = body.select("li.fea")
|
||||
var list = []
|
||||
var hasNextPage = true
|
||||
if (items.length > 0) {
|
||||
for (var item of items) {
|
||||
var imageUrl = item.selectFirst('img').getSrc
|
||||
var linkSection = item.selectFirst('.rightpop').selectFirst('a')
|
||||
var link = linkSection.getHref
|
||||
var name = linkSection.text
|
||||
list.push({
|
||||
name,
|
||||
imageUrl,
|
||||
link
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
hasNextPage = false
|
||||
}
|
||||
return { list, hasNextPage }
|
||||
}
|
||||
|
||||
async getPopular(page) {
|
||||
var start = (page - 1) * 25;
|
||||
var limit = start + 25;
|
||||
|
||||
var category = ""
|
||||
var pop = this.getPreference("animegg_popular_category")
|
||||
switch (pop) {
|
||||
case 1: {
|
||||
category = "sortBy=createdAt&sortDirection=DESC&";
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
category = "ongoing=true&";
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
category = "ongoing=false&";
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
category = "sortBy=sortLetter&sortDirection=ASC&";
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
var slug = `/popular-series?${category}start=${start}&limit=${limit}`
|
||||
return await this.fetchPopularnLatest(slug)
|
||||
|
||||
|
||||
}
|
||||
get supportsLatest() {
|
||||
throw new Error("supportsLatest not implemented");
|
||||
}
|
||||
async getLatestUpdates(page) {
|
||||
var start = (page - 1) * 25;
|
||||
var limit = start + 25;
|
||||
|
||||
var slug = `/releases?start=${start}&limit=${limit}`
|
||||
return await this.fetchPopularnLatest(slug)
|
||||
|
||||
}
|
||||
async search(query, page, filters) {
|
||||
var slug = `/search?q=${query}`
|
||||
var body = await this.request(slug)
|
||||
var items = body.select(".moose.page > a")
|
||||
var list = []
|
||||
for (var item of items) {
|
||||
var imageUrl = item.selectFirst('img').getSrc
|
||||
var link = item.getHref
|
||||
var name = item.selectFirst("h2").text
|
||||
list.push({
|
||||
name,
|
||||
imageUrl,
|
||||
link
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return { list, hasNextPage: false }
|
||||
}
|
||||
|
||||
statusCode(status) {
|
||||
return {
|
||||
"Ongoing": 0,
|
||||
"Completed": 1,
|
||||
}[status] ?? 5;
|
||||
}
|
||||
|
||||
async getDetail(url) {
|
||||
var link = this.source.baseUrl + url;
|
||||
|
||||
var body = await this.request(url)
|
||||
|
||||
var media = body.selectFirst(".media")
|
||||
var title = media.selectFirst("h1").text
|
||||
var spans = media.selectFirst("p.infoami").select("span")
|
||||
var statusText = spans[spans.length - 1].text.replace("Status: ", '')
|
||||
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 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 type = ep.select("span.btn-xs")
|
||||
type.forEach(t => {
|
||||
scanlator += t.text + ", ";
|
||||
|
||||
})
|
||||
scanlator = scanlator.slice(0, -2);
|
||||
|
||||
chapters.push({ name: epName, url: epUrl, scanlator })
|
||||
})
|
||||
|
||||
|
||||
return { description, status, genre, chapters, link }
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
async exxtractStreams(div,audio){
|
||||
|
||||
var slug = div.selectFirst("iframe").getSrc
|
||||
var streams = []
|
||||
if(slug.length < 1){
|
||||
return streams;
|
||||
}
|
||||
var body = await this.requestText(slug)
|
||||
var sKey = "var videoSources = "
|
||||
var eKey = "var httpProtocol"
|
||||
var start = body.indexOf(sKey) + sKey.length
|
||||
var end = body.indexOf(eKey) - 8
|
||||
var videoSourcesStr = body.substring(start, end)
|
||||
let videoSources = eval("(" + videoSourcesStr + ")");
|
||||
var headers = this.getHeaders();
|
||||
videoSources.forEach(videoSource => {
|
||||
var url = this.source.baseUrl +videoSource.file
|
||||
var quality = `${videoSource.label} - ${audio}`
|
||||
|
||||
streams.push({
|
||||
url,
|
||||
originalUrl: url,
|
||||
quality,
|
||||
headers
|
||||
});
|
||||
async fetchPopularnLatest(slug) {
|
||||
var body = await this.request(slug);
|
||||
var items = body.select("li.fea");
|
||||
var list = [];
|
||||
var hasNextPage = true;
|
||||
if (items.length > 0) {
|
||||
for (var item of items) {
|
||||
var imageUrl = item.selectFirst("img").getSrc;
|
||||
var linkSection = item.selectFirst(".rightpop").selectFirst("a");
|
||||
var link = linkSection.getHref;
|
||||
var name = linkSection.text;
|
||||
list.push({
|
||||
name,
|
||||
imageUrl,
|
||||
link,
|
||||
});
|
||||
return streams.reverse();
|
||||
}
|
||||
} else {
|
||||
hasNextPage = false;
|
||||
}
|
||||
return { list, hasNextPage };
|
||||
}
|
||||
|
||||
async getPopular(page) {
|
||||
var start = (page - 1) * 25;
|
||||
var limit = start + 25;
|
||||
|
||||
var category = "";
|
||||
var pop = this.getPreference("animegg_popular_category");
|
||||
switch (pop) {
|
||||
case 1: {
|
||||
category = "sortBy=createdAt&sortDirection=DESC&";
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
category = "ongoing=true&";
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
category = "ongoing=false&";
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
category = "sortBy=sortLetter&sortDirection=ASC&";
|
||||
break;
|
||||
}
|
||||
}
|
||||
var slug = `/popular-series?${category}start=${start}&limit=${limit}`;
|
||||
return await this.fetchPopularnLatest(slug);
|
||||
}
|
||||
get supportsLatest() {
|
||||
throw new Error("supportsLatest not implemented");
|
||||
}
|
||||
async getLatestUpdates(page) {
|
||||
var start = (page - 1) * 25;
|
||||
var limit = start + 25;
|
||||
|
||||
var slug = `/releases?start=${start}&limit=${limit}`;
|
||||
return await this.fetchPopularnLatest(slug);
|
||||
}
|
||||
async search(query, page, filters) {
|
||||
var slug = `/search?q=${query}`;
|
||||
var body = await this.request(slug);
|
||||
var items = body.select(".moose.page > a");
|
||||
var list = [];
|
||||
for (var item of items) {
|
||||
var imageUrl = item.selectFirst("img").getSrc;
|
||||
var link = item.getHref;
|
||||
var name = item.selectFirst("h2").text;
|
||||
list.push({
|
||||
name,
|
||||
imageUrl,
|
||||
link,
|
||||
});
|
||||
}
|
||||
|
||||
// For anime episode video list
|
||||
async getVideoList(url) {
|
||||
var body = await this.request(url)
|
||||
|
||||
var sub = body.selectFirst("#subbed-Animegg")
|
||||
var subStreams = await this.exxtractStreams(sub,"Sub")
|
||||
return { list, hasNextPage: false };
|
||||
}
|
||||
|
||||
var dub = body.selectFirst("#dubbed-Animegg")
|
||||
var dubStreams = await this.exxtractStreams(dub,"Dub")
|
||||
statusCode(status) {
|
||||
return (
|
||||
{
|
||||
Ongoing: 0,
|
||||
Completed: 1,
|
||||
}[status] ?? 5
|
||||
);
|
||||
}
|
||||
|
||||
var raw = body.selectFirst("#raw-Animegg")
|
||||
var rawStreams = await this.exxtractStreams(raw,"Raw")
|
||||
async getDetail(url) {
|
||||
var baseUrl = this.source.baseUrl;
|
||||
var slug = url.replace(baseUrl, "");
|
||||
var link = baseUrl + slug;
|
||||
|
||||
var body = await this.request(slug);
|
||||
|
||||
var media = body.selectFirst(".media");
|
||||
var title = media.selectFirst("h1").text;
|
||||
var spans = media.selectFirst("p.infoami").select("span");
|
||||
var statusText = spans[spans.length - 1].text.replace("Status: ", "");
|
||||
var status = this.statusCode(statusText);
|
||||
|
||||
var pref = this.getPreference("animegg_stream_type_1")
|
||||
var streams = [];
|
||||
if(pref == 0){
|
||||
streams = [...subStreams,...dubStreams, ...rawStreams]
|
||||
}else if(pref == 1){
|
||||
streams = [...dubStreams,...subStreams, ...rawStreams]
|
||||
}else{
|
||||
streams = [...rawStreams,...subStreams, ...dubStreams]
|
||||
}
|
||||
|
||||
return streams
|
||||
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 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 type = ep.select("span.btn-xs");
|
||||
type.forEach((t) => {
|
||||
scanlator += t.text + ", ";
|
||||
});
|
||||
scanlator = scanlator.slice(0, -2);
|
||||
|
||||
chapters.push({ name: epName, url: epUrl, scanlator });
|
||||
});
|
||||
|
||||
return { description, status, genre, chapters, link };
|
||||
}
|
||||
|
||||
async exxtractStreams(div, audio) {
|
||||
var slug = div.selectFirst("iframe").getSrc;
|
||||
var streams = [];
|
||||
if (slug.length < 1) {
|
||||
return streams;
|
||||
}
|
||||
var body = await this.requestText(slug);
|
||||
var sKey = "var videoSources = ";
|
||||
var eKey = "var httpProtocol";
|
||||
var start = body.indexOf(sKey) + sKey.length;
|
||||
var end = body.indexOf(eKey) - 8;
|
||||
var videoSourcesStr = body.substring(start, end);
|
||||
let videoSources = eval("(" + videoSourcesStr + ")");
|
||||
var headers = this.getHeaders();
|
||||
videoSources.forEach((videoSource) => {
|
||||
var url = this.source.baseUrl + videoSource.file;
|
||||
var quality = `${videoSource.label} - ${audio}`;
|
||||
|
||||
streams.push({
|
||||
url,
|
||||
originalUrl: url,
|
||||
quality,
|
||||
headers,
|
||||
});
|
||||
});
|
||||
return streams.reverse();
|
||||
}
|
||||
|
||||
// For anime episode video list
|
||||
async getVideoList(url) {
|
||||
var body = await this.request(url);
|
||||
|
||||
var sub = body.selectFirst("#subbed-Animegg");
|
||||
var subStreams = await this.exxtractStreams(sub, "Sub");
|
||||
|
||||
var dub = body.selectFirst("#dubbed-Animegg");
|
||||
var dubStreams = await this.exxtractStreams(dub, "Dub");
|
||||
|
||||
var raw = body.selectFirst("#raw-Animegg");
|
||||
var rawStreams = await this.exxtractStreams(raw, "Raw");
|
||||
|
||||
var pref = this.getPreference("animegg_stream_type_1");
|
||||
var streams = [];
|
||||
if (pref == 0) {
|
||||
streams = [...subStreams, ...dubStreams, ...rawStreams];
|
||||
} else if (pref == 1) {
|
||||
streams = [...dubStreams, ...subStreams, ...rawStreams];
|
||||
} else {
|
||||
streams = [...rawStreams, ...subStreams, ...dubStreams];
|
||||
}
|
||||
|
||||
getSourcePreferences() {
|
||||
return [
|
||||
{
|
||||
key: "animegg_popular_category",
|
||||
listPreference: {
|
||||
title: 'Preferred popular category',
|
||||
summary: '',
|
||||
valueIndex: 0,
|
||||
entries: ["Popular", "Newest", "Ongoing", "Completed", "Alphabetical"],
|
||||
entryValues: ["0", "1", "2", "3", "4"]
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "animegg_stream_type_1",
|
||||
listPreference: {
|
||||
title: 'Preferred stream type',
|
||||
summary: '',
|
||||
valueIndex: 0,
|
||||
entries: ["Sub","Dub","Raw"],
|
||||
entryValues: ["0", "1", "2"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
return streams;
|
||||
}
|
||||
|
||||
getSourcePreferences() {
|
||||
return [
|
||||
{
|
||||
key: "animegg_popular_category",
|
||||
listPreference: {
|
||||
title: "Preferred popular category",
|
||||
summary: "",
|
||||
valueIndex: 0,
|
||||
entries: [
|
||||
"Popular",
|
||||
"Newest",
|
||||
"Ongoing",
|
||||
"Completed",
|
||||
"Alphabetical",
|
||||
],
|
||||
entryValues: ["0", "1", "2", "3", "4"],
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "animegg_stream_type_1",
|
||||
listPreference: {
|
||||
title: "Preferred stream type",
|
||||
summary: "",
|
||||
valueIndex: 0,
|
||||
entries: ["Sub", "Dub", "Raw"],
|
||||
entryValues: ["0", "1", "2"],
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ const mangayomiSources = [{
|
||||
"iconUrl": "https://www.google.com/s2/favicons?sz=256&domain=https://www.animeonsen.xyz",
|
||||
"typeSource": "single",
|
||||
"itemType": 1,
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"pkgPath": "anime/src/all/animeonsen.js"
|
||||
}];
|
||||
|
||||
@@ -143,7 +143,9 @@ class DefaultExtension extends MProvider {
|
||||
}
|
||||
|
||||
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 animeDetails = await this.request(detailsApiSlug);
|
||||
|
||||
|
||||
@@ -1,241 +1,270 @@
|
||||
const mangayomiSources = [{
|
||||
const mangayomiSources = [
|
||||
{
|
||||
"name": "AnimeParadise",
|
||||
"lang": "en",
|
||||
"baseUrl": "https://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",
|
||||
"itemType": 1,
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"pkgPath": "anime/src/en/animeparadise.js"
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
class DefaultExtension extends MProvider {
|
||||
getPreference(key) {
|
||||
const preferences = new SharedPreferences();
|
||||
return preferences.get(key);
|
||||
}
|
||||
|
||||
getPreference(key) {
|
||||
const preferences = new SharedPreferences();
|
||||
return preferences.get(key);
|
||||
async extractFromUrl(url) {
|
||||
var res = await new Client().get(this.source.baseUrl + url);
|
||||
var doc = new Document(res.body);
|
||||
var jsonData = doc.selectFirst("#__NEXT_DATA__").text;
|
||||
return JSON.parse(jsonData).props.pageProps;
|
||||
}
|
||||
|
||||
async requestAPI(slug) {
|
||||
var api = `${this.source.apiUrl}/${slug}`;
|
||||
var response = await new Client().get(api);
|
||||
var body = JSON.parse(response.body);
|
||||
return body;
|
||||
}
|
||||
|
||||
async formList(slug) {
|
||||
var jsonData = await this.requestAPI(slug);
|
||||
var list = [];
|
||||
if ("episodes" in jsonData) {
|
||||
jsonData.episodes.forEach((item) => {
|
||||
list.push({
|
||||
"name": item.origin.title,
|
||||
"link": item.origin.link,
|
||||
"imageUrl": item.image,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
jsonData.data.forEach((item) => {
|
||||
list.push({
|
||||
"name": item.title,
|
||||
"link": item.link,
|
||||
"imageUrl": item.posterImage.original,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async extractFromUrl(url) {
|
||||
var res = await new Client().get(this.source.baseUrl + url);
|
||||
var doc = new Document(res.body);
|
||||
var jsonData = doc.selectFirst("#__NEXT_DATA__").text
|
||||
return JSON.parse(jsonData).props.pageProps
|
||||
}
|
||||
return {
|
||||
"list": list,
|
||||
"hasNextPage": false,
|
||||
};
|
||||
}
|
||||
|
||||
async requestAPI(slug) {
|
||||
var api = `${this.source.apiUrl}/${slug}`
|
||||
var response = await new Client().get(api);
|
||||
var body = JSON.parse(response.body);
|
||||
return body;
|
||||
}
|
||||
async getPopular(page) {
|
||||
return await this.formList('?sort={"rate": -1 }');
|
||||
}
|
||||
|
||||
async formList(slug) {
|
||||
var jsonData = await this.requestAPI(slug);
|
||||
var list = [];
|
||||
if ("episodes" in jsonData) {
|
||||
jsonData.episodes.forEach(item => {
|
||||
list.push({
|
||||
"name": item.origin.title,
|
||||
"link": item.origin.link,
|
||||
"imageUrl": item.image
|
||||
});
|
||||
})
|
||||
} else {
|
||||
jsonData.data.forEach(item => {
|
||||
list.push({
|
||||
"name": item.title,
|
||||
"link": item.link,
|
||||
"imageUrl": item.posterImage.original
|
||||
});
|
||||
})
|
||||
async getLatestUpdates(page) {
|
||||
var slug = '?sort={"postDate": -1 }';
|
||||
|
||||
var choice = this.getPreference("animeparadise_pref_latest_tab");
|
||||
if (choice === "recent_ep") slug = "ep/recently-added";
|
||||
|
||||
return await this.formList(slug);
|
||||
}
|
||||
async search(query, page, filters) {
|
||||
var season = filters[0].values[filters[0].state].value;
|
||||
var year = filters[1].values[filters[1].state].value;
|
||||
|
||||
var genre = "genre[]=";
|
||||
for (var filter of filters[2].state) {
|
||||
if (filter.state == true) genre += `${filter.value}&genre[]=`;
|
||||
}
|
||||
var slug = `search?q=${query}&year=${year}&season=${season}&${genre}`;
|
||||
return await this.formList(slug);
|
||||
}
|
||||
statusCode(status) {
|
||||
return (
|
||||
{
|
||||
"current": 0,
|
||||
"finished": 1,
|
||||
}[status] ?? 5
|
||||
);
|
||||
}
|
||||
|
||||
async getDetail(url) {
|
||||
var linkSlug = this.source.baseUrl + `/anime/`;
|
||||
if (url.includes(linkSlug)) url = url.replace(linkSlug, "");
|
||||
|
||||
var jsonData = await this.extractFromUrl(`/anime/${url}`);
|
||||
jsonData = jsonData.data;
|
||||
var details = {};
|
||||
var chapters = [];
|
||||
details.imageUrl = jsonData.posterImage.original;
|
||||
details.description = jsonData.synopsys;
|
||||
details.genre = jsonData.genres;
|
||||
details.status = this.statusCode(jsonData.status);
|
||||
var id = jsonData._id;
|
||||
var epAPI = await this.requestAPI(`anime/${id}/episode`);
|
||||
epAPI.data.forEach((ep) => {
|
||||
var epName = `E${ep.number}: ${ep.title}`;
|
||||
var epUrl = `${ep.uid}?origin=${ep.origin}`;
|
||||
chapters.push({ name: epName, url: epUrl });
|
||||
});
|
||||
details.link = `${linkSlug}${url}`;
|
||||
details.chapters = chapters.reverse();
|
||||
return details;
|
||||
}
|
||||
// Sorts streams based on user preference.
|
||||
async sortStreams(streams) {
|
||||
var sortedStreams = [];
|
||||
var copyStreams = streams.slice();
|
||||
|
||||
var pref = await this.getPreference("animeparadise_pref_video_resolution");
|
||||
for (var stream of streams) {
|
||||
if (stream.quality.indexOf(pref) > -1) {
|
||||
sortedStreams.push(stream);
|
||||
var index = copyStreams.indexOf(stream);
|
||||
if (index > -1) {
|
||||
copyStreams.splice(index, 1);
|
||||
}
|
||||
|
||||
return {
|
||||
"list": list,
|
||||
"hasNextPage": false
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [...sortedStreams, ...copyStreams];
|
||||
}
|
||||
|
||||
async getPopular(page) {
|
||||
return await this.formList('?sort={"rate": -1 }')
|
||||
// Extracts the streams url for different resolutions from a hls stream.
|
||||
async extractStreams(url) {
|
||||
const response = await new Client().get(url);
|
||||
const body = response.body;
|
||||
const lines = body.split("\n");
|
||||
var streams = [
|
||||
{
|
||||
url: url,
|
||||
originalUrl: url,
|
||||
quality: `Auto`,
|
||||
},
|
||||
];
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (lines[i].startsWith("#EXT-X-STREAM-INF:")) {
|
||||
var resolution = lines[i].match(/RESOLUTION=(\d+x\d+)/)[1];
|
||||
var m3u8Url = lines[i + 1].trim();
|
||||
m3u8Url = url.replace("master.m3u8", m3u8Url);
|
||||
|
||||
streams.push({
|
||||
url: m3u8Url,
|
||||
originalUrl: m3u8Url,
|
||||
quality: resolution,
|
||||
});
|
||||
}
|
||||
}
|
||||
return streams;
|
||||
}
|
||||
|
||||
async getLatestUpdates(page) {
|
||||
var slug = '?sort={"postDate": -1 }';
|
||||
// For anime episode video list
|
||||
async getVideoList(url) {
|
||||
var streams = [];
|
||||
var jsonData = await this.extractFromUrl(`/watch/${url}`);
|
||||
var epData = jsonData.episode;
|
||||
streams = await this.extractStreams(epData.streamLink);
|
||||
|
||||
var choice = this.getPreference("animeparadise_pref_latest_tab");
|
||||
if (choice === "recent_ep") slug = 'ep/recently-added';
|
||||
var subtitles = [];
|
||||
epData.subData.forEach((sub) => {
|
||||
subtitles.push({
|
||||
"label": sub.label,
|
||||
"file": `${this.source.apiUrl}/stream/file/${sub.src}`,
|
||||
});
|
||||
});
|
||||
|
||||
return await this.formList(slug)
|
||||
}
|
||||
async search(query, page, filters) {
|
||||
var season = filters[0].values[filters[0].state].value
|
||||
var year = filters[1].values[filters[1].state].value
|
||||
streams[0].subtitles = subtitles;
|
||||
|
||||
var genre = "genre[]="
|
||||
for (var filter of filters[2].state) {
|
||||
if (filter.state == true)
|
||||
genre += `${filter.value}&genre[]=`
|
||||
}
|
||||
var slug = `search?q=${query}&year=${year}&season=${season}&${genre}`
|
||||
return await this.formList(slug);
|
||||
}
|
||||
statusCode(status) {
|
||||
return {
|
||||
"current": 0,
|
||||
"finished": 1,
|
||||
}[status] ?? 5;
|
||||
}
|
||||
return streams;
|
||||
}
|
||||
|
||||
async getDetail(url) {
|
||||
var link = this.source.baseUrl + `/anime/${url}`
|
||||
var jsonData = await this.extractFromUrl(`/anime/${url}`)
|
||||
jsonData = jsonData.data
|
||||
var details = {}
|
||||
var chapters = []
|
||||
details.imageUrl = jsonData.posterImage.original
|
||||
details.description = jsonData.synopsys
|
||||
details.genre = jsonData.genres
|
||||
details.status = this.statusCode(jsonData.status)
|
||||
var id = jsonData._id
|
||||
var epAPI = await this.requestAPI(`anime/${id}/episode`)
|
||||
epAPI.data.forEach(ep => {
|
||||
var epName = `E${ep.number}: ${ep.title}`;
|
||||
var epUrl = `${ep.uid}?origin=${ep.origin}`
|
||||
chapters.push({ name: epName, url: epUrl })
|
||||
})
|
||||
details.chapters = chapters.reverse();
|
||||
return details;
|
||||
}
|
||||
// Sorts streams based on user preference.
|
||||
async sortStreams(streams) {
|
||||
var sortedStreams = [];
|
||||
var copyStreams = streams.slice()
|
||||
addCatogory(arr, typ) {
|
||||
arr = arr.map((x) => ({ type_name: typ, name: x, value: x }));
|
||||
arr.unshift({
|
||||
type_name: typ,
|
||||
name: "All",
|
||||
value: "",
|
||||
});
|
||||
return arr;
|
||||
}
|
||||
|
||||
var pref = await this.getPreference("animeparadise_pref_video_resolution");
|
||||
for (var stream of streams) {
|
||||
getFilterList() {
|
||||
var seasons = ["Winter", "Spring", "Summer", "Fall"];
|
||||
|
||||
if (stream.quality.indexOf(pref) > -1) {
|
||||
sortedStreams.push(stream);
|
||||
var index = copyStreams.indexOf(stream);
|
||||
if (index > -1) {
|
||||
copyStreams.splice(index, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [...sortedStreams, ...copyStreams]
|
||||
}
|
||||
const currentYear = new Date().getFullYear();
|
||||
var years = Array.from({ length: currentYear - 1939 }, (_, i) =>
|
||||
(i + 1940).toString()
|
||||
).reverse();
|
||||
|
||||
// Extracts the streams url for different resolutions from a hls stream.
|
||||
async extractStreams(url) {
|
||||
const response = await new Client().get(url);
|
||||
const body = response.body;
|
||||
const lines = body.split('\n');
|
||||
var streams = [{
|
||||
url: url,
|
||||
originalUrl: url,
|
||||
quality: `Auto`,
|
||||
}];
|
||||
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 }));
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (lines[i].startsWith('#EXT-X-STREAM-INF:')) {
|
||||
var resolution = lines[i].match(/RESOLUTION=(\d+x\d+)/)[1];
|
||||
var m3u8Url = lines[i + 1].trim();
|
||||
m3u8Url = url.replace("master.m3u8", m3u8Url)
|
||||
return [
|
||||
{
|
||||
type_name: "SelectFilter",
|
||||
name: "Season",
|
||||
state: 0,
|
||||
values: this.addCatogory(seasons, "SelectOption"),
|
||||
},
|
||||
{
|
||||
type_name: "SelectFilter",
|
||||
name: "Year",
|
||||
state: 0,
|
||||
values: this.addCatogory(years, "SelectOption"),
|
||||
},
|
||||
{
|
||||
type_name: "GroupFilter",
|
||||
name: "Genres",
|
||||
state: genres,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
streams.push({
|
||||
url: m3u8Url,
|
||||
originalUrl: m3u8Url,
|
||||
quality: resolution
|
||||
});
|
||||
}
|
||||
}
|
||||
return streams
|
||||
|
||||
}
|
||||
|
||||
// For anime episode video list
|
||||
async getVideoList(url) {
|
||||
var streams = []
|
||||
var jsonData = await this.extractFromUrl(`/watch/${url}`);
|
||||
var epData = jsonData.episode
|
||||
streams = await this.extractStreams(epData.streamLink)
|
||||
|
||||
var subtitles = []
|
||||
epData.subData.forEach(sub => {
|
||||
subtitles.push({
|
||||
"label": sub.label,
|
||||
"file": `${this.source.apiUrl}/stream/file/${sub.src}`,
|
||||
});
|
||||
})
|
||||
|
||||
streams[0].subtitles = subtitles
|
||||
|
||||
return streams
|
||||
|
||||
}
|
||||
|
||||
addCatogory(arr, typ) {
|
||||
arr = arr.map(x => ({ type_name: typ, name: x, value: x }))
|
||||
arr.unshift({
|
||||
type_name: typ,
|
||||
name: 'All',
|
||||
value: ''
|
||||
})
|
||||
return arr
|
||||
}
|
||||
|
||||
getFilterList() {
|
||||
var seasons = ["Winter", "Spring", "Summer", "Fall"]
|
||||
|
||||
const currentYear = new Date().getFullYear();
|
||||
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 }))
|
||||
|
||||
return [
|
||||
{
|
||||
type_name: "SelectFilter",
|
||||
name: "Season",
|
||||
state: 0,
|
||||
values: this.addCatogory(seasons, "SelectOption")
|
||||
}, {
|
||||
type_name: "SelectFilter",
|
||||
name: "Year",
|
||||
state: 0,
|
||||
values: this.addCatogory(years, "SelectOption")
|
||||
}, {
|
||||
type_name: "GroupFilter",
|
||||
name: "Genres",
|
||||
state: genres
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
getSourcePreferences() {
|
||||
return [{
|
||||
key: 'animeparadise_pref_latest_tab',
|
||||
listPreference: {
|
||||
title: 'Latest tab category',
|
||||
summary: 'Anime list to be shown in latest tab',
|
||||
valueIndex: 0,
|
||||
entries: ["Recently added anime", "Recently added episode"],
|
||||
entryValues: ["recent_ani", "recent_ep"]
|
||||
}
|
||||
}, {
|
||||
key: 'animeparadise_pref_video_resolution',
|
||||
listPreference: {
|
||||
title: 'Preferred video resolution',
|
||||
summary: '',
|
||||
valueIndex: 0,
|
||||
entries: ["Auto", "1080p", "720p", "360p"],
|
||||
entryValues: ["auto", "1080", "720", "360"]
|
||||
}
|
||||
getSourcePreferences() {
|
||||
return [
|
||||
{
|
||||
key: "animeparadise_pref_latest_tab",
|
||||
listPreference: {
|
||||
title: "Latest tab category",
|
||||
summary: "Anime list to be shown in latest tab",
|
||||
valueIndex: 0,
|
||||
entries: ["Recently added anime", "Recently added episode"],
|
||||
entryValues: ["recent_ani", "recent_ep"],
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "animeparadise_pref_video_resolution",
|
||||
listPreference: {
|
||||
title: "Preferred video resolution",
|
||||
summary: "",
|
||||
valueIndex: 0,
|
||||
entries: ["Auto", "1080p", "720p", "360p"],
|
||||
entryValues: ["auto", "1080", "720", "360"],
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,267 +1,300 @@
|
||||
const mangayomiSources = [{
|
||||
const mangayomiSources = [
|
||||
{
|
||||
"name": "AnimeZ",
|
||||
"lang": "en",
|
||||
"baseUrl": "https://animez.org",
|
||||
"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",
|
||||
"itemType": 1,
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.2",
|
||||
"pkgPath": "anime/src/en/animez.js"
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
class DefaultExtension extends MProvider {
|
||||
constructor() {
|
||||
super();
|
||||
this.client = new Client();
|
||||
}
|
||||
constructor() {
|
||||
super();
|
||||
this.client = new Client();
|
||||
}
|
||||
|
||||
getHeaders(url) {
|
||||
return {
|
||||
"Referer": this.source.baseUrl,
|
||||
getHeaders(url) {
|
||||
return {
|
||||
"Referer": this.source.baseUrl,
|
||||
};
|
||||
}
|
||||
|
||||
getPreference(key) {
|
||||
return new SharedPreferences().get(key);
|
||||
}
|
||||
|
||||
async request(slug) {
|
||||
var url = this.source.baseUrl + slug;
|
||||
var res = await this.client.get(url, this.getHeaders());
|
||||
return new Document(res.body);
|
||||
}
|
||||
async page(slug) {
|
||||
var body = await this.request(slug);
|
||||
var list = [];
|
||||
var hasNextPage = false;
|
||||
|
||||
var animes = body.select("li.TPostMv");
|
||||
animes.forEach((anime) => {
|
||||
var link = anime.selectFirst("a").getHref;
|
||||
var name = anime.selectFirst("h2.Title").text;
|
||||
var imageUrl =
|
||||
this.source.baseUrl + "/" + anime.selectFirst("img").getSrc;
|
||||
|
||||
list.push({ name, link, imageUrl });
|
||||
});
|
||||
|
||||
var paginations = body.select(".pagination > li");
|
||||
hasNextPage =
|
||||
paginations[paginations.length - 1].text == "Last" ? true : false;
|
||||
|
||||
return { list, hasNextPage };
|
||||
}
|
||||
|
||||
sortByPref(key) {
|
||||
var sort = parseInt(this.getPreference(key));
|
||||
var sortBy = "hot";
|
||||
switch (sort) {
|
||||
case 1: {
|
||||
sortBy = "lastest-chap";
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
sortBy = "hot";
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
sortBy = "lastest-manga";
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
sortBy = "top-manga";
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
sortBy = "top-month";
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
sortBy = "top-week";
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
sortBy = "top-day";
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
sortBy = "follow";
|
||||
break;
|
||||
}
|
||||
case 9: {
|
||||
sortBy = "comment";
|
||||
break;
|
||||
}
|
||||
case 10: {
|
||||
sortBy = "num-chap";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sortBy;
|
||||
}
|
||||
|
||||
async getPopular(page) {
|
||||
var sortBy = this.sortByPref("animez_pref_popular_section");
|
||||
var slug = `/?act=search&f[status]=all&f[sortby]=${sortBy}&&pageNum=${page}`;
|
||||
return await this.page(slug);
|
||||
}
|
||||
get supportsLatest() {
|
||||
throw new Error("supportsLatest not implemented");
|
||||
}
|
||||
async getLatestUpdates(page) {
|
||||
var sortBy = this.sortByPref("animez_pref_latest_section");
|
||||
var slug = `/?act=search&f[status]=all&f[sortby]=${sortBy}&&pageNum=${page}`;
|
||||
return await this.page(slug);
|
||||
}
|
||||
async search(query, page, filters) {
|
||||
var slug = `/?act=search&f[status]=all&f[keyword]=${query}&&pageNum=${page}`;
|
||||
return await this.page(slug);
|
||||
}
|
||||
async getDetail(url) {
|
||||
var baseUrl = this.source.baseUrl;
|
||||
if (url.includes(baseUrl)) url = url.replace(baseUrl, "");
|
||||
var link = +url;
|
||||
var body = await this.request(url);
|
||||
var name = body.selectFirst("#title-detail-manga").text;
|
||||
var animeId = body.selectFirst("#title-detail-manga").attr("data-manga");
|
||||
var genre = [];
|
||||
body
|
||||
.select("li.AAIco-adjust")[3]
|
||||
.select("a")
|
||||
.forEach((g) => genre.push(g.text));
|
||||
var description = body.selectFirst("#summary_shortened").text;
|
||||
|
||||
var chapters = [];
|
||||
var chapLen = 0;
|
||||
var pageNum = 1;
|
||||
var hasNextPage = true;
|
||||
while (hasNextPage) {
|
||||
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 parsedBody = JSON.parse(pageBody.html);
|
||||
var nav = parsedBody.nav;
|
||||
if (nav == null) {
|
||||
// if "nav" doesnt exists there is no next page
|
||||
hasNextPage = false;
|
||||
} else {
|
||||
var navLi = new Document(nav).select(".page-link.next").length;
|
||||
if (navLi > 0) {
|
||||
// if "nav" exists and has li.next then there is next page
|
||||
pageNum++;
|
||||
} else {
|
||||
// if "nav" exists and doesn't have li.next then there is no next page
|
||||
hasNextPage = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getPreference(key) {
|
||||
return new SharedPreferences().get(key);
|
||||
}
|
||||
var list_chap = new Document(parsedBody.list_chap).select(
|
||||
"li.wp-manga-chapter"
|
||||
);
|
||||
|
||||
async request(slug) {
|
||||
var url = this.source.baseUrl + slug
|
||||
var res = await this.client.get(url, this.getHeaders());
|
||||
return new Document(res.body);
|
||||
}
|
||||
async page(slug) {
|
||||
var body = await this.request(slug)
|
||||
var list = []
|
||||
var hasNextPage = false;
|
||||
|
||||
var animes = body.select("li.TPostMv")
|
||||
animes.forEach(anime => {
|
||||
var link = anime.selectFirst("a").getHref
|
||||
var name = anime.selectFirst('h2.Title').text;
|
||||
var imageUrl = this.source.baseUrl +"/"+ anime.selectFirst('img').getSrc;
|
||||
|
||||
list.push({ name, link, imageUrl });
|
||||
});
|
||||
|
||||
var paginations = body.select(".pagination > li")
|
||||
hasNextPage = paginations[paginations.length - 1].text == "Last" ? true : false
|
||||
|
||||
return { list, hasNextPage }
|
||||
}
|
||||
|
||||
sortByPref(key) {
|
||||
var sort = parseInt(this.getPreference(key))
|
||||
var sortBy = "hot"
|
||||
switch (sort) {
|
||||
case 1: {
|
||||
sortBy = "lastest-chap"
|
||||
break;
|
||||
} case 2: {
|
||||
sortBy = "hot"
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
sortBy = "lastest-manga"
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
sortBy = "top-manga"
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
sortBy = "top-month"
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
sortBy = "top-week"
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
sortBy = "top-day"
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
sortBy = "follow"
|
||||
break;
|
||||
}
|
||||
case 9: {
|
||||
sortBy = "comment"
|
||||
break;
|
||||
}
|
||||
case 10: {
|
||||
sortBy = "num-chap"
|
||||
break;
|
||||
}
|
||||
list_chap.forEach((chapter) => {
|
||||
var a = chapter.selectFirst("a");
|
||||
var title = a.text;
|
||||
var epLink = a.getHref;
|
||||
var scanlator = "Sub";
|
||||
if (title.indexOf("Dub") > 0) {
|
||||
title = title.replace("-Dub", "");
|
||||
scanlator = "Dub";
|
||||
}
|
||||
return sortBy;
|
||||
|
||||
}
|
||||
|
||||
async getPopular(page) {
|
||||
var sortBy = this.sortByPref("animez_pref_popular_section")
|
||||
var slug = `/?act=search&f[status]=all&f[sortby]=${sortBy}&&pageNum=${page}`
|
||||
return await this.page(slug)
|
||||
|
||||
}
|
||||
get supportsLatest() {
|
||||
throw new Error("supportsLatest not implemented");
|
||||
}
|
||||
async getLatestUpdates(page) {
|
||||
var sortBy = this.sortByPref("animez_pref_latest_section")
|
||||
var slug = `/?act=search&f[status]=all&f[sortby]=${sortBy}&&pageNum=${page}`
|
||||
return await this.page(slug)
|
||||
}
|
||||
async search(query, page, filters) {
|
||||
var slug = `/?act=search&f[status]=all&f[keyword]=${query}&&pageNum=${page}`
|
||||
return await this.page(slug)
|
||||
}
|
||||
async getDetail(url) {
|
||||
var link = this.source.baseUrl + url;
|
||||
var body = await this.request(url);
|
||||
var name = body.selectFirst("#title-detail-manga").text
|
||||
var animeId = body.selectFirst("#title-detail-manga").attr("data-manga")
|
||||
var genre = []
|
||||
body.select("li.AAIco-adjust")[3].select("a").forEach(g => genre.push(g.text))
|
||||
var description = body.selectFirst("#summary_shortened").text
|
||||
|
||||
|
||||
var chapters = []
|
||||
var chapLen = 0
|
||||
var pageNum = 1
|
||||
var hasNextPage = true;
|
||||
while(hasNextPage) {
|
||||
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 parsedBody = JSON.parse(pageBody.html);
|
||||
var nav = parsedBody.nav
|
||||
if(nav==null){ // if "nav" doesnt exists there is no next page
|
||||
hasNextPage = false;
|
||||
|
||||
}else{
|
||||
var navLi = new Document(nav).select(".page-link.next").length
|
||||
if(navLi>0){ // if "nav" exists and has li.next then there is next page
|
||||
pageNum++;
|
||||
}else{// if "nav" exists and doesn't have li.next then there is no next page
|
||||
hasNextPage = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var list_chap = new Document(parsedBody.list_chap).select('li.wp-manga-chapter')
|
||||
|
||||
list_chap.forEach(chapter => {
|
||||
var a = chapter.selectFirst("a")
|
||||
var title = a.text
|
||||
var epLink = a.getHref
|
||||
var scanlator = "Sub"
|
||||
if(title.indexOf("Dub")>0){
|
||||
title = title.replace("-Dub","")
|
||||
scanlator = "Dub"
|
||||
|
||||
}
|
||||
title = title.indexOf("Movie") > -1? title : `Episode ${title}`
|
||||
var epData = {
|
||||
name:title,
|
||||
url:epLink,
|
||||
scanlator
|
||||
}
|
||||
if(chapLen>0){
|
||||
var pos = chapLen -1
|
||||
var lastEntry = chapters[pos]
|
||||
if(lastEntry.name == epData.name){ // if last entries name is same then append url and scanlator to last entry
|
||||
chapters.pop() // remove the last entry
|
||||
epData.url = `${epData.url}||${lastEntry.url}`
|
||||
epData.scanlator = `${lastEntry.scanlator}, ${epData.scanlator}`
|
||||
chapLen = pos; // since the last entry is removed the chapLen will decrease
|
||||
}
|
||||
}
|
||||
|
||||
chapters.push(epData)
|
||||
chapLen++;
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
link,
|
||||
description,
|
||||
chapters,
|
||||
genre,
|
||||
title = title.indexOf("Movie") > -1 ? title : `Episode ${title}`;
|
||||
var epData = {
|
||||
name: title,
|
||||
url: epLink,
|
||||
scanlator,
|
||||
};
|
||||
}
|
||||
|
||||
// Sorts streams based on user preference.
|
||||
sortStreams(streams) {
|
||||
var sortedStreams = [];
|
||||
|
||||
var copyStreams = streams.slice()
|
||||
var pref = this.getPreference("animez_pref_stream_audio");
|
||||
for (var stream of streams) {
|
||||
if (stream.quality.indexOf(pref) > -1) {
|
||||
sortedStreams.push(stream);
|
||||
var index = copyStreams.indexOf(stream);
|
||||
if (index > -1) {
|
||||
copyStreams.splice(index, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [...sortedStreams, ...copyStreams]
|
||||
}
|
||||
|
||||
// For anime episode video list
|
||||
async getVideoList(url) {
|
||||
var linkSlugs = url.split("||")
|
||||
var streams = [];
|
||||
for(var slug of linkSlugs){
|
||||
var body = await this.request(slug)
|
||||
var iframeSrc = body.selectFirst("iframe").getSrc
|
||||
var streamLink = iframeSrc.replace("/embed/","/anime/")
|
||||
var audio = slug.indexOf("dub-") > -1 ? "Dub" : "Sub"
|
||||
|
||||
streams.push({
|
||||
url: streamLink,
|
||||
originalUrl: streamLink,
|
||||
quality: audio,
|
||||
})
|
||||
if (chapLen > 0) {
|
||||
var pos = chapLen - 1;
|
||||
var lastEntry = chapters[pos];
|
||||
if (lastEntry.name == epData.name) {
|
||||
// if last entries name is same then append url and scanlator to last entry
|
||||
chapters.pop(); // remove the last entry
|
||||
epData.url = `${epData.url}||${lastEntry.url}`;
|
||||
epData.scanlator = `${lastEntry.scanlator}, ${epData.scanlator}`;
|
||||
chapLen = pos; // since the last entry is removed the chapLen will decrease
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return sortStreams(streams);
|
||||
|
||||
|
||||
chapters.push(epData);
|
||||
chapLen++;
|
||||
});
|
||||
}
|
||||
|
||||
getSourcePreferences() {
|
||||
return [{
|
||||
key: 'animez_pref_popular_section',
|
||||
listPreference: {
|
||||
title: 'Preferred popular content',
|
||||
summary: '',
|
||||
valueIndex: 1,
|
||||
entries: ["Latest update", "Hot", "New releases", "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: {
|
||||
title: 'Preferred latest content',
|
||||
summary: '',
|
||||
valueIndex: 0,
|
||||
entries: ["Latest update", "Hot", "New releases", "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: {
|
||||
title: 'Preferred stream audio',
|
||||
summary: '',
|
||||
valueIndex: 0,
|
||||
entries: ["Sub","Dub"],
|
||||
entryValues: ["Sub","Dub"],
|
||||
}
|
||||
},]
|
||||
|
||||
return {
|
||||
link,
|
||||
description,
|
||||
chapters,
|
||||
genre,
|
||||
};
|
||||
}
|
||||
|
||||
// Sorts streams based on user preference.
|
||||
sortStreams(streams) {
|
||||
var sortedStreams = [];
|
||||
|
||||
var copyStreams = streams.slice();
|
||||
var pref = this.getPreference("animez_pref_stream_audio");
|
||||
for (var stream of streams) {
|
||||
if (stream.quality.indexOf(pref) > -1) {
|
||||
sortedStreams.push(stream);
|
||||
var index = copyStreams.indexOf(stream);
|
||||
if (index > -1) {
|
||||
copyStreams.splice(index, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [...sortedStreams, ...copyStreams];
|
||||
}
|
||||
|
||||
// For anime episode video list
|
||||
async getVideoList(url) {
|
||||
var linkSlugs = url.split("||");
|
||||
var streams = [];
|
||||
for (var slug of linkSlugs) {
|
||||
var body = await this.request(slug);
|
||||
var iframeSrc = body.selectFirst("iframe").getSrc;
|
||||
var streamLink = iframeSrc.replace("/embed/", "/anime/");
|
||||
var audio = slug.indexOf("dub-") > -1 ? "Dub" : "Sub";
|
||||
|
||||
streams.push({
|
||||
url: streamLink,
|
||||
originalUrl: streamLink,
|
||||
quality: audio,
|
||||
});
|
||||
}
|
||||
|
||||
return sortStreams(streams);
|
||||
}
|
||||
|
||||
getSourcePreferences() {
|
||||
return [
|
||||
{
|
||||
key: "animez_pref_popular_section",
|
||||
listPreference: {
|
||||
title: "Preferred popular content",
|
||||
summary: "",
|
||||
valueIndex: 1,
|
||||
entries: [
|
||||
"Latest update",
|
||||
"Hot",
|
||||
"New releases",
|
||||
"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: {
|
||||
title: "Preferred latest content",
|
||||
summary: "",
|
||||
valueIndex: 0,
|
||||
entries: [
|
||||
"Latest update",
|
||||
"Hot",
|
||||
"New releases",
|
||||
"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: {
|
||||
title: "Preferred stream audio",
|
||||
summary: "",
|
||||
valueIndex: 0,
|
||||
entries: ["Sub", "Dub"],
|
||||
entryValues: ["Sub", "Dub"],
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ const mangayomiSources = [{
|
||||
"iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://gojo.wtf/",
|
||||
"typeSource": "multi",
|
||||
"itemType": 1,
|
||||
"version": "0.0.5",
|
||||
"version": "0.0.6",
|
||||
"pkgPath": "anime/src/en/gojo.js"
|
||||
}];
|
||||
|
||||
@@ -103,6 +103,9 @@ class DefaultExtension extends MProvider {
|
||||
|
||||
|
||||
async getDetail(url) {
|
||||
var linkSlug = `${this.source.baseUrl}/watch/`
|
||||
if (url.includes(linkSlug)) url = url.replace(linkSlug, "");
|
||||
|
||||
var anilistId = url
|
||||
var res = await this.gojoAPI(`/info/${anilistId}`)
|
||||
if (res == null) {
|
||||
@@ -111,7 +114,7 @@ class DefaultExtension extends MProvider {
|
||||
var name = this.getTitle(res.title)
|
||||
var imageUrl = res.coverImage.large
|
||||
var description = res.description;
|
||||
var link = `${this.source.baseUrl}/watch/${anilistId}`
|
||||
var link = `${linkSlug}${anilistId}`
|
||||
var genres = res.genres
|
||||
var status = (() => {
|
||||
switch (res.status) {
|
||||
|
||||
@@ -5,7 +5,7 @@ const mangayomiSources = [{
|
||||
"apiUrl": "",
|
||||
"iconUrl": "https://www.google.com/s2/favicons?sz=128&domain=https://sudatchi.com",
|
||||
"typeSource": "single",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.1",
|
||||
"dateFormat": "",
|
||||
"dateFormatLocale": "",
|
||||
"itemType": 1,
|
||||
@@ -148,8 +148,11 @@ class DefaultExtension extends MProvider {
|
||||
|
||||
|
||||
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 link = `https://sudatchi.com/anime/${url}`
|
||||
var link = `${linkSlug}${url}`
|
||||
var details = await this.requestApi(`/anime/${url}`);
|
||||
var titles = details.title
|
||||
var name = titles.romaji
|
||||
|
||||
Reference in New Issue
Block a user