diff --git a/ashi/ashi.js b/ashi/ashi.js index 20ba88a..49dab73 100644 --- a/ashi/ashi.js +++ b/ashi/ashi.js @@ -546,6 +546,11 @@ async function extractStreamUrl(url) { } if (source === "Animekai") { + const headers = { + "Referer": "https://anikai.to/", + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36" + }; + try { const useProxy = await isAnimekaiBlockedForUser(); const tokenMatch = actualUrl.match(/token=([^&]+)/); @@ -573,25 +578,15 @@ async function extractStreamUrl(url) { const subRegex = /
]*>([\s\S]*?)<\/div>/; const softsubRegex = /
]*>([\s\S]*?)<\/div>/; const dubRegex = /
]*>([\s\S]*?)<\/div>/; - const subMatch = subRegex.exec(serverHtmlSource); - const softsubMatch = softsubRegex.exec(serverHtmlSource); - const dubMatch = dubRegex.exec(serverHtmlSource); - const subContent = subMatch ? subMatch[1].trim() : ""; - const softsubContent = softsubMatch ? softsubMatch[1].trim() : ""; - const dubContent = dubMatch ? dubMatch[1].trim() : ""; + const subContent = subRegex.exec(serverHtmlSource)?.[1]?.trim() || ""; + const softsubContent = softsubRegex.exec(serverHtmlSource)?.[1]?.trim() || ""; + const dubContent = dubRegex.exec(serverHtmlSource)?.[1]?.trim() || ""; const extractServerId = (content) => { - if (!content) { - return null; - } - + if (!content) return null; const preferred = /]*data-lid="([^"]+)"[^>]*>\s*Server\s*1\s*<\/span>/i.exec(content); - if (preferred?.[1]) { - return preferred[1]; - } - - const fallback = /]*data-lid="([^"]+)"/i.exec(content); - return fallback?.[1] || null; + if (preferred?.[1]) return preferred[1]; + return /]*data-lid="([^"]+)"/i.exec(content)?.[1] || null; }; const serverIdDub = extractServerId(dubContent); @@ -604,109 +599,66 @@ async function extractStreamUrl(url) { { name: "Sub", data: serverIdSub } ].filter(item => item.data); - const tokenPromises = tokenRequestData.map(item => + const tokenResults = await Promise.all(tokenRequestData.map(item => fetchv2(`https://enc-dec.app/api/enc-kai?text=${encodeURIComponent(item.data)}`) .then(res => res.json()) .then(json => ({ name: item.name, data: json.result })) .catch(err => ({ name: item.name, error: err.toString() })) - ); - const tokenResults = await Promise.all(tokenPromises); + )); - const streamUrls = tokenResults.map(result => { - const serverIdMap = { - "Dub": serverIdDub, - "Softsub": serverIdSoftsub, - "Sub": serverIdSub - }; - return { - type: result.name, - url: `https://anikai.to/ajax/links/view?id=${serverIdMap[result.name]}&_=${result.data}` - }; - }); + const serverIdMap = { "Dub": serverIdDub, "Softsub": serverIdSoftsub, "Sub": serverIdSub }; - const processStreams = async (streamUrls) => { - const streamResponses = await Promise.all( - streamUrls.map(async ({ type, url }) => { - try { - const res = await fetchv2(useProxy ? proxyUrl(url) : url); - const json = await res.json(); - return { - type: type, - result: json.result - }; - } catch (error) { - console.log(`Error fetching ${type} stream:` + error); - return { - type: type, - result: null - }; - } - }) - ); + const streamUrls = tokenResults.map(result => ({ + type: result.name, + url: `https://anikai.to/ajax/links/view?id=${serverIdMap[result.name]}&_=${result.data}` + })); - const decryptRequestData = streamResponses - .filter(item => item.result) - .map(item => ({ - name: item.type, - data: item.result - })); - - if (decryptRequestData.length === 0) { - return {}; - } - - const decryptPromises = decryptRequestData.map(item => - fetchv2(`https://enc-dec.app/api/dec-kai?text=${encodeURIComponent(item.data)}`) - .then(res => res.json()) - .then(json => ({ name: item.name, data: JSON.stringify(json.result) })) - .catch(err => ({ name: item.name, error: err.toString() })) - ); - const decryptResults = await Promise.all(decryptPromises); - - const finalResults = {}; - decryptResults.forEach(result => { + const streamResponses = await Promise.all( + streamUrls.map(async ({ type, url }) => { try { - const parsed = JSON.parse(result.data); - finalResults[result.name] = parsed.url; - console.log(`decrypted${result.name} URL:` + parsed.url); + const res = await fetchv2(useProxy ? proxyUrl(url) : url); + const json = await res.json(); + return { type, result: json.result }; } catch (error) { - console.log(`Error parsing ${result.name} result:` + error); - finalResults[result.name] = null; + console.log(`Error fetching ${type} stream:` + error); + return { type, result: null }; } - }); + }) + ); - return finalResults; - }; + const decryptResults = await Promise.all( + streamResponses + .filter(item => item.result) + .map(item => + fetchv2(`https://enc-dec.app/api/dec-kai?text=${item.result}`, headers) + .then(res => res.json()) + .then(json => { + console.log(`decrypted${item.type} URL:` + json.result?.url); + return { name: item.type, url: json.result?.url || null }; + }) + .catch(err => { + console.log(`Error parsing ${item.type} result:` + err); + return { name: item.type, url: null }; + }) + ) + ); - const decryptedUrls = await processStreams(streamUrls); - const decryptedSub = decryptedUrls.Sub; - const decryptedDub = decryptedUrls.Dub; - const decryptedRaw = decryptedUrls.Softsub; - - const headers = { - "Referer": "https://anikai.to/", - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36" - }; + const urlMap = Object.fromEntries(decryptResults.map(i => [i.name, i.url])); + const decryptedSub = urlMap.Sub; + const decryptedDub = urlMap.Dub; + const decryptedRaw = urlMap.Softsub; async function getStream(url) { try { const response = await fetchv2(url.replace("/e/", "/media/"), headers); const responseJson = await response.json(); - const result = responseJson?.result; - - const postData = { - "text": result, - "agent": headers["User-Agent"] - }; - const finalResponse = await fetchv2( "https://enc-dec.app/api/dec-mega", { "Content-Type": "application/json" }, "POST", - JSON.stringify(postData) + JSON.stringify({ text: result, agent: headers["User-Agent"] }) ); - const finalJson = await finalResponse.json(); return finalJson?.result?.sources?.[0]?.file || null; } catch { @@ -714,23 +666,18 @@ async function extractStreamUrl(url) { } } - const streams = []; - const [subStream, dubStream, rawStream] = await Promise.all([ decryptedSub ? getStream(decryptedSub) : Promise.resolve(null), decryptedDub ? getStream(decryptedDub) : Promise.resolve(null), decryptedRaw ? getStream(decryptedRaw) : Promise.resolve(null) ]); - + + const streams = []; if (subStream) streams.push({ title: "Hardsub English", streamUrl: subStream }); - if (dubStream) streams.push({ title: "Dubbed English", streamUrl: dubStream }); - if (rawStream) streams.push({ title: "Original audio", streamUrl: rawStream }); - - const final = { - streams, - subtitles: "" - }; + if (dubStream) streams.push({ title: "Dubbed English", streamUrl: dubStream }); + if (rawStream) streams.push({ title: "Original audio", streamUrl: rawStream }); + const final = { streams, subtitles: "" }; console.log("RETURN: " + JSON.stringify(final)); return JSON.stringify(final); @@ -738,7 +685,13 @@ async function extractStreamUrl(url) { console.log("Animekai fetch error:" + error); return "https://error.org"; } + } else if (source === "1Movies") { + const headers = { + "Referer": "https://1movies.bz/", + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36" + }; + try { const eidMatch = actualUrl.match(/eid=([^&]+)/); if (eidMatch && eidMatch[1]) { @@ -762,13 +715,8 @@ async function extractStreamUrl(url) { } const serverId = server1Match[1]; - - const tokenPromises = [ - fetchv2(`https://enc-dec.app/api/enc-movies-flix?text=${encodeURIComponent(serverId)}`) - ]; - - const tokenResponses = await Promise.all(tokenPromises); - const tokenData = await tokenResponses[0].json(); + const tokenData = await fetchv2(`https://enc-dec.app/api/enc-movies-flix?text=${encodeURIComponent(serverId)}`) + .then(res => res.json()); const token = tokenData.result; if (!token) { @@ -785,61 +733,52 @@ async function extractStreamUrl(url) { return "error"; } - const decryptPromises = [ - fetchv2("https://enc-dec.app/api/dec-movies-flix", { "Content-Type": "application/json" }, "POST", JSON.stringify({ text: streamData.result })) - ]; - - const decryptResponses = await Promise.all(decryptPromises); - const decryptData = await decryptResponses[0].json(); + const decryptData = await fetchv2( + `https://enc-dec.app/api/dec-movies-flix?text=${streamData.result}`, + headers + ).then(res => res.json()); + console.log("Decrypted response:" + JSON.stringify(decryptData)); - const decryptedUrl = decryptData.result.url; - - const subListEncoded = decryptedUrl.split("sub.list=")[1]?.split("&")[0]; - let subtitles = "N/A"; - - if (subListEncoded) { - try { - const subListUrl = decodeURIComponent(subListEncoded); - const subResponse = await fetchv2(subListUrl); - subtitles = await subResponse.json(); - } catch { - subtitles = "N/A"; - } - } - - const englishSubUrl = Array.isArray(subtitles) - ? subtitles.find(sub => sub.label === "English")?.file.replace(/\\\//g, "/") - : "N/A"; + const decryptedUrl = decryptData.result?.url; if (!decryptedUrl) { console.log("Decryption failed"); return "error"; } - - const headers = { - "Referer": "https://1movies.bz/", - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36" - }; + + const subListEncoded = decryptedUrl.split("sub.list=")[1]?.split("&")[0]; + let subtitles = "N/A"; + if (subListEncoded) { + try { + const subListUrl = decodeURIComponent(subListEncoded); + const subResponse = await fetchv2(subListUrl); + subtitles = await subResponse.json(); + } catch { + subtitles = "N/A"; + } + } + + const englishSubUrl = Array.isArray(subtitles) + ? subtitles.find(sub => sub.label === "English")?.file.replace(/\\\//g, "/") + : "N/A"; const mediaResponse = await fetchv2(decryptedUrl.replace("/e/", "/media/"), headers); const mediaJson = await mediaResponse.json(); - const result = mediaJson?.result; + if (!result) { console.log("Media result not found"); return "error"; } - const finalResponse = await fetchv2(`https://enc-dec.app/api/dec-rapid?text=${encodeURIComponent(result)}&agent=${encodeURIComponent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36")}`); - const finalJsonText = await finalResponse.text(); - const finalJson = JSON.parse(finalJsonText); + const finalResponse = await fetchv2(`https://enc-dec.app/api/dec-rapid?text=${encodeURIComponent(result)}&agent=${encodeURIComponent(headers["User-Agent"])}`); + const finalJson = JSON.parse(await finalResponse.text()); const m3u8Link = finalJson?.result?.sources?.[0]?.file; const m3u8Response = await fetchv2(m3u8Link); const m3u8Text = await m3u8Response.text(); const baseUrl = m3u8Link.substring(0, m3u8Link.lastIndexOf('/') + 1); - const streams = []; const lines = m3u8Text.split('\n'); @@ -848,30 +787,26 @@ async function extractStreamUrl(url) { if (line.startsWith('#EXT-X-STREAM-INF:')) { const resolutionMatch = line.match(/RESOLUTION=(\d+x\d+)/); let quality = 'Unknown'; - if (resolutionMatch) { const [width, height] = resolutionMatch[1].split('x'); quality = `${height}p`; } - if (i + 1 < lines.length) { - const streamPath = lines[i + 1].trim(); - const streamUrl = baseUrl + streamPath; - streams.push({ title: quality, - streamUrl: streamUrl + streamUrl: baseUrl + lines[i + 1].trim() }); } } } const returnValue = { - streams: streams, + streams, subtitles: englishSubUrl !== "N/A" ? englishSubUrl : "" }; console.log("RETURN: " + JSON.stringify(returnValue)); return JSON.stringify(returnValue); + } catch (error) { console.log("1Movies fetch error:" + error); return "https://error.org";