async function searchResults(keyword) { try { const response = await fetchv2("https://api.franime.fr/api/animes"); const data = await response.json(); const results = data .filter(anime => anime.title.toLowerCase().includes(keyword.toLowerCase())) .map(anime => ({ href: anime.id.toString(), title: anime.title, image: anime.affiche })); return JSON.stringify(results); } catch (err) { return JSON.stringify([{ title: "Error", image: "Error", href: "Error" }]); } } async function extractDetails(id) { try { const response = await fetchv2("https://api.franime.fr/api/animes"); const data = await response.json(); const anime = data.find(item => item.id === Number(id)); if (!anime) { return JSON.stringify([{ description: "Not found", aliases: "N/A", airdate: "N/A" }]); } return JSON.stringify([{ description: anime.description || "N/A", aliases: anime.titles ? Object.values(anime.titles).join(", ") : "N/A", airdate: anime.startDate || "N/A" }]); } catch (err) { return JSON.stringify([{ description: "Error", aliases: "Error", airdate: "Error" }]); } } async function extractEpisodes(id) { const results = []; try { const response = await fetchv2("https://api.franime.fr/api/animes"); const data = await response.json(); const anime = data.find(item => item.id === Number(id)); if (!anime || !anime.saisons) { return JSON.stringify([{ href: "N/A", number: "N/A" }]); } anime.saisons.forEach((season, seasonIndex) => { season.episodes.forEach((episode, episodeIndex) => { results.push({ href: `${id}/${seasonIndex}/${episodeIndex}`, number: episodeIndex + 1 }); }); }); return JSON.stringify(results); } catch (err) { return JSON.stringify([{ href: "Error", number: "Error" }]); } } async function extractStreamUrl(id) { try { const headers = { "Host": "api.franime.fr", "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:143.0) Gecko/20100101 Firefox/143.0", "Referer": "https://franime.fr/", "Content-Type": "application/json", "Origin": "https://franime.fr", "Connection": "keep-alive", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-site", "Priority": "u=0", "TE": "trailers" }; async function fetchUntilMp4(type) { let i = 0; while (i < 10) { const url = `https://api.franime.fr/api/anime/${id}/${type}/${i}`; const res = await fetchv2(url, headers); const text = await res.text(); console.log(type.toUpperCase(), i, text); if (text.includes("Aucun lecteur disponible")) return null; if (text.endsWith(".mp4")) return text; i++; } } const vf = await fetchUntilMp4("vf"); const vo = await fetchUntilMp4("vo"); const streams = []; if (vf) streams.push("VOSTFR", vf); if (vo) streams.push("VF", vo); const final = { streams, subtitles: "" }; console.log("RETURN: " + JSON.stringify(final)); return JSON.stringify(final); } catch (error) { console.log("Error in extractStreamUrl:", error); return JSON.stringify({ streams: [], subtitles: "" }); } }