mirror of
https://github.com/kodjodevf/mangayomi-extensions.git
synced 2026-02-14 10:51:17 +00:00
Merge pull request #159 from Swakshan/extension/animeparadise
Source: Animeparadise
This commit is contained in:
241
javascript/anime/src/en/animeparadise.js
Normal file
241
javascript/anime/src/en/animeparadise.js
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
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",
|
||||||
|
"typeSource": "single",
|
||||||
|
"itemType": 1,
|
||||||
|
"version": "0.0.1",
|
||||||
|
"pkgPath": "anime/src/en/animeparadise.js"
|
||||||
|
}];
|
||||||
|
|
||||||
|
class DefaultExtension extends MProvider {
|
||||||
|
|
||||||
|
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
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"list": list,
|
||||||
|
"hasNextPage": false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async getPopular(page) {
|
||||||
|
return await this.formList('?sort={"rate": -1 }')
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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()
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [...sortedStreams, ...copyStreams]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user