From 7c982916e18de74d840b662a784d86f1015a82dd Mon Sep 17 00:00:00 2001 From: aka paul <50n50@noreply.localhost> Date: Sun, 2 Nov 2025 21:52:00 +0000 Subject: [PATCH] Add kuramanime/kuramanime.js --- kuramanime/kuramanime.js | 138 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 kuramanime/kuramanime.js diff --git a/kuramanime/kuramanime.js b/kuramanime/kuramanime.js new file mode 100644 index 0000000..6a58268 --- /dev/null +++ b/kuramanime/kuramanime.js @@ -0,0 +1,138 @@ +async function searchResults(keyword) { + const response = await fetchv2(`https://v6.kuramanime.run/anime?search=${keyword}&order_by=oldest`); + const html = await response.text(); + const results = []; + + const animeEntryRegex = /
[\s\S]*?]*>([^<]+)<\/a><\/h5>/g; + + const entries = html.matchAll(animeEntryRegex); + for (const entry of entries) { + const href = entry[1].trim(); + const imageUrl = entry[2].trim(); + const title = entry[3].trim(); + + if (href && imageUrl && title) { + results.push({ + title: title, + href: href, + image: imageUrl + }); + } + } + + console.log(JSON.stringify(results)); + return JSON.stringify(results); +} + +async function extractDetails(url) { + const response = await fetchv2(url); + const html = await response.text(); + + const details = []; + const descriptionMatch = html.match(/

]*>([\s\S]*?)<\/p>/); + + const description = descriptionMatch ? + descriptionMatch[1] + .replace(/<\/?[^>]+(>|$)/g, '') + .replace(/\s+/g, ' ') + .trim() : + 'N/A'; + + details.push({ + description: description, + aliases: 'N/A', + airdate: 'N/A' + }); + + console.log(details); + return JSON.stringify(details); +} + +async function extractEpisodes(url) { + const response = await fetchv2(url); + const html = await response.text(); + const episodes = []; + + const oldestMatch = html.match(/]*>\s*Ep\s*\d+\s*\(Terlama\)/i); + + const newestMatch = html.match(/]*>\s*Ep\s*\d+\s*\(Terbaru\)/i); + + if (oldestMatch && newestMatch) { + const firstEpisode = parseInt(oldestMatch[2], 10); + const lastEpisode = parseInt(newestMatch[2], 10); + + for (let i = firstEpisode; i <= lastEpisode; i++) { + episodes.push({ + href: `${url}/episode/${i}`, + number: i + }); + } + } else { + const episodeLinks = [...html.matchAll(/]*>\s*Ep\s*\d+/gi)]; + + if (episodeLinks.length > 0) { + for (const match of episodeLinks) { + episodes.push({ + href: match[1], + number: parseInt(match[2], 10) + }); + } + } else { + episodes.push({ + href: `${url}/episode/1`, + number: 1 + }); + } + } + + console.error("Extracted episodes:" + JSON.stringify(episodes)); + return JSON.stringify(episodes); +} + +async function extractStreamUrl(url) { + const response = await fetchv2(url); + const html = await response.text(); + const firstCodeMatch = /data-kk="([^"]+)"/.exec(html); + + if (!firstCodeMatch) return null; + + const firstCode = firstCodeMatch[1]; + + const responseTwo = await fetchv2(`https://v6.kuramanime.run/assets/js/${firstCode}.js`); + const htmlTwo = await responseTwo.text(); + + const authRouteMatch = /MIX_AUTH_ROUTE_PARAM:\s*'([^']+)'/.exec(htmlTwo); + const pageTokenMatch = /MIX_PAGE_TOKEN_KEY:\s*'([^']+)'/.exec(htmlTwo); + const streamServerMatch = /MIX_STREAM_SERVER_KEY:\s*'([^']+)'/.exec(htmlTwo); + + const authRouteParam = authRouteMatch ? authRouteMatch[1] : null; + const pageTokenKey = pageTokenMatch ? pageTokenMatch[1] : null; + const streamServerKey = streamServerMatch ? streamServerMatch[1] : null; + + const responseThree = await fetchv2(`https://v6.kuramanime.run/assets/${authRouteParam}`); + const thirdRandomAssCode = await responseThree.text(); + const fullUrl = `${url}?${pageTokenMatch}=${thirdRandomAssCode}&${streamServerMatch}=kuramadrive&page=1` + + const fullUrlClean = cleanUrl(fullUrl); + console.error(fullUrlClean); + + const responseFour = await fetchv2(fullUrlClean); + const actualHtml = await responseFour.text(); + + const mp4SourceMatch = actualHtml.match(/]+src="([^"]+)"[^>]+type="video\/mp4"/); + + if (mp4SourceMatch) { + const mp4Url = mp4SourceMatch[1].replace(/&/g, '&'); + console.error("Found MP4 URL:"+ mp4Url); + return mp4Url; + } + + console.error("No MP4 source found"); + return null; +} + +function cleanUrl(url) { + return url.replace(/MIX_PAGE_TOKEN_KEY:\s*'[^']+',/, '') + .replace(/MIX_STREAM_SERVER_KEY:\s*'[^']+',/, '') + .replace(/:\s*'[^']+'/, ''); +} \ No newline at end of file