Update anime/animeav1/source.js

This commit is contained in:
2025-12-25 03:17:30 +01:00
parent ae8d8c7b3e
commit 7abb08cc87

View File

@@ -6,55 +6,67 @@ class AnimeAV1 {
} }
getSettings() { getSettings() {
return { return { episodeServers: ["HLS", "HLS-DUB"], supportsDub: true };
episodeServers: ["HLS", "HLS-DUB"],
supportsDub: true,
};
} }
async search(query) { _nativeFetch(url, method, headers, body) {
const raw = Native.fetch(String(url), method || "GET", JSON.stringify(headers || {}), body == null ? "" : String(body));
try { return JSON.parse(raw || "{}"); } catch (e) { return { ok: false, status: 0, headers: {}, body: "" }; }
}
_getText(url, headers) {
const res = this._nativeFetch(url, "GET", headers, "");
return String(res.body || "");
}
_getJson(url, headers) {
const res = this._nativeFetch(url, "GET", headers, "");
try { return JSON.parse(String(res.body || "{}")); } catch (e) { return {}; }
}
_postJson(url, headers, obj) {
const res = this._nativeFetch(url, "POST", headers, JSON.stringify(obj || {}));
try { return JSON.parse(String(res.body || "{}")); } catch (e) { return null; }
}
search(query) {
const q = const q =
(query && typeof query === "object" && query.query) (query && typeof query === "object" && query.query) ? String(query.query)
? String(query.query)
: (typeof query === "string" ? query : ""); : (typeof query === "string" ? query : "");
if (!q.trim()) return []; if (!q.trim()) return [];
const res = await fetch(`${this.api}/api/search`, { const data = this._postJson(
method: "POST", `${this.api}/api/search`,
headers: { "Content-Type": "application/json" }, { "Content-Type": "application/json" },
body: JSON.stringify({ query: q }), { query: q }
}); );
if (!res.ok) return [];
const data = await res.json();
if (!Array.isArray(data)) return []; if (!Array.isArray(data)) return [];
return data return data.map((anime) => {
.map(anime => { const slug = anime && anime.slug ? String(anime.slug) : "";
if (!anime || !anime.slug) return null; if (!slug) return null;
return { return {
id: anime.slug, id: slug,
title: anime.title || "Unknown", title: (anime && anime.title) ? String(anime.title) : "Unknown",
url: `${this.api}/media/${anime.slug}`, url: `${this.api}/media/${slug}`,
subOrDub: "both", subOrDub: "both",
}; };
}) }).filter(Boolean);
.filter(Boolean);
} }
async getMetadata(id) { getMetadata(id) {
const slug = String(id || "").trim(); const slug = String(id || "").trim();
if (!slug) throw new Error("Missing id"); if (!slug) throw new Error("Missing id");
const html = await fetch(`${this.api}/media/${slug}`).then(r => r.text()); const html = this._getText(`${this.api}/media/${slug}`, {});
const parsed = this.parseSvelteData(html); const parsed = this.parseSvelteData(html);
const media = parsed.find(x => x?.data?.media)?.data?.media || {}; const media = (parsed.find(x => x && x.data && x.data.media)?.data?.media) || {};
let image = null; let image = null;
const imageMatch = html.match(/<img[^>]*class="aspect-poster[^"]*"[^>]*src="([^"]+)"/i); const imageMatch = html.match(/<img[^>]*class="aspect-poster[^"]*"[^>]*src="([^"]+)"/i);
if (imageMatch) image = imageMatch[1]; if (imageMatch && imageMatch[1]) image = imageMatch[1];
let year = null; let year = null;
if (media.startDate) { if (media.startDate) {
@@ -72,38 +84,42 @@ class AnimeAV1 {
studio: "Unknown", studio: "Unknown",
score: media.score || 0, score: media.score || 0,
year, year,
genres: (media.genres || []).map(g => g?.name).filter(Boolean), genres: (media.genres || []).map(g => g && g.name ? g.name : "").filter(Boolean),
image, image,
}; };
} }
async findEpisodes(id) { findEpisodes(id) {
const slug = String(id || "").trim(); const slug = String(id || "").trim();
if (!slug) throw new Error("Missing id"); if (!slug) throw new Error("Missing id");
const html = await fetch(`${this.api}/media/${slug}`).then(r => r.text()); const html = this._getText(`${this.api}/media/${slug}`, {});
const parsed = this.parseSvelteData(html); const parsed = this.parseSvelteData(html);
const media = parsed.find(x => x?.data?.media)?.data?.media; const media = (parsed.find(x => x && x.data && x.data.media)?.data?.media) || null;
if (!media || !Array.isArray(media.episodes)) if (!media || !Array.isArray(media.episodes)) throw new Error("No episodes");
throw new Error("No episodes");
return media.episodes.map((ep, i) => { return media.episodes.map((ep, i) => {
const n = ep?.number ?? (i + 1); const nRaw = ep && ep.number != null ? ep.number : (i + 1);
const n = Number(nRaw);
const num = Number.isFinite(n) ? n : (i + 1);
return { return {
id: `${media.slug || slug}$${n}`, id: `${media.slug || slug}$${num}`,
number: n, number: num,
title: ep?.title || `Episode ${n}`, title: (ep && ep.title) ? String(ep.title) : `Episode ${num}`,
url: `${this.api}/media/${media.slug || slug}/${n}`, url: `${this.api}/media/${media.slug || slug}/${num}`,
}; };
}); });
} }
async findEpisodeServer(episodeOrId, server) { findEpisodeServer(episodeOrId, server) {
const ep = let ep = episodeOrId;
typeof episodeOrId === "string" if (typeof ep === "string") { try { ep = JSON.parse(ep); } catch (e) {} }
? (() => { try { return JSON.parse(episodeOrId); } catch { return { id: episodeOrId }; } })() ep = ep || {};
: episodeOrId;
const srv = String(server || "").trim();
if (srv !== "HLS" && srv !== "HLS-DUB") throw new Error("Unknown server");
const pageUrl = const pageUrl =
ep.url || ep.url ||
@@ -113,38 +129,28 @@ class AnimeAV1 {
if (!pageUrl) throw new Error("Missing episode url"); if (!pageUrl) throw new Error("Missing episode url");
const html = await fetch(pageUrl, { const html = this._getText(pageUrl, { Referer: `${this.api}/` });
headers: { Referer: `${this.api}/` },
}).then(r => r.text());
const parsed = this.parseSvelteData(html); const parsed = this.parseSvelteData(html);
const entry = parsed.find(x => x?.data?.embeds) || parsed[3];
const embeds = entry?.data?.embeds;
const entry = parsed.find(x => x && x.data && x.data.embeds) || parsed[3];
const embeds = entry && entry.data ? entry.data.embeds : null;
if (!embeds) throw new Error("No embeds"); if (!embeds) throw new Error("No embeds");
const list = const list = (srv === "HLS") ? (embeds.SUB || []) : (embeds.DUB || []);
server === "HLS" ? embeds.SUB : if (!Array.isArray(list) || !list.length) throw new Error("No mirrors");
server === "HLS-DUB" ? embeds.DUB :
null;
if (!Array.isArray(list) || !list.length) const match = list.find(m => String((m && m.url) || "").includes("zilla-networks.com/play/"));
throw new Error("No mirrors"); if (!match || !match.url) throw new Error("No valid source");
const match = list.find(m => String(m?.url || "").includes("zilla-networks.com/play/"));
if (!match) throw new Error("No valid source");
return { return {
server, server: srv,
headers: { Referer: pageUrl }, headers: { Referer: pageUrl },
videoSources: [ videoSources: [{
{
url: String(match.url).replace("/play/", "/m3u8/"), url: String(match.url).replace("/play/", "/m3u8/"),
type: "m3u8", type: "m3u8",
quality: "auto", quality: "auto",
subtitles: [], subtitles: []
}, }]
],
}; };
} }
@@ -159,10 +165,8 @@ class AnimeAV1 {
try { try {
return new Function(`"use strict"; return (${jsArray});`)(); return new Function(`"use strict"; return (${jsArray});`)();
} catch { } catch (e) {
const cleaned = jsArray const cleaned = jsArray.replace(/\bvoid 0\b/g, "null").replace(/undefined/g, "null");
.replace(/\bvoid 0\b/g, "null")
.replace(/undefined/g, "null");
return new Function(`"use strict"; return (${cleaned});`)(); return new Function(`"use strict"; return (${cleaned});`)();
} }
} }