diff --git a/hicine/hicine.js b/hicine/hicine.js new file mode 100644 index 0000000..133df3e --- /dev/null +++ b/hicine/hicine.js @@ -0,0 +1,196 @@ +async function searchResults(keyword) { + const results = []; + try { + const response = await fetchv2("https://api.hicine.info/rpc/search/" + encodeURIComponent(keyword)); + const data = await response.json(); + + for (const item of data) { + if (item.data) { + results.push({ + title: item.data.title, + image: item.data.featured_image, + href: `https://api.hicine.info/api/${item.source_table}/${item.data.record_id}` + }); + } + } + + return JSON.stringify(results); + } catch (err) { + return JSON.stringify([{ + title: "Error", + image: "Error", + href: "Error" + }]); + } +} + +async function extractDetails(url) { + try { + const response = await fetchv2(url); + const data = await response.json(); + + return JSON.stringify([{ + description: data.categories, + aliases: "N/A", + airdate: "N/A" + }]); + } catch (err) { + return JSON.stringify([{ + description: "Error", + aliases: "Error", + airdate: "Error" + }]); + } +} + +async function extractEpisodes(url) { + const results = []; + try { + const response = await fetchv2(url); + const data = await response.json(); + + for (let seasonNum = 1; seasonNum <= 10; seasonNum++) { + const seasonKey = `season_${seasonNum}`; + const seasonData = data[seasonKey]; + + if (!seasonData) continue; + + const episodes = seasonData.split('\n').filter(line => line.trim().startsWith('Episode')); + let episodeNum = 1; + + for (const episodeLine of episodes) { + const qualityLinks = []; + const qualityParts = episodeLine.split(' : ').slice(1); + + for (const part of qualityParts) { + const match = part.match(/^(.+?),\s*([^,]*),(.+?)$/); + if (match) { + const fullUrl = match[1].trim(); + const size = match[2].trim(); + const quality = match[3].trim(); + + const vcloudMatch = fullUrl.match(/vcloud=(https:\/\/vcloud\.zip\/[^,&]+)/); + const vcloudUrl = vcloudMatch ? vcloudMatch[1] : fullUrl; + + qualityLinks.push({ + link: vcloudUrl, + quality: quality, + size: size + }); + } + } + + if (qualityLinks.length > 0) { + results.push({ + season: seasonNum, + number: episodeNum, + href: JSON.stringify(qualityLinks) + }); + episodeNum++; + } + } + } + + if (data.links && results.length === 0) { + const links = data.links.split('\n').filter(line => line.trim()); + const qualityLinks = []; + + for (const line of links) { + const match = line.match(/vcloud=(https:\/\/vcloud\.zip\/[^,]+),\s*Link2,\s*Link3,\s*Link4,\s*Link5,\s*Link6,\s*Link7,\s*(.+?)(?:,\s*(\d+(?:\.\d+)?(?:MB|GB)))?$/); + if (match) { + const vcloudUrl = match[1].trim(); + const quality = match[2].trim(); + const size = match[3] ? match[3].trim() : ''; + qualityLinks.push({ + link: vcloudUrl, + quality: quality, + size: size + }); + } + } + + if (qualityLinks.length > 0) { + results.push({ + href: JSON.stringify(qualityLinks), + number: 1 + }); + } + } + + return JSON.stringify(results.length > 0 ? results : [{ + href: "Error", + number: "Error", + season: "Error" + }]); + } catch (err) { + return JSON.stringify([{ + href: "Error", + number: "Error", + season: "Error" + }]); + } +} + +async function extractStreamUrl(url) { + try { + const qualityLinks = JSON.parse(url); + + const vcloudPromises = qualityLinks.map(async (quality, idx) => { + try { + const vcloudUrl = quality.link; + const qualityName = quality.quality; + + const vcloudResponse = await fetchv2(vcloudUrl, { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", + "Referer": "https://vcloud.zip/" + }); + const vcloudHtml = await vcloudResponse.text(); + + const urlMatch = vcloudHtml.match(/var\s+url\s*=\s*'(https:\/\/[^']+)'/); + if (!urlMatch) { + return null; + } + + const hubcloudUrl = urlMatch[1]; + + const hubcloudResponse = await fetchv2(hubcloudUrl, { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", + "Referer": vcloudUrl, + "X-Requested-With": "XMLHttpRequest" + }); + const hubcloudHtml = await hubcloudResponse.text(); + + const fslMatch = hubcloudHtml.match(/]*>[\s\S]*?Download\s*\[FSL\s*Server\]/i); + if (fslMatch) { + return { + title: qualityName, + streamUrl: fslMatch[1], + headers: {} + }; + } + + return null; + } catch (err) { + console.error(`Error in quality ${idx}:`, err.message); + return null; + } + }); + + const streams = (await Promise.all(vcloudPromises)).filter(s => s !== null); + + const result = { + type: "servers", + streams: streams, + subtitle: "nonrt" + }; + + return JSON.stringify(result); + } catch (err) { + console.error(" Top-level error:", err.message); + return JSON.stringify({ + type: "servers", + streams: [], + subtitle: "error" + }); + } +}