diff --git a/gojowtf/gojowtf.js b/gojowtf/gojowtf.js index db0b704..265b966 100644 --- a/gojowtf/gojowtf.js +++ b/gojowtf/gojowtf.js @@ -1,17 +1,17 @@ async function searchResults(keyword) { const results = []; const headers = { - 'Referer': 'https://animetsu.to/', + 'Referer': 'https://animetsu.live/', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' }; const encodedKeyword = encodeURIComponent(keyword); - const response = await fetchv2(`https://backend.animetsu.to/api/anime/search?query=${encodedKeyword}&page=1&perPage=1000`, headers); + const response = await fetchv2(`https://animetsu.live/v2/api/anime/search/?query=${encodedKeyword}`, headers); const json = await response.json(); json.results.forEach(anime => { const title = anime.title.english || anime.title.romaji || anime.title.native || "Unknown Title"; - const image = anime.coverImage.large; + const image = anime.cover_image.large; const href = `${anime.id}`; if (title && href && image) { @@ -35,19 +35,19 @@ async function searchResults(keyword) { async function extractDetails(id) { const results = []; const headers = { - 'Referer': 'https://animetsu.to/', + 'Referer': 'https://animetsu.live/', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' }; - const response = await fetchv2(`https://backend.animetsu.to/api/anime/info/${id}`, headers); + const response = await fetchv2(`https://animetsu.live/v2/api/anime/info/${id}`, headers); const json = await response.json(); const description = cleanHtmlSymbols(json.description) || "No description available"; results.push({ description: description.replace(/
/g, ''), - aliases: 'N/A', - airdate: 'N/A' + aliases: json.synonyms ? json.synonyms.join(', ') : 'N/A', + airdate: json.start_date || 'N/A' }); return JSON.stringify(results); @@ -56,17 +56,17 @@ async function extractDetails(id) { async function extractEpisodes(id) { const results = []; const headers = { - 'Referer': 'https://animetsu.to/', + 'Referer': 'https://animetsu.live/', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' }; - const response = await fetchv2(`https://backend.animetsu.to/api/anime/eps/${id}`, headers); + const response = await fetchv2(`https://animetsu.live/v2/api/anime/eps/${id}`, headers); const json = await response.json(); for (const ep of json) { results.push({ - number: ep.number, - href: `&id=${id}&num=${ep.number}` + number: ep.ep_num, + href: `&id=${id}&num=${ep.ep_num}` }); } @@ -75,45 +75,88 @@ async function extractEpisodes(id) { async function extractStreamUrl(slug) { const headers = { - 'Referer': 'https://animetsu.to/', + 'Referer': 'https://animetsu.live/', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' }; - const fixedSlug = slug.replace('&', '?'); + const id = (slug.match(/[?&]id=([^&]+)/) || [])[1]; + const num = (slug.match(/[?&]num=([^&]+)/) || [])[1]; + const streams = []; - const serverListRes = await fetchv2(`https://backend.animetsu.to/api/anime/servers${fixedSlug}`, headers); - const serverList = await serverListRes.json(); - console.log("Fetched server list: " + JSON.stringify(serverList)); - const unfixedSlug = fixedSlug.replace('?', '&'); + try { + const serverListRes = await fetchv2(`https://animetsu.live/v2/api/anime/servers/${id}/${num}`, headers); + const serverList = await serverListRes.json(); - for (const server of serverList) { - if (server.name?.toLowerCase().includes('zoro') || server.id?.toLowerCase().includes('zoro')) { - console.log(`Skipping Zoro server: ${server.name || server.id}`); - continue; - } + const promises = []; + for (const server of serverList) { + for (const subType of ['sub', 'dub']) { + promises.push((async () => { + try { + const url = `https://animetsu.live/v2/api/anime/oppai/${id}/${num}?server=${server.id}&source_type=${subType}`; + const res = await fetchv2(url, headers); + const data = await res.json(); - for (const subType of ['sub', ...(server.hasDub ? ['dub'] : [])]) { - const url = `https://backend.animetsu.to/api/anime/tiddies?server=${server.id}${unfixedSlug}&subType=${subType}`; - console.log("Fetching stream URL:" + url); - const res = await fetchv2(url, headers); - const data = await res.json(); - - if (data?.sources?.length) { - for (const { quality, url: streamUrl } of data.sources) { - const language = subType === 'sub' ? 'HARDSUB' : subType.toUpperCase(); - streams.push(`${server.id} - ${quality} - ${language}`, streamUrl); - } + if (data?.sources?.length) { + data.sources.forEach(source => { + streams.push({ + title: `${server.id} - ${source.quality} - ${subType.toUpperCase()}`, + streamUrl: `https://mega-cloud.top/proxy${source.url}`, + headers: headers + }); + }); + } + } catch (e) { + console.error(`Error fetching streams for server ${server.id} (${subType}):`, e); + } + })()); } } + + await Promise.all(promises); + } catch (e) { + console.error("Error fetching server list:", e); } - const final = { - streams, - subtitles: "" + const serverOrder = { 'pahe': 1, 'meg': 2, 'kite': 3 }; + const qualityOrder = (q) => { + if (q.includes('1080')) return 1; + if (q.includes('720')) return 2; + if (q.includes('480')) return 3; + if (q.includes('360')) return 4; + if (q.includes('master')) return 5; + return 6; + }; + + streams.sort((a, b) => { + const partsA = a.title.split(' - '); + const partsB = b.title.split(' - '); + + const sA = partsA[0].toLowerCase(); + const sB = partsB[0].toLowerCase(); + const qA = partsA[1].toLowerCase(); + const qB = partsB[1].toLowerCase(); + + const qOrderA = qualityOrder(qA); + const qOrderB = qualityOrder(qB); + + if (qOrderA !== qOrderB) return qOrderA - qOrderB; + + const sOrderA = serverOrder[sA] || 99; + const sOrderB = serverOrder[sB] || 99; + return sOrderA - sOrderB; + }); + + const finalStreams = streams.map((s, index) => ({ + ...s, + title: `[Server ${index + 1}] ${s.title}` + })); + + const final = { + streams: finalStreams, + subtitle: "" }; - console.log("RETURN: " + JSON.stringify(final)); return JSON.stringify(final); }