mirror of
https://github.com/kodjodevf/mangayomi-extensions.git
synced 2026-02-14 10:51:17 +00:00
215 lines
9.1 KiB
JavaScript
215 lines
9.1 KiB
JavaScript
const mangayomiSources = [{
|
|
"name": "NetflixMirror",
|
|
"lang": "all",
|
|
"baseUrl": "https://iosmirror.cc",
|
|
"apiUrl": "",
|
|
"iconUrl": "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/javascript/icon/all.netflixmirror.png",
|
|
"typeSource": "single",
|
|
"isManga": false,
|
|
"version": "0.0.6",
|
|
"dateFormat": "",
|
|
"dateFormatLocale": "",
|
|
"pkgPath": "anime/src/all/netflixmirror.js"
|
|
}];
|
|
|
|
class DefaultExtension extends MProvider {
|
|
async getCookie() {
|
|
const preferences = new SharedPreferences();
|
|
let cookie;
|
|
cookie = preferences.getString("cookie", "");
|
|
const check = await new Client().get(`${this.source.baseUrl}/home`, { "cookie": cookie });
|
|
const elements = new Document(check.body).select(".tray-container, #top10");
|
|
if (elements && elements.length > 0) {
|
|
return cookie;
|
|
}
|
|
const hDoc = new Document((await new Client().get(`${this.source.baseUrl}/home`, { "cookie": "" })).body);
|
|
const addhash = hDoc.selectFirst("body").attr("data-addhash");
|
|
const time = hDoc.selectFirst("body").attr("data-time");
|
|
await new Client().get(`https://userverify.netmirror.app/?fr3=${addhash}&a=y&t=${time}`);
|
|
let body;
|
|
let res;
|
|
do {
|
|
res = await new Client().post(`${this.source.baseUrl}/verify2.php`, { "cookie": "" }, { "verify": addhash });
|
|
body = res.body;
|
|
} while (!body.includes('"statusup":"All Done"'));
|
|
cookie = `ott=nf; hd=on; ${res.headers["set-cookie"]}`;
|
|
preferences.setString("cookie", cookie);
|
|
return cookie;
|
|
}
|
|
async request(url, cookie) {
|
|
cookie = cookie ?? await this.getCookie();
|
|
return (await new Client().get(this.source.baseUrl + url, { "cookie": cookie })).body;
|
|
}
|
|
async getPopular(page) {
|
|
return await this.getPages(await this.request("/home"), ".tray-container, #top10")
|
|
}
|
|
async getLatestUpdates(page) {
|
|
return await this.getPages(await this.request("/home"), ".inner-mob-tray-container")
|
|
}
|
|
async getPages(body, selector) {
|
|
const elements = new Document(body).select(selector);
|
|
const cookie = await this.getCookie();
|
|
const list = [];
|
|
for (const element of elements) {
|
|
const linkElement = element.selectFirst("article, .top10-post");
|
|
const id = linkElement.selectFirst("a").attr("data-post");
|
|
if (id.length > 0) {
|
|
const imageUrl = linkElement.selectFirst(".card-img-container img, .top10-img img").attr("data-src");
|
|
list.push({ name: JSON.parse(await this.request(`/post.php?id=${id}`, cookie)).title, imageUrl, link: id });
|
|
}
|
|
}
|
|
return {
|
|
list: list,
|
|
hasNextPage: false
|
|
}
|
|
}
|
|
async search(query, page, filters) {
|
|
const data = JSON.parse(await this.request(`/search.php?s=${query}`));
|
|
const list = [];
|
|
data.searchResult.map(async (res) => {
|
|
const id = res.id;
|
|
list.push({ name: res.t, imageUrl: `https://img.nfmirrorcdn.top/poster/v/${id}.jpg`, link: id });
|
|
})
|
|
|
|
return {
|
|
list: list,
|
|
hasNextPage: false
|
|
}
|
|
}
|
|
async getDetail(url) {
|
|
const cookie = await this.getCookie();
|
|
const data = JSON.parse(await this.request(`/post.php?id=${url}`, cookie));
|
|
const name = data.title;
|
|
const genre = [data.ua, ...(data.genre || '').split(',').map(g => g.trim())];
|
|
const description = data.desc;
|
|
let episodes = [];
|
|
if (data.episodes[0] === null) {
|
|
episodes.push({ name, url: JSON.stringify({ id: url, name }) });
|
|
} else {
|
|
episodes = data.episodes.map(ep => ({
|
|
name: `${ep.s.replace('S', 'Season ')} ${ep.ep.replace('E', 'Episode ')} : ${ep.t}`,
|
|
url: JSON.stringify({ id: ep.id, name })
|
|
}));
|
|
}
|
|
if (data.nextPageShow === 1) {
|
|
const eps = await this.getEpisodes(name, url, data.nextPageSeason, 2, cookie);
|
|
episodes.push(...eps);
|
|
}
|
|
episodes.reverse();
|
|
if (data.season && data.season.length > 1) {
|
|
let newEpisodes = [];
|
|
const seasonsToProcess = data.season.slice(0, -1);
|
|
await Promise.all(seasonsToProcess.map(async (season) => {
|
|
const eps = await this.getEpisodes(name, url, season.id, 1, cookie);
|
|
newEpisodes.push(...eps);
|
|
}));
|
|
newEpisodes.reverse();
|
|
episodes.push(...newEpisodes);
|
|
|
|
}
|
|
|
|
return {
|
|
description, status: 1, genre, episodes
|
|
};
|
|
}
|
|
async getEpisodes(name, eid, sid, page, cookie) {
|
|
const episodes = [];
|
|
let pg = page;
|
|
while (true) {
|
|
try {
|
|
const data = JSON.parse(await this.request(`/episodes.php?s=${sid}&series=${eid}&page=${pg}`, cookie));
|
|
|
|
data.episodes?.forEach(ep => {
|
|
episodes.push({
|
|
name: `${ep.s.replace('S', 'Season ')} ${ep.ep.replace('E', 'Episode ')} : ${ep.t}`,
|
|
url: JSON.stringify({ id: ep.id, name })
|
|
});
|
|
});
|
|
|
|
if (data.nextPageShow === 0) break;
|
|
pg++;
|
|
} catch (_) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return episodes;
|
|
}
|
|
|
|
|
|
async getVideoList(url) {
|
|
const baseUrl = this.source.baseUrl;
|
|
const urlData = JSON.parse(url);
|
|
const data = JSON.parse(await this.request(`/playlist.php?id=${urlData.id}&t=${urlData.name}`));
|
|
const videoList = [];
|
|
for (const playlist of data) {
|
|
for (const source of playlist.sources) {
|
|
try {
|
|
const subtitles = [];
|
|
playlist.tracks.filter(track => track.kind === 'captions').forEach(track => {
|
|
subtitles.push({
|
|
label: track.label,
|
|
file: track.file
|
|
});
|
|
});
|
|
const link = baseUrl + source.file;
|
|
const headers =
|
|
{
|
|
'Host': link.match(/^(?:https?:\/\/)?(?:www\.)?([^\/]+)/)[1],
|
|
'Origin': baseUrl,
|
|
'Referer': `${baseUrl}/`
|
|
};
|
|
const resp = await new Client().get(link, headers);
|
|
|
|
if (resp.statusCode === 200) {
|
|
const masterPlaylist = resp.body;
|
|
const audios = [];
|
|
masterPlaylist.substringAfter('#EXT-X-MEDIA:').split('#EXT-X-MEDIA:').forEach(it => {
|
|
if (it.includes('TYPE=AUDIO')) {
|
|
const audioInfo = it.substringAfter('TYPE=AUDIO').substringBefore('\n');
|
|
const language = audioInfo.substringAfter('NAME="').substringBefore('"');
|
|
const url = audioInfo.substringAfter('URI="').substringBefore('"');
|
|
audios.push({ file: url, label: language });
|
|
}
|
|
});
|
|
|
|
if (!masterPlaylist.includes('#EXT-X-STREAM-INF:')) {
|
|
if (audios.length === 0) {
|
|
videoList.push({ url: link, quality: source.label, originalUrl: link, subtitles, headers });
|
|
} else {
|
|
videoList.push({ url: link, quality: source.label, originalUrl: link, subtitles, audios, headers });
|
|
}
|
|
} else {
|
|
masterPlaylist.substringAfter('#EXT-X-STREAM-INF:').split('#EXT-X-STREAM-INF:').forEach(it => {
|
|
|
|
const quality = `${it.substringAfter('RESOLUTION=').substringAfter('x').substringBefore(',')}p (${source.label})`;
|
|
let videoUrl = it.substringAfter('\n').substringBefore('\n');
|
|
|
|
if (!videoUrl.startsWith('http')) {
|
|
videoUrl = resp.request.url.substringBeforeLast('/') + `/${videoUrl}`;
|
|
}
|
|
const headers =
|
|
{
|
|
'Host': videoUrl.match(/^(?:https?:\/\/)?(?:www\.)?([^\/]+)/)[1],
|
|
'Origin': baseUrl,
|
|
'Referer': `${baseUrl}/`
|
|
};
|
|
if (audios.length === 0) {
|
|
videoList.push({ url: videoUrl, quality, originalUrl: videoUrl, subtitles, headers });
|
|
} else {
|
|
videoList.push({ url: videoUrl, quality, originalUrl: videoUrl, subtitles, audios, headers });
|
|
}
|
|
|
|
});
|
|
}
|
|
}
|
|
} catch (_) {
|
|
|
|
}
|
|
}
|
|
}
|
|
return videoList;
|
|
}
|
|
|
|
}
|