diff --git a/1movies/1movies.js b/1movies/1movies.js index cb77c7f..57c8c71 100644 --- a/1movies/1movies.js +++ b/1movies/1movies.js @@ -243,41 +243,53 @@ async function extractStreamUrl(url) { const streams = []; if (m3u8Link) { - streams.push({ - title: "Auto", - streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + m3u8Link - }); - } - /* - const m3u8Response = await fetchv2("https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(m3u8Link)); - const m3u8Text = await m3u8Response.text(); - - const baseUrl = m3u8Link.substring(0, m3u8Link.lastIndexOf('/') + 1); - - const streams = []; - const lines = m3u8Text.split('\n'); - - for (let i = 0; i < lines.length; i++) { - const line = lines[i].trim(); - if (line.startsWith('#EXT-X-STREAM-INF:')) { - const resolutionMatch = line.match(/RESOLUTION=(\d+x\d+)/); - let quality = 'Unknown'; + let pushedQualities = 0; + try { + const m3u8Response = await fetchv2("https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(m3u8Link)); + const m3u8Text = await m3u8Response.text(); + const lines = m3u8Text.split('\n'); - if (resolutionMatch) { - const [width, height] = resolutionMatch[1].split('x'); - quality = `${height}p`; - } - - if (i + 1 < lines.length) { - const streamPath = lines[i + 1].trim(); - streams.push({ - title: quality, - streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(baseUrl + streamPath) - }); + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + 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) { + let streamPath = lines[i + 1].trim(); + let absolutePath; + if (streamPath.startsWith('/api/')) { + absolutePath = 'https://1anime.app' + streamPath; + } else if (streamPath.startsWith('http')) { + absolutePath = "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(streamPath); + } else { + const baseUrl = m3u8Link.substring(0, m3u8Link.lastIndexOf('/') + 1); + absolutePath = "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(baseUrl + streamPath); + } + streams.push({ + title: quality, + streamUrl: absolutePath + }); + pushedQualities++; + } + } } + } catch (e) { + console.log("Failed to extract qualities:", e); + } + + if (pushedQualities === 0) { + streams.push({ + title: "Source", + streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(m3u8Link) + }); } } - */ const returnValue = { streams: streams, subtitles: englishSubUrl !== "N/A" ? englishSubUrl : "" diff --git a/1movies/1movies.json b/1movies/1movies.json index 7404a62..b3d10f2 100644 --- a/1movies/1movies.json +++ b/1movies/1movies.json @@ -5,7 +5,7 @@ "name": "50/50", "icon": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3122kQwublLkZ6rf1fEpUP79BxZOFmH9BSA&s" }, - "version": "1.2.4", + "version": "1.2.5", "language": "English", "streamType": "HLS", "quality": "1080p", diff --git a/animekai/animekai.js b/animekai/animekai.js index 2f8ddd2..efe5a17 100644 --- a/animekai/animekai.js +++ b/animekai/animekai.js @@ -226,7 +226,53 @@ async function extractStreamUrl(url) { if (file) { const titleMap = { sub: "Hardsub English", softsub: "Original audio", dub: "Dubbed English" }; - streams.push({ title: titleMap[type] || type, streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + file }); + let pushedQualities = 0; + const baseTitle = titleMap[type] || type; + + try { + const proxyReqUrl = "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(file); + const m3u8Response = await fetchv2(proxyReqUrl); + const m3u8Text = await m3u8Response.text(); + const lines = m3u8Text.split('\n'); + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + if (line.startsWith('#EXT-X-STREAM-INF:')) { + const resolutionMatch = line.match(/RESOLUTION=(\d+x\d+)/); + const nameMatch = line.match(/NAME="([^"]+)"/i) || line.match(/BANDWIDTH=(\d+)/i); + + let quality = 'Unknown'; + if (resolutionMatch) { + const [width, height] = resolutionMatch[1].split('x'); + quality = `${height}p`; + } else if (nameMatch && nameMatch[1]) { + quality = nameMatch[1]; + } + + if (i + 1 < lines.length) { + let streamPath = lines[i + 1].trim(); + let absolutePath; + if (streamPath.startsWith('/api/')) { + absolutePath = 'https://1anime.app' + streamPath; + } else if (streamPath.startsWith('http')) { + absolutePath = 'https://1anime.app/api/m3u8-proxy?url=' + encodeURIComponent(streamPath); + } else { + const baseUrl = file.substring(0, file.lastIndexOf('/') + 1); + absolutePath = 'https://1anime.app/api/m3u8-proxy?url=' + encodeURIComponent(baseUrl + streamPath); + } + streams.push({ + title: `${quality} - ${baseTitle}`, + streamUrl: absolutePath + }); + pushedQualities++; + } + } + } + } catch (e) { + console.log("Failed to extract qualities:", e); + } + if (pushedQualities === 0) { + streams.push({ title: baseTitle, streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(file) }); + } } for (const track of tracks) { diff --git a/animekai/dub/animekai.js b/animekai/dub/animekai.js index 622614b..b5af1c7 100644 --- a/animekai/dub/animekai.js +++ b/animekai/dub/animekai.js @@ -223,7 +223,47 @@ async function extractStreamUrl(url) { if (file) { const titleMap = { dub: "Dubbed English" }; - streams.push({ title: titleMap[type] || type, streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + file }); + let pushedQualities = 0; + const baseTitle = titleMap[type] || type; + + try { + const m3u8Response = await fetchv2("https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(file)); + const m3u8Text = await m3u8Response.text(); + const lines = m3u8Text.split('\n'); + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + 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) { + let streamPath = lines[i + 1].trim(); + let absolutePath; + if (streamPath.startsWith('/api/')) { + absolutePath = 'https://1anime.app' + streamPath; + } else if (streamPath.startsWith('http')) { + absolutePath = 'https://1anime.app/api/m3u8-proxy?url=' + encodeURIComponent(streamPath); + } else { + const baseUrl = file.substring(0, file.lastIndexOf('/') + 1); + absolutePath = 'https://1anime.app/api/m3u8-proxy?url=' + encodeURIComponent(baseUrl + streamPath); + } + streams.push({ + title: `${quality} - ${baseTitle}`, + streamUrl: absolutePath + }); + pushedQualities++; + } + } + } + } catch (e) { + console.log("Failed to extract qualities:", e); + } + if (pushedQualities === 0) { + streams.push({ title: baseTitle, streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(file) }); + } } for (const track of tracks) { @@ -237,7 +277,7 @@ async function extractStreamUrl(url) { } })); - return streams.length > 0 ? streams[0].streamUrl : "error"; + return JSON.stringify({ streams, subtitles }); } catch (error) { console.error("Animekai fetch error:" + error); return "https://error.org"; diff --git a/animekai/dub/animekai.json b/animekai/dub/animekai.json index ab38d8e..8731b3f 100644 --- a/animekai/dub/animekai.json +++ b/animekai/dub/animekai.json @@ -5,7 +5,7 @@ "name": "50/50", "icon": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3122kQwublLkZ6rf1fEpUP79BxZOFmH9BSA&s" }, - "version": "1.1.6", + "version": "1.1.7", "language": "English", "streamType": "HLS", "quality": "1080p", diff --git a/animekai/hardsub/animekai.js b/animekai/hardsub/animekai.js index 27dd148..3f9615f 100644 --- a/animekai/hardsub/animekai.js +++ b/animekai/hardsub/animekai.js @@ -216,7 +216,47 @@ async function extractStreamUrl(url) { if (file) { const titleMap = { sub: "Hardsub English" }; - streams.push({ title: titleMap[type] || type, streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + file }); + let pushedQualities = 0; + const baseTitle = titleMap[type] || type; + + try { + const m3u8Response = await fetchv2("https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(file)); + const m3u8Text = await m3u8Response.text(); + const lines = m3u8Text.split('\n'); + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + 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) { + let streamPath = lines[i + 1].trim(); + let absolutePath; + if (streamPath.startsWith('/api/')) { + absolutePath = 'https://1anime.app' + streamPath; + } else if (streamPath.startsWith('http')) { + absolutePath = 'https://1anime.app/api/m3u8-proxy?url=' + encodeURIComponent(streamPath); + } else { + const baseUrl = file.substring(0, file.lastIndexOf('/') + 1); + absolutePath = 'https://1anime.app/api/m3u8-proxy?url=' + encodeURIComponent(baseUrl + streamPath); + } + streams.push({ + title: `${quality} - ${baseTitle}`, + streamUrl: absolutePath + }); + pushedQualities++; + } + } + } + } catch (e) { + console.log("Failed to extract qualities:", e); + } + if (pushedQualities === 0) { + streams.push({ title: baseTitle, streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(file) }); + } } for (const track of tracks) { @@ -230,7 +270,7 @@ async function extractStreamUrl(url) { } })); - return streams.length > 0 ? streams[0].streamUrl : "error"; + return JSON.stringify({ streams, subtitles }); } catch (error) { console.error("Animekai fetch error:" + error); return "https://error.org"; diff --git a/animekai/hardsub/animekai.json b/animekai/hardsub/animekai.json index 10f6acd..1d76e4d 100644 --- a/animekai/hardsub/animekai.json +++ b/animekai/hardsub/animekai.json @@ -5,7 +5,7 @@ "name": "50/50", "icon": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3122kQwublLkZ6rf1fEpUP79BxZOFmH9BSA&s" }, - "version": "1.1.4", + "version": "1.1.5", "language": "English", "streamType": "HLS", "quality": "1080p", diff --git a/ashi/ashi.js b/ashi/ashi.js index de5e376..cb88d33 100644 --- a/ashi/ashi.js +++ b/ashi/ashi.js @@ -548,7 +548,14 @@ 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" + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0", + "Accept": "text/html, */*; q=0.01", + "Accept-Language": "en-US,en;q=0.5", + "Sec-Fetch-Dest": "empty", + "Sec-Fetch-Mode": "cors", + "Sec-Fetch-Site": "same-origin", + "Pragma": "no-cache", + "Cache-Control": "no-cache" }; try { @@ -584,9 +591,11 @@ async function extractStreamUrl(url) { const extractServerId = (content) => { if (!content) return null; - const preferred = /]*data-lid="([^"]+)"[^>]*>\s*Server\s*1\s*<\/span>/i.exec(content); - if (preferred?.[1]) return preferred[1]; - return /]*data-lid="([^"]+)"/i.exec(content)?.[1] || null; + const spanRegex = /]*data-lid="([^"]+)"[^>]*>/g; + const ids = []; + let match; + while ((match = spanRegex.exec(content)) !== null) ids.push(match[1]); + return ids.length > 1 ? ids[1] : ids[0] ?? null; }; const serverIdDub = extractServerId(dubContent); @@ -630,7 +639,12 @@ async function extractStreamUrl(url) { streamResponses .filter(item => item.result) .map(item => - fetchv2(`https://enc-dec.app/api/dec-kai?text=${item.result}`, headers) + fetchv2( + "https://enc-dec.app/api/dec-kai", + { "Content-Type": "application/json" }, + "POST", + JSON.stringify({ text: item.result }) + ) .then(res => res.json()) .then(json => { console.log(`decrypted${item.type} URL:` + json.result?.url); @@ -682,9 +696,58 @@ async function extractStreamUrl(url) { ]); const streams = []; - if (subStream) streams.push({ title: "Hardsub English", streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + subStream }); - if (dubStream) streams.push({ title: "Dubbed English", streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + dubStream }); - if (rawStream) streams.push({ title: "Original audio", streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + rawStream }); + + async function addStreamQualities(m3u8Link, baseTitle) { + let pushedQualities = 0; + try { + const proxyReqUrl = "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(m3u8Link); + const m3u8Response = await fetchv2(proxyReqUrl); + const m3u8Text = await m3u8Response.text(); + const lines = m3u8Text.split('\n'); + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + if (line.startsWith('#EXT-X-STREAM-INF:')) { + const resolutionMatch = line.match(/RESOLUTION=(\d+x\d+)/); + const nameMatch = line.match(/NAME="([^"]+)"/i) || line.match(/BANDWIDTH=(\d+)/i); + + let quality = 'Unknown'; + if (resolutionMatch) { + const [width, height] = resolutionMatch[1].split('x'); + quality = `${height}p`; + } else if (nameMatch && nameMatch[1]) { + quality = nameMatch[1]; + } + + if (i + 1 < lines.length) { + const streamPath = lines[i + 1].trim(); + let absolutePath; + if (streamPath.startsWith('/api/')) { + absolutePath = 'https://1anime.app' + streamPath; + } else if (streamPath.startsWith('http')) { + absolutePath = "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(streamPath); + } else { + const baseUrl = m3u8Link.substring(0, m3u8Link.lastIndexOf('/') + 1); + absolutePath = "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(baseUrl + streamPath); + } + streams.push({ + title: `${quality} - ${baseTitle}`, + streamUrl: absolutePath + }); + pushedQualities++; + } + } + } + } catch (e) { + console.log("Failed to extract qualities:", e); + } + if (pushedQualities === 0) { + streams.push({ title: baseTitle, streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(m3u8Link) }); + } + } + + if (subStream) await addStreamQualities(subStream, "Hardsub English"); + if (dubStream) await addStreamQualities(dubStream, "Dubbed English"); + if (rawStream) await addStreamQualities(rawStream, "Original audio"); const final = { streams, subtitles: "" }; console.log("RETURN: " + JSON.stringify(final)); @@ -806,10 +869,55 @@ async function extractStreamUrl(url) { const m3u8Link = finalJson?.result?.sources?.[0]?.file; const streams = []; if (m3u8Link) { - streams.push({ - title: "Auto", - streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + m3u8Link - }); + let pushedQualities = 0; + try { + const m3u8Response = await fetchv2("https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(m3u8Link)); + const m3u8Text = await m3u8Response.text(); + const lines = m3u8Text.split('\n'); + + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + if (line.startsWith('#EXT-X-STREAM-INF:')) { + const resolutionMatch = line.match(/RESOLUTION=(\d+x\d+)/); + const nameMatch = line.match(/NAME="([^"]+)"/i) || line.match(/BANDWIDTH=(\d+)/i); + + let quality = 'Unknown'; + if (resolutionMatch) { + const [width, height] = resolutionMatch[1].split('x'); + quality = `${height}p`; + } else if (nameMatch && nameMatch[1]) { + quality = nameMatch[1]; + } + + if (i + 1 < lines.length) { + const streamPath = lines[i + 1].trim(); + let absolutePath; + if (streamPath.startsWith('/api/')) { + absolutePath = 'https://1anime.app' + streamPath; + } else if (streamPath.startsWith('http')) { + absolutePath = "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(streamPath); + } else { + const baseUrl = m3u8Link.substring(0, m3u8Link.lastIndexOf('/') + 1); + absolutePath = "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(baseUrl + streamPath); + } + streams.push({ + title: quality, + streamUrl: absolutePath + }); + pushedQualities++; + } + } + } + } catch (e) { + console.log("Failed to extract qualities:", e); + } + + if (pushedQualities === 0) { + streams.push({ + title: "Source", + streamUrl: "https://1anime.app/api/m3u8-proxy?url=" + encodeURIComponent(m3u8Link) + }); + } } const returnValue = { diff --git a/ashi/ashi.json b/ashi/ashi.json index ccc8a09..6307403 100644 --- a/ashi/ashi.json +++ b/ashi/ashi.json @@ -5,7 +5,7 @@ "name": "50/50", "icon": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3122kQwublLkZ6rf1fEpUP79BxZOFmH9BSA&s" }, - "version": "1.3.2", + "version": "1.3.3", "language": "English", "streamType": "HLS", "quality": "1080p",