155 lines
4.6 KiB
JavaScript
155 lines
4.6 KiB
JavaScript
class AniDream {
|
|
constructor() {
|
|
this.baseUrl = "https://anidream.cc";
|
|
this.api = "https://common.anidream.cc/v1";
|
|
this.type = "anime-board";
|
|
this.version = "1.0";
|
|
}
|
|
|
|
getSettings() {
|
|
return {
|
|
episodeServers: ["Default", "Zen"],
|
|
supportsDub: false,
|
|
};
|
|
}
|
|
|
|
async search(queryObj) {
|
|
const res = await fetch(
|
|
`${this.api}/search?pageSize=8&query=${encodeURIComponent(queryObj.query)}`,
|
|
{
|
|
headers: {
|
|
accept: "*/*",
|
|
"user-agent":
|
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36",
|
|
},
|
|
}
|
|
);
|
|
|
|
const json = await res.json();
|
|
const series = json?.data?.series ?? [];
|
|
|
|
return series.map((s) => ({
|
|
id: s.id,
|
|
title: s.title,
|
|
url: `https://anidream.cc/series/${s.slug}`,
|
|
subOrDub: "sub",
|
|
}));
|
|
}
|
|
|
|
async findEpisodes(id) {
|
|
const res = await fetch(`${this.api}/series/${id}`, {
|
|
headers: {
|
|
accept: "application/json, text/javascript, */*; q=0.01",
|
|
"accept-language": "es-ES,es;q=0.9",
|
|
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
|
|
referer: "https://anidream.cc/",
|
|
},
|
|
});
|
|
|
|
if (!res.ok) throw new Error(`Error HTTP ${res.status}`);
|
|
|
|
const json = await res.json();
|
|
const episodes = json?.data?.episodes;
|
|
|
|
if (!Array.isArray(episodes)) return [];
|
|
|
|
return episodes.map((ep) => ({
|
|
id: ep.id,
|
|
number: parseInt(ep.number, 10),
|
|
title: ep.title,
|
|
url: `https://anidream.cc/watch/${ep.slug}`,
|
|
}));
|
|
}
|
|
|
|
parseSubtitles(data) {
|
|
if (!data || !Array.isArray(data.subtitles)) return [];
|
|
|
|
return data.subtitles.map((s) => {
|
|
const cleanLang = (s.language_name ?? "")
|
|
.replace(/^Language\s*\(|\)$/g, "")
|
|
.trim();
|
|
|
|
return {
|
|
id: cleanLang,
|
|
url: s.url,
|
|
language: `${cleanLang} - ${s.title ?? ""}`,
|
|
isDefault: s.is_default ?? false,
|
|
};
|
|
});
|
|
}
|
|
|
|
async findEpisodeServer(episodeOrId, server) {
|
|
const headers = {
|
|
"user-agent":
|
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36",
|
|
accept: "*/*",
|
|
};
|
|
|
|
// Default
|
|
if (server.toLowerCase() === "default") {
|
|
const res = await fetch(
|
|
`${this.api}/watch/default/${episodeOrId.id}/`,
|
|
{ headers }
|
|
);
|
|
const json = await res.json();
|
|
|
|
if (!json?.data?.m3u8_url)
|
|
throw new Error("Stream not found at Default");
|
|
|
|
return {
|
|
server: "Default",
|
|
headers: {},
|
|
videoSources: [
|
|
{
|
|
url: json.data.m3u8_url,
|
|
type: "m3u8",
|
|
quality: "auto",
|
|
subtitles: json.data?.subtitles?.length
|
|
? this.parseSubtitles(json.data)
|
|
: [],
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
// Otros servidores (Zen)
|
|
const res = await fetch(`${this.api}/episodes/${episodeOrId.id}/`, {
|
|
headers,
|
|
});
|
|
const json = await res.json();
|
|
const servers = json?.data?.servers ?? [];
|
|
|
|
const target = servers.find(
|
|
(s) => s.server.toLowerCase() === server.toLowerCase()
|
|
);
|
|
if (!target?.access_id)
|
|
throw new Error(`Server ${server} not found`);
|
|
|
|
const res2 = await fetch(
|
|
`${this.api}/watch/${server}/${target.access_id}/`,
|
|
{ headers }
|
|
);
|
|
const json2 = await res2.json();
|
|
|
|
if (!json2?.data?.m3u8_url)
|
|
throw new Error(`Stream not found on ${server}`);
|
|
|
|
return {
|
|
server,
|
|
headers: {},
|
|
videoSources: [
|
|
{
|
|
url: json2.data.m3u8_url,
|
|
type: "m3u8",
|
|
quality: "auto",
|
|
subtitles: json2.data?.subtitles?.length
|
|
? this.parseSubtitles(json2.data)
|
|
: [],
|
|
},
|
|
],
|
|
};
|
|
}
|
|
}
|
|
|
|
module.exports = AniDream;
|