diff --git a/anime/animeav1/source.js b/anime/animeav1/source.js
new file mode 100644
index 0000000..1ee6f23
--- /dev/null
+++ b/anime/animeav1/source.js
@@ -0,0 +1,171 @@
+class AnimeAV1 {
+ constructor() {
+ this.type = "anime-board";
+ this.version = "1.0.0";
+ this.api = "https://animeav1.com";
+ }
+
+ getSettings() {
+ return {
+ episodeServers: ["HLS", "HLS-DUB"],
+ supportsDub: true,
+ };
+ }
+
+ async search(query) {
+ const q =
+ (query && typeof query === "object" && query.query)
+ ? String(query.query)
+ : (typeof query === "string" ? query : "");
+
+ if (!q.trim()) return [];
+
+ const res = await fetch(`${this.api}/api/search`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ query: q }),
+ });
+
+ if (!res.ok) return [];
+
+ const data = await res.json();
+ if (!Array.isArray(data)) return [];
+
+ return data
+ .map(anime => {
+ if (!anime || !anime.slug) return null;
+ return {
+ id: anime.slug,
+ title: anime.title || "Unknown",
+ url: `${this.api}/media/${anime.slug}`,
+ subOrDub: "both",
+ };
+ })
+ .filter(Boolean);
+ }
+
+ async getMetadata(id) {
+ const slug = String(id || "").trim();
+ if (!slug) throw new Error("Missing id");
+
+ const html = await fetch(`${this.api}/media/${slug}`).then(r => r.text());
+ const parsed = this.parseSvelteData(html);
+ const media = parsed.find(x => x?.data?.media)?.data?.media || {};
+
+ let image = null;
+ const imageMatch = html.match(/
]*class="aspect-poster[^"]*"[^>]*src="([^"]+)"/i);
+ if (imageMatch) image = imageMatch[1];
+
+ let year = null;
+ if (media.startDate) {
+ const y = Number(String(media.startDate).slice(0, 4));
+ if (!Number.isNaN(y)) year = y;
+ }
+
+ return {
+ title: media.title || "Unknown",
+ summary: media.synopsis || "No summary available",
+ episodes: media.episodesCount || 0,
+ characters: [],
+ season: media.seasons || null,
+ status: media.status || "Unknown",
+ studio: "Unknown",
+ score: media.score || 0,
+ year,
+ genres: (media.genres || []).map(g => g?.name).filter(Boolean),
+ image,
+ };
+ }
+
+ async findEpisodes(id) {
+ const slug = String(id || "").trim();
+ if (!slug) throw new Error("Missing id");
+
+ const html = await fetch(`${this.api}/media/${slug}`).then(r => r.text());
+ const parsed = this.parseSvelteData(html);
+ const media = parsed.find(x => x?.data?.media)?.data?.media;
+
+ if (!media || !Array.isArray(media.episodes))
+ throw new Error("No episodes");
+
+ return media.episodes.map((ep, i) => {
+ const n = ep?.number ?? (i + 1);
+ return {
+ id: `${media.slug || slug}$${n}`,
+ number: n,
+ title: ep?.title || `Episode ${n}`,
+ url: `${this.api}/media/${media.slug || slug}/${n}`,
+ };
+ });
+ }
+
+ async findEpisodeServer(episodeOrId, server) {
+ const ep =
+ typeof episodeOrId === "string"
+ ? (() => { try { return JSON.parse(episodeOrId); } catch { return { id: episodeOrId }; } })()
+ : episodeOrId;
+
+ const pageUrl =
+ ep.url ||
+ (typeof ep.id === "string" && ep.id.includes("$")
+ ? `${this.api}/media/${ep.id.split("$")[0]}/${ep.number || ep.id.split("$")[1]}`
+ : null);
+
+ if (!pageUrl) throw new Error("Missing episode url");
+
+ const html = await fetch(pageUrl, {
+ headers: { Referer: `${this.api}/` },
+ }).then(r => r.text());
+
+ const parsed = this.parseSvelteData(html);
+ const entry = parsed.find(x => x?.data?.embeds) || parsed[3];
+ const embeds = entry?.data?.embeds;
+
+ if (!embeds) throw new Error("No embeds");
+
+ const list =
+ server === "HLS" ? embeds.SUB :
+ server === "HLS-DUB" ? embeds.DUB :
+ null;
+
+ if (!Array.isArray(list) || !list.length)
+ throw new Error("No mirrors");
+
+ const match = list.find(m => String(m?.url || "").includes("zilla-networks.com/play/"));
+ if (!match) throw new Error("No valid source");
+
+ return {
+ server,
+ headers: { Referer: pageUrl },
+ videoSources: [
+ {
+ url: String(match.url).replace("/play/", "/m3u8/"),
+ type: "m3u8",
+ quality: "auto",
+ subtitles: [],
+ },
+ ],
+ };
+ }
+
+ parseSvelteData(html) {
+ const scriptMatch = html.match(/