commit 3f3e12f5df3c46fccceb43fca01bf5091d8266b6 Author: himanshu8443 Date: Sun Jun 15 21:29:40 2025 +0530 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..11d5993 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +build/ +*.log +*.env \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..f5efb57 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,12 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "label": "Initialize TypeScript", + "command": "npx tsc --init", + "group": "build", + "problemMatcher": ["$tsc"] + } + ] +} diff --git a/dist/autoEmbed/allCatalog.js b/dist/autoEmbed/allCatalog.js new file mode 100644 index 0000000..d2fc485 --- /dev/null +++ b/dist/autoEmbed/allCatalog.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.allGenresList = exports.allCatalog = void 0; +exports.allCatalog = [ + { + title: 'Popular Movies', + filter: '/top/catalog/movie/top.json', + }, + { + title: 'Popular TV Shows', + filter: '/top/catalog/series/top.json', + }, + { + title: 'Featured Movies', + filter: '/imdbRating/catalog/movie/imdbRating.json', + }, + { + title: 'Featured TV Shows', + filter: '/imdbRating/catalog/series/imdbRating.json', + }, +]; +exports.allGenresList = []; diff --git a/dist/autoEmbed/allGetInfo.js b/dist/autoEmbed/allGetInfo.js new file mode 100644 index 0000000..cf97a04 --- /dev/null +++ b/dist/autoEmbed/allGetInfo.js @@ -0,0 +1,89 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.allGetInfo = void 0; +const allGetInfo = async function ({ link, providerContext, }) { + const axios = providerContext.axios; + try { + console.log('all', link); + const res = await axios.get(link); + const data = res.data; + const meta = { + title: '', + synopsis: '', + image: '', + imdbId: data?.meta?.imdb_id || '', + type: data?.meta?.type || 'movie', + }; + const links = []; + let directLinks = []; + let season = new Map(); + if (meta.type === 'series') { + data?.meta?.videos?.map((video) => { + if (video?.season <= 0) + return; + if (!season.has(video?.season)) { + season.set(video?.season, []); + } + season.get(video?.season).push({ + title: 'Episode ' + video?.episode, + type: 'series', + link: JSON.stringify({ + title: data?.meta?.name, + imdbId: data?.meta?.imdb_id, + season: video?.id?.split(':')[1], + episode: video?.id?.split(':')[2], + type: data?.meta?.type, + tmdbId: data?.meta?.moviedb_id?.toString() || '', + year: data?.meta?.year, + }), + }); + }); + const keys = Array.from(season.keys()); + keys.sort(); + keys.map(key => { + directLinks = season.get(key); + links.push({ + title: `Season ${key}`, + directLinks: directLinks, + }); + }); + } + else { + console.log('all meta Mv🔥🔥', meta); + links.push({ + title: data?.meta?.name, + directLinks: [ + { + title: 'Movie', + type: 'movie', + link: JSON.stringify({ + title: data?.meta?.name, + imdbId: data?.meta?.imdb_id, + season: '', + episode: '', + type: data?.meta?.type, + tmdbId: data?.meta?.moviedb_id?.toString() || '', + year: data?.meta?.year, + }), + }, + ], + }); + } + return { + ...meta, + linkList: links, + }; + } + catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.allGetInfo = allGetInfo; diff --git a/dist/autoEmbed/allGetPost.js b/dist/autoEmbed/allGetPost.js new file mode 100644 index 0000000..5b65a2f --- /dev/null +++ b/dist/autoEmbed/allGetPost.js @@ -0,0 +1,89 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.allGetSearchPosts = exports.allGetPost = void 0; +const allGetPost = async function ({ filter, signal, providerContext, }) { + try { + const catalog = []; + const url = 'https://cinemeta-catalogs.strem.io' + filter; + console.log('allGetPostUrl', url); + const res = await providerContext.axios.get(url, { + headers: providerContext.commonHeaders, + signal, + }); + const data = res.data; + data?.metas.map((result) => { + const title = result?.name; + const id = result?.imdb_id || result?.id; + const type = result?.type; + const image = result?.poster; + if (id) { + catalog.push({ + title: title, + link: `https://v3-cinemeta.strem.io/meta/${type}/${id}.json`, + image: image, + }); + } + }); + console.log('catalog', catalog.length); + return catalog; + } + catch (err) { + console.error('AutoEmbed error ', err); + return []; + } +}; +exports.allGetPost = allGetPost; +const allGetSearchPosts = async function ({ searchQuery, page, +// providerValue, +signal, providerContext, }) { + try { + if (page > 1) { + return []; + } + const catalog = []; + const url1 = `https://v3-cinemeta.strem.io/catalog/series/top/search=${encodeURI(searchQuery)}.json`; + const url2 = `https://v3-cinemeta.strem.io/catalog/movie/top/search=${encodeURI(searchQuery)}.json`; + const res = await providerContext.axios.get(url1, { + headers: providerContext.commonHeaders, + signal, + }); + const data = res.data; + data?.metas.map((result) => { + const title = result.name || ''; + const id = result?.imdb_id || result?.id; + const image = result?.poster; + const type = result?.type; + if (id) { + catalog.push({ + title: title, + link: `https://v3-cinemeta.strem.io/meta/${type}/${id}.json`, + image: image, + }); + } + }); + const res2 = await providerContext.axios.get(url2, { + headers: providerContext.commonHeaders, + signal, + }); + const data2 = res2.data; + data2?.metas.map((result) => { + const title = result?.name || ''; + const id = result?.imdb_id || result?.id; + const image = result?.poster; + const type = result?.type; + if (id) { + catalog.push({ + title: title, + link: `https://v3-cinemeta.strem.io/meta/${type}/${id}.json`, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('AutoEmbed error ', err); + return []; + } +}; +exports.allGetSearchPosts = allGetSearchPosts; diff --git a/dist/autoEmbed/allGetStream.js b/dist/autoEmbed/allGetStream.js new file mode 100644 index 0000000..290b6dd --- /dev/null +++ b/dist/autoEmbed/allGetStream.js @@ -0,0 +1,222 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.allGetStream = void 0; +exports.getRiveStream = getRiveStream; +const types_1 = require("../types"); +const allGetStream = async ({ link: id, type, providerContext, }) => { + try { + const streams = []; + const { imdbId, season, episode, title, tmdbId, year } = JSON.parse(id); + await getRiveStream(tmdbId, episode, season, type, streams, providerContext); + return streams; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.allGetStream = allGetStream; +async function getRiveStream(tmdId, episode, season, type, Streams, providerContext) { + const secret = generateSecretKey(Number(tmdId)); + const servers = [ + 'flowcast', + 'shadow', + 'asiacloud', + 'hindicast', + 'anime', + 'animez', + 'guard', + 'curve', + 'hq', + 'ninja', + 'alpha', + 'kaze', + 'zenesis', + 'genesis', + 'zenith', + 'ghost', + 'halo', + 'kinoecho', + 'ee3', + 'volt', + 'putafilme', + 'ophim', + 'kage', + ]; + const baseUrl = await providerContext.getBaseUrl('rive'); + const cors = process.env.CORS_PRXY ? process.env.CORS_PRXY + '?url=' : ''; + console.log('CORS: ' + cors); + const route = type === 'series' + ? `/api/backendfetch?requestID=tvVideoProvider&id=${tmdId}&season=${season}&episode=${episode}&secretKey=${secret}&service=` + : `/api/backendfetch?requestID=movieVideoProvider&id=${tmdId}&secretKey=${secret}&service=`; + const url = cors + ? cors + encodeURIComponent(baseUrl + route) + : baseUrl + route; + await Promise.all(servers.map(async (server) => { + console.log('Rive: ' + url + server); + try { + const res = await providerContext.axios.get(url + server, { + timeout: 4000, + headers: providerContext.commonHeaders, + }); + const subtitles = []; + if (res.data?.data?.captions) { + res.data?.data?.captions.forEach((sub) => { + subtitles.push({ + language: sub?.label?.slice(0, 2) || 'Und', + uri: sub?.file, + title: sub?.label || 'Undefined', + type: sub?.file?.endsWith('.vtt') + ? types_1.TextTrackType.VTT + : types_1.TextTrackType.SUBRIP, + }); + }); + } + res.data?.data?.sources.forEach((source) => { + Streams.push({ + server: source?.source + '-' + source?.quality, + link: source?.url, + type: source?.format === 'hls' ? 'm3u8' : 'mp4', + quality: source?.quality, + subtitles: subtitles, + }); + }); + } + catch (e) { + console.log(e); + } + })); +} +function generateSecretKey(id) { + // Array of secret key fragments - updated array from the new implementation + const c = [ + 'Yhv40uKAZa', + 'nn8YU4yBA', + 'uNeH', + 'ehK', + 'jT0', + 'n5G', + '99R', + 'MvB1M', + 'DQtPCh', + 'GBRjk4k4I', + 'CzIOoa95UT', + 'BLE8s', + 'GDZlc7', + 'Fz45T', + 'JW6lWn', + 'DE3g4uw0i', + '18KxmYizv', + '8ji', + 'JUDdNMnZ', + 'oGpBippPgm', + '7De8Pg', + 'Zv6', + 'VHT9TVN', + 'bYH6m', + 'aK1', + 'WcWH6jU', + 'Q47YEMi4k', + 'vRD3A', + 'CGOsfJO', + 'BLn8', + 'RgK0drv7l', + 'oPTfGCn3a', + 'MkpMDkttW9', + 'VNI1fPM', + 'XNFi6', + '6cq', + '4LvTksXoEI', + '1rRa2KOZB0', + 'zoOGRb8HT2', + 'mhcXDtvz', + 'NUmexFY2Ur', + '6BIMdvSZ', + 'Tr0zU2vjRd', + 'QPR', + 'fhOqJR', + 'R9VnFY', + 'xkZ99D6S', + 'umY7E', + '5Ds8qyDq', + 'Cc6jy09y3', + 'yvU3iR', + 'Bg07zY', + 'GccECglg', + 'VYd', + '6vOiXqz', + '7xX', + 'UdRrbEzF', + 'fE6wc', + 'BUd25Rb', + 'lxq5Zum89o', + ]; + // Handle undefined input + if (id === undefined) { + return 'rive'; + } + try { + let fragment, insertPos; + // Convert input to string + const idStr = String(id); + // Updated string hash function to match the new implementation + /* eslint-disable no-bitwise */ + const generateStringHash = function (input) { + input = String(input); + let hash = 0; + for (let i = 0; i < input.length; i++) { + const char = input.charCodeAt(i); + hash = + ((char + (hash << 6) + (hash << 16) - hash) ^ (char << i % 5)) >>> 0; + } + hash ^= hash >>> 13; + hash = (1540483477 * hash) >>> 0; + return (hash ^= hash >>> 15).toString(16).padStart(8, '0'); + }; + // Updated MurmurHash-like function to match the new implementation + const applyMurmurHash = function (input) { + const str = String(input); + let hash = 3735928559 ^ str.length; + for (let i = 0; i < str.length; i++) { + let char = str.charCodeAt(i); + char ^= ((i + 31) * 131) & 255; + hash = + (668265261 * + (hash = (((hash << 7) | (hash >>> 25)) >>> 0) ^ char)) >>> + 0; + } + hash ^= hash >>> 16; + hash = (2246822507 * hash) >>> 0; + hash ^= hash >>> 13; + hash = (3266489909 * hash) >>> 0; + return (hash ^= hash >>> 16).toString(16).padStart(8, '0'); + }; + /* eslint-enable no-bitwise */ + // Generate the encoded hash using the new implementation + const encodedHash = btoa(applyMurmurHash(generateStringHash(idStr))); + // Different handling for non-numeric vs numeric inputs + if (isNaN(Number(id))) { + // For non-numeric inputs, sum the character codes + const charSum = idStr + .split('') + .reduce((sum, char) => sum + char.charCodeAt(0), 0); + // Select array element or fallback to base64 encoded input + fragment = c[charSum % c.length] || btoa(idStr); + // Calculate insertion position + insertPos = Math.floor((charSum % encodedHash.length) / 2); + } + else { + // For numeric inputs, use the number directly + const numId = Number(id); + fragment = c[numId % c.length] || btoa(idStr); + // Calculate insertion position + insertPos = Math.floor((numId % encodedHash.length) / 2); + } + // Construct the final key by inserting the selected value into the base64 string + return (encodedHash.slice(0, insertPos) + fragment + encodedHash.slice(insertPos)); + } + catch (error) { + // Return fallback value if any errors occur + return 'topSecret'; + } +} diff --git a/dist/autoEmbed/index.js b/dist/autoEmbed/index.js new file mode 100644 index 0000000..4558b34 --- /dev/null +++ b/dist/autoEmbed/index.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.autoEmbed = void 0; +const allCatalog_1 = require("./allCatalog"); +const allGetInfo_1 = require("./allGetInfo"); +const allGetStream_1 = require("./allGetStream"); +const allGetPost_1 = require("./allGetPost"); +exports.autoEmbed = { + catalog: allCatalog_1.allCatalog, + genres: allCatalog_1.allGenresList, + GetMetaData: allGetInfo_1.allGetInfo, + GetHomePosts: allGetPost_1.allGetPost, + GetStream: allGetStream_1.allGetStream, + GetSearchPosts: allGetPost_1.allGetSearchPosts, +}; diff --git a/dist/cinemaLuxe/clCatalog.js b/dist/cinemaLuxe/clCatalog.js new file mode 100644 index 0000000..dd66ebd --- /dev/null +++ b/dist/cinemaLuxe/clCatalog.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.clGenresList = exports.clCatalog = void 0; +exports.clCatalog = [ + { + title: 'Trending', + filter: '/genre/latest-trending-releases/', + }, + { + title: 'Netflix', + filter: '/network/netflix/', + }, + { + title: 'Amazon Prime', + filter: '/network/prime-video/', + }, + { + title: 'Animation', + filter: '/genre/anime/', + }, +]; +exports.clGenresList = []; diff --git a/dist/cinemaLuxe/clGetEpisodes.js b/dist/cinemaLuxe/clGetEpisodes.js new file mode 100644 index 0000000..b7e7783 --- /dev/null +++ b/dist/cinemaLuxe/clGetEpisodes.js @@ -0,0 +1,64 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.clsEpisodeLinks = void 0; +const clsEpisodeLinks = async function ({ url, providerContext, }) { + try { + if (!url.includes('luxelinks') || url.includes('luxecinema')) { + const res = await providerContext.axios.get(url, { + headers: providerContext.commonHeaders, + }); + const data = res.data; + const encodedLink = data.match(/"link":"([^"]+)"/)?.[1]; + if (encodedLink) { + url = encodedLink ? atob(encodedLink) : url; + } + else { + const redirectUrlRes = await fetch('https://ext.8man.me/api/cinemaluxe', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ url }), + }); + const redirectUrl = await redirectUrlRes.json(); + url = redirectUrl?.redirectUrl || url; + } + } + const res = await providerContext.axios.get(url, { + headers: providerContext.commonHeaders, + }); + const html = res.data; + let $ = providerContext.cheerio.load(html); + const episodeLinks = []; + if (url.includes('luxedrive')) { + episodeLinks.push({ + title: 'Movie', + link: url, + }); + return episodeLinks; + } + $('a.maxbutton-4,a.maxbutton,.maxbutton-hubcloud,.ep-simple-button').map((i, element) => { + const title = $(element).text()?.trim(); + const link = $(element).attr('href'); + if (title && + link && + !title.includes('Batch') && + !title.toLowerCase().includes('zip')) { + episodeLinks.push({ + title: title + .replace(/\(\d{4}\)/, '') + .replace('Download', 'Movie') + .replace('⚡', '') + .trim(), + link, + }); + } + }); + return episodeLinks; + } + catch (err) { + console.error('cl episode links', err); + return []; + } +}; +exports.clsEpisodeLinks = clsEpisodeLinks; diff --git a/dist/cinemaLuxe/clGetMeta.js b/dist/cinemaLuxe/clGetMeta.js new file mode 100644 index 0000000..51d91a9 --- /dev/null +++ b/dist/cinemaLuxe/clGetMeta.js @@ -0,0 +1,64 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.clGetInfo = void 0; +const clGetInfo = async function ({ link, providerContext, }) { + try { + const url = link; + const res = await providerContext.axios.get(url, { + headers: providerContext.commonHeaders, + }); + const data = res.data; + const $ = providerContext.cheerio.load(data); + const type = url.includes('tvshows') ? 'series' : 'movie'; + const imdbId = ''; + const title = url.split('/')[4].replace(/-/g, ' '); + const image = $('.g-item').find('a').attr('href') || ''; + const synopsis = $('.wp-content').text().trim(); + const tags = $('.sgeneros') + .children() + .map((i, element) => $(element).text()) + .get() + .slice(3); + const rating = Number($('#repimdb').find('strong').text()) + .toFixed(1) + .toString(); + const links = []; + $('.mb-center.maxbutton-5-center,.ep-button-container').map((i, element) => { + const title = $(element) + .text() + .replace('\u2b07Download', '') + .replace('\u2b07 Download', '') + .trim(); + const link = $(element).find('a').attr('href'); + if (title && link) { + links.push({ + title, + episodesLink: link, + quality: title?.match(/\d+P\b/)?.[0].replace('P', 'p') || '', + }); + } + }); + return { + title, + tags, + rating, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } + catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.clGetInfo = clGetInfo; diff --git a/dist/cinemaLuxe/clGetPosts.js b/dist/cinemaLuxe/clGetPosts.js new file mode 100644 index 0000000..010db34 --- /dev/null +++ b/dist/cinemaLuxe/clGetPosts.js @@ -0,0 +1,55 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.clGetPostsSearch = exports.clGetPosts = void 0; +const clGetPosts = async function ({ filter, page, signal, providerContext, }) { + const baseUrl = await providerContext.getBaseUrl('cinemaLuxe'); + const url = `${baseUrl + filter}page/${page}/`; + return posts({ url, signal, providerContext }); +}; +exports.clGetPosts = clGetPosts; +const clGetPostsSearch = async function ({ searchQuery, page, signal, providerContext, }) { + const baseUrl = await providerContext.getBaseUrl('cinemaLuxe'); + const url = `${baseUrl}/page/${page}/?s=${searchQuery}`; + return posts({ url, signal, providerContext }); +}; +exports.clGetPostsSearch = clGetPostsSearch; +async function posts({ url, signal, providerContext, }) { + try { + const res = await fetch(url, { + headers: providerContext.commonHeaders, + signal, + }); + const data = await res.text(); + const $ = providerContext.cheerio.load(data); + const catalog = []; + $('.item.tvshows,.item.movies').map((i, element) => { + const title = $(element).find('.poster').find('img').attr('alt'); + const link = $(element).find('.poster').find('a').attr('href'); + const image = $(element).find('.poster').find('img').attr('data-src'); + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + $('.result-item').map((i, element) => { + const title = $(element).find('.thumbnail').find('img').attr('alt'); + const link = $(element).find('.thumbnail').find('a').attr('href'); + const image = $(element).find('.thumbnail').find('img').attr('data-src'); + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('cinemaluxe error ', err); + return []; + } +} diff --git a/dist/cinemaLuxe/clGetSteam.js b/dist/cinemaLuxe/clGetSteam.js new file mode 100644 index 0000000..f9315dd --- /dev/null +++ b/dist/cinemaLuxe/clGetSteam.js @@ -0,0 +1,36 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.clGetStream = void 0; +const clGetStream = async ({ link, signal, providerContext, }) => { + try { + let newLink = link; + if (link.includes('luxedrive')) { + const res = await providerContext.axios.get(link); + const $ = providerContext.cheerio.load(res.data); + const hubcloudLink = $('a.btn.hubcloud').attr('href'); + if (hubcloudLink) { + newLink = hubcloudLink; + } + else { + const gdFlixLink = $('a.btn.gdflix').attr('href'); + if (gdFlixLink) { + newLink = gdFlixLink; + } + } + } + if (newLink.includes('gdflix')) { + const sreams = await providerContext.extractors.gdFlixExtracter(newLink, signal); + return sreams; + } + const res2 = await providerContext.axios.get(newLink, { signal }); + const data2 = res2.data; + const hcLink = data2.match(/location\.replace\('([^']+)'/)?.[1] || newLink; + const hubCloudLinks = await providerContext.extractors.hubcloudExtracter(hcLink.includes('https://hubcloud') ? hcLink : newLink, signal); + return hubCloudLinks; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.clGetStream = clGetStream; diff --git a/dist/cinemaLuxe/index.js b/dist/cinemaLuxe/index.js new file mode 100644 index 0000000..1605275 --- /dev/null +++ b/dist/cinemaLuxe/index.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.cinemaLuxe = void 0; +const clCatalog_1 = require("./clCatalog"); +const clGetMeta_1 = require("./clGetMeta"); +const clGetEpisodes_1 = require("./clGetEpisodes"); +const clGetPosts_1 = require("./clGetPosts"); +const clGetSteam_1 = require("./clGetSteam"); +exports.cinemaLuxe = { + catalog: clCatalog_1.clCatalog, + genres: clCatalog_1.clGenresList, + GetHomePosts: clGetPosts_1.clGetPosts, + GetMetaData: clGetMeta_1.clGetInfo, + GetSearchPosts: clGetPosts_1.clGetPostsSearch, + GetEpisodeLinks: clGetEpisodes_1.clsEpisodeLinks, + GetStream: clGetSteam_1.clGetStream, +}; diff --git a/dist/dooflix/dooCatalog.js b/dist/dooflix/dooCatalog.js new file mode 100644 index 0000000..7dab250 --- /dev/null +++ b/dist/dooflix/dooCatalog.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.dooGenresList = exports.dooCatalog = void 0; +exports.dooCatalog = [ + { + title: 'Series', + filter: '/rest-api//v130/tvseries', + }, + { + title: 'Movies', + filter: '/rest-api//v130/movies', + }, +]; +exports.dooGenresList = []; diff --git a/dist/dooflix/dooGetInfo.js b/dist/dooflix/dooGetInfo.js new file mode 100644 index 0000000..72b3716 --- /dev/null +++ b/dist/dooflix/dooGetInfo.js @@ -0,0 +1,79 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.dooGetInfo = void 0; +const headers = { + 'Accept-Encoding': 'gzip', + 'API-KEY': '2pm95lc6prpdbk0ppji9rsqo', + Connection: 'Keep-Alive', + 'If-Modified-Since': 'Wed, 14 Aug 2024 13:00:04 GMT', + 'User-Agent': 'okhttp/3.14.9', +}; +const dooGetInfo = async function ({ link, providerContext, }) { + try { + const { axios } = providerContext; + const res = await axios.get(link, { headers }); + const resData = res.data; + const jsonStart = resData?.indexOf('{'); + const jsonEnd = resData?.lastIndexOf('}') + 1; + const data = JSON?.parse(resData?.substring(jsonStart, jsonEnd))?.title + ? JSON?.parse(resData?.substring(jsonStart, jsonEnd)) + : resData; + const title = data?.title || ''; + const synopsis = data?.description || ''; + const image = data?.poster_url || ''; + const cast = data?.cast || []; + const rating = data?.imdb_rating || ''; + const type = Number(data?.is_tvseries) ? 'series' : 'movie'; + const tags = data?.genre?.map((genre) => genre?.name) || []; + const links = []; + if (type === 'series') { + data?.season?.map((season) => { + const title = season?.seasons_name || ''; + const directLinks = season?.episodes?.map((episode) => ({ + title: episode?.episodes_name, + link: episode?.file_url, + })) || []; + links.push({ + title: title, + directLinks: directLinks, + }); + }); + } + else { + data?.videos?.map((video) => { + links.push({ + title: title + ' ' + video?.label, + directLinks: [ + { + title: 'Play', + link: video?.file_url, + }, + ], + }); + }); + } + return { + image: image?.includes('https') ? image : image?.replace('http', 'https'), + synopsis: synopsis, + title: title, + rating: rating, + imdbId: '', + cast: cast, + tags: tags, + type: type, + linkList: links, + }; + } + catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.dooGetInfo = dooGetInfo; diff --git a/dist/dooflix/dooGetPosts.js b/dist/dooflix/dooGetPosts.js new file mode 100644 index 0000000..0b0f83e --- /dev/null +++ b/dist/dooflix/dooGetPosts.js @@ -0,0 +1,140 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.dooGetSearchPost = exports.dooGetPost = void 0; +const headers = { + 'Accept-Encoding': 'gzip', + 'API-KEY': '2pm95lc6prpdbk0ppji9rsqo', + Connection: 'Keep-Alive', + 'If-Modified-Since': 'Wed, 14 Aug 2024 13:00:04 GMT', + 'User-Agent': 'okhttp/3.14.9', +}; +const dooGetPost = async function ({ filter, page, signal, providerContext, }) { + try { + const { axios, getBaseUrl } = providerContext; + const baseUrl = await getBaseUrl('dooflix'); + const catalog = []; + const url = `${baseUrl + filter + `?page=${page}`}`; + const res = await axios.get(url, { headers, signal }); + const resData = res.data; + if (!resData || typeof resData !== 'string') { + console.warn('Unexpected response format from dooflix API'); + return []; + } + let data; + try { + const jsonStart = resData.indexOf('['); + const jsonEnd = resData.lastIndexOf(']') + 1; + if (jsonStart === -1 || jsonEnd <= jsonStart) { + // If we can't find valid JSON array markers, try parsing the entire response + data = JSON.parse(resData); + } + else { + const jsonSubstring = resData.substring(jsonStart, jsonEnd); + const parsedArray = JSON.parse(jsonSubstring); + data = parsedArray.length > 0 ? parsedArray : resData; + } + } + catch (parseError) { + console.error('Error parsing dooflix response:', parseError); + return []; + } + if (!Array.isArray(data)) { + console.warn('Unexpected data format from dooflix API'); + return []; + } + data.forEach((result) => { + const id = result?.videos_id; + if (!id) + return; + const type = !result?.is_tvseries ? 'tvseries' : 'movie'; + const link = `${baseUrl}/rest-api//v130/single_details?type=${type}&id=${id}`; + const thumbnailUrl = result?.thumbnail_url; + const image = thumbnailUrl?.includes('https') + ? thumbnailUrl + : thumbnailUrl?.replace('http', 'https'); + catalog.push({ + title: result?.title || '', + link, + image, + }); + }); + return catalog; + } + catch (err) { + console.error('dooflix error:', err); + return []; + } +}; +exports.dooGetPost = dooGetPost; +const dooGetSearchPost = async function ({ searchQuery, page, providerContext, signal, }) { + try { + if (page > 1) { + return []; + } + const { axios, getBaseUrl } = providerContext; + const catalog = []; + const baseUrl = await getBaseUrl('dooflix'); + const url = `${baseUrl}/rest-api//v130/search?q=${searchQuery}&type=movietvserieslive&range_to=0&range_from=0&tv_category_id=0&genre_id=0&country_id=0`; + const res = await axios.get(url, { headers, signal }); + const resData = res.data; + if (!resData || typeof resData !== 'string') { + console.warn('Unexpected search response format from dooflix API'); + return []; + } + let data; + try { + const jsonStart = resData.indexOf('{'); + const jsonEnd = resData.lastIndexOf('}') + 1; + if (jsonStart === -1 || jsonEnd <= jsonStart) { + data = resData; + } + else { + const jsonSubstring = resData.substring(jsonStart, jsonEnd); + const parsedData = JSON.parse(jsonSubstring); + data = parsedData?.movie ? parsedData : resData; + } + } + catch (parseError) { + console.error('Error parsing dooflix search response:', parseError); + return []; + } + // Process movies + data?.movie?.forEach((result) => { + const id = result?.videos_id; + if (!id) + return; + const link = `${baseUrl}/rest-api//v130/single_details?type=movie&id=${id}`; + const thumbnailUrl = result?.thumbnail_url; + const image = thumbnailUrl?.includes('https') + ? thumbnailUrl + : thumbnailUrl?.replace('http', 'https'); + catalog.push({ + title: result?.title || '', + link, + image, + }); + }); + // Process TV series + data?.tvseries?.forEach((result) => { + const id = result?.videos_id; + if (!id) + return; + const link = `${baseUrl}/rest-api//v130/single_details?type=tvseries&id=${id}`; + const thumbnailUrl = result?.thumbnail_url; + const image = thumbnailUrl?.includes('https') + ? thumbnailUrl + : thumbnailUrl?.replace('http', 'https'); + catalog.push({ + title: result?.title || '', + link, + image, + }); + }); + return catalog; + } + catch (error) { + console.error('dooflix search error:', error); + return []; + } +}; +exports.dooGetSearchPost = dooGetSearchPost; diff --git a/dist/dooflix/dooGetSteam.js b/dist/dooflix/dooGetSteam.js new file mode 100644 index 0000000..f7d6c1e --- /dev/null +++ b/dist/dooflix/dooGetSteam.js @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.dooGetStream = void 0; +const dooGetStream = async function ({ link, }) { + try { + const streams = []; + streams.push({ + server: 'Dooflix', + link: link, + type: 'm3u8', + headers: { + Connection: 'Keep-Alive', + 'User-Agent': 'Mozilla/5.0 (WindowsNT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.37', + Referer: 'https://molop.art/', + Cookie: 'cf_clearance=M2_2Hy4lKRy_ruRX3dzOgm3iho1FHe2DUC1lq28BUtI-1737377622-1.2.1.1-6R8RaH94._H2BuNuotsjTZ3fAF6cLwPII0guemu9A5Xa46lpCJPuELycojdREwoonYS2kRTYcZ9_1c4h4epi2LtDvMM9jIoOZKE9pIdWa30peM1hRMpvffTjGUCraHsJNCJez8S_QZ6XkkdP7GeQ5iwiYaI6Grp6qSJWoq0Hj8lS7EITZ1LzyrALI6iLlYjgLmgLGa1VuhORWJBN8ZxrJIZ_ba_pqbrR9fjnyToqxZ0XQaZfk1d3rZyNWoZUjI98GoAxVjnKtcBQQG6b2jYPJuMbbYraGoa54N7E7BR__7o', + }, + }); + console.log('doo streams', streams); + return streams; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.dooGetStream = dooGetStream; diff --git a/dist/dooflix/index.js b/dist/dooflix/index.js new file mode 100644 index 0000000..f8b7c29 --- /dev/null +++ b/dist/dooflix/index.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.dooflixProvider = void 0; +const dooCatalog_1 = require("./dooCatalog"); +const dooGetInfo_1 = require("./dooGetInfo"); +const dooGetPosts_1 = require("./dooGetPosts"); +const dooGetSteam_1 = require("./dooGetSteam"); +exports.dooflixProvider = { + catalog: dooCatalog_1.dooCatalog, + genres: dooCatalog_1.dooGenresList, + GetMetaData: dooGetInfo_1.dooGetInfo, + GetStream: dooGetSteam_1.dooGetStream, + GetHomePosts: dooGetPosts_1.dooGetPost, + GetSearchPosts: dooGetPosts_1.dooGetSearchPost, +}; diff --git a/dist/drive/catalog.js b/dist/drive/catalog.js new file mode 100644 index 0000000..daaa222 --- /dev/null +++ b/dist/drive/catalog.js @@ -0,0 +1,63 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.driveGenresList = exports.driveCatalog = void 0; +exports.driveCatalog = [ + { + title: 'Latest', + filter: '', + }, + { + title: 'Anime', + filter: 'category/anime/', + }, + { + title: 'Netflix', + filter: 'category/netflix/', + }, + { + title: '4K', + filter: 'category/2160p-4k/', + }, +]; +exports.driveGenresList = [ + { + title: 'Action', + filter: '/category/action', + }, + { + title: 'Crime', + filter: '/category/crime', + }, + { + title: 'Comedy', + filter: '/category/comedy', + }, + { + title: 'Drama', + filter: '/category/drama', + }, + { + title: 'Horror', + filter: '/category/horror', + }, + { + title: 'Family', + filter: '/category/family', + }, + { + title: 'Sci-Fi', + filter: '/category/sifi', + }, + { + title: 'Thriller', + filter: '/category/triller', + }, + { + title: 'Romance', + filter: '/category/romance', + }, + { + title: 'Fight', + filter: '/category/fight', + }, +]; diff --git a/dist/drive/driveGetEpisodesList.js b/dist/drive/driveGetEpisodesList.js new file mode 100644 index 0000000..5c79e8d --- /dev/null +++ b/dist/drive/driveGetEpisodesList.js @@ -0,0 +1,34 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.driveGetEpisodeLinks = void 0; +const driveGetEpisodeLinks = async function ({ url, providerContext, }) { + try { + const { axios, cheerio } = providerContext; + const res = await axios.get(url); + const html = res.data; + let $ = cheerio.load(html); + const episodeLinks = []; + $('a:contains("HubCloud")').map((i, element) => { + const title = $(element).parent().prev().text(); + const link = $(element).attr('href'); + if (link && (title.includes('Ep') || title.includes('Download'))) { + episodeLinks.push({ + title: title.includes('Download') ? 'Play' : title, + link, + }); + } + }); + // console.log(episodeLinks); + return episodeLinks; + } + catch (err) { + console.error(err); + return [ + { + title: 'Server 1', + link: url, + }, + ]; + } +}; +exports.driveGetEpisodeLinks = driveGetEpisodeLinks; diff --git a/dist/drive/driveGetInfo.js b/dist/drive/driveGetInfo.js new file mode 100644 index 0000000..4705396 --- /dev/null +++ b/dist/drive/driveGetInfo.js @@ -0,0 +1,72 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.driveGetInfo = void 0; +const driveGetInfo = async function ({ link, providerContext, }) { + try { + const { axios, cheerio } = providerContext; + const url = link; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const type = $('.left-wrapper') + .text() + .toLocaleLowerCase() + .includes('movie name') + ? 'movie' + : 'series'; + const imdbId = $('a:contains("IMDb")').attr('href')?.split('/')[4] || ''; + const title = $('.left-wrapper').find('strong:contains("Name")').next().text() || + $('.left-wrapper') + .find('strong:contains("Name"),h5:contains("Name")') + .find('span:first') + .text(); + const synopsis = $('.left-wrapper') + .find('h2:contains("Storyline"),h3:contains("Storyline"),h5:contains("Storyline"),h4:contains("Storyline"),h4:contains("STORYLINE")') + .next() + .text() || + $('.ipc-html-content-inner-div').text() || + ''; + const image = $('img.entered.lazyloaded,img.entered,img.litespeed-loaded').attr('src') || + $('img.aligncenter').attr('src') || + ''; + // Links + const links = []; + $('a:contains("1080")a:not(:contains("Zip")),a:contains("720")a:not(:contains("Zip")),a:contains("480")a:not(:contains("Zip")),a:contains("2160")a:not(:contains("Zip")),a:contains("4k")a:not(:contains("Zip"))').map((i, element) => { + const title = $(element).parent('h5').prev().text(); + const episodesLink = $(element).attr('href'); + const quality = title.match(/\b(480p|720p|1080p|2160p)\b/i)?.[0] || ''; + if (episodesLink && title) { + links.push({ + title, + episodesLink: type === 'series' ? episodesLink : '', + directLinks: type === 'movie' + ? [{ title: 'Movie', link: episodesLink, type: 'movie' }] + : [], + quality: quality, + }); + } + }); + // console.log('drive meta', title, synopsis, image, imdbId, type, links); + console.log('drive meta', links, type); + return { + title, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } + catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.driveGetInfo = driveGetInfo; diff --git a/dist/drive/driveGetPosts.js b/dist/drive/driveGetPosts.js new file mode 100644 index 0000000..f540aaf --- /dev/null +++ b/dist/drive/driveGetPosts.js @@ -0,0 +1,45 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.driveGetSearchPost = exports.driveGetPosts = void 0; +const driveGetPosts = async function ({ filter, page, signal, providerContext, }) { + const { getBaseUrl } = providerContext; + const baseUrl = await getBaseUrl('drive'); + const url = `${baseUrl + filter}/page/${page}/`; + return posts({ url, signal, providerContext }); +}; +exports.driveGetPosts = driveGetPosts; +const driveGetSearchPost = async function ({ searchQuery, page, signal, providerContext, }) { + const { getBaseUrl } = providerContext; + const baseUrl = await getBaseUrl('drive'); + const url = `${baseUrl}page/${page}/?s=${searchQuery}`; + return posts({ url, signal, providerContext }); +}; +exports.driveGetSearchPost = driveGetSearchPost; +async function posts({ url, signal, providerContext, }) { + try { + const { cheerio } = providerContext; + const res = await fetch(url, { signal }); + const data = await res.text(); + const $ = cheerio.load(data); + const catalog = []; + $('.recent-movies') + .children() + .map((i, element) => { + const title = $(element).find('figure').find('img').attr('alt'); + const link = $(element).find('a').attr('href'); + const image = $(element).find('figure').find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title.replace('Download', '').trim(), + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('drive error ', err); + return []; + } +} diff --git a/dist/drive/driveGetStream.js b/dist/drive/driveGetStream.js new file mode 100644 index 0000000..d56b76a --- /dev/null +++ b/dist/drive/driveGetStream.js @@ -0,0 +1,33 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.driveGetStream = void 0; +const driveGetStream = async function ({ link: url, type, signal, providerContext, }) { + const headers = providerContext.commonHeaders; + try { + if (type === 'movie') { + const res = await providerContext.axios.get(url, { headers }); + const html = res.data; + const $ = providerContext.cheerio.load(html); + const link = $('a:contains("HubCloud")').attr('href'); + url = link || url; + } + const res = await providerContext.axios.get(url, { headers }); + let redirectUrl = res.data.match(//i)?.[1]; + if (url.includes('/archives/')) { + redirectUrl = res.data.match(/]*href="(https:\/\/hubcloud\.[^\/]+\/[^"]+)"/i)?.[1]; + } + if (!redirectUrl) { + return await providerContext.extractors.hubcloudExtracter(url, signal); + } + const res2 = await providerContext.axios.get(redirectUrl, { headers }); + const data = res2.data; + const $ = providerContext.cheerio.load(data); + const hubcloudLink = $('.fa-file-download').parent().attr('href'); + return await providerContext.extractors.hubcloudExtracter(hubcloudLink?.includes('https://hubcloud') ? hubcloudLink : redirectUrl, signal); + } + catch (err) { + console.error('Movies Drive err', err); + return []; + } +}; +exports.driveGetStream = driveGetStream; diff --git a/dist/drive/index.js b/dist/drive/index.js new file mode 100644 index 0000000..71fc32a --- /dev/null +++ b/dist/drive/index.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.moviesDrive = void 0; +const catalog_1 = require("./catalog"); +const driveGetEpisodesList_1 = require("./driveGetEpisodesList"); +const driveGetInfo_1 = require("./driveGetInfo"); +const driveGetPosts_1 = require("./driveGetPosts"); +const driveGetStream_1 = require("./driveGetStream"); +exports.moviesDrive = { + catalog: catalog_1.driveCatalog, + genres: catalog_1.driveGenresList, + GetMetaData: driveGetInfo_1.driveGetInfo, + GetHomePosts: driveGetPosts_1.driveGetPosts, + GetStream: driveGetStream_1.driveGetStream, + GetEpisodeLinks: driveGetEpisodesList_1.driveGetEpisodeLinks, + GetSearchPosts: driveGetPosts_1.driveGetSearchPost, +}; diff --git a/dist/filmyfly/ffCatalog.js b/dist/filmyfly/ffCatalog.js new file mode 100644 index 0000000..6ad531b --- /dev/null +++ b/dist/filmyfly/ffCatalog.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ffGenresList = exports.ffCatalog = void 0; +exports.ffCatalog = [ + { + title: 'Home', + filter: '', + }, + { + title: 'Web Series', + filter: '/page-cat/42/Web-Series.html', + }, + { + title: 'Hollywood', + filter: '/page-cat/9/New-Hollywood-Hindi-Dubbed-Movie-2016-2025.html', + }, +]; +exports.ffGenresList = []; diff --git a/dist/filmyfly/ffGetEpisodes.js b/dist/filmyfly/ffGetEpisodes.js new file mode 100644 index 0000000..6dcae91 --- /dev/null +++ b/dist/filmyfly/ffGetEpisodes.js @@ -0,0 +1,33 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ffEpisodeLinks = void 0; +const ffEpisodeLinks = async function ({ url, providerContext, }) { + try { + const headers = providerContext.commonHeaders; + const { axios, cheerio } = providerContext; + const res = await axios.get(url, { headers }); + const data = res.data; + const $ = cheerio.load(data); + const episodeLinks = []; + $('.dlink.dl').map((i, element) => { + const title = $(element) + .find('a') + .text() + ?.replace('Download', '') + ?.trim(); + const link = $(element).find('a').attr('href'); + if (title && link) { + episodeLinks.push({ + title, + link, + }); + } + }); + return episodeLinks; + } + catch (err) { + console.error('cl episode links', err); + return []; + } +}; +exports.ffEpisodeLinks = ffEpisodeLinks; diff --git a/dist/filmyfly/ffGetMeta.js b/dist/filmyfly/ffGetMeta.js new file mode 100644 index 0000000..be939dc --- /dev/null +++ b/dist/filmyfly/ffGetMeta.js @@ -0,0 +1,52 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ffGetInfo = void 0; +const ffGetInfo = async function ({ link, providerContext, }) { + try { + const { axios, cheerio, commonHeaders: headers } = providerContext; + const url = link; + const res = await axios.get(url, { headers }); + const data = res.data; + const $ = cheerio.load(data); + const type = url.includes('tvshows') ? 'series' : 'movie'; + const imdbId = ''; + const title = $('.fname:contains("Name")').find('.colora').text().trim(); + const image = $('.ss').find('img').attr('src') || ''; + const synopsis = $('.fname:contains("Description")') + .find('.colorg') + .text() + .trim(); + const tags = $('.fname:contains("Genre")').find('.colorb').text().split(',') || []; + const rating = ''; + const links = []; + const downloadLink = $('.dlbtn').find('a').attr('href'); + if (downloadLink) { + links.push({ + title: title, + episodesLink: downloadLink, + }); + } + return { + title, + tags, + rating, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } + catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.ffGetInfo = ffGetInfo; diff --git a/dist/filmyfly/ffGetPosts.js b/dist/filmyfly/ffGetPosts.js new file mode 100644 index 0000000..bad5618 --- /dev/null +++ b/dist/filmyfly/ffGetPosts.js @@ -0,0 +1,46 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ffGetPostsSearch = exports.ffGetPosts = void 0; +const ffGetPosts = async function ({ filter, page, signal, providerContext, }) { + const { getBaseUrl } = providerContext; + const baseUrl = await getBaseUrl('filmyfly'); + const url = `${baseUrl + filter}/${page}`; + return posts({ url, signal, baseUrl, providerContext }); +}; +exports.ffGetPosts = ffGetPosts; +const ffGetPostsSearch = async function ({ searchQuery, page, signal, providerContext, }) { + const { getBaseUrl } = providerContext; + const baseUrl = await getBaseUrl('filmyfly'); + const url = `${baseUrl}/site-1.html?to-search=${searchQuery}`; + if (page > 1) { + return []; + } + return posts({ url, signal, baseUrl, providerContext }); +}; +exports.ffGetPostsSearch = ffGetPostsSearch; +async function posts({ url, signal, baseUrl, providerContext, }) { + try { + const { cheerio, commonHeaders: headers } = providerContext; + const res = await fetch(url, { headers, signal }); + const data = await res.text(); + const $ = cheerio.load(data); + const catalog = []; + $('.A2,.A10,.fl').map((i, element) => { + const title = $(element).find('a').eq(1).text() || $(element).find('b').text(); + const link = $(element).find('a').attr('href'); + const image = $(element).find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title, + link: baseUrl + link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('ff error ', err); + return []; + } +} diff --git a/dist/filmyfly/ffGetStream.js b/dist/filmyfly/ffGetStream.js new file mode 100644 index 0000000..82aa28d --- /dev/null +++ b/dist/filmyfly/ffGetStream.js @@ -0,0 +1,40 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ffGetStream = void 0; +const ffGetStream = async function ({ link, signal, providerContext, }) { + try { + const res = await providerContext.axios.get(link, { signal }); + const data = res.data; + const $ = providerContext.cheerio.load(data); + const streams = []; + const elements = $('.button2,.button1,.button3,.button4,.button').toArray(); + const promises = elements.map(async (element) => { + const title = $(element).text(); + let link = $(element).attr('href'); + if (title.includes('GDFLIX') && link) { + const gdLinks = await providerContext.extractors.gdFlixExtracter(link, signal); + streams.push(...gdLinks); + } + const alreadyAdded = streams.find(s => s.link === link); + if (title && + link && + !title.includes('Watch') && + !title.includes('Login') && + !title.includes('GoFile') && + !alreadyAdded) { + streams.push({ + server: title, + link: link, + type: 'mkv', + }); + } + }); + await Promise.all(promises); + return streams; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.ffGetStream = ffGetStream; diff --git a/dist/filmyfly/index.js b/dist/filmyfly/index.js new file mode 100644 index 0000000..180f4c9 --- /dev/null +++ b/dist/filmyfly/index.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.filmyfly = void 0; +const ffCatalog_1 = require("./ffCatalog"); +const ffGetEpisodes_1 = require("./ffGetEpisodes"); +const ffGetMeta_1 = require("./ffGetMeta"); +const ffGetPosts_1 = require("./ffGetPosts"); +const ffGetStream_1 = require("./ffGetStream"); +exports.filmyfly = { + catalog: ffCatalog_1.ffCatalog, + genres: ffCatalog_1.ffGenresList, + GetHomePosts: ffGetPosts_1.ffGetPosts, + GetMetaData: ffGetMeta_1.ffGetInfo, + GetSearchPosts: ffGetPosts_1.ffGetPostsSearch, + GetEpisodeLinks: ffGetEpisodes_1.ffEpisodeLinks, + GetStream: ffGetStream_1.ffGetStream, +}; diff --git a/dist/flixhq/flixhqCatalog.js b/dist/flixhq/flixhqCatalog.js new file mode 100644 index 0000000..f4882f8 --- /dev/null +++ b/dist/flixhq/flixhqCatalog.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.flixhqGenresList = exports.flixhqCatalog = void 0; +exports.flixhqCatalog = [ + { + title: 'Trending', + filter: '/trending', + }, + { + title: 'Movies', + filter: '/recent-movies', + }, + { + title: 'TV Shows', + filter: '/recent-shows', + }, +]; +exports.flixhqGenresList = []; diff --git a/dist/flixhq/flixhqGetInfo.js b/dist/flixhq/flixhqGetInfo.js new file mode 100644 index 0000000..d1e789b --- /dev/null +++ b/dist/flixhq/flixhqGetInfo.js @@ -0,0 +1,56 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.flixhqGetInfo = void 0; +const flixhqGetInfo = async function ({ link: id, providerContext, }) { + try { + const { axios, getBaseUrl } = providerContext; + const baseUrl = await getBaseUrl('consumet'); + const url = `${baseUrl}/movies/flixhq/info?id=` + id; + const res = await axios.get(url); + const data = res.data; + const meta = { + title: data.title, + synopsis: data.description.replace(/<[^>]*>?/gm, '').trim(), + image: data.cover, + cast: data.casts, + rating: data.rating, + tags: [data?.type, data?.duration, data.releaseDate.split('-')[0]], + imdbId: '', + type: data.episodes.length > 1 ? 'series' : 'movie', + }; + const links = []; + data.episodes.forEach((episode) => { + const title = episode?.number + ? 'Season-' + episode?.season + ' Ep-' + episode.number + : episode.title; + const link = episode.id + '*' + data.id; + if (link && title) { + links.push({ + title, + link, + }); + } + }); + return { + ...meta, + linkList: [ + { + title: meta.title, + directLinks: links, + }, + ], + }; + } + catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.flixhqGetInfo = flixhqGetInfo; diff --git a/dist/flixhq/flixhqGetPosts.js b/dist/flixhq/flixhqGetPosts.js new file mode 100644 index 0000000..25fb039 --- /dev/null +++ b/dist/flixhq/flixhqGetPosts.js @@ -0,0 +1,44 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.flixhqGetSearchPost = exports.flixhqGetPosts = void 0; +const flixhqGetPosts = async function ({ filter, signal, providerContext, }) { + const { getBaseUrl } = providerContext; + const urlRes = await getBaseUrl('consumet'); + const baseUrl = urlRes + '/movies/flixhq'; + const url = `${baseUrl + filter}`; + return posts({ url, signal, providerContext }); +}; +exports.flixhqGetPosts = flixhqGetPosts; +const flixhqGetSearchPost = async function ({ searchQuery, page, signal, providerContext, }) { + const { getBaseUrl } = providerContext; + const urlRes = await getBaseUrl('consumet'); + const baseUrl = urlRes + '/movies/flixhq'; + const url = `${baseUrl}/${searchQuery}?page=${page}`; + return posts({ url, signal, providerContext }); +}; +exports.flixhqGetSearchPost = flixhqGetSearchPost; +async function posts({ url, signal, providerContext, }) { + try { + const { axios } = providerContext; + const res = await axios.get(url, { signal }); + const data = res.data?.results || res.data; + const catalog = []; + data?.map((element) => { + const title = element.title; + const link = element.id; + const image = element.image; + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('flixhq error ', err); + return []; + } +} diff --git a/dist/flixhq/flixhqGetStream.js b/dist/flixhq/flixhqGetStream.js new file mode 100644 index 0000000..45f4654 --- /dev/null +++ b/dist/flixhq/flixhqGetStream.js @@ -0,0 +1,55 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.flixhqGetStream = void 0; +const types_1 = require("../types"); +const flixhqGetStream = async function ({ link: id, providerContext, }) { + try { + const { getBaseUrl } = providerContext; + const episodeId = id.split('*')[0]; + const mediaId = id.split('*')[1]; + const baseUrl = await getBaseUrl('consumet'); + const serverUrl = `${baseUrl}/movies/flixhq/servers?episodeId=${episodeId}&mediaId=${mediaId}`; + const res = await fetch(serverUrl); + const servers = await res.json(); + const streamLinks = []; + for (const server of servers) { + const streamUrl = `${baseUrl}/movies/flixhq/watch?server=` + + server.name + + '&episodeId=' + + episodeId + + '&mediaId=' + + mediaId; + const streamRes = await fetch(streamUrl); + const streamData = await streamRes.json(); + const subtitles = []; + if (streamData?.sources?.length > 0) { + if (streamData.subtitles) { + streamData.subtitles.forEach((sub) => { + subtitles.push({ + language: sub?.lang?.slice(0, 2), + uri: sub?.url, + type: types_1.TextTrackType.VTT, + title: sub?.lang, + }); + }); + } + streamData.sources.forEach((source) => { + streamLinks.push({ + server: server?.name + + '-' + + source?.quality?.replace('auto', 'MultiQuality'), + link: source.url, + type: source.isM3U8 ? 'm3u8' : 'mp4', + subtitles: subtitles, + }); + }); + } + } + return streamLinks; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.flixhqGetStream = flixhqGetStream; diff --git a/dist/flixhq/index.js b/dist/flixhq/index.js new file mode 100644 index 0000000..0b61c11 --- /dev/null +++ b/dist/flixhq/index.js @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.flixhq = void 0; +const flixhqCatalog_1 = require("./flixhqCatalog"); +const flixhqGetInfo_1 = require("./flixhqGetInfo"); +const flixhqGetPosts_1 = require("./flixhqGetPosts"); +const flixhqGetStream_1 = require("./flixhqGetStream"); +exports.flixhq = { + catalog: flixhqCatalog_1.flixhqCatalog, + genres: flixhqCatalog_1.flixhqGenresList, + GetMetaData: flixhqGetInfo_1.flixhqGetInfo, + GetHomePosts: flixhqGetPosts_1.flixhqGetPosts, + GetStream: flixhqGetStream_1.flixhqGetStream, + GetSearchPosts: flixhqGetPosts_1.flixhqGetSearchPost, + nonDownloadableServer: ['upcloud-MultiQuality', 'vidcloud-MultiQuality'], + nonStreamableServer: [ + 'upcloud-1080', + 'upcloud-720', + 'upcloud-480', + 'upcloud-360', + 'vidcloud-1080', + 'vidcloud-720', + 'vidcloud-480', + 'vidcloud-360', + ], +}; diff --git a/dist/gdflixExtractor.js b/dist/gdflixExtractor.js new file mode 100644 index 0000000..059a9b3 --- /dev/null +++ b/dist/gdflixExtractor.js @@ -0,0 +1,201 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.gdFlixExtracter = gdFlixExtracter; +const axios_1 = __importDefault(require("axios")); +const cheerio = __importStar(require("cheerio")); +const headers_1 = require("./headers"); +async function gdFlixExtracter(link, signal) { + try { + const streamLinks = []; + const res = await (0, axios_1.default)(`${link}`, { headers: headers_1.headers, signal }); + console.log('gdFlixExtracter', link); + const data = res.data; + let $drive = cheerio.load(data); + // handle if redirected to another link + if ($drive('body').attr('onload')?.includes('location.replace')) { + const newLink = $drive('body') + .attr('onload') + ?.split("location.replace('")?.[1] + .split("'")?.[0]; + console.log('newLink', newLink); + if (newLink) { + const newRes = await axios_1.default.get(newLink, { headers: headers_1.headers, signal }); + $drive = cheerio.load(newRes.data); + } + } + // try { + // const resumeBot = $drive('.fab.fa-artstation').prev().attr('href') || ''; + // console.log('resumeBot', resumeBot); + // const resumeBotRes = await axios.get(resumeBot, {headers}); + // const resumeBotToken = resumeBotRes.data.match( + // /formData\.append\('token', '([a-f0-9]+)'\)/, + // )[1]; + // const resumeBotBody = new FormData(); + // resumeBotBody.append('token', resumeBotToken); + // const resumeBotPath = resumeBotRes.data.match( + // /fetch\('\/download\?id=([a-zA-Z0-9\/+]+)'/, + // )[1]; + // const resumeBotBaseUrl = resumeBot.split('/download')[0]; + // // console.log( + // // 'resumeBotPath', + // // resumeBotBaseUrl + '/download?id=' + resumeBotPath, + // // ); + // // console.log('resumeBotBody', resumeBotToken); + // const resumeBotDownload = await fetch( + // resumeBotBaseUrl + '/download?id=' + resumeBotPath, + // { + // method: 'POST', + // body: resumeBotBody, + // headers: { + // Referer: resumeBot, + // Cookie: 'PHPSESSID=7e9658ce7c805dab5bbcea9046f7f308', + // }, + // }, + // ); + // const resumeBotDownloadData = await resumeBotDownload.json(); + // console.log('resumeBotDownloadData', resumeBotDownloadData.url); + // streamLinks.push({ + // server: 'ResumeBot', + // link: resumeBotDownloadData.url, + // type: 'mkv', + // }); + // } catch (err) { + // console.log('ResumeBot link not found', err); + // } + /// resume cloud + try { + const baseUrl = link.split('/').slice(0, 3).join('/'); + const resumeDrive = $drive('.btn-secondary').attr('href') || ''; + console.log('resumeDrive', resumeDrive); + if (resumeDrive.includes('indexbot')) { + const resumeBotRes = await axios_1.default.get(resumeDrive, { headers: headers_1.headers }); + const resumeBotToken = resumeBotRes.data.match(/formData\.append\('token', '([a-f0-9]+)'\)/)[1]; + const resumeBotBody = new FormData(); + resumeBotBody.append('token', resumeBotToken); + const resumeBotPath = resumeBotRes.data.match(/fetch\('\/download\?id=([a-zA-Z0-9\/+]+)'/)[1]; + const resumeBotBaseUrl = resumeDrive.split('/download')[0]; + // console.log( + // 'resumeBotPath', + // resumeBotBaseUrl + '/download?id=' + resumeBotPath, + // ); + // console.log('resumeBotBody', resumeBotToken); + const resumeBotDownload = await fetch(resumeBotBaseUrl + '/download?id=' + resumeBotPath, { + method: 'POST', + body: resumeBotBody, + headers: { + Referer: resumeDrive, + Cookie: 'PHPSESSID=7e9658ce7c805dab5bbcea9046f7f308', + }, + }); + const resumeBotDownloadData = await resumeBotDownload.json(); + console.log('resumeBotDownloadData', resumeBotDownloadData.url); + streamLinks.push({ + server: 'ResumeBot', + link: resumeBotDownloadData.url, + type: 'mkv', + }); + } + else { + const url = baseUrl + resumeDrive; + const resumeDriveRes = await axios_1.default.get(url, { headers: headers_1.headers }); + const resumeDriveHtml = resumeDriveRes.data; + const $resumeDrive = cheerio.load(resumeDriveHtml); + const resumeLink = $resumeDrive('.btn-success').attr('href'); + // console.log('resumeLink', resumeLink); + if (resumeLink) { + streamLinks.push({ + server: 'ResumeCloud', + link: resumeLink, + type: 'mkv', + }); + } + } + } + catch (err) { + console.log('Resume link not found'); + } + //instant link + try { + const seed = $drive('.btn-danger').attr('href') || ''; + console.log('seed', seed); + if (!seed.includes('?url=')) { + const newLinkRes = await axios_1.default.head(seed, { headers: headers_1.headers, signal }); + console.log('newLinkRes', newLinkRes.request?.responseURL); + const newLink = newLinkRes.request?.responseURL?.split('?url=')?.[1] || seed; + streamLinks.push({ server: 'G-Drive', link: newLink, type: 'mkv' }); + } + else { + const instantToken = seed.split('=')[1]; + // console.log('InstantToken', instantToken); + const InstantFromData = new FormData(); + InstantFromData.append('keys', instantToken); + const videoSeedUrl = seed.split('/').slice(0, 3).join('/') + '/api'; + // console.log('videoSeedUrl', videoSeedUrl); + const instantLinkRes = await fetch(videoSeedUrl, { + method: 'POST', + body: InstantFromData, + headers: { + 'x-token': videoSeedUrl, + }, + }); + const instantLinkData = await instantLinkRes.json(); + // console.log('instantLinkData', instantLinkData); + if (instantLinkData.error === false) { + const instantLink = instantLinkData.url; + streamLinks.push({ + server: 'Gdrive-Instant', + link: instantLink, + type: 'mkv', + }); + } + else { + console.log('Instant link not found', instantLinkData); + } + } + } + catch (err) { + console.log('Instant link not found', err); + } + return streamLinks; + } + catch (error) { + console.log('gdflix error: ', error); + return []; + } +} diff --git a/dist/getBaseUrl.js b/dist/getBaseUrl.js new file mode 100644 index 0000000..8f42fa3 --- /dev/null +++ b/dist/getBaseUrl.js @@ -0,0 +1,33 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getBaseUrl = void 0; +const storage_1 = require("../storage"); +// 1 hour +const expireTime = 60 * 60 * 1000; +const getBaseUrl = async (providerValue) => { + try { + let baseUrl = ''; + const cacheKey = 'CacheBaseUrl' + providerValue; + const timeKey = 'baseUrlTime' + providerValue; + const cachedUrl = storage_1.cacheStorageService.getString(cacheKey); + const cachedTime = storage_1.cacheStorageService.getObject(timeKey); + if (cachedUrl && + cachedTime && + Date.now() - cachedTime < expireTime) { + baseUrl = cachedUrl; + } + else { + const baseUrlRes = await fetch('https://himanshu8443.github.io/providers/modflix.json'); + const baseUrlData = await baseUrlRes.json(); + baseUrl = baseUrlData[providerValue].url; + storage_1.cacheStorageService.setString(cacheKey, baseUrl); + storage_1.cacheStorageService.setObject(timeKey, Date.now()); + } + return baseUrl; + } + catch (error) { + console.error(`Error fetching baseUrl: ${providerValue}`, error); + return ''; + } +}; +exports.getBaseUrl = getBaseUrl; diff --git a/dist/gofileExtracter.js b/dist/gofileExtracter.js new file mode 100644 index 0000000..246fff2 --- /dev/null +++ b/dist/gofileExtracter.js @@ -0,0 +1,37 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.gofileExtracter = gofileExtracter; +const axios_1 = __importDefault(require("axios")); +async function gofileExtracter(id) { + try { + const gofileRes = await axios_1.default.get('https://gofile.io/d/' + id); + const genAccountres = await axios_1.default.post('https://api.gofile.io/accounts'); + const token = genAccountres.data.data.token; + console.log('gofile token', token); + const wtRes = await axios_1.default.get('https://gofile.io/dist/js/global.js'); + const wt = wtRes.data.match(/appdata\.wt\s*=\s*["']([^"']+)["']/)[1]; + console.log('gofile wt', wt); + const res = await axios_1.default.get(`https://api.gofile.io/contents/${id}?wt=${wt}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + const oId = Object.keys(res.data.data.children)[0]; + console.log('gofile extracter', res.data.data.children[oId].link); + const link = res.data.data.children[oId].link; + return { + link, + token, + }; + } + catch (e) { + console.log('gofile extracter err', e); + return { + link: '', + token: '', + }; + } +} diff --git a/dist/guardahd/GetGuardahdStream.js b/dist/guardahd/GetGuardahdStream.js new file mode 100644 index 0000000..b19502f --- /dev/null +++ b/dist/guardahd/GetGuardahdStream.js @@ -0,0 +1,104 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.GuardahdGetStream = void 0; +const GuardahdGetStream = async function ({ link: id, type, providerContext, }) { + try { + const { axios, cheerio, extractors } = providerContext; + const { superVideoExtractor } = extractors; + async function ExtractGuardahd({ imdb, // type, + // episode, + } // season, + ) { + try { + const baseUrl = 'https://guardahd.stream'; + const path = '/set-movie-a/' + imdb; + const url = baseUrl + path; + console.log('url:', url); + const res = await axios.get(url, { timeout: 4000 }); + const html = res.data; + const $ = cheerio.load(html); + const superVideoUrl = $('li:contains("supervideo")').attr('data-link'); + console.log('superVideoUrl:', superVideoUrl); + if (!superVideoUrl) { + return null; + } + const controller2 = new AbortController(); + const signal2 = controller2.signal; + setTimeout(() => controller2.abort(), 4000); + const res2 = await fetch('https:' + superVideoUrl, { signal: signal2 }); + const data = await res2.text(); + // console.log('mostraguarda data:', data); + const streamUrl = await superVideoExtractor(data); + return streamUrl; + } + catch (err) { + console.error('Error in GetMostraguardaStram:', err); + } + } + async function GetMostraguardaStream({ imdb, type, season, episode, }) { + try { + const baseUrl = 'https://mostraguarda.stream'; + const path = type === 'tv' + ? `/serie/${imdb}/${season}/${episode}` + : `/movie/${imdb}`; + const url = baseUrl + path; + console.log('url:', url); + const res = await axios(url, { timeout: 4000 }); + const html = res.data; + const $ = cheerio.load(html); + const superVideoUrl = $('li:contains("supervideo")').attr('data-link'); + console.log('superVideoUrl:', superVideoUrl); + if (!superVideoUrl) { + return null; + } + const controller2 = new AbortController(); + const signal2 = controller2.signal; + setTimeout(() => controller2.abort(), 4000); + const res2 = await fetch('https:' + superVideoUrl, { signal: signal2 }); + const data = await res2.text(); + // console.log('mostraguarda data:', data); + const streamUrl = await superVideoExtractor(data); + return streamUrl; + } + catch (err) { + console.error('Error in GetMostraguardaStram:', err); + } + } + console.log(id); + const streams = []; + const { imdbId, season, episode } = JSON.parse(id); + ///// mostraguarda + const mostraguardaStream = await GetMostraguardaStream({ + imdb: imdbId, + type: type, + season: season, + episode: episode, + }); + if (mostraguardaStream) { + streams.push({ + server: 'Supervideo 1', + link: mostraguardaStream, + type: 'm3u8', + }); + } + const guardahdStream = await ExtractGuardahd({ + imdb: imdbId, + type: type, + season: season, + episode: episode, + }); + if (guardahdStream) { + streams.push({ + server: 'Supervideo 2', + link: guardahdStream, + type: 'm3u8', + }); + } + return streams; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.GuardahdGetStream = GuardahdGetStream; diff --git a/dist/guardahd/guardahdCatalog.js b/dist/guardahd/guardahdCatalog.js new file mode 100644 index 0000000..3f4b73f --- /dev/null +++ b/dist/guardahd/guardahdCatalog.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.guardahdGenresList = exports.guardahdCatalog = void 0; +exports.guardahdCatalog = [ + { + title: 'Popular Movies', + filter: '/top/catalog/movie/top.json', + }, + { + title: 'Featured Movies', + filter: '/imdbRating/catalog/movie/imdbRating.json', + }, +]; +exports.guardahdGenresList = []; diff --git a/dist/guardahd/guardahdGetPosts.js b/dist/guardahd/guardahdGetPosts.js new file mode 100644 index 0000000..186008d --- /dev/null +++ b/dist/guardahd/guardahdGetPosts.js @@ -0,0 +1,34 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.guardahdGetSearchPosts = void 0; +const guardahdGetSearchPosts = async function ({ searchQuery, page, signal, providerContext, }) { + try { + const { axios, commonHeaders: headers } = providerContext; + if (page > 1) { + return []; + } + const catalog = []; + const url2 = `https://v3-cinemeta.strem.io/catalog/movie/top/search=${encodeURI(searchQuery)}.json`; + const res2 = await axios.get(url2, { headers, signal }); + const data2 = res2.data; + data2?.metas.map((result) => { + const title = result?.name || ''; + const id = result?.imdb_id || result?.id; + const image = result?.poster; + const type = result?.type; + if (id) { + catalog.push({ + title: title, + link: `https://v3-cinemeta.strem.io/meta/${type}/${id}.json`, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('AutoEmbed error ', err); + return []; + } +}; +exports.guardahdGetSearchPosts = guardahdGetSearchPosts; diff --git a/dist/guardahd/index.js b/dist/guardahd/index.js new file mode 100644 index 0000000..3188504 --- /dev/null +++ b/dist/guardahd/index.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.guardahd = void 0; +const guardahdCatalog_1 = require("./guardahdCatalog"); +const allGetInfo_1 = require("../autoEmbed/allGetInfo"); +const allGetPost_1 = require("../autoEmbed/allGetPost"); +const guardahdGetPosts_1 = require("./guardahdGetPosts"); +const GetGuardahdStream_1 = require("./GetGuardahdStream"); +exports.guardahd = { + catalog: guardahdCatalog_1.guardahdCatalog, + genres: guardahdCatalog_1.guardahdGenresList, + GetMetaData: allGetInfo_1.allGetInfo, + GetHomePosts: allGetPost_1.allGetPost, + GetStream: GetGuardahdStream_1.GuardahdGetStream, + GetSearchPosts: guardahdGetPosts_1.guardahdGetSearchPosts, +}; diff --git a/dist/hdhub4u/hdhub4uGetSteam.js b/dist/hdhub4u/hdhub4uGetSteam.js new file mode 100644 index 0000000..51e56b0 --- /dev/null +++ b/dist/hdhub4u/hdhub4uGetSteam.js @@ -0,0 +1,150 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.hdhub4uGetStream = hdhub4uGetStream; +exports.getRedirectLinks = getRedirectLinks; +exports.decodeString = decodeString; +async function hdhub4uGetStream({ link, signal, providerContext, }) { + const { axios, cheerio, extractors, commonHeaders: headers } = providerContext; + const { hubcloudExtracter } = extractors; + let hubdriveLink = ''; + if (link.includes('hubdrive')) { + const hubdriveRes = await axios.get(link, { headers, signal }); + const hubdriveText = hubdriveRes.data; + const $ = cheerio.load(hubdriveText); + hubdriveLink = + $('.btn.btn-primary.btn-user.btn-success1.m-1').attr('href') || link; + } + else { + const res = await axios.get(link, { headers, signal }); + const text = res.data; + const encryptedString = text.split("s('o','")?.[1]?.split("',180")?.[0]; + const decodedString = decodeString(encryptedString); + link = atob(decodedString?.o); + const redirectLink = await getRedirectLinks(link, signal, headers); + const redirectLinkRes = await axios.get(redirectLink, { headers, signal }); + const redirectLinkText = redirectLinkRes.data; + const $ = cheerio.load(redirectLinkText); + hubdriveLink = + $('h3:contains("1080p")').find('a').attr('href') || + redirectLinkText.match(/href="(https:\/\/hubcloud\.[^\/]+\/drive\/[^"]+)"/)[1]; + if (hubdriveLink.includes('hubdrive')) { + const hubdriveRes = await axios.get(hubdriveLink, { headers, signal }); + const hubdriveText = hubdriveRes.data; + const $$ = cheerio.load(hubdriveText); + hubdriveLink = + $$('.btn.btn-primary.btn-user.btn-success1.m-1').attr('href') || + hubdriveLink; + } + } + const hubdriveLinkRes = await axios.get(hubdriveLink, { headers, signal }); + const hubcloudText = hubdriveLinkRes.data; + const hubcloudLink = hubcloudText.match(//i)?.[1] || hubdriveLink; + try { + return await hubcloudExtracter(hubcloudLink, signal); + } + catch (error) { + console.log('hd hub 4 getStream error: ', error); + return []; + } +} +const encode = function (value) { + return btoa(value.toString()); +}; +const decode = function (value) { + if (value === undefined) { + return ''; + } + return atob(value.toString()); +}; +const pen = function (value) { + return value.replace(/[a-zA-Z]/g, function (_0x1a470e) { + return String.fromCharCode((_0x1a470e <= 'Z' ? 90 : 122) >= + (_0x1a470e = _0x1a470e.charCodeAt(0) + 13) + ? _0x1a470e + : _0x1a470e - 26); + }); +}; +const abortableTimeout = (ms, { signal } = {}) => { + return new Promise((resolve, reject) => { + if (signal && signal.aborted) { + return reject(new Error('Aborted')); + } + const timer = setTimeout(resolve, ms); + if (signal) { + signal.addEventListener('abort', () => { + clearTimeout(timer); + reject(new Error('Aborted')); + }); + } + }); +}; +async function getRedirectLinks(link, signal, headers) { + try { + const res = await fetch(link, { headers, signal }); + const resText = await res.text(); + var regex = /ck\('_wp_http_\d+','([^']+)'/g; + var combinedString = ''; + var match; + while ((match = regex.exec(resText)) !== null) { + // console.log(match[1]); + combinedString += match[1]; + } + // console.log(decode(combinedString)); + const decodedString = decode(pen(decode(decode(combinedString)))); + // console.log(decodedString); + const data = JSON.parse(decodedString); + console.log(data); + const token = encode(data?.data); + const blogLink = data?.wp_http1 + '?re=' + token; + // abort timeout on signal + let wait = abortableTimeout((Number(data?.total_time) + 3) * 1000, { + signal, + }); + await wait; + console.log('blogLink', blogLink); + let vcloudLink = 'Invalid Request'; + while (vcloudLink.includes('Invalid Request')) { + const blogRes = await fetch(blogLink, { headers, signal }); + const blogResText = (await blogRes.text()); + if (blogResText.includes('Invalid Request')) { + console.log(blogResText); + } + else { + vcloudLink = blogResText.match(/var reurl = "([^"]+)"/) || ''; + break; + } + } + // console.log('vcloudLink', vcloudLink?.[1]); + return blogLink || link; + } + catch (err) { + console.log('Error in getRedirectLinks', err); + return link; + } +} +function rot13(str) { + return str.replace(/[a-zA-Z]/g, function (char) { + const charCode = char.charCodeAt(0); + const isUpperCase = char <= 'Z'; + const baseCharCode = isUpperCase ? 65 : 97; + return String.fromCharCode(((charCode - baseCharCode + 13) % 26) + baseCharCode); + }); +} +function decodeString(encryptedString) { + try { + // First base64 decode + let decoded = atob(encryptedString); + // Second base64 decode + decoded = atob(decoded); + // ROT13 decode + decoded = rot13(decoded); + // Third base64 decode + decoded = atob(decoded); + // Parse JSON + return JSON.parse(decoded); + } + catch (error) { + console.error('Error decoding string:', error); + return null; + } +} diff --git a/dist/hdhub4u/hdhubCatalog.js b/dist/hdhub4u/hdhubCatalog.js new file mode 100644 index 0000000..a5412f7 --- /dev/null +++ b/dist/hdhub4u/hdhubCatalog.js @@ -0,0 +1,63 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.hdhub4uGenresList = exports.hdhub4uCatalog = void 0; +exports.hdhub4uCatalog = [ + { + title: 'Latest', + filter: '', + }, + { + title: 'Web Series', + filter: '/category/web-series', + }, + { + title: 'Hollywood ', + filter: '/category/hollywood-movies', + }, + { + title: 'South Movies', + filter: '/category/south-hindi-movies', + }, +]; +exports.hdhub4uGenresList = [ + { + title: 'Action', + filter: '/category/action', + }, + { + title: 'Crime', + filter: '/category/crime', + }, + { + title: 'Comedy', + filter: '/category/comedy', + }, + { + title: 'Drama', + filter: '/category/drama', + }, + { + title: 'Horror', + filter: '/category/horror', + }, + { + title: 'Family', + filter: '/category/family', + }, + { + title: 'Sci-Fi', + filter: '/category/sifi', + }, + { + title: 'Thriller', + filter: '/category/triller', + }, + { + title: 'Romance', + filter: '/category/romance', + }, + { + title: 'Fight', + filter: '/category/fight', + }, +]; diff --git a/dist/hdhub4u/hdhubGetInfo.js b/dist/hdhub4u/hdhubGetInfo.js new file mode 100644 index 0000000..a518868 --- /dev/null +++ b/dist/hdhub4u/hdhubGetInfo.js @@ -0,0 +1,113 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.hdhub4uGetInfo = void 0; +const hdbHeaders = { + Cookie: 'xla=s4t', + Referer: 'https://google.com', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0', +}; +const hdhub4uGetInfo = async function ({ link, providerContext, }) { + try { + const { axios, cheerio } = providerContext; + const url = link; + const res = await axios.get(url, { headers: hdbHeaders }); + const data = res.data; + const $ = cheerio.load(data); + const container = $('.page-body'); + const imdbId = container + .find('a[href*="imdb.com/title/tt"]:not([href*="imdb.com/title/tt/"])') + .attr('href') + ?.split('/')[4] || ''; + const title = container + .find('h2[data-ved="2ahUKEwjL0NrBk4vnAhWlH7cAHRCeAlwQ3B0oATAfegQIFBAM"],h2[data-ved="2ahUKEwiP0pGdlermAhUFYVAKHV8tAmgQ3B0oATAZegQIDhAM"]') + .text(); + const type = title.toLocaleLowerCase().includes('season') + ? 'series' + : 'movie'; + const synopsis = container + .find('strong:contains("DESCRIPTION")') + .parent() + .text() + .replace('DESCRIPTION:', ''); + const image = container.find('img[decoding="async"]').attr('src') || ''; + // Links + const links = []; + const directLink = []; + // direct link type + $('strong:contains("EPiSODE")').map((i, element) => { + const epTitle = $(element).parent().parent().text(); + const episodesLink = $(element) + .parent() + .parent() + .parent() + .next() + .next() + .find('a') + .attr('href') || + $(element).parent().parent().parent().next().find('a').attr('href'); + if (episodesLink && episodesLink) { + directLink.push({ + title: epTitle, + link: episodesLink, + }); + } + }); + if (directLink.length === 0) { + container.find('a:contains("EPiSODE")').map((i, element) => { + const epTitle = $(element).text(); + const episodesLink = $(element).attr('href'); + if (episodesLink) { + directLink.push({ + title: epTitle.toLocaleUpperCase(), + link: episodesLink, + }); + } + }); + } + if (directLink.length > 0) { + links.push({ + title: title, + directLinks: directLink, + }); + } + if (directLink.length === 0) { + container + .find('a:contains("480"),a:contains("720"),a:contains("1080"),a:contains("2160"),a:contains("4K")') + .map((i, element) => { + const quality = $(element) + .text() + .match(/\b(480p|720p|1080p|2160p)\b/i)?.[0] || ''; + const movieLinks = $(element).attr('href'); + const title = $(element).text(); + if (movieLinks) { + links.push({ + directLinks: [{ link: movieLinks, title: 'Movie', type: 'movie' }], + quality: quality, + title: title, + }); + } + }); + } + // console.log('drive meta', title, synopsis, image, imdbId, type, links); + return { + title, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } + catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.hdhub4uGetInfo = hdhub4uGetInfo; diff --git a/dist/hdhub4u/hdhubGetPosts.js b/dist/hdhub4u/hdhubGetPosts.js new file mode 100644 index 0000000..5a07330 --- /dev/null +++ b/dist/hdhub4u/hdhubGetPosts.js @@ -0,0 +1,53 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.hdhubGetPostsSearch = exports.hdhubGetPosts = void 0; +const hdbHeaders = { + Cookie: 'xla=s4t', + Referer: 'https://google.com', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0', +}; +const hdhubGetPosts = async function ({ filter, page, signal, providerContext, }) { + const { getBaseUrl } = providerContext; + const baseUrl = await getBaseUrl('hdhub'); + const url = `${baseUrl + filter}/page/${page}/`; + return posts({ url, signal, providerContext }); +}; +exports.hdhubGetPosts = hdhubGetPosts; +const hdhubGetPostsSearch = async function ({ searchQuery, page, signal, providerContext, }) { + const { getBaseUrl } = providerContext; + const baseUrl = await getBaseUrl('hdhub'); + const url = `${baseUrl}/page/${page}/?s=${searchQuery}`; + return posts({ url, signal, providerContext }); +}; +exports.hdhubGetPostsSearch = hdhubGetPostsSearch; +async function posts({ url, signal, providerContext, }) { + const { cheerio } = providerContext; + try { + const res = await fetch(url, { + headers: hdbHeaders, + signal, + }); + const data = await res.text(); + const $ = cheerio.load(data); + const catalog = []; + $('.recent-movies') + .children() + .map((i, element) => { + const title = $(element).find('figure').find('img').attr('alt'); + const link = $(element).find('a').attr('href'); + const image = $(element).find('figure').find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title.replace('Download', '').trim(), + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('hdhubGetPosts error ', err); + return []; + } +} diff --git a/dist/hdhub4u/index.js b/dist/hdhub4u/index.js new file mode 100644 index 0000000..79da534 --- /dev/null +++ b/dist/hdhub4u/index.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.hdhub4uProvider = void 0; +const hdhubCatalog_1 = require("./hdhubCatalog"); +const hdhubGetInfo_1 = require("./hdhubGetInfo"); +const hdhub4uGetSteam_1 = require("./hdhub4uGetSteam"); +const hdhubGetPosts_1 = require("./hdhubGetPosts"); +exports.hdhub4uProvider = { + catalog: hdhubCatalog_1.hdhub4uCatalog, + genres: hdhubCatalog_1.hdhub4uGenresList, + GetMetaData: hdhubGetInfo_1.hdhub4uGetInfo, + GetStream: hdhub4uGetSteam_1.hdhub4uGetStream, + GetHomePosts: hdhubGetPosts_1.hdhubGetPosts, + GetSearchPosts: hdhubGetPosts_1.hdhubGetPostsSearch, +}; diff --git a/dist/headers.js b/dist/headers.js new file mode 100644 index 0000000..67246b4 --- /dev/null +++ b/dist/headers.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.headers = void 0; +exports.headers = { + 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + // 'Sec-Fetch-Site': 'none', + // 'Sec-Fetch-User': '?1', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', +}; diff --git a/dist/hiAnime/HiGetSteam.js b/dist/hiAnime/HiGetSteam.js new file mode 100644 index 0000000..9e9f011 --- /dev/null +++ b/dist/hiAnime/HiGetSteam.js @@ -0,0 +1,54 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.hiGetStream = void 0; +const types_1 = require("../types"); +const hiGetStream = async function ({ link: id, providerContext, }) { + try { + const { getBaseUrl, axios } = providerContext; + const baseUrl = await getBaseUrl('consumet'); + const servers = ['vidcloud', 'vidstreaming']; + const url = `${baseUrl}/anime/zoro/watch?episodeId=${id}&server=`; + const streamLinks = []; + await Promise.all(servers.map(async (server) => { + try { + const res = await axios.get(url + server); + if (res.data) { + const subtitles = []; + res.data?.subtitles.forEach((sub) => { + if (sub?.lang === 'Thumbnails') + return; + subtitles.push({ + language: sub?.lang?.slice(0, 2) || 'Und', + uri: sub?.url, + title: sub?.lang || 'Undefined', + type: sub?.url?.endsWith('.vtt') + ? types_1.TextTrackType.VTT + : types_1.TextTrackType.SUBRIP, + }); + }); + res.data?.sources.forEach((source) => { + streamLinks.push({ + server: server, + link: source?.url, + type: source?.isM3U8 ? 'm3u8' : 'mp4', + headers: { + Referer: 'https://megacloud.club/', + Origin: 'https://megacloud.club', + }, + subtitles: subtitles, + }); + }); + } + } + catch (e) { + console.log(e); + } + })); + return streamLinks; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.hiGetStream = hiGetStream; diff --git a/dist/hiAnime/hiCatalog.js b/dist/hiAnime/hiCatalog.js new file mode 100644 index 0000000..71ccb37 --- /dev/null +++ b/dist/hiAnime/hiCatalog.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.hiGenresList = exports.hiCatalog = void 0; +exports.hiCatalog = [ + { + title: 'Recent', + filter: '/anime/zoro/recent-episodes', + }, + { + title: 'Top Airing', + filter: '/anime/zoro/top-airing', + }, + { + title: 'Most Popular', + filter: '/anime/zoro/most-popular', + }, + { + title: 'Most Favorited', + filter: '/anime/zoro/most-favorite', + }, +]; +exports.hiGenresList = []; diff --git a/dist/hiAnime/hiGetInfo.js b/dist/hiAnime/hiGetInfo.js new file mode 100644 index 0000000..ffd1770 --- /dev/null +++ b/dist/hiAnime/hiGetInfo.js @@ -0,0 +1,78 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.hiGetInfo = void 0; +const hiGetInfo = async function ({ link, providerContext, }) { + try { + const { getBaseUrl, axios } = providerContext; + const baseUrl = await getBaseUrl('consumet'); + const url = `${baseUrl}/anime/zoro/info?id=` + link; + const res = await axios.get(url); + const data = res.data; + const meta = { + title: data.title, + synopsis: data.description, + image: data.image, + tags: [ + data?.type, + data?.subOrDub === 'both' ? 'Sub And Dub' : data?.subOrDub, + ], + imdbId: '', + type: data.episodes.length > 0 ? 'series' : 'movie', + }; + const linkList = []; + const subLinks = []; + data.episodes.forEach((episode) => { + if (!episode?.isSubbed) { + return; + } + const title = 'Episode ' + episode.number + (episode?.isFiller ? ' (Filler)' : ''); + const link = episode.id + '$sub'; + if (link && title) { + subLinks.push({ + title, + link, + }); + } + }); + linkList.push({ + title: meta.title + ' (Sub)', + directLinks: subLinks, + }); + if (data?.subOrDub === 'both') { + const dubLinks = []; + data.episodes.forEach((episode) => { + if (!episode?.isDubbed) { + return; + } + const title = 'Episode ' + episode.number + (episode?.isFiller ? ' (Filler)' : ''); + const link = episode.id + '$dub'; + if (link && title) { + dubLinks.push({ + title, + link, + }); + } + }); + linkList.push({ + title: meta.title + ' (Dub)', + directLinks: dubLinks, + }); + } + return { + ...meta, + linkList: linkList, + }; + } + catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.hiGetInfo = hiGetInfo; diff --git a/dist/hiAnime/hiGetPosts.js b/dist/hiAnime/hiGetPosts.js new file mode 100644 index 0000000..4c4b562 --- /dev/null +++ b/dist/hiAnime/hiGetPosts.js @@ -0,0 +1,41 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.hiGetPostsSearch = exports.hiGetPosts = void 0; +const hiGetPosts = async function ({ filter, page, signal, providerContext, }) { + const { getBaseUrl, axios } = providerContext; + const baseUrl = await getBaseUrl('consumet'); + const url = `${baseUrl + filter}?page=${page}`; + return posts({ url, signal, axios }); +}; +exports.hiGetPosts = hiGetPosts; +const hiGetPostsSearch = async function ({ searchQuery, page, signal, providerContext, }) { + const { getBaseUrl, axios } = providerContext; + const baseUrl = await getBaseUrl('consumet'); + const url = `${baseUrl}/anime/zoro/${searchQuery}?page=${page}`; + return posts({ url, signal, axios }); +}; +exports.hiGetPostsSearch = hiGetPostsSearch; +async function posts({ url, signal, axios, }) { + try { + const res = await axios.get(url, { signal }); + const data = res.data?.results; + const catalog = []; + data?.map((element) => { + const title = element.title; + const link = element.id; + const image = element.image; + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('zoro error ', err); + return []; + } +} diff --git a/dist/hiAnime/index.js b/dist/hiAnime/index.js new file mode 100644 index 0000000..34ab168 --- /dev/null +++ b/dist/hiAnime/index.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.HiAnime = void 0; +const hiGetInfo_1 = require("./hiGetInfo"); +const hiCatalog_1 = require("./hiCatalog"); +const HiGetSteam_1 = require("./HiGetSteam"); +const hiGetPosts_1 = require("./hiGetPosts"); +exports.HiAnime = { + catalog: hiCatalog_1.hiCatalog, + genres: hiCatalog_1.hiGenresList, + GetMetaData: hiGetInfo_1.hiGetInfo, + GetHomePosts: hiGetPosts_1.hiGetPosts, + GetStream: HiGetSteam_1.hiGetStream, + GetSearchPosts: hiGetPosts_1.hiGetPostsSearch, +}; diff --git a/dist/hubcloudExtractor.js b/dist/hubcloudExtractor.js new file mode 100644 index 0000000..77df343 --- /dev/null +++ b/dist/hubcloudExtractor.js @@ -0,0 +1,120 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.hubcloudExtracter = hubcloudExtracter; +const axios_1 = __importDefault(require("axios")); +const cheerio = __importStar(require("cheerio")); +const headers_1 = require("./headers"); +const decode = function (value) { + if (value === undefined) { + return ''; + } + return atob(value.toString()); +}; +async function hubcloudExtracter(link, signal) { + try { + console.log('hubcloudExtracter', link); + const baseUrl = link.split('/').slice(0, 3).join('/'); + const streamLinks = []; + const vLinkRes = await (0, axios_1.default)(`${link}`, { headers: headers_1.headers, signal }); + const vLinkText = vLinkRes.data; + const $vLink = cheerio.load(vLinkText); + const vLinkRedirect = vLinkText.match(/var\s+url\s*=\s*'([^']+)';/) || []; + let vcloudLink = decode(vLinkRedirect[1]?.split('r=')?.[1]) || + vLinkRedirect[1] || + $vLink('.fa-file-download.fa-lg').parent().attr('href') || + link; + console.log('vcloudLink', vcloudLink); + if (vcloudLink?.startsWith('/')) { + vcloudLink = `${baseUrl}${vcloudLink}`; + console.log('New vcloudLink', vcloudLink); + } + const vcloudRes = await fetch(vcloudLink, { + headers: headers_1.headers, + signal, + redirect: 'follow', + }); + const $ = cheerio.load(await vcloudRes.text()); + // console.log('vcloudRes', $.text()); + const linkClass = $('.btn-success.btn-lg.h6,.btn-danger,.btn-secondary'); + for (const element of linkClass) { + const itm = $(element); + let link = itm.attr('href') || ''; + if (link?.includes('.dev') && !link?.includes('/?id=')) { + streamLinks.push({ server: 'Cf Worker', link: link, type: 'mkv' }); + } + if (link?.includes('pixeld')) { + if (!link?.includes('api')) { + const token = link.split('/').pop(); + const baseUrl = link.split('/').slice(0, -2).join('/'); + link = `${baseUrl}/api/file/${token}?download`; + } + streamLinks.push({ server: 'Pixeldrain', link: link, type: 'mkv' }); + } + if (link?.includes('hubcloud') || link?.includes('/?id=')) { + try { + const newLinkRes = await axios_1.default.head(link, { headers: headers_1.headers, signal }); + const newLink = newLinkRes.request?.responseURL?.split('link=')?.[1] || link; + streamLinks.push({ server: 'hubcloud', link: newLink, type: 'mkv' }); + } + catch (error) { + console.log('hubcloudExtracter error in hubcloud link: ', error); + } + } + if (link?.includes('cloudflarestorage')) { + streamLinks.push({ server: 'CfStorage', link: link, type: 'mkv' }); + } + if (link?.includes('fastdl')) { + streamLinks.push({ server: 'FastDl', link: link, type: 'mkv' }); + } + if (link.includes('hubcdn')) { + streamLinks.push({ + server: 'HubCdn', + link: link, + type: 'mkv', + }); + } + } + console.log('streamLinks', streamLinks); + return streamLinks; + } + catch (error) { + console.log('hubcloudExtracter error: ', error); + return []; + } +} diff --git a/dist/katmovies/index.js b/dist/katmovies/index.js new file mode 100644 index 0000000..6df4551 --- /dev/null +++ b/dist/katmovies/index.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.katMoviesHd = void 0; +const katCatalog_1 = require("./katCatalog"); +const katGetEpsodes_1 = require("./katGetEpsodes"); +const katGetInfo_1 = require("./katGetInfo"); +const katGetPosts_1 = require("./katGetPosts"); +const katGetSteam_1 = require("./katGetSteam"); +exports.katMoviesHd = { + catalog: katCatalog_1.katCatalog, + genres: katCatalog_1.katGenresList, + GetMetaData: katGetInfo_1.katGetInfo, + GetHomePosts: katGetPosts_1.katGetPosts, + GetStream: katGetSteam_1.katGetStream, + GetEpisodeLinks: katGetEpsodes_1.katEpisodeLinks, + GetSearchPosts: katGetPosts_1.katGetPostsSearch, +}; diff --git a/dist/katmovies/katCatalog.js b/dist/katmovies/katCatalog.js new file mode 100644 index 0000000..75ef5fd --- /dev/null +++ b/dist/katmovies/katCatalog.js @@ -0,0 +1,63 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.katGenresList = exports.katCatalog = void 0; +exports.katCatalog = [ + { + title: 'Latest', + filter: '', + }, + { + title: 'Netflix', + filter: '/category/netflix', + }, + { + title: 'Animated', + filter: '/category/animated', + }, + { + title: 'Amazon Prime', + filter: '/category/amazon-prime', + }, +]; +exports.katGenresList = [ + { + title: 'Action', + filter: '/category/action', + }, + { + title: 'Crime', + filter: '/category/crime', + }, + { + title: 'Comedy', + filter: '/category/comedy', + }, + { + title: 'Drama', + filter: '/category/drama', + }, + { + title: 'Horror', + filter: '/category/horror', + }, + { + title: 'Family', + filter: '/category/family', + }, + { + title: 'Sci-Fi', + filter: '/category/sifi', + }, + { + title: 'Thriller', + filter: '/category/triller', + }, + { + title: 'Romance', + filter: '/category/romance', + }, + { + title: 'Fight', + filter: '/category/fight', + }, +]; diff --git a/dist/katmovies/katGetEpsodes.js b/dist/katmovies/katGetEpsodes.js new file mode 100644 index 0000000..8b15fd8 --- /dev/null +++ b/dist/katmovies/katGetEpsodes.js @@ -0,0 +1,70 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.katEpisodeLinks = void 0; +exports.extractKmhdLink = extractKmhdLink; +const katEpisodeLinks = async function ({ url, providerContext, }) { + const { axios, cheerio } = providerContext; + const episodesLink = []; + try { + if (url.includes('gdflix')) { + const baseUrl = url.split('/pack')?.[0]; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const links = $('.list-group-item'); + links?.map((i, link) => { + episodesLink.push({ + title: $(link).text() || '', + link: baseUrl + $(link).find('a').attr('href') || '', + }); + }); + if (episodesLink.length > 0) { + return episodesLink; + } + } + if (url.includes('/pack')) { + const epIds = await extractKmhdEpisodes(url, providerContext); + epIds?.forEach((id, index) => { + episodesLink.push({ + title: `Episode ${index + 1}`, + link: url.split('/pack')[0] + '/file/' + id, + }); + }); + } + const res = await axios.get(url, { + headers: { + Cookie: '_ga_GNR438JY8N=GS1.1.1722240350.5.0.1722240350.0.0.0; _ga=GA1.1.372196696.1722150754; unlocked=true', + }, + }); + const episodeData = res.data; + const $ = cheerio.load(episodeData); + const links = $('.autohyperlink'); + links?.map((i, link) => { + episodesLink.push({ + title: $(link).parent().children().remove().end().text() || '', + link: $(link).attr('href') || '', + }); + }); + return episodesLink; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.katEpisodeLinks = katEpisodeLinks; +async function extractKmhdLink(katlink, providerContext) { + const { axios } = providerContext; + const res = await axios.get(katlink); + const data = res.data; + const hubDriveRes = data.match(/hubdrive_res:\s*"([^"]+)"/)[1]; + const hubDriveLink = data.match(/hubdrive_res\s*:\s*{[^}]*?link\s*:\s*"([^"]+)"/)[1]; + return hubDriveLink + hubDriveRes; +} +async function extractKmhdEpisodes(katlink, providerContext) { + const { axios } = providerContext; + const res = await axios.get(katlink); + const data = res.data; + const ids = data.match(/[\w]+_[a-f0-9]{8}/g); + return ids; +} diff --git a/dist/katmovies/katGetInfo.js b/dist/katmovies/katGetInfo.js new file mode 100644 index 0000000..3bf3e83 --- /dev/null +++ b/dist/katmovies/katGetInfo.js @@ -0,0 +1,115 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.katGetInfo = void 0; +const katGetInfo = async function ({ link, providerContext, }) { + try { + const { axios, cheerio } = providerContext; + const url = link; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const container = $('.yQ8hqd.ksSzJd.LoQAYe').html() + ? $('.yQ8hqd.ksSzJd.LoQAYe') + : $('.FxvUNb'); + const imdbId = container + .find('a[href*="imdb.com/title/tt"]:not([href*="imdb.com/title/tt/"])') + .attr('href') + ?.split('/')[4] || ''; + const title = container + .find('li:contains("Name")') + .children() + .remove() + .end() + .text(); + const type = $('.yQ8hqd.ksSzJd.LoQAYe').html() ? 'series' : 'movie'; + const synopsis = container.find('li:contains("Stars")').text(); + const image = $('h4:contains("SCREENSHOTS")').next().find('img').attr('src') || ''; + console.log('katGetInfo', title, synopsis, image, imdbId, type); + // Links + const links = []; + const directLink = []; + // direct links + $('.entry-content') + .find('p:contains("Episode")') + .each((i, element) => { + const dlLink = $(element) + .nextAll('h3,h2') + .first() + .find('a:contains("1080"),a:contains("720"),a:contains("480")') + .attr('href') || ''; + const dlTitle = $(element).find('span').text(); + if (link.trim().length > 0 && dlTitle.includes('Episode ')) { + directLink.push({ + title: dlTitle, + link: dlLink, + }); + } + }); + if (directLink.length > 0) { + links.push({ + quality: '', + title: title, + directLinks: directLink, + }); + } + $('.entry-content') + .find('pre') + .nextUntil('div') + .filter('h2') + .each((i, element) => { + const link = $(element).find('a').attr('href'); + const quality = $(element) + .text() + .match(/\b(480p|720p|1080p|2160p)\b/i)?.[0] || ''; + const title = $(element).text(); + if (link && title.includes('')) { + links.push({ + quality, + title, + episodesLink: link, + }); + } + }); + if (links.length === 0 && type === 'movie') { + $('.entry-content') + .find('h2:contains("DOWNLOAD"),h3:contains("DOWNLOAD")') + .nextUntil('pre,div') + .filter('h2') + .each((i, element) => { + const link = $(element).find('a').attr('href'); + const quality = $(element) + .text() + .match(/\b(480p|720p|1080p|2160p)\b/i)?.[0] || ''; + const title = $(element).text(); + if (link && !title.includes('Online')) { + links.push({ + quality, + title, + directLinks: [{ link, title, type: 'movie' }], + }); + } + }); + } + // console.log('drive meta', title, synopsis, image, imdbId, type, links); + return { + title, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } + catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.katGetInfo = katGetInfo; diff --git a/dist/katmovies/katGetPosts.js b/dist/katmovies/katGetPosts.js new file mode 100644 index 0000000..668f59f --- /dev/null +++ b/dist/katmovies/katGetPosts.js @@ -0,0 +1,44 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.katGetPostsSearch = exports.katGetPosts = void 0; +const katGetPosts = async function ({ filter, page, signal, providerContext, }) { + const { getBaseUrl, cheerio } = providerContext; + const baseUrl = await getBaseUrl('kat'); + const url = `${baseUrl + filter}/page/${page}/`; + return posts({ url, signal, cheerio }); +}; +exports.katGetPosts = katGetPosts; +const katGetPostsSearch = async function ({ searchQuery, page, signal, providerContext, }) { + const { getBaseUrl, cheerio } = providerContext; + const baseUrl = await getBaseUrl('kat'); + const url = `${baseUrl}/page/${page}/?s=${searchQuery}`; + return posts({ url, signal, cheerio }); +}; +exports.katGetPostsSearch = katGetPostsSearch; +async function posts({ url, signal, cheerio, }) { + try { + const res = await fetch(url, { signal }); + const data = await res.text(); + const $ = cheerio.load(data); + const catalog = []; + $('.recent-posts') + .children() + .map((i, element) => { + const title = $(element).find('img').attr('alt'); + const link = $(element).find('a').attr('href'); + const image = $(element).find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title.replace('Download', '').trim(), + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('katmovies error ', err); + return []; + } +} diff --git a/dist/katmovies/katGetSteam.js b/dist/katmovies/katGetSteam.js new file mode 100644 index 0000000..7c95523 --- /dev/null +++ b/dist/katmovies/katGetSteam.js @@ -0,0 +1,90 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.katGetStream = katGetStream; +async function extractKmhdLink(katlink, providerContext) { + const { axios } = providerContext; + const res = await axios.get(katlink); + const data = res.data; + const hubDriveRes = data.match(/hubdrive_res:\s*"([^"]+)"/)[1]; + const hubDriveLink = data.match(/hubdrive_res\s*:\s*{[^}]*?link\s*:\s*"([^"]+)"/)[1]; + return hubDriveLink + hubDriveRes; +} +async function katGetStream({ link, signal, providerContext, }) { + const { axios, cheerio, extractors } = providerContext; + const { hubcloudExtracter, gdFlixExtracter } = extractors; + const streamLinks = []; + console.log('katGetStream', link); + try { + if (link.includes('gdflix')) { + return await gdFlixExtracter(link, signal); + } + if (link.includes('kmhd')) { + const hubcloudLink = await extractKmhdLink(link, providerContext); + return await hubcloudExtracter(hubcloudLink, signal); + } + if (link.includes('gdflix')) { + // resume link + try { + const resumeDrive = link.replace('/file', '/zfile'); + // console.log('resumeDrive', resumeDrive); + const resumeDriveRes = await axios.get(resumeDrive); + const resumeDriveHtml = resumeDriveRes.data; + const $resumeDrive = cheerio.load(resumeDriveHtml); + const resumeLink = $resumeDrive('.btn-success').attr('href'); + console.log('resumeLink', resumeLink); + if (resumeLink) { + streamLinks.push({ + server: 'ResumeCloud', + link: resumeLink, + type: 'mkv', + }); + } + } + catch (err) { + console.log('Resume link not found'); + } + //instant link + try { + const driveres = await axios.get(link, { timeout: 10000 }); + const $drive = cheerio.load(driveres.data); + const seed = $drive('.btn-danger').attr('href') || ''; + const instantToken = seed.split('=')[1]; + // console.log('InstantToken', instantToken); + const InstantFromData = new FormData(); + InstantFromData.append('keys', instantToken); + const videoSeedUrl = seed.split('/').slice(0, 3).join('/') + '/api'; + // console.log('videoSeedUrl', videoSeedUrl); + const instantLinkRes = await fetch(videoSeedUrl, { + method: 'POST', + body: InstantFromData, + headers: { + 'x-token': videoSeedUrl, + }, + }); + const instantLinkData = await instantLinkRes.json(); + console.log('instantLinkData', instantLinkData); + if (instantLinkData.error === false) { + const instantLink = instantLinkData.url; + streamLinks.push({ + server: 'Gdrive-Instant', + link: instantLink, + type: 'mkv', + }); + } + else { + console.log('Instant link not found', instantLinkData); + } + } + catch (err) { + console.log('Instant link not found', err); + } + return streamLinks; + } + const stereams = await hubcloudExtracter(link, signal); + return stereams; + } + catch (error) { + console.log('katgetStream error: ', error); + return []; + } +} diff --git a/dist/kissKh/index.js b/dist/kissKh/index.js new file mode 100644 index 0000000..3f25123 --- /dev/null +++ b/dist/kissKh/index.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.kissKhProvider = void 0; +const kissKhCatalog_1 = require("./kissKhCatalog"); +const kissKhGetInfo_1 = require("./kissKhGetInfo"); +const kissKhGetPosts_1 = require("./kissKhGetPosts"); +const kissKhGetStream_1 = require("./kissKhGetStream"); +exports.kissKhProvider = { + catalog: kissKhCatalog_1.kisskhCatalog, + genres: kissKhCatalog_1.kisskhGenresList, + GetHomePosts: kissKhGetPosts_1.kissKhGetPosts, + GetMetaData: kissKhGetInfo_1.kissKhGetInfo, + GetStream: kissKhGetStream_1.kissKhGetStream, + GetSearchPosts: kissKhGetPosts_1.kissKhGetPostsSearch, +}; diff --git a/dist/kissKh/kissKhCatalog.js b/dist/kissKh/kissKhCatalog.js new file mode 100644 index 0000000..8e654e3 --- /dev/null +++ b/dist/kissKh/kissKhCatalog.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.kisskhGenresList = exports.kisskhCatalog = void 0; +exports.kisskhCatalog = [ + { + title: 'Latest', + filter: '/api/DramaList/List?type=0&sub=0&country=0&status=0&order=2', + }, + { + title: 'Hollywood', + filter: '/api/DramaList/List?type=4&sub=0&country=0&status=0&order=2', + }, + { + title: 'Anime', + filter: '/api/DramaList/List?type=3&sub=0&country=0&status=0&order=2', + }, + { + title: 'K Drama', + filter: '/api/DramaList/List?type=0&sub=0&country=0&status=0&order=2', + }, +]; +exports.kisskhGenresList = []; diff --git a/dist/kissKh/kissKhGetInfo.js b/dist/kissKh/kissKhGetInfo.js new file mode 100644 index 0000000..3ac0c18 --- /dev/null +++ b/dist/kissKh/kissKhGetInfo.js @@ -0,0 +1,50 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.kissKhGetInfo = void 0; +const kissKhGetInfo = async function ({ link, providerContext, }) { + try { + const { axios } = providerContext; + const res = await axios.get(link); + const data = res.data; + const meta = { + title: data.title, + synopsis: data.description, + image: data.thumbnail, + tags: [data?.releaseDate?.split('-')[0], data?.status, data?.type], + imdbId: '', + type: data.episodesCount > 1 ? 'series' : 'movie', + }; + const linkList = []; + const subLinks = []; + data?.episodes?.reverse().map((episode) => { + const title = 'Episode ' + episode?.number; + const link = episode?.id?.toString(); + if (link && title) { + subLinks.push({ + title, + link, + }); + } + }); + linkList.push({ + title: meta.title, + directLinks: subLinks, + }); + return { + ...meta, + linkList: linkList, + }; + } + catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.kissKhGetInfo = kissKhGetInfo; diff --git a/dist/kissKh/kissKhGetPosts.js b/dist/kissKh/kissKhGetPosts.js new file mode 100644 index 0000000..d437386 --- /dev/null +++ b/dist/kissKh/kissKhGetPosts.js @@ -0,0 +1,59 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.kissKhGetPostsSearch = exports.kissKhGetPosts = void 0; +const kissKhGetPosts = async function ({ filter, signal, providerContext, }) { + const { getBaseUrl, axios } = providerContext; + const baseUrl = await getBaseUrl('kissKh'); + const url = `${baseUrl + filter}&type=0`; + try { + const res = await axios.get(url, { signal }); + const data = res.data?.data; + const catalog = []; + data?.map((element) => { + const title = element.title; + const link = baseUrl + `/api/DramaList/Drama/${element?.id}?isq=false`; + const image = element.thumbnail; + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('kiss error ', err); + return []; + } +}; +exports.kissKhGetPosts = kissKhGetPosts; +const kissKhGetPostsSearch = async function ({ searchQuery, signal, providerContext, }) { + const { getBaseUrl, axios } = providerContext; + const baseUrl = await getBaseUrl('kissKh'); + const url = `${baseUrl}/api/DramaList/Search?q=${searchQuery}&type=0`; + try { + const res = await axios.get(url, { signal }); + const data = res.data; + const catalog = []; + data?.map((element) => { + const title = element.title; + const link = baseUrl + `/api/DramaList/Drama/${element?.id}?isq=false`; + const image = element.thumbnail; + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('kiss error ', err); + return []; + } +}; +exports.kissKhGetPostsSearch = kissKhGetPostsSearch; diff --git a/dist/kissKh/kissKhGetStream.js b/dist/kissKh/kissKhGetStream.js new file mode 100644 index 0000000..5ecaf3a --- /dev/null +++ b/dist/kissKh/kissKhGetStream.js @@ -0,0 +1,42 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.kissKhGetStream = void 0; +const types_1 = require("../types"); +const kissKhGetStream = async function ({ link: id, providerContext, }) { + try { + const { axios, getBaseUrl } = providerContext; + const streamLinks = []; + const subtitles = []; + const baseUrl = await getBaseUrl('kissKh'); + const streamUrl = 'https://adorable-salamander-ecbb21.netlify.app/api/kisskh/video?id=' + + id; + const res = await axios.get(streamUrl); + const stream = res.data?.source?.Video; + const subData = res.data?.subtitles; + subData?.map((sub) => { + subtitles.push({ + title: sub?.label, + language: sub?.land, + type: sub?.src?.includes('.vtt') + ? types_1.TextTrackType.VTT + : types_1.TextTrackType.SUBRIP, + uri: sub?.src, + }); + }); + streamLinks.push({ + server: 'kissKh', + link: stream, + type: 'm3u8', + subtitles, + headers: { + referer: baseUrl, + }, + }); + return streamLinks; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.kissKhGetStream = kissKhGetStream; diff --git a/dist/luxMovies/index.js b/dist/luxMovies/index.js new file mode 100644 index 0000000..3662ad3 --- /dev/null +++ b/dist/luxMovies/index.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.luxMovies = void 0; +const luxGetPosts_1 = require("./luxGetPosts"); +const getInfo_1 = require("../vega/getInfo"); +const getStream_1 = require("../vega/getStream"); +const getEpisodesLink_1 = require("../vega/getEpisodesLink"); +const luxCatalog_1 = require("./luxCatalog"); +exports.luxMovies = { + catalog: luxCatalog_1.homeList, + genres: luxCatalog_1.genresList, + GetMetaData: getInfo_1.vegaGetInfo, + GetHomePosts: luxGetPosts_1.luxGetPosts, + GetStream: getStream_1.vegaGetStream, + nonStreamableServer: ['filepress'], + GetEpisodeLinks: getEpisodesLink_1.vegaGetEpisodeLinks, + GetSearchPosts: luxGetPosts_1.luxGetPostsSearch, +}; diff --git a/dist/luxMovies/luxCatalog.js b/dist/luxMovies/luxCatalog.js new file mode 100644 index 0000000..2db8fbf --- /dev/null +++ b/dist/luxMovies/luxCatalog.js @@ -0,0 +1,103 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.genresList = exports.homeList = void 0; +exports.homeList = [ + { + title: 'New', + filter: '', + }, + { + title: 'Netflix', + filter: 'category/web-series/netflix', + }, + { + title: 'Amazon Prime', + filter: 'category/web-series/amazon-prime-video', + }, + { + title: '4K Movies', + filter: 'category/movies-by-quality/2160p', + }, +]; +exports.genresList = [ + { + title: 'Action', + filter: 'category/movies-by-genres/action/', + }, + { + title: 'Adventure', + filter: 'category/movies-by-genres/adventure/', + }, + { + title: 'Animation', + filter: 'category/movies-by-genres/animation/', + }, + { + title: 'Biography', + filter: 'category/movies-by-genres/biography/', + }, + { + title: 'Comedy', + filter: 'category/movies-by-genres/comedy/', + }, + { + title: 'Crime', + filter: 'category/movies-by-genres/crime/', + }, + { + title: 'Documentary', + filter: 'category/movies-by-genres/documentary/', + }, + { + title: 'Drama', + filter: 'category/movies-by-genres/drama/', + }, + { + title: 'Family', + filter: 'category/movies-by-genres/family/', + }, + { + title: 'Fantasy', + filter: 'category/movies-by-genres/fantasy/', + }, + { + title: 'History', + filter: 'category/movies-by-genres/history/', + }, + { + title: 'Horror', + filter: 'category/movies-by-genres/horror/', + }, + { + title: 'Music', + filter: 'category/movies-by-genres/music/', + }, + { + title: 'Mystery', + filter: 'category/movies-by-genres/mystery/', + }, + { + title: 'Romance', + filter: 'category/movies-by-genres/romance/', + }, + { + title: 'Sci-Fi', + filter: 'category/movies-by-genres/sci-fi/', + }, + { + title: 'Sport', + filter: 'category/movies-by-genres/sport/', + }, + { + title: 'Thriller', + filter: 'category/movies-by-genres/thriller/', + }, + { + title: 'War', + filter: 'category/movies-by-genres/war/', + }, + { + title: 'Western', + filter: 'category/movies-by-genres/western/', + }, +]; diff --git a/dist/luxMovies/luxGetPosts.js b/dist/luxMovies/luxGetPosts.js new file mode 100644 index 0000000..e13e8f1 --- /dev/null +++ b/dist/luxMovies/luxGetPosts.js @@ -0,0 +1,73 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.luxGetPostsSearch = exports.luxGetPosts = void 0; +const headers = { + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + Cookie: 'ext_name=ojplmecpdpgccookcobabopnaifgidhf; cf_clearance=gaIhTNzqSvp27JCVf7qiEUfYRfwyj0Jx9rcsn774BbE-1732694853-1.2.1.1-QKgYJvmrEz08gM9qbAp70diztE2.hseO2NNi.0imIUk_gkuWUcr7U8t5Zn_z4Ov30sIGPBES1PBgMUEa.s8e8QTkQoZjgziFmoC7YdX7s2Jnt.tYCxE_s5mMLQQBYbz_94A89IYe93Y6kyLQm_L.dvUKPPiGjn_sH3qRD0g4p9oOl0SPvH0T2W_EaD0r6mVBasbgro9dAROt_6CxshXOEGeMOnoWR.ID699FKldjMUhbXJbATAffdOY6kf2sD_iwrSl4bcetTlDHd4gusTVfxSS1pL5qNjyTU9wa38soPl1wZoqFHkEGOPWz6S7FD5ikHxX0bArFem9hiDeJXctYfWz5e_Lkc6lH7nW0Rm2XS3gxCadQSg21RkSReN6kDAEecqjgJSE4zUomkWAxFZ98TSShgGWC0ridPTpdQizPDZQ; _lscache_vary=c1d682536aea2d88fbb2574666e1f0aa', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', +}; +const luxGetPosts = async ({ filter, page, providerValue, signal, providerContext, }) => { + const { getBaseUrl } = providerContext; + const baseUrl = await getBaseUrl('lux'); + console.log('vegaGetPosts baseUrl:', providerValue, baseUrl); + const url = `${baseUrl}/${filter}/page/${page}/`; + console.log('lux url:', url); + return posts(url, signal, providerContext); +}; +exports.luxGetPosts = luxGetPosts; +const luxGetPostsSearch = async ({ searchQuery, page, providerValue, signal, providerContext, }) => { + const { getBaseUrl } = providerContext; + const baseUrl = await getBaseUrl('lux'); + console.log('vegaGetPosts baseUrl:', providerValue, baseUrl); + const url = `${baseUrl}/page/${page}/?s=${searchQuery}`; + console.log('lux url:', url); + return posts(url, signal, providerContext); +}; +exports.luxGetPostsSearch = luxGetPostsSearch; +async function posts(url, signal, providerContext) { + try { + const { axios, cheerio } = providerContext; + const urlRes = await axios.get(url, { headers, signal }); + const $ = cheerio.load(urlRes.data); + const posts = []; + $('.blog-items') + ?.children('article') + ?.each((index, element) => { + const post = { + title: $(element) + ?.find('a') + ?.attr('title') + ?.replace('Download', '') + ?.match(/^(.*?)\s*\((\d{4})\)|^(.*?)\s*\((Season \d+)\)/)?.[0] || + $(element)?.find('a')?.attr('title')?.replace('Download', '') || + '', + link: $(element)?.find('a')?.attr('href') || '', + image: $(element).find('a').find('img').attr('data-lazy-src') || + $(element).find('a').find('img').attr('data-src') || + $(element).find('a').find('img').attr('src') || + '', + }; + if (post.image.startsWith('//')) { + post.image = 'https:' + post.image; + } + posts.push(post); + }); + // console.log(posts); + return posts; + } + catch (error) { + console.error('vegaGetPosts error:', error); + return []; + } +} diff --git a/dist/mod/catalog.js b/dist/mod/catalog.js new file mode 100644 index 0000000..449fb75 --- /dev/null +++ b/dist/mod/catalog.js @@ -0,0 +1,87 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.modGenresList = exports.catalogList = void 0; +exports.catalogList = [ + { + title: 'Latest', + filter: '', + }, + { + title: 'Netflix', + filter: '/ott/netflix', + }, + { + title: 'HBO Max', + filter: '/ott/hbo-max', + }, + { + title: 'Amazon Prime', + filter: '/ott/amazon-prime-video', + }, +]; +exports.modGenresList = [ + { + title: 'Apple TV+', + filter: '/ott/apple-tv', + }, + { + title: 'Disney+', + filter: '/ott/disney-plus', + }, + { + title: 'Hulu', + filter: '/ott/hulu', + }, + { + title: 'Crunchyroll', + filter: '/ott/crunchyroll', + }, + { + title: 'Action', + filter: '/movies-by-genre/action/', + }, + { + title: 'Adventure', + filter: '/movies-by-genre/adventure/', + }, + { + title: 'Animation', + filter: '/movies-by-genre/animated/', + }, + { + title: 'Comedy', + filter: '/movies-by-genre/comedy/', + }, + { + title: 'Crime', + filter: '/movies-by-genre/crime/', + }, + { + title: 'Documentary', + filter: '/movies-by-genre/documentary/', + }, + { + title: 'Fantasy', + filter: '/movies-by-genre/fantasy/', + }, + { + title: 'Horror', + filter: '/movies-by-genre/horror/', + }, + { + title: 'Mystery', + filter: '/movies-by-genre/mystery/', + }, + { + title: 'Romance', + filter: '/movies-by-genre/romance/', + }, + { + title: 'Thriller', + filter: '/movies-by-genre/thriller/', + }, + { + title: 'Sci-Fi', + filter: '/movies-by-genre/sci-fi/', + }, +]; diff --git a/dist/mod/index.js b/dist/mod/index.js new file mode 100644 index 0000000..1c3ed18 --- /dev/null +++ b/dist/mod/index.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.modMovies = void 0; +const catalog_1 = require("./catalog"); +const modGetInfo_1 = require("./modGetInfo"); +const modGetEpisodesList_1 = require("./modGetEpisodesList"); +const modGetPosts_1 = require("./modGetPosts"); +const modGetStream_1 = require("./modGetStream"); +exports.modMovies = { + catalog: catalog_1.catalogList, + genres: catalog_1.modGenresList, + GetMetaData: modGetInfo_1.modGetInfo, + GetHomePosts: modGetPosts_1.modGetPosts, + GetStream: modGetStream_1.modGetStream, + GetEpisodeLinks: modGetEpisodesList_1.modGetEpisodeLinks, + // nonStreamableServer: ['Gdrive-Instant'], + GetSearchPosts: modGetPosts_1.modGetPostsSearch, +}; diff --git a/dist/mod/modGetEpisodesList.js b/dist/mod/modGetEpisodesList.js new file mode 100644 index 0000000..7711d6b --- /dev/null +++ b/dist/mod/modGetEpisodesList.js @@ -0,0 +1,49 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.modGetEpisodeLinks = void 0; +const modGetEpisodeLinks = async function ({ url, providerContext, }) { + const { axios, cheerio } = providerContext; + try { + if (url.includes('url=')) { + url = atob(url.split('url=')[1]); + } + const res = await axios.get(url); + const html = res.data; + let $ = cheerio.load(html); + if (url.includes('url=')) { + const newUrl = $("meta[http-equiv='refresh']") + .attr('content') + ?.split('url=')[1]; + const res2 = await axios.get(newUrl || url); + const html2 = res2.data; + $ = cheerio.load(html2); + } + const episodeLinks = []; + $('h3,h4').map((i, element) => { + const seriesTitle = $(element).text(); + const episodesLink = $(element).find('a').attr('href'); + if (episodesLink && episodesLink !== '#') { + episodeLinks.push({ + title: seriesTitle.trim() || 'No title found', + link: episodesLink || '', + }); + } + }); + $('a.maxbutton').map((i, element) => { + const seriesTitle = $(element).children('span').text(); + const episodesLink = $(element).attr('href'); + if (episodesLink && episodesLink !== '#') { + episodeLinks.push({ + title: seriesTitle.trim() || 'No title found', + link: episodesLink || '', + }); + } + }); + return episodeLinks; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.modGetEpisodeLinks = modGetEpisodeLinks; diff --git a/dist/mod/modGetInfo.js b/dist/mod/modGetInfo.js new file mode 100644 index 0000000..bba1745 --- /dev/null +++ b/dist/mod/modGetInfo.js @@ -0,0 +1,62 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.modGetInfo = void 0; +const modGetInfo = async function ({ link, providerContext, }) { + try { + const { axios, cheerio } = providerContext; + const url = link; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const meta = { + title: $('.imdbwp__title').text(), + synopsis: $('.imdbwp__teaser').text(), + image: $('.imdbwp__thumb').find('img').attr('src') || '', + imdbId: $('.imdbwp__link').attr('href')?.split('/')[4] || '', + type: $('.thecontent').text().toLocaleLowerCase().includes('season') + ? 'series' + : 'movie', + }; + const links = []; + $('h3,h4').map((i, element) => { + const seriesTitle = $(element).text(); + // const batchZipLink = $(element) + // .next("p") + // .find(".maxbutton-batch-zip,.maxbutton-zip-download") + // .attr("href"); + const episodesLink = $(element) + .next('p') + .find('.maxbutton-episode-links,.maxbutton-g-drive,.maxbutton-af-download') + .attr('href'); + const movieLink = $(element) + .next('p') + .find('.maxbutton-download-links') + .attr('href'); + if (movieLink || + (episodesLink && episodesLink !== 'javascript:void(0);')) { + links.push({ + title: seriesTitle.replace('Download ', '').trim() || 'Download', + episodesLink: episodesLink || '', + directLinks: movieLink + ? [{ link: movieLink, title: 'Movie', type: 'movie' }] + : [], + quality: seriesTitle?.match(/\d+p\b/)?.[0] || '', + }); + } + }); + // console.log('mod meta', links); + return { ...meta, linkList: links }; + } + catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.modGetInfo = modGetInfo; diff --git a/dist/mod/modGetPosts.js b/dist/mod/modGetPosts.js new file mode 100644 index 0000000..5717aed --- /dev/null +++ b/dist/mod/modGetPosts.js @@ -0,0 +1,44 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.modGetPostsSearch = exports.modGetPosts = void 0; +const modGetPosts = async function ({ filter, page, signal, providerContext, }) { + const { getBaseUrl, axios, cheerio } = providerContext; + const baseUrl = await getBaseUrl('Moviesmod'); + const url = `${baseUrl + filter}/page/${page}/`; + return posts({ url, signal, axios, cheerio }); +}; +exports.modGetPosts = modGetPosts; +const modGetPostsSearch = async function ({ searchQuery, page, signal, providerContext, }) { + const { getBaseUrl, axios, cheerio } = providerContext; + const baseUrl = await getBaseUrl('Moviesmod'); + const url = `${baseUrl}/search/${searchQuery}/page/${page}/`; + return posts({ url, signal, axios, cheerio }); +}; +exports.modGetPostsSearch = modGetPostsSearch; +async function posts({ url, signal, axios, cheerio, }) { + try { + const res = await axios.get(url, { signal }); + const data = res.data; + const $ = cheerio.load(data); + const catalog = []; + $('.post-cards') + .find('article') + .map((i, element) => { + const title = $(element).find('a').attr('title'); + const link = $(element).find('a').attr('href'); + const image = $(element).find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('modGetPosts error ', err); + return []; + } +} diff --git a/dist/mod/modGetStream.js b/dist/mod/modGetStream.js new file mode 100644 index 0000000..d5dc6ac --- /dev/null +++ b/dist/mod/modGetStream.js @@ -0,0 +1,256 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.modGetStream = void 0; +const headers = { + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + Cookie: 'popads_user_id=6ba8fe60a481387a3249f05aa058822d', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', +}; +const modGetStream = async function ({ link: url, type, providerContext, }) { + const { axios, cheerio } = providerContext; + try { + const modGetEpisodeLinks = async function ({ url, providerContext, }) { + const { axios, cheerio } = providerContext; + try { + if (url.includes('url=')) { + url = atob(url.split('url=')[1]); + } + const res = await axios.get(url); + const html = res.data; + let $ = cheerio.load(html); + if (url.includes('url=')) { + const newUrl = $("meta[http-equiv='refresh']") + .attr('content') + ?.split('url=')[1]; + const res2 = await axios.get(newUrl || url); + const html2 = res2.data; + $ = cheerio.load(html2); + } + const episodeLinks = []; + $('h3,h4').map((i, element) => { + const seriesTitle = $(element).text(); + const episodesLink = $(element).find('a').attr('href'); + if (episodesLink && episodesLink !== '#') { + episodeLinks.push({ + title: seriesTitle.trim() || 'No title found', + link: episodesLink || '', + }); + } + }); + $('a.maxbutton').map((i, element) => { + const seriesTitle = $(element).children('span').text(); + const episodesLink = $(element).attr('href'); + if (episodesLink && episodesLink !== '#') { + episodeLinks.push({ + title: seriesTitle.trim() || 'No title found', + link: episodesLink || '', + }); + } + }); + return episodeLinks; + } + catch (err) { + console.error(err); + return []; + } + }; + console.log('modGetStream', type, url); + if (type === 'movie') { + const servers = await modGetEpisodeLinks({ url, providerContext }); + url = servers[0].link || url; + } + let downloadLink = await modExtractor(url, providerContext); + // console.log(downloadLink.data); + const ddl = downloadLink?.data?.match(/content="0;url=(.*?)"/)?.[1] || url; + // console.log('ddl', url); + // console.log(ddl); + // console.log(ddl); + const servers = []; + const driveLink = await isDriveLink(ddl); + const driveRes = await axios.get(driveLink, { headers }); + const driveHtml = driveRes.data; + const $drive = cheerio.load(driveHtml); + try { + const resumeBot = $drive('.btn.btn-light').attr('href') || ''; + const resumeBotRes = await axios.get(resumeBot, { headers }); + const resumeBotToken = resumeBotRes.data.match(/formData\.append\('token', '([a-f0-9]+)'\)/)[1]; + const resumeBotBody = new FormData(); + resumeBotBody.append('token', resumeBotToken); + const resumeBotPath = resumeBotRes.data.match(/fetch\('\/download\?id=([a-zA-Z0-9\/+]+)'/)[1]; + const resumeBotBaseUrl = resumeBot.split('/download')[0]; + // console.log( + // 'resumeBotPath', + // resumeBotBaseUrl + '/download?id=' + resumeBotPath, + // ); + // console.log('resumeBotBody', resumeBotToken); + const resumeBotDownload = await fetch(resumeBotBaseUrl + '/download?id=' + resumeBotPath, { + method: 'POST', + body: resumeBotBody, + headers: { + Referer: resumeBot, + Cookie: 'PHPSESSID=7e9658ce7c805dab5bbcea9046f7f308', + }, + }); + const resumeBotDownloadData = await resumeBotDownload.json(); + console.log('resumeBotDownloadData', resumeBotDownloadData.url); + servers.push({ + server: 'ResumeBot', + link: resumeBotDownloadData.url, + type: 'mkv', + }); + } + catch (err) { + console.log('ResumeBot link not found', err); + } + // CF workers type 1 + try { + const cfWorkersLink = driveLink.replace('/file', '/wfile') + '?type=1'; + const cfWorkersRes = await axios.get(cfWorkersLink, { headers }); + const cfWorkersHtml = cfWorkersRes.data; + const $cfWorkers = cheerio.load(cfWorkersHtml); + const cfWorkersStream = $cfWorkers('.btn-success'); + cfWorkersStream.each((i, el) => { + const link = el.attribs.href; + if (link) { + servers.push({ + server: 'Cf Worker 1.' + i, + link: link, + type: 'mkv', + }); + } + }); + } + catch (err) { + console.log('CF workers link not found', err); + } + // CF workers type 2 + try { + const cfWorkersLink = driveLink.replace('/file', '/wfile') + '?type=2'; + const cfWorkersRes = await axios.get(cfWorkersLink, { headers }); + const cfWorkersHtml = cfWorkersRes.data; + const $cfWorkers = cheerio.load(cfWorkersHtml); + const cfWorkersStream = $cfWorkers('.btn-success'); + cfWorkersStream.each((i, el) => { + const link = el.attribs.href; + if (link) { + servers.push({ + server: 'Cf Worker 2.' + i, + link: link, + type: 'mkv', + }); + } + }); + } + catch (err) { + console.log('CF workers link not found', err); + } + // gdrive + //instant link + try { + const seed = $drive('.btn-danger').attr('href') || ''; + const instantToken = seed.split('=')[1]; + // console.log('InstantToken', instantToken); + const InstantFromData = new FormData(); + InstantFromData.append('keys', instantToken); + const videoSeedUrl = seed.split('/').slice(0, 3).join('/') + '/api'; + // console.log('videoSeedUrl', videoSeedUrl); + const instantLinkRes = await fetch(videoSeedUrl, { + method: 'POST', + body: InstantFromData, + headers: { + 'x-token': videoSeedUrl, + }, + }); + const instantLinkData = await instantLinkRes.json(); + // console.log('instantLinkData', instantLinkData); + if (instantLinkData.error === false) { + const instantLink = instantLinkData.url; + servers.push({ + server: 'Gdrive-Instant', + link: instantLink, + type: 'mkv', + }); + } + else { + console.log('Instant link not found', instantLinkData); + } + } + catch (err) { + console.log('Instant link not found', err); + } + return servers; + } + catch (err) { + console.log('getStream error', err); + return []; + } +}; +exports.modGetStream = modGetStream; +const isDriveLink = async (ddl) => { + if (ddl.includes('drive')) { + const driveLeach = await fetch(ddl); + const driveLeachData = await driveLeach.text(); + const pathMatch = driveLeachData.match(/window\.location\.replace\("([^"]+)"\)/); + const path = pathMatch?.[1]; + const mainUrl = ddl.split('/')[2]; + console.log(`driveUrl = https://${mainUrl}${path}`); + return `https://${mainUrl}${path}`; + } + else { + return ddl; + } +}; +async function modExtractor(url, providerContext) { + const { axios, cheerio } = providerContext; + try { + const wpHttp = url.split('sid=')[1]; + var bodyFormData0 = new FormData(); + bodyFormData0.append('_wp_http', wpHttp); + const res = await fetch(url.split('?')[0], { + method: 'POST', + body: bodyFormData0, + }); + const data = await res.text(); + // console.log('', data); + const html = data; + const $ = cheerio.load(html); + // find input with name="_wp_http2" + const wpHttp2 = $('input').attr('name', '_wp_http2').val(); + // console.log('wpHttp2', wpHttp2); + // form data + var bodyFormData = new FormData(); + bodyFormData.append('_wp_http2', wpHttp2); + const formUrl1 = $('form').attr('action'); + const formUrl = formUrl1 || url.split('?')[0]; + const res2 = await fetch(formUrl, { + method: 'POST', + body: bodyFormData, + }); + const html2 = await res2.text(); + const link = html2.match(/setAttribute\("href",\s*"(.*?)"/)[1]; + console.log(link); + const cookie = link.split('=')[1]; + console.log('cookie', cookie); + const downloadLink = await axios.get(link, { + headers: { + Referer: formUrl, + Cookie: `${cookie}=${wpHttp2}`, + }, + }); + return downloadLink; + } + catch (err) { + console.log('modGetStream error', err); + } +} diff --git a/dist/moviesApi/index.js b/dist/moviesApi/index.js new file mode 100644 index 0000000..a7d072d --- /dev/null +++ b/dist/moviesApi/index.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.moviesApi = void 0; +const allCatalog_1 = require("../autoEmbed/allCatalog"); +const allGetInfo_1 = require("../autoEmbed/allGetInfo"); +const allGetPost_1 = require("../autoEmbed/allGetPost"); +const mpGetStream_1 = require("./mpGetStream"); +exports.moviesApi = { + catalog: allCatalog_1.allCatalog, + genres: allCatalog_1.allGenresList, + GetMetaData: allGetInfo_1.allGetInfo, + GetHomePosts: allGetPost_1.allGetPost, + GetStream: mpGetStream_1.mpGetStream, + GetSearchPosts: allGetPost_1.allGetSearchPosts, +}; diff --git a/dist/moviesApi/mpGetStream.js b/dist/moviesApi/mpGetStream.js new file mode 100644 index 0000000..f18561f --- /dev/null +++ b/dist/moviesApi/mpGetStream.js @@ -0,0 +1,85 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.mpGetStream = void 0; +const types_1 = require("../types"); +const mpGetStream = async function ({ link: id, type, providerContext, }) { + try { + const { getBaseUrl, cheerio } = providerContext; + const streams = []; + const { season, episode, tmdbId } = JSON.parse(id); + const baseUrl = await getBaseUrl('moviesapi'); + const link = type === 'movie' + ? `${baseUrl}/movie/${tmdbId}` + : `${baseUrl}/tv/${tmdbId}-${season}-${episode}`; + const res = await fetch(link, { + headers: { + referer: baseUrl, + }, + }); + const baseData = await res.text(); + const $ = cheerio.load(baseData); + const embededUrl = $('iframe').attr('src') || ''; + const response = await fetch(embededUrl, { + credentials: 'omit', + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0', + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', + 'Accept-Language': 'en-US,en;q=0.5', + 'Alt-Used': 'w1.moviesapi.club', + 'Upgrade-Insecure-Requests': '1', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + Pragma: 'no-cache', + 'Cache-Control': 'no-cache', + referer: baseUrl, + }, + referrer: baseUrl, + method: 'GET', + mode: 'cors', + }); + const data2 = await response.text(); + // Extract the encrypted content + const contents = data2.match(/const\s+Encrypted\s*=\s*['"]({.*})['"]/)?.[1] || ''; + if (embededUrl) { + const res2 = await fetch('https://ext.8man.me/api/decrypt?passphrase==JV[t}{trEV=Ilh5', { + method: 'POST', + body: contents, + }); + const finalData = await res2.json(); + const subtitle = finalData?.subtitles?.map((sub) => ({ + title: sub?.label || 'Unknown', + language: sub?.label, + type: sub?.file?.includes('.vtt') + ? types_1.TextTrackType.VTT + : types_1.TextTrackType.SUBRIP, + uri: sub?.file, + })); + streams.push({ + server: 'vidstreaming ', + type: 'm3u8', + subtitles: subtitle, + link: finalData?.videoUrl, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0', + Referer: baseUrl, + Origin: baseUrl, + Accept: '*/*', + 'Accept-Language': 'en-US,en;q=0.5', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'cross-site', + Pragma: 'no-cache', + 'Cache-Control': 'no-cache', + }, + }); + } + return streams; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.mpGetStream = mpGetStream; diff --git a/dist/multi/index.js b/dist/multi/index.js new file mode 100644 index 0000000..2db3327 --- /dev/null +++ b/dist/multi/index.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.multiMovies = void 0; +const multiCatalog_1 = require("./multiCatalog"); +const multiGetInfo_1 = require("./multiGetInfo"); +const multiPosts_1 = require("./multiPosts"); +const multiGetStream_1 = require("./multiGetStream"); +exports.multiMovies = { + catalog: multiCatalog_1.multiCatalog, + genres: multiCatalog_1.multiGenresList, + GetMetaData: multiGetInfo_1.multiGetInfo, + GetHomePosts: multiPosts_1.multiGetPosts, + GetStream: multiGetStream_1.multiGetStream, + GetSearchPosts: multiPosts_1.multiGetPostsSearch, +}; diff --git a/dist/multi/multiCatalog.js b/dist/multi/multiCatalog.js new file mode 100644 index 0000000..caa1a8e --- /dev/null +++ b/dist/multi/multiCatalog.js @@ -0,0 +1,79 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.multiGenresList = exports.multiCatalog = void 0; +exports.multiCatalog = [ + { + title: 'Trending', + filter: '/trending/', + }, + { + title: 'Netflix', + filter: '/genre/netflix/', + }, + { + title: 'Amazon Prime', + filter: '/genre/amazon-prime/', + }, + { + title: 'Disney Hotstar', + filter: '/genre/disney-hotstar/', + }, +]; +exports.multiGenresList = [ + { + title: 'Action', + filter: '/genre/action/', + }, + { + title: 'Adventure', + filter: '/genre/adventure/', + }, + { + title: 'Animation', + filter: '/genre/animation/', + }, + { + title: 'Comedy', + filter: '/genre/comedy/', + }, + { + title: 'Crime', + filter: '/genre/crime/', + }, + { + title: 'Drama', + filter: '/genre/drama/', + }, + { + title: 'Family', + filter: '/genre/family/', + }, + { + title: 'Fantasy', + filter: '/genre/fantasy/', + }, + { + title: 'History', + filter: '/genre/history/', + }, + { + title: 'Horror', + filter: '/genre/horror/', + }, + { + title: 'Mystery', + filter: '/genre/mystery/', + }, + { + title: 'Romance', + filter: '/genre/romance/', + }, + { + title: 'Science Fiction', + filter: '/genre/science-fiction/', + }, + { + title: 'Thriller', + filter: '/genre/thriller/', + }, +]; diff --git a/dist/multi/multiGetInfo.js b/dist/multi/multiGetInfo.js new file mode 100644 index 0000000..8a944e7 --- /dev/null +++ b/dist/multi/multiGetInfo.js @@ -0,0 +1,76 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.multiGetInfo = void 0; +const multiGetInfo = async function ({ link, providerContext, }) { + try { + const { axios, cheerio } = providerContext; + const url = link; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const type = url.includes('tvshows') ? 'series' : 'movie'; + const imdbId = ''; + const title = url.split('/')[4].replace(/-/g, ' '); + const image = $('.g-item').find('a').attr('href') || ''; + const synopsis = $('.wp-content').find('p').text() || ''; + // Links + const links = []; + if (type === 'series') { + $('#seasons') + .children() + .map((i, element) => { + const title = $(element) + .find('.title') + .children() + .remove() + .end() + .text(); + let episodesList = []; + $(element) + .find('.episodios') + .children() + .map((i, element) => { + const title = 'Episode' + + $(element).find('.numerando').text().trim().split('-')[1]; + const link = $(element).find('a').attr('href'); + if (title && link) { + episodesList.push({ title, link }); + } + }); + if (title && episodesList.length > 0) { + links.push({ + title, + directLinks: episodesList, + }); + } + }); + } + else { + links.push({ + title: title, + directLinks: [{ title: title, link: url.slice(0, -1), type: 'movie' }], + }); + } + // console.log('multi meta', links); + return { + title, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } + catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.multiGetInfo = multiGetInfo; diff --git a/dist/multi/multiGetStream.js b/dist/multi/multiGetStream.js new file mode 100644 index 0000000..7f920e0 --- /dev/null +++ b/dist/multi/multiGetStream.js @@ -0,0 +1,134 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.multiGetStream = void 0; +const types_1 = require("../types"); +const multiGetStream = async function ({ link: url, providerContext, }) { + const { axios, cheerio } = providerContext; + const headers = { + 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + Referer: 'https://multimovies.online/', + 'Sec-Fetch-User': '?1', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', + }; + try { + const res = await axios.get(url, { headers }); + const html = res.data; + const $ = cheerio.load(html); + const streamLinks = []; + const postId = $('#player-option-1').attr('data-post'); + const nume = $('#player-option-1').attr('data-nume'); + const typeValue = $('#player-option-1').attr('data-type'); + const baseUrl = url.split('/').slice(0, 3).join('/'); + console.log('baseUrl', baseUrl); + const formData = new FormData(); + formData.append('action', 'doo_player_ajax'); + formData.append('post', postId); + formData.append('nume', nume); + formData.append('type', typeValue); + console.log('formData', formData); + const playerRes = await fetch(`${baseUrl}/wp-admin/admin-ajax.php`, { + headers: headers, + body: formData, + method: 'POST', + }); + const playerData = await playerRes.json(); + console.log('playerData', playerData); + let ifameUrl = playerData?.embed_url?.match(/]+src="([^"]+)"[^>]*>/i)?.[1] || + playerData?.embed_url; + console.log('ifameUrl', ifameUrl); + if (!ifameUrl.includes('multimovies')) { + let playerBaseUrl = ifameUrl.split('/').slice(0, 3).join('/'); + const newPlayerBaseUrl = await axios.head(playerBaseUrl, { headers }); + if (newPlayerBaseUrl) { + playerBaseUrl = newPlayerBaseUrl.request?.responseURL + ?.split('/') + .slice(0, 3) + .join('/'); + } + const playerId = ifameUrl.split('/').pop(); + const NewformData = new FormData(); + NewformData.append('sid', playerId); + console.log('NewformData', playerBaseUrl + '/embedhelper.php', NewformData); + const playerRes = await fetch(`${playerBaseUrl}/embedhelper.php`, { + headers: headers, + body: NewformData, + method: 'POST', + }); + const playerData = await playerRes.json(); + // console.log('playerData', playerData); + const siteUrl = playerData?.siteUrls?.smwh; + const siteId = JSON.parse(atob(playerData?.mresult))?.smwh || + playerData?.mresult?.smwh; + const newIframeUrl = siteUrl + siteId; + console.log('newIframeUrl', newIframeUrl); + if (newIframeUrl) { + ifameUrl = newIframeUrl; + } + } + const iframeRes = await axios.get(ifameUrl, { + headers: { + ...headers, + Referer: url, + }, + }); + const iframeData = iframeRes.data; + // Step 1: Extract the function parameters and the encoded string + var functionRegex = /eval\(function\((.*?)\)\{.*?return p\}.*?\('(.*?)'\.split/; + var match = functionRegex.exec(iframeData); + let p = ''; + if (match) { + // var params = match[1].split(',').map(param => param.trim()); + var encodedString = match[2]; + // console.log('Parameters:', params); + // console.log('Encoded String:', encodedString.split("',36,")[0], '🔥🔥'); + p = encodedString.split("',36,")?.[0].trim(); + let a = 36; + let c = encodedString.split("',36,")[1].slice(2).split('|').length; + let k = encodedString.split("',36,")[1].slice(2).split('|'); + while (c--) { + if (k[c]) { + var regex = new RegExp('\\b' + c.toString(a) + '\\b', 'g'); + p = p.replace(regex, k[c]); + } + } + // console.log('Decoded String:', p); + } + else { + console.log('No match found'); + } + const streamUrl = p?.match(/https?:\/\/[^"]+?\.m3u8[^"]*/)?.[0]; + const subtitles = []; + const subtitleMatch = p?.match(/https:\/\/[^\s"]+\.vtt/g); + // console.log('subtitleMatch', subtitleMatch); + // console.log('streamUrl', streamUrl); + if (subtitleMatch?.length) { + subtitleMatch.forEach((sub) => { + const lang = sub.match(/_([a-zA-Z]{3})\.vtt$/)[1]; + subtitles.push({ + language: lang, + uri: sub, + type: types_1.TextTrackType.VTT, + title: lang, + }); + }); + } + console.log('streamUrl', streamUrl); + console.log('newUrl', streamUrl?.replace(/&i=\d+,'\.4&/, '&i=0.4&')); + if (streamUrl) { + streamLinks.push({ + server: 'Multi', + link: streamUrl.replace(/&i=\d+,'\.4&/, '&i=0.4&'), + type: 'm3u8', + subtitles: subtitles, + }); + } + return streamLinks; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.multiGetStream = multiGetStream; diff --git a/dist/multi/multiPosts.js b/dist/multi/multiPosts.js new file mode 100644 index 0000000..2bb6c9a --- /dev/null +++ b/dist/multi/multiPosts.js @@ -0,0 +1,45 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.multiGetPostsSearch = exports.multiGetPosts = void 0; +const multiGetPosts = async function ({ filter, page, signal, providerContext, }) { + const { getBaseUrl, cheerio } = providerContext; + const baseUrl = await getBaseUrl('multi'); + const url = `${baseUrl + filter}page/${page}/`; + return posts({ url, signal, cheerio }); +}; +exports.multiGetPosts = multiGetPosts; +const multiGetPostsSearch = async function ({ searchQuery, signal, providerContext, }) { + const { getBaseUrl, cheerio } = providerContext; + const baseUrl = await getBaseUrl('multi'); + const url = `${baseUrl}/?s=${searchQuery}`; + return posts({ url, signal, cheerio }); +}; +exports.multiGetPostsSearch = multiGetPostsSearch; +async function posts({ url, signal, cheerio, }) { + try { + const res = await fetch(url, { signal }); + const data = await res.text(); + const $ = cheerio.load(data); + const catalog = []; + $('.items.full') + .children() + .map((i, element) => { + const title = $(element).find('.poster').find('img').attr('alt'); + const link = $(element).find('.poster').find('a').attr('href'); + const image = $(element).find('.poster').find('img').attr('data-src') || + $(element).find('.poster').find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('multiGetPosts error ', err); + return []; + } +} diff --git a/dist/netflixMirror/index.js b/dist/netflixMirror/index.js new file mode 100644 index 0000000..e32e4d0 --- /dev/null +++ b/dist/netflixMirror/index.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.netflixMirror = void 0; +const nfCatalog_1 = require("./nfCatalog"); +const nfGetInfo_1 = require("./nfGetInfo"); +const nfGetPost_1 = require("./nfGetPost"); +const nfGetEpisodes_1 = require("./nfGetEpisodes"); +const nfGetSteam_1 = require("./nfGetSteam"); +exports.netflixMirror = { + catalog: nfCatalog_1.nfCatalog, + genres: nfCatalog_1.nfGenresList, + GetMetaData: nfGetInfo_1.nfGetInfo, + GetHomePosts: nfGetPost_1.nfGetPost, + GetStream: nfGetSteam_1.nfGetStream, + GetEpisodeLinks: nfGetEpisodes_1.nfGetEpisodes, + GetSearchPosts: nfGetPost_1.nfGetPostsSearch, +}; diff --git a/dist/netflixMirror/nfCatalog.js b/dist/netflixMirror/nfCatalog.js new file mode 100644 index 0000000..d7546ee --- /dev/null +++ b/dist/netflixMirror/nfCatalog.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.nfGenresList = exports.nfCatalog = void 0; +exports.nfCatalog = [ + { + title: 'Home', + filter: '/mobile/home?app=1', + }, + { + title: 'Series', + filter: '/mobile/series', + }, + { + title: 'Movies', + filter: '/mobile/movies', + }, +]; +exports.nfGenresList = []; diff --git a/dist/netflixMirror/nfGetEpisodes.js b/dist/netflixMirror/nfGetEpisodes.js new file mode 100644 index 0000000..60b9159 --- /dev/null +++ b/dist/netflixMirror/nfGetEpisodes.js @@ -0,0 +1,39 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.nfGetEpisodes = void 0; +const nfGetEpisodes = async function ({ url: link, providerContext, }) { + const { getBaseUrl, axios } = providerContext; + let providerValue = 'netflixMirror'; + try { + const baseUrl = await getBaseUrl('nfMirror'); + const url = `${baseUrl}${providerValue === 'netflixMirror' + ? '/episodes.php?s=' + : '/pv/episodes.php?s='}` + + link + + '&t=' + + Math.round(new Date().getTime() / 1000); + console.log('nfEpisodesUrl', url); + const res = await axios.get(url, { + headers: { + 'Content-Type': 'application/json', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36', + 'Accept-Language': 'en-US,en;q=0.9', + }, + }); + const data = res.data; + console.log('nfEpisodes', data); + const episodeList = []; + data?.episodes?.map((episode) => { + episodeList.push({ + title: 'Episode ' + episode?.ep.replace('E', ''), + link: episode?.id, + }); + }); + return episodeList; + } + catch (err) { + console.error('nfGetEpisodes error', err); + return []; + } +}; +exports.nfGetEpisodes = nfGetEpisodes; diff --git a/dist/netflixMirror/nfGetInfo.js b/dist/netflixMirror/nfGetInfo.js new file mode 100644 index 0000000..a8097fa --- /dev/null +++ b/dist/netflixMirror/nfGetInfo.js @@ -0,0 +1,57 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.nfGetInfo = void 0; +const nfGetInfo = async function ({ link, }) { + let providerValue = 'netflixMirror'; + try { + const isPrime = providerValue === 'primeMirror' ? 'isPrime=true' : 'isPrime=false'; + const url = `https://netmirror.8man.me/api/net-proxy?${isPrime}&url=${encodeURIComponent(link)}`; + console.log('nfifo', url); + const res = await fetch(url, { + credentials: 'omit', + }); + const data = await res.json(); + const id = link.split('id=')[1]?.split('&')[0]; + const meta = { + title: data.title, + synopsis: data.desc, + image: `https://img.nfmirrorcdn.top/poster/h/${id}.jpg`, + cast: data?.short_cast?.split(','), + tags: [data?.year, data?.hdsd, ...data?.thismovieis?.split(',')], + imdbId: '', + type: 'series', + }; + console.log('nfinfo', meta); + const linkList = []; + if (data?.season?.length > 0) { + data.season.map((season) => { + linkList.push({ + title: 'Season ' + season?.s, + episodesLink: season?.id, + }); + }); + } + else { + linkList.push({ + title: meta.title, + directLinks: [{ link: id, title: 'Movie', type: 'movie' }], + }); + } + return { + ...meta, + linkList: linkList, + }; + } + catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: '', + linkList: [], + }; + } +}; +exports.nfGetInfo = nfGetInfo; diff --git a/dist/netflixMirror/nfGetPost.js b/dist/netflixMirror/nfGetPost.js new file mode 100644 index 0000000..b8c1969 --- /dev/null +++ b/dist/netflixMirror/nfGetPost.js @@ -0,0 +1,94 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.nfGetPostsSearch = exports.nfGetPost = void 0; +const nfGetPost = async function ({ filter, page, providerValue, signal, providerContext, }) { + try { + const { getBaseUrl, cheerio } = providerContext; + const baseUrl = await getBaseUrl('nfMirror'); + const catalog = []; + if (page > 1) { + return []; + } + // console.log(filter); + const isPrime = providerValue === 'primeMirror' ? 'isPrime=true' : 'isPrime=false'; + const url = `https://netmirror.8man.me/api/net-proxy?${isPrime}&url=${baseUrl + filter}`; + const res = await fetch(url, { + signal: signal, + method: 'GET', + credentials: 'omit', + }); + const data = await res.text(); + // console.log('nfPost', data); + const $ = cheerio.load(data); + $('a.post-data').map((i, element) => { + const title = ''; + const id = $(element).attr('data-post'); + // console.log('id', id); + const image = $(element).find('img').attr('data-src') || ''; + if (id) { + catalog.push({ + title: title, + link: baseUrl + + `${providerValue === 'netflixMirror' + ? '/post.php?id=' + : '/pv/post.php?id='}` + + id + + '&t=' + + Math.round(new Date().getTime() / 1000), + image: image, + }); + } + }); + // console.log(catalog); + return catalog; + } + catch (err) { + console.error('nf error ', err); + return []; + } +}; +exports.nfGetPost = nfGetPost; +const nfGetPostsSearch = async function ({ searchQuery, page, providerValue, signal, providerContext, }) { + const { getBaseUrl } = providerContext; + try { + if (page > 1) { + return []; + } + const catalog = []; + const baseUrl = await getBaseUrl('nfMirror'); + const isPrime = providerValue === 'primeMirror' ? 'isPrime=true' : 'isPrime=false'; + const url = `https://netmirror.8man.me/api/net-proxy?${isPrime}&url=${baseUrl}${providerValue === 'netflixMirror' ? '' : '/pv'}/search.php?s=${encodeURI(searchQuery)}`; + const res = await fetch(url, { + signal: signal, + method: 'GET', + credentials: 'omit', + }); + const data = await res.json(); + data?.searchResult?.forEach((result) => { + const title = result?.t || ''; + const id = result?.id; + const image = providerValue === 'netflixMirror' + ? `https://imgcdn.media/poster/v/${id}.jpg` + : ''; + if (id) { + catalog.push({ + title: title, + link: baseUrl + + `${providerValue === 'netflixMirror' + ? '/mobile/post.php?id=' + : '/mobile/pv/post.php?id='}` + + id + + '&t=' + + Math.round(new Date().getTime() / 1000), + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('Search error:', err); + return []; + } +}; +exports.nfGetPostsSearch = nfGetPostsSearch; diff --git a/dist/netflixMirror/nfGetSteam.js b/dist/netflixMirror/nfGetSteam.js new file mode 100644 index 0000000..b185c4b --- /dev/null +++ b/dist/netflixMirror/nfGetSteam.js @@ -0,0 +1,39 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.nfGetStream = void 0; +const nfGetStream = async ({ link: id, providerContext, }) => { + const { getBaseUrl } = providerContext; + try { + let providerValue = 'netflixMirror'; + const baseUrl = await getBaseUrl('nfMirror'); + const url = `https://netmirror.8man.me/api/net-proxy?url=${baseUrl}${providerValue === 'netflixMirror' + ? '/mobile/playlist.php?id=' + : '/pv/playlist.php?id='}${id}&t=${Math.round(new Date().getTime() / 1000)}`; + console.log('nfGetStream, url:', url); + const res = await fetch(url, { + credentials: 'omit', + }); + const resJson = await res.json(); + const data = resJson?.[0]; + const streamLinks = []; + data?.sources.forEach((source) => { + streamLinks.push({ + server: source.label, + link: (baseUrl + source.file)?.replace(':su', ':ni'), + type: 'm3u8', + headers: { + Referer: baseUrl, + origin: baseUrl, + Cookie: 'hd=on', + }, + }); + }); + console.log(streamLinks); + return streamLinks; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.nfGetStream = nfGetStream; diff --git a/dist/primeMirror/index.js b/dist/primeMirror/index.js new file mode 100644 index 0000000..220e5dd --- /dev/null +++ b/dist/primeMirror/index.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.primeMirror = void 0; +const nfCatalog_1 = require("../netflixMirror/nfCatalog"); +const nfGetPost_1 = require("../netflixMirror/nfGetPost"); +const pmGetInfo_1 = require("./pmGetInfo"); +const pmGetStream_1 = require("./pmGetStream"); +const pmGetEpisodes_1 = require("./pmGetEpisodes"); +exports.primeMirror = { + catalog: nfCatalog_1.nfCatalog, + genres: nfCatalog_1.nfGenresList, + GetMetaData: pmGetInfo_1.pmGetInfo, + GetHomePosts: nfGetPost_1.nfGetPost, + GetStream: pmGetStream_1.pmGetStream, + GetEpisodeLinks: pmGetEpisodes_1.pmGetEpisodes, + GetSearchPosts: nfGetPost_1.nfGetPostsSearch, +}; diff --git a/dist/primeMirror/pmGetEpisodes.js b/dist/primeMirror/pmGetEpisodes.js new file mode 100644 index 0000000..e1722b6 --- /dev/null +++ b/dist/primeMirror/pmGetEpisodes.js @@ -0,0 +1,39 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.pmGetEpisodes = void 0; +const pmGetEpisodes = async function ({ url: link, providerContext, }) { + const { getBaseUrl, axios } = providerContext; + let providerValue = 'primeMirror'; + try { + const baseUrl = await getBaseUrl('nfMirror'); + const url = `${baseUrl}${providerValue === 'netflixMirror' + ? '/episodes.php?s=' + : '/pv/episodes.php?s='}` + + link + + '&t=' + + Math.round(new Date().getTime() / 1000); + console.log('nfEpisodesUrl', url); + const res = await axios.get(url, { + headers: { + 'Content-Type': 'application/json', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36', + 'Accept-Language': 'en-US,en;q=0.9', + }, + }); + const data = res.data; + console.log('nfEpisodes', data); + const episodeList = []; + data?.episodes?.map((episode) => { + episodeList.push({ + title: 'Episode ' + episode?.ep.replace('E', ''), + link: episode?.id, + }); + }); + return episodeList; + } + catch (err) { + console.error('nfGetEpisodes error', err); + return []; + } +}; +exports.pmGetEpisodes = pmGetEpisodes; diff --git a/dist/primeMirror/pmGetInfo.js b/dist/primeMirror/pmGetInfo.js new file mode 100644 index 0000000..dcc7e01 --- /dev/null +++ b/dist/primeMirror/pmGetInfo.js @@ -0,0 +1,57 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.pmGetInfo = void 0; +const pmGetInfo = async function ({ link, }) { + let providerValue = 'primeMirror'; + try { + const isPrime = providerValue === 'primeMirror' ? 'isPrime=true' : 'isPrime=false'; + const url = `https://netmirror.8man.me/api/net-proxy?${isPrime}&url=${encodeURIComponent(link)}`; + console.log('nfifo', url); + const res = await fetch(url, { + credentials: 'omit', + }); + const data = await res.json(); + const id = link.split('id=')[1]?.split('&')[0]; + const meta = { + title: data.title, + synopsis: data.desc, + image: `https://img.nfmirrorcdn.top/poster/h/${id}.jpg`, + cast: data?.short_cast?.split(','), + tags: [data?.year, data?.hdsd, ...data?.thismovieis?.split(',')], + imdbId: '', + type: 'series', + }; + console.log('nfinfo', meta); + const linkList = []; + if (data?.season?.length > 0) { + data.season.map((season) => { + linkList.push({ + title: 'Season ' + season?.s, + episodesLink: season?.id, + }); + }); + } + else { + linkList.push({ + title: meta.title, + directLinks: [{ link: id, title: 'Movie', type: 'movie' }], + }); + } + return { + ...meta, + linkList: linkList, + }; + } + catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: '', + linkList: [], + }; + } +}; +exports.pmGetInfo = pmGetInfo; diff --git a/dist/primeMirror/pmGetStream.js b/dist/primeMirror/pmGetStream.js new file mode 100644 index 0000000..ab85194 --- /dev/null +++ b/dist/primeMirror/pmGetStream.js @@ -0,0 +1,39 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.pmGetStream = void 0; +const pmGetStream = async ({ link: id, providerContext, }) => { + const { getBaseUrl } = providerContext; + try { + let providerValue = 'primeMirror'; + const baseUrl = await getBaseUrl('nfMirror'); + const url = `https://netmirror.8man.me/api/net-proxy?url=${baseUrl}${providerValue === 'netflixMirror' + ? '/mobile/playlist.php?id=' + : '/pv/playlist.php?id='}${id}&t=${Math.round(new Date().getTime() / 1000)}`; + console.log('nfGetStream, url:', url); + const res = await fetch(url, { + credentials: 'omit', + }); + const resJson = await res.json(); + const data = resJson?.[0]; + const streamLinks = []; + data?.sources.forEach((source) => { + streamLinks.push({ + server: source.label, + link: (baseUrl + source.file)?.replace(':su', ':ni'), + type: 'm3u8', + headers: { + Referer: baseUrl, + origin: baseUrl, + Cookie: 'hd=on', + }, + }); + }); + console.log(streamLinks); + return streamLinks; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.pmGetStream = pmGetStream; diff --git a/dist/primewire/index.js b/dist/primewire/index.js new file mode 100644 index 0000000..892282a --- /dev/null +++ b/dist/primewire/index.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.primewire = void 0; +const pwCatalogl_1 = require("./pwCatalogl"); +const pwGetPosts_1 = require("./pwGetPosts"); +const pwGetInfo_1 = require("./pwGetInfo"); +const pwGetStream_1 = require("./pwGetStream"); +exports.primewire = { + catalog: pwCatalogl_1.pwCatalogList, + genres: pwCatalogl_1.pwGenresList, + GetMetaData: pwGetInfo_1.pwGetInfo, + GetHomePosts: pwGetPosts_1.pwGetPosts, + GetStream: pwGetStream_1.pwGetStream, + GetSearchPosts: pwGetPosts_1.pwGetPostsSearch, +}; diff --git a/dist/primewire/pwCatalogl.js b/dist/primewire/pwCatalogl.js new file mode 100644 index 0000000..6a19393 --- /dev/null +++ b/dist/primewire/pwCatalogl.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.pwGenresList = exports.pwCatalogList = void 0; +exports.pwCatalogList = [ + { + title: 'Recently Added', + filter: '/filter?sort=Just+Added&free_links=true', + }, + { + title: 'TV Shows', + filter: '/filter?sort=Trending+Today&type=tv', + }, + { + title: 'Movies', + filter: '/filter?sort=Trending+Today&type=movie', + }, +]; +exports.pwGenresList = []; diff --git a/dist/primewire/pwGetInfo.js b/dist/primewire/pwGetInfo.js new file mode 100644 index 0000000..07f6518 --- /dev/null +++ b/dist/primewire/pwGetInfo.js @@ -0,0 +1,78 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.pwGetInfo = void 0; +const pwGetInfo = async function ({ link, providerContext, }) { + try { + const { axios, cheerio } = providerContext; + const url = link; + const baseUrl = link.split('/').slice(0, 3).join('/'); + const res = await axios.get(url); + const html = await res.data; + const $ = cheerio.load(html); + const imdbId = $('.movie_info') + .find('a[href*="imdb.com/title/tt"]:not([href*="imdb.com/title/tt/"])') + .attr('href') + ?.split('/')[4] || ''; + const type = $('.show_season').html() ? 'series' : 'movie'; + const linkList = []; + $('.show_season').each((i, element) => { + const seasonTitle = 'Season ' + $(element).attr('data-id'); + const episodes = []; + $(element) + .children() + .each((i, element2) => { + const episodeTitle = $(element2) + .find('a') + .children() + .remove() + .end() + .text() + .trim() + .replace('E', 'Epiosode '); + const episodeLink = baseUrl + $(element2).find('a').attr('href'); + if (episodeTitle && episodeLink) { + episodes.push({ + title: episodeTitle, + link: episodeLink, + }); + } + }); + linkList.push({ + title: seasonTitle, + directLinks: episodes, + }); + }); + if (type === 'movie') { + linkList.push({ + title: 'Movie', + directLinks: [ + { + link: link, + title: 'Movie', + type: 'movie', + }, + ], + }); + } + return { + title: '', + image: '', + imdbId: imdbId, + synopsis: '', + type: type, + linkList: linkList, + }; + } + catch (error) { + console.error(error); + return { + title: '', + image: '', + imdbId: '', + synopsis: '', + linkList: [], + type: 'uhd', + }; + } +}; +exports.pwGetInfo = pwGetInfo; diff --git a/dist/primewire/pwGetPosts.js b/dist/primewire/pwGetPosts.js new file mode 100644 index 0000000..aa078f4 --- /dev/null +++ b/dist/primewire/pwGetPosts.js @@ -0,0 +1,46 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.pwGetPostsSearch = exports.pwGetPosts = void 0; +const pwGetPosts = async function ({ filter, page, signal, providerContext, }) { + const { getBaseUrl, axios, cheerio } = providerContext; + const baseUrl = await getBaseUrl('primewire'); + const url = `${baseUrl + filter}&page=${page}`; + return posts({ baseUrl, url, signal, axios, cheerio }); +}; +exports.pwGetPosts = pwGetPosts; +const pwGetPostsSearch = async function ({ searchQuery, page, signal, providerContext, }) { + const { getBaseUrl, axios, cheerio, Aes } = providerContext; + const getSHA256ofJSON = async function (input) { + return await Aes.sha1(input); + }; + const baseUrl = await getBaseUrl('primewire'); + const hash = await getSHA256ofJSON(searchQuery + 'JyjId97F9PVqUPuMO0'); + const url = `${baseUrl}/filter?s=${searchQuery}&page=${page}&ds=${hash.slice(0, 10)}`; + return posts({ baseUrl, url, signal, axios, cheerio }); +}; +exports.pwGetPostsSearch = pwGetPostsSearch; +async function posts({ baseUrl, url, signal, axios, cheerio, }) { + try { + const res = await axios.get(url, { signal }); + const data = res.data; + const $ = cheerio.load(data); + const catalog = []; + $('.index_item.index_item_ie').map((i, element) => { + const title = $(element).find('a').attr('title'); + const link = $(element).find('a').attr('href'); + const image = $(element).find('img').attr('src') || ''; + if (title && link) { + catalog.push({ + title: title, + link: baseUrl + link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('primewire error ', err); + return []; + } +} diff --git a/dist/primewire/pwGetStream.js b/dist/primewire/pwGetStream.js new file mode 100644 index 0000000..3c272e8 --- /dev/null +++ b/dist/primewire/pwGetStream.js @@ -0,0 +1,125 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.pwGetStream = void 0; +const pwGetStream = async function ({ link: url, type, providerContext, }) { + const { axios, cheerio } = providerContext; + try { + console.log('pwGetStream', type, url); + const baseUrl = url.split('/').slice(0, 3).join('/'); + const streamLinks = []; + const urls = []; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + $('tr:contains("mixdrop")').map((i, element) => { + const id = $(element).find('.wp-menu-btn').attr('data-wp-menu'); + const size = $(element).find('.wp-menu-btn').next().text(); + if (id) { + urls.push({ id: baseUrl + '/links/go/' + id, size }); + } + }); + console.log('urls', urls); + for (const url of urls) { + const res2 = await axios.head(url.id); + const location = res2.request?.responseURL.replace('/f/', '/e/'); + const res3 = await fetch(location, { + credentials: 'include', + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0', + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', + 'Accept-Language': 'en-US,en;q=0.5', + 'Upgrade-Insecure-Requests': '1', + 'Sec-Fetch-Dest': 'iframe', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'same-origin', + Pragma: 'no-cache', + 'Cache-Control': 'no-cache', + referer: res2.request?.responseURL, + }, + referrer: res2.request?.responseURL, + method: 'GET', + mode: 'cors', + }); + const data3 = await res3.text(); + // let MDCore: any = {}; + // Step 1: Extract the function parameters and the encoded string + var functionRegex = /eval\(function\((.*?)\)\{.*?return p\}.*?\('(.*?)'\.split/; + var match = functionRegex.exec(data3); + let p = ''; + if (match) { + // var params = match[1].split(',').map(param => param.trim()); + var encodedString = match[2]; + console.log('Encoded String:', encodedString); + // console.log('Parameters:', params); + // console.log('Encoded String:', encodedString.split("',36,")[0], '🔥🔥'); + const base = Number(encodedString.split(",'|MDCore|")[0].split(',')[encodedString.split(",'|MDCore|")[0].split(',').length - 1]); + console.log('Base:', base); + p = encodedString.split(`',${base},`)?.[0].trim(); + let a = base; + let c = encodedString.split(`',${base},`)[1].slice(2).split('|').length; + let k = encodedString.split(`',${base},`)[1].slice(2).split('|'); + // console.log('p:', p); + // console.log('a:', a); + // console.log('c:', c); + // console.log('k:', k); + const decode = function (p, a, c, k, e, d) { + e = function (c) { + return c.toString(36); + }; + if (!''.replace(/^/, String)) { + while (c--) { + d[c.toString(a)] = k[c] || c.toString(a); + } + k = [ + function (e) { + return d[e]; + }, + ]; + e = function () { + return '\\w+'; + }; + c = 1; + } + while (c--) { + if (k[c]) { + p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]); + } + } + return p; + }; + const decoded = decode(p, a, c, k, 0, {}); + // get MDCore.wurl= + const wurl = decoded.match(/MDCore\.wurl="([^"]+)"/)?.[1]; + console.log('wurl:', wurl); + const streamUrl = 'https:' + wurl; + console.log('streamUrl:', streamUrl); + streamLinks.push({ + server: 'Mixdrop ' + url.size, + link: streamUrl, + type: 'mp4', + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0', + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', + 'Accept-Language': 'en-US,en;q=0.5', + 'Upgrade-Insecure-Requests': '1', + 'Sec-Fetch-Dest': 'iframe', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'same-origin', + Pragma: 'no-cache', + 'Cache-Control': 'no-cache', + referer: res2.request?.responseURL, + }, + }); + } + else { + console.log('No match found'); + } + } + return streamLinks; + } + catch (err) { + console.error(err); + return []; + } +}; +exports.pwGetStream = pwGetStream; diff --git a/dist/protonMovies/index.js b/dist/protonMovies/index.js new file mode 100644 index 0000000..f51d553 --- /dev/null +++ b/dist/protonMovies/index.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.protonMovies = void 0; +const protonCatalog_1 = require("./protonCatalog"); +const protonGetPosts_1 = require("./protonGetPosts"); +const protonGetMeta_1 = require("./protonGetMeta"); +const protonGetStream_1 = require("./protonGetStream"); +exports.protonMovies = { + catalog: protonCatalog_1.protonCatalogList, + genres: protonCatalog_1.protonGenresList, + GetMetaData: protonGetMeta_1.protonGetInfo, + GetHomePosts: protonGetPosts_1.protonGetPosts, + GetStream: protonGetStream_1.protonGetStream, + GetSearchPosts: protonGetPosts_1.protonGetPostsSearch, +}; diff --git a/dist/protonMovies/protonCatalog.js b/dist/protonMovies/protonCatalog.js new file mode 100644 index 0000000..9cef0ce --- /dev/null +++ b/dist/protonMovies/protonCatalog.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.protonGenresList = exports.protonCatalogList = void 0; +exports.protonCatalogList = [ + { + title: 'Latest', + filter: '/movies', + }, + { + title: 'Netflix', + filter: '/platform/netflix', + }, + { + title: 'Disney +', + filter: '/platform/disney-hotstar', + }, + { + title: 'Amazon Prime', + filter: '/platform/amazon-prime-video', + }, +]; +exports.protonGenresList = []; diff --git a/dist/protonMovies/protonGetMeta.js b/dist/protonMovies/protonGetMeta.js new file mode 100644 index 0000000..2533501 --- /dev/null +++ b/dist/protonMovies/protonGetMeta.js @@ -0,0 +1,93 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.protonGetInfo = void 0; +const protonGetInfo = async function ({ link, providerContext, }) { + try { + const { axios, cheerio, getBaseUrl } = providerContext; + console.log('all', link); + const res = await axios.get(link); + const data = res.data; + function decodeHtml(encodedArray) { + // Join array elements into a single string + const joined = encodedArray.join(''); + // Replace escaped quotes + const unescaped = joined.replace(/\\"/g, '"').replace(/\\'/g, "'"); + // Remove remaining escape characters + const cleaned = unescaped + .replace(/\\n/g, '\n') + .replace(/\\t/g, '\t') + .replace(/\\r/g, '\r'); + // Convert literal string representations back to characters + const decoded = cleaned + .replace(/"/g, '"') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/&/g, '&'); + return decoded; + } + const $$ = cheerio.load(data); + const htmlArray = $$('script:contains("decodeURIComponent")') + .text() + .split(' = ')?.[1] + ?.split('protomovies')?.[0] + ?.trim() + ?.slice(0, -1); // remove the last character + // console.log('protonGetInfo', htmlArray); + const html = decodeHtml(JSON.parse(htmlArray)); + // console.log('all', html); + const $ = cheerio.load(html); + const title = $('.trending-text.fw-bold.texture-text.text-uppercase.my-0.fadeInLeft.animated.d-inline-block').text(); + const image = $('#thumbnail').attr('src'); + const type = link.includes('series') ? 'series' : 'movie'; + const synopsis = $('.col-12.iq-mb-30.animated.fadeIn').first().text() || + $('.description-content').text(); + const tags = $('.p-0.mt-2.list-inline.d-flex.flex-wrap.movie-tag') + .find('li') + .map((i, el) => $(el).text()) + .slice(0, 3) + .get(); + const baseUrl = await getBaseUrl('protonMovies'); + const links = []; + if (type === 'movie') { + const directLinks = []; + directLinks.push({ title: 'Movie', link: link }); + links.push({ title: 'Movie', directLinks: directLinks }); + } + else { + $('#episodes') + .children() + .map((i, element) => { + let directLinks = []; + $(element) + .find('.episode-block') + .map((j, ep) => { + const link = baseUrl + $(ep).find('a').attr('href') || ''; + const title = 'Episode ' + $(ep).find('.episode-number').text().split('E')[1]; + directLinks.push({ title, link }); + }); + links.push({ title: 'Season ' + (i + 1), directLinks: directLinks }); + }); + } + return { + image: image || '', + imdbId: '', + linkList: links, + title: title || '', + synopsis: synopsis, + tags: tags, + type: type, + }; + } + catch (err) { + console.error('prton', err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.protonGetInfo = protonGetInfo; diff --git a/dist/protonMovies/protonGetPosts.js b/dist/protonMovies/protonGetPosts.js new file mode 100644 index 0000000..7bd918c --- /dev/null +++ b/dist/protonMovies/protonGetPosts.js @@ -0,0 +1,70 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.protonGetPostsSearch = exports.protonGetPosts = void 0; +const protonGetPosts = async function ({ filter, page, signal, providerContext, }) { + const { getBaseUrl, axios, cheerio } = providerContext; + const baseUrl = await getBaseUrl('protonMovies'); + const url = `${baseUrl + filter}/page/${page}/`; + return posts({ url, baseUrl, signal, axios, cheerio }); +}; +exports.protonGetPosts = protonGetPosts; +const protonGetPostsSearch = async function ({ searchQuery, page, signal, providerContext, }) { + const { getBaseUrl, axios, cheerio } = providerContext; + const baseUrl = await getBaseUrl('protonMovies'); + const url = `${baseUrl}/search/${searchQuery}/page/${page}/`; + return posts({ url, baseUrl, signal, axios, cheerio }); +}; +exports.protonGetPostsSearch = protonGetPostsSearch; +async function posts({ url, baseUrl, signal, axios, cheerio, }) { + function decodeHtml(encodedArray) { + // Join array elements into a single string + const joined = encodedArray.join(''); + // Replace escaped quotes + const unescaped = joined.replace(/\\"/g, '"').replace(/\\'/g, "'"); + // Remove remaining escape characters + const cleaned = unescaped + .replace(/\\n/g, '\n') + .replace(/\\t/g, '\t') + .replace(/\\r/g, '\r'); + // Convert literal string representations back to characters + const decoded = cleaned + .replace(/"/g, '"') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/&/g, '&'); + return decoded; + } + try { + const res = await axios.get(url, { + headers: { + referer: baseUrl, + }, + signal, + }); + const data = res.data; + const regex = /\[(?=.*?"
{ + const title = $(element).find('h5').text(); + const link = $(element).find('h5').find('a').attr('href'); + const image = $(element).find('img').attr('data-src') || + $(element).find('img').attr('src') || + ''; + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('protonGetPosts error ', err); + return []; + } +} diff --git a/dist/protonMovies/protonGetStream.js b/dist/protonMovies/protonGetStream.js new file mode 100644 index 0000000..0fa66c1 --- /dev/null +++ b/dist/protonMovies/protonGetStream.js @@ -0,0 +1,165 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.protonGetStream = void 0; +function LALLJLutmoZpvvbikjaWM(str) { + var buf = new ArrayBuffer(str.length * 2); + var bufView = new Uint8Array(buf); + for (var i = 0, strLen = str.length; i < strLen; i++) { + bufView[i] = str.charCodeAt(i); + } + return buf; +} +function getOrCreateUID() { + const uid = 'uid_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); + return uid; +} +const protonGetStream = async function ({ link, providerContext, }) { + const { axios, cheerio, commonHeaders: headers, extractors } = providerContext; + const { gofileExtracter } = extractors; + function generateMessageToken(baseUrlL) { + const hostname = baseUrlL?.replace(/https?:\/\//, '').split('/')[0]; + console.log('generateMessageToken hostname', hostname); + const NsmxUftCNibQ = `[hostname=${hostname}][agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0][tmz=India Standard Time][userTimezoneOffset=-330][{"url":"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js","type":"script","duration":253.30000000074506},{"url":"https://challenges.cloudflare.com/turnstile/v0/api.js?onload=onloadTurnstileCallback","type":"script","duration":397.19999999925494},{"url":"https://adoto.net/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js","type":"img","duration":225.90000000223517},{"url":"https://code.jquery.com/jquery-3.3.1.slim.min.js","type":"script","duration":65.30000000074506},{"url":"https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015","type":"script","duration":225.89999999850988},{"url":"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js","type":"script","duration":253.30000000074506},{"url":"https://challenges.cloudflare.com/turnstile/v0/api.js?onload=onloadTurnstileCallback","type":"script","duration":397.19999999925494},{"url":"https://adoto.net/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js","type":"img","duration":225.90000000223517},{"url":"https://code.jquery.com/jquery-3.3.1.slim.min.js","type":"script","duration":65.30000000074506},{"url":"https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015","type":"script","duration":225.89999999850988},{"url":"https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/b/turnstile/if/ov2/av0/rcv/b3dhg/0x4AAAAAAAQDru7r64xT2ifD/auto/fbE/new/normal/auto/","type":"iframe","duration":2050.300000000745},{"url":"https://new19.gdtot.dad/favicon.ico","type":"img","duration":1003.6999999992549},{"url":"https://vikingfile.com/assets/favicon-64375c377b5df8304acbdad4f4430694.ico","type":"img","duration":183.19999999925494},{"url":"https://gofile.io/dist/img/favicon32.png","type":"img","duration":19177.199999999255},{"url":"https://pub.clickadu.com/assets/scripts/supported-browsers.js","type":"fetch","duration":18.799999997019768},{"url":"https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/b/turnstile/if/ov2/av0/rcv/b3dhg/0x4AAAAAAAQDru7r64xT2ifD/auto/fbE/auto_expire/normal/auto/","type":"iframe","duration":1612.5999999977648},{"url":"https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/b/turnstile/if/ov2/av0/rcv/b3dhg/0x4AAAAAAAQDru7r64xT2ifD/auto/fbE/auto_expire/normal/auto/","type":"iframe","duration":1154.0999999977648},{"url":"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js","type":"script","duration":253.30000000074506},{"url":"https://challenges.cloudflare.com/turnstile/v0/api.js?onload=onloadTurnstileCallback","type":"script","duration":397.19999999925494},{"url":"https://adoto.net/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js","type":"img","duration":225.90000000223517},{"url":"https://code.jquery.com/jquery-3.3.1.slim.min.js","type":"script","duration":65.30000000074506},{"url":"https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015","type":"script","duration":225.89999999850988},{"url":"https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/b/turnstile/if/ov2/av0/rcv/b3dhg/0x4AAAAAAAQDru7r64xT2ifD/auto/fbE/new/normal/auto/","type":"iframe","duration":2050.300000000745},{"url":"https://new19.gdtot.dad/favicon.ico","type":"img","duration":1003.6999999992549},{"url":"https://vikingfile.com/assets/favicon-64375c377b5df8304acbdad4f4430694.ico","type":"img","duration":183.19999999925494},{"url":"https://gofile.io/dist/img/favicon32.png","type":"img","duration":19177.199999999255},{"url":"https://pub.clickadu.com/assets/scripts/supported-browsers.js","type":"fetch","duration":18.799999997019768},{"url":"https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/b/turnstile/if/ov2/av0/rcv/b3dhg/0x4AAAAAAAQDru7r64xT2ifD/auto/fbE/auto_expire/normal/auto/","type":"iframe","duration":1612.5999999977648},{"url":"https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/b/turnstile/if/ov2/av0/rcv/b3dhg/0x4AAAAAAAQDru7r64xT2ifD/auto/fbE/auto_expire/normal/auto/","type":"iframe","duration":1154.0999999977648},{"url":"https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/b/turnstile/if/ov2/av0/rcv/b3dhg/0x4AAAAAAAQDru7r64xT2ifD/auto/fbE/auto_expire/normal/auto/","type":"iframe","duration":986}][{"elements":{"div":70,"span":68,"img":4,"iframe":0,"script":28,"link":20,"p":5,"a":213,"ul":28,"li":208,"button":9,"input":5},"hidden":{"div":13,"span":60,"img":1,"iframe":0,"script":28,"link":20,"p":0,"a":186,"ul":22,"li":184,"button":6,"input":2},"errors":{"network":0,"js":0},"eventListeners":0}]`; + var jRpeP = LALLJLutmoZpvvbikjaWM(NsmxUftCNibQ); + var jzKEwqEAcWFMNwHZnCCqJQ = new Uint8Array(jRpeP); + var kyMXQUxoFYuZIBlKvlHa = jzKEwqEAcWFMNwHZnCCqJQ.toString(); + var kyMXQUxoFYuZIBlKvlHa = kyMXQUxoFYuZIBlKvlHa.replace(/2/g, '004'); + var kyMXQUxoFYuZIBlKvlHa = kyMXQUxoFYuZIBlKvlHa.replace(/3/g, '005'); + var kyMXQUxoFYuZIBlKvlHa = kyMXQUxoFYuZIBlKvlHa.replace(/7/g, '007'); + var kyMXQUxoFYuZIBlKvlHa = kyMXQUxoFYuZIBlKvlHa.replace(/,0,0,0/g, ''); + return kyMXQUxoFYuZIBlKvlHa; + } + function decodeHtml(encodedArray) { + // Join array elements into a single string + const joined = encodedArray.join(''); + // Replace escaped quotes + const unescaped = joined.replace(/\\"/g, '"').replace(/\\'/g, "'"); + // Remove remaining escape characters + const cleaned = unescaped + .replace(/\\n/g, '\n') + .replace(/\\t/g, '\t') + .replace(/\\r/g, '\r'); + // Convert literal string representations back to characters + const decoded = cleaned + .replace(/"/g, '"') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/&/g, '&'); + return decoded; + } + try { + const streamLinks = []; + const res = await axios.get(link, { headers }); + const data = res.data; + // const regex = /\[(?=.*?"
{ + const formData = new URLSearchParams(); + formData.append('downloadid', id.id); + formData.append('token', 'ok'); + const messageToken = generateMessageToken(baseUrl); + const uid = getOrCreateUID(); + const idRes = await fetch(`${baseUrl}/ppd.php`, { + headers: { + accept: '*/*', + 'accept-language': 'en-US,en;q=0.9,en-IN;q=0.8', + 'cache-control': 'no-cache', + 'content-type': 'application/x-www-form-urlencoded', + pragma: 'no-cache', + priority: 'u=1, i', + 'sec-ch-ua': '"Chromium";v="136", "Microsoft Edge";v="136", "Not.A/Brand";v="99"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'sec-fetch-dest': 'empty', + 'sec-fetch-mode': 'cors', + 'sec-fetch-site': 'same-origin', + cookie: 'ext_name=ojplmecpdpgccookcobabopnaifgidhf; tgInvite222=true; cf_clearance=3ynJv2B6lHMj3FCOqtfQaL7lTN4KC3xmPRMgcNtddAc-1748787867-1.2.1.1-SEIhLbWR3ehfib5Y3P5pjzj1Qu9wipc52Icv4AmNkztXn2pTXhjKgxXnvTuA2bNscgHuc1juXujAHteqY_vaMmy2C3djMWnJGzjje_XvXZXKht8rwHZt6sviq7KAYvrYZPTrATqENuopzmqmK6dDFS.CAnWHt0VDn8q06iLm5rYj1AXUo3qkV5p1Idx_25elWHYGG8yengBrQV1MYVM9LMdQqv44PXu69FZvNkgv.d6blCKyneJnoLkw4LHAccu.QRPbFwWqqTDyO9YTLRQW9w29bKghD3_JVxkz.qxpg5FbocJ3i6tJJy74SvROpYdpVUOn0fW1YgQ7RxYwhNoHpdTKy8pvmQJGRuSVW1GjO_k', + Referer: 'https://m3.protonmovies.top/download/', + 'Referrer-Policy': 'strict-origin-when-cross-origin', + }, + body: `downloadid=${id.id}&msg=${messageToken}&uid=${uid}&token=ok`, + method: 'POST', + }); + const idData = await idRes.text(); + secondIdList.push({ + quality: id.quality, + id: idData, + }); + console.log('idData', idData); + })); + await Promise.all(secondIdList.map(async (id) => { + const idRes = await axios.post(`${baseUrl}/tmp/${id.id}`); + if (idRes.data.ppd['gofile.io']) { + const goRes = await gofileExtracter(idRes.data.ppd['gofile.io'].link.split('/').pop()); + console.log('link', goRes.link); + if (goRes.link) { + streamLinks.push({ + link: goRes.link, + server: 'gofile ' + id.quality, + type: 'mkv', + headers: { + referer: 'https://gofile.io', + connection: 'keep-alive', + contentType: 'video/x-matroska', + cookie: 'accountToken=' + goRes.token, + }, + }); + } + } + })); + return streamLinks; + } + catch (e) { + console.log('proton get stream err', e); + return []; + } +}; +exports.protonGetStream = protonGetStream; diff --git a/dist/providerContext.js b/dist/providerContext.js new file mode 100644 index 0000000..5b6a8a9 --- /dev/null +++ b/dist/providerContext.js @@ -0,0 +1,66 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.providerContext = void 0; +const axios_1 = __importDefault(require("axios")); +const getBaseUrl_1 = require("./getBaseUrl"); +const headers_1 = require("./headers"); +const cheerio = __importStar(require("cheerio")); +const hubcloudExtractor_1 = require("./hubcloudExtractor"); +const gofileExtracter_1 = require("./gofileExtracter"); +const superVideoExtractor_1 = require("./superVideoExtractor"); +const gdflixExtractor_1 = require("./gdflixExtractor"); +const react_native_aes_crypto_1 = __importDefault(require("react-native-aes-crypto")); +/** + * Context for provider functions. + * This context is used to pass common dependencies to provider functions. + */ +const extractors = { + hubcloudExtracter: hubcloudExtractor_1.hubcloudExtracter, + gofileExtracter: gofileExtracter_1.gofileExtracter, + superVideoExtractor: superVideoExtractor_1.superVideoExtractor, + gdFlixExtracter: gdflixExtractor_1.gdFlixExtracter, +}; +exports.providerContext = { + axios: axios_1.default, + getBaseUrl: getBaseUrl_1.getBaseUrl, + commonHeaders: headers_1.headers, + Aes: react_native_aes_crypto_1.default, + cheerio, + extractors, +}; diff --git a/dist/ridoMovies/index.js b/dist/ridoMovies/index.js new file mode 100644 index 0000000..4f5db2e --- /dev/null +++ b/dist/ridoMovies/index.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ridoMovies = void 0; +const guardahdCatalog_1 = require("../guardahd/guardahdCatalog"); +const allGetPost_1 = require("../autoEmbed/allGetPost"); +const guardahdGetPosts_1 = require("../guardahd/guardahdGetPosts"); +const ridoGetMeta_1 = require("./ridoGetMeta"); +const ridoGetSream_1 = require("./ridoGetSream"); +exports.ridoMovies = { + catalog: guardahdCatalog_1.guardahdCatalog, + genres: guardahdCatalog_1.guardahdGenresList, + GetMetaData: ridoGetMeta_1.ridoGetInfo, + GetHomePosts: allGetPost_1.allGetPost, + GetStream: ridoGetSream_1.ridoGetStream, + GetSearchPosts: guardahdGetPosts_1.guardahdGetSearchPosts, +}; diff --git a/dist/ridoMovies/ridoGetMeta.js b/dist/ridoMovies/ridoGetMeta.js new file mode 100644 index 0000000..74f7ba4 --- /dev/null +++ b/dist/ridoMovies/ridoGetMeta.js @@ -0,0 +1,85 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ridoGetInfo = void 0; +const ridoGetInfo = async function ({ link, providerContext, }) { + try { + const { getBaseUrl, axios } = providerContext; + const res = await axios.get(link); + const data = res.data; + const meta = { + title: '', + synopsis: '', + image: '', + imdbId: data?.meta?.imdb_id || '', + type: data?.meta?.type || 'movie', + }; + const baseUrl = await getBaseUrl('ridomovies'); + let slug = ''; + try { + const res2 = await axios.get(baseUrl + '/core/api/search?q=' + meta.imdbId); + const data2 = res2.data; + slug = data2?.data?.items[0]?.fullSlug; + if (!slug || meta?.type === 'series') { + return { + title: '', + synopsis: '', + image: '', + imdbId: data?.meta?.imdb_id || '', + type: meta?.type || 'movie', + linkList: [], + }; + } + } + catch (err) { + return { + title: '', + synopsis: '', + image: '', + imdbId: meta?.imdbId || '', + type: meta?.type || 'movie', + linkList: [], + }; + } + const links = []; + let directLinks = []; + let season = new Map(); + if (meta.type === 'series') { + data?.meta?.videos?.map((video) => { + if (video?.season <= 0) + return; + if (!season.has(video?.season)) { + season.set(video?.season, []); + } + season.get(video?.season).push({ + title: 'Episode ' + video?.episode, + link: '', + }); + }); + for (const [seasonNum, episodes] of season.entries()) { + links.push({ + title: 'Season ' + seasonNum, + directLinks: episodes, + }); + } + } + else { + directLinks.push({ title: 'Movie', link: link }); + links.push({ title: 'Movie', directLinks: directLinks }); + } + return { + ...meta, + linkList: links, + }; + } + catch (err) { + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.ridoGetInfo = ridoGetInfo; diff --git a/dist/ridoMovies/ridoGetSream.js b/dist/ridoMovies/ridoGetSream.js new file mode 100644 index 0000000..1efad2e --- /dev/null +++ b/dist/ridoMovies/ridoGetSream.js @@ -0,0 +1,64 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ridoGetStream = void 0; +const ridoGetStream = async ({ link: data, providerContext, }) => { + try { + const { cheerio, commonHeaders: headers, axios } = providerContext; + const streamData = JSON.parse(data); + const streamLinks = []; + // const path = + // streamData?.type === 'movie' + // ? `/${streamData?.slug}` + // : `/${streamData?.slug}/season-${streamData?.season}/episode-${streamData?.episode}`; + // const url = streamData?.baseUrl + path; + // console.log('all', url); + // const res = await axios.get(url, {headers}); + // const postId = res.data.split('\\"postid\\":\\"')[1].split('\\"')[0]; + // console.log('rido post id', postId); + const url = streamData?.baseUrl + '/api/' + streamData?.slug; + console.log('rido url', url); + const res = await axios.get(url, { headers }); + const iframe = res.data.data?.[0]?.url; + console.log('rido data', iframe); + const iframeUrl = iframe.split('src="')[1].split('"')[0]; + console.log('rido iframeUrl', iframeUrl); + const iframeRes = await axios.get(iframeUrl, { + headers: { + ...headers, + Referer: streamData?.baseUrl, + }, + }); + const $ = cheerio.load(iframeRes.data); + const script = $('script:contains("eval")').html(); + if (!script) { + throw new Error('Unable to find script'); + } + // console.log('rido script', script); + const srcUrl = unpackJavaScript(script.trim()); + console.log('rido srcUrl', srcUrl); + streamLinks.push({ + link: srcUrl, + server: 'rido', + type: 'm3u8', + headers: { + Referer: iframeUrl, + }, + }); + return streamLinks; + } + catch (e) { + console.log('rido get stream err', e); + return []; + } +}; +exports.ridoGetStream = ridoGetStream; +function unpackJavaScript(packedCode) { + const encodedString = packedCode.split('|aHR')[1].split('|')[0]; + const base64Url = 'aHR' + encodedString; + function addPadding(base64) { + return base64 + '='.repeat((4 - (base64.length % 4)) % 4); + } + console.log('rido base64Url', base64Url); + const unpackedCode = atob(addPadding(base64Url)); + return unpackedCode; +} diff --git a/dist/ringz/index.js b/dist/ringz/index.js new file mode 100644 index 0000000..b23bc23 --- /dev/null +++ b/dist/ringz/index.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ringz = void 0; +const ringzGetPosts_1 = require("./ringzGetPosts"); +const ringzGetMeta_1 = require("./ringzGetMeta"); +const ringzCatalog_1 = require("./ringzCatalog"); +const ringzGetStream_1 = require("./ringzGetStream"); +exports.ringz = { + catalog: ringzCatalog_1.ringzCatalogList, + genres: ringzCatalog_1.ringzGenresList, + GetMetaData: ringzGetMeta_1.ringzGetInfo, + GetHomePosts: ringzGetPosts_1.ringzGetPosts, + GetStream: ringzGetStream_1.ringzGetStream, + GetSearchPosts: ringzGetPosts_1.ringzGetPostsSearch, +}; diff --git a/dist/ringz/ringzCatalog.js b/dist/ringz/ringzCatalog.js new file mode 100644 index 0000000..d77fcb9 --- /dev/null +++ b/dist/ringz/ringzCatalog.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ringzGenresList = exports.ringzCatalogList = void 0; +exports.ringzCatalogList = [ + { + title: 'Movies', + filter: 'MOVIES', + }, + { + title: 'TV Shows', + filter: 'SERIES', + }, + { + title: 'Anime', + filter: 'ANIME', + }, +]; +exports.ringzGenresList = []; diff --git a/dist/ringz/ringzGetMeta.js b/dist/ringz/ringzGetMeta.js new file mode 100644 index 0000000..530468f --- /dev/null +++ b/dist/ringz/ringzGetMeta.js @@ -0,0 +1,85 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ringzGetInfo = void 0; +const ringzGetInfo = async function ({ link: data, }) { + try { + const dataJson = JSON.parse(data); + const title = dataJson?.kn || dataJson?.mn; + const image = dataJson?.IH || dataJson?.IV; + const tags = dataJson?.gn + .split(',') + .slice(0, 3) + .map((tag) => tag.trim()); + const type = dataJson?.cg === 'webSeries' ? 'series' : 'movie'; + const linkList = []; + if (dataJson?.cg === 'webSeries') { + ['1', '2', '3', '4']?.forEach(item => { + const directLinks = []; + if (typeof dataJson?.['eServer' + item] === 'object' && + Object?.keys(dataJson?.['eServer' + item])?.length > 0) { + Object.keys(dataJson?.['eServer' + item]).forEach(key => { + directLinks.push({ + title: 'Episode ' + key, + link: JSON.stringify({ + url: dataJson?.['eServer' + item][key], + server: 'Server ' + item, + }), + }); + }); + linkList.push({ + title: dataJson?.pn + ' (Server ' + item + ')', + directLinks, + }); + } + }); + } + else { + const directLinks = []; + ['1', '2', '3', '4']?.forEach(item => { + if (dataJson?.['s' + item]) { + directLinks.push({ + title: 'Server ' + item + ' (HD)', + link: JSON.stringify({ + url: dataJson?.s1, + server: 'Server ' + item, + }), + }); + } + if (dataJson?.['4s' + item]) { + directLinks.push({ + title: 'Server ' + item + ' (480p)', + link: JSON.stringify({ + url: dataJson?.['4s' + item], + server: 'Server ' + item, + }), + }); + } + }); + linkList.push({ + title: dataJson?.pn, + directLinks, + }); + } + return { + title, + image, + imdbId: '', + synopsis: '', + type, + linkList, + tags, + }; + } + catch (err) { + return { + title: '', + image: '', + imdbId: '', + synopsis: '', + type: 'movie', + linkList: [], + tags: [], + }; + } +}; +exports.ringzGetInfo = ringzGetInfo; diff --git a/dist/ringz/ringzGetPosts.js b/dist/ringz/ringzGetPosts.js new file mode 100644 index 0000000..072e59b --- /dev/null +++ b/dist/ringz/ringzGetPosts.js @@ -0,0 +1,154 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ringzData = exports.headers = exports.ringzGetPostsSearch = exports.ringzGetPosts = void 0; +exports.getRingzMovies = getRingzMovies; +exports.getRingzShows = getRingzShows; +exports.getRingzAnime = getRingzAnime; +exports.getRingzAdult = getRingzAdult; +const ringzGetPosts = async function ({ filter, signal, providerContext, }) { + return posts({ filter, signal, providerContext }); +}; +exports.ringzGetPosts = ringzGetPosts; +const ringzGetPostsSearch = async function ({ searchQuery, page, // providerContext, + }) { + if (page > 1) + return []; + function searchData(data, query) { + // Convert query to lowercase for case-insensitive search + const searchQuery = query.toLowerCase(); + // Filter movies based on movie name (mn) + return data.filter((movie) => { + // Convert movie name to lowercase and check if it includes the search query + const movieName = movie.mn.toLowerCase(); + return movieName.includes(searchQuery); + }); + } + try { + const catalog = []; + const promises = [getRingzMovies(), getRingzShows(), getRingzAnime()]; + const responses = await Promise.all(promises); + responses.map((response) => { + const searchResults = searchData(response, searchQuery); + searchResults.map((element) => { + const title = element?.kn || element?.mn; + const link = JSON.stringify(element); + const image = element?.IV; + if (title && link) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + }); + return catalog; + } + catch (err) { + console.error('ringz error ', err); + return []; + } +}; +exports.ringzGetPostsSearch = ringzGetPostsSearch; +async function posts({ filter, // signal, +// providerContext, + }) { + try { + let response; + if (filter === 'MOVIES') { + response = getRingzMovies(); + } + if (filter === 'SERIES') { + response = getRingzShows(); + } + if (filter === 'ANIME') { + response = getRingzAnime(); + } + const data = await response; + const catalog = []; + data.map((element) => { + const title = element?.kn || element?.mn; + const link = JSON.stringify(element); + const image = element?.IV; + if (title && link) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + console.error('ringz error ', err); + return []; + } +} +exports.headers = { + 'cf-access-client-id': '833049b087acf6e787cedfd85d1ccdb8.access', + 'cf-access-client-secret': '02db296a961d7513c3102d7785df4113eff036b2d57d060ffcc2ba3ba820c6aa', +}; +const BASE_URL = 'https://privatereporz.pages.dev'; +async function getRingzMovies() { + try { + const response = await fetch(`${BASE_URL}/test.json`, { + headers: { + ...exports.headers, + }, + }); + const data = await response.json(); + return data.AllMovieDataList; + } + catch (error) { + console.error(error); + } +} +async function getRingzShows() { + try { + const response = await fetch(`${BASE_URL}/srs.json`, { + headers: { + ...exports.headers, + }, + }); + const data = await response.json(); + return data.webSeriesDataList; + } + catch (error) { + console.error(error); + } +} +async function getRingzAnime() { + try { + const response = await fetch(`${BASE_URL}/anime.json`, { + headers: { + ...exports.headers, + }, + }); + const data = await response.json(); + return data.webSeriesDataList; + } + catch (error) { + console.error(error); + } +} +async function getRingzAdult() { + try { + const response = await fetch(`${BASE_URL}/desihub.json`, { + headers: { + ...exports.headers, + }, + }); + const data = await response.json(); + return data.webSeriesDataList; + } + catch (error) { + console.error(error); + } +} +exports.ringzData = { + getRingzMovies, + getRingzShows, + getRingzAnime, + getRingzAdult, +}; diff --git a/dist/ringz/ringzGetStream.js b/dist/ringz/ringzGetStream.js new file mode 100644 index 0000000..4875ff9 --- /dev/null +++ b/dist/ringz/ringzGetStream.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ringzGetStream = void 0; +const ringzGetStream = async function ({ link: data, }) { + const streamLinks = []; + const dataJson = JSON.parse(data); + streamLinks.push({ + link: dataJson.url, + server: dataJson.server, + type: 'mkv', + }); + return streamLinks; +}; +exports.ringzGetStream = ringzGetStream; diff --git a/dist/showbox/index.js b/dist/showbox/index.js new file mode 100644 index 0000000..0c61caf --- /dev/null +++ b/dist/showbox/index.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.showBox = void 0; +const sbCatalog_1 = require("./sbCatalog"); +const sbGetEpisodeList_1 = require("./sbGetEpisodeList"); +const sbGetMeta_1 = require("./sbGetMeta"); +const sbGetPosts_1 = require("./sbGetPosts"); +const sbGetStream_1 = require("./sbGetStream"); +exports.showBox = { + catalog: sbCatalog_1.catalogList, + genres: sbCatalog_1.sbGenresList, + GetMetaData: sbGetMeta_1.sbGetInfo, + GetHomePosts: sbGetPosts_1.sbGetPosts, + GetStream: sbGetStream_1.sbGetStream, + GetSearchPosts: sbGetPosts_1.sbGetPostsSearch, + GetEpisodeLinks: sbGetEpisodeList_1.sbGetEpisodeLinks, +}; diff --git a/dist/showbox/sbCatalog.js b/dist/showbox/sbCatalog.js new file mode 100644 index 0000000..933d224 --- /dev/null +++ b/dist/showbox/sbCatalog.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.sbGenresList = exports.catalogList = void 0; +exports.catalogList = [ + { + title: 'Home', + filter: '', + }, + { + title: 'Movies', + filter: '/movie', + }, + { + title: 'TV Shows', + filter: '/tv', + }, +]; +exports.sbGenresList = []; diff --git a/dist/showbox/sbGetEpisodeList.js b/dist/showbox/sbGetEpisodeList.js new file mode 100644 index 0000000..bcc6299 --- /dev/null +++ b/dist/showbox/sbGetEpisodeList.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.sbGetEpisodeLinks = void 0; +const sbGetEpisodeLinks = async function ({ url: id, providerContext, }) { + const { axios } = providerContext; + try { + const [fileId, febboxId] = id.split('&'); + const febLink = febboxId + ? `https://www.febbox.com/file/file_share_list?share_key=${fileId}&pwd=&parent_id=${febboxId}&is_html=0` + : `https://www.febbox.com/file/file_share_list?share_key=${fileId}&pwd=&is_html=0`; + const res = await axios.get(febLink); + const data = res.data; + const fileList = data.data.file_list; + const episodeLinks = []; + fileList?.map((file) => { + const fileName = formatEpisodeName(file.file_name); + const epId = file?.fid; + if (!file.is_dir && fileName && epId) { + episodeLinks.push({ + title: fileName, + link: `${fileId}&${epId}`, + }); + } + }); + return episodeLinks; + } + catch (err) { + return []; + } +}; +exports.sbGetEpisodeLinks = sbGetEpisodeLinks; +function formatEpisodeName(title) { + const regex = /[sS](\d+)\s*[eE](\d+)/; + const match = title.match(regex); + if (match) { + const season = match[1].padStart(2, '0'); + const episode = match[2].padStart(2, '0'); + return `Season${season} Episode${episode}`; + } + else { + return title; + } +} diff --git a/dist/showbox/sbGetMeta.js b/dist/showbox/sbGetMeta.js new file mode 100644 index 0000000..0ef9a8b --- /dev/null +++ b/dist/showbox/sbGetMeta.js @@ -0,0 +1,65 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.sbGetInfo = void 0; +const sbGetInfo = async function ({ link, providerContext, }) { + try { + const { axios, cheerio } = providerContext; + const url = link; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const type = url.includes('tv') ? 'series' : 'movie'; + const imdbId = ''; + const title = $('.heading-name').text(); + const rating = $('.btn-imdb') + .text() + ?.match(/\d+(\.\d+)?/g)?.[0] || ''; + const image = $('.cover_follow').attr('style')?.split('url(')[1]?.split(')')[0] || ''; + const synopsis = $('.description') + .text() + ?.replaceAll(/[\n\t]/g, '') + ?.trim(); + const febID = $('.heading-name').find('a').attr('href')?.split('/')?.pop(); + const baseUrl = url.split('/').slice(0, 3).join('/'); + const indexUrl = `${baseUrl}/index/share_link?id=${febID}&type=${type === 'movie' ? '1' : '2'}`; + const indexRes = await axios.get(indexUrl); + const indexData = indexRes.data; + const febKey = indexData.data.link.split('/').pop(); + const febLink = `https://www.febbox.com/file/file_share_list?share_key=${febKey}&is_html=0`; + const febRes = await axios.get(febLink); + const febData = febRes.data; + const fileList = febData?.data?.file_list; + const links = []; + if (fileList) { + fileList.map((file) => { + const fileName = `${file.file_name} (${file.file_size})`; + const fileId = file.fid; + links.push({ + title: fileName, + episodesLink: file.is_dir ? `${febKey}&${fileId}` : `${febKey}&`, + }); + }); + } + return { + title, + rating, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } + catch (err) { + return { + title: '', + rating: '', + synopsis: '', + image: '', + imdbId: '', + type: '', + linkList: [], + }; + } +}; +exports.sbGetInfo = sbGetInfo; diff --git a/dist/showbox/sbGetPosts.js b/dist/showbox/sbGetPosts.js new file mode 100644 index 0000000..9193df6 --- /dev/null +++ b/dist/showbox/sbGetPosts.js @@ -0,0 +1,47 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.sbGetPostsSearch = exports.sbGetPosts = void 0; +const sbGetPosts = async function ({ filter, page, +// providerValue, +signal, providerContext, }) { + const { getBaseUrl, axios, cheerio } = providerContext; + const baseUrl = await getBaseUrl('showbox'); + const url = `${baseUrl + filter}?page=${page}/`; + return posts({ url, signal, baseUrl, axios, cheerio }); +}; +exports.sbGetPosts = sbGetPosts; +const sbGetPostsSearch = async function ({ searchQuery, page, +// providerValue, +signal, providerContext, }) { + const { getBaseUrl, axios, cheerio } = providerContext; + const baseUrl = await getBaseUrl('showbox'); + const url = `${baseUrl}/search?keyword=${searchQuery}&page=${page}`; + return posts({ url, signal, baseUrl, axios, cheerio }); +}; +exports.sbGetPostsSearch = sbGetPostsSearch; +async function posts({ url, signal, +// baseUrl, +axios, cheerio, }) { + try { + const res = await axios.get(url, { signal }); + const data = res.data; + const $ = cheerio.load(data); + const catalog = []; + $('.movie-item').map((i, element) => { + const title = $(element).find('.movie-title').text(); + const link = $(element).find('a').attr('href'); + const image = $(element).find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + return []; + } +} diff --git a/dist/showbox/sbGetStream.js b/dist/showbox/sbGetStream.js new file mode 100644 index 0000000..fb9aac6 --- /dev/null +++ b/dist/showbox/sbGetStream.js @@ -0,0 +1,70 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.sbGetStream = void 0; +const cheerio = __importStar(require("cheerio")); +const sbGetStream = async function ({ link: id, +// type, +signal, providerContext, }) { + try { + const { axios } = providerContext; + const stream = []; + const [, epId] = id.split('&'); + const url = `https://febbox.vercel.app/api/video-quality?fid=${epId}`; + const res = await axios.get(url, { signal }); + const data = res.data; + const $ = cheerio.load(data.html); + $('.file_quality').each((i, el) => { + const server = $(el).find('p.name').text() + + ' - ' + + $(el).find('p.size').text() + + ' - ' + + $(el).find('p.speed').text(); + const link = $(el).attr('data-url'); + if (link) { + stream.push({ + server: server, + type: 'mkv', + link: link, + }); + } + }); + return stream; + } + catch (err) { + return []; + } +}; +exports.sbGetStream = sbGetStream; diff --git a/dist/superVideoExtractor.js b/dist/superVideoExtractor.js new file mode 100644 index 0000000..27dc0e0 --- /dev/null +++ b/dist/superVideoExtractor.js @@ -0,0 +1,38 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.superVideoExtractor = superVideoExtractor; +async function superVideoExtractor(data) { + try { + // Step 1: Extract the function parameters and the encoded string + var functionRegex = /eval\(function\((.*?)\)\{.*?return p\}.*?\('(.*?)'\.split/; + var match = functionRegex.exec(data); + let p = ''; + if (match) { + // var params = match[1].split(',').map(param => param.trim()); + var encodedString = match[2]; + // console.log('Parameters:', params); + // console.log('Encoded String:', encodedString.split("',36,")[0], '🔥🔥'); + p = encodedString.split("',36,")?.[0].trim(); + let a = 36; + let c = encodedString.split("',36,")[1].slice(2).split('|').length; + let k = encodedString.split("',36,")[1].slice(2).split('|'); + while (c--) { + if (k[c]) { + var regex = new RegExp('\\b' + c.toString(a) + '\\b', 'g'); + p = p.replace(regex, k[c]); + } + } + // console.log('Decoded String:', p); + } + else { + console.log('No match found'); + } + const streamUrl = p?.match(/file:\s*"([^"]+\.m3u8[^"]*)"/)?.[1]; + console.log('streamUrl:', streamUrl); + return streamUrl || ''; + } + catch (err) { + console.error('SuperVideoExtractor Error:', err); + return ''; + } +} diff --git a/dist/tokyoInsider/catalog.js b/dist/tokyoInsider/catalog.js new file mode 100644 index 0000000..1ffc621 --- /dev/null +++ b/dist/tokyoInsider/catalog.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.tokyoGenresList = exports.tokyoCatalogList = void 0; +exports.tokyoCatalogList = [ + { + title: 'Top Anime', + filter: 'anime/search?r=5', + }, + { + title: 'Popular Anime', + filter: 'anime/', + }, +]; +exports.tokyoGenresList = []; diff --git a/dist/tokyoInsider/index.js b/dist/tokyoInsider/index.js new file mode 100644 index 0000000..f92386a --- /dev/null +++ b/dist/tokyoInsider/index.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.tokyoInsider = void 0; +const catalog_1 = require("./catalog"); +const tokyoGetInfo_1 = require("./tokyoGetInfo"); +const tokyoGetPosts_1 = require("./tokyoGetPosts"); +const tokyoGetStream_1 = require("./tokyoGetStream"); +exports.tokyoInsider = { + catalog: catalog_1.tokyoCatalogList, + genres: catalog_1.tokyoGenresList, + GetMetaData: tokyoGetInfo_1.tokyoGetInfo, + GetHomePosts: tokyoGetPosts_1.tokyoGetPosts, + GetStream: tokyoGetStream_1.tokyoGetStream, + GetSearchPosts: tokyoGetPosts_1.tokyoGetPostsSearch, + blurImage: true, +}; diff --git a/dist/tokyoInsider/tokyoGetInfo.js b/dist/tokyoInsider/tokyoGetInfo.js new file mode 100644 index 0000000..54b0da5 --- /dev/null +++ b/dist/tokyoInsider/tokyoGetInfo.js @@ -0,0 +1,60 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.tokyoGetInfo = void 0; +const tokyoGetInfo = async function ({ link, providerContext, }) { + try { + const { cheerio } = providerContext; + const url = link; + const res = await fetch(url); + const data = await res.text(); + const $ = cheerio.load(data); + const meta = { + title: $('.c_h2:contains("Title(s):")') + .text() + .replace('Title(s):', '') + .trim() + .split('\n')[0], + synopsis: $('.c_h2b:contains("Summary:"),.c_h2:contains("Summary:")') + .text() + .replace('Summary:', '') + .trim(), + image: $('.a_img').attr('src') || '', + imdbId: '', + type: 'series', + }; + const episodesList = []; + $('.episode').map((i, element) => { + const link = 'https://www.tokyoinsider.com' + $(element).find('a').attr('href') || + $('.download-link').attr('href'); + let title = $(element).find('a').find('em').text() + + ' ' + + $(element).find('a').find('strong').text(); + if (!title.trim()) { + title = $('.download-link').text(); + } + if (link && title.trim()) { + episodesList.push({ title, link }); + } + }); + return { + ...meta, + linkList: [ + { + title: meta.title, + directLinks: episodesList, + }, + ], + }; + } + catch (err) { + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'series', + linkList: [], + }; + } +}; +exports.tokyoGetInfo = tokyoGetInfo; diff --git a/dist/tokyoInsider/tokyoGetPosts.js b/dist/tokyoInsider/tokyoGetPosts.js new file mode 100644 index 0000000..632b8de --- /dev/null +++ b/dist/tokyoInsider/tokyoGetPosts.js @@ -0,0 +1,50 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.tokyoGetPostsSearch = exports.tokyoGetPosts = void 0; +const tokyoGetPosts = async function ({ filter, page, +// providerValue, +signal, providerContext, }) { + const { getBaseUrl, axios, cheerio } = providerContext; + const baseURL = await getBaseUrl('tokyoinsider'); + const start = page < 2 ? 0 : (page - 1) * 20; + const url = `${baseURL}/${filter}&start=${start}`; + return posts({ baseURL, url, signal, axios, cheerio }); +}; +exports.tokyoGetPosts = tokyoGetPosts; +const tokyoGetPostsSearch = async function ({ searchQuery, page, +// providerValue, +signal, providerContext, }) { + const { getBaseUrl, axios, cheerio } = providerContext; + const baseURL = await getBaseUrl('tokyoinsider'); + const start = page < 2 ? 0 : (page - 1) * 20; + const url = `${baseURL}/anime/search?k=${searchQuery}&start=${start}`; + return posts({ baseURL, url, signal, axios, cheerio }); +}; +exports.tokyoGetPostsSearch = tokyoGetPostsSearch; +async function posts({ baseURL, url, signal, axios, cheerio, }) { + try { + const res = await axios.get(url, { signal }); + const data = res.data; + const $ = cheerio.load(data); + const catalog = []; + $('td.c_h2[width="40"]').map((i, element) => { + const image = $(element) + .find('.a_img') + .attr('src') + ?.replace('small', 'default'); + const title = $(element).find('a').attr('title'); + const link = baseURL + $(element).find('a').attr('href'); + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + return []; + } +} diff --git a/dist/tokyoInsider/tokyoGetStream.js b/dist/tokyoInsider/tokyoGetStream.js new file mode 100644 index 0000000..dc295d8 --- /dev/null +++ b/dist/tokyoInsider/tokyoGetStream.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.tokyoGetStream = void 0; +const tokyoGetStream = async function ({ link, providerContext, }) { + try { + const { cheerio } = providerContext; + const url = link; + const res = await fetch(url); + const data = await res.text(); + const $ = cheerio.load(data); + const streamLinks = []; + $('.c_h1,.c_h2').map((i, element) => { + $(element).find('span').remove(); + const title = $(element).find('a').text() || ''; + const link = $(element).find('a').attr('href') || ''; + if (title && link.includes('media')) { + streamLinks.push({ + server: title, + link, + type: link.split('.').pop() || 'mkv', + }); + } + }); + return streamLinks; + } + catch (err) { + return []; + } +}; +exports.tokyoGetStream = tokyoGetStream; diff --git a/dist/topmovies/index.js b/dist/topmovies/index.js new file mode 100644 index 0000000..9348e8f --- /dev/null +++ b/dist/topmovies/index.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.topMovies = void 0; +const modGetInfo_1 = require("../mod/modGetInfo"); +const modGetEpisodesList_1 = require("../mod/modGetEpisodesList"); +const modGetStream_1 = require("../mod/modGetStream"); +const topGetPosts_1 = require("./topGetPosts"); +const topCatalog_1 = require("./topCatalog"); +exports.topMovies = { + catalog: topCatalog_1.topCatalogList, + genres: topCatalog_1.topGenresList, + GetMetaData: modGetInfo_1.modGetInfo, + GetHomePosts: topGetPosts_1.topGetPosts, + GetStream: modGetStream_1.modGetStream, + GetEpisodeLinks: modGetEpisodesList_1.modGetEpisodeLinks, + nonStreamableServer: [], + GetSearchPosts: topGetPosts_1.topGetPostsSearch, +}; diff --git a/dist/topmovies/topCatalog.js b/dist/topmovies/topCatalog.js new file mode 100644 index 0000000..508c321 --- /dev/null +++ b/dist/topmovies/topCatalog.js @@ -0,0 +1,87 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.topGenresList = exports.topCatalogList = void 0; +exports.topCatalogList = [ + { + title: 'Latest', + filter: '', + }, + { + title: 'Netflix', + filter: '/web-series/tv-shows-by-network/netflix', + }, + { + title: 'Hotstar', + filter: '/web-series/tv-shows-by-network/hotstar', + }, + { + title: 'Amazon Prime', + filter: '/web-series/tv-shows-by-network/amazon-prime-video', + }, +]; +exports.topGenresList = [ + { + title: 'Apple TV+', + filter: '/ott/apple-tv', + }, + { + title: 'Disney+', + filter: '/ott/disney-plus', + }, + { + title: 'Hulu', + filter: '/ott/hulu', + }, + { + title: 'Crunchyroll', + filter: '/ott/crunchyroll', + }, + { + title: 'Action', + filter: '/movies-by-genre/action/', + }, + { + title: 'Adventure', + filter: '/movies-by-genre/adventure/', + }, + { + title: 'Animation', + filter: '/movies-by-genre/animated/', + }, + { + title: 'Comedy', + filter: '/movies-by-genre/comedy/', + }, + { + title: 'Crime', + filter: '/movies-by-genre/crime/', + }, + { + title: 'Documentary', + filter: '/movies-by-genre/documentary/', + }, + { + title: 'Fantasy', + filter: '/movies-by-genre/fantasy/', + }, + { + title: 'Horror', + filter: '/movies-by-genre/horror/', + }, + { + title: 'Mystery', + filter: '/movies-by-genre/mystery/', + }, + { + title: 'Romance', + filter: '/movies-by-genre/romance/', + }, + { + title: 'Thriller', + filter: '/movies-by-genre/thriller/', + }, + { + title: 'Sci-Fi', + filter: '/movies-by-genre/sci-fi/', + }, +]; diff --git a/dist/topmovies/topGetPosts.js b/dist/topmovies/topGetPosts.js new file mode 100644 index 0000000..b36dff6 --- /dev/null +++ b/dist/topmovies/topGetPosts.js @@ -0,0 +1,64 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.topGetPostsSearch = exports.topGetPosts = void 0; +const headers = { + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + Cookie: 'popads_user_id=6ba8fe60a481387a3249f05aa058822d', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', +}; +const topGetPosts = async function ({ filter, page, signal, providerContext, }) { + const { getBaseUrl } = providerContext; + const baseUrl = await getBaseUrl('Topmovies'); + const url = `${baseUrl + filter}/page/${page}/`; + return posts(url, signal, providerContext); +}; +exports.topGetPosts = topGetPosts; +const topGetPostsSearch = async function ({ searchQuery, page, signal, providerContext, }) { + const { getBaseUrl } = providerContext; + const baseUrl = await getBaseUrl('Topmovies'); + const url = `${baseUrl}/search/${searchQuery}/page/${page}/`; + return posts(url, signal, providerContext); +}; +exports.topGetPostsSearch = topGetPostsSearch; +async function posts(url, signal, providerContext) { + try { + const { axios, cheerio } = providerContext; + const res = await axios.get(url, { headers, signal }); + const data = res.data; + const $ = cheerio.load(data); + const catalog = []; + $('.post-cards') + .find('article') + .map((i, element) => { + const title = $(element).find('a').attr('title'); + const link = $(element).find('a').attr('href'); + const image = $(element).find('img').attr('data-src') || + $(element).find('img').attr('src') || + ''; + if (title && link) { + catalog.push({ + title: title.replace('Download', '').trim(), + link: link, + image: image, + }); + } + }); + // console.log(catalog); + return catalog; + } + catch (err) { + console.error('mod error ', err); + return []; + } +} diff --git a/dist/types.js b/dist/types.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/dist/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/uhd/getUhdInfo.js b/dist/uhd/getUhdInfo.js new file mode 100644 index 0000000..cbbfcdc --- /dev/null +++ b/dist/uhd/getUhdInfo.js @@ -0,0 +1,107 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getUhdInfo = getUhdInfo; +const headers = { + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', +}; +async function getUhdInfo({ link, providerContext, }) { + try { + const { axios, cheerio } = providerContext; + const url = link; + const res = await axios.get(url, { headers }); + const html = await res.data; + const $ = cheerio.load(html); + const title = $('h2:first').text() || ''; + const image = $('h2').siblings().find('img').attr('src') || ''; + // const trailer = $('iframe').attr('src') || ''; + // console.log({ title, image, trailer }); + // Links + const episodes = []; + // new structure + $('.mks_separator').each((index, element) => { + $(element) + .nextUntil('.mks_separator') + .each((index, element) => { + const title = $(element).text(); + const episodesList = []; + $(element) + .next('p') + .find('a') + .each((index, element) => { + const title = $(element).text(); + const link = $(element).attr('href'); + if (title && link && !title.toLocaleLowerCase().includes('zip')) { + episodesList.push({ title, link }); + // console.log({ title, link }); + } + }); + if (title && episodesList.length > 0) { + episodes.push({ + title, + directLinks: episodesList, + }); + } + }); + }); + // old structure + $('hr').each((index, element) => { + $(element) + .nextUntil('hr') + .each((index, element) => { + const title = $(element).text(); + const episodesList = []; + $(element) + .next('p') + .find('a') + .each((index, element) => { + const title = $(element).text(); + const link = $(element).attr('href'); + if (title && link && !title.toLocaleLowerCase().includes('zip')) { + episodesList.push({ title, link }); + // console.log({ title, link }); + } + }); + if (title && episodesList.length > 0) { + episodes.push({ + title, + directLinks: episodesList, + }); + } + }); + }); + // console.log(episodes); + return { + title: title.match(/^Download\s+([^(\[]+)/i) + ? title?.match(/^Download\s+([^(\[]+)/i)?.[1] || '' + : title.replace('Download', '') || '', + image, + imdbId: '', + synopsis: title, + type: '', + linkList: episodes, + }; + } + catch (error) { + console.error(error); + return { + title: '', + image: '', + imdbId: '', + synopsis: '', + linkList: [], + type: 'uhd', + }; + } +} diff --git a/dist/uhd/index.js b/dist/uhd/index.js new file mode 100644 index 0000000..9a8c06c --- /dev/null +++ b/dist/uhd/index.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.uhdMovies = void 0; +const uhCtatalog_1 = require("./uhCtatalog"); +const uhdGetPosts_1 = require("./uhdGetPosts"); +const uhdGetStream_1 = require("./uhdGetStream"); +const getUhdInfo_1 = require("./getUhdInfo"); +exports.uhdMovies = { + catalog: uhCtatalog_1.uhdCatalogList, + genres: uhCtatalog_1.uhdGenresList, + GetMetaData: getUhdInfo_1.getUhdInfo, + GetHomePosts: uhdGetPosts_1.uhdGetPosts, + GetStream: uhdGetStream_1.uhdGetStream, + nonStreamableServer: ['Gdrive-Instant'], + GetSearchPosts: uhdGetPosts_1.uhdGetPostsSearch, +}; diff --git a/dist/uhd/uhCtatalog.js b/dist/uhd/uhCtatalog.js new file mode 100644 index 0000000..36ef7ed --- /dev/null +++ b/dist/uhd/uhCtatalog.js @@ -0,0 +1,39 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.uhdGenresList = exports.uhdCatalogList = void 0; +exports.uhdCatalogList = [ + { + title: 'Latest', + filter: '', + }, + { + title: 'Web Series', + filter: '/web-series', + }, + { + title: 'Movies', + filter: '/movies', + }, + { + title: '4K HDR', + filter: '/4k-hdr', + }, +]; +exports.uhdGenresList = [ + { + title: '4K HEVC', + filter: '/2160p-hevc', + }, + { + title: 'HD 10bit', + filter: '/1080p-10bit', + }, + { + title: 'English Movies', + filter: '/movies/english-movies', + }, + { + title: 'Dual Audio', + filter: '/movies/dual-audio-movies', + }, +]; diff --git a/dist/uhd/uhdGetPosts.js b/dist/uhd/uhdGetPosts.js new file mode 100644 index 0000000..63e65e9 --- /dev/null +++ b/dist/uhd/uhdGetPosts.js @@ -0,0 +1,65 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.uhdGetPostsSearch = exports.uhdGetPosts = void 0; +const headers = { + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', +}; +const uhdGetPosts = async ({ filter, page, +// providerValue, +signal, providerContext, }) => { + const { getBaseUrl } = providerContext; + const baseUrl = await getBaseUrl('UhdMovies'); + const url = page === 1 ? `${baseUrl}/${filter}/` : `${baseUrl + filter}/page/${page}/`; + console.log('url', url); + return posts(baseUrl, url, signal, providerContext); +}; +exports.uhdGetPosts = uhdGetPosts; +const uhdGetPostsSearch = async ({ searchQuery, page, +// providerValue, +signal, providerContext, }) => { + const { getBaseUrl } = providerContext; + const baseUrl = await getBaseUrl('UhdMovies'); + const url = `${baseUrl}/search/${searchQuery}/page/${page}/`; + return posts(baseUrl, url, signal, providerContext); +}; +exports.uhdGetPostsSearch = uhdGetPostsSearch; +async function posts(baseURL, url, signal, providerContext) { + try { + const { axios, cheerio } = providerContext; + const res = await axios.get(url, { headers, signal }); + const html = res.data; + const $ = cheerio.load(html); + const uhdCatalog = []; + $('.gridlove-posts') + .find('.layout-masonry') + .each((index, element) => { + const title = $(element).find('a').attr('title'); + const link = $(element).find('a').attr('href'); + const image = $(element).find('a').find('img').attr('src'); + if (title && link && image) { + uhdCatalog.push({ + title: title.replace('Download', '').trim(), + link: link, + image: image, + }); + } + }); + return uhdCatalog; + } + catch (err) { + console.error('uhd error ', err); + return []; + } +} diff --git a/dist/uhd/uhdGetStream.js b/dist/uhd/uhdGetStream.js new file mode 100644 index 0000000..f1947dc --- /dev/null +++ b/dist/uhd/uhdGetStream.js @@ -0,0 +1,192 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.uhdGetStream = void 0; +const headers = { + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', +}; +const uhdGetStream = async ({ link: url, providerContext, }) => { + try { + const { axios, cheerio } = providerContext; + let downloadLink = await modExtractor(url, providerContext); + // console.log(downloadLink.data); + const ddl = downloadLink?.data?.match(/content="0;url=(.*?)"/)?.[1] || url; + console.log('ddl', ddl); + // console.log(ddl); + const driveLink = await isDriveLink(ddl); + const ServerLinks = []; + const driveRes = await axios.get(driveLink, { headers }); + const driveHtml = driveRes.data; + const $drive = cheerio.load(driveHtml); + //instant link + try { + const seed = $drive('.btn-danger').attr('href') || ''; + const instantToken = seed.split('=')[1]; + // console.log('InstantToken', instantToken); + const InstantFromData = new FormData(); + InstantFromData.append('keys', instantToken); + const videoSeedUrl = seed.split('/').slice(0, 3).join('/') + '/api'; + // console.log('videoSeedUrl', videoSeedUrl); + const instantLinkRes = await fetch(videoSeedUrl, { + method: 'POST', + body: InstantFromData, + headers: { + 'x-token': videoSeedUrl, + }, + }); + const instantLinkData = await instantLinkRes.json(); + // console.log('instantLinkData', instantLinkData); + if (instantLinkData.error === false) { + const instantLink = instantLinkData.url; + ServerLinks.push({ + server: 'Gdrive-Instant', + link: instantLink, + type: 'mkv', + }); + } + else { + console.log('Instant link not found', instantLinkData); + } + } + catch (err) { + console.log('Instant link not found', err); + } + // resume link + try { + const resumeDrive = driveLink.replace('/file', '/zfile'); + // console.log('resumeDrive', resumeDrive); + const resumeDriveRes = await axios.get(resumeDrive, { headers }); + const resumeDriveHtml = resumeDriveRes.data; + const $resumeDrive = cheerio.load(resumeDriveHtml); + const resumeLink = $resumeDrive('.btn-success').attr('href'); + // console.log('resumeLink', resumeLink); + if (resumeLink) { + ServerLinks.push({ + server: 'ResumeCloud', + link: resumeLink, + type: 'mkv', + }); + } + } + catch (err) { + console.log('Resume link not found'); + } + // CF workers type 1 + try { + const cfWorkersLink = driveLink.replace('/file', '/wfile') + '?type=1'; + const cfWorkersRes = await axios.get(cfWorkersLink, { headers }); + const cfWorkersHtml = cfWorkersRes.data; + const $cfWorkers = cheerio.load(cfWorkersHtml); + const cfWorkersStream = $cfWorkers('.btn-success'); + cfWorkersStream.each((i, el) => { + const link = el.attribs.href; + if (link) { + ServerLinks.push({ + server: 'Cf Worker 1.' + i, + link: link, + type: 'mkv', + }); + } + }); + } + catch (err) { + console.log('CF workers link not found', err); + } + // CF workers type 2 + try { + const cfWorkersLink = driveLink.replace('/file', '/wfile') + '?type=2'; + const cfWorkersRes = await axios.get(cfWorkersLink, { headers }); + const cfWorkersHtml = cfWorkersRes.data; + const $cfWorkers = cheerio.load(cfWorkersHtml); + const cfWorkersStream = $cfWorkers('.btn-success'); + cfWorkersStream.each((i, el) => { + const link = el.attribs.href; + if (link) { + ServerLinks.push({ + server: 'Cf Worker 2.' + i, + link: link, + type: 'mkv', + }); + } + }); + } + catch (err) { + console.log('CF workers link not found', err); + } + console.log('ServerLinks', ServerLinks); + return ServerLinks; + } + catch (err) { + console.log('getStream error', err); + return []; + } +}; +exports.uhdGetStream = uhdGetStream; +const isDriveLink = async (ddl) => { + if (ddl.includes('drive')) { + const driveLeach = await fetch(ddl); + const driveLeachData = await driveLeach.text(); + const pathMatch = driveLeachData.match(/window\.location\.replace\("([^"]+)"\)/); + const path = pathMatch?.[1]; + const mainUrl = ddl.split('/')[2]; + console.log(`driveUrl = https://${mainUrl}${path}`); + return `https://${mainUrl}${path}`; + } + else { + return ddl; + } +}; +async function modExtractor(url, providerContext) { + const { axios, cheerio } = providerContext; + try { + const wpHttp = url.split('sid=')[1]; + var bodyFormData0 = new FormData(); + bodyFormData0.append('_wp_http', wpHttp); + const res = await fetch(url.split('?')[0], { + method: 'POST', + body: bodyFormData0, + }); + const data = await res.text(); + // console.log('', data); + const html = data; + const $ = cheerio.load(html); + // find input with name="_wp_http2" + const wpHttp2 = $('input').attr('name', '_wp_http2').val(); + // console.log('wpHttp2', wpHttp2); + // form data + var bodyFormData = new FormData(); + bodyFormData.append('_wp_http2', wpHttp2); + const formUrl1 = $('form').attr('action'); + const formUrl = formUrl1 || url.split('?')[0]; + const res2 = await fetch(formUrl, { + method: 'POST', + body: bodyFormData, + }); + const html2 = await res2.text(); + const link = html2.match(/setAttribute\("href",\s*"(.*?)"/)[1]; + console.log(link); + const cookie = link.split('=')[1]; + console.log('cookie', cookie); + const downloadLink = await axios.get(link, { + headers: { + Referer: formUrl, + Cookie: `${cookie}=${wpHttp2}`, + }, + }); + return downloadLink; + } + catch (err) { + console.log('modGetStream error', err); + } +} diff --git a/dist/vadapav/VagapavCatalog.js b/dist/vadapav/VagapavCatalog.js new file mode 100644 index 0000000..37cea9c --- /dev/null +++ b/dist/vadapav/VagapavCatalog.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.vadapavGenresList = exports.vadapavCatalogList = void 0; +exports.vadapavCatalogList = [ + { + title: 'Movies', + filter: '/608c853f-704e-48f0-b785-4ae1f48ea70d', + }, + { + title: 'Tv Shows', + filter: '/72983eef-a12f-4be4-99a7-e8f6afa568c1', + }, + { + title: 'Anime', + filter: '/36abf81c-1032-4fbf-9a55-347a05ce2ca3', + }, +]; +exports.vadapavGenresList = []; diff --git a/dist/vadapav/index.js b/dist/vadapav/index.js new file mode 100644 index 0000000..f56f33f --- /dev/null +++ b/dist/vadapav/index.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.vadapavProvider = void 0; +const vadapavGetPosts_1 = require("./vadapavGetPosts"); +const VagapavCatalog_1 = require("./VagapavCatalog"); +const vadapavGetInfo_1 = require("./vadapavGetInfo"); +const vadapavGetStream_1 = require("./vadapavGetStream"); +const vadapavGetEpisodes_1 = require("./vadapavGetEpisodes"); +exports.vadapavProvider = { + catalog: VagapavCatalog_1.vadapavCatalogList, + genres: VagapavCatalog_1.vadapavGenresList, + GetHomePosts: vadapavGetPosts_1.vadapavGetPosts, + GetEpisodeLinks: vadapavGetEpisodes_1.vadapavGetEpisodeLinks, + GetMetaData: vadapavGetInfo_1.vadapavGetInfo, + GetStream: vadapavGetStream_1.vadapavGetStream, + GetSearchPosts: vadapavGetPosts_1.vadapavGetPostsSearch, +}; diff --git a/dist/vadapav/vadapavGetEpisodes.js b/dist/vadapav/vadapavGetEpisodes.js new file mode 100644 index 0000000..4933187 --- /dev/null +++ b/dist/vadapav/vadapavGetEpisodes.js @@ -0,0 +1,30 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.vadapavGetEpisodeLinks = void 0; +const vadapavGetEpisodeLinks = async function ({ url, providerContext, }) { + const { axios, cheerio } = providerContext; + try { + const baseUrl = url?.split('/').slice(0, 3).join('/'); + const res = await axios.get(url); + const html = res.data; + let $ = cheerio.load(html); + const episodeLinks = []; + $('.file-entry:not(:contains("Parent Directory"))').map((i, element) => { + const link = $(element).attr('href'); + if (link && + ($(element).text()?.includes('.mp4') || + $(element).text()?.includes('.mkv'))) { + episodeLinks.push({ + title: $(element).text()?.match(/E\d+/)?.[0]?.replace('E', 'Episode ') || + i + 1 + '. ' + $(element).text()?.replace('.mkv', ''), + link: baseUrl + link, + }); + } + }); + return episodeLinks; + } + catch (err) { + return []; + } +}; +exports.vadapavGetEpisodeLinks = vadapavGetEpisodeLinks; diff --git a/dist/vadapav/vadapavGetInfo.js b/dist/vadapav/vadapavGetInfo.js new file mode 100644 index 0000000..0a0bb34 --- /dev/null +++ b/dist/vadapav/vadapavGetInfo.js @@ -0,0 +1,68 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.vadapavGetInfo = void 0; +const vadapavGetInfo = async function ({ link, providerContext, }) { + try { + const { axios, cheerio } = providerContext; + const baseUrl = link?.split('/').slice(0, 3).join('/'); + const url = link; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const title = $('.directory') + .children() + .first() + .text() + .trim() + ?.split('/') + .pop() + ?.trim() || ''; + const links = []; + $('.directory-entry:not(:contains("Parent Directory"))').map((i, element) => { + const link = $(element).attr('href'); + if (link) { + links.push({ + episodesLink: baseUrl + link, + title: $(element).text(), + }); + } + }); + const directLinks = []; + $('.file-entry:not(:contains("Parent Directory"))').map((i, element) => { + const link = $(element).attr('href'); + if (link && + ($(element).text()?.includes('.mp4') || + $(element).text()?.includes('.mkv'))) { + directLinks.push({ + title: i + 1 + '. ' + $(element).text(), + link: baseUrl + link, + }); + } + }); + if (directLinks.length > 0) { + links.push({ + title: title + ' DL', + directLinks: directLinks, + }); + } + return { + title: title, + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: links, + }; + } + catch (err) { + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.vadapavGetInfo = vadapavGetInfo; diff --git a/dist/vadapav/vadapavGetPosts.js b/dist/vadapav/vadapavGetPosts.js new file mode 100644 index 0000000..7a1a6bf --- /dev/null +++ b/dist/vadapav/vadapavGetPosts.js @@ -0,0 +1,56 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.vadapavGetPostsSearch = exports.vadapavGetPosts = void 0; +const vadapavGetPosts = async function ({ filter, page, +// providerValue, +signal, providerContext, }) { + const { getBaseUrl, axios, cheerio } = providerContext; + const baseUrl = await getBaseUrl('vadapav'); + if (page > 1) { + return []; + } + const url = `${baseUrl + filter}`; + return posts({ baseUrl, url, signal, axios, cheerio }); +}; +exports.vadapavGetPosts = vadapavGetPosts; +const vadapavGetPostsSearch = async function ({ searchQuery, page, +// providerValue, +signal, providerContext, }) { + const { getBaseUrl, axios, cheerio } = providerContext; + const baseUrl = await getBaseUrl('vadapav'); + if (page > 1) { + return []; + } + const url = `${baseUrl}/s/${searchQuery}`; + return posts({ baseUrl, url, signal, axios, cheerio }); +}; +exports.vadapavGetPostsSearch = vadapavGetPostsSearch; +async function posts({ +// baseUrl, +url, signal, axios, cheerio, }) { + try { + const res = await axios.get(url, { signal }); + const data = res.data; + const $ = cheerio.load(data); + const catalog = []; + $('.directory-entry:not(:contains("Parent Directory"))').map((i, element) => { + const title = $(element).text(); + const link = $(element).attr('href'); + const imageTitle = title?.length > 30 + ? title?.slice(0, 30)?.replaceAll('.', ' ') + : title?.replaceAll('.', ' '); + const image = `https://placehold.jp/23/000000/ffffff/200x400.png?text=${encodeURIComponent(imageTitle)}&css=%7B%22background%22%3A%22%20-webkit-gradient(linear%2C%20left%20bottom%2C%20left%20top%2C%20from(%233f3b3b)%2C%20to(%23000000))%22%2C%22text-transform%22%3A%22%20capitalize%22%7D`; + if (title && link) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + return []; + } +} diff --git a/dist/vadapav/vadapavGetStream.js b/dist/vadapav/vadapavGetStream.js new file mode 100644 index 0000000..4db9478 --- /dev/null +++ b/dist/vadapav/vadapavGetStream.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.vadapavGetStream = void 0; +const vadapavGetStream = async function ({ link: url, // type, + } // providerContext, +) { + try { + const stream = []; + stream.push({ + server: 'vadapav', + link: url, + type: url?.split('.').pop() || 'mkv', + }); + return stream; + } + catch (err) { + return []; + } +}; +exports.vadapavGetStream = vadapavGetStream; diff --git a/dist/vega/catalog.js b/dist/vega/catalog.js new file mode 100644 index 0000000..3d4dddb --- /dev/null +++ b/dist/vega/catalog.js @@ -0,0 +1,103 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.genresList = exports.homeList = void 0; +exports.homeList = [ + { + title: 'New', + filter: '', + }, + { + title: 'Netflix', + filter: 'web-series/netflix', + }, + { + title: 'Amazon Prime', + filter: 'web-series/amazon-prime-video', + }, + { + title: '4K Movies', + filter: 'movies-by-quality/2160p', + }, +]; +exports.genresList = [ + { + title: 'Action', + filter: 'category/movies-by-genres/action', + }, + { + title: 'Adventure', + filter: 'category/movies-by-genres/adventure', + }, + { + title: 'Animation', + filter: 'category/movies-by-genres/animation', + }, + { + title: 'Biography', + filter: 'category/movies-by-genres/biography', + }, + { + title: 'Comedy', + filter: 'category/movies-by-genres/comedy', + }, + { + title: 'Crime', + filter: 'category/movies-by-genres/crime', + }, + { + title: 'Documentary', + filter: 'category/movies-by-genres/documentary', + }, + { + title: 'Drama', + filter: 'category/movies-by-genres/drama', + }, + { + title: 'Family', + filter: 'category/movies-by-genres/family', + }, + { + title: 'Fantasy', + filter: 'category/movies-by-genres/fantasy', + }, + { + title: 'History', + filter: 'category/movies-by-genres/history', + }, + { + title: 'Horror', + filter: 'category/movies-by-genres/horror', + }, + { + title: 'Music', + filter: 'category/movies-by-genres/music', + }, + { + title: 'Mystery', + filter: 'category/movies-by-genres/mystery', + }, + { + title: 'Romance', + filter: 'category/movies-by-genres/romance', + }, + { + title: 'Sci-Fi', + filter: 'category/movies-by-genres/sci-fi', + }, + { + title: 'Sport', + filter: 'category/movies-by-genres/sport', + }, + { + title: 'Thriller', + filter: 'category/movies-by-genres/thriller', + }, + { + title: 'War', + filter: 'category/movies-by-genres/war', + }, + { + title: 'Western', + filter: 'category/movies-by-genres/western', + }, +]; diff --git a/dist/vega/getEpisodesLink.js b/dist/vega/getEpisodesLink.js new file mode 100644 index 0000000..97a9924 --- /dev/null +++ b/dist/vega/getEpisodesLink.js @@ -0,0 +1,34 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.vegaGetEpisodeLinks = void 0; +const vegaGetEpisodeLinks = async function ({ url, providerContext, }) { + const { axios, cheerio, commonHeaders: headers } = providerContext; + console.log('getEpisodeLinks', url); + try { + const res = await axios.get(url, { headers }); + const $ = cheerio.load(res.data); + const container = $('.entry-content,.entry-inner'); + $('.unili-content,.code-block-1').remove(); + const episodes = []; + container.find('h4').each((index, element) => { + const el = $(element); + const title = el.text().replaceAll('-', '').replaceAll(':', ''); + const link = el + .next('p') + .find('.btn-outline[style="background:linear-gradient(135deg,#ed0b0b,#f2d152); color: white;"]') + .parent() + .attr('href'); + if (title && link) { + episodes.push({ title, link }); + } + }); + // console.log(episodes); + return episodes; + } + catch (err) { + console.log('getEpisodeLinks error: '); + // console.error(err); + return []; + } +}; +exports.vegaGetEpisodeLinks = vegaGetEpisodeLinks; diff --git a/dist/vega/getInfo.js b/dist/vega/getInfo.js new file mode 100644 index 0000000..05085e1 --- /dev/null +++ b/dist/vega/getInfo.js @@ -0,0 +1,135 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.vegaGetInfo = void 0; +const headers = { + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + Cookie: '_lscache_vary=62abf8b96599676eb8ec211cffaeb8ff; ext_name=ojplmecpdpgccookcobabopnaifgidhf; cf_clearance=n4Y1XTKZ5TfIMBNQuAXzerwKpx0U35KoOm3imfT0GpU-1732097818-1.2.1.1-ZeAnEu.8D9TSZHYDoj7vwo1A1rpdKl304ZpaBn_QbAQOr211JFAb7.JRQU3EL2eIy1Dfl8HhYvH7_259.22lUz8gbchHcQ8hvfuQXMtFMCbqDBLzjNUZa9stuk.39l28IcPhH9Z2szsf3SGtNI1sAfo66Djt7sOReLK3lHw9UkJp7BdGqt6a2X9qAc8EsAI3lE480Tmt0fkHv14Oc30LSbPB_WwFmiqAki2W.Gv9hV7TN_QBFESleTDlXd.6KGflfd4.KwWF7rpSRo_cgoc9ALLLIafpxHVbe7_g5r7zvpml_Pj8fEL75fw.1GBuy16bciHBuB8s_kahuJYUnhtQFFgfTQl8_Gn6KeovBWx.PJ7nFv5sklHUfAyBVq3t30xKe8ZDydsQ_G.yipfj_In5GmmWcXGb6E4.bioDOwW_sKLtxwdTQt7Nu.RkILX_mKvXNpyLqflIVj8G7X5E8I.unw', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0', +}; +const vegaGetInfo = async ({ link, providerContext, }) => { + try { + const { axios, cheerio } = providerContext; + const url = link; + console.log('url', url); + const baseUrl = url.split('/').slice(0, 3).join('/'); + const response = await axios.get(url, { + headers: { + ...headers, + Referer: baseUrl, + }, + }); + const $ = cheerio.load(response.data); + const infoContainer = $('.entry-content,.post-inner'); + const heading = infoContainer?.find('h3'); + const imdbId = heading?.next('p')?.find('a')?.[0]?.attribs?.href?.match(/tt\d+/g)?.[0] || + infoContainer.text().match(/tt\d+/g)?.[0] || + ''; + // console.log(imdbId) + const type = heading?.next('p')?.text()?.includes('Series Name') + ? 'series' + : 'movie'; + // console.log(type); + // title + const titleRegex = /Name: (.+)/; + const title = heading?.next('p')?.text()?.match(titleRegex)?.[1] || ''; + // console.log(title); + // synopsis + const synopsisNode = infoContainer?.find('p')?.next('h3,h4')?.next('p')?.[0] + ?.children?.[0]; + const synopsis = synopsisNode && 'data' in synopsisNode ? synopsisNode.data : ''; + // console.log(synopsis); + // image + let image = infoContainer?.find('img[data-lazy-src]')?.attr('data-lazy-src') || ''; + if (image.startsWith('//')) { + image = 'https:' + image; + } + // console.log(image); + // console.log({title, synopsis, image, imdbId, type}); + /// Links + const hr = infoContainer?.first()?.find('hr'); + const list = hr?.nextUntil('hr'); + const links = []; + list.each((index, element) => { + element = $(element); + // title + const title = element?.text() || ''; + const quality = element?.text().match(/\d+p\b/)?.[0] || ''; + // console.log(title); + // movieLinks + const movieLinks = element + ?.next() + .find('.dwd-button') + .text() + .toLowerCase() + .includes('download') + ? element?.next().find('.dwd-button')?.parent()?.attr('href') + : ''; + // episode links + const vcloudLinks = element + ?.next() + .find(".btn-outline[style='background:linear-gradient(135deg,#ed0b0b,#f2d152); color: white;'],.btn-outline[style='background:linear-gradient(135deg,#ed0b0b,#f2d152); color: #fdf8f2;']") + ?.parent() + ?.attr('href'); + console.log(title); + const episodesLink = (vcloudLinks + ? vcloudLinks + : element + ?.next() + .find('.dwd-button') + .text() + .toLowerCase() + .includes('episode') + ? element?.next().find('.dwd-button')?.parent()?.attr('href') + : '') || + element + ?.next() + .find(".btn-outline[style='background:linear-gradient(135deg,#0ebac3,#09d261); color: white;']") + ?.parent() + ?.attr('href'); + if (movieLinks || episodesLink) { + links.push({ + title, + directLinks: movieLinks + ? [{ title: 'Movie', link: movieLinks, type: 'movie' }] + : [], + episodesLink, + quality, + }); + } + }); + // console.log(links); + return { + title, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } + catch (error) { + console.log('getInfo error'); + console.error(error); + // ToastAndroid.show('No response', ToastAndroid.SHORT); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: '', + linkList: [], + }; + } +}; +exports.vegaGetInfo = vegaGetInfo; diff --git a/dist/vega/getPosts.js b/dist/vega/getPosts.js new file mode 100644 index 0000000..5f08c54 --- /dev/null +++ b/dist/vega/getPosts.js @@ -0,0 +1,79 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.vegaGetPostsSearch = exports.vegaGetPosts = void 0; +const headers = { + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + Cookie: '_lscache_vary=62abf8b96599676eb8ec211cffaeb8ff; ext_name=ojplmecpdpgccookcobabopnaifgidhf; cf_clearance=n4Y1XTKZ5TfIMBNQuAXzerwKpx0U35KoOm3imfT0GpU-1732097818-1.2.1.1-ZeAnEu.8D9TSZHYDoj7vwo1A1rpdKl304ZpaBn_QbAQOr211JFAb7.JRQU3EL2eIy1Dfl8HhYvH7_259.22lUz8gbchHcQ8hvfuQXMtFMCbqDBLzjNUZa9stuk.39l28IcPhH9Z2szsf3SGtNI1sAfo66Djt7sOReLK3lHw9UkJp7BdGqt6a2X9qAc8EsAI3lE480Tmt0fkHv14Oc30LSbPB_WwFmiqAki2W.Gv9hV7TN_QBFESleTDlXd.6KGflfd4.KwWF7rpSRo_cgoc9ALLLIafpxHVbe7_g5r7zvpml_Pj8fEL75fw.1GBuy16bciHBuB8s_kahuJYUnhtQFFgfTQl8_Gn6KeovBWx.PJ7nFv5sklHUfAyBVq3t30xKe8ZDydsQ_G.yipfj_In5GmmWcXGb6E4.bioDOwW_sKLtxwdTQt7Nu.RkILX_mKvXNpyLqflIVj8G7X5E8I.unw', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0', +}; +const vegaGetPosts = async ({ filter, page, providerValue, signal, providerContext, }) => { + const { getBaseUrl, axios, cheerio } = providerContext; + const baseUrl = await getBaseUrl('Vega'); + console.log('vegaGetPosts baseUrl:', providerValue, baseUrl); + const url = `${baseUrl}/${filter}/page/${page}/`; + console.log('vegaGetPosts url:', url); + return posts(baseUrl, url, signal, headers, axios, cheerio); +}; +exports.vegaGetPosts = vegaGetPosts; +const vegaGetPostsSearch = async ({ searchQuery, page, providerValue, signal, providerContext, }) => { + const { getBaseUrl, axios, commonHeaders, cheerio } = providerContext; + const baseUrl = await getBaseUrl('Vega'); + console.log('vegaGetPosts baseUrl:', providerValue, baseUrl); + const url = `${baseUrl}/page/${page}/?s=${searchQuery}`; + console.log('vegaGetPosts url:', url); + return posts(baseUrl, url, signal, commonHeaders, axios, cheerio); +}; +exports.vegaGetPostsSearch = vegaGetPostsSearch; +async function posts(baseUrl, url, signal, headers = {}, axios, cheerio) { + try { + const urlRes = await axios.get(url, { + headers: { + ...headers, + Referer: baseUrl, + }, + signal, + }); + const $ = cheerio.load(urlRes.data); + const posts = []; + $('.blog-items,.post-list') + ?.children('article') + ?.each((index, element) => { + const post = { + title: ($(element) + ?.find('a') + ?.attr('title') + ?.replace('Download', '') + ?.match(/^(.*?)\s*\((\d{4})\)|^(.*?)\s*\((Season \d+)\)/)?.[0] || + $(element)?.find('a')?.attr('title')?.replace('Download', '') || + $(element)?.find('.post-title').text()?.replace('Download', '') || + '').trim(), + link: $(element)?.find('a')?.attr('href') || '', + image: $(element).find('a').find('img').attr('data-lazy-src') || + $(element).find('a').find('img').attr('data-src') || + $(element).find('a').find('img').attr('src') || + '', + }; + if (post.image.startsWith('//')) { + post.image = 'https:' + post.image; + } + posts.push(post); + }); + // console.log(posts); + return posts; + } + catch (error) { + console.error('vegaGetPosts error:', error); + return []; + } +} diff --git a/dist/vega/getStream.js b/dist/vega/getStream.js new file mode 100644 index 0000000..e07b1aa --- /dev/null +++ b/dist/vega/getStream.js @@ -0,0 +1,94 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.vegaGetStream = vegaGetStream; +const headers = { + Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + Cookie: '_lscache_vary=62abf8b96599676eb8ec211cffaeb8ff; ext_name=ojplmecpdpgccookcobabopnaifgidhf; cf_clearance=n4Y1XTKZ5TfIMBNQuAXzerwKpx0U35KoOm3imfT0GpU-1732097818-1.2.1.1-ZeAnEu.8D9TSZHYDoj7vwo1A1rpdKl304ZpaBn_QbAQOr211JFAb7.JRQU3EL2eIy1Dfl8HhYvH7_259.22lUz8gbchHcQ8hvfuQXMtFMCbqDBLzjNUZa9stuk.39l28IcPhH9Z2szsf3SGtNI1sAfo66Djt7sOReLK3lHw9UkJp7BdGqt6a2X9qAc8EsAI3lE480Tmt0fkHv14Oc30LSbPB_WwFmiqAki2W.Gv9hV7TN_QBFESleTDlXd.6KGflfd4.KwWF7rpSRo_cgoc9ALLLIafpxHVbe7_g5r7zvpml_Pj8fEL75fw.1GBuy16bciHBuB8s_kahuJYUnhtQFFgfTQl8_Gn6KeovBWx.PJ7nFv5sklHUfAyBVq3t30xKe8ZDydsQ_G.yipfj_In5GmmWcXGb6E4.bioDOwW_sKLtxwdTQt7Nu.RkILX_mKvXNpyLqflIVj8G7X5E8I.unw', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0', +}; +async function vegaGetStream({ link, type, signal, providerContext, }) { + const { axios, cheerio, extractors } = providerContext; + const { hubcloudExtracter } = extractors; + try { + const streamLinks = []; + console.log('dotlink', link); + if (type === 'movie') { + // vlink + const dotlinkRes = await axios(`${link}`, { headers }); + const dotlinkText = dotlinkRes.data; + // console.log('dotlinkText', dotlinkText); + const vlink = dotlinkText.match(/ { + const title = $(element).text(); + const link = $(element) + .parent() + .parent() + .next('h4') + .find('a') + .attr('href'); + if (link && !title.includes('zip')) { + episodeLinks.push({ + title: title, + link, + }); + } + }); + return episodeLinks; + } + catch (err) { + return [ + { + title: 'Server 1', + link: url, + }, + ]; + } +}; +exports.world4uGetEpisodeLinks = world4uGetEpisodeLinks; diff --git a/dist/world4u/world4uGetInfo.js b/dist/world4u/world4uGetInfo.js new file mode 100644 index 0000000..63bb066 --- /dev/null +++ b/dist/world4u/world4uGetInfo.js @@ -0,0 +1,76 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.world4uGetInfo = void 0; +const world4uGetInfo = async function ({ link, providerContext, }) { + try { + const { axios, cheerio } = providerContext; + const url = link; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const type = $('.entry-content') + .text() + .toLocaleLowerCase() + .includes('movie name') + ? 'movie' + : 'series'; + const imdbId = $('.imdb_left').find('a').attr('href')?.split('/')[4] || ''; + const title = $('.entry-content') + .find('strong:contains("Name")') + .children() + .remove() + .end() + .text() + .replace(':', ''); + const synopsis = $('.entry-content') + .find('p:contains("Synopsis"),p:contains("Plot"),p:contains("Story")') + .children() + .remove() + .end() + .text(); + const image = $('.wp-caption').find('img').attr('data-src') || + $('.entry-content').find('img').attr('data-src') || + ''; + const links = []; + $('.my-button').map((i, element) => { + const title = $(element).parent().parent().prev().text(); + const episodesLink = $(element).attr('href'); + const quality = title.match(/\b(480p|720p|1080p|2160p)\b/i)?.[0] || ''; + if (episodesLink && title) { + links.push({ + title, + episodesLink: type === 'series' ? episodesLink : '', + directLinks: type === 'movie' + ? [ + { + link: episodesLink, + title, + type: 'movie', + }, + ] + : [], + quality, + }); + } + }); + return { + title, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } + catch (err) { + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; +exports.world4uGetInfo = world4uGetInfo; diff --git a/dist/world4u/world4uGetPosts.js b/dist/world4u/world4uGetPosts.js new file mode 100644 index 0000000..2b1f0f4 --- /dev/null +++ b/dist/world4u/world4uGetPosts.js @@ -0,0 +1,48 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.world4uGetPostsSearch = exports.world4uGetPosts = void 0; +const world4uGetPosts = async function ({ filter, page, +// providerValue, +signal, providerContext, }) { + const { getBaseUrl, axios, cheerio } = providerContext; + const baseUrl = await getBaseUrl('w4u'); + const url = `${baseUrl + filter}/page/${page}/`; + return posts({ url, signal, axios, cheerio }); +}; +exports.world4uGetPosts = world4uGetPosts; +const world4uGetPostsSearch = async function ({ searchQuery, page, +// providerValue, +signal, providerContext, }) { + const { getBaseUrl, axios, cheerio } = providerContext; + const baseUrl = await getBaseUrl('w4u'); + const url = `${baseUrl}/page/${page}/?s=${searchQuery}`; + return posts({ url, signal, axios, cheerio }); +}; +exports.world4uGetPostsSearch = world4uGetPostsSearch; +async function posts({ url, signal, axios, cheerio, }) { + try { + const res = await axios.get(url, { signal }); + const data = res.data; + const $ = cheerio.load(data); + const catalog = []; + $('.recent-posts') + .children() + .map((i, element) => { + const title = $(element).find('.post-thumb').find('a').attr('title'); + const link = $(element).find('.post-thumb').find('a').attr('href'); + const image = $(element).find('.post-thumb').find('img').attr('data-src') || + $(element).find('.post-thumb').find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title.replace('Download', '').trim(), + link: link, + image: image, + }); + } + }); + return catalog; + } + catch (err) { + return []; + } +} diff --git a/dist/world4u/world4uGetStream.js b/dist/world4u/world4uGetStream.js new file mode 100644 index 0000000..50d499e --- /dev/null +++ b/dist/world4u/world4uGetStream.js @@ -0,0 +1,186 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.world4uGetStream = void 0; +const world4uGetStream = async function ({ link: url, type, providerContext, }) { + const { axios, cheerio } = providerContext; + const headers = { + 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', + }; + try { + if (type === 'movie') { + const linkRes = await axios.get(url, { headers }); + const linkData = linkRes.data; + const $ = cheerio.load(linkData); + url = $('strong:contains("INSTANT")').parent().attr('href') || url; + } + // fastilinks + if (url.includes('fastilinks')) { + const fastilinksRes = await axios.get(url, { headers }); + const fastilinksData = fastilinksRes.data; + const $$ = cheerio.load(fastilinksData); + const fastilinksKey = $$('input[name="_csrf_token_645a83a41868941e4692aa31e7235f2"]').attr('value'); + console.log('fastilinksKey', fastilinksKey); + const fastilinksFormData = new FormData(); + fastilinksFormData.append('_csrf_token_645a83a41868941e4692aa31e7235f2', fastilinksKey); + const fastilinksRes2 = await fetch(url, { + method: 'POST', + headers: headers, + body: fastilinksFormData, + }); + const fastilinksHtml = await fastilinksRes2.text(); + // console.log('fastilinksHtml', fastilinksHtml); + const $$$ = cheerio.load(fastilinksHtml); + const fastilinksLink = $$$('a:contains("mediafire")').attr('href') || + $$$('a:contains("photolinx")').attr('href'); + console.log('fastilinksLink', fastilinksLink); + url = fastilinksLink || url; + } + console.log('world4uGetStream', type, url); + if (url.includes('photolinx')) { + console.log('photolinx', url); + // const photolinxBaseUrl = url.split('/').slice(0, 3).join('/'); + const photolinxRes = await axios.get(url, { headers }); + const photolinxData = photolinxRes.data; + const $$$ = cheerio.load(photolinxData); + const access_token = $$$('#generate_url').attr('data-token'); + const uid = $$$('#generate_url').attr('data-uid'); + const body = { + type: 'DOWNLOAD_GENERATE', + payload: { + access_token, + uid, + }, + }; + console.log('photolinxData', JSON.stringify(body)); + const photolinxRes2 = await fetch('https://photolinx.shop/action', { + headers: { + 'sec-fetch-site': 'same-origin', + 'x-requested-with': 'xmlhttprequest', + cookie: 'PHPSESSID=9a8d855c700cf0711831c04960c2e2b4', + Referer: 'https://photolinx.shop/download/5mPkrBD0D2x', + 'Referrer-Policy': 'strict-origin-when-cross-origin', + }, + body: JSON.stringify(body), + method: 'POST', + }); + const photolinxData2 = await photolinxRes2.json(); + console.log('photolinxData2', photolinxData2); + const dwUrl = photolinxData2?.download_url; + if (dwUrl) { + const streamLinks = [ + { + server: 'Photolinx', + link: dwUrl, + type: 'mkv', + }, + ]; + return streamLinks; + } + } + const res = await axios.get(url, { headers }); + const html = res.data; + const streamLinks = []; + let data = { download: '' }; + try { + const key = html.match(/formData\.append\('key',\s*'(\d+)'\);/)?.[1] || ''; + console.log('key', key); + const formData = new FormData(); + formData.append('key', key); + const streamRes = await fetch(url, { + method: 'POST', + headers: headers, + body: formData, + }); + data = await streamRes.json(); + } + catch (err) { + console.log('error in world4uGetStream', err); + } + // console.log('streamRes', streamRes); + let $ = cheerio.load(html); + // console.log('data', html); + const mediafireUrl = $('h1:contains("Download")').find('a').attr('href') || + $('.input.popsok').attr('href'); + console.log('mediafireUrl', mediafireUrl); + if (mediafireUrl) { + const directUrl = await axios.head(mediafireUrl); + const urlContentType = directUrl.headers['content-type']; + console.log('mfcontentType', urlContentType); + if (urlContentType && urlContentType.includes('video')) { + streamLinks.push({ + server: 'Mediafire', + link: mediafireUrl, + type: 'mkv', + }); + return streamLinks; + } + else { + const repairRes = await axios.get(mediafireUrl, { + headers: { + Referer: url, + }, + }); + const repairHtml = repairRes.data; + // Regex to match the window.location.href assignment in the script content + const hrefRegex = /window\.location\.href\s*=\s*['"]([^'"]+)['"]/; + const match = repairHtml.match(hrefRegex); + // If a match is found, return the URL; otherwise return null + let downloadLInk = match ? match[1] : null; + console.log('downloadLInk', downloadLInk); + if (downloadLInk) { + streamLinks.push({ + server: 'Mediafire', + link: downloadLInk, + type: 'mkv', + }); + } + return streamLinks; + } + } + const requireRepairRes = await axios.head(data.download); + const contentType = requireRepairRes.headers['content-type']; + console.log('contentType', contentType); + if (contentType && contentType.includes('video')) { + streamLinks.push({ + server: 'Mediafire', + link: data.download, + type: 'mkv', + }); + return streamLinks; + } + else { + const repairRes = await axios.get(data.download, { + headers: { + Referer: url, + }, + }); + const repairHtml = repairRes.data; + const $ = cheerio.load(repairHtml); + const repairLink = $('#continue-btn').attr('href'); + console.log('repairLink', 'https://www.mediafire.com' + repairLink); + const repairRequireRepairRes = await axios.get('https://www.mediafire.com' + repairLink); + const $$ = cheerio.load(repairRequireRepairRes.data); + const repairDownloadLink = $$('.input.popsok').attr('href'); + console.log('repairDownloadLink', repairDownloadLink); + if (repairDownloadLink) { + streamLinks.push({ + server: 'Mediafire', + link: repairDownloadLink, + type: 'mkv', + }); + } + } + return streamLinks; + } + catch (err) { + console.log(err); + return []; + } +}; +exports.world4uGetStream = world4uGetStream; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c1f4fd0 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,638 @@ +{ + "name": "vega-providers", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "vega-providers", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "axios": "^1.10.0", + "cheerio": "^1.1.0" + }, + "devDependencies": { + "@types/cheerio": "^0.22.35", + "@types/node": "^24.0.1", + "typescript": "^5.8.3" + } + }, + "node_modules/@types/cheerio": { + "version": "0.22.35", + "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.35.tgz", + "integrity": "sha512-yD57BchKRvTV+JD53UZ6PD8KWY5g5rvvMLRnZR3EQBCZXiDT/HR+pKpMzFGlWNhFrXlo7VPZXtKvIEwZkAWOIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "24.0.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.1.tgz", + "integrity": "sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.8.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/cheerio": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.1.0.tgz", + "integrity": "sha512-+0hMx9eYhJvWbgpKV9hN7jg0JcwydpopZE4hgi+KvQtByZXPp04NiCWU0LzcAbP63abZckIHkTQaXVF52mX3xQ==", + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.0", + "htmlparser2": "^10.0.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.10.0", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=18.17" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/htmlparser2": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", + "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.1", + "entities": "^6.0.0" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.10.0.tgz", + "integrity": "sha512-u5otvFBOBZvmdjWLVW+5DAc9Nkq8f24g0O9oY7qw2JVIF1VocIFoyz9JFkuVOS2j41AufeO0xnlweJ2RLT8nGw==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", + "dev": true, + "license": "MIT" + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..b5f1788 --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "vega-providers", + "version": "1.0.0", + "description": "providers for vega-app", + "license": "ISC", + "author": "", + "type": "commonjs", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "devDependencies": { + "@types/cheerio": "^0.22.35", + "@types/node": "^24.0.1", + "typescript": "^5.8.3" + }, + "dependencies": { + "axios": "^1.10.0", + "cheerio": "^1.1.0" + } +} diff --git a/providers/autoEmbed/allCatalog.ts b/providers/autoEmbed/allCatalog.ts new file mode 100644 index 0000000..b59bd02 --- /dev/null +++ b/providers/autoEmbed/allCatalog.ts @@ -0,0 +1,20 @@ +export const allCatalog = [ + { + title: 'Popular Movies', + filter: '/top/catalog/movie/top.json', + }, + { + title: 'Popular TV Shows', + filter: '/top/catalog/series/top.json', + }, + { + title: 'Featured Movies', + filter: '/imdbRating/catalog/movie/imdbRating.json', + }, + { + title: 'Featured TV Shows', + filter: '/imdbRating/catalog/series/imdbRating.json', + }, +]; + +export const allGenresList = []; diff --git a/providers/autoEmbed/allGetInfo.ts b/providers/autoEmbed/allGetInfo.ts new file mode 100644 index 0000000..28b6b26 --- /dev/null +++ b/providers/autoEmbed/allGetInfo.ts @@ -0,0 +1,91 @@ +import {EpisodeLink, Info, Link, ProviderContext} from '../types'; + +export const allGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + const axios = providerContext.axios; + try { + console.log('all', link); + const res = await axios.get(link); + const data = res.data; + const meta = { + title: '', + synopsis: '', + image: '', + imdbId: data?.meta?.imdb_id || '', + type: data?.meta?.type || 'movie', + }; + + const links: Link[] = []; + let directLinks: EpisodeLink[] = []; + let season = new Map(); + if (meta.type === 'series') { + data?.meta?.videos?.map((video: any) => { + if (video?.season <= 0) return; + if (!season.has(video?.season)) { + season.set(video?.season, []); + } + season.get(video?.season).push({ + title: 'Episode ' + video?.episode, + type: 'series', + link: JSON.stringify({ + title: data?.meta?.name as string, + imdbId: data?.meta?.imdb_id, + season: video?.id?.split(':')[1], + episode: video?.id?.split(':')[2], + type: data?.meta?.type, + tmdbId: data?.meta?.moviedb_id?.toString() || '', + year: data?.meta?.year, + }), + }); + }); + const keys = Array.from(season.keys()); + keys.sort(); + keys.map(key => { + directLinks = season.get(key); + links.push({ + title: `Season ${key}`, + directLinks: directLinks, + }); + }); + } else { + console.log('all meta Mv🔥🔥', meta); + links.push({ + title: data?.meta?.name as string, + directLinks: [ + { + title: 'Movie', + type: 'movie', + link: JSON.stringify({ + title: data?.meta?.name as string, + imdbId: data?.meta?.imdb_id, + season: '', + episode: '', + type: data?.meta?.type, + tmdbId: data?.meta?.moviedb_id?.toString() || '', + year: data?.meta?.year, + }), + }, + ], + }); + } + return { + ...meta, + linkList: links, + }; + } catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/autoEmbed/allGetPost.ts b/providers/autoEmbed/allGetPost.ts new file mode 100644 index 0000000..743b215 --- /dev/null +++ b/providers/autoEmbed/allGetPost.ts @@ -0,0 +1,109 @@ +import {Post, ProviderContext} from '../types'; + +export const allGetPost = async function ({ + filter, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + try { + const catalog: Post[] = []; + const url = 'https://cinemeta-catalogs.strem.io' + filter; + console.log('allGetPostUrl', url); + const res = await providerContext.axios.get(url, { + headers: providerContext.commonHeaders, + signal, + }); + const data = res.data; + data?.metas.map((result: any) => { + const title = result?.name; + const id = result?.imdb_id || result?.id; + const type = result?.type; + const image = result?.poster; + if (id) { + catalog.push({ + title: title, + link: `https://v3-cinemeta.strem.io/meta/${type}/${id}.json`, + image: image, + }); + } + }); + console.log('catalog', catalog.length); + return catalog; + } catch (err) { + console.error('AutoEmbed error ', err); + return []; + } +}; + +export const allGetSearchPosts = async function ({ + searchQuery, + page, + // providerValue, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + try { + if (page > 1) { + return []; + } + const catalog: Post[] = []; + const url1 = `https://v3-cinemeta.strem.io/catalog/series/top/search=${encodeURI( + searchQuery, + )}.json`; + const url2 = `https://v3-cinemeta.strem.io/catalog/movie/top/search=${encodeURI( + searchQuery, + )}.json`; + const res = await providerContext.axios.get(url1, { + headers: providerContext.commonHeaders, + signal, + }); + const data = res.data; + data?.metas.map((result: any) => { + const title = result.name || ''; + const id = result?.imdb_id || result?.id; + const image = result?.poster; + const type = result?.type; + if (id) { + catalog.push({ + title: title, + link: `https://v3-cinemeta.strem.io/meta/${type}/${id}.json`, + image: image, + }); + } + }); + const res2 = await providerContext.axios.get(url2, { + headers: providerContext.commonHeaders, + signal, + }); + const data2 = res2.data; + data2?.metas.map((result: any) => { + const title = result?.name || ''; + const id = result?.imdb_id || result?.id; + const image = result?.poster; + const type = result?.type; + if (id) { + catalog.push({ + title: title, + link: `https://v3-cinemeta.strem.io/meta/${type}/${id}.json`, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('AutoEmbed error ', err); + return []; + } +}; diff --git a/providers/autoEmbed/allGetStream.ts b/providers/autoEmbed/allGetStream.ts new file mode 100644 index 0000000..f2ffd05 --- /dev/null +++ b/providers/autoEmbed/allGetStream.ts @@ -0,0 +1,250 @@ +import {Stream, ProviderContext, TextTrackType, TextTracks} from '../types'; + +export const allGetStream = async ({ + link: id, + type, + providerContext, +}: { + link: string; + type: string; + providerContext: ProviderContext; +}): Promise => { + try { + const streams: Stream[] = []; + const {imdbId, season, episode, title, tmdbId, year} = JSON.parse(id); + await getRiveStream( + tmdbId, + episode, + season, + type, + streams, + providerContext, + ); + return streams; + } catch (err) { + console.error(err); + return []; + } +}; + +export async function getRiveStream( + tmdId: string, + episode: string, + season: string, + type: string, + Streams: Stream[], + providerContext: ProviderContext, +) { + const secret = generateSecretKey(Number(tmdId)); + const servers = [ + 'flowcast', + 'shadow', + 'asiacloud', + 'hindicast', + 'anime', + 'animez', + 'guard', + 'curve', + 'hq', + 'ninja', + 'alpha', + 'kaze', + 'zenesis', + 'genesis', + 'zenith', + 'ghost', + 'halo', + 'kinoecho', + 'ee3', + 'volt', + 'putafilme', + 'ophim', + 'kage', + ]; + const baseUrl = await providerContext.getBaseUrl('rive'); + const cors = process.env.CORS_PRXY ? process.env.CORS_PRXY + '?url=' : ''; + console.log('CORS: ' + cors); + const route = + type === 'series' + ? `/api/backendfetch?requestID=tvVideoProvider&id=${tmdId}&season=${season}&episode=${episode}&secretKey=${secret}&service=` + : `/api/backendfetch?requestID=movieVideoProvider&id=${tmdId}&secretKey=${secret}&service=`; + const url = cors + ? cors + encodeURIComponent(baseUrl + route) + : baseUrl + route; + await Promise.all( + servers.map(async server => { + console.log('Rive: ' + url + server); + try { + const res = await providerContext.axios.get(url + server, { + timeout: 4000, + headers: providerContext.commonHeaders, + }); + const subtitles: TextTracks = []; + if (res.data?.data?.captions) { + res.data?.data?.captions.forEach((sub: any) => { + subtitles.push({ + language: sub?.label?.slice(0, 2) || 'Und', + uri: sub?.file, + title: sub?.label || 'Undefined', + type: sub?.file?.endsWith('.vtt') + ? TextTrackType.VTT + : TextTrackType.SUBRIP, + }); + }); + } + res.data?.data?.sources.forEach((source: any) => { + Streams.push({ + server: source?.source + '-' + source?.quality, + link: source?.url, + type: source?.format === 'hls' ? 'm3u8' : 'mp4', + quality: source?.quality, + subtitles: subtitles, + }); + }); + } catch (e) { + console.log(e); + } + }), + ); +} + +function generateSecretKey(id: number | string) { + // Array of secret key fragments - updated array from the new implementation + const c = [ + 'Yhv40uKAZa', + 'nn8YU4yBA', + 'uNeH', + 'ehK', + 'jT0', + 'n5G', + '99R', + 'MvB1M', + 'DQtPCh', + 'GBRjk4k4I', + 'CzIOoa95UT', + 'BLE8s', + 'GDZlc7', + 'Fz45T', + 'JW6lWn', + 'DE3g4uw0i', + '18KxmYizv', + '8ji', + 'JUDdNMnZ', + 'oGpBippPgm', + '7De8Pg', + 'Zv6', + 'VHT9TVN', + 'bYH6m', + 'aK1', + 'WcWH6jU', + 'Q47YEMi4k', + 'vRD3A', + 'CGOsfJO', + 'BLn8', + 'RgK0drv7l', + 'oPTfGCn3a', + 'MkpMDkttW9', + 'VNI1fPM', + 'XNFi6', + '6cq', + '4LvTksXoEI', + '1rRa2KOZB0', + 'zoOGRb8HT2', + 'mhcXDtvz', + 'NUmexFY2Ur', + '6BIMdvSZ', + 'Tr0zU2vjRd', + 'QPR', + 'fhOqJR', + 'R9VnFY', + 'xkZ99D6S', + 'umY7E', + '5Ds8qyDq', + 'Cc6jy09y3', + 'yvU3iR', + 'Bg07zY', + 'GccECglg', + 'VYd', + '6vOiXqz', + '7xX', + 'UdRrbEzF', + 'fE6wc', + 'BUd25Rb', + 'lxq5Zum89o', + ]; + + // Handle undefined input + if (id === undefined) { + return 'rive'; + } + + try { + let fragment, insertPos; + // Convert input to string + const idStr = String(id); + + // Updated string hash function to match the new implementation + /* eslint-disable no-bitwise */ + const generateStringHash = function (input: string) { + input = String(input); + let hash = 0; + for (let i = 0; i < input.length; i++) { + const char = input.charCodeAt(i); + hash = + ((char + (hash << 6) + (hash << 16) - hash) ^ (char << i % 5)) >>> 0; + } + hash ^= hash >>> 13; + hash = (1540483477 * hash) >>> 0; + return (hash ^= hash >>> 15).toString(16).padStart(8, '0'); + }; + + // Updated MurmurHash-like function to match the new implementation + const applyMurmurHash = function (input: string) { + const str = String(input); + let hash = 3735928559 ^ str.length; + for (let i = 0; i < str.length; i++) { + let char = str.charCodeAt(i); + char ^= ((i + 31) * 131) & 255; + hash = + (668265261 * + (hash = (((hash << 7) | (hash >>> 25)) >>> 0) ^ char)) >>> + 0; + } + hash ^= hash >>> 16; + hash = (2246822507 * hash) >>> 0; + hash ^= hash >>> 13; + hash = (3266489909 * hash) >>> 0; + return (hash ^= hash >>> 16).toString(16).padStart(8, '0'); + }; + /* eslint-enable no-bitwise */ + + // Generate the encoded hash using the new implementation + const encodedHash = btoa(applyMurmurHash(generateStringHash(idStr))); + + // Different handling for non-numeric vs numeric inputs + if (isNaN(Number(id))) { + // For non-numeric inputs, sum the character codes + const charSum = idStr + .split('') + .reduce((sum, char) => sum + char.charCodeAt(0), 0); + // Select array element or fallback to base64 encoded input + fragment = c[charSum % c.length] || btoa(idStr); + // Calculate insertion position + insertPos = Math.floor((charSum % encodedHash.length) / 2); + } else { + // For numeric inputs, use the number directly + const numId = Number(id); + fragment = c[numId % c.length] || btoa(idStr); + // Calculate insertion position + insertPos = Math.floor((numId % encodedHash.length) / 2); + } + + // Construct the final key by inserting the selected value into the base64 string + return ( + encodedHash.slice(0, insertPos) + fragment + encodedHash.slice(insertPos) + ); + } catch (error) { + // Return fallback value if any errors occur + return 'topSecret'; + } +} diff --git a/providers/autoEmbed/index.ts b/providers/autoEmbed/index.ts new file mode 100644 index 0000000..144d86c --- /dev/null +++ b/providers/autoEmbed/index.ts @@ -0,0 +1,14 @@ +import {allCatalog, allGenresList} from './allCatalog'; +import {allGetInfo} from './allGetInfo'; +import {allGetStream} from './allGetStream'; +import {allGetPost, allGetSearchPosts} from './allGetPost'; +import {ProviderType} from '../../Manifest'; + +export const autoEmbed: ProviderType = { + catalog: allCatalog, + genres: allGenresList, + GetMetaData: allGetInfo, + GetHomePosts: allGetPost, + GetStream: allGetStream, + GetSearchPosts: allGetSearchPosts, +}; diff --git a/providers/cinemaLuxe/clCatalog.ts b/providers/cinemaLuxe/clCatalog.ts new file mode 100644 index 0000000..fc8ff8c --- /dev/null +++ b/providers/cinemaLuxe/clCatalog.ts @@ -0,0 +1,20 @@ +export const clCatalog = [ + { + title: 'Trending', + filter: '/genre/latest-trending-releases/', + }, + { + title: 'Netflix', + filter: '/network/netflix/', + }, + { + title: 'Amazon Prime', + filter: '/network/prime-video/', + }, + { + title: 'Animation', + filter: '/genre/anime/', + }, +]; + +export const clGenresList = []; diff --git a/providers/cinemaLuxe/clGetEpisodes.ts b/providers/cinemaLuxe/clGetEpisodes.ts new file mode 100644 index 0000000..4383903 --- /dev/null +++ b/providers/cinemaLuxe/clGetEpisodes.ts @@ -0,0 +1,73 @@ +import {EpisodeLink, ProviderContext} from '../types'; + +export const clsEpisodeLinks = async function ({ + url, + providerContext, +}: { + url: string; + providerContext: ProviderContext; +}): Promise { + try { + if (!url.includes('luxelinks') || url.includes('luxecinema')) { + const res = await providerContext.axios.get(url, { + headers: providerContext.commonHeaders, + }); + const data = res.data; + const encodedLink = data.match(/"link":"([^"]+)"/)?.[1]; + if (encodedLink) { + url = encodedLink ? atob(encodedLink) : url; + } else { + const redirectUrlRes = await fetch( + 'https://ext.8man.me/api/cinemaluxe', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({url}), + }, + ); + const redirectUrl = await redirectUrlRes.json(); + url = redirectUrl?.redirectUrl || url; + } + } + const res = await providerContext.axios.get(url, { + headers: providerContext.commonHeaders, + }); + const html = res.data; + let $ = providerContext.cheerio.load(html); + const episodeLinks: EpisodeLink[] = []; + if (url.includes('luxedrive')) { + episodeLinks.push({ + title: 'Movie', + link: url, + }); + return episodeLinks; + } + $('a.maxbutton-4,a.maxbutton,.maxbutton-hubcloud,.ep-simple-button').map( + (i, element) => { + const title = $(element).text()?.trim(); + const link = $(element).attr('href'); + if ( + title && + link && + !title.includes('Batch') && + !title.toLowerCase().includes('zip') + ) { + episodeLinks.push({ + title: title + .replace(/\(\d{4}\)/, '') + .replace('Download', 'Movie') + .replace('⚡', '') + .trim(), + link, + }); + } + }, + ); + return episodeLinks; + } catch (err) { + console.error('cl episode links', err); + return []; + } +}; diff --git a/providers/cinemaLuxe/clGetMeta.ts b/providers/cinemaLuxe/clGetMeta.ts new file mode 100644 index 0000000..cb563ad --- /dev/null +++ b/providers/cinemaLuxe/clGetMeta.ts @@ -0,0 +1,69 @@ +import {Info, Link, ProviderContext} from '../types'; + +export const clGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const url = link; + const res = await providerContext.axios.get(url, { + headers: providerContext.commonHeaders, + }); + const data = res.data; + const $ = providerContext.cheerio.load(data); + const type = url.includes('tvshows') ? 'series' : 'movie'; + const imdbId = ''; + const title = url.split('/')[4].replace(/-/g, ' '); + const image = $('.g-item').find('a').attr('href') || ''; + const synopsis = $('.wp-content').text().trim(); + const tags = $('.sgeneros') + .children() + .map((i, element) => $(element).text()) + .get() + .slice(3); + const rating = Number($('#repimdb').find('strong').text()) + .toFixed(1) + .toString(); + const links: Link[] = []; + $('.mb-center.maxbutton-5-center,.ep-button-container').map( + (i, element) => { + const title = $(element) + .text() + .replace('\u2b07Download', '') + .replace('\u2b07 Download', '') + .trim(); + const link = $(element).find('a').attr('href'); + if (title && link) { + links.push({ + title, + episodesLink: link, + quality: title?.match(/\d+P\b/)?.[0].replace('P', 'p') || '', + }); + } + }, + ); + return { + title, + tags, + rating, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/cinemaLuxe/clGetPosts.ts b/providers/cinemaLuxe/clGetPosts.ts new file mode 100644 index 0000000..c18918c --- /dev/null +++ b/providers/cinemaLuxe/clGetPosts.ts @@ -0,0 +1,82 @@ +import {Post, ProviderContext} from '../types'; + +export const clGetPosts = async function ({ + filter, + page, + signal, + providerContext, +}: { + filter: string; + page: number; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const baseUrl = await providerContext.getBaseUrl('cinemaLuxe'); + const url = `${baseUrl + filter}page/${page}/`; + return posts({url, signal, providerContext}); +}; + +export const clGetPostsSearch = async function ({ + searchQuery, + page, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const baseUrl = await providerContext.getBaseUrl('cinemaLuxe'); + const url = `${baseUrl}/page/${page}/?s=${searchQuery}`; + return posts({url, signal, providerContext}); +}; + +async function posts({ + url, + signal, + providerContext, +}: { + url: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + try { + const res = await fetch(url, { + headers: providerContext.commonHeaders, + signal, + }); + const data = await res.text(); + const $ = providerContext.cheerio.load(data); + const catalog: Post[] = []; + $('.item.tvshows,.item.movies').map((i, element) => { + const title = $(element).find('.poster').find('img').attr('alt'); + const link = $(element).find('.poster').find('a').attr('href'); + const image = $(element).find('.poster').find('img').attr('data-src'); + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + $('.result-item').map((i, element) => { + const title = $(element).find('.thumbnail').find('img').attr('alt'); + const link = $(element).find('.thumbnail').find('a').attr('href'); + const image = $(element).find('.thumbnail').find('img').attr('data-src'); + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('cinemaluxe error ', err); + return []; + } +} diff --git a/providers/cinemaLuxe/clGetSteam.ts b/providers/cinemaLuxe/clGetSteam.ts new file mode 100644 index 0000000..654a017 --- /dev/null +++ b/providers/cinemaLuxe/clGetSteam.ts @@ -0,0 +1,47 @@ +import {Stream, ProviderContext} from '../types'; + +export const clGetStream = async ({ + link, + signal, + providerContext, +}: { + link: string; + type: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise => { + try { + let newLink = link; + if (link.includes('luxedrive')) { + const res = await providerContext.axios.get(link); + const $ = providerContext.cheerio.load(res.data); + const hubcloudLink = $('a.btn.hubcloud').attr('href'); + if (hubcloudLink) { + newLink = hubcloudLink; + } else { + const gdFlixLink = $('a.btn.gdflix').attr('href'); + if (gdFlixLink) { + newLink = gdFlixLink; + } + } + } + if (newLink.includes('gdflix')) { + const sreams = await providerContext.extractors.gdFlixExtracter( + newLink, + signal, + ); + return sreams; + } + const res2 = await providerContext.axios.get(newLink, {signal}); + const data2 = res2.data; + const hcLink = data2.match(/location\.replace\('([^']+)'/)?.[1] || newLink; + const hubCloudLinks = await providerContext.extractors.hubcloudExtracter( + hcLink.includes('https://hubcloud') ? hcLink : newLink, + signal, + ); + return hubCloudLinks; + } catch (err) { + console.error(err); + return []; + } +}; diff --git a/providers/cinemaLuxe/index.ts b/providers/cinemaLuxe/index.ts new file mode 100644 index 0000000..5631520 --- /dev/null +++ b/providers/cinemaLuxe/index.ts @@ -0,0 +1,16 @@ +import {clGenresList, clCatalog} from './clCatalog'; +import {clGetInfo} from './clGetMeta'; +import {clsEpisodeLinks} from './clGetEpisodes'; +import {clGetPostsSearch, clGetPosts} from './clGetPosts'; +import {ProviderType} from '../types'; +import {clGetStream} from './clGetSteam'; + +export const cinemaLuxe: ProviderType = { + catalog: clCatalog, + genres: clGenresList, + GetHomePosts: clGetPosts, + GetMetaData: clGetInfo, + GetSearchPosts: clGetPostsSearch, + GetEpisodeLinks: clsEpisodeLinks, + GetStream: clGetStream, +}; diff --git a/providers/dooflix/dooCatalog.ts b/providers/dooflix/dooCatalog.ts new file mode 100644 index 0000000..bfe119e --- /dev/null +++ b/providers/dooflix/dooCatalog.ts @@ -0,0 +1,12 @@ +export const dooCatalog = [ + { + title: 'Series', + filter: '/rest-api//v130/tvseries', + }, + { + title: 'Movies', + filter: '/rest-api//v130/movies', + }, +]; + +export const dooGenresList = []; diff --git a/providers/dooflix/dooGetInfo.ts b/providers/dooflix/dooGetInfo.ts new file mode 100644 index 0000000..6e35537 --- /dev/null +++ b/providers/dooflix/dooGetInfo.ts @@ -0,0 +1,83 @@ +import {EpisodeLink, Info, Link, ProviderContext} from '../types'; + +const headers = { + 'Accept-Encoding': 'gzip', + 'API-KEY': '2pm95lc6prpdbk0ppji9rsqo', + Connection: 'Keep-Alive', + 'If-Modified-Since': 'Wed, 14 Aug 2024 13:00:04 GMT', + 'User-Agent': 'okhttp/3.14.9', +}; + +export const dooGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios} = providerContext; + const res = await axios.get(link, {headers}); + const resData = res.data; + const jsonStart = resData?.indexOf('{'); + const jsonEnd = resData?.lastIndexOf('}') + 1; + const data = JSON?.parse(resData?.substring(jsonStart, jsonEnd))?.title + ? JSON?.parse(resData?.substring(jsonStart, jsonEnd)) + : resData; + const title = data?.title || ''; + const synopsis = data?.description || ''; + const image = data?.poster_url || ''; + const cast = data?.cast || []; + const rating = data?.imdb_rating || ''; + const type = Number(data?.is_tvseries) ? 'series' : 'movie'; + const tags = data?.genre?.map((genre: any) => genre?.name) || []; + const links: Link[] = []; + if (type === 'series') { + data?.season?.map((season: any) => { + const title = season?.seasons_name || ''; + const directLinks: EpisodeLink[] = + season?.episodes?.map((episode: any) => ({ + title: episode?.episodes_name, + link: episode?.file_url, + })) || []; + links.push({ + title: title, + directLinks: directLinks, + }); + }); + } else { + data?.videos?.map((video: any) => { + links.push({ + title: title + ' ' + video?.label, + directLinks: [ + { + title: 'Play', + link: video?.file_url, + }, + ], + }); + }); + } + return { + image: image?.includes('https') ? image : image?.replace('http', 'https'), + synopsis: synopsis, + title: title, + rating: rating, + imdbId: '', + cast: cast, + tags: tags, + type: type, + linkList: links, + }; + } catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/dooflix/dooGetPosts.ts b/providers/dooflix/dooGetPosts.ts new file mode 100644 index 0000000..e79ed0d --- /dev/null +++ b/providers/dooflix/dooGetPosts.ts @@ -0,0 +1,173 @@ +import {Post, ProviderContext} from '../types'; + +const headers = { + 'Accept-Encoding': 'gzip', + 'API-KEY': '2pm95lc6prpdbk0ppji9rsqo', + Connection: 'Keep-Alive', + 'If-Modified-Since': 'Wed, 14 Aug 2024 13:00:04 GMT', + 'User-Agent': 'okhttp/3.14.9', +}; + +export const dooGetPost = async function ({ + filter, + page, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + providerContext: ProviderContext; + signal: AbortSignal; +}): Promise { + try { + const {axios, getBaseUrl} = providerContext; + const baseUrl = await getBaseUrl('dooflix'); + const catalog: Post[] = []; + const url = `${baseUrl + filter + `?page=${page}`}`; + + const res = await axios.get(url, {headers, signal}); + const resData = res.data; + + if (!resData || typeof resData !== 'string') { + console.warn('Unexpected response format from dooflix API'); + return []; + } + + let data; + try { + const jsonStart = resData.indexOf('['); + const jsonEnd = resData.lastIndexOf(']') + 1; + + if (jsonStart === -1 || jsonEnd <= jsonStart) { + // If we can't find valid JSON array markers, try parsing the entire response + data = JSON.parse(resData); + } else { + const jsonSubstring = resData.substring(jsonStart, jsonEnd); + const parsedArray = JSON.parse(jsonSubstring); + data = parsedArray.length > 0 ? parsedArray : resData; + } + } catch (parseError) { + console.error('Error parsing dooflix response:', parseError); + return []; + } + + if (!Array.isArray(data)) { + console.warn('Unexpected data format from dooflix API'); + return []; + } + + data.forEach((result: any) => { + const id = result?.videos_id; + if (!id) return; + + const type = !result?.is_tvseries ? 'tvseries' : 'movie'; + const link = `${baseUrl}/rest-api//v130/single_details?type=${type}&id=${id}`; + + const thumbnailUrl = result?.thumbnail_url; + const image = thumbnailUrl?.includes('https') + ? thumbnailUrl + : thumbnailUrl?.replace('http', 'https'); + + catalog.push({ + title: result?.title || '', + link, + image, + }); + }); + + return catalog; + } catch (err) { + console.error('dooflix error:', err); + return []; + } +}; + +export const dooGetSearchPost = async function ({ + searchQuery, + page, + providerContext, + signal, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + try { + if (page > 1) { + return []; + } + const {axios, getBaseUrl} = providerContext; + const catalog: Post[] = []; + const baseUrl = await getBaseUrl('dooflix'); + const url = `${baseUrl}/rest-api//v130/search?q=${searchQuery}&type=movietvserieslive&range_to=0&range_from=0&tv_category_id=0&genre_id=0&country_id=0`; + + const res = await axios.get(url, {headers, signal}); + const resData = res.data; + + if (!resData || typeof resData !== 'string') { + console.warn('Unexpected search response format from dooflix API'); + return []; + } + + let data; + try { + const jsonStart = resData.indexOf('{'); + const jsonEnd = resData.lastIndexOf('}') + 1; + + if (jsonStart === -1 || jsonEnd <= jsonStart) { + data = resData; + } else { + const jsonSubstring = resData.substring(jsonStart, jsonEnd); + const parsedData = JSON.parse(jsonSubstring); + data = parsedData?.movie ? parsedData : resData; + } + } catch (parseError) { + console.error('Error parsing dooflix search response:', parseError); + return []; + } + + // Process movies + data?.movie?.forEach((result: any) => { + const id = result?.videos_id; + if (!id) return; + + const link = `${baseUrl}/rest-api//v130/single_details?type=movie&id=${id}`; + const thumbnailUrl = result?.thumbnail_url; + const image = thumbnailUrl?.includes('https') + ? thumbnailUrl + : thumbnailUrl?.replace('http', 'https'); + + catalog.push({ + title: result?.title || '', + link, + image, + }); + }); + + // Process TV series + data?.tvseries?.forEach((result: any) => { + const id = result?.videos_id; + if (!id) return; + + const link = `${baseUrl}/rest-api//v130/single_details?type=tvseries&id=${id}`; + const thumbnailUrl = result?.thumbnail_url; + const image = thumbnailUrl?.includes('https') + ? thumbnailUrl + : thumbnailUrl?.replace('http', 'https'); + + catalog.push({ + title: result?.title || '', + link, + image, + }); + }); + + return catalog; + } catch (error) { + console.error('dooflix search error:', error); + return []; + } +}; diff --git a/providers/dooflix/dooGetSteam.ts b/providers/dooflix/dooGetSteam.ts new file mode 100644 index 0000000..ed0f8aa --- /dev/null +++ b/providers/dooflix/dooGetSteam.ts @@ -0,0 +1,29 @@ +import {Stream} from '../types'; + +export const dooGetStream = async function ({ + link, +}: { + link: string; +}): Promise { + try { + const streams: Stream[] = []; + streams.push({ + server: 'Dooflix', + link: link, + type: 'm3u8', + headers: { + Connection: 'Keep-Alive', + 'User-Agent': + 'Mozilla/5.0 (WindowsNT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.37', + Referer: 'https://molop.art/', + Cookie: + 'cf_clearance=M2_2Hy4lKRy_ruRX3dzOgm3iho1FHe2DUC1lq28BUtI-1737377622-1.2.1.1-6R8RaH94._H2BuNuotsjTZ3fAF6cLwPII0guemu9A5Xa46lpCJPuELycojdREwoonYS2kRTYcZ9_1c4h4epi2LtDvMM9jIoOZKE9pIdWa30peM1hRMpvffTjGUCraHsJNCJez8S_QZ6XkkdP7GeQ5iwiYaI6Grp6qSJWoq0Hj8lS7EITZ1LzyrALI6iLlYjgLmgLGa1VuhORWJBN8ZxrJIZ_ba_pqbrR9fjnyToqxZ0XQaZfk1d3rZyNWoZUjI98GoAxVjnKtcBQQG6b2jYPJuMbbYraGoa54N7E7BR__7o', + }, + }); + console.log('doo streams', streams); + return streams; + } catch (err) { + console.error(err); + return []; + } +}; diff --git a/providers/dooflix/index.ts b/providers/dooflix/index.ts new file mode 100644 index 0000000..cf24e3a --- /dev/null +++ b/providers/dooflix/index.ts @@ -0,0 +1,14 @@ +import {ProviderType} from '../types'; +import {dooCatalog, dooGenresList} from './dooCatalog'; +import {dooGetInfo} from './dooGetInfo'; +import {dooGetPost, dooGetSearchPost} from './dooGetPosts'; +import {dooGetStream} from './dooGetSteam'; + +export const dooflixProvider: ProviderType = { + catalog: dooCatalog, + genres: dooGenresList, + GetMetaData: dooGetInfo, + GetStream: dooGetStream, + GetHomePosts: dooGetPost, + GetSearchPosts: dooGetSearchPost, +}; diff --git a/providers/drive/catalog.ts b/providers/drive/catalog.ts new file mode 100644 index 0000000..b792eff --- /dev/null +++ b/providers/drive/catalog.ts @@ -0,0 +1,61 @@ +export const driveCatalog = [ + { + title: 'Latest', + filter: '', + }, + { + title: 'Anime', + filter: 'category/anime/', + }, + { + title: 'Netflix', + filter: 'category/netflix/', + }, + { + title: '4K', + filter: 'category/2160p-4k/', + }, +]; + +export const driveGenresList = [ + { + title: 'Action', + filter: '/category/action', + }, + { + title: 'Crime', + filter: '/category/crime', + }, + { + title: 'Comedy', + filter: '/category/comedy', + }, + { + title: 'Drama', + filter: '/category/drama', + }, + { + title: 'Horror', + filter: '/category/horror', + }, + { + title: 'Family', + filter: '/category/family', + }, + { + title: 'Sci-Fi', + filter: '/category/sifi', + }, + { + title: 'Thriller', + filter: '/category/triller', + }, + { + title: 'Romance', + filter: '/category/romance', + }, + { + title: 'Fight', + filter: '/category/fight', + }, +]; diff --git a/providers/drive/driveGetEpisodesList.ts b/providers/drive/driveGetEpisodesList.ts new file mode 100644 index 0000000..92f6a7e --- /dev/null +++ b/providers/drive/driveGetEpisodesList.ts @@ -0,0 +1,39 @@ +import {EpisodeLink, ProviderContext} from '../types'; + +export const driveGetEpisodeLinks = async function ({ + url, + providerContext, +}: { + url: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, cheerio} = providerContext; + const res = await axios.get(url); + const html = res.data; + let $ = cheerio.load(html); + + const episodeLinks: EpisodeLink[] = []; + $('a:contains("HubCloud")').map((i, element) => { + const title = $(element).parent().prev().text(); + const link = $(element).attr('href'); + if (link && (title.includes('Ep') || title.includes('Download'))) { + episodeLinks.push({ + title: title.includes('Download') ? 'Play' : title, + link, + }); + } + }); + + // console.log(episodeLinks); + return episodeLinks; + } catch (err) { + console.error(err); + return [ + { + title: 'Server 1', + link: url, + }, + ]; + } +}; diff --git a/providers/drive/driveGetInfo.ts b/providers/drive/driveGetInfo.ts new file mode 100644 index 0000000..1a6b583 --- /dev/null +++ b/providers/drive/driveGetInfo.ts @@ -0,0 +1,92 @@ +import {Info, Link} from '../types'; + +export const driveGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: { + axios: any; + cheerio: any; + getBaseUrl: (provider: string) => Promise; + }; +}): Promise { + try { + const {axios, cheerio} = providerContext; + const url = link; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const type = $('.left-wrapper') + .text() + .toLocaleLowerCase() + .includes('movie name') + ? 'movie' + : 'series'; + const imdbId = $('a:contains("IMDb")').attr('href')?.split('/')[4] || ''; + const title = + $('.left-wrapper').find('strong:contains("Name")').next().text() || + $('.left-wrapper') + .find('strong:contains("Name"),h5:contains("Name")') + .find('span:first') + .text(); + const synopsis = + $('.left-wrapper') + .find( + 'h2:contains("Storyline"),h3:contains("Storyline"),h5:contains("Storyline"),h4:contains("Storyline"),h4:contains("STORYLINE")', + ) + .next() + .text() || + $('.ipc-html-content-inner-div').text() || + ''; + const image = + $('img.entered.lazyloaded,img.entered,img.litespeed-loaded').attr( + 'src', + ) || + $('img.aligncenter').attr('src') || + ''; + + // Links + const links: Link[] = []; + + $( + 'a:contains("1080")a:not(:contains("Zip")),a:contains("720")a:not(:contains("Zip")),a:contains("480")a:not(:contains("Zip")),a:contains("2160")a:not(:contains("Zip")),a:contains("4k")a:not(:contains("Zip"))', + ).map((i: number, element: any) => { + const title = $(element).parent('h5').prev().text(); + const episodesLink = $(element).attr('href'); + const quality = title.match(/\b(480p|720p|1080p|2160p)\b/i)?.[0] || ''; + if (episodesLink && title) { + links.push({ + title, + episodesLink: type === 'series' ? episodesLink : '', + directLinks: + type === 'movie' + ? [{title: 'Movie', link: episodesLink, type: 'movie'}] + : [], + quality: quality, + }); + } + }); + + // console.log('drive meta', title, synopsis, image, imdbId, type, links); + console.log('drive meta', links, type); + return { + title, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/drive/driveGetPosts.ts b/providers/drive/driveGetPosts.ts new file mode 100644 index 0000000..ba336d1 --- /dev/null +++ b/providers/drive/driveGetPosts.ts @@ -0,0 +1,73 @@ +import {Post, ProviderContext} from '../types'; + +export const driveGetPosts = async function ({ + filter, + page, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl} = providerContext; + const baseUrl = await getBaseUrl('drive'); + const url = `${baseUrl + filter}/page/${page}/`; + return posts({url, signal, providerContext}); +}; + +export const driveGetSearchPost = async function ({ + searchQuery, + page, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + providerContext: ProviderContext; + signal: AbortSignal; +}): Promise { + const {getBaseUrl} = providerContext; + const baseUrl = await getBaseUrl('drive'); + const url = `${baseUrl}page/${page}/?s=${searchQuery}`; + return posts({url, signal, providerContext}); +}; + +async function posts({ + url, + signal, + providerContext, +}: { + url: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + try { + const {cheerio} = providerContext; + const res = await fetch(url, {signal}); + const data = await res.text(); + const $ = cheerio.load(data); + const catalog: Post[] = []; + $('.recent-movies') + .children() + .map((i, element) => { + const title = $(element).find('figure').find('img').attr('alt'); + const link = $(element).find('a').attr('href'); + const image = $(element).find('figure').find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title.replace('Download', '').trim(), + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('drive error ', err); + return []; + } +} diff --git a/providers/drive/driveGetStream.ts b/providers/drive/driveGetStream.ts new file mode 100644 index 0000000..d163123 --- /dev/null +++ b/providers/drive/driveGetStream.ts @@ -0,0 +1,47 @@ +import {Stream, ProviderContext} from '../types'; + +export const driveGetStream = async function ({ + link: url, + type, + signal, + providerContext, +}: { + link: string; + type: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const headers = providerContext.commonHeaders; + try { + if (type === 'movie') { + const res = await providerContext.axios.get(url, {headers}); + const html = res.data; + const $ = providerContext.cheerio.load(html); + const link = $('a:contains("HubCloud")').attr('href'); + url = link || url; + } + const res = await providerContext.axios.get(url, {headers}); + let redirectUrl = res.data.match( + //i, + )?.[1]; + if (url.includes('/archives/')) { + redirectUrl = res.data.match( + /]*href="(https:\/\/hubcloud\.[^\/]+\/[^"]+)"/i, + )?.[1]; + } + if (!redirectUrl) { + return await providerContext.extractors.hubcloudExtracter(url, signal); + } + const res2 = await providerContext.axios.get(redirectUrl, {headers}); + const data = res2.data; + const $ = providerContext.cheerio.load(data); + const hubcloudLink = $('.fa-file-download').parent().attr('href'); + return await providerContext.extractors.hubcloudExtracter( + hubcloudLink?.includes('https://hubcloud') ? hubcloudLink : redirectUrl, + signal, + ); + } catch (err) { + console.error('Movies Drive err', err); + return []; + } +}; diff --git a/providers/drive/index.ts b/providers/drive/index.ts new file mode 100644 index 0000000..802cd4d --- /dev/null +++ b/providers/drive/index.ts @@ -0,0 +1,16 @@ +import {ProviderType} from '../../Manifest'; +import {driveCatalog, driveGenresList} from './catalog'; +import {driveGetEpisodeLinks} from './driveGetEpisodesList'; +import {driveGetInfo} from './driveGetInfo'; +import {driveGetPosts, driveGetSearchPost} from './driveGetPosts'; +import {driveGetStream} from './driveGetStream'; + +export const moviesDrive: ProviderType = { + catalog: driveCatalog, + genres: driveGenresList, + GetMetaData: driveGetInfo, + GetHomePosts: driveGetPosts, + GetStream: driveGetStream, + GetEpisodeLinks: driveGetEpisodeLinks, + GetSearchPosts: driveGetSearchPost, +}; diff --git a/providers/filmyfly/ffCatalog.ts b/providers/filmyfly/ffCatalog.ts new file mode 100644 index 0000000..b3c6929 --- /dev/null +++ b/providers/filmyfly/ffCatalog.ts @@ -0,0 +1,16 @@ +export const ffCatalog = [ + { + title: 'Home', + filter: '', + }, + { + title: 'Web Series', + filter: '/page-cat/42/Web-Series.html', + }, + { + title: 'Hollywood', + filter: '/page-cat/9/New-Hollywood-Hindi-Dubbed-Movie-2016-2025.html', + }, +]; + +export const ffGenresList = []; diff --git a/providers/filmyfly/ffGetEpisodes.ts b/providers/filmyfly/ffGetEpisodes.ts new file mode 100644 index 0000000..6a537a0 --- /dev/null +++ b/providers/filmyfly/ffGetEpisodes.ts @@ -0,0 +1,38 @@ +import {EpisodeLink, ProviderContext} from '../types'; + +export const ffEpisodeLinks = async function ({ + url, + providerContext, +}: { + url: string; + providerContext: ProviderContext; +}): Promise { + try { + const headers = providerContext.commonHeaders; + const {axios, cheerio} = providerContext; + const res = await axios.get(url, {headers}); + const data = res.data; + const $ = cheerio.load(data); + const episodeLinks: EpisodeLink[] = []; + + $('.dlink.dl').map((i, element) => { + const title = $(element) + .find('a') + .text() + ?.replace('Download', '') + ?.trim(); + const link = $(element).find('a').attr('href'); + + if (title && link) { + episodeLinks.push({ + title, + link, + }); + } + }); + return episodeLinks; + } catch (err) { + console.error('cl episode links', err); + return []; + } +}; diff --git a/providers/filmyfly/ffGetMeta.ts b/providers/filmyfly/ffGetMeta.ts new file mode 100644 index 0000000..616ee57 --- /dev/null +++ b/providers/filmyfly/ffGetMeta.ts @@ -0,0 +1,56 @@ +import {Info, Link, ProviderContext} from '../types'; + +export const ffGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, cheerio, commonHeaders: headers} = providerContext; + const url = link; + const res = await axios.get(url, {headers}); + const data = res.data; + const $ = cheerio.load(data); + const type = url.includes('tvshows') ? 'series' : 'movie'; + const imdbId = ''; + const title = $('.fname:contains("Name")').find('.colora').text().trim(); + const image = $('.ss').find('img').attr('src') || ''; + const synopsis = $('.fname:contains("Description")') + .find('.colorg') + .text() + .trim(); + const tags = + $('.fname:contains("Genre")').find('.colorb').text().split(',') || []; + const rating = ''; + const links: Link[] = []; + const downloadLink = $('.dlbtn').find('a').attr('href'); + if (downloadLink) { + links.push({ + title: title, + episodesLink: downloadLink, + }); + } + return { + title, + tags, + rating, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/filmyfly/ffGetPosts.ts b/providers/filmyfly/ffGetPosts.ts new file mode 100644 index 0000000..db7cfd6 --- /dev/null +++ b/providers/filmyfly/ffGetPosts.ts @@ -0,0 +1,77 @@ +import {Post, ProviderContext} from '../types'; + +export const ffGetPosts = async function ({ + filter, + page, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl} = providerContext; + const baseUrl = await getBaseUrl('filmyfly'); + const url = `${baseUrl + filter}/${page}`; + return posts({url, signal, baseUrl, providerContext}); +}; + +export const ffGetPostsSearch = async function ({ + searchQuery, + page, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + providerContext: ProviderContext; + signal: AbortSignal; +}): Promise { + const {getBaseUrl} = providerContext; + const baseUrl = await getBaseUrl('filmyfly'); + const url = `${baseUrl}/site-1.html?to-search=${searchQuery}`; + if (page > 1) { + return []; + } + return posts({url, signal, baseUrl, providerContext}); +}; + +async function posts({ + url, + signal, + baseUrl, + providerContext, +}: { + url: string; + signal: AbortSignal; + baseUrl: string; + providerContext: ProviderContext; +}): Promise { + try { + const {cheerio, commonHeaders: headers} = providerContext; + const res = await fetch(url, {headers, signal}); + const data = await res.text(); + const $ = cheerio.load(data); + const catalog: Post[] = []; + $('.A2,.A10,.fl').map((i, element) => { + const title = + $(element).find('a').eq(1).text() || $(element).find('b').text(); + const link = $(element).find('a').attr('href'); + const image = $(element).find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title, + link: baseUrl + link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('ff error ', err); + return []; + } +} diff --git a/providers/filmyfly/ffGetStream.ts b/providers/filmyfly/ffGetStream.ts new file mode 100644 index 0000000..8176a44 --- /dev/null +++ b/providers/filmyfly/ffGetStream.ts @@ -0,0 +1,51 @@ +import {Stream, ProviderContext} from '../types'; + +export const ffGetStream = async function ({ + link, + signal, + providerContext, +}: { + link: string; + type: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + try { + const res = await providerContext.axios.get(link, {signal}); + const data = res.data; + const $ = providerContext.cheerio.load(data); + const streams: Stream[] = []; + const elements = $('.button2,.button1,.button3,.button4,.button').toArray(); + const promises = elements.map(async element => { + const title = $(element).text(); + let link = $(element).attr('href'); + if (title.includes('GDFLIX') && link) { + const gdLinks = await providerContext.extractors.gdFlixExtracter( + link, + signal, + ); + streams.push(...gdLinks); + } + const alreadyAdded = streams.find(s => s.link === link); + if ( + title && + link && + !title.includes('Watch') && + !title.includes('Login') && + !title.includes('GoFile') && + !alreadyAdded + ) { + streams.push({ + server: title, + link: link, + type: 'mkv', + }); + } + }); + await Promise.all(promises); + return streams; + } catch (err) { + console.error(err); + return []; + } +}; diff --git a/providers/filmyfly/index.ts b/providers/filmyfly/index.ts new file mode 100644 index 0000000..255652d --- /dev/null +++ b/providers/filmyfly/index.ts @@ -0,0 +1,16 @@ +import {ProviderType} from '../types'; +import {ffCatalog, ffGenresList} from './ffCatalog'; +import {ffEpisodeLinks} from './ffGetEpisodes'; +import {ffGetInfo} from './ffGetMeta'; +import {ffGetPosts, ffGetPostsSearch} from './ffGetPosts'; +import {ffGetStream} from './ffGetStream'; + +export const filmyfly: ProviderType = { + catalog: ffCatalog, + genres: ffGenresList, + GetHomePosts: ffGetPosts, + GetMetaData: ffGetInfo, + GetSearchPosts: ffGetPostsSearch, + GetEpisodeLinks: ffEpisodeLinks, + GetStream: ffGetStream, +}; diff --git a/providers/flixhq/flixhqCatalog.ts b/providers/flixhq/flixhqCatalog.ts new file mode 100644 index 0000000..1f92cf0 --- /dev/null +++ b/providers/flixhq/flixhqCatalog.ts @@ -0,0 +1,16 @@ +export const flixhqCatalog = [ + { + title: 'Trending', + filter: '/trending', + }, + { + title: 'Movies', + filter: '/recent-movies', + }, + { + title: 'TV Shows', + filter: '/recent-shows', + }, +]; + +export const flixhqGenresList = []; diff --git a/providers/flixhq/flixhqGetInfo.ts b/providers/flixhq/flixhqGetInfo.ts new file mode 100644 index 0000000..816e089 --- /dev/null +++ b/providers/flixhq/flixhqGetInfo.ts @@ -0,0 +1,61 @@ +import {Info, Link, ProviderContext} from '../types'; + +export const flixhqGetInfo = async function ({ + link: id, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, getBaseUrl} = providerContext; + const baseUrl = await getBaseUrl('consumet'); + const url = `${baseUrl}/movies/flixhq/info?id=` + id; + const res = await axios.get(url); + const data = res.data; + const meta = { + title: data.title, + synopsis: data.description.replace(/<[^>]*>?/gm, '').trim(), + image: data.cover, + cast: data.casts, + rating: data.rating, + tags: [data?.type, data?.duration, data.releaseDate.split('-')[0]], + imdbId: '', + type: data.episodes.length > 1 ? 'series' : 'movie', + }; + + const links: Link['directLinks'] = []; + data.episodes.forEach((episode: any) => { + const title = episode?.number + ? 'Season-' + episode?.season + ' Ep-' + episode.number + : episode.title; + const link = episode.id + '*' + data.id; + if (link && title) { + links.push({ + title, + link, + }); + } + }); + + return { + ...meta, + linkList: [ + { + title: meta.title, + directLinks: links, + }, + ], + }; + } catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/flixhq/flixhqGetPosts.ts b/providers/flixhq/flixhqGetPosts.ts new file mode 100644 index 0000000..3fa438c --- /dev/null +++ b/providers/flixhq/flixhqGetPosts.ts @@ -0,0 +1,71 @@ +import {Post, ProviderContext} from '../types'; + +export const flixhqGetPosts = async function ({ + filter, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl} = providerContext; + const urlRes = await getBaseUrl('consumet'); + const baseUrl = urlRes + '/movies/flixhq'; + const url = `${baseUrl + filter}`; + return posts({url, signal, providerContext}); +}; + +export const flixhqGetSearchPost = async function ({ + searchQuery, + page, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl} = providerContext; + const urlRes = await getBaseUrl('consumet'); + const baseUrl = urlRes + '/movies/flixhq'; + const url = `${baseUrl}/${searchQuery}?page=${page}`; + return posts({url, signal, providerContext}); +}; + +async function posts({ + url, + signal, + providerContext, +}: { + url: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + try { + const {axios} = providerContext; + const res = await axios.get(url, {signal}); + const data = res.data?.results || res.data; + const catalog: Post[] = []; + data?.map((element: any) => { + const title = element.title; + const link = element.id; + const image = element.image; + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('flixhq error ', err); + return []; + } +} diff --git a/providers/flixhq/flixhqGetStream.ts b/providers/flixhq/flixhqGetStream.ts new file mode 100644 index 0000000..2f925e1 --- /dev/null +++ b/providers/flixhq/flixhqGetStream.ts @@ -0,0 +1,59 @@ +import {ProviderContext, Stream, TextTrackType} from '../types'; + +export const flixhqGetStream = async function ({ + link: id, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {getBaseUrl} = providerContext; + const episodeId = id.split('*')[0]; + const mediaId = id.split('*')[1]; + const baseUrl = await getBaseUrl('consumet'); + const serverUrl = `${baseUrl}/movies/flixhq/servers?episodeId=${episodeId}&mediaId=${mediaId}`; + const res = await fetch(serverUrl); + const servers = await res.json(); + const streamLinks: Stream[] = []; + for (const server of servers) { + const streamUrl = + `${baseUrl}/movies/flixhq/watch?server=` + + server.name + + '&episodeId=' + + episodeId + + '&mediaId=' + + mediaId; + const streamRes = await fetch(streamUrl); + const streamData = await streamRes.json(); + const subtitles: Stream['subtitles'] = []; + if (streamData?.sources?.length > 0) { + if (streamData.subtitles) { + streamData.subtitles.forEach((sub: {lang: string; url: string}) => { + subtitles.push({ + language: sub?.lang?.slice(0, 2) as any, + uri: sub?.url, + type: TextTrackType.VTT, + title: sub?.lang, + }); + }); + } + streamData.sources.forEach((source: any) => { + streamLinks.push({ + server: + server?.name + + '-' + + source?.quality?.replace('auto', 'MultiQuality'), + link: source.url, + type: source.isM3U8 ? 'm3u8' : 'mp4', + subtitles: subtitles, + }); + }); + } + } + return streamLinks; + } catch (err) { + console.error(err); + return []; + } +}; diff --git a/providers/flixhq/index.ts b/providers/flixhq/index.ts new file mode 100644 index 0000000..d6e95bf --- /dev/null +++ b/providers/flixhq/index.ts @@ -0,0 +1,25 @@ +import {ProviderType} from '../types'; +import {flixhqCatalog, flixhqGenresList} from './flixhqCatalog'; +import {flixhqGetInfo} from './flixhqGetInfo'; +import {flixhqGetPosts, flixhqGetSearchPost} from './flixhqGetPosts'; +import {flixhqGetStream} from './flixhqGetStream'; + +export const flixhq: ProviderType = { + catalog: flixhqCatalog, + genres: flixhqGenresList, + GetMetaData: flixhqGetInfo, + GetHomePosts: flixhqGetPosts, + GetStream: flixhqGetStream, + GetSearchPosts: flixhqGetSearchPost, + nonDownloadableServer: ['upcloud-MultiQuality', 'vidcloud-MultiQuality'], + nonStreamableServer: [ + 'upcloud-1080', + 'upcloud-720', + 'upcloud-480', + 'upcloud-360', + 'vidcloud-1080', + 'vidcloud-720', + 'vidcloud-480', + 'vidcloud-360', + ], +}; diff --git a/providers/gdflixExtractor.ts b/providers/gdflixExtractor.ts new file mode 100644 index 0000000..d94bafc --- /dev/null +++ b/providers/gdflixExtractor.ts @@ -0,0 +1,173 @@ +import axios from 'axios'; +import * as cheerio from 'cheerio'; +import {Stream} from './types'; +import {headers} from './headers'; + +export async function gdFlixExtracter(link: string, signal: AbortSignal) { + try { + const streamLinks: Stream[] = []; + const res = await axios(`${link}`, {headers, signal}); + console.log('gdFlixExtracter', link); + const data = res.data; + let $drive = cheerio.load(data); + // handle if redirected to another link + + if ($drive('body').attr('onload')?.includes('location.replace')) { + const newLink = $drive('body') + .attr('onload') + ?.split("location.replace('")?.[1] + .split("'")?.[0]; + + console.log('newLink', newLink); + if (newLink) { + const newRes = await axios.get(newLink, {headers, signal}); + $drive = cheerio.load(newRes.data); + } + } + + // try { + // const resumeBot = $drive('.fab.fa-artstation').prev().attr('href') || ''; + // console.log('resumeBot', resumeBot); + // const resumeBotRes = await axios.get(resumeBot, {headers}); + // const resumeBotToken = resumeBotRes.data.match( + // /formData\.append\('token', '([a-f0-9]+)'\)/, + // )[1]; + // const resumeBotBody = new FormData(); + // resumeBotBody.append('token', resumeBotToken); + // const resumeBotPath = resumeBotRes.data.match( + // /fetch\('\/download\?id=([a-zA-Z0-9\/+]+)'/, + // )[1]; + // const resumeBotBaseUrl = resumeBot.split('/download')[0]; + // // console.log( + // // 'resumeBotPath', + // // resumeBotBaseUrl + '/download?id=' + resumeBotPath, + // // ); + // // console.log('resumeBotBody', resumeBotToken); + + // const resumeBotDownload = await fetch( + // resumeBotBaseUrl + '/download?id=' + resumeBotPath, + // { + // method: 'POST', + // body: resumeBotBody, + // headers: { + // Referer: resumeBot, + // Cookie: 'PHPSESSID=7e9658ce7c805dab5bbcea9046f7f308', + // }, + // }, + // ); + // const resumeBotDownloadData = await resumeBotDownload.json(); + // console.log('resumeBotDownloadData', resumeBotDownloadData.url); + // streamLinks.push({ + // server: 'ResumeBot', + // link: resumeBotDownloadData.url, + // type: 'mkv', + // }); + // } catch (err) { + // console.log('ResumeBot link not found', err); + // } + + /// resume cloud + try { + const baseUrl = link.split('/').slice(0, 3).join('/'); + const resumeDrive = $drive('.btn-secondary').attr('href') || ''; + console.log('resumeDrive', resumeDrive); + if (resumeDrive.includes('indexbot')) { + const resumeBotRes = await axios.get(resumeDrive, {headers}); + const resumeBotToken = resumeBotRes.data.match( + /formData\.append\('token', '([a-f0-9]+)'\)/, + )[1]; + const resumeBotBody = new FormData(); + resumeBotBody.append('token', resumeBotToken); + const resumeBotPath = resumeBotRes.data.match( + /fetch\('\/download\?id=([a-zA-Z0-9\/+]+)'/, + )[1]; + const resumeBotBaseUrl = resumeDrive.split('/download')[0]; + // console.log( + // 'resumeBotPath', + // resumeBotBaseUrl + '/download?id=' + resumeBotPath, + // ); + // console.log('resumeBotBody', resumeBotToken); + + const resumeBotDownload = await fetch( + resumeBotBaseUrl + '/download?id=' + resumeBotPath, + { + method: 'POST', + body: resumeBotBody, + headers: { + Referer: resumeDrive, + Cookie: 'PHPSESSID=7e9658ce7c805dab5bbcea9046f7f308', + }, + }, + ); + const resumeBotDownloadData = await resumeBotDownload.json(); + console.log('resumeBotDownloadData', resumeBotDownloadData.url); + streamLinks.push({ + server: 'ResumeBot', + link: resumeBotDownloadData.url, + type: 'mkv', + }); + } else { + const url = baseUrl + resumeDrive; + const resumeDriveRes = await axios.get(url, {headers}); + const resumeDriveHtml = resumeDriveRes.data; + const $resumeDrive = cheerio.load(resumeDriveHtml); + const resumeLink = $resumeDrive('.btn-success').attr('href'); + // console.log('resumeLink', resumeLink); + if (resumeLink) { + streamLinks.push({ + server: 'ResumeCloud', + link: resumeLink, + type: 'mkv', + }); + } + } + } catch (err) { + console.log('Resume link not found'); + } + + //instant link + try { + const seed = $drive('.btn-danger').attr('href') || ''; + console.log('seed', seed); + if (!seed.includes('?url=')) { + const newLinkRes = await axios.head(seed, {headers, signal}); + console.log('newLinkRes', newLinkRes.request?.responseURL); + const newLink = + newLinkRes.request?.responseURL?.split('?url=')?.[1] || seed; + streamLinks.push({server: 'G-Drive', link: newLink, type: 'mkv'}); + } else { + const instantToken = seed.split('=')[1]; + // console.log('InstantToken', instantToken); + const InstantFromData = new FormData(); + InstantFromData.append('keys', instantToken); + const videoSeedUrl = seed.split('/').slice(0, 3).join('/') + '/api'; + // console.log('videoSeedUrl', videoSeedUrl); + const instantLinkRes = await fetch(videoSeedUrl, { + method: 'POST', + body: InstantFromData, + headers: { + 'x-token': videoSeedUrl, + }, + }); + const instantLinkData = await instantLinkRes.json(); + // console.log('instantLinkData', instantLinkData); + if (instantLinkData.error === false) { + const instantLink = instantLinkData.url; + streamLinks.push({ + server: 'Gdrive-Instant', + link: instantLink, + type: 'mkv', + }); + } else { + console.log('Instant link not found', instantLinkData); + } + } + } catch (err) { + console.log('Instant link not found', err); + } + return streamLinks; + } catch (error) { + console.log('gdflix error: ', error); + return []; + } +} diff --git a/providers/getBaseUrl.ts b/providers/getBaseUrl.ts new file mode 100644 index 0000000..265504a --- /dev/null +++ b/providers/getBaseUrl.ts @@ -0,0 +1,35 @@ +import { cacheStorageService } from '../storage'; + +// 1 hour +const expireTime = 60 * 60 * 1000; + +export const getBaseUrl = async (providerValue: string) => { + try { + let baseUrl = ''; + const cacheKey = 'CacheBaseUrl' + providerValue; + const timeKey = 'baseUrlTime' + providerValue; + + const cachedUrl = cacheStorageService.getString(cacheKey); + const cachedTime = cacheStorageService.getObject(timeKey); + + if ( + cachedUrl && + cachedTime && + Date.now() - cachedTime < expireTime + ) { + baseUrl = cachedUrl; + } else { + const baseUrlRes = await fetch( + 'https://himanshu8443.github.io/providers/modflix.json', + ); + const baseUrlData = await baseUrlRes.json(); + baseUrl = baseUrlData[providerValue].url; + cacheStorageService.setString(cacheKey, baseUrl); + cacheStorageService.setObject(timeKey, Date.now()); + } + return baseUrl; + } catch (error) { + console.error(`Error fetching baseUrl: ${providerValue}`, error); + return ''; + } +}; diff --git a/providers/gofileExtracter.ts b/providers/gofileExtracter.ts new file mode 100644 index 0000000..a3fdafa --- /dev/null +++ b/providers/gofileExtracter.ts @@ -0,0 +1,38 @@ +import axios from 'axios'; + +export async function gofileExtracter( + id: string, +): Promise<{link: string; token: string}> { + try { + const gofileRes = await axios.get('https://gofile.io/d/' + id); + const genAccountres = await axios.post('https://api.gofile.io/accounts'); + const token = genAccountres.data.data.token; + console.log('gofile token', token); + + const wtRes = await axios.get('https://gofile.io/dist/js/global.js'); + const wt = wtRes.data.match(/appdata\.wt\s*=\s*["']([^"']+)["']/)[1]; + console.log('gofile wt', wt); + + const res = await axios.get( + `https://api.gofile.io/contents/${id}?wt=${wt}`, + { + headers: { + Authorization: `Bearer ${token}`, + }, + }, + ); + const oId = Object.keys(res.data.data.children)[0]; + console.log('gofile extracter', res.data.data.children[oId].link); + const link = res.data.data.children[oId].link; + return { + link, + token, + }; + } catch (e) { + console.log('gofile extracter err', e); + return { + link: '', + token: '', + }; + } +} diff --git a/providers/guardahd/GetGuardahdStream.ts b/providers/guardahd/GetGuardahdStream.ts new file mode 100644 index 0000000..43df469 --- /dev/null +++ b/providers/guardahd/GetGuardahdStream.ts @@ -0,0 +1,133 @@ +import {ProviderContext, Stream} from '../types'; + +export const GuardahdGetStream = async function ({ + link: id, + type, + providerContext, +}: { + link: string; + type: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, cheerio, extractors} = providerContext; + const {superVideoExtractor} = extractors; + async function ExtractGuardahd({ + imdb, // type, + // episode, + } // season, + : { + imdb: string; + type: string; + season: string; + episode: string; + }) { + try { + const baseUrl = 'https://guardahd.stream'; + const path = '/set-movie-a/' + imdb; + const url = baseUrl + path; + + console.log('url:', url); + const res = await axios.get(url, {timeout: 4000}); + const html = res.data; + const $ = cheerio.load(html); + const superVideoUrl = $('li:contains("supervideo")').attr('data-link'); + console.log('superVideoUrl:', superVideoUrl); + + if (!superVideoUrl) { + return null; + } + const controller2 = new AbortController(); + const signal2 = controller2.signal; + setTimeout(() => controller2.abort(), 4000); + const res2 = await fetch('https:' + superVideoUrl, {signal: signal2}); + const data = await res2.text(); + // console.log('mostraguarda data:', data); + const streamUrl = await superVideoExtractor(data); + return streamUrl; + } catch (err) { + console.error('Error in GetMostraguardaStram:', err); + } + } + async function GetMostraguardaStream({ + imdb, + type, + season, + episode, + }: { + imdb: string; + type: string; + season: string; + episode: string; + }) { + try { + const baseUrl = 'https://mostraguarda.stream'; + const path = + type === 'tv' + ? `/serie/${imdb}/${season}/${episode}` + : `/movie/${imdb}`; + const url = baseUrl + path; + + console.log('url:', url); + + const res = await axios(url, {timeout: 4000}); + const html = res.data; + const $ = cheerio.load(html); + const superVideoUrl = $('li:contains("supervideo")').attr('data-link'); + console.log('superVideoUrl:', superVideoUrl); + + if (!superVideoUrl) { + return null; + } + const controller2 = new AbortController(); + const signal2 = controller2.signal; + setTimeout(() => controller2.abort(), 4000); + const res2 = await fetch('https:' + superVideoUrl, {signal: signal2}); + const data = await res2.text(); + // console.log('mostraguarda data:', data); + const streamUrl = await superVideoExtractor(data); + return streamUrl; + } catch (err) { + console.error('Error in GetMostraguardaStram:', err); + } + } + console.log(id); + const streams: Stream[] = []; + const {imdbId, season, episode} = JSON.parse(id); + + ///// mostraguarda + const mostraguardaStream = await GetMostraguardaStream({ + imdb: imdbId, + type: type, + season: season, + episode: episode, + }); + if (mostraguardaStream) { + streams.push({ + server: 'Supervideo 1', + link: mostraguardaStream, + type: 'm3u8', + }); + } + + const guardahdStream = await ExtractGuardahd({ + imdb: imdbId, + type: type, + season: season, + episode: episode, + }); + + if (guardahdStream) { + streams.push({ + server: 'Supervideo 2', + link: guardahdStream, + type: 'm3u8', + }); + } + + return streams; + } catch (err) { + console.error(err); + return []; + } +}; diff --git a/providers/guardahd/guardahdCatalog.ts b/providers/guardahd/guardahdCatalog.ts new file mode 100644 index 0000000..07454a5 --- /dev/null +++ b/providers/guardahd/guardahdCatalog.ts @@ -0,0 +1,12 @@ +export const guardahdCatalog = [ + { + title: 'Popular Movies', + filter: '/top/catalog/movie/top.json', + }, + { + title: 'Featured Movies', + filter: '/imdbRating/catalog/movie/imdbRating.json', + }, +]; + +export const guardahdGenresList = []; diff --git a/providers/guardahd/guardahdGetPosts.ts b/providers/guardahd/guardahdGetPosts.ts new file mode 100644 index 0000000..1788965 --- /dev/null +++ b/providers/guardahd/guardahdGetPosts.ts @@ -0,0 +1,44 @@ +import {Post, ProviderContext} from '../types'; + +export const guardahdGetSearchPosts = async function ({ + searchQuery, + page, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + providerContext: ProviderContext; + signal: AbortSignal; +}): Promise { + try { + const {axios, commonHeaders: headers} = providerContext; + if (page > 1) { + return []; + } + const catalog: Post[] = []; + const url2 = `https://v3-cinemeta.strem.io/catalog/movie/top/search=${encodeURI( + searchQuery, + )}.json`; + const res2 = await axios.get(url2, {headers, signal}); + const data2 = res2.data; + data2?.metas.map((result: any) => { + const title = result?.name || ''; + const id = result?.imdb_id || result?.id; + const image = result?.poster; + const type = result?.type; + if (id) { + catalog.push({ + title: title, + link: `https://v3-cinemeta.strem.io/meta/${type}/${id}.json`, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('AutoEmbed error ', err); + return []; + } +}; diff --git a/providers/guardahd/index.ts b/providers/guardahd/index.ts new file mode 100644 index 0000000..1a16b2d --- /dev/null +++ b/providers/guardahd/index.ts @@ -0,0 +1,15 @@ +import {guardahdCatalog, guardahdGenresList} from './guardahdCatalog'; +import {allGetInfo} from '../autoEmbed/allGetInfo'; +import {allGetPost} from '../autoEmbed/allGetPost'; +import {guardahdGetSearchPosts} from './guardahdGetPosts'; +import {ProviderType} from '../types'; +import {GuardahdGetStream} from './GetGuardahdStream'; + +export const guardahd: ProviderType = { + catalog: guardahdCatalog, + genres: guardahdGenresList, + GetMetaData: allGetInfo, + GetHomePosts: allGetPost, + GetStream: GuardahdGetStream, + GetSearchPosts: guardahdGetSearchPosts, +}; diff --git a/providers/hdhub4u/hdhub4uGetSteam.ts b/providers/hdhub4u/hdhub4uGetSteam.ts new file mode 100644 index 0000000..8ebb144 --- /dev/null +++ b/providers/hdhub4u/hdhub4uGetSteam.ts @@ -0,0 +1,183 @@ +import {ProviderContext} from '../types'; + +export async function hdhub4uGetStream({ + link, + signal, + providerContext, +}: { + link: string; + type: string; + signal: AbortSignal; + providerContext: ProviderContext; +}) { + const {axios, cheerio, extractors, commonHeaders: headers} = providerContext; + const {hubcloudExtracter} = extractors; + let hubdriveLink = ''; + if (link.includes('hubdrive')) { + const hubdriveRes = await axios.get(link, {headers, signal}); + const hubdriveText = hubdriveRes.data; + const $ = cheerio.load(hubdriveText); + hubdriveLink = + $('.btn.btn-primary.btn-user.btn-success1.m-1').attr('href') || link; + } else { + const res = await axios.get(link, {headers, signal}); + const text = res.data; + const encryptedString = text.split("s('o','")?.[1]?.split("',180")?.[0]; + const decodedString: any = decodeString(encryptedString); + link = atob(decodedString?.o); + const redirectLink = await getRedirectLinks(link, signal, headers); + const redirectLinkRes = await axios.get(redirectLink, {headers, signal}); + const redirectLinkText = redirectLinkRes.data; + const $ = cheerio.load(redirectLinkText); + hubdriveLink = + $('h3:contains("1080p")').find('a').attr('href') || + redirectLinkText.match( + /href="(https:\/\/hubcloud\.[^\/]+\/drive\/[^"]+)"/, + )[1]; + if (hubdriveLink.includes('hubdrive')) { + const hubdriveRes = await axios.get(hubdriveLink, {headers, signal}); + const hubdriveText = hubdriveRes.data; + const $$ = cheerio.load(hubdriveText); + hubdriveLink = + $$('.btn.btn-primary.btn-user.btn-success1.m-1').attr('href') || + hubdriveLink; + } + } + const hubdriveLinkRes = await axios.get(hubdriveLink, {headers, signal}); + const hubcloudText = hubdriveLinkRes.data; + const hubcloudLink = + hubcloudText.match( + //i, + )?.[1] || hubdriveLink; + try { + return await hubcloudExtracter(hubcloudLink, signal); + } catch (error: any) { + console.log('hd hub 4 getStream error: ', error); + return []; + } +} + +const encode = function (value: string) { + return btoa(value.toString()); +}; +const decode = function (value: string) { + if (value === undefined) { + return ''; + } + return atob(value.toString()); +}; +const pen = function (value: string) { + return value.replace(/[a-zA-Z]/g, function (_0x1a470e: any) { + return String.fromCharCode( + (_0x1a470e <= 'Z' ? 90 : 122) >= + (_0x1a470e = _0x1a470e.charCodeAt(0) + 13) + ? _0x1a470e + : _0x1a470e - 26, + ); + }); +}; + +const abortableTimeout = ( + ms: number, + {signal}: {signal?: AbortSignal} = {}, +) => { + return new Promise((resolve, reject) => { + if (signal && signal.aborted) { + return reject(new Error('Aborted')); + } + + const timer = setTimeout(resolve, ms); + + if (signal) { + signal.addEventListener('abort', () => { + clearTimeout(timer); + reject(new Error('Aborted')); + }); + } + }); +}; + +export async function getRedirectLinks( + link: string, + signal: AbortSignal, + headers: any, +) { + try { + const res = await fetch(link, {headers, signal}); + const resText = await res.text(); + + var regex = /ck\('_wp_http_\d+','([^']+)'/g; + var combinedString = ''; + + var match; + while ((match = regex.exec(resText)) !== null) { + // console.log(match[1]); + combinedString += match[1]; + } + // console.log(decode(combinedString)); + const decodedString = decode(pen(decode(decode(combinedString)))); + // console.log(decodedString); + const data = JSON.parse(decodedString); + console.log(data); + const token = encode(data?.data); + const blogLink = data?.wp_http1 + '?re=' + token; + // abort timeout on signal + let wait = abortableTimeout((Number(data?.total_time) + 3) * 1000, { + signal, + }); + + await wait; + console.log('blogLink', blogLink); + + let vcloudLink = 'Invalid Request'; + while (vcloudLink.includes('Invalid Request')) { + const blogRes = await fetch(blogLink, {headers, signal}); + const blogResText = (await blogRes.text()) as any; + if (blogResText.includes('Invalid Request')) { + console.log(blogResText); + } else { + vcloudLink = blogResText.match(/var reurl = "([^"]+)"/) || ''; + break; + } + } + + // console.log('vcloudLink', vcloudLink?.[1]); + return blogLink || link; + } catch (err) { + console.log('Error in getRedirectLinks', err); + return link; + } +} + +function rot13(str: string) { + return str.replace(/[a-zA-Z]/g, function (char) { + const charCode = char.charCodeAt(0); + const isUpperCase = char <= 'Z'; + const baseCharCode = isUpperCase ? 65 : 97; + return String.fromCharCode( + ((charCode - baseCharCode + 13) % 26) + baseCharCode, + ); + }); +} + +export function decodeString(encryptedString: string) { + try { + // First base64 decode + let decoded = atob(encryptedString); + + // Second base64 decode + decoded = atob(decoded); + + // ROT13 decode + decoded = rot13(decoded); + + // Third base64 decode + decoded = atob(decoded); + + // Parse JSON + return JSON.parse(decoded); + } catch (error) { + console.error('Error decoding string:', error); + return null; + } +} diff --git a/providers/hdhub4u/hdhubCatalog.ts b/providers/hdhub4u/hdhubCatalog.ts new file mode 100644 index 0000000..d4488cf --- /dev/null +++ b/providers/hdhub4u/hdhubCatalog.ts @@ -0,0 +1,61 @@ +export const hdhub4uCatalog = [ + { + title: 'Latest', + filter: '', + }, + { + title: 'Web Series', + filter: '/category/web-series', + }, + { + title: 'Hollywood ', + filter: '/category/hollywood-movies', + }, + { + title: 'South Movies', + filter: '/category/south-hindi-movies', + }, +]; + +export const hdhub4uGenresList = [ + { + title: 'Action', + filter: '/category/action', + }, + { + title: 'Crime', + filter: '/category/crime', + }, + { + title: 'Comedy', + filter: '/category/comedy', + }, + { + title: 'Drama', + filter: '/category/drama', + }, + { + title: 'Horror', + filter: '/category/horror', + }, + { + title: 'Family', + filter: '/category/family', + }, + { + title: 'Sci-Fi', + filter: '/category/sifi', + }, + { + title: 'Thriller', + filter: '/category/triller', + }, + { + title: 'Romance', + filter: '/category/romance', + }, + { + title: 'Fight', + filter: '/category/fight', + }, +]; diff --git a/providers/hdhub4u/hdhubGetInfo.ts b/providers/hdhub4u/hdhubGetInfo.ts new file mode 100644 index 0000000..1670867 --- /dev/null +++ b/providers/hdhub4u/hdhubGetInfo.ts @@ -0,0 +1,129 @@ +import {Info, Link, ProviderContext} from '../types'; + +const hdbHeaders = { + Cookie: 'xla=s4t', + Referer: 'https://google.com', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0', +}; +export const hdhub4uGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, cheerio} = providerContext; + const url = link; + const res = await axios.get(url, {headers: hdbHeaders}); + const data = res.data; + const $ = cheerio.load(data); + const container = $('.page-body'); + const imdbId = + container + .find('a[href*="imdb.com/title/tt"]:not([href*="imdb.com/title/tt/"])') + .attr('href') + ?.split('/')[4] || ''; + const title = container + .find( + 'h2[data-ved="2ahUKEwjL0NrBk4vnAhWlH7cAHRCeAlwQ3B0oATAfegQIFBAM"],h2[data-ved="2ahUKEwiP0pGdlermAhUFYVAKHV8tAmgQ3B0oATAZegQIDhAM"]', + ) + .text(); + const type = title.toLocaleLowerCase().includes('season') + ? 'series' + : 'movie'; + const synopsis = container + .find('strong:contains("DESCRIPTION")') + .parent() + .text() + .replace('DESCRIPTION:', ''); + const image = container.find('img[decoding="async"]').attr('src') || ''; + + // Links + const links: Link[] = []; + const directLink: Link['directLinks'] = []; + + // direct link type + $('strong:contains("EPiSODE")').map((i, element) => { + const epTitle = $(element).parent().parent().text(); + const episodesLink = + $(element) + .parent() + .parent() + .parent() + .next() + .next() + .find('a') + .attr('href') || + $(element).parent().parent().parent().next().find('a').attr('href'); + + if (episodesLink && episodesLink) { + directLink.push({ + title: epTitle, + link: episodesLink, + }); + } + }); + + if (directLink.length === 0) { + container.find('a:contains("EPiSODE")').map((i, element) => { + const epTitle = $(element).text(); + const episodesLink = $(element).attr('href'); + if (episodesLink) { + directLink.push({ + title: epTitle.toLocaleUpperCase(), + link: episodesLink, + }); + } + }); + } + if (directLink.length > 0) { + links.push({ + title: title, + directLinks: directLink, + }); + } + if (directLink.length === 0) { + container + .find( + 'a:contains("480"),a:contains("720"),a:contains("1080"),a:contains("2160"),a:contains("4K")', + ) + .map((i, element) => { + const quality = + $(element) + .text() + .match(/\b(480p|720p|1080p|2160p)\b/i)?.[0] || ''; + const movieLinks = $(element).attr('href'); + const title = $(element).text(); + if (movieLinks) { + links.push({ + directLinks: [{link: movieLinks, title: 'Movie', type: 'movie'}], + quality: quality, + title: title, + }); + } + }); + } + + // console.log('drive meta', title, synopsis, image, imdbId, type, links); + return { + title, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/hdhub4u/hdhubGetPosts.ts b/providers/hdhub4u/hdhubGetPosts.ts new file mode 100644 index 0000000..52b8392 --- /dev/null +++ b/providers/hdhub4u/hdhubGetPosts.ts @@ -0,0 +1,84 @@ +import {Post, ProviderContext} from '../types'; + +const hdbHeaders = { + Cookie: 'xla=s4t', + Referer: 'https://google.com', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0', +}; + +export const hdhubGetPosts = async function ({ + filter, + page, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + providerContext: ProviderContext; + signal: AbortSignal; +}): Promise { + const {getBaseUrl} = providerContext; + const baseUrl = await getBaseUrl('hdhub'); + const url = `${baseUrl + filter}/page/${page}/`; + return posts({url, signal, providerContext}); +}; + +export const hdhubGetPostsSearch = async function ({ + searchQuery, + page, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + providerContext: ProviderContext; + signal: AbortSignal; +}): Promise { + const {getBaseUrl} = providerContext; + const baseUrl = await getBaseUrl('hdhub'); + const url = `${baseUrl}/page/${page}/?s=${searchQuery}`; + return posts({url, signal, providerContext}); +}; + +async function posts({ + url, + signal, + providerContext, +}: { + url: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {cheerio} = providerContext; + try { + const res = await fetch(url, { + headers: hdbHeaders, + signal, + }); + const data = await res.text(); + const $ = cheerio.load(data); + const catalog: Post[] = []; + $('.recent-movies') + .children() + .map((i, element) => { + const title = $(element).find('figure').find('img').attr('alt'); + const link = $(element).find('a').attr('href'); + const image = $(element).find('figure').find('img').attr('src'); + + if (title && link && image) { + catalog.push({ + title: title.replace('Download', '').trim(), + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('hdhubGetPosts error ', err); + return []; + } +} diff --git a/providers/hdhub4u/index.ts b/providers/hdhub4u/index.ts new file mode 100644 index 0000000..547a4fd --- /dev/null +++ b/providers/hdhub4u/index.ts @@ -0,0 +1,14 @@ +import {hdhub4uCatalog, hdhub4uGenresList} from './hdhubCatalog'; +import {hdhub4uGetInfo} from './hdhubGetInfo'; +import {hdhub4uGetStream} from './hdhub4uGetSteam'; +import {hdhubGetPosts, hdhubGetPostsSearch} from './hdhubGetPosts'; +import {ProviderType} from '../types'; + +export const hdhub4uProvider: ProviderType = { + catalog: hdhub4uCatalog, + genres: hdhub4uGenresList, + GetMetaData: hdhub4uGetInfo, + GetStream: hdhub4uGetStream, + GetHomePosts: hdhubGetPosts, + GetSearchPosts: hdhubGetPostsSearch, +}; diff --git a/providers/headers.ts b/providers/headers.ts new file mode 100644 index 0000000..e856108 --- /dev/null +++ b/providers/headers.ts @@ -0,0 +1,10 @@ +export const headers = { + 'sec-ch-ua': + '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + // 'Sec-Fetch-Site': 'none', + // 'Sec-Fetch-User': '?1', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', +}; diff --git a/providers/hiAnime/HiGetSteam.ts b/providers/hiAnime/HiGetSteam.ts new file mode 100644 index 0000000..6127a21 --- /dev/null +++ b/providers/hiAnime/HiGetSteam.ts @@ -0,0 +1,56 @@ +import {Stream, ProviderContext, TextTracks, TextTrackType} from '../types'; + +export const hiGetStream = async function ({ + link: id, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {getBaseUrl, axios} = providerContext; + const baseUrl = await getBaseUrl('consumet'); + const servers = ['vidcloud', 'vidstreaming']; + const url = `${baseUrl}/anime/zoro/watch?episodeId=${id}&server=`; + const streamLinks: Stream[] = []; + await Promise.all( + servers.map(async server => { + try { + const res = await axios.get(url + server); + if (res.data) { + const subtitles: TextTracks = []; + res.data?.subtitles.forEach((sub: any) => { + if (sub?.lang === 'Thumbnails') return; + subtitles.push({ + language: sub?.lang?.slice(0, 2) || 'Und', + uri: sub?.url, + title: sub?.lang || 'Undefined', + type: sub?.url?.endsWith('.vtt') + ? TextTrackType.VTT + : TextTrackType.SUBRIP, + }); + }); + res.data?.sources.forEach((source: any) => { + streamLinks.push({ + server: server, + link: source?.url, + type: source?.isM3U8 ? 'm3u8' : 'mp4', + headers: { + Referer: 'https://megacloud.club/', + Origin: 'https://megacloud.club', + }, + subtitles: subtitles, + }); + }); + } + } catch (e) { + console.log(e); + } + }), + ); + return streamLinks; + } catch (err) { + console.error(err); + return []; + } +}; diff --git a/providers/hiAnime/hiCatalog.ts b/providers/hiAnime/hiCatalog.ts new file mode 100644 index 0000000..555f5f7 --- /dev/null +++ b/providers/hiAnime/hiCatalog.ts @@ -0,0 +1,20 @@ +export const hiCatalog = [ + { + title: 'Recent', + filter: '/anime/zoro/recent-episodes', + }, + { + title: 'Top Airing', + filter: '/anime/zoro/top-airing', + }, + { + title: 'Most Popular', + filter: '/anime/zoro/most-popular', + }, + { + title: 'Most Favorited', + filter: '/anime/zoro/most-favorite', + }, +]; + +export const hiGenresList = []; diff --git a/providers/hiAnime/hiGetInfo.ts b/providers/hiAnime/hiGetInfo.ts new file mode 100644 index 0000000..a29a74c --- /dev/null +++ b/providers/hiAnime/hiGetInfo.ts @@ -0,0 +1,83 @@ +import {Info, Link, ProviderContext} from '../types'; + +export const hiGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {getBaseUrl, axios} = providerContext; + const baseUrl = await getBaseUrl('consumet'); + const url = `${baseUrl}/anime/zoro/info?id=` + link; + const res = await axios.get(url); + const data = res.data; + const meta = { + title: data.title, + synopsis: data.description, + image: data.image, + tags: [ + data?.type, + data?.subOrDub === 'both' ? 'Sub And Dub' : data?.subOrDub, + ], + imdbId: '', + type: data.episodes.length > 0 ? 'series' : 'movie', + }; + const linkList: Link[] = []; + const subLinks: Link['directLinks'] = []; + data.episodes.forEach((episode: any) => { + if (!episode?.isSubbed) { + return; + } + const title = + 'Episode ' + episode.number + (episode?.isFiller ? ' (Filler)' : ''); + const link = episode.id + '$sub'; + if (link && title) { + subLinks.push({ + title, + link, + }); + } + }); + linkList.push({ + title: meta.title + ' (Sub)', + directLinks: subLinks, + }); + if (data?.subOrDub === 'both') { + const dubLinks: Link['directLinks'] = []; + data.episodes.forEach((episode: any) => { + if (!episode?.isDubbed) { + return; + } + const title = + 'Episode ' + episode.number + (episode?.isFiller ? ' (Filler)' : ''); + const link = episode.id + '$dub'; + if (link && title) { + dubLinks.push({ + title, + link, + }); + } + }); + linkList.push({ + title: meta.title + ' (Dub)', + directLinks: dubLinks, + }); + } + return { + ...meta, + linkList: linkList, + }; + } catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/hiAnime/hiGetPosts.ts b/providers/hiAnime/hiGetPosts.ts new file mode 100644 index 0000000..746c3ab --- /dev/null +++ b/providers/hiAnime/hiGetPosts.ts @@ -0,0 +1,69 @@ +import {Post, ProviderContext} from '../types'; + +export const hiGetPosts = async function ({ + filter, + page, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios} = providerContext; + const baseUrl = await getBaseUrl('consumet'); + const url = `${baseUrl + filter}?page=${page}`; + return posts({url, signal, axios}); +}; + +export const hiGetPostsSearch = async function ({ + searchQuery, + page, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios} = providerContext; + const baseUrl = await getBaseUrl('consumet'); + const url = `${baseUrl}/anime/zoro/${searchQuery}?page=${page}`; + return posts({url, signal, axios}); +}; + +async function posts({ + url, + signal, + axios, +}: { + url: string; + signal: AbortSignal; + axios: ProviderContext['axios']; +}): Promise { + try { + const res = await axios.get(url, {signal}); + const data = res.data?.results; + const catalog: Post[] = []; + data?.map((element: any) => { + const title = element.title; + const link = element.id; + const image = element.image; + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('zoro error ', err); + return []; + } +} diff --git a/providers/hiAnime/index.ts b/providers/hiAnime/index.ts new file mode 100644 index 0000000..181be5b --- /dev/null +++ b/providers/hiAnime/index.ts @@ -0,0 +1,14 @@ +import {hiGetInfo} from './hiGetInfo'; +import {hiCatalog, hiGenresList} from './hiCatalog'; +import {hiGetStream} from './HiGetSteam'; +import {hiGetPosts, hiGetPostsSearch} from './hiGetPosts'; +import {ProviderType} from '../types'; + +export const HiAnime: ProviderType = { + catalog: hiCatalog, + genres: hiGenresList, + GetMetaData: hiGetInfo, + GetHomePosts: hiGetPosts, + GetStream: hiGetStream, + GetSearchPosts: hiGetPostsSearch, +}; diff --git a/providers/hubcloudExtractor.ts b/providers/hubcloudExtractor.ts new file mode 100644 index 0000000..129fb24 --- /dev/null +++ b/providers/hubcloudExtractor.ts @@ -0,0 +1,85 @@ +import axios from 'axios'; +import * as cheerio from 'cheerio'; +import {Stream} from './types'; +import {headers} from './headers'; + +const decode = function (value: string) { + if (value === undefined) { + return ''; + } + return atob(value.toString()); +}; + +export async function hubcloudExtracter(link: string, signal: AbortSignal) { + try { + console.log('hubcloudExtracter', link); + const baseUrl = link.split('/').slice(0, 3).join('/'); + const streamLinks: Stream[] = []; + const vLinkRes = await axios(`${link}`, {headers, signal}); + const vLinkText = vLinkRes.data; + const $vLink = cheerio.load(vLinkText); + const vLinkRedirect = vLinkText.match(/var\s+url\s*=\s*'([^']+)';/) || []; + let vcloudLink = + decode(vLinkRedirect[1]?.split('r=')?.[1]) || + vLinkRedirect[1] || + $vLink('.fa-file-download.fa-lg').parent().attr('href') || + link; + console.log('vcloudLink', vcloudLink); + if (vcloudLink?.startsWith('/')) { + vcloudLink = `${baseUrl}${vcloudLink}`; + console.log('New vcloudLink', vcloudLink); + } + const vcloudRes = await fetch(vcloudLink, { + headers, + signal, + redirect: 'follow', + }); + const $ = cheerio.load(await vcloudRes.text()); + // console.log('vcloudRes', $.text()); + + const linkClass = $('.btn-success.btn-lg.h6,.btn-danger,.btn-secondary'); + for (const element of linkClass) { + const itm = $(element); + let link = itm.attr('href') || ''; + if (link?.includes('.dev') && !link?.includes('/?id=')) { + streamLinks.push({server: 'Cf Worker', link: link, type: 'mkv'}); + } + if (link?.includes('pixeld')) { + if (!link?.includes('api')) { + const token = link.split('/').pop(); + const baseUrl = link.split('/').slice(0, -2).join('/'); + link = `${baseUrl}/api/file/${token}?download`; + } + streamLinks.push({server: 'Pixeldrain', link: link, type: 'mkv'}); + } + if (link?.includes('hubcloud') || link?.includes('/?id=')) { + try { + const newLinkRes = await axios.head(link, {headers, signal}); + const newLink = + newLinkRes.request?.responseURL?.split('link=')?.[1] || link; + streamLinks.push({server: 'hubcloud', link: newLink, type: 'mkv'}); + } catch (error) { + console.log('hubcloudExtracter error in hubcloud link: ', error); + } + } + if (link?.includes('cloudflarestorage')) { + streamLinks.push({server: 'CfStorage', link: link, type: 'mkv'}); + } + if (link?.includes('fastdl')) { + streamLinks.push({server: 'FastDl', link: link, type: 'mkv'}); + } + if (link.includes('hubcdn')) { + streamLinks.push({ + server: 'HubCdn', + link: link, + type: 'mkv', + }); + } + } + console.log('streamLinks', streamLinks); + return streamLinks; + } catch (error) { + console.log('hubcloudExtracter error: ', error); + return []; + } +} diff --git a/providers/katmovies/index.ts b/providers/katmovies/index.ts new file mode 100644 index 0000000..1fef967 --- /dev/null +++ b/providers/katmovies/index.ts @@ -0,0 +1,16 @@ +import {katCatalog, katGenresList} from './katCatalog'; +import {katEpisodeLinks} from './katGetEpsodes'; +import {katGetInfo} from './katGetInfo'; +import {katGetPosts, katGetPostsSearch} from './katGetPosts'; +import {katGetStream} from './katGetSteam'; +import {ProviderType} from '../types'; + +export const katMoviesHd: ProviderType = { + catalog: katCatalog, + genres: katGenresList, + GetMetaData: katGetInfo, + GetHomePosts: katGetPosts, + GetStream: katGetStream, + GetEpisodeLinks: katEpisodeLinks, + GetSearchPosts: katGetPostsSearch, +}; diff --git a/providers/katmovies/katCatalog.ts b/providers/katmovies/katCatalog.ts new file mode 100644 index 0000000..e328c61 --- /dev/null +++ b/providers/katmovies/katCatalog.ts @@ -0,0 +1,61 @@ +export const katCatalog = [ + { + title: 'Latest', + filter: '', + }, + { + title: 'Netflix', + filter: '/category/netflix', + }, + { + title: 'Animated', + filter: '/category/animated', + }, + { + title: 'Amazon Prime', + filter: '/category/amazon-prime', + }, +]; + +export const katGenresList = [ + { + title: 'Action', + filter: '/category/action', + }, + { + title: 'Crime', + filter: '/category/crime', + }, + { + title: 'Comedy', + filter: '/category/comedy', + }, + { + title: 'Drama', + filter: '/category/drama', + }, + { + title: 'Horror', + filter: '/category/horror', + }, + { + title: 'Family', + filter: '/category/family', + }, + { + title: 'Sci-Fi', + filter: '/category/sifi', + }, + { + title: 'Thriller', + filter: '/category/triller', + }, + { + title: 'Romance', + filter: '/category/romance', + }, + { + title: 'Fight', + filter: '/category/fight', + }, +]; diff --git a/providers/katmovies/katGetEpsodes.ts b/providers/katmovies/katGetEpsodes.ts new file mode 100644 index 0000000..932200f --- /dev/null +++ b/providers/katmovies/katGetEpsodes.ts @@ -0,0 +1,84 @@ +import {EpisodeLink, ProviderContext} from '../types'; + +export const katEpisodeLinks = async function ({ + url, + providerContext, +}: { + url: string; + providerContext: ProviderContext; +}): Promise { + const {axios, cheerio} = providerContext; + const episodesLink: EpisodeLink[] = []; + try { + if (url.includes('gdflix')) { + const baseUrl = url.split('/pack')?.[0]; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const links = $('.list-group-item'); + links?.map((i, link) => { + episodesLink.push({ + title: $(link).text() || '', + link: baseUrl + $(link).find('a').attr('href') || '', + }); + }); + if (episodesLink.length > 0) { + return episodesLink; + } + } + if (url.includes('/pack')) { + const epIds = await extractKmhdEpisodes(url, providerContext); + epIds?.forEach((id: string, index: number) => { + episodesLink.push({ + title: `Episode ${index + 1}`, + link: url.split('/pack')[0] + '/file/' + id, + }); + }); + } + const res = await axios.get(url, { + headers: { + Cookie: + '_ga_GNR438JY8N=GS1.1.1722240350.5.0.1722240350.0.0.0; _ga=GA1.1.372196696.1722150754; unlocked=true', + }, + }); + const episodeData = res.data; + const $ = cheerio.load(episodeData); + const links = $('.autohyperlink'); + links?.map((i, link) => { + episodesLink.push({ + title: $(link).parent().children().remove().end().text() || '', + link: $(link).attr('href') || '', + }); + }); + + return episodesLink; + } catch (err) { + console.error(err); + return []; + } +}; + +export async function extractKmhdLink( + katlink: string, + providerContext: ProviderContext, +) { + const {axios} = providerContext; + const res = await axios.get(katlink); + const data = res.data; + const hubDriveRes = data.match(/hubdrive_res:\s*"([^"]+)"/)[1]; + const hubDriveLink = data.match( + /hubdrive_res\s*:\s*{[^}]*?link\s*:\s*"([^"]+)"/, + )[1]; + return hubDriveLink + hubDriveRes; +} + +async function extractKmhdEpisodes( + katlink: string, + providerContext: ProviderContext, +) { + const {axios} = providerContext; + const res = await axios.get(katlink); + const data = res.data; + const ids = data.match(/[\w]+_[a-f0-9]{8}/g); + return ids; +} diff --git a/providers/katmovies/katGetInfo.ts b/providers/katmovies/katGetInfo.ts new file mode 100644 index 0000000..35b9f80 --- /dev/null +++ b/providers/katmovies/katGetInfo.ts @@ -0,0 +1,131 @@ +import {Info, Link, ProviderContext} from '../types'; + +export const katGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, cheerio} = providerContext; + const url = link; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const container = $('.yQ8hqd.ksSzJd.LoQAYe').html() + ? $('.yQ8hqd.ksSzJd.LoQAYe') + : $('.FxvUNb'); + const imdbId = + container + .find('a[href*="imdb.com/title/tt"]:not([href*="imdb.com/title/tt/"])') + .attr('href') + ?.split('/')[4] || ''; + const title = container + .find('li:contains("Name")') + .children() + .remove() + .end() + .text(); + const type = $('.yQ8hqd.ksSzJd.LoQAYe').html() ? 'series' : 'movie'; + const synopsis = container.find('li:contains("Stars")').text(); + const image = + $('h4:contains("SCREENSHOTS")').next().find('img').attr('src') || ''; + + console.log('katGetInfo', title, synopsis, image, imdbId, type); + + // Links + const links: Link[] = []; + const directLink: Link['directLinks'] = []; + + // direct links + $('.entry-content') + .find('p:contains("Episode")') + .each((i, element) => { + const dlLink = + $(element) + .nextAll('h3,h2') + .first() + .find('a:contains("1080"),a:contains("720"),a:contains("480")') + .attr('href') || ''; + const dlTitle = $(element).find('span').text(); + + if (link.trim().length > 0 && dlTitle.includes('Episode ')) { + directLink.push({ + title: dlTitle, + link: dlLink, + }); + } + }); + + if (directLink.length > 0) { + links.push({ + quality: '', + title: title, + directLinks: directLink, + }); + } + + $('.entry-content') + .find('pre') + .nextUntil('div') + .filter('h2') + .each((i, element) => { + const link = $(element).find('a').attr('href'); + const quality = + $(element) + .text() + .match(/\b(480p|720p|1080p|2160p)\b/i)?.[0] || ''; + const title = $(element).text(); + if (link && title.includes('')) { + links.push({ + quality, + title, + episodesLink: link, + }); + } + }); + + if (links.length === 0 && type === 'movie') { + $('.entry-content') + .find('h2:contains("DOWNLOAD"),h3:contains("DOWNLOAD")') + .nextUntil('pre,div') + .filter('h2') + .each((i, element) => { + const link = $(element).find('a').attr('href'); + const quality = + $(element) + .text() + .match(/\b(480p|720p|1080p|2160p)\b/i)?.[0] || ''; + const title = $(element).text(); + if (link && !title.includes('Online')) { + links.push({ + quality, + title, + directLinks: [{link, title, type: 'movie'}], + }); + } + }); + } + + // console.log('drive meta', title, synopsis, image, imdbId, type, links); + return { + title, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/katmovies/katGetPosts.ts b/providers/katmovies/katGetPosts.ts new file mode 100644 index 0000000..d0974a2 --- /dev/null +++ b/providers/katmovies/katGetPosts.ts @@ -0,0 +1,72 @@ +import {Post, ProviderContext} from '../types'; + +export const katGetPosts = async function ({ + filter, + page, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, cheerio} = providerContext; + const baseUrl = await getBaseUrl('kat'); + const url = `${baseUrl + filter}/page/${page}/`; + return posts({url, signal, cheerio}); +}; + +export const katGetPostsSearch = async function ({ + searchQuery, + page, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, cheerio} = providerContext; + const baseUrl = await getBaseUrl('kat'); + const url = `${baseUrl}/page/${page}/?s=${searchQuery}`; + return posts({url, signal, cheerio}); +}; + +async function posts({ + url, + signal, + cheerio, +}: { + url: string; + signal: AbortSignal; + cheerio: ProviderContext['cheerio']; +}): Promise { + try { + const res = await fetch(url, {signal}); + const data = await res.text(); + const $ = cheerio.load(data); + const catalog: Post[] = []; + $('.recent-posts') + .children() + .map((i, element) => { + const title = $(element).find('img').attr('alt'); + const link = $(element).find('a').attr('href'); + const image = $(element).find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title.replace('Download', '').trim(), + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('katmovies error ', err); + return []; + } +} diff --git a/providers/katmovies/katGetSteam.ts b/providers/katmovies/katGetSteam.ts new file mode 100644 index 0000000..ec4f0bf --- /dev/null +++ b/providers/katmovies/katGetSteam.ts @@ -0,0 +1,99 @@ +import {Stream, ProviderContext} from '../types'; + +async function extractKmhdLink( + katlink: string, + providerContext: ProviderContext, +) { + const {axios} = providerContext; + const res = await axios.get(katlink); + const data = res.data; + const hubDriveRes = data.match(/hubdrive_res:\s*"([^"]+)"/)[1]; + const hubDriveLink = data.match( + /hubdrive_res\s*:\s*{[^}]*?link\s*:\s*"([^"]+)"/, + )[1]; + return hubDriveLink + hubDriveRes; +} +export async function katGetStream({ + link, + signal, + providerContext, +}: { + link: string; + type: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {axios, cheerio, extractors} = providerContext; + const {hubcloudExtracter, gdFlixExtracter} = extractors; + const streamLinks: Stream[] = []; + console.log('katGetStream', link); + try { + if (link.includes('gdflix')) { + return await gdFlixExtracter(link, signal); + } + if (link.includes('kmhd')) { + const hubcloudLink = await extractKmhdLink(link, providerContext); + return await hubcloudExtracter(hubcloudLink, signal); + } + if (link.includes('gdflix')) { + // resume link + try { + const resumeDrive = link.replace('/file', '/zfile'); + // console.log('resumeDrive', resumeDrive); + const resumeDriveRes = await axios.get(resumeDrive); + const resumeDriveHtml = resumeDriveRes.data; + const $resumeDrive = cheerio.load(resumeDriveHtml); + const resumeLink = $resumeDrive('.btn-success').attr('href'); + console.log('resumeLink', resumeLink); + if (resumeLink) { + streamLinks.push({ + server: 'ResumeCloud', + link: resumeLink, + type: 'mkv', + }); + } + } catch (err) { + console.log('Resume link not found'); + } + //instant link + try { + const driveres = await axios.get(link, {timeout: 10000}); + const $drive = cheerio.load(driveres.data); + const seed = $drive('.btn-danger').attr('href') || ''; + const instantToken = seed.split('=')[1]; + // console.log('InstantToken', instantToken); + const InstantFromData = new FormData(); + InstantFromData.append('keys', instantToken); + const videoSeedUrl = seed.split('/').slice(0, 3).join('/') + '/api'; + // console.log('videoSeedUrl', videoSeedUrl); + const instantLinkRes = await fetch(videoSeedUrl, { + method: 'POST', + body: InstantFromData, + headers: { + 'x-token': videoSeedUrl, + }, + }); + const instantLinkData = await instantLinkRes.json(); + console.log('instantLinkData', instantLinkData); + if (instantLinkData.error === false) { + const instantLink = instantLinkData.url; + streamLinks.push({ + server: 'Gdrive-Instant', + link: instantLink, + type: 'mkv', + }); + } else { + console.log('Instant link not found', instantLinkData); + } + } catch (err) { + console.log('Instant link not found', err); + } + return streamLinks; + } + const stereams = await hubcloudExtracter(link, signal); + return stereams; + } catch (error: any) { + console.log('katgetStream error: ', error); + return []; + } +} diff --git a/providers/kissKh/index.ts b/providers/kissKh/index.ts new file mode 100644 index 0000000..135e588 --- /dev/null +++ b/providers/kissKh/index.ts @@ -0,0 +1,14 @@ +import {kisskhCatalog, kisskhGenresList} from './kissKhCatalog'; +import {kissKhGetInfo} from './kissKhGetInfo'; +import {kissKhGetPosts, kissKhGetPostsSearch} from './kissKhGetPosts'; +import {kissKhGetStream} from './kissKhGetStream'; +import {ProviderType} from '../types'; + +export const kissKhProvider: ProviderType = { + catalog: kisskhCatalog, + genres: kisskhGenresList, + GetHomePosts: kissKhGetPosts, + GetMetaData: kissKhGetInfo, + GetStream: kissKhGetStream, + GetSearchPosts: kissKhGetPostsSearch, +}; diff --git a/providers/kissKh/kissKhCatalog.ts b/providers/kissKh/kissKhCatalog.ts new file mode 100644 index 0000000..bf71a02 --- /dev/null +++ b/providers/kissKh/kissKhCatalog.ts @@ -0,0 +1,20 @@ +export const kisskhCatalog = [ + { + title: 'Latest', + filter: '/api/DramaList/List?type=0&sub=0&country=0&status=0&order=2', + }, + { + title: 'Hollywood', + filter: '/api/DramaList/List?type=4&sub=0&country=0&status=0&order=2', + }, + { + title: 'Anime', + filter: '/api/DramaList/List?type=3&sub=0&country=0&status=0&order=2', + }, + { + title: 'K Drama', + filter: '/api/DramaList/List?type=0&sub=0&country=0&status=0&order=2', + }, +]; + +export const kisskhGenresList = []; diff --git a/providers/kissKh/kissKhGetInfo.ts b/providers/kissKh/kissKhGetInfo.ts new file mode 100644 index 0000000..677b08a --- /dev/null +++ b/providers/kissKh/kissKhGetInfo.ts @@ -0,0 +1,57 @@ +import {Info, Link, ProviderContext} from '../types'; + +export const kissKhGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios} = providerContext; + const res = await axios.get(link); + const data = res.data; + const meta = { + title: data.title, + synopsis: data.description, + image: data.thumbnail, + tags: [data?.releaseDate?.split('-')[0], data?.status, data?.type], + imdbId: '', + type: data.episodesCount > 1 ? 'series' : 'movie', + }; + + const linkList: Link[] = []; + const subLinks: Link['directLinks'] = []; + + data?.episodes?.reverse().map((episode: any) => { + const title = 'Episode ' + episode?.number; + const link = episode?.id?.toString(); + if (link && title) { + subLinks.push({ + title, + link, + }); + } + }); + + linkList.push({ + title: meta.title, + directLinks: subLinks, + }); + + return { + ...meta, + linkList: linkList, + }; + } catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/kissKh/kissKhGetPosts.ts b/providers/kissKh/kissKhGetPosts.ts new file mode 100644 index 0000000..c0da383 --- /dev/null +++ b/providers/kissKh/kissKhGetPosts.ts @@ -0,0 +1,75 @@ +import {Post, ProviderContext} from '../types'; + +export const kissKhGetPosts = async function ({ + filter, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios} = providerContext; + const baseUrl = await getBaseUrl('kissKh'); + const url = `${baseUrl + filter}&type=0`; + try { + const res = await axios.get(url, {signal}); + const data = res.data?.data; + const catalog: Post[] = []; + data?.map((element: any) => { + const title = element.title; + const link = baseUrl + `/api/DramaList/Drama/${element?.id}?isq=false`; + const image = element.thumbnail; + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('kiss error ', err); + return []; + } +}; + +export const kissKhGetPostsSearch = async function ({ + searchQuery, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios} = providerContext; + const baseUrl = await getBaseUrl('kissKh'); + const url = `${baseUrl}/api/DramaList/Search?q=${searchQuery}&type=0`; + try { + const res = await axios.get(url, {signal}); + const data = res.data; + const catalog: Post[] = []; + data?.map((element: any) => { + const title = element.title; + const link = baseUrl + `/api/DramaList/Drama/${element?.id}?isq=false`; + const image = element.thumbnail; + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('kiss error ', err); + return []; + } +}; diff --git a/providers/kissKh/kissKhGetStream.ts b/providers/kissKh/kissKhGetStream.ts new file mode 100644 index 0000000..f64ea38 --- /dev/null +++ b/providers/kissKh/kissKhGetStream.ts @@ -0,0 +1,45 @@ +import {Stream, ProviderContext, TextTrackType, TextTracks} from '../types'; + +export const kissKhGetStream = async function ({ + link: id, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, getBaseUrl} = providerContext; + const streamLinks: Stream[] = []; + const subtitles: TextTracks = []; + const baseUrl = await getBaseUrl('kissKh'); + const streamUrl = + 'https://adorable-salamander-ecbb21.netlify.app/api/kisskh/video?id=' + + id; + const res = await axios.get(streamUrl); + const stream = res.data?.source?.Video; + const subData = res.data?.subtitles; + subData?.map((sub: any) => { + subtitles.push({ + title: sub?.label, + language: sub?.land, + type: sub?.src?.includes('.vtt') + ? TextTrackType.VTT + : TextTrackType.SUBRIP, + uri: sub?.src, + }); + }); + streamLinks.push({ + server: 'kissKh', + link: stream, + type: 'm3u8', + subtitles, + headers: { + referer: baseUrl, + }, + }); + return streamLinks; + } catch (err) { + console.error(err); + return []; + } +}; diff --git a/providers/luxMovies/index.ts b/providers/luxMovies/index.ts new file mode 100644 index 0000000..789306c --- /dev/null +++ b/providers/luxMovies/index.ts @@ -0,0 +1,17 @@ +import {luxGetPosts, luxGetPostsSearch} from './luxGetPosts'; +import {vegaGetInfo} from '../vega/getInfo'; +import {vegaGetStream} from '../vega/getStream'; +import {vegaGetEpisodeLinks} from '../vega/getEpisodesLink'; +import {homeList, genresList} from './luxCatalog'; +import {ProviderType} from '../types'; + +export const luxMovies: ProviderType = { + catalog: homeList, + genres: genresList, + GetMetaData: vegaGetInfo, + GetHomePosts: luxGetPosts, + GetStream: vegaGetStream, + nonStreamableServer: ['filepress'], + GetEpisodeLinks: vegaGetEpisodeLinks, + GetSearchPosts: luxGetPostsSearch, +}; diff --git a/providers/luxMovies/luxCatalog.ts b/providers/luxMovies/luxCatalog.ts new file mode 100644 index 0000000..c2cf425 --- /dev/null +++ b/providers/luxMovies/luxCatalog.ts @@ -0,0 +1,101 @@ +export const homeList = [ + { + title: 'New', + filter: '', + }, + { + title: 'Netflix', + filter: 'category/web-series/netflix', + }, + { + title: 'Amazon Prime', + filter: 'category/web-series/amazon-prime-video', + }, + { + title: '4K Movies', + filter: 'category/movies-by-quality/2160p', + }, +]; + +export const genresList = [ + { + title: 'Action', + filter: 'category/movies-by-genres/action/', + }, + { + title: 'Adventure', + filter: 'category/movies-by-genres/adventure/', + }, + { + title: 'Animation', + filter: 'category/movies-by-genres/animation/', + }, + { + title: 'Biography', + filter: 'category/movies-by-genres/biography/', + }, + { + title: 'Comedy', + filter: 'category/movies-by-genres/comedy/', + }, + { + title: 'Crime', + filter: 'category/movies-by-genres/crime/', + }, + { + title: 'Documentary', + filter: 'category/movies-by-genres/documentary/', + }, + { + title: 'Drama', + filter: 'category/movies-by-genres/drama/', + }, + { + title: 'Family', + filter: 'category/movies-by-genres/family/', + }, + { + title: 'Fantasy', + filter: 'category/movies-by-genres/fantasy/', + }, + { + title: 'History', + filter: 'category/movies-by-genres/history/', + }, + { + title: 'Horror', + filter: 'category/movies-by-genres/horror/', + }, + { + title: 'Music', + filter: 'category/movies-by-genres/music/', + }, + { + title: 'Mystery', + filter: 'category/movies-by-genres/mystery/', + }, + { + title: 'Romance', + filter: 'category/movies-by-genres/romance/', + }, + { + title: 'Sci-Fi', + filter: 'category/movies-by-genres/sci-fi/', + }, + { + title: 'Sport', + filter: 'category/movies-by-genres/sport/', + }, + { + title: 'Thriller', + filter: 'category/movies-by-genres/thriller/', + }, + { + title: 'War', + filter: 'category/movies-by-genres/war/', + }, + { + title: 'Western', + filter: 'category/movies-by-genres/western/', + }, +]; diff --git a/providers/luxMovies/luxGetPosts.ts b/providers/luxMovies/luxGetPosts.ts new file mode 100644 index 0000000..fb949bd --- /dev/null +++ b/providers/luxMovies/luxGetPosts.ts @@ -0,0 +1,111 @@ +import {Post, ProviderContext} from '../types'; + +const headers = { + Accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': + '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + Cookie: + 'ext_name=ojplmecpdpgccookcobabopnaifgidhf; cf_clearance=gaIhTNzqSvp27JCVf7qiEUfYRfwyj0Jx9rcsn774BbE-1732694853-1.2.1.1-QKgYJvmrEz08gM9qbAp70diztE2.hseO2NNi.0imIUk_gkuWUcr7U8t5Zn_z4Ov30sIGPBES1PBgMUEa.s8e8QTkQoZjgziFmoC7YdX7s2Jnt.tYCxE_s5mMLQQBYbz_94A89IYe93Y6kyLQm_L.dvUKPPiGjn_sH3qRD0g4p9oOl0SPvH0T2W_EaD0r6mVBasbgro9dAROt_6CxshXOEGeMOnoWR.ID699FKldjMUhbXJbATAffdOY6kf2sD_iwrSl4bcetTlDHd4gusTVfxSS1pL5qNjyTU9wa38soPl1wZoqFHkEGOPWz6S7FD5ikHxX0bArFem9hiDeJXctYfWz5e_Lkc6lH7nW0Rm2XS3gxCadQSg21RkSReN6kDAEecqjgJSE4zUomkWAxFZ98TSShgGWC0ridPTpdQizPDZQ; _lscache_vary=c1d682536aea2d88fbb2574666e1f0aa', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', +}; + +export const luxGetPosts = async ({ + filter, + page, + providerValue, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise => { + const {getBaseUrl} = providerContext; + const baseUrl = await getBaseUrl('lux'); + + console.log('vegaGetPosts baseUrl:', providerValue, baseUrl); + const url = `${baseUrl}/${filter}/page/${page}/`; + console.log('lux url:', url); + return posts(url, signal, providerContext); +}; + +export const luxGetPostsSearch = async ({ + searchQuery, + page, + providerValue, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise => { + const {getBaseUrl} = providerContext; + const baseUrl = await getBaseUrl('lux'); + + console.log('vegaGetPosts baseUrl:', providerValue, baseUrl); + const url = `${baseUrl}/page/${page}/?s=${searchQuery}`; + console.log('lux url:', url); + + return posts(url, signal, providerContext); +}; + +async function posts( + url: string, + signal: AbortSignal, + providerContext: ProviderContext, +): Promise { + try { + const {axios, cheerio} = providerContext; + const urlRes = await axios.get(url, {headers, signal}); + const $ = cheerio.load(urlRes.data); + const posts: Post[] = []; + $('.blog-items') + ?.children('article') + ?.each((index, element) => { + const post = { + title: + $(element) + ?.find('a') + ?.attr('title') + ?.replace('Download', '') + ?.match(/^(.*?)\s*\((\d{4})\)|^(.*?)\s*\((Season \d+)\)/)?.[0] || + $(element)?.find('a')?.attr('title')?.replace('Download', '') || + '', + + link: $(element)?.find('a')?.attr('href') || '', + image: + $(element).find('a').find('img').attr('data-lazy-src') || + $(element).find('a').find('img').attr('data-src') || + $(element).find('a').find('img').attr('src') || + '', + }; + if (post.image.startsWith('//')) { + post.image = 'https:' + post.image; + } + posts.push(post); + }); + + // console.log(posts); + return posts; + } catch (error) { + console.error('vegaGetPosts error:', error); + return []; + } +} diff --git a/providers/mod/catalog.ts b/providers/mod/catalog.ts new file mode 100644 index 0000000..ba79f18 --- /dev/null +++ b/providers/mod/catalog.ts @@ -0,0 +1,85 @@ +export const catalogList = [ + { + title: 'Latest', + filter: '', + }, + { + title: 'Netflix', + filter: '/ott/netflix', + }, + { + title: 'HBO Max', + filter: '/ott/hbo-max', + }, + { + title: 'Amazon Prime', + filter: '/ott/amazon-prime-video', + }, +]; + +export const modGenresList = [ + { + title: 'Apple TV+', + filter: '/ott/apple-tv', + }, + { + title: 'Disney+', + filter: '/ott/disney-plus', + }, + { + title: 'Hulu', + filter: '/ott/hulu', + }, + { + title: 'Crunchyroll', + filter: '/ott/crunchyroll', + }, + { + title: 'Action', + filter: '/movies-by-genre/action/', + }, + { + title: 'Adventure', + filter: '/movies-by-genre/adventure/', + }, + { + title: 'Animation', + filter: '/movies-by-genre/animated/', + }, + { + title: 'Comedy', + filter: '/movies-by-genre/comedy/', + }, + { + title: 'Crime', + filter: '/movies-by-genre/crime/', + }, + { + title: 'Documentary', + filter: '/movies-by-genre/documentary/', + }, + { + title: 'Fantasy', + filter: '/movies-by-genre/fantasy/', + }, + { + title: 'Horror', + filter: '/movies-by-genre/horror/', + }, + { + title: 'Mystery', + filter: '/movies-by-genre/mystery/', + }, + { + title: 'Romance', + filter: '/movies-by-genre/romance/', + }, + { + title: 'Thriller', + filter: '/movies-by-genre/thriller/', + }, + { + title: 'Sci-Fi', + filter: '/movies-by-genre/sci-fi/', + }, +]; diff --git a/providers/mod/index.ts b/providers/mod/index.ts new file mode 100644 index 0000000..d7acc76 --- /dev/null +++ b/providers/mod/index.ts @@ -0,0 +1,17 @@ +import {modGenresList, catalogList} from './catalog'; +import {modGetInfo} from './modGetInfo'; +import {modGetEpisodeLinks} from './modGetEpisodesList'; +import {modGetPosts, modGetPostsSearch} from './modGetPosts'; +import {modGetStream} from './modGetStream'; +import {ProviderType} from '../types'; + +export const modMovies: ProviderType = { + catalog: catalogList, + genres: modGenresList, + GetMetaData: modGetInfo, + GetHomePosts: modGetPosts, + GetStream: modGetStream, + GetEpisodeLinks: modGetEpisodeLinks, + // nonStreamableServer: ['Gdrive-Instant'], + GetSearchPosts: modGetPostsSearch, +}; diff --git a/providers/mod/modGetEpisodesList.ts b/providers/mod/modGetEpisodesList.ts new file mode 100644 index 0000000..8272d7a --- /dev/null +++ b/providers/mod/modGetEpisodesList.ts @@ -0,0 +1,52 @@ +import {EpisodeLink, ProviderContext} from '../types'; + +export const modGetEpisodeLinks = async function ({ + url, + providerContext, +}: { + url: string; + providerContext: ProviderContext; +}): Promise { + const {axios, cheerio} = providerContext; + try { + if (url.includes('url=')) { + url = atob(url.split('url=')[1]); + } + const res = await axios.get(url); + const html = res.data; + let $ = cheerio.load(html); + if (url.includes('url=')) { + const newUrl = $("meta[http-equiv='refresh']") + .attr('content') + ?.split('url=')[1]; + const res2 = await axios.get(newUrl || url); + const html2 = res2.data; + $ = cheerio.load(html2); + } + const episodeLinks: EpisodeLink[] = []; + $('h3,h4').map((i, element) => { + const seriesTitle = $(element).text(); + const episodesLink = $(element).find('a').attr('href'); + if (episodesLink && episodesLink !== '#') { + episodeLinks.push({ + title: seriesTitle.trim() || 'No title found', + link: episodesLink || '', + }); + } + }); + $('a.maxbutton').map((i, element) => { + const seriesTitle = $(element).children('span').text(); + const episodesLink = $(element).attr('href'); + if (episodesLink && episodesLink !== '#') { + episodeLinks.push({ + title: seriesTitle.trim() || 'No title found', + link: episodesLink || '', + }); + } + }); + return episodeLinks; + } catch (err) { + console.error(err); + return []; + } +}; diff --git a/providers/mod/modGetInfo.ts b/providers/mod/modGetInfo.ts new file mode 100644 index 0000000..1331cf4 --- /dev/null +++ b/providers/mod/modGetInfo.ts @@ -0,0 +1,71 @@ +import {Info, Link, ProviderContext} from '../types'; + +export const modGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, cheerio} = providerContext; + const url = link; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const meta = { + title: $('.imdbwp__title').text(), + synopsis: $('.imdbwp__teaser').text(), + image: $('.imdbwp__thumb').find('img').attr('src') || '', + imdbId: $('.imdbwp__link').attr('href')?.split('/')[4] || '', + type: $('.thecontent').text().toLocaleLowerCase().includes('season') + ? 'series' + : 'movie', + }; + const links: Link[] = []; + + $('h3,h4').map((i, element) => { + const seriesTitle = $(element).text(); + // const batchZipLink = $(element) + // .next("p") + // .find(".maxbutton-batch-zip,.maxbutton-zip-download") + // .attr("href"); + const episodesLink = $(element) + .next('p') + .find( + '.maxbutton-episode-links,.maxbutton-g-drive,.maxbutton-af-download', + ) + .attr('href'); + const movieLink = $(element) + .next('p') + .find('.maxbutton-download-links') + .attr('href'); + + if ( + movieLink || + (episodesLink && episodesLink !== 'javascript:void(0);') + ) { + links.push({ + title: seriesTitle.replace('Download ', '').trim() || 'Download', + episodesLink: episodesLink || '', + directLinks: movieLink + ? [{link: movieLink, title: 'Movie', type: 'movie'}] + : [], + quality: seriesTitle?.match(/\d+p\b/)?.[0] || '', + }); + } + }); + // console.log('mod meta', links); + return {...meta, linkList: links}; + } catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/mod/modGetPosts.ts b/providers/mod/modGetPosts.ts new file mode 100644 index 0000000..ff69425 --- /dev/null +++ b/providers/mod/modGetPosts.ts @@ -0,0 +1,74 @@ +import {Post, ProviderContext} from '../types'; + +export const modGetPosts = async function ({ + filter, + page, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios, cheerio} = providerContext; + const baseUrl = await getBaseUrl('Moviesmod'); + const url = `${baseUrl + filter}/page/${page}/`; + return posts({url, signal, axios, cheerio}); +}; + +export const modGetPostsSearch = async function ({ + searchQuery, + page, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios, cheerio} = providerContext; + const baseUrl = await getBaseUrl('Moviesmod'); + const url = `${baseUrl}/search/${searchQuery}/page/${page}/`; + return posts({url, signal, axios, cheerio}); +}; + +async function posts({ + url, + signal, + axios, + cheerio, +}: { + url: string; + signal: AbortSignal; + axios: ProviderContext['axios']; + cheerio: ProviderContext['cheerio']; +}): Promise { + try { + const res = await axios.get(url, {signal}); + const data = res.data; + const $ = cheerio.load(data); + const catalog: Post[] = []; + $('.post-cards') + .find('article') + .map((i, element) => { + const title = $(element).find('a').attr('title'); + const link = $(element).find('a').attr('href'); + const image = $(element).find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('modGetPosts error ', err); + return []; + } +} diff --git a/providers/mod/modGetStream.ts b/providers/mod/modGetStream.ts new file mode 100644 index 0000000..0f84824 --- /dev/null +++ b/providers/mod/modGetStream.ts @@ -0,0 +1,288 @@ +import {Stream, ProviderContext, EpisodeLink} from '../types'; + +const headers = { + Accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': + '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + Cookie: 'popads_user_id=6ba8fe60a481387a3249f05aa058822d', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', +}; + +export const modGetStream = async function ({ + link: url, + type, + providerContext, +}: { + link: string; + type: string; + providerContext: ProviderContext; +}): Promise { + const {axios, cheerio} = providerContext; + try { + const modGetEpisodeLinks = async function ({ + url, + providerContext, + }: { + url: string; + providerContext: ProviderContext; + }): Promise { + const {axios, cheerio} = providerContext; + try { + if (url.includes('url=')) { + url = atob(url.split('url=')[1]); + } + const res = await axios.get(url); + const html = res.data; + let $ = cheerio.load(html); + if (url.includes('url=')) { + const newUrl = $("meta[http-equiv='refresh']") + .attr('content') + ?.split('url=')[1]; + const res2 = await axios.get(newUrl || url); + const html2 = res2.data; + $ = cheerio.load(html2); + } + const episodeLinks: EpisodeLink[] = []; + $('h3,h4').map((i, element) => { + const seriesTitle = $(element).text(); + const episodesLink = $(element).find('a').attr('href'); + if (episodesLink && episodesLink !== '#') { + episodeLinks.push({ + title: seriesTitle.trim() || 'No title found', + link: episodesLink || '', + }); + } + }); + $('a.maxbutton').map((i, element) => { + const seriesTitle = $(element).children('span').text(); + const episodesLink = $(element).attr('href'); + if (episodesLink && episodesLink !== '#') { + episodeLinks.push({ + title: seriesTitle.trim() || 'No title found', + link: episodesLink || '', + }); + } + }); + return episodeLinks; + } catch (err) { + console.error(err); + return []; + } + }; + console.log('modGetStream', type, url); + if (type === 'movie') { + const servers = await modGetEpisodeLinks({url, providerContext}); + url = servers[0].link || url; + } + + let downloadLink = await modExtractor(url, providerContext); + + // console.log(downloadLink.data); + + const ddl = downloadLink?.data?.match(/content="0;url=(.*?)"/)?.[1] || url; + // console.log('ddl', url); + + // console.log(ddl); + // console.log(ddl); + const servers: Stream[] = []; + const driveLink = await isDriveLink(ddl); + const driveRes = await axios.get(driveLink, {headers}); + const driveHtml = driveRes.data; + const $drive = cheerio.load(driveHtml); + + try { + const resumeBot = $drive('.btn.btn-light').attr('href') || ''; + const resumeBotRes = await axios.get(resumeBot, {headers}); + const resumeBotToken = resumeBotRes.data.match( + /formData\.append\('token', '([a-f0-9]+)'\)/, + )[1]; + const resumeBotBody = new FormData(); + resumeBotBody.append('token', resumeBotToken); + const resumeBotPath = resumeBotRes.data.match( + /fetch\('\/download\?id=([a-zA-Z0-9\/+]+)'/, + )[1]; + const resumeBotBaseUrl = resumeBot.split('/download')[0]; + // console.log( + // 'resumeBotPath', + // resumeBotBaseUrl + '/download?id=' + resumeBotPath, + // ); + // console.log('resumeBotBody', resumeBotToken); + + const resumeBotDownload = await fetch( + resumeBotBaseUrl + '/download?id=' + resumeBotPath, + { + method: 'POST', + body: resumeBotBody, + headers: { + Referer: resumeBot, + Cookie: 'PHPSESSID=7e9658ce7c805dab5bbcea9046f7f308', + }, + }, + ); + const resumeBotDownloadData = await resumeBotDownload.json(); + console.log('resumeBotDownloadData', resumeBotDownloadData.url); + servers.push({ + server: 'ResumeBot', + link: resumeBotDownloadData.url, + type: 'mkv', + }); + } catch (err) { + console.log('ResumeBot link not found', err); + } + // CF workers type 1 + try { + const cfWorkersLink = driveLink.replace('/file', '/wfile') + '?type=1'; + const cfWorkersRes = await axios.get(cfWorkersLink, {headers}); + const cfWorkersHtml = cfWorkersRes.data; + const $cfWorkers = cheerio.load(cfWorkersHtml); + const cfWorkersStream = $cfWorkers('.btn-success'); + cfWorkersStream.each((i, el) => { + const link = el.attribs.href; + if (link) { + servers.push({ + server: 'Cf Worker 1.' + i, + link: link, + type: 'mkv', + }); + } + }); + } catch (err) { + console.log('CF workers link not found', err); + } + + // CF workers type 2 + try { + const cfWorkersLink = driveLink.replace('/file', '/wfile') + '?type=2'; + const cfWorkersRes = await axios.get(cfWorkersLink, {headers}); + const cfWorkersHtml = cfWorkersRes.data; + const $cfWorkers = cheerio.load(cfWorkersHtml); + const cfWorkersStream = $cfWorkers('.btn-success'); + cfWorkersStream.each((i, el) => { + const link = el.attribs.href; + if (link) { + servers.push({ + server: 'Cf Worker 2.' + i, + link: link, + type: 'mkv', + }); + } + }); + } catch (err) { + console.log('CF workers link not found', err); + } + + // gdrive + + //instant link + try { + const seed = $drive('.btn-danger').attr('href') || ''; + const instantToken = seed.split('=')[1]; + // console.log('InstantToken', instantToken); + const InstantFromData = new FormData(); + InstantFromData.append('keys', instantToken); + const videoSeedUrl = seed.split('/').slice(0, 3).join('/') + '/api'; + // console.log('videoSeedUrl', videoSeedUrl); + const instantLinkRes = await fetch(videoSeedUrl, { + method: 'POST', + body: InstantFromData, + headers: { + 'x-token': videoSeedUrl, + }, + }); + const instantLinkData = await instantLinkRes.json(); + // console.log('instantLinkData', instantLinkData); + if (instantLinkData.error === false) { + const instantLink = instantLinkData.url; + servers.push({ + server: 'Gdrive-Instant', + link: instantLink, + type: 'mkv', + }); + } else { + console.log('Instant link not found', instantLinkData); + } + } catch (err) { + console.log('Instant link not found', err); + } + return servers; + } catch (err) { + console.log('getStream error', err); + return []; + } +}; + +const isDriveLink = async (ddl: string) => { + if (ddl.includes('drive')) { + const driveLeach = await fetch(ddl); + const driveLeachData = await driveLeach.text(); + const pathMatch = driveLeachData.match( + /window\.location\.replace\("([^"]+)"\)/, + ); + const path = pathMatch?.[1]; + const mainUrl = ddl.split('/')[2]; + console.log(`driveUrl = https://${mainUrl}${path}`); + return `https://${mainUrl}${path}`; + } else { + return ddl; + } +}; + +async function modExtractor(url: string, providerContext: ProviderContext) { + const {axios, cheerio} = providerContext; + try { + const wpHttp = url.split('sid=')[1]; + var bodyFormData0 = new FormData(); + bodyFormData0.append('_wp_http', wpHttp); + const res = await fetch(url.split('?')[0], { + method: 'POST', + body: bodyFormData0, + }); + const data = await res.text(); + // console.log('', data); + const html = data; + const $ = cheerio.load(html); + + // find input with name="_wp_http2" + const wpHttp2 = $('input').attr('name', '_wp_http2').val(); + + // console.log('wpHttp2', wpHttp2); + + // form data + var bodyFormData = new FormData(); + bodyFormData.append('_wp_http2', wpHttp2); + const formUrl1 = $('form').attr('action'); + const formUrl = formUrl1 || url.split('?')[0]; + + const res2 = await fetch(formUrl, { + method: 'POST', + body: bodyFormData, + }); + const html2: any = await res2.text(); + const link = html2.match(/setAttribute\("href",\s*"(.*?)"/)[1]; + console.log(link); + const cookie = link.split('=')[1]; + console.log('cookie', cookie); + + const downloadLink = await axios.get(link, { + headers: { + Referer: formUrl, + Cookie: `${cookie}=${wpHttp2}`, + }, + }); + return downloadLink; + } catch (err) { + console.log('modGetStream error', err); + } +} diff --git a/providers/moviesApi/index.ts b/providers/moviesApi/index.ts new file mode 100644 index 0000000..3d1e234 --- /dev/null +++ b/providers/moviesApi/index.ts @@ -0,0 +1,14 @@ +import {allCatalog, allGenresList} from '../autoEmbed/allCatalog'; +import {allGetInfo} from '../autoEmbed/allGetInfo'; +import {allGetPost, allGetSearchPosts} from '../autoEmbed/allGetPost'; +import {ProviderType} from '../types'; +import {mpGetStream} from './mpGetStream'; + +export const moviesApi: ProviderType = { + catalog: allCatalog, + genres: allGenresList, + GetMetaData: allGetInfo, + GetHomePosts: allGetPost, + GetStream: mpGetStream, + GetSearchPosts: allGetSearchPosts, +}; diff --git a/providers/moviesApi/mpGetStream.ts b/providers/moviesApi/mpGetStream.ts new file mode 100644 index 0000000..5da8eed --- /dev/null +++ b/providers/moviesApi/mpGetStream.ts @@ -0,0 +1,100 @@ +import {Stream, ProviderContext, TextTrackType, TextTracks} from '../types'; + +export const mpGetStream = async function ({ + link: id, + type, + providerContext, +}: { + link: string; + type: string; + providerContext: ProviderContext; +}): Promise { + try { + const {getBaseUrl, cheerio} = providerContext; + const streams: Stream[] = []; + const {season, episode, tmdbId} = JSON.parse(id); + const baseUrl = await getBaseUrl('moviesapi'); + const link = + type === 'movie' + ? `${baseUrl}/movie/${tmdbId}` + : `${baseUrl}/tv/${tmdbId}-${season}-${episode}`; + const res = await fetch(link, { + headers: { + referer: baseUrl, + }, + }); + const baseData = await res.text(); + const $ = cheerio.load(baseData); + const embededUrl = $('iframe').attr('src') || ''; + const response = await fetch(embededUrl, { + credentials: 'omit', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0', + Accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', + 'Accept-Language': 'en-US,en;q=0.5', + 'Alt-Used': 'w1.moviesapi.club', + 'Upgrade-Insecure-Requests': '1', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + Pragma: 'no-cache', + 'Cache-Control': 'no-cache', + referer: baseUrl, + }, + referrer: baseUrl, + method: 'GET', + mode: 'cors', + }); + const data2 = await response.text(); + + // Extract the encrypted content + const contents = + data2.match(/const\s+Encrypted\s*=\s*['"]({.*})['"]/)?.[1] || ''; + if (embededUrl) { + const res2 = await fetch( + 'https://ext.8man.me/api/decrypt?passphrase==JV[t}{trEV=Ilh5', + { + method: 'POST', + body: contents, + }, + ); + const finalData = await res2.json(); + const subtitle: TextTracks = finalData?.subtitles?.map((sub: any) => ({ + title: sub?.label || 'Unknown', + language: sub?.label as string, + type: sub?.file?.includes('.vtt') + ? TextTrackType.VTT + : TextTrackType.SUBRIP, + uri: sub?.file, + })); + + streams.push({ + server: 'vidstreaming ', + type: 'm3u8', + subtitles: subtitle, + link: finalData?.videoUrl, + headers: { + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0', + Referer: baseUrl, + Origin: baseUrl, + Accept: '*/*', + 'Accept-Language': 'en-US,en;q=0.5', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'cross-site', + Pragma: 'no-cache', + 'Cache-Control': 'no-cache', + }, + }); + } + + return streams; + } catch (err) { + console.error(err); + return []; + } +}; diff --git a/providers/multi/index.ts b/providers/multi/index.ts new file mode 100644 index 0000000..8266acd --- /dev/null +++ b/providers/multi/index.ts @@ -0,0 +1,14 @@ +import {multiGenresList, multiCatalog} from './multiCatalog'; +import {multiGetInfo} from './multiGetInfo'; +import {multiGetPosts, multiGetPostsSearch} from './multiPosts'; +import {multiGetStream} from './multiGetStream'; +import {ProviderType} from '../types'; + +export const multiMovies: ProviderType = { + catalog: multiCatalog, + genres: multiGenresList, + GetMetaData: multiGetInfo, + GetHomePosts: multiGetPosts, + GetStream: multiGetStream, + GetSearchPosts: multiGetPostsSearch, +}; diff --git a/providers/multi/multiCatalog.ts b/providers/multi/multiCatalog.ts new file mode 100644 index 0000000..796d006 --- /dev/null +++ b/providers/multi/multiCatalog.ts @@ -0,0 +1,77 @@ +export const multiCatalog = [ + { + title: 'Trending', + filter: '/trending/', + }, + { + title: 'Netflix', + filter: '/genre/netflix/', + }, + { + title: 'Amazon Prime', + filter: '/genre/amazon-prime/', + }, + { + title: 'Disney Hotstar', + filter: '/genre/disney-hotstar/', + }, +]; + +export const multiGenresList = [ + { + title: 'Action', + filter: '/genre/action/', + }, + { + title: 'Adventure', + filter: '/genre/adventure/', + }, + { + title: 'Animation', + filter: '/genre/animation/', + }, + { + title: 'Comedy', + filter: '/genre/comedy/', + }, + { + title: 'Crime', + filter: '/genre/crime/', + }, + { + title: 'Drama', + filter: '/genre/drama/', + }, + { + title: 'Family', + filter: '/genre/family/', + }, + { + title: 'Fantasy', + filter: '/genre/fantasy/', + }, + { + title: 'History', + filter: '/genre/history/', + }, + { + title: 'Horror', + filter: '/genre/horror/', + }, + { + title: 'Mystery', + filter: '/genre/mystery/', + }, + { + title: 'Romance', + filter: '/genre/romance/', + }, + { + title: 'Science Fiction', + filter: '/genre/science-fiction/', + }, + { + title: 'Thriller', + filter: '/genre/thriller/', + }, +]; diff --git a/providers/multi/multiGetInfo.ts b/providers/multi/multiGetInfo.ts new file mode 100644 index 0000000..fdd2f03 --- /dev/null +++ b/providers/multi/multiGetInfo.ts @@ -0,0 +1,82 @@ +import {Info, Link, ProviderContext} from '../types'; + +export const multiGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, cheerio} = providerContext; + const url = link; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const type = url.includes('tvshows') ? 'series' : 'movie'; + const imdbId = ''; + const title = url.split('/')[4].replace(/-/g, ' '); + const image = $('.g-item').find('a').attr('href') || ''; + const synopsis = $('.wp-content').find('p').text() || ''; + + // Links + const links: Link[] = []; + + if (type === 'series') { + $('#seasons') + .children() + .map((i, element) => { + const title = $(element) + .find('.title') + .children() + .remove() + .end() + .text(); + let episodesList: {title: string; link: string}[] = []; + $(element) + .find('.episodios') + .children() + .map((i, element) => { + const title = + 'Episode' + + $(element).find('.numerando').text().trim().split('-')[1]; + const link = $(element).find('a').attr('href'); + if (title && link) { + episodesList.push({title, link}); + } + }); + if (title && episodesList.length > 0) { + links.push({ + title, + directLinks: episodesList, + }); + } + }); + } else { + links.push({ + title: title, + directLinks: [{title: title, link: url.slice(0, -1), type: 'movie'}], + }); + } + // console.log('multi meta', links); + + return { + title, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/multi/multiGetStream.ts b/providers/multi/multiGetStream.ts new file mode 100644 index 0000000..afd6418 --- /dev/null +++ b/providers/multi/multiGetStream.ts @@ -0,0 +1,157 @@ +import {Stream, ProviderContext, TextTracks, TextTrackType} from '../types'; + +export const multiGetStream = async function ({ + link: url, + providerContext, +}: { + link: string; + type: string; + providerContext: ProviderContext; +}): Promise { + const {axios, cheerio} = providerContext; + const headers = { + 'sec-ch-ua': + '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + Referer: 'https://multimovies.online/', + 'Sec-Fetch-User': '?1', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', + }; + + try { + const res = await axios.get(url, {headers}); + const html = res.data; + const $ = cheerio.load(html); + const streamLinks: Stream[] = []; + const postId = $('#player-option-1').attr('data-post'); + const nume = $('#player-option-1').attr('data-nume'); + const typeValue = $('#player-option-1').attr('data-type'); + + const baseUrl = url.split('/').slice(0, 3).join('/'); + console.log('baseUrl', baseUrl); + + const formData = new FormData(); + formData.append('action', 'doo_player_ajax'); + formData.append('post', postId); + formData.append('nume', nume); + formData.append('type', typeValue); + + console.log('formData', formData); + + const playerRes = await fetch(`${baseUrl}/wp-admin/admin-ajax.php`, { + headers: headers, + body: formData, + method: 'POST', + }); + const playerData = await playerRes.json(); + console.log('playerData', playerData); + let ifameUrl = + playerData?.embed_url?.match(/]+src="([^"]+)"[^>]*>/i)?.[1] || + playerData?.embed_url; + console.log('ifameUrl', ifameUrl); + if (!ifameUrl.includes('multimovies')) { + let playerBaseUrl = ifameUrl.split('/').slice(0, 3).join('/'); + const newPlayerBaseUrl = await axios.head(playerBaseUrl, {headers}); + if (newPlayerBaseUrl) { + playerBaseUrl = newPlayerBaseUrl.request?.responseURL + ?.split('/') + .slice(0, 3) + .join('/'); + } + const playerId = ifameUrl.split('/').pop(); + const NewformData = new FormData(); + NewformData.append('sid', playerId); + console.log( + 'NewformData', + playerBaseUrl + '/embedhelper.php', + NewformData, + ); + const playerRes = await fetch(`${playerBaseUrl}/embedhelper.php`, { + headers: headers, + body: NewformData, + method: 'POST', + }); + const playerData = await playerRes.json(); + // console.log('playerData', playerData); + const siteUrl = playerData?.siteUrls?.smwh; + const siteId = + JSON.parse(atob(playerData?.mresult))?.smwh || + playerData?.mresult?.smwh; + const newIframeUrl = siteUrl + siteId; + console.log('newIframeUrl', newIframeUrl); + if (newIframeUrl) { + ifameUrl = newIframeUrl; + } + } + const iframeRes = await axios.get(ifameUrl, { + headers: { + ...headers, + Referer: url, + }, + }); + const iframeData = iframeRes.data; + + // Step 1: Extract the function parameters and the encoded string + var functionRegex = + /eval\(function\((.*?)\)\{.*?return p\}.*?\('(.*?)'\.split/; + var match = functionRegex.exec(iframeData); + let p = ''; + if (match) { + // var params = match[1].split(',').map(param => param.trim()); + var encodedString = match[2]; + + // console.log('Parameters:', params); + // console.log('Encoded String:', encodedString.split("',36,")[0], '🔥🔥'); + + p = encodedString.split("',36,")?.[0].trim(); + let a = 36; + let c = encodedString.split("',36,")[1].slice(2).split('|').length; + let k = encodedString.split("',36,")[1].slice(2).split('|'); + + while (c--) { + if (k[c]) { + var regex = new RegExp('\\b' + c.toString(a) + '\\b', 'g'); + p = p.replace(regex, k[c]); + } + } + + // console.log('Decoded String:', p); + } else { + console.log('No match found'); + } + + const streamUrl = p?.match(/https?:\/\/[^"]+?\.m3u8[^"]*/)?.[0]; + const subtitles: TextTracks = []; + const subtitleMatch = p?.match(/https:\/\/[^\s"]+\.vtt/g); + // console.log('subtitleMatch', subtitleMatch); + // console.log('streamUrl', streamUrl); + if (subtitleMatch?.length) { + subtitleMatch.forEach((sub: any) => { + const lang = sub.match(/_([a-zA-Z]{3})\.vtt$/)[1]; + subtitles.push({ + language: lang, + uri: sub, + type: TextTrackType.VTT, + title: lang, + }); + }); + } + console.log('streamUrl', streamUrl); + console.log('newUrl', streamUrl?.replace(/&i=\d+,'\.4&/, '&i=0.4&')); + if (streamUrl) { + streamLinks.push({ + server: 'Multi', + link: streamUrl.replace(/&i=\d+,'\.4&/, '&i=0.4&'), + type: 'm3u8', + subtitles: subtitles, + }); + } + + return streamLinks; + } catch (err) { + console.error(err); + return []; + } +}; diff --git a/providers/multi/multiPosts.ts b/providers/multi/multiPosts.ts new file mode 100644 index 0000000..71dff11 --- /dev/null +++ b/providers/multi/multiPosts.ts @@ -0,0 +1,74 @@ +import {Post, ProviderContext} from '../types'; + +export const multiGetPosts = async function ({ + filter, + page, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, cheerio} = providerContext; + const baseUrl = await getBaseUrl('multi'); + const url = `${baseUrl + filter}page/${page}/`; + return posts({url, signal, cheerio}); +}; + +export const multiGetPostsSearch = async function ({ + searchQuery, + + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, cheerio} = providerContext; + const baseUrl = await getBaseUrl('multi'); + const url = `${baseUrl}/?s=${searchQuery}`; + return posts({url, signal, cheerio}); +}; + +async function posts({ + url, + signal, + cheerio, +}: { + url: string; + signal: AbortSignal; + cheerio: ProviderContext['cheerio']; +}): Promise { + try { + const res = await fetch(url, {signal}); + const data = await res.text(); + const $ = cheerio.load(data); + const catalog: Post[] = []; + $('.items.full') + .children() + .map((i, element) => { + const title = $(element).find('.poster').find('img').attr('alt'); + const link = $(element).find('.poster').find('a').attr('href'); + const image = + $(element).find('.poster').find('img').attr('data-src') || + $(element).find('.poster').find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('multiGetPosts error ', err); + return []; + } +} diff --git a/providers/netflixMirror/index.ts b/providers/netflixMirror/index.ts new file mode 100644 index 0000000..9b724d0 --- /dev/null +++ b/providers/netflixMirror/index.ts @@ -0,0 +1,16 @@ +import {nfCatalog, nfGenresList} from './nfCatalog'; +import {nfGetInfo} from './nfGetInfo'; +import {nfGetPost, nfGetPostsSearch} from './nfGetPost'; +import {nfGetEpisodes} from './nfGetEpisodes'; +import {nfGetStream} from './nfGetSteam'; +import {ProviderType} from '../types'; + +export const netflixMirror: ProviderType = { + catalog: nfCatalog, + genres: nfGenresList, + GetMetaData: nfGetInfo, + GetHomePosts: nfGetPost, + GetStream: nfGetStream, + GetEpisodeLinks: nfGetEpisodes, + GetSearchPosts: nfGetPostsSearch, +}; diff --git a/providers/netflixMirror/nfCatalog.ts b/providers/netflixMirror/nfCatalog.ts new file mode 100644 index 0000000..ab75040 --- /dev/null +++ b/providers/netflixMirror/nfCatalog.ts @@ -0,0 +1,16 @@ +export const nfCatalog = [ + { + title: 'Home', + filter: '/mobile/home?app=1', + }, + { + title: 'Series', + filter: '/mobile/series', + }, + { + title: 'Movies', + filter: '/mobile/movies', + }, +]; + +export const nfGenresList = []; diff --git a/providers/netflixMirror/nfGetEpisodes.ts b/providers/netflixMirror/nfGetEpisodes.ts new file mode 100644 index 0000000..a61ccfa --- /dev/null +++ b/providers/netflixMirror/nfGetEpisodes.ts @@ -0,0 +1,49 @@ +import {EpisodeLink, ProviderContext} from '../types'; + +export const nfGetEpisodes = async function ({ + url: link, + providerContext, +}: { + url: string; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios} = providerContext; + let providerValue = 'netflixMirror'; + try { + const baseUrl = await getBaseUrl('nfMirror'); + const url = + `${baseUrl}${ + providerValue === 'netflixMirror' + ? '/episodes.php?s=' + : '/pv/episodes.php?s=' + }` + + link + + '&t=' + + Math.round(new Date().getTime() / 1000); + console.log('nfEpisodesUrl', url); + const res = await axios.get(url, { + headers: { + 'Content-Type': 'application/json', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36', + 'Accept-Language': 'en-US,en;q=0.9', + }, + }); + const data = res.data; + console.log('nfEpisodes', data); + + const episodeList: EpisodeLink[] = []; + + data?.episodes?.map((episode: any) => { + episodeList.push({ + title: 'Episode ' + episode?.ep.replace('E', ''), + link: episode?.id, + }); + }); + + return episodeList; + } catch (err) { + console.error('nfGetEpisodes error', err); + return []; + } +}; diff --git a/providers/netflixMirror/nfGetInfo.ts b/providers/netflixMirror/nfGetInfo.ts new file mode 100644 index 0000000..fc5c356 --- /dev/null +++ b/providers/netflixMirror/nfGetInfo.ts @@ -0,0 +1,63 @@ +import {Info, Link} from '../types'; + +export const nfGetInfo = async function ({ + link, +}: { + link: string; +}): Promise { + let providerValue = 'netflixMirror'; + try { + const isPrime = + providerValue === 'primeMirror' ? 'isPrime=true' : 'isPrime=false'; + const url = `https://netmirror.8man.me/api/net-proxy?${isPrime}&url=${encodeURIComponent( + link, + )}`; + console.log('nfifo', url); + const res = await fetch(url, { + credentials: 'omit', + }); + const data = await res.json(); + const id = link.split('id=')[1]?.split('&')[0]; + const meta = { + title: data.title, + synopsis: data.desc, + image: `https://img.nfmirrorcdn.top/poster/h/${id}.jpg`, + cast: data?.short_cast?.split(','), + tags: [data?.year, data?.hdsd, ...data?.thismovieis?.split(',')], + imdbId: '', + type: 'series', + }; + console.log('nfinfo', meta); + + const linkList: Link[] = []; + if (data?.season?.length > 0) { + data.season.map((season: any) => { + linkList.push({ + title: 'Season ' + season?.s, + episodesLink: season?.id, + }); + }); + } else { + linkList.push({ + title: meta.title, + directLinks: [{link: id, title: 'Movie', type: 'movie'}], + }); + } + + return { + ...meta, + + linkList: linkList, + }; + } catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: '', + linkList: [], + }; + } +}; diff --git a/providers/netflixMirror/nfGetPost.ts b/providers/netflixMirror/nfGetPost.ts new file mode 100644 index 0000000..a32e02c --- /dev/null +++ b/providers/netflixMirror/nfGetPost.ts @@ -0,0 +1,135 @@ +import {Post, ProviderContext} from '../types'; + +export const nfGetPost = async function ({ + filter, + page, + providerValue, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + try { + const {getBaseUrl, cheerio} = providerContext; + const baseUrl = await getBaseUrl('nfMirror'); + const catalog: Post[] = []; + if (page > 1) { + return []; + } + // console.log(filter); + const isPrime = + providerValue === 'primeMirror' ? 'isPrime=true' : 'isPrime=false'; + + const url = `https://netmirror.8man.me/api/net-proxy?${isPrime}&url=${ + baseUrl + filter + }`; + + const res = await fetch(url, { + signal: signal, + method: 'GET', + credentials: 'omit', + }); + const data = await res.text(); + // console.log('nfPost', data); + const $ = cheerio.load(data); + $('a.post-data').map((i, element) => { + const title = ''; + const id = $(element).attr('data-post'); + // console.log('id', id); + const image = $(element).find('img').attr('data-src') || ''; + if (id) { + catalog.push({ + title: title, + link: + baseUrl + + `${ + providerValue === 'netflixMirror' + ? '/post.php?id=' + : '/pv/post.php?id=' + }` + + id + + '&t=' + + Math.round(new Date().getTime() / 1000), + image: image, + }); + } + }); + // console.log(catalog); + return catalog; + } catch (err) { + console.error('nf error ', err); + return []; + } +}; + +export const nfGetPostsSearch = async function ({ + searchQuery, + page, + providerValue, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl} = providerContext; + try { + if (page > 1) { + return []; + } + const catalog: Post[] = []; + const baseUrl = await getBaseUrl('nfMirror'); + const isPrime = + providerValue === 'primeMirror' ? 'isPrime=true' : 'isPrime=false'; + + const url = `https://netmirror.8man.me/api/net-proxy?${isPrime}&url=${baseUrl}${ + providerValue === 'netflixMirror' ? '' : '/pv' + }/search.php?s=${encodeURI(searchQuery)}`; + + const res = await fetch(url, { + signal: signal, + method: 'GET', + credentials: 'omit', + }); + + const data = await res.json(); + + data?.searchResult?.forEach((result: any) => { + const title = result?.t || ''; + const id = result?.id; + const image = + providerValue === 'netflixMirror' + ? `https://imgcdn.media/poster/v/${id}.jpg` + : ''; + + if (id) { + catalog.push({ + title: title, + link: + baseUrl + + `${ + providerValue === 'netflixMirror' + ? '/mobile/post.php?id=' + : '/mobile/pv/post.php?id=' + }` + + id + + '&t=' + + Math.round(new Date().getTime() / 1000), + image: image, + }); + } + }); + + return catalog; + } catch (err) { + console.error('Search error:', err); + return []; + } +}; diff --git a/providers/netflixMirror/nfGetSteam.ts b/providers/netflixMirror/nfGetSteam.ts new file mode 100644 index 0000000..516dcc9 --- /dev/null +++ b/providers/netflixMirror/nfGetSteam.ts @@ -0,0 +1,44 @@ +import {ProviderContext, Stream} from '../types'; + +export const nfGetStream = async ({ + link: id, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise => { + const {getBaseUrl} = providerContext; + try { + let providerValue = 'netflixMirror'; + const baseUrl = await getBaseUrl('nfMirror'); + const url = `https://netmirror.8man.me/api/net-proxy?url=${baseUrl}${ + providerValue === 'netflixMirror' + ? '/mobile/playlist.php?id=' + : '/pv/playlist.php?id=' + }${id}&t=${Math.round(new Date().getTime() / 1000)}`; + console.log('nfGetStream, url:', url); + const res = await fetch(url, { + credentials: 'omit', + }); + const resJson = await res.json(); + const data = resJson?.[0]; + const streamLinks: Stream[] = []; + data?.sources.forEach((source: any) => { + streamLinks.push({ + server: source.label, + link: (baseUrl + source.file)?.replace(':su', ':ni'), + type: 'm3u8', + headers: { + Referer: baseUrl, + origin: baseUrl, + Cookie: 'hd=on', + }, + }); + }); + console.log(streamLinks); + return streamLinks; + } catch (err) { + console.error(err); + return []; + } +}; diff --git a/providers/primeMirror/index.ts b/providers/primeMirror/index.ts new file mode 100644 index 0000000..0abe7c3 --- /dev/null +++ b/providers/primeMirror/index.ts @@ -0,0 +1,16 @@ +import {nfCatalog, nfGenresList} from '../netflixMirror/nfCatalog'; +import {nfGetPost, nfGetPostsSearch} from '../netflixMirror/nfGetPost'; +import {ProviderType} from '../types'; +import {pmGetInfo} from './pmGetInfo'; +import {pmGetStream} from './pmGetStream'; +import {pmGetEpisodes} from './pmGetEpisodes'; + +export const primeMirror: ProviderType = { + catalog: nfCatalog, + genres: nfGenresList, + GetMetaData: pmGetInfo, + GetHomePosts: nfGetPost, + GetStream: pmGetStream, + GetEpisodeLinks: pmGetEpisodes, + GetSearchPosts: nfGetPostsSearch, +}; diff --git a/providers/primeMirror/pmGetEpisodes.ts b/providers/primeMirror/pmGetEpisodes.ts new file mode 100644 index 0000000..e148e09 --- /dev/null +++ b/providers/primeMirror/pmGetEpisodes.ts @@ -0,0 +1,49 @@ +import {EpisodeLink, ProviderContext} from '../types'; + +export const pmGetEpisodes = async function ({ + url: link, + providerContext, +}: { + url: string; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios} = providerContext; + let providerValue = 'primeMirror'; + try { + const baseUrl = await getBaseUrl('nfMirror'); + const url = + `${baseUrl}${ + providerValue === 'netflixMirror' + ? '/episodes.php?s=' + : '/pv/episodes.php?s=' + }` + + link + + '&t=' + + Math.round(new Date().getTime() / 1000); + console.log('nfEpisodesUrl', url); + const res = await axios.get(url, { + headers: { + 'Content-Type': 'application/json', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36', + 'Accept-Language': 'en-US,en;q=0.9', + }, + }); + const data = res.data; + console.log('nfEpisodes', data); + + const episodeList: EpisodeLink[] = []; + + data?.episodes?.map((episode: any) => { + episodeList.push({ + title: 'Episode ' + episode?.ep.replace('E', ''), + link: episode?.id, + }); + }); + + return episodeList; + } catch (err) { + console.error('nfGetEpisodes error', err); + return []; + } +}; diff --git a/providers/primeMirror/pmGetInfo.ts b/providers/primeMirror/pmGetInfo.ts new file mode 100644 index 0000000..b30f451 --- /dev/null +++ b/providers/primeMirror/pmGetInfo.ts @@ -0,0 +1,63 @@ +import {Info, Link} from '../types'; + +export const pmGetInfo = async function ({ + link, +}: { + link: string; +}): Promise { + let providerValue = 'primeMirror'; + try { + const isPrime = + providerValue === 'primeMirror' ? 'isPrime=true' : 'isPrime=false'; + const url = `https://netmirror.8man.me/api/net-proxy?${isPrime}&url=${encodeURIComponent( + link, + )}`; + console.log('nfifo', url); + const res = await fetch(url, { + credentials: 'omit', + }); + const data = await res.json(); + const id = link.split('id=')[1]?.split('&')[0]; + const meta = { + title: data.title, + synopsis: data.desc, + image: `https://img.nfmirrorcdn.top/poster/h/${id}.jpg`, + cast: data?.short_cast?.split(','), + tags: [data?.year, data?.hdsd, ...data?.thismovieis?.split(',')], + imdbId: '', + type: 'series', + }; + console.log('nfinfo', meta); + + const linkList: Link[] = []; + if (data?.season?.length > 0) { + data.season.map((season: any) => { + linkList.push({ + title: 'Season ' + season?.s, + episodesLink: season?.id, + }); + }); + } else { + linkList.push({ + title: meta.title, + directLinks: [{link: id, title: 'Movie', type: 'movie'}], + }); + } + + return { + ...meta, + + linkList: linkList, + }; + } catch (err) { + console.error(err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: '', + linkList: [], + }; + } +}; diff --git a/providers/primeMirror/pmGetStream.ts b/providers/primeMirror/pmGetStream.ts new file mode 100644 index 0000000..4bfb535 --- /dev/null +++ b/providers/primeMirror/pmGetStream.ts @@ -0,0 +1,44 @@ +import {ProviderContext, Stream} from '../types'; + +export const pmGetStream = async ({ + link: id, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise => { + const {getBaseUrl} = providerContext; + try { + let providerValue = 'primeMirror'; + const baseUrl = await getBaseUrl('nfMirror'); + const url = `https://netmirror.8man.me/api/net-proxy?url=${baseUrl}${ + providerValue === 'netflixMirror' + ? '/mobile/playlist.php?id=' + : '/pv/playlist.php?id=' + }${id}&t=${Math.round(new Date().getTime() / 1000)}`; + console.log('nfGetStream, url:', url); + const res = await fetch(url, { + credentials: 'omit', + }); + const resJson = await res.json(); + const data = resJson?.[0]; + const streamLinks: Stream[] = []; + data?.sources.forEach((source: any) => { + streamLinks.push({ + server: source.label, + link: (baseUrl + source.file)?.replace(':su', ':ni'), + type: 'm3u8', + headers: { + Referer: baseUrl, + origin: baseUrl, + Cookie: 'hd=on', + }, + }); + }); + console.log(streamLinks); + return streamLinks; + } catch (err) { + console.error(err); + return []; + } +}; diff --git a/providers/primewire/index.ts b/providers/primewire/index.ts new file mode 100644 index 0000000..a294547 --- /dev/null +++ b/providers/primewire/index.ts @@ -0,0 +1,14 @@ +import {pwCatalogList, pwGenresList} from './pwCatalogl'; +import {pwGetPosts, pwGetPostsSearch} from './pwGetPosts'; +import {pwGetInfo} from './pwGetInfo'; +import {pwGetStream} from './pwGetStream'; +import {ProviderType} from '../types'; + +export const primewire: ProviderType = { + catalog: pwCatalogList, + genres: pwGenresList, + GetMetaData: pwGetInfo, + GetHomePosts: pwGetPosts, + GetStream: pwGetStream, + GetSearchPosts: pwGetPostsSearch, +}; diff --git a/providers/primewire/pwCatalogl.ts b/providers/primewire/pwCatalogl.ts new file mode 100644 index 0000000..895eef0 --- /dev/null +++ b/providers/primewire/pwCatalogl.ts @@ -0,0 +1,16 @@ +export const pwCatalogList = [ + { + title: 'Recently Added', + filter: '/filter?sort=Just+Added&free_links=true', + }, + { + title: 'TV Shows', + filter: '/filter?sort=Trending+Today&type=tv', + }, + { + title: 'Movies', + filter: '/filter?sort=Trending+Today&type=movie', + }, +]; + +export const pwGenresList = []; diff --git a/providers/primewire/pwGetInfo.ts b/providers/primewire/pwGetInfo.ts new file mode 100644 index 0000000..9fe7441 --- /dev/null +++ b/providers/primewire/pwGetInfo.ts @@ -0,0 +1,82 @@ +import {Info, Link, ProviderContext} from '../types'; + +export const pwGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, cheerio} = providerContext; + const url = link; + const baseUrl = link.split('/').slice(0, 3).join('/'); + const res = await axios.get(url); + const html = await res.data; + const $ = cheerio.load(html); + const imdbId = + $('.movie_info') + .find('a[href*="imdb.com/title/tt"]:not([href*="imdb.com/title/tt/"])') + .attr('href') + ?.split('/')[4] || ''; + const type = $('.show_season').html() ? 'series' : 'movie'; + const linkList: Link[] = []; + $('.show_season').each((i, element) => { + const seasonTitle = 'Season ' + $(element).attr('data-id'); + const episodes: Link['directLinks'] = []; + $(element) + .children() + .each((i, element2) => { + const episodeTitle = $(element2) + .find('a') + .children() + .remove() + .end() + .text() + .trim() + .replace('E', 'Epiosode '); + const episodeLink = baseUrl + $(element2).find('a').attr('href'); + if (episodeTitle && episodeLink) { + episodes.push({ + title: episodeTitle, + link: episodeLink, + }); + } + }); + linkList.push({ + title: seasonTitle, + directLinks: episodes, + }); + }); + if (type === 'movie') { + linkList.push({ + title: 'Movie', + directLinks: [ + { + link: link, + title: 'Movie', + type: 'movie', + }, + ], + }); + } + return { + title: '', + image: '', + imdbId: imdbId, + synopsis: '', + type: type, + linkList: linkList, + }; + } catch (error) { + console.error(error); + return { + title: '', + image: '', + imdbId: '', + synopsis: '', + linkList: [], + type: 'uhd', + }; + } +}; diff --git a/providers/primewire/pwGetPosts.ts b/providers/primewire/pwGetPosts.ts new file mode 100644 index 0000000..0375f4e --- /dev/null +++ b/providers/primewire/pwGetPosts.ts @@ -0,0 +1,82 @@ +import {Post, ProviderContext} from '../types'; + +export const pwGetPosts = async function ({ + filter, + page, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios, cheerio} = providerContext; + + const baseUrl = await getBaseUrl('primewire'); + const url = `${baseUrl + filter}&page=${page}`; + return posts({baseUrl, url, signal, axios, cheerio}); +}; + +export const pwGetPostsSearch = async function ({ + searchQuery, + page, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios, cheerio, Aes} = providerContext; + const getSHA256ofJSON = async function (input: any) { + return await Aes.sha1(input); + }; + const baseUrl = await getBaseUrl('primewire'); + const hash = await getSHA256ofJSON(searchQuery + 'JyjId97F9PVqUPuMO0'); + const url = `${baseUrl}/filter?s=${searchQuery}&page=${page}&ds=${hash.slice( + 0, + 10, + )}`; + return posts({baseUrl, url, signal, axios, cheerio}); +}; + +async function posts({ + baseUrl, + url, + signal, + axios, + cheerio, +}: { + baseUrl: string; + url: string; + signal: AbortSignal; + axios: ProviderContext['axios']; + cheerio: ProviderContext['cheerio']; +}): Promise { + try { + const res = await axios.get(url, {signal}); + const data = res.data; + const $ = cheerio.load(data); + const catalog: Post[] = []; + $('.index_item.index_item_ie').map((i, element) => { + const title = $(element).find('a').attr('title'); + const link = $(element).find('a').attr('href'); + const image = $(element).find('img').attr('src') || ''; + if (title && link) { + catalog.push({ + title: title, + link: baseUrl + link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('primewire error ', err); + return []; + } +} diff --git a/providers/primewire/pwGetStream.ts b/providers/primewire/pwGetStream.ts new file mode 100644 index 0000000..5798298 --- /dev/null +++ b/providers/primewire/pwGetStream.ts @@ -0,0 +1,155 @@ +import {Stream, ProviderContext} from '../types'; + +export const pwGetStream = async function ({ + link: url, + type, + providerContext, +}: { + link: string; + type: string; + providerContext: ProviderContext; +}): Promise { + const {axios, cheerio} = providerContext; + try { + console.log('pwGetStream', type, url); + const baseUrl = url.split('/').slice(0, 3).join('/'); + const streamLinks: Stream[] = []; + const urls: {id: string; size: string}[] = []; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + $('tr:contains("mixdrop")').map((i, element) => { + const id = $(element).find('.wp-menu-btn').attr('data-wp-menu'); + const size = $(element).find('.wp-menu-btn').next().text(); + if (id) { + urls.push({id: baseUrl + '/links/go/' + id, size}); + } + }); + + console.log('urls', urls); + + for (const url of urls) { + const res2 = await axios.head(url.id); + const location = res2.request?.responseURL.replace('/f/', '/e/'); + + const res3 = await fetch(location, { + credentials: 'include', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0', + Accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', + 'Accept-Language': 'en-US,en;q=0.5', + 'Upgrade-Insecure-Requests': '1', + 'Sec-Fetch-Dest': 'iframe', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'same-origin', + Pragma: 'no-cache', + 'Cache-Control': 'no-cache', + referer: res2.request?.responseURL, + }, + referrer: res2.request?.responseURL, + method: 'GET', + mode: 'cors', + }); + const data3 = await res3.text(); + + // let MDCore: any = {}; + // Step 1: Extract the function parameters and the encoded string + var functionRegex = + /eval\(function\((.*?)\)\{.*?return p\}.*?\('(.*?)'\.split/; + var match = functionRegex.exec(data3); + let p = ''; + if (match) { + // var params = match[1].split(',').map(param => param.trim()); + var encodedString = match[2]; + console.log('Encoded String:', encodedString); + + // console.log('Parameters:', params); + // console.log('Encoded String:', encodedString.split("',36,")[0], '🔥🔥'); + + const base = Number( + encodedString.split(",'|MDCore|")[0].split(',')[ + encodedString.split(",'|MDCore|")[0].split(',').length - 1 + ], + ); + console.log('Base:', base); + + p = encodedString.split(`',${base},`)?.[0].trim(); + let a = base; + let c = encodedString.split(`',${base},`)[1].slice(2).split('|').length; + let k = encodedString.split(`',${base},`)[1].slice(2).split('|'); + + // console.log('p:', p); + // console.log('a:', a); + // console.log('c:', c); + // console.log('k:', k); + + const decode = function ( + p: any, + a: any, + c: any, + k: any, + e: any, + d: any, + ) { + e = function (c: any) { + return c.toString(36); + }; + if (!''.replace(/^/, String)) { + while (c--) { + d[c.toString(a)] = k[c] || c.toString(a); + } + k = [ + function (e: any) { + return d[e]; + }, + ]; + e = function () { + return '\\w+'; + }; + c = 1; + } + while (c--) { + if (k[c]) { + p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]); + } + } + return p; + }; + + const decoded = decode(p, a, c, k, 0, {}); + // get MDCore.wurl= + const wurl = decoded.match(/MDCore\.wurl="([^"]+)"/)?.[1]; + console.log('wurl:', wurl); + const streamUrl = 'https:' + wurl; + console.log('streamUrl:', streamUrl); + streamLinks.push({ + server: 'Mixdrop ' + url.size, + link: streamUrl, + type: 'mp4', + headers: { + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:101.0) Gecko/20100101 Firefox/101.0', + Accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', + 'Accept-Language': 'en-US,en;q=0.5', + 'Upgrade-Insecure-Requests': '1', + 'Sec-Fetch-Dest': 'iframe', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'same-origin', + Pragma: 'no-cache', + 'Cache-Control': 'no-cache', + referer: res2.request?.responseURL, + }, + }); + } else { + console.log('No match found'); + } + } + return streamLinks; + } catch (err) { + console.error(err); + return []; + } +}; diff --git a/providers/protonMovies/index.ts b/providers/protonMovies/index.ts new file mode 100644 index 0000000..299eae8 --- /dev/null +++ b/providers/protonMovies/index.ts @@ -0,0 +1,14 @@ +import {protonGenresList, protonCatalogList} from './protonCatalog'; +import {protonGetPosts, protonGetPostsSearch} from './protonGetPosts'; +import {protonGetInfo} from './protonGetMeta'; +import {ProviderType} from '../types'; +import {protonGetStream} from './protonGetStream'; + +export const protonMovies: ProviderType = { + catalog: protonCatalogList, + genres: protonGenresList, + GetMetaData: protonGetInfo, + GetHomePosts: protonGetPosts, + GetStream: protonGetStream, + GetSearchPosts: protonGetPostsSearch, +}; diff --git a/providers/protonMovies/protonCatalog.ts b/providers/protonMovies/protonCatalog.ts new file mode 100644 index 0000000..676b5a0 --- /dev/null +++ b/providers/protonMovies/protonCatalog.ts @@ -0,0 +1,20 @@ +export const protonCatalogList = [ + { + title: 'Latest', + filter: '/movies', + }, + { + title: 'Netflix', + filter: '/platform/netflix', + }, + { + title: 'Disney +', + filter: '/platform/disney-hotstar', + }, + { + title: 'Amazon Prime', + filter: '/platform/amazon-prime-video', + }, +]; + +export const protonGenresList = []; diff --git a/providers/protonMovies/protonGetMeta.ts b/providers/protonMovies/protonGetMeta.ts new file mode 100644 index 0000000..e7eab11 --- /dev/null +++ b/providers/protonMovies/protonGetMeta.ts @@ -0,0 +1,109 @@ +import {EpisodeLink, Info, Link, ProviderContext} from '../types'; + +export const protonGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, cheerio, getBaseUrl} = providerContext; + console.log('all', link); + const res = await axios.get(link); + const data = res.data; + + function decodeHtml(encodedArray: string[]): string { + // Join array elements into a single string + const joined = encodedArray.join(''); + + // Replace escaped quotes + const unescaped = joined.replace(/\\"/g, '"').replace(/\\'/g, "'"); + + // Remove remaining escape characters + const cleaned = unescaped + .replace(/\\n/g, '\n') + .replace(/\\t/g, '\t') + .replace(/\\r/g, '\r'); + + // Convert literal string representations back to characters + const decoded = cleaned + .replace(/"/g, '"') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/&/g, '&'); + + return decoded; + } + + const $$ = cheerio.load(data); + const htmlArray = $$('script:contains("decodeURIComponent")') + .text() + .split(' = ')?.[1] + ?.split('protomovies')?.[0] + ?.trim() + ?.slice(0, -1); // remove the last character + // console.log('protonGetInfo', htmlArray); + const html = decodeHtml(JSON.parse(htmlArray)); + // console.log('all', html); + const $ = cheerio.load(html); + + const title = $( + '.trending-text.fw-bold.texture-text.text-uppercase.my-0.fadeInLeft.animated.d-inline-block', + ).text(); + const image = $('#thumbnail').attr('src'); + const type = link.includes('series') ? 'series' : 'movie'; + const synopsis = + $('.col-12.iq-mb-30.animated.fadeIn').first().text() || + $('.description-content').text(); + const tags = $('.p-0.mt-2.list-inline.d-flex.flex-wrap.movie-tag') + .find('li') + .map((i, el) => $(el).text()) + .slice(0, 3) + .get(); + + const baseUrl = await getBaseUrl('protonMovies'); + const links: Link[] = []; + + if (type === 'movie') { + const directLinks: EpisodeLink[] = []; + directLinks.push({title: 'Movie', link: link}); + links.push({title: 'Movie', directLinks: directLinks}); + } else { + $('#episodes') + .children() + .map((i, element) => { + let directLinks: EpisodeLink[] = []; + $(element) + .find('.episode-block') + .map((j, ep) => { + const link = baseUrl + $(ep).find('a').attr('href') || ''; + const title = + 'Episode ' + $(ep).find('.episode-number').text().split('E')[1]; + directLinks.push({title, link}); + }); + links.push({title: 'Season ' + (i + 1), directLinks: directLinks}); + }); + } + + return { + image: image || '', + imdbId: '', + linkList: links, + title: title || '', + synopsis: synopsis, + tags: tags, + type: type, + }; + } catch (err) { + console.error('prton', err); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/protonMovies/protonGetPosts.ts b/providers/protonMovies/protonGetPosts.ts new file mode 100644 index 0000000..15d1b9d --- /dev/null +++ b/providers/protonMovies/protonGetPosts.ts @@ -0,0 +1,107 @@ +import {Post, ProviderContext} from '../types'; + +export const protonGetPosts = async function ({ + filter, + page, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios, cheerio} = providerContext; + const baseUrl = await getBaseUrl('protonMovies'); + const url = `${baseUrl + filter}/page/${page}/`; + return posts({url, baseUrl, signal, axios, cheerio}); +}; + +export const protonGetPostsSearch = async function ({ + searchQuery, + page, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios, cheerio} = providerContext; + const baseUrl = await getBaseUrl('protonMovies'); + const url = `${baseUrl}/search/${searchQuery}/page/${page}/`; + return posts({url, baseUrl, signal, axios, cheerio}); +}; + +async function posts({ + url, + baseUrl, + signal, + axios, + cheerio, +}: { + url: string; + baseUrl: string; + signal: AbortSignal; + axios: ProviderContext['axios']; + cheerio: ProviderContext['cheerio']; +}): Promise { + function decodeHtml(encodedArray: string[]): string { + // Join array elements into a single string + const joined = encodedArray.join(''); + + // Replace escaped quotes + const unescaped = joined.replace(/\\"/g, '"').replace(/\\'/g, "'"); + + // Remove remaining escape characters + const cleaned = unescaped + .replace(/\\n/g, '\n') + .replace(/\\t/g, '\t') + .replace(/\\r/g, '\r'); + + // Convert literal string representations back to characters + const decoded = cleaned + .replace(/"/g, '"') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/&/g, '&'); + + return decoded; + } + try { + const res = await axios.get(url, { + headers: { + referer: baseUrl, + }, + signal, + }); + const data = res.data; + const regex = /\[(?=.*?"
{ + const title = $(element).find('h5').text(); + const link = $(element).find('h5').find('a').attr('href'); + const image = + $(element).find('img').attr('data-src') || + $(element).find('img').attr('src') || + ''; + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('protonGetPosts error ', err); + return []; + } +} diff --git a/providers/protonMovies/protonGetStream.ts b/providers/protonMovies/protonGetStream.ts new file mode 100644 index 0000000..e8ac52d --- /dev/null +++ b/providers/protonMovies/protonGetStream.ts @@ -0,0 +1,200 @@ +import {Stream, ProviderContext} from '../types'; + +function LALLJLutmoZpvvbikjaWM(str: string): ArrayBuffer { + var buf = new ArrayBuffer(str.length * 2); + var bufView = new Uint8Array(buf); + for (var i = 0, strLen = str.length; i < strLen; i++) { + bufView[i] = str.charCodeAt(i); + } + return buf; +} + +function getOrCreateUID() { + const uid = + 'uid_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); + + return uid; +} + +export const protonGetStream = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + const {axios, cheerio, commonHeaders: headers, extractors} = providerContext; + const {gofileExtracter} = extractors; + function generateMessageToken(baseUrlL: string): string { + const hostname = baseUrlL?.replace(/https?:\/\//, '').split('/')[0]; + console.log('generateMessageToken hostname', hostname); + const NsmxUftCNibQ = `[hostname=${hostname}][agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0][tmz=India Standard Time][userTimezoneOffset=-330][{"url":"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js","type":"script","duration":253.30000000074506},{"url":"https://challenges.cloudflare.com/turnstile/v0/api.js?onload=onloadTurnstileCallback","type":"script","duration":397.19999999925494},{"url":"https://adoto.net/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js","type":"img","duration":225.90000000223517},{"url":"https://code.jquery.com/jquery-3.3.1.slim.min.js","type":"script","duration":65.30000000074506},{"url":"https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015","type":"script","duration":225.89999999850988},{"url":"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js","type":"script","duration":253.30000000074506},{"url":"https://challenges.cloudflare.com/turnstile/v0/api.js?onload=onloadTurnstileCallback","type":"script","duration":397.19999999925494},{"url":"https://adoto.net/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js","type":"img","duration":225.90000000223517},{"url":"https://code.jquery.com/jquery-3.3.1.slim.min.js","type":"script","duration":65.30000000074506},{"url":"https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015","type":"script","duration":225.89999999850988},{"url":"https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/b/turnstile/if/ov2/av0/rcv/b3dhg/0x4AAAAAAAQDru7r64xT2ifD/auto/fbE/new/normal/auto/","type":"iframe","duration":2050.300000000745},{"url":"https://new19.gdtot.dad/favicon.ico","type":"img","duration":1003.6999999992549},{"url":"https://vikingfile.com/assets/favicon-64375c377b5df8304acbdad4f4430694.ico","type":"img","duration":183.19999999925494},{"url":"https://gofile.io/dist/img/favicon32.png","type":"img","duration":19177.199999999255},{"url":"https://pub.clickadu.com/assets/scripts/supported-browsers.js","type":"fetch","duration":18.799999997019768},{"url":"https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/b/turnstile/if/ov2/av0/rcv/b3dhg/0x4AAAAAAAQDru7r64xT2ifD/auto/fbE/auto_expire/normal/auto/","type":"iframe","duration":1612.5999999977648},{"url":"https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/b/turnstile/if/ov2/av0/rcv/b3dhg/0x4AAAAAAAQDru7r64xT2ifD/auto/fbE/auto_expire/normal/auto/","type":"iframe","duration":1154.0999999977648},{"url":"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js","type":"script","duration":253.30000000074506},{"url":"https://challenges.cloudflare.com/turnstile/v0/api.js?onload=onloadTurnstileCallback","type":"script","duration":397.19999999925494},{"url":"https://adoto.net/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js","type":"img","duration":225.90000000223517},{"url":"https://code.jquery.com/jquery-3.3.1.slim.min.js","type":"script","duration":65.30000000074506},{"url":"https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015","type":"script","duration":225.89999999850988},{"url":"https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/b/turnstile/if/ov2/av0/rcv/b3dhg/0x4AAAAAAAQDru7r64xT2ifD/auto/fbE/new/normal/auto/","type":"iframe","duration":2050.300000000745},{"url":"https://new19.gdtot.dad/favicon.ico","type":"img","duration":1003.6999999992549},{"url":"https://vikingfile.com/assets/favicon-64375c377b5df8304acbdad4f4430694.ico","type":"img","duration":183.19999999925494},{"url":"https://gofile.io/dist/img/favicon32.png","type":"img","duration":19177.199999999255},{"url":"https://pub.clickadu.com/assets/scripts/supported-browsers.js","type":"fetch","duration":18.799999997019768},{"url":"https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/b/turnstile/if/ov2/av0/rcv/b3dhg/0x4AAAAAAAQDru7r64xT2ifD/auto/fbE/auto_expire/normal/auto/","type":"iframe","duration":1612.5999999977648},{"url":"https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/b/turnstile/if/ov2/av0/rcv/b3dhg/0x4AAAAAAAQDru7r64xT2ifD/auto/fbE/auto_expire/normal/auto/","type":"iframe","duration":1154.0999999977648},{"url":"https://challenges.cloudflare.com/cdn-cgi/challenge-platform/h/b/turnstile/if/ov2/av0/rcv/b3dhg/0x4AAAAAAAQDru7r64xT2ifD/auto/fbE/auto_expire/normal/auto/","type":"iframe","duration":986}][{"elements":{"div":70,"span":68,"img":4,"iframe":0,"script":28,"link":20,"p":5,"a":213,"ul":28,"li":208,"button":9,"input":5},"hidden":{"div":13,"span":60,"img":1,"iframe":0,"script":28,"link":20,"p":0,"a":186,"ul":22,"li":184,"button":6,"input":2},"errors":{"network":0,"js":0},"eventListeners":0}]`; + + var jRpeP = LALLJLutmoZpvvbikjaWM(NsmxUftCNibQ); + var jzKEwqEAcWFMNwHZnCCqJQ = new Uint8Array(jRpeP); + var kyMXQUxoFYuZIBlKvlHa = jzKEwqEAcWFMNwHZnCCqJQ.toString(); + var kyMXQUxoFYuZIBlKvlHa = kyMXQUxoFYuZIBlKvlHa.replace(/2/g, '004'); + var kyMXQUxoFYuZIBlKvlHa = kyMXQUxoFYuZIBlKvlHa.replace(/3/g, '005'); + var kyMXQUxoFYuZIBlKvlHa = kyMXQUxoFYuZIBlKvlHa.replace(/7/g, '007'); + var kyMXQUxoFYuZIBlKvlHa = kyMXQUxoFYuZIBlKvlHa.replace(/,0,0,0/g, ''); + + return kyMXQUxoFYuZIBlKvlHa; + } + function decodeHtml(encodedArray: string[]): string { + // Join array elements into a single string + const joined = encodedArray.join(''); + + // Replace escaped quotes + const unescaped = joined.replace(/\\"/g, '"').replace(/\\'/g, "'"); + + // Remove remaining escape characters + const cleaned = unescaped + .replace(/\\n/g, '\n') + .replace(/\\t/g, '\t') + .replace(/\\r/g, '\r'); + + // Convert literal string representations back to characters + const decoded = cleaned + .replace(/"/g, '"') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/&/g, '&'); + + return decoded; + } + try { + const streamLinks: Stream[] = []; + const res = await axios.get(link, {headers}); + const data = res.data; + // const regex = /\[(?=.*?"
{ + const formData = new URLSearchParams(); + formData.append('downloadid', id.id); + formData.append('token', 'ok'); + const messageToken = generateMessageToken(baseUrl); + const uid = getOrCreateUID(); + + const idRes = await fetch(`${baseUrl}/ppd.php`, { + headers: { + accept: '*/*', + 'accept-language': 'en-US,en;q=0.9,en-IN;q=0.8', + 'cache-control': 'no-cache', + 'content-type': 'application/x-www-form-urlencoded', + pragma: 'no-cache', + priority: 'u=1, i', + 'sec-ch-ua': + '"Chromium";v="136", "Microsoft Edge";v="136", "Not.A/Brand";v="99"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'sec-fetch-dest': 'empty', + 'sec-fetch-mode': 'cors', + 'sec-fetch-site': 'same-origin', + cookie: + 'ext_name=ojplmecpdpgccookcobabopnaifgidhf; tgInvite222=true; cf_clearance=3ynJv2B6lHMj3FCOqtfQaL7lTN4KC3xmPRMgcNtddAc-1748787867-1.2.1.1-SEIhLbWR3ehfib5Y3P5pjzj1Qu9wipc52Icv4AmNkztXn2pTXhjKgxXnvTuA2bNscgHuc1juXujAHteqY_vaMmy2C3djMWnJGzjje_XvXZXKht8rwHZt6sviq7KAYvrYZPTrATqENuopzmqmK6dDFS.CAnWHt0VDn8q06iLm5rYj1AXUo3qkV5p1Idx_25elWHYGG8yengBrQV1MYVM9LMdQqv44PXu69FZvNkgv.d6blCKyneJnoLkw4LHAccu.QRPbFwWqqTDyO9YTLRQW9w29bKghD3_JVxkz.qxpg5FbocJ3i6tJJy74SvROpYdpVUOn0fW1YgQ7RxYwhNoHpdTKy8pvmQJGRuSVW1GjO_k', + Referer: 'https://m3.protonmovies.top/download/', + 'Referrer-Policy': 'strict-origin-when-cross-origin', + }, + body: `downloadid=${id.id}&msg=${messageToken}&uid=${uid}&token=ok`, + method: 'POST', + }); + const idData = await idRes.text(); + secondIdList.push({ + quality: id.quality, + id: idData, + }); + console.log('idData', idData); + }), + ); + await Promise.all( + secondIdList.map(async id => { + const idRes = await axios.post(`${baseUrl}/tmp/${id.id}`); + if (idRes.data.ppd['gofile.io']) { + const goRes = await gofileExtracter( + idRes.data.ppd['gofile.io'].link.split('/').pop(), + ); + console.log('link', goRes.link); + if (goRes.link) { + streamLinks.push({ + link: goRes.link, + server: 'gofile ' + id.quality, + type: 'mkv', + headers: { + referer: 'https://gofile.io', + connection: 'keep-alive', + contentType: 'video/x-matroska', + cookie: 'accountToken=' + goRes.token, + }, + }); + } + } + }), + ); + + return streamLinks; + } catch (e) { + console.log('proton get stream err', e); + return []; + } +}; diff --git a/providers/providerContext.ts b/providers/providerContext.ts new file mode 100644 index 0000000..1c30e85 --- /dev/null +++ b/providers/providerContext.ts @@ -0,0 +1,31 @@ +import axios from 'axios'; +import {getBaseUrl} from './getBaseUrl'; +import {headers} from './headers'; +import * as cheerio from 'cheerio'; +import {hubcloudExtracter} from './hubcloudExtractor'; +import {gofileExtracter} from './gofileExtracter'; +import {superVideoExtractor} from './superVideoExtractor'; +import {gdFlixExtracter} from './gdflixExtractor'; +import {ProviderContext} from './types'; +import Aes from 'react-native-aes-crypto'; + +/** + * Context for provider functions. + * This context is used to pass common dependencies to provider functions. + */ + +const extractors = { + hubcloudExtracter, + gofileExtracter, + superVideoExtractor, + gdFlixExtracter, +}; + +export const providerContext: ProviderContext = { + axios, + getBaseUrl, + commonHeaders: headers, + Aes, + cheerio, + extractors, +}; diff --git a/providers/ridoMovies/index.ts b/providers/ridoMovies/index.ts new file mode 100644 index 0000000..ce8fdd8 --- /dev/null +++ b/providers/ridoMovies/index.ts @@ -0,0 +1,15 @@ +import {ProviderType} from '../types'; +import {guardahdCatalog, guardahdGenresList} from '../guardahd/guardahdCatalog'; +import {allGetPost} from '../autoEmbed/allGetPost'; +import {guardahdGetSearchPosts} from '../guardahd/guardahdGetPosts'; +import {ridoGetInfo} from './ridoGetMeta'; +import {ridoGetStream} from './ridoGetSream'; + +export const ridoMovies: ProviderType = { + catalog: guardahdCatalog, + genres: guardahdGenresList, + GetMetaData: ridoGetInfo, + GetHomePosts: allGetPost, + GetStream: ridoGetStream, + GetSearchPosts: guardahdGetSearchPosts, +}; diff --git a/providers/ridoMovies/ridoGetMeta.ts b/providers/ridoMovies/ridoGetMeta.ts new file mode 100644 index 0000000..4cc34be --- /dev/null +++ b/providers/ridoMovies/ridoGetMeta.ts @@ -0,0 +1,87 @@ +import {EpisodeLink, Info, Link, ProviderContext} from '../types'; + +export const ridoGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {getBaseUrl, axios} = providerContext; + const res = await axios.get(link); + const data = res.data; + const meta = { + title: '', + synopsis: '', + image: '', + imdbId: data?.meta?.imdb_id || '', + type: data?.meta?.type || 'movie', + }; + const baseUrl = await getBaseUrl('ridomovies'); + let slug = ''; + try { + const res2 = await axios.get( + baseUrl + '/core/api/search?q=' + meta.imdbId, + ); + const data2 = res2.data; + slug = data2?.data?.items[0]?.fullSlug; + if (!slug || meta?.type === 'series') { + return { + title: '', + synopsis: '', + image: '', + imdbId: data?.meta?.imdb_id || '', + type: meta?.type || 'movie', + linkList: [], + }; + } + } catch (err) { + return { + title: '', + synopsis: '', + image: '', + imdbId: meta?.imdbId || '', + type: meta?.type || 'movie', + linkList: [], + }; + } + const links: Link[] = []; + let directLinks: EpisodeLink[] = []; + let season = new Map(); + if (meta.type === 'series') { + data?.meta?.videos?.map((video: any) => { + if (video?.season <= 0) return; + if (!season.has(video?.season)) { + season.set(video?.season, []); + } + season.get(video?.season).push({ + title: 'Episode ' + video?.episode, + link: '', + }); + }); + for (const [seasonNum, episodes] of season.entries()) { + links.push({ + title: 'Season ' + seasonNum, + directLinks: episodes, + }); + } + } else { + directLinks.push({title: 'Movie', link: link}); + links.push({title: 'Movie', directLinks: directLinks}); + } + return { + ...meta, + linkList: links, + }; + } catch (err) { + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/ridoMovies/ridoGetSream.ts b/providers/ridoMovies/ridoGetSream.ts new file mode 100644 index 0000000..bed7020 --- /dev/null +++ b/providers/ridoMovies/ridoGetSream.ts @@ -0,0 +1,75 @@ +import {ProviderContext, Stream} from '../types'; + +export const ridoGetStream = async ({ + link: data, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise => { + try { + const {cheerio, commonHeaders: headers, axios} = providerContext; + const streamData = JSON.parse(data); + const streamLinks: Stream[] = []; + + // const path = + // streamData?.type === 'movie' + // ? `/${streamData?.slug}` + // : `/${streamData?.slug}/season-${streamData?.season}/episode-${streamData?.episode}`; + // const url = streamData?.baseUrl + path; + // console.log('all', url); + // const res = await axios.get(url, {headers}); + // const postId = res.data.split('\\"postid\\":\\"')[1].split('\\"')[0]; + // console.log('rido post id', postId); + + const url = streamData?.baseUrl + '/api/' + streamData?.slug; + console.log('rido url', url); + + const res = await axios.get(url, {headers}); + const iframe = res.data.data?.[0]?.url; + + console.log('rido data', iframe); + const iframeUrl = iframe.split('src="')[1].split('"')[0]; + console.log('rido iframeUrl', iframeUrl); + const iframeRes = await axios.get(iframeUrl, { + headers: { + ...headers, + Referer: streamData?.baseUrl, + }, + }); + const $ = cheerio.load(iframeRes.data); + const script = $('script:contains("eval")').html(); + if (!script) { + throw new Error('Unable to find script'); + } + // console.log('rido script', script); + const srcUrl = unpackJavaScript(script.trim()); + console.log('rido srcUrl', srcUrl); + + streamLinks.push({ + link: srcUrl, + server: 'rido', + type: 'm3u8', + headers: { + Referer: iframeUrl, + }, + }); + + return streamLinks; + } catch (e) { + console.log('rido get stream err', e); + return []; + } +}; + +function unpackJavaScript(packedCode: string): string { + const encodedString = packedCode.split('|aHR')[1].split('|')[0]; + const base64Url = 'aHR' + encodedString; + function addPadding(base64: string) { + return base64 + '='.repeat((4 - (base64.length % 4)) % 4); + } + + console.log('rido base64Url', base64Url); + const unpackedCode = atob(addPadding(base64Url)); + return unpackedCode; +} diff --git a/providers/ringz/index.ts b/providers/ringz/index.ts new file mode 100644 index 0000000..606cb65 --- /dev/null +++ b/providers/ringz/index.ts @@ -0,0 +1,14 @@ +import {ringzGetPosts, ringzGetPostsSearch} from './ringzGetPosts'; +import {ringzGetInfo} from './ringzGetMeta'; +import {ringzGenresList, ringzCatalogList} from './ringzCatalog'; +import {ProviderType} from '../types'; +import {ringzGetStream} from './ringzGetStream'; + +export const ringz: ProviderType = { + catalog: ringzCatalogList, + genres: ringzGenresList, + GetMetaData: ringzGetInfo, + GetHomePosts: ringzGetPosts, + GetStream: ringzGetStream, + GetSearchPosts: ringzGetPostsSearch, +}; diff --git a/providers/ringz/ringzCatalog.ts b/providers/ringz/ringzCatalog.ts new file mode 100644 index 0000000..cd70469 --- /dev/null +++ b/providers/ringz/ringzCatalog.ts @@ -0,0 +1,16 @@ +export const ringzCatalogList = [ + { + title: 'Movies', + filter: 'MOVIES', + }, + { + title: 'TV Shows', + filter: 'SERIES', + }, + { + title: 'Anime', + filter: 'ANIME', + }, +]; + +export const ringzGenresList = []; diff --git a/providers/ringz/ringzGetMeta.ts b/providers/ringz/ringzGetMeta.ts new file mode 100644 index 0000000..bf7f076 --- /dev/null +++ b/providers/ringz/ringzGetMeta.ts @@ -0,0 +1,87 @@ +import {Info, Link, ProviderContext} from '../types'; +export const ringzGetInfo = async function ({ + link: data, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const dataJson = JSON.parse(data); + const title = dataJson?.kn || dataJson?.mn; + const image = dataJson?.IH || dataJson?.IV; + const tags = dataJson?.gn + .split(',') + .slice(0, 3) + .map((tag: string) => tag.trim()); + const type = dataJson?.cg === 'webSeries' ? 'series' : 'movie'; + const linkList: Link[] = []; + if (dataJson?.cg === 'webSeries') { + ['1', '2', '3', '4']?.forEach(item => { + const directLinks: Link['directLinks'] = []; + if ( + typeof dataJson?.['eServer' + item] === 'object' && + Object?.keys(dataJson?.['eServer' + item])?.length > 0 + ) { + Object.keys(dataJson?.['eServer' + item]).forEach(key => { + directLinks.push({ + title: 'Episode ' + key, + link: JSON.stringify({ + url: dataJson?.['eServer' + item][key], + server: 'Server ' + item, + }), + }); + }); + linkList.push({ + title: dataJson?.pn + ' (Server ' + item + ')', + directLinks, + }); + } + }); + } else { + const directLinks: Link['directLinks'] = []; + ['1', '2', '3', '4']?.forEach(item => { + if (dataJson?.['s' + item]) { + directLinks.push({ + title: 'Server ' + item + ' (HD)', + link: JSON.stringify({ + url: dataJson?.s1, + server: 'Server ' + item, + }), + }); + } + if (dataJson?.['4s' + item]) { + directLinks.push({ + title: 'Server ' + item + ' (480p)', + link: JSON.stringify({ + url: dataJson?.['4s' + item], + server: 'Server ' + item, + }), + }); + } + }); + linkList.push({ + title: dataJson?.pn, + directLinks, + }); + } + return { + title, + image, + imdbId: '', + synopsis: '', + type, + linkList, + tags, + }; + } catch (err) { + return { + title: '', + image: '', + imdbId: '', + synopsis: '', + type: 'movie', + linkList: [], + tags: [], + }; + } +}; diff --git a/providers/ringz/ringzGetPosts.ts b/providers/ringz/ringzGetPosts.ts new file mode 100644 index 0000000..e9f4062 --- /dev/null +++ b/providers/ringz/ringzGetPosts.ts @@ -0,0 +1,178 @@ +import {Post, ProviderContext} from '../types'; + +export const ringzGetPosts = async function ({ + filter, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + return posts({filter, signal, providerContext}); +}; + +export const ringzGetPostsSearch = async function ({ + searchQuery, + page, // providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + if (page > 1) return []; + function searchData(data: any, query: string) { + // Convert query to lowercase for case-insensitive search + const searchQuery = query.toLowerCase(); + + // Filter movies based on movie name (mn) + return data.filter((movie: any) => { + // Convert movie name to lowercase and check if it includes the search query + const movieName = movie.mn.toLowerCase(); + return movieName.includes(searchQuery); + }); + } + try { + const catalog: Post[] = []; + const promises = [getRingzMovies(), getRingzShows(), getRingzAnime()]; + const responses = await Promise.all(promises); + responses.map((response: any) => { + const searchResults = searchData(response, searchQuery); + searchResults.map((element: any) => { + const title = element?.kn || element?.mn; + const link = JSON.stringify(element); + const image = element?.IV; + if (title && link) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + }); + return catalog; + } catch (err) { + console.error('ringz error ', err); + return []; + } +}; + +async function posts({ + filter, // signal, + // providerContext, +}: { + filter: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + try { + let response; + if (filter === 'MOVIES') { + response = getRingzMovies(); + } + if (filter === 'SERIES') { + response = getRingzShows(); + } + if (filter === 'ANIME') { + response = getRingzAnime(); + } + const data = await response; + const catalog: Post[] = []; + data.map((element: any) => { + const title = element?.kn || element?.mn; + const link = JSON.stringify(element); + const image = element?.IV; + if (title && link) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + console.error('ringz error ', err); + return []; + } +} + +export const headers = { + 'cf-access-client-id': '833049b087acf6e787cedfd85d1ccdb8.access', + 'cf-access-client-secret': + '02db296a961d7513c3102d7785df4113eff036b2d57d060ffcc2ba3ba820c6aa', +}; + +const BASE_URL = 'https://privatereporz.pages.dev'; +export async function getRingzMovies() { + try { + const response = await fetch(`${BASE_URL}/test.json`, { + headers: { + ...headers, + }, + }); + const data = await response.json(); + return data.AllMovieDataList; + } catch (error) { + console.error(error); + } +} + +export async function getRingzShows() { + try { + const response = await fetch(`${BASE_URL}/srs.json`, { + headers: { + ...headers, + }, + }); + const data = await response.json(); + return data.webSeriesDataList; + } catch (error) { + console.error(error); + } +} + +export async function getRingzAnime() { + try { + const response = await fetch(`${BASE_URL}/anime.json`, { + headers: { + ...headers, + }, + }); + const data = await response.json(); + return data.webSeriesDataList; + } catch (error) { + console.error(error); + } +} + +export async function getRingzAdult() { + try { + const response = await fetch(`${BASE_URL}/desihub.json`, { + headers: { + ...headers, + }, + }); + const data = await response.json(); + return data.webSeriesDataList; + } catch (error) { + console.error(error); + } +} + +export const ringzData: { + getRingzMovies: () => Promise; + getRingzShows: () => Promise; + getRingzAnime: () => Promise; + getRingzAdult: () => Promise; +} = { + getRingzMovies, + getRingzShows, + getRingzAnime, + getRingzAdult, +}; diff --git a/providers/ringz/ringzGetStream.ts b/providers/ringz/ringzGetStream.ts new file mode 100644 index 0000000..8fac548 --- /dev/null +++ b/providers/ringz/ringzGetStream.ts @@ -0,0 +1,17 @@ +import {Stream, ProviderContext} from '../types'; + +export const ringzGetStream = async function ({ + link: data, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + const streamLinks: Stream[] = []; + const dataJson = JSON.parse(data); + streamLinks.push({ + link: dataJson.url, + server: dataJson.server, + type: 'mkv', + }); + return streamLinks; +}; diff --git a/providers/showbox/index.ts b/providers/showbox/index.ts new file mode 100644 index 0000000..54a04bd --- /dev/null +++ b/providers/showbox/index.ts @@ -0,0 +1,16 @@ +import {ProviderType} from '../types'; +import {catalogList, sbGenresList} from './sbCatalog'; +import {sbGetEpisodeLinks} from './sbGetEpisodeList'; +import {sbGetInfo} from './sbGetMeta'; +import {sbGetPosts, sbGetPostsSearch} from './sbGetPosts'; +import {sbGetStream} from './sbGetStream'; + +export const showBox: ProviderType = { + catalog: catalogList, + genres: sbGenresList, + GetMetaData: sbGetInfo, + GetHomePosts: sbGetPosts, + GetStream: sbGetStream, + GetSearchPosts: sbGetPostsSearch, + GetEpisodeLinks: sbGetEpisodeLinks, +}; diff --git a/providers/showbox/sbCatalog.ts b/providers/showbox/sbCatalog.ts new file mode 100644 index 0000000..05e62d6 --- /dev/null +++ b/providers/showbox/sbCatalog.ts @@ -0,0 +1,16 @@ +export const catalogList = [ + { + title: 'Home', + filter: '', + }, + { + title: 'Movies', + filter: '/movie', + }, + { + title: 'TV Shows', + filter: '/tv', + }, +]; + +export const sbGenresList = []; diff --git a/providers/showbox/sbGetEpisodeList.ts b/providers/showbox/sbGetEpisodeList.ts new file mode 100644 index 0000000..136cd36 --- /dev/null +++ b/providers/showbox/sbGetEpisodeList.ts @@ -0,0 +1,46 @@ +import {EpisodeLink, ProviderContext} from '../types'; + +export const sbGetEpisodeLinks = async function ({ + url: id, + providerContext, +}: { + url: string; + providerContext: ProviderContext; +}): Promise { + const {axios} = providerContext; + try { + const [fileId, febboxId] = id.split('&'); + const febLink = febboxId + ? `https://www.febbox.com/file/file_share_list?share_key=${fileId}&pwd=&parent_id=${febboxId}&is_html=0` + : `https://www.febbox.com/file/file_share_list?share_key=${fileId}&pwd=&is_html=0`; + const res = await axios.get(febLink); + const data = res.data; + const fileList = data.data.file_list; + const episodeLinks: EpisodeLink[] = []; + fileList?.map((file: any) => { + const fileName = formatEpisodeName(file.file_name); + const epId = file?.fid; + if (!file.is_dir && fileName && epId) { + episodeLinks.push({ + title: fileName, + link: `${fileId}&${epId}`, + }); + } + }); + return episodeLinks; + } catch (err) { + return []; + } +}; + +function formatEpisodeName(title: string): string { + const regex = /[sS](\d+)\s*[eE](\d+)/; + const match = title.match(regex); + if (match) { + const season = match[1].padStart(2, '0'); + const episode = match[2].padStart(2, '0'); + return `Season${season} Episode${episode}`; + } else { + return title; + } +} diff --git a/providers/showbox/sbGetMeta.ts b/providers/showbox/sbGetMeta.ts new file mode 100644 index 0000000..de16804 --- /dev/null +++ b/providers/showbox/sbGetMeta.ts @@ -0,0 +1,72 @@ +import {Info, Link, ProviderContext} from '../types'; + +export const sbGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, cheerio} = providerContext; + const url = link; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const type = url.includes('tv') ? 'series' : 'movie'; + const imdbId = ''; + const title = $('.heading-name').text(); + const rating = + $('.btn-imdb') + .text() + ?.match(/\d+(\.\d+)?/g)?.[0] || ''; + const image = + $('.cover_follow').attr('style')?.split('url(')[1]?.split(')')[0] || ''; + const synopsis = $('.description') + .text() + ?.replaceAll(/[\n\t]/g, '') + ?.trim(); + const febID = $('.heading-name').find('a').attr('href')?.split('/')?.pop(); + const baseUrl = url.split('/').slice(0, 3).join('/'); + const indexUrl = `${baseUrl}/index/share_link?id=${febID}&type=${ + type === 'movie' ? '1' : '2' + }`; + const indexRes = await axios.get(indexUrl); + const indexData = indexRes.data; + const febKey = indexData.data.link.split('/').pop(); + const febLink = `https://www.febbox.com/file/file_share_list?share_key=${febKey}&is_html=0`; + const febRes = await axios.get(febLink); + const febData = febRes.data; + const fileList = febData?.data?.file_list; + const links: Link[] = []; + if (fileList) { + fileList.map((file: any) => { + const fileName = `${file.file_name} (${file.file_size})`; + const fileId = file.fid; + links.push({ + title: fileName, + episodesLink: file.is_dir ? `${febKey}&${fileId}` : `${febKey}&`, + }); + }); + } + return { + title, + rating, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } catch (err) { + return { + title: '', + rating: '', + synopsis: '', + image: '', + imdbId: '', + type: '', + linkList: [], + }; + } +}; diff --git a/providers/showbox/sbGetPosts.ts b/providers/showbox/sbGetPosts.ts new file mode 100644 index 0000000..7380b92 --- /dev/null +++ b/providers/showbox/sbGetPosts.ts @@ -0,0 +1,75 @@ +import {Post, ProviderContext} from '../types'; + +export const sbGetPosts = async function ({ + filter, + page, + // providerValue, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios, cheerio} = providerContext; + const baseUrl = await getBaseUrl('showbox'); + const url = `${baseUrl + filter}?page=${page}/`; + return posts({url, signal, baseUrl, axios, cheerio}); +}; + +export const sbGetPostsSearch = async function ({ + searchQuery, + page, + // providerValue, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios, cheerio} = providerContext; + const baseUrl = await getBaseUrl('showbox'); + const url = `${baseUrl}/search?keyword=${searchQuery}&page=${page}`; + return posts({url, signal, baseUrl, axios, cheerio}); +}; + +async function posts({ + url, + signal, + // baseUrl, + axios, + cheerio, +}: { + url: string; + signal: AbortSignal; + baseUrl: string; + axios: ProviderContext['axios']; + cheerio: ProviderContext['cheerio']; +}): Promise { + try { + const res = await axios.get(url, {signal}); + const data = res.data; + const $ = cheerio.load(data); + const catalog: Post[] = []; + $('.movie-item').map((i, element) => { + const title = $(element).find('.movie-title').text(); + const link = $(element).find('a').attr('href'); + const image = $(element).find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + return []; + } +} diff --git a/providers/showbox/sbGetStream.ts b/providers/showbox/sbGetStream.ts new file mode 100644 index 0000000..e4d74fa --- /dev/null +++ b/providers/showbox/sbGetStream.ts @@ -0,0 +1,43 @@ +import {Stream, ProviderContext} from '../types'; +import * as cheerio from 'cheerio'; + +export const sbGetStream = async function ({ + link: id, + // type, + signal, + providerContext, +}: { + link: string; + type: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + try { + const {axios} = providerContext; + const stream: Stream[] = []; + const [, epId] = id.split('&'); + const url = `https://febbox.vercel.app/api/video-quality?fid=${epId}`; + const res = await axios.get(url, {signal}); + const data = res.data; + const $ = cheerio.load(data.html); + $('.file_quality').each((i, el) => { + const server = + $(el).find('p.name').text() + + ' - ' + + $(el).find('p.size').text() + + ' - ' + + $(el).find('p.speed').text(); + const link = $(el).attr('data-url'); + if (link) { + stream.push({ + server: server, + type: 'mkv', + link: link, + }); + } + }); + return stream; + } catch (err) { + return []; + } +}; diff --git a/providers/superVideoExtractor.ts b/providers/superVideoExtractor.ts new file mode 100644 index 0000000..1f2ec39 --- /dev/null +++ b/providers/superVideoExtractor.ts @@ -0,0 +1,40 @@ +export async function superVideoExtractor(data: any) { + try { + // Step 1: Extract the function parameters and the encoded string + var functionRegex = + /eval\(function\((.*?)\)\{.*?return p\}.*?\('(.*?)'\.split/; + var match = functionRegex.exec(data); + let p = ''; + if (match) { + // var params = match[1].split(',').map(param => param.trim()); + var encodedString = match[2]; + + // console.log('Parameters:', params); + // console.log('Encoded String:', encodedString.split("',36,")[0], '🔥🔥'); + + p = encodedString.split("',36,")?.[0].trim(); + let a = 36; + let c = encodedString.split("',36,")[1].slice(2).split('|').length; + let k = encodedString.split("',36,")[1].slice(2).split('|'); + + while (c--) { + if (k[c]) { + var regex = new RegExp('\\b' + c.toString(a) + '\\b', 'g'); + p = p.replace(regex, k[c]); + } + } + + // console.log('Decoded String:', p); + } else { + console.log('No match found'); + } + + const streamUrl = p?.match(/file:\s*"([^"]+\.m3u8[^"]*)"/)?.[1]; + console.log('streamUrl:', streamUrl); + + return streamUrl || ''; + } catch (err) { + console.error('SuperVideoExtractor Error:', err); + return ''; + } +} diff --git a/providers/tokyoInsider/catalog.ts b/providers/tokyoInsider/catalog.ts new file mode 100644 index 0000000..f3e609e --- /dev/null +++ b/providers/tokyoInsider/catalog.ts @@ -0,0 +1,12 @@ +export const tokyoCatalogList = [ + { + title: 'Top Anime', + filter: 'anime/search?r=5', + }, + { + title: 'Popular Anime', + filter: 'anime/', + }, +]; + +export const tokyoGenresList = []; diff --git a/providers/tokyoInsider/index.ts b/providers/tokyoInsider/index.ts new file mode 100644 index 0000000..5c7b166 --- /dev/null +++ b/providers/tokyoInsider/index.ts @@ -0,0 +1,15 @@ +import {tokyoCatalogList, tokyoGenresList} from './catalog'; +import {tokyoGetInfo} from './tokyoGetInfo'; +import {tokyoGetPosts, tokyoGetPostsSearch} from './tokyoGetPosts'; +import {tokyoGetStream} from './tokyoGetStream'; +import {ProviderType} from '../types'; + +export const tokyoInsider: ProviderType = { + catalog: tokyoCatalogList, + genres: tokyoGenresList, + GetMetaData: tokyoGetInfo, + GetHomePosts: tokyoGetPosts, + GetStream: tokyoGetStream, + GetSearchPosts: tokyoGetPostsSearch, + blurImage: true, +}; diff --git a/providers/tokyoInsider/tokyoGetInfo.ts b/providers/tokyoInsider/tokyoGetInfo.ts new file mode 100644 index 0000000..c5f5915 --- /dev/null +++ b/providers/tokyoInsider/tokyoGetInfo.ts @@ -0,0 +1,65 @@ +import {Info, ProviderContext} from '../types'; + +export const tokyoGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {cheerio} = providerContext; + const url = link; + const res = await fetch(url); + const data = await res.text(); + const $ = cheerio.load(data); + const meta = { + title: $('.c_h2:contains("Title(s):")') + .text() + .replace('Title(s):', '') + .trim() + .split('\n')[0], + synopsis: $('.c_h2b:contains("Summary:"),.c_h2:contains("Summary:")') + .text() + .replace('Summary:', '') + .trim(), + image: $('.a_img').attr('src') || '', + imdbId: '', + type: 'series', + }; + const episodesList: {title: string; link: string}[] = []; + $('.episode').map((i, element) => { + const link = + 'https://www.tokyoinsider.com' + $(element).find('a').attr('href') || + $('.download-link').attr('href'); + let title = + $(element).find('a').find('em').text() + + ' ' + + $(element).find('a').find('strong').text(); + if (!title.trim()) { + title = $('.download-link').text(); + } + if (link && title.trim()) { + episodesList.push({title, link}); + } + }); + return { + ...meta, + linkList: [ + { + title: meta.title, + directLinks: episodesList, + }, + ], + }; + } catch (err) { + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'series', + linkList: [], + }; + } +}; diff --git a/providers/tokyoInsider/tokyoGetPosts.ts b/providers/tokyoInsider/tokyoGetPosts.ts new file mode 100644 index 0000000..ea2dc29 --- /dev/null +++ b/providers/tokyoInsider/tokyoGetPosts.ts @@ -0,0 +1,80 @@ +import {Post, ProviderContext} from '../types'; + +export const tokyoGetPosts = async function ({ + filter, + page, + // providerValue, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios, cheerio} = providerContext; + const baseURL = await getBaseUrl('tokyoinsider'); + const start = page < 2 ? 0 : (page - 1) * 20; + const url = `${baseURL}/${filter}&start=${start}`; + return posts({baseURL, url, signal, axios, cheerio}); +}; + +export const tokyoGetPostsSearch = async function ({ + searchQuery, + page, + // providerValue, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios, cheerio} = providerContext; + const baseURL = await getBaseUrl('tokyoinsider'); + const start = page < 2 ? 0 : (page - 1) * 20; + const url = `${baseURL}/anime/search?k=${searchQuery}&start=${start}`; + return posts({baseURL, url, signal, axios, cheerio}); +}; + +async function posts({ + baseURL, + url, + signal, + axios, + cheerio, +}: { + baseURL: string; + url: string; + signal: AbortSignal; + axios: ProviderContext['axios']; + cheerio: ProviderContext['cheerio']; +}): Promise { + try { + const res = await axios.get(url, {signal}); + const data = res.data; + const $ = cheerio.load(data); + const catalog: Post[] = []; + $('td.c_h2[width="40"]').map((i, element) => { + const image = $(element) + .find('.a_img') + .attr('src') + ?.replace('small', 'default'); + const title = $(element).find('a').attr('title'); + const link = baseURL + $(element).find('a').attr('href'); + if (title && link && image) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + return []; + } +} diff --git a/providers/tokyoInsider/tokyoGetStream.ts b/providers/tokyoInsider/tokyoGetStream.ts new file mode 100644 index 0000000..e5f73dd --- /dev/null +++ b/providers/tokyoInsider/tokyoGetStream.ts @@ -0,0 +1,33 @@ +import {Stream, ProviderContext} from '../types'; + +export const tokyoGetStream = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {cheerio} = providerContext; + const url = link; + const res = await fetch(url); + const data = await res.text(); + const $ = cheerio.load(data); + const streamLinks: Stream[] = []; + $('.c_h1,.c_h2').map((i, element) => { + $(element).find('span').remove(); + const title = $(element).find('a').text() || ''; + const link = $(element).find('a').attr('href') || ''; + if (title && link.includes('media')) { + streamLinks.push({ + server: title, + link, + type: link.split('.').pop() || 'mkv', + }); + } + }); + return streamLinks; + } catch (err) { + return []; + } +}; diff --git a/providers/topmovies/index.ts b/providers/topmovies/index.ts new file mode 100644 index 0000000..396cb6c --- /dev/null +++ b/providers/topmovies/index.ts @@ -0,0 +1,17 @@ +import {modGetInfo} from '../mod/modGetInfo'; +import {modGetEpisodeLinks} from '../mod/modGetEpisodesList'; +import {modGetStream} from '../mod/modGetStream'; +import {ProviderType} from '../types'; +import {topGetPosts, topGetPostsSearch} from './topGetPosts'; +import {topCatalogList, topGenresList} from './topCatalog'; + +export const topMovies: ProviderType = { + catalog: topCatalogList, + genres: topGenresList, + GetMetaData: modGetInfo, + GetHomePosts: topGetPosts, + GetStream: modGetStream, + GetEpisodeLinks: modGetEpisodeLinks, + nonStreamableServer: [], + GetSearchPosts: topGetPostsSearch, +}; diff --git a/providers/topmovies/topCatalog.ts b/providers/topmovies/topCatalog.ts new file mode 100644 index 0000000..f9cc773 --- /dev/null +++ b/providers/topmovies/topCatalog.ts @@ -0,0 +1,85 @@ +export const topCatalogList = [ + { + title: 'Latest', + filter: '', + }, + { + title: 'Netflix', + filter: '/web-series/tv-shows-by-network/netflix', + }, + { + title: 'Hotstar', + filter: '/web-series/tv-shows-by-network/hotstar', + }, + { + title: 'Amazon Prime', + filter: '/web-series/tv-shows-by-network/amazon-prime-video', + }, +]; + +export const topGenresList = [ + { + title: 'Apple TV+', + filter: '/ott/apple-tv', + }, + { + title: 'Disney+', + filter: '/ott/disney-plus', + }, + { + title: 'Hulu', + filter: '/ott/hulu', + }, + { + title: 'Crunchyroll', + filter: '/ott/crunchyroll', + }, + { + title: 'Action', + filter: '/movies-by-genre/action/', + }, + { + title: 'Adventure', + filter: '/movies-by-genre/adventure/', + }, + { + title: 'Animation', + filter: '/movies-by-genre/animated/', + }, + { + title: 'Comedy', + filter: '/movies-by-genre/comedy/', + }, + { + title: 'Crime', + filter: '/movies-by-genre/crime/', + }, + { + title: 'Documentary', + filter: '/movies-by-genre/documentary/', + }, + { + title: 'Fantasy', + filter: '/movies-by-genre/fantasy/', + }, + { + title: 'Horror', + filter: '/movies-by-genre/horror/', + }, + { + title: 'Mystery', + filter: '/movies-by-genre/mystery/', + }, + { + title: 'Romance', + filter: '/movies-by-genre/romance/', + }, + { + title: 'Thriller', + filter: '/movies-by-genre/thriller/', + }, + { + title: 'Sci-Fi', + filter: '/movies-by-genre/sci-fi/', + }, +]; diff --git a/providers/topmovies/topGetPosts.ts b/providers/topmovies/topGetPosts.ts new file mode 100644 index 0000000..8f53586 --- /dev/null +++ b/providers/topmovies/topGetPosts.ts @@ -0,0 +1,94 @@ +import {Post, ProviderContext} from '../types'; + +const headers = { + Accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': + '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + Cookie: 'popads_user_id=6ba8fe60a481387a3249f05aa058822d', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', +}; + +export const topGetPosts = async function ({ + filter, + page, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl} = providerContext; + const baseUrl = await getBaseUrl('Topmovies'); + const url = `${baseUrl + filter}/page/${page}/`; + + return posts(url, signal, providerContext); +}; + +export const topGetPostsSearch = async function ({ + searchQuery, + page, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl} = providerContext; + const baseUrl = await getBaseUrl('Topmovies'); + const url = `${baseUrl}/search/${searchQuery}/page/${page}/`; + return posts(url, signal, providerContext); +}; + +async function posts( + url: string, + signal: AbortSignal, + providerContext: ProviderContext, +): Promise { + try { + const {axios, cheerio} = providerContext; + const res = await axios.get(url, {headers, signal}); + const data = res.data; + const $ = cheerio.load(data); + const catalog: Post[] = []; + $('.post-cards') + .find('article') + .map((i, element) => { + const title = $(element).find('a').attr('title'); + const link = $(element).find('a').attr('href'); + const image = + $(element).find('img').attr('data-src') || + $(element).find('img').attr('src') || + ''; + if (title && link) { + catalog.push({ + title: title.replace('Download', '').trim(), + link: link, + image: image, + }); + } + }); + // console.log(catalog); + return catalog; + } catch (err) { + console.error('mod error ', err); + return []; + } +} diff --git a/providers/types.ts b/providers/types.ts new file mode 100644 index 0000000..bbd0b26 --- /dev/null +++ b/providers/types.ts @@ -0,0 +1,333 @@ +import {AxiosStatic} from 'axios'; +import * as cheerio from 'cheerio'; +import {Content} from '../zustand/contentStore'; + +// getPosts +export interface Post { + title: string; + link: string; + image: string; + provider?: string; +} + +export declare enum TextTrackType { + SUBRIP = 'application/x-subrip', + TTML = 'application/ttml+xml', + VTT = 'text/vtt', +} + +export type TextTracks = { + title: string; + language: ISO639_1; + type: TextTrackType; + uri: string; +}[]; + +// getStream +export interface Stream { + server: string; + link: string; + type: string; + quality?: '360' | '480' | '720' | '1080' | '2160'; + subtitles?: TextTracks; + headers?: any; +} + +// getInfo +export interface Info { + title: string; + image: string; + synopsis: string; + imdbId: string; + type: string; + tags?: string[]; + cast?: string[]; + rating?: string; + linkList: Link[]; +} +// getEpisodeLinks +export interface EpisodeLink { + title: string; + link: string; +} + +export interface Link { + title: string; + quality?: string; + episodesLink?: string; + directLinks?: { + title: string; + link: string; + type?: 'movie' | 'series'; + }[]; +} + +// catalog +export interface Catalog { + title: string; + filter: string; +} + +export interface ProviderType { + searchFilter?: string; + catalog: Catalog[]; + genres: Catalog[]; + blurImage?: boolean; + nonStreamableServer?: string[]; + nonDownloadableServer?: string[]; + GetStream: ({ + link, + type, + signal, + providerContext, + }: { + link: string; + type: string; + signal: AbortSignal; + providerContext: ProviderContext; + }) => Promise; + GetHomePosts: ({ + filter, + page, + providerValue, + signal, + providerContext, + }: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; + }) => Promise; + GetEpisodeLinks?: ({ + url, + providerContext, + }: { + url: string; + providerContext: ProviderContext; + }) => Promise; + GetMetaData: ({ + link, + provider, + providerContext, + }: { + link: string; + provider: Content['provider']; + providerContext: ProviderContext; + }) => Promise; + GetSearchPosts: ({ + searchQuery, + page, + providerValue, + signal, + providerContext, + }: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; + }) => Promise; +} + +export type ProviderContext = { + axios: AxiosStatic; + Aes: any; // AES encryption utility, if used + getBaseUrl: (providerValue: string) => Promise; + commonHeaders: Record; + cheerio: typeof cheerio; + extractors: { + hubcloudExtracter: (link: string, signal: AbortSignal) => Promise; + gofileExtracter: (id: string) => Promise<{ + link: string; + token: string; + }>; + superVideoExtractor: (data: any) => Promise; + gdFlixExtracter: (link: string, signal: AbortSignal) => Promise; + }; +}; + +export type ISO639_1 = + | 'aa' + | 'ab' + | 'ae' + | 'af' + | 'ak' + | 'am' + | 'an' + | 'ar' + | 'as' + | 'av' + | 'ay' + | 'az' + | 'ba' + | 'be' + | 'bg' + | 'bi' + | 'bm' + | 'bn' + | 'bo' + | 'br' + | 'bs' + | 'ca' + | 'ce' + | 'ch' + | 'co' + | 'cr' + | 'cs' + | 'cu' + | 'cv' + | 'cy' + | 'da' + | 'de' + | 'dv' + | 'dz' + | 'ee' + | 'el' + | 'en' + | 'eo' + | 'es' + | 'et' + | 'eu' + | 'fa' + | 'ff' + | 'fi' + | 'fj' + | 'fo' + | 'fr' + | 'fy' + | 'ga' + | 'gd' + | 'gl' + | 'gn' + | 'gu' + | 'gv' + | 'ha' + | 'he' + | 'hi' + | 'ho' + | 'hr' + | 'ht' + | 'hu' + | 'hy' + | 'hz' + | 'ia' + | 'id' + | 'ie' + | 'ig' + | 'ii' + | 'ik' + | 'io' + | 'is' + | 'it' + | 'iu' + | 'ja' + | 'jv' + | 'ka' + | 'kg' + | 'ki' + | 'kj' + | 'kk' + | 'kl' + | 'km' + | 'kn' + | 'ko' + | 'kr' + | 'ks' + | 'ku' + | 'kv' + | 'kw' + | 'ky' + | 'la' + | 'lb' + | 'lg' + | 'li' + | 'ln' + | 'lo' + | 'lt' + | 'lu' + | 'lv' + | 'mg' + | 'mh' + | 'mi' + | 'mk' + | 'ml' + | 'mn' + | 'mr' + | 'ms' + | 'mt' + | 'my' + | 'na' + | 'nb' + | 'nd' + | 'ne' + | 'ng' + | 'nl' + | 'nn' + | 'no' + | 'nr' + | 'nv' + | 'ny' + | 'oc' + | 'oj' + | 'om' + | 'or' + | 'os' + | 'pa' + | 'pi' + | 'pl' + | 'ps' + | 'pt' + | 'qu' + | 'rm' + | 'rn' + | 'ro' + | 'ru' + | 'rw' + | 'sa' + | 'sc' + | 'sd' + | 'se' + | 'sg' + | 'si' + | 'sk' + | 'sl' + | 'sm' + | 'sn' + | 'so' + | 'sq' + | 'sr' + | 'ss' + | 'st' + | 'su' + | 'sv' + | 'sw' + | 'ta' + | 'te' + | 'tg' + | 'th' + | 'ti' + | 'tk' + | 'tl' + | 'tn' + | 'to' + | 'tr' + | 'ts' + | 'tt' + | 'tw' + | 'ty' + | 'ug' + | 'uk' + | 'ur' + | 'uz' + | 've' + | 'vi' + | 'vo' + | 'wa' + | 'wo' + | 'xh' + | 'yi' + | 'yo' + | 'za' + | 'zh' + | 'zu'; diff --git a/providers/uhd/getUhdInfo.ts b/providers/uhd/getUhdInfo.ts new file mode 100644 index 0000000..b54e2f9 --- /dev/null +++ b/providers/uhd/getUhdInfo.ts @@ -0,0 +1,120 @@ +import {Info, Link, ProviderContext} from '../types'; + +const headers = { + Accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': + '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', +}; + +export async function getUhdInfo({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, cheerio} = providerContext; + const url = link; + const res = await axios.get(url, {headers}); + const html = await res.data; + const $ = cheerio.load(html); + + const title = $('h2:first').text() || ''; + const image = $('h2').siblings().find('img').attr('src') || ''; + // const trailer = $('iframe').attr('src') || ''; + + // console.log({ title, image, trailer }); + + // Links + const episodes: Link[] = []; + + // new structure + $('.mks_separator').each((index, element) => { + $(element) + .nextUntil('.mks_separator') + .each((index, element) => { + const title = $(element).text(); + const episodesList: {title: string; link: string}[] = []; + $(element) + .next('p') + .find('a') + .each((index, element) => { + const title = $(element).text(); + const link = $(element).attr('href'); + if (title && link && !title.toLocaleLowerCase().includes('zip')) { + episodesList.push({title, link}); + // console.log({ title, link }); + } + }); + if (title && episodesList.length > 0) { + episodes.push({ + title, + directLinks: episodesList, + }); + } + }); + }); + + // old structure + $('hr').each((index, element) => { + $(element) + .nextUntil('hr') + .each((index, element) => { + const title = $(element).text(); + const episodesList: {title: string; link: string}[] = []; + $(element) + .next('p') + .find('a') + .each((index, element) => { + const title = $(element).text(); + const link = $(element).attr('href'); + if (title && link && !title.toLocaleLowerCase().includes('zip')) { + episodesList.push({title, link}); + // console.log({ title, link }); + } + }); + if (title && episodesList.length > 0) { + episodes.push({ + title, + directLinks: episodesList, + }); + } + }); + }); + // console.log(episodes); + return { + title: title.match(/^Download\s+([^(\[]+)/i) + ? title?.match(/^Download\s+([^(\[]+)/i)?.[1] || '' + : title.replace('Download', '') || '', + image, + imdbId: '', + synopsis: title, + type: '', + linkList: episodes, + }; + } catch (error) { + console.error(error); + return { + title: '', + image: '', + imdbId: '', + synopsis: '', + linkList: [], + type: 'uhd', + }; + } +} diff --git a/providers/uhd/index.ts b/providers/uhd/index.ts new file mode 100644 index 0000000..3a95318 --- /dev/null +++ b/providers/uhd/index.ts @@ -0,0 +1,15 @@ +import {uhdCatalogList, uhdGenresList} from './uhCtatalog'; +import {uhdGetPosts, uhdGetPostsSearch} from './uhdGetPosts'; +import {uhdGetStream} from './uhdGetStream'; +import {getUhdInfo} from './getUhdInfo'; +import {ProviderType} from '../types'; + +export const uhdMovies: ProviderType = { + catalog: uhdCatalogList, + genres: uhdGenresList, + GetMetaData: getUhdInfo, + GetHomePosts: uhdGetPosts, + GetStream: uhdGetStream, + nonStreamableServer: ['Gdrive-Instant'], + GetSearchPosts: uhdGetPostsSearch, +}; diff --git a/providers/uhd/uhCtatalog.ts b/providers/uhd/uhCtatalog.ts new file mode 100644 index 0000000..50fa4f5 --- /dev/null +++ b/providers/uhd/uhCtatalog.ts @@ -0,0 +1,37 @@ +export const uhdCatalogList = [ + { + title: 'Latest', + filter: '', + }, + { + title: 'Web Series', + filter: '/web-series', + }, + { + title: 'Movies', + filter: '/movies', + }, + { + title: '4K HDR', + filter: '/4k-hdr', + }, +]; + +export const uhdGenresList = [ + { + title: '4K HEVC', + filter: '/2160p-hevc', + }, + { + title: 'HD 10bit', + filter: '/1080p-10bit', + }, + { + title: 'English Movies', + filter: '/movies/english-movies', + }, + { + title: 'Dual Audio', + filter: '/movies/dual-audio-movies', + }, +]; diff --git a/providers/uhd/uhdGetPosts.ts b/providers/uhd/uhdGetPosts.ts new file mode 100644 index 0000000..6c2fa6e --- /dev/null +++ b/providers/uhd/uhdGetPosts.ts @@ -0,0 +1,97 @@ +import {Post, ProviderContext} from '../types'; + +const headers = { + Accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': + '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', +}; + +export const uhdGetPosts = async ({ + filter, + page, + // providerValue, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise => { + const {getBaseUrl} = providerContext; + const baseUrl = await getBaseUrl('UhdMovies'); + const url = + page === 1 ? `${baseUrl}/${filter}/` : `${baseUrl + filter}/page/${page}/`; + console.log('url', url); + + return posts(baseUrl, url, signal, providerContext); +}; + +export const uhdGetPostsSearch = async ({ + searchQuery, + page, + // providerValue, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise => { + const {getBaseUrl} = providerContext; + const baseUrl = await getBaseUrl('UhdMovies'); + const url = `${baseUrl}/search/${searchQuery}/page/${page}/`; + + return posts(baseUrl, url, signal, providerContext); +}; + +async function posts( + baseURL: string, + url: string, + signal: AbortSignal, + providerContext: ProviderContext, +): Promise { + try { + const {axios, cheerio} = providerContext; + const res = await axios.get(url, {headers, signal}); + const html = res.data; + const $ = cheerio.load(html); + const uhdCatalog: Post[] = []; + + $('.gridlove-posts') + .find('.layout-masonry') + .each((index, element) => { + const title = $(element).find('a').attr('title'); + const link = $(element).find('a').attr('href'); + const image = $(element).find('a').find('img').attr('src'); + + if (title && link && image) { + uhdCatalog.push({ + title: title.replace('Download', '').trim(), + link: link, + image: image, + }); + } + }); + return uhdCatalog; + } catch (err) { + console.error('uhd error ', err); + return []; + } +} diff --git a/providers/uhd/uhdGetStream.ts b/providers/uhd/uhdGetStream.ts new file mode 100644 index 0000000..0e8a710 --- /dev/null +++ b/providers/uhd/uhdGetStream.ts @@ -0,0 +1,209 @@ +import {ProviderContext, Stream} from '../types'; + +const headers = { + Accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': + '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', +}; + +export const uhdGetStream = async ({ + link: url, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise => { + try { + const {axios, cheerio} = providerContext; + let downloadLink = await modExtractor(url, providerContext); + + // console.log(downloadLink.data); + + const ddl = downloadLink?.data?.match(/content="0;url=(.*?)"/)?.[1] || url; + + console.log('ddl', ddl); + // console.log(ddl); + const driveLink = await isDriveLink(ddl); + const ServerLinks: Stream[] = []; + + const driveRes = await axios.get(driveLink, {headers}); + const driveHtml = driveRes.data; + const $drive = cheerio.load(driveHtml); + //instant link + try { + const seed = $drive('.btn-danger').attr('href') || ''; + const instantToken = seed.split('=')[1]; + // console.log('InstantToken', instantToken); + const InstantFromData = new FormData(); + InstantFromData.append('keys', instantToken); + const videoSeedUrl = seed.split('/').slice(0, 3).join('/') + '/api'; + // console.log('videoSeedUrl', videoSeedUrl); + const instantLinkRes = await fetch(videoSeedUrl, { + method: 'POST', + body: InstantFromData, + headers: { + 'x-token': videoSeedUrl, + }, + }); + const instantLinkData = await instantLinkRes.json(); + // console.log('instantLinkData', instantLinkData); + if (instantLinkData.error === false) { + const instantLink = instantLinkData.url; + ServerLinks.push({ + server: 'Gdrive-Instant', + link: instantLink, + type: 'mkv', + }); + } else { + console.log('Instant link not found', instantLinkData); + } + } catch (err) { + console.log('Instant link not found', err); + } + + // resume link + try { + const resumeDrive = driveLink.replace('/file', '/zfile'); + // console.log('resumeDrive', resumeDrive); + const resumeDriveRes = await axios.get(resumeDrive, {headers}); + const resumeDriveHtml = resumeDriveRes.data; + const $resumeDrive = cheerio.load(resumeDriveHtml); + const resumeLink = $resumeDrive('.btn-success').attr('href'); + // console.log('resumeLink', resumeLink); + if (resumeLink) { + ServerLinks.push({ + server: 'ResumeCloud', + link: resumeLink, + type: 'mkv', + }); + } + } catch (err) { + console.log('Resume link not found'); + } + + // CF workers type 1 + try { + const cfWorkersLink = driveLink.replace('/file', '/wfile') + '?type=1'; + const cfWorkersRes = await axios.get(cfWorkersLink, {headers}); + const cfWorkersHtml = cfWorkersRes.data; + const $cfWorkers = cheerio.load(cfWorkersHtml); + const cfWorkersStream = $cfWorkers('.btn-success'); + cfWorkersStream.each((i, el) => { + const link = el.attribs.href; + if (link) { + ServerLinks.push({ + server: 'Cf Worker 1.' + i, + link: link, + type: 'mkv', + }); + } + }); + } catch (err) { + console.log('CF workers link not found', err); + } + + // CF workers type 2 + try { + const cfWorkersLink = driveLink.replace('/file', '/wfile') + '?type=2'; + const cfWorkersRes = await axios.get(cfWorkersLink, {headers}); + const cfWorkersHtml = cfWorkersRes.data; + const $cfWorkers = cheerio.load(cfWorkersHtml); + const cfWorkersStream = $cfWorkers('.btn-success'); + cfWorkersStream.each((i, el) => { + const link = el.attribs.href; + if (link) { + ServerLinks.push({ + server: 'Cf Worker 2.' + i, + link: link, + type: 'mkv', + }); + } + }); + } catch (err) { + console.log('CF workers link not found', err); + } + + console.log('ServerLinks', ServerLinks); + return ServerLinks; + } catch (err) { + console.log('getStream error', err); + return []; + } +}; + +const isDriveLink = async (ddl: string) => { + if (ddl.includes('drive')) { + const driveLeach = await fetch(ddl); + const driveLeachData = await driveLeach.text(); + const pathMatch = driveLeachData.match( + /window\.location\.replace\("([^"]+)"\)/, + ); + const path = pathMatch?.[1]; + const mainUrl = ddl.split('/')[2]; + console.log(`driveUrl = https://${mainUrl}${path}`); + return `https://${mainUrl}${path}`; + } else { + return ddl; + } +}; + +async function modExtractor(url: string, providerContext: ProviderContext) { + const {axios, cheerio} = providerContext; + try { + const wpHttp = url.split('sid=')[1]; + var bodyFormData0 = new FormData(); + bodyFormData0.append('_wp_http', wpHttp); + const res = await fetch(url.split('?')[0], { + method: 'POST', + body: bodyFormData0, + }); + const data = await res.text(); + // console.log('', data); + const html = data; + const $ = cheerio.load(html); + + // find input with name="_wp_http2" + const wpHttp2 = $('input').attr('name', '_wp_http2').val(); + + // console.log('wpHttp2', wpHttp2); + + // form data + var bodyFormData = new FormData(); + bodyFormData.append('_wp_http2', wpHttp2); + const formUrl1 = $('form').attr('action'); + const formUrl = formUrl1 || url.split('?')[0]; + + const res2 = await fetch(formUrl, { + method: 'POST', + body: bodyFormData, + }); + const html2: any = await res2.text(); + const link = html2.match(/setAttribute\("href",\s*"(.*?)"/)[1]; + console.log(link); + const cookie = link.split('=')[1]; + console.log('cookie', cookie); + + const downloadLink = await axios.get(link, { + headers: { + Referer: formUrl, + Cookie: `${cookie}=${wpHttp2}`, + }, + }); + return downloadLink; + } catch (err) { + console.log('modGetStream error', err); + } +} diff --git a/providers/vadapav/VagapavCatalog.ts b/providers/vadapav/VagapavCatalog.ts new file mode 100644 index 0000000..dc9dbc3 --- /dev/null +++ b/providers/vadapav/VagapavCatalog.ts @@ -0,0 +1,16 @@ +export const vadapavCatalogList = [ + { + title: 'Movies', + filter: '/608c853f-704e-48f0-b785-4ae1f48ea70d', + }, + { + title: 'Tv Shows', + filter: '/72983eef-a12f-4be4-99a7-e8f6afa568c1', + }, + { + title: 'Anime', + filter: '/36abf81c-1032-4fbf-9a55-347a05ce2ca3', + }, +]; + +export const vadapavGenresList = []; diff --git a/providers/vadapav/index.ts b/providers/vadapav/index.ts new file mode 100644 index 0000000..110972f --- /dev/null +++ b/providers/vadapav/index.ts @@ -0,0 +1,16 @@ +import {vadapavGetPosts, vadapavGetPostsSearch} from './vadapavGetPosts'; +import {vadapavCatalogList, vadapavGenresList} from './VagapavCatalog'; +import {ProviderType} from '../types'; +import {vadapavGetInfo} from './vadapavGetInfo'; +import {vadapavGetStream} from './vadapavGetStream'; +import {vadapavGetEpisodeLinks} from './vadapavGetEpisodes'; + +export const vadapavProvider: ProviderType = { + catalog: vadapavCatalogList, + genres: vadapavGenresList, + GetHomePosts: vadapavGetPosts, + GetEpisodeLinks: vadapavGetEpisodeLinks, + GetMetaData: vadapavGetInfo, + GetStream: vadapavGetStream, + GetSearchPosts: vadapavGetPostsSearch, +}; diff --git a/providers/vadapav/vadapavGetEpisodes.ts b/providers/vadapav/vadapavGetEpisodes.ts new file mode 100644 index 0000000..229328b --- /dev/null +++ b/providers/vadapav/vadapavGetEpisodes.ts @@ -0,0 +1,38 @@ +import {EpisodeLink, ProviderContext} from '../types'; + +export const vadapavGetEpisodeLinks = async function ({ + url, + providerContext, +}: { + url: string; + providerContext: ProviderContext; +}): Promise { + const {axios, cheerio} = providerContext; + try { + const baseUrl = url?.split('/').slice(0, 3).join('/'); + const res = await axios.get(url); + const html = res.data; + let $ = cheerio.load(html); + const episodeLinks: EpisodeLink[] = []; + + $('.file-entry:not(:contains("Parent Directory"))').map((i, element) => { + const link = $(element).attr('href'); + if ( + link && + ($(element).text()?.includes('.mp4') || + $(element).text()?.includes('.mkv')) + ) { + episodeLinks.push({ + title: + $(element).text()?.match(/E\d+/)?.[0]?.replace('E', 'Episode ') || + i + 1 + '. ' + $(element).text()?.replace('.mkv', ''), + link: baseUrl + link, + }); + } + }); + + return episodeLinks; + } catch (err) { + return []; + } +}; diff --git a/providers/vadapav/vadapavGetInfo.ts b/providers/vadapav/vadapavGetInfo.ts new file mode 100644 index 0000000..0c805c2 --- /dev/null +++ b/providers/vadapav/vadapavGetInfo.ts @@ -0,0 +1,76 @@ +import {EpisodeLink, Info, Link, ProviderContext} from '../types'; + +export const vadapavGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, cheerio} = providerContext; + const baseUrl = link?.split('/').slice(0, 3).join('/'); + const url = link; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const title = + $('.directory') + .children() + .first() + .text() + .trim() + ?.split('/') + .pop() + ?.trim() || ''; + const links: Link[] = []; + $('.directory-entry:not(:contains("Parent Directory"))').map( + (i, element) => { + const link = $(element).attr('href'); + if (link) { + links.push({ + episodesLink: baseUrl + link, + title: $(element).text(), + }); + } + }, + ); + const directLinks: EpisodeLink[] = []; + $('.file-entry:not(:contains("Parent Directory"))').map((i, element) => { + const link = $(element).attr('href'); + if ( + link && + ($(element).text()?.includes('.mp4') || + $(element).text()?.includes('.mkv')) + ) { + directLinks.push({ + title: i + 1 + '. ' + $(element).text(), + link: baseUrl + link, + }); + } + }); + if (directLinks.length > 0) { + links.push({ + title: title + ' DL', + directLinks: directLinks, + }); + } + return { + title: title, + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: links, + }; + } catch (err) { + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/vadapav/vadapavGetPosts.ts b/providers/vadapav/vadapavGetPosts.ts new file mode 100644 index 0000000..4eb3305 --- /dev/null +++ b/providers/vadapav/vadapavGetPosts.ts @@ -0,0 +1,89 @@ +import {Post, ProviderContext} from '../types'; + +export const vadapavGetPosts = async function ({ + filter, + page, + // providerValue, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios, cheerio} = providerContext; + const baseUrl = await getBaseUrl('vadapav'); + if (page > 1) { + return []; + } + const url = `${baseUrl + filter}`; + return posts({baseUrl, url, signal, axios, cheerio}); +}; + +export const vadapavGetPostsSearch = async function ({ + searchQuery, + page, + // providerValue, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios, cheerio} = providerContext; + const baseUrl = await getBaseUrl('vadapav'); + if (page > 1) { + return []; + } + const url = `${baseUrl}/s/${searchQuery}`; + return posts({baseUrl, url, signal, axios, cheerio}); +}; + +async function posts({ + // baseUrl, + url, + signal, + axios, + cheerio, +}: { + baseUrl: string; + url: string; + signal: AbortSignal; + axios: ProviderContext['axios']; + cheerio: ProviderContext['cheerio']; +}): Promise { + try { + const res = await axios.get(url, {signal}); + const data = res.data; + const $ = cheerio.load(data); + const catalog: Post[] = []; + $('.directory-entry:not(:contains("Parent Directory"))').map( + (i, element) => { + const title = $(element).text(); + const link = $(element).attr('href'); + const imageTitle = + title?.length > 30 + ? title?.slice(0, 30)?.replaceAll('.', ' ') + : title?.replaceAll('.', ' '); + const image = `https://placehold.jp/23/000000/ffffff/200x400.png?text=${encodeURIComponent( + imageTitle, + )}&css=%7B%22background%22%3A%22%20-webkit-gradient(linear%2C%20left%20bottom%2C%20left%20top%2C%20from(%233f3b3b)%2C%20to(%23000000))%22%2C%22text-transform%22%3A%22%20capitalize%22%7D`; + if (title && link) { + catalog.push({ + title: title, + link: link, + image: image, + }); + } + }, + ); + return catalog; + } catch (err) { + return []; + } +} diff --git a/providers/vadapav/vadapavGetStream.ts b/providers/vadapav/vadapavGetStream.ts new file mode 100644 index 0000000..472e4c0 --- /dev/null +++ b/providers/vadapav/vadapavGetStream.ts @@ -0,0 +1,22 @@ +import {Stream, ProviderContext} from '../types'; + +export const vadapavGetStream = async function ({ + link: url, // type, +} // providerContext, +: { + link: string; + type: string; + providerContext: ProviderContext; +}): Promise { + try { + const stream: Stream[] = []; + stream.push({ + server: 'vadapav', + link: url, + type: url?.split('.').pop() || 'mkv', + }); + return stream; + } catch (err) { + return []; + } +}; diff --git a/providers/vega/catalog.ts b/providers/vega/catalog.ts new file mode 100644 index 0000000..f89d73e --- /dev/null +++ b/providers/vega/catalog.ts @@ -0,0 +1,101 @@ +export const homeList = [ + { + title: 'New', + filter: '', + }, + { + title: 'Netflix', + filter: 'web-series/netflix', + }, + { + title: 'Amazon Prime', + filter: 'web-series/amazon-prime-video', + }, + { + title: '4K Movies', + filter: 'movies-by-quality/2160p', + }, +]; + +export const genresList = [ + { + title: 'Action', + filter: 'category/movies-by-genres/action', + }, + { + title: 'Adventure', + filter: 'category/movies-by-genres/adventure', + }, + { + title: 'Animation', + filter: 'category/movies-by-genres/animation', + }, + { + title: 'Biography', + filter: 'category/movies-by-genres/biography', + }, + { + title: 'Comedy', + filter: 'category/movies-by-genres/comedy', + }, + { + title: 'Crime', + filter: 'category/movies-by-genres/crime', + }, + { + title: 'Documentary', + filter: 'category/movies-by-genres/documentary', + }, + { + title: 'Drama', + filter: 'category/movies-by-genres/drama', + }, + { + title: 'Family', + filter: 'category/movies-by-genres/family', + }, + { + title: 'Fantasy', + filter: 'category/movies-by-genres/fantasy', + }, + { + title: 'History', + filter: 'category/movies-by-genres/history', + }, + { + title: 'Horror', + filter: 'category/movies-by-genres/horror', + }, + { + title: 'Music', + filter: 'category/movies-by-genres/music', + }, + { + title: 'Mystery', + filter: 'category/movies-by-genres/mystery', + }, + { + title: 'Romance', + filter: 'category/movies-by-genres/romance', + }, + { + title: 'Sci-Fi', + filter: 'category/movies-by-genres/sci-fi', + }, + { + title: 'Sport', + filter: 'category/movies-by-genres/sport', + }, + { + title: 'Thriller', + filter: 'category/movies-by-genres/thriller', + }, + { + title: 'War', + filter: 'category/movies-by-genres/war', + }, + { + title: 'Western', + filter: 'category/movies-by-genres/western', + }, +]; diff --git a/providers/vega/getEpisodesLink.ts b/providers/vega/getEpisodesLink.ts new file mode 100644 index 0000000..91f3622 --- /dev/null +++ b/providers/vega/getEpisodesLink.ts @@ -0,0 +1,39 @@ +import {EpisodeLink, ProviderContext} from '../types'; + +export const vegaGetEpisodeLinks = async function ({ + url, + providerContext, +}: { + url: string; + providerContext: ProviderContext; +}): Promise { + const {axios, cheerio, commonHeaders: headers} = providerContext; + console.log('getEpisodeLinks', url); + try { + const res = await axios.get(url, {headers}); + const $ = cheerio.load(res.data); + const container = $('.entry-content,.entry-inner'); + $('.unili-content,.code-block-1').remove(); + const episodes: EpisodeLink[] = []; + container.find('h4').each((index, element) => { + const el = $(element); + const title = el.text().replaceAll('-', '').replaceAll(':', ''); + const link = el + .next('p') + .find( + '.btn-outline[style="background:linear-gradient(135deg,#ed0b0b,#f2d152); color: white;"]', + ) + .parent() + .attr('href'); + if (title && link) { + episodes.push({title, link}); + } + }); + // console.log(episodes); + return episodes; + } catch (err) { + console.log('getEpisodeLinks error: '); + // console.error(err); + return []; + } +}; diff --git a/providers/vega/getInfo.ts b/providers/vega/getInfo.ts new file mode 100644 index 0000000..a9e4919 --- /dev/null +++ b/providers/vega/getInfo.ts @@ -0,0 +1,157 @@ +import {Info, Link, ProviderContext} from '../types'; + +const headers = { + Accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': + '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + Cookie: + '_lscache_vary=62abf8b96599676eb8ec211cffaeb8ff; ext_name=ojplmecpdpgccookcobabopnaifgidhf; cf_clearance=n4Y1XTKZ5TfIMBNQuAXzerwKpx0U35KoOm3imfT0GpU-1732097818-1.2.1.1-ZeAnEu.8D9TSZHYDoj7vwo1A1rpdKl304ZpaBn_QbAQOr211JFAb7.JRQU3EL2eIy1Dfl8HhYvH7_259.22lUz8gbchHcQ8hvfuQXMtFMCbqDBLzjNUZa9stuk.39l28IcPhH9Z2szsf3SGtNI1sAfo66Djt7sOReLK3lHw9UkJp7BdGqt6a2X9qAc8EsAI3lE480Tmt0fkHv14Oc30LSbPB_WwFmiqAki2W.Gv9hV7TN_QBFESleTDlXd.6KGflfd4.KwWF7rpSRo_cgoc9ALLLIafpxHVbe7_g5r7zvpml_Pj8fEL75fw.1GBuy16bciHBuB8s_kahuJYUnhtQFFgfTQl8_Gn6KeovBWx.PJ7nFv5sklHUfAyBVq3t30xKe8ZDydsQ_G.yipfj_In5GmmWcXGb6E4.bioDOwW_sKLtxwdTQt7Nu.RkILX_mKvXNpyLqflIVj8G7X5E8I.unw', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0', +}; + +export const vegaGetInfo = async ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise => { + try { + const {axios, cheerio} = providerContext; + const url = link; + console.log('url', url); + const baseUrl = url.split('/').slice(0, 3).join('/'); + const response = await axios.get(url, { + headers: { + ...headers, + Referer: baseUrl, + }, + }); + const $ = cheerio.load(response.data); + const infoContainer = $('.entry-content,.post-inner'); + const heading = infoContainer?.find('h3'); + const imdbId = + heading?.next('p')?.find('a')?.[0]?.attribs?.href?.match(/tt\d+/g)?.[0] || + infoContainer.text().match(/tt\d+/g)?.[0] || + ''; + // console.log(imdbId) + + const type = heading?.next('p')?.text()?.includes('Series Name') + ? 'series' + : 'movie'; + // console.log(type); + // title + const titleRegex = /Name: (.+)/; + const title = heading?.next('p')?.text()?.match(titleRegex)?.[1] || ''; + // console.log(title); + + // synopsis + const synopsisNode = infoContainer?.find('p')?.next('h3,h4')?.next('p')?.[0] + ?.children?.[0]; + const synopsis = + synopsisNode && 'data' in synopsisNode ? synopsisNode.data : ''; + // console.log(synopsis); + + // image + let image = + infoContainer?.find('img[data-lazy-src]')?.attr('data-lazy-src') || ''; + if (image.startsWith('//')) { + image = 'https:' + image; + } + // console.log(image); + + // console.log({title, synopsis, image, imdbId, type}); + /// Links + const hr = infoContainer?.first()?.find('hr'); + const list = hr?.nextUntil('hr'); + const links: Link[] = []; + list.each((index, element: any) => { + element = $(element); + // title + const title = element?.text() || ''; + + const quality = element?.text().match(/\d+p\b/)?.[0] || ''; + // console.log(title); + // movieLinks + const movieLinks = element + ?.next() + .find('.dwd-button') + .text() + .toLowerCase() + .includes('download') + ? element?.next().find('.dwd-button')?.parent()?.attr('href') + : ''; + + // episode links + const vcloudLinks = element + ?.next() + .find( + ".btn-outline[style='background:linear-gradient(135deg,#ed0b0b,#f2d152); color: white;'],.btn-outline[style='background:linear-gradient(135deg,#ed0b0b,#f2d152); color: #fdf8f2;']", + ) + ?.parent() + ?.attr('href'); + console.log(title); + const episodesLink = + (vcloudLinks + ? vcloudLinks + : element + ?.next() + .find('.dwd-button') + .text() + .toLowerCase() + .includes('episode') + ? element?.next().find('.dwd-button')?.parent()?.attr('href') + : '') || + element + ?.next() + .find( + ".btn-outline[style='background:linear-gradient(135deg,#0ebac3,#09d261); color: white;']", + ) + ?.parent() + ?.attr('href'); + if (movieLinks || episodesLink) { + links.push({ + title, + directLinks: movieLinks + ? [{title: 'Movie', link: movieLinks, type: 'movie'}] + : [], + episodesLink, + quality, + }); + } + }); + // console.log(links); + return { + title, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } catch (error) { + console.log('getInfo error'); + console.error(error); + // ToastAndroid.show('No response', ToastAndroid.SHORT); + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: '', + linkList: [], + }; + } +}; diff --git a/providers/vega/getPosts.ts b/providers/vega/getPosts.ts new file mode 100644 index 0000000..07b3af7 --- /dev/null +++ b/providers/vega/getPosts.ts @@ -0,0 +1,121 @@ +import {Post, ProviderContext} from '../types'; + +const headers = { + Accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': + '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + Cookie: + '_lscache_vary=62abf8b96599676eb8ec211cffaeb8ff; ext_name=ojplmecpdpgccookcobabopnaifgidhf; cf_clearance=n4Y1XTKZ5TfIMBNQuAXzerwKpx0U35KoOm3imfT0GpU-1732097818-1.2.1.1-ZeAnEu.8D9TSZHYDoj7vwo1A1rpdKl304ZpaBn_QbAQOr211JFAb7.JRQU3EL2eIy1Dfl8HhYvH7_259.22lUz8gbchHcQ8hvfuQXMtFMCbqDBLzjNUZa9stuk.39l28IcPhH9Z2szsf3SGtNI1sAfo66Djt7sOReLK3lHw9UkJp7BdGqt6a2X9qAc8EsAI3lE480Tmt0fkHv14Oc30LSbPB_WwFmiqAki2W.Gv9hV7TN_QBFESleTDlXd.6KGflfd4.KwWF7rpSRo_cgoc9ALLLIafpxHVbe7_g5r7zvpml_Pj8fEL75fw.1GBuy16bciHBuB8s_kahuJYUnhtQFFgfTQl8_Gn6KeovBWx.PJ7nFv5sklHUfAyBVq3t30xKe8ZDydsQ_G.yipfj_In5GmmWcXGb6E4.bioDOwW_sKLtxwdTQt7Nu.RkILX_mKvXNpyLqflIVj8G7X5E8I.unw', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0', +}; + +export const vegaGetPosts = async ({ + filter, + page, + providerValue, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise => { + const {getBaseUrl, axios, cheerio} = providerContext; + const baseUrl = await getBaseUrl('Vega'); + + console.log('vegaGetPosts baseUrl:', providerValue, baseUrl); + const url = `${baseUrl}/${filter}/page/${page}/`; + console.log('vegaGetPosts url:', url); + return posts(baseUrl, url, signal, headers, axios, cheerio); +}; + +export const vegaGetPostsSearch = async ({ + searchQuery, + page, + providerValue, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise => { + const {getBaseUrl, axios, commonHeaders, cheerio} = providerContext; + const baseUrl = await getBaseUrl('Vega'); + + console.log('vegaGetPosts baseUrl:', providerValue, baseUrl); + const url = `${baseUrl}/page/${page}/?s=${searchQuery}`; + console.log('vegaGetPosts url:', url); + + return posts(baseUrl, url, signal, commonHeaders, axios, cheerio); +}; + +async function posts( + baseUrl: string, + url: string, + signal: AbortSignal, + headers: Record = {}, + axios: ProviderContext['axios'], + cheerio: ProviderContext['cheerio'], +): Promise { + try { + const urlRes = await axios.get(url, { + headers: { + ...headers, + Referer: baseUrl, + }, + signal, + }); + const $ = cheerio.load(urlRes.data); + const posts: Post[] = []; + $('.blog-items,.post-list') + ?.children('article') + ?.each((index, element) => { + const post = { + title: ( + $(element) + ?.find('a') + ?.attr('title') + ?.replace('Download', '') + ?.match(/^(.*?)\s*\((\d{4})\)|^(.*?)\s*\((Season \d+)\)/)?.[0] || + $(element)?.find('a')?.attr('title')?.replace('Download', '') || + $(element)?.find('.post-title').text()?.replace('Download', '') || + '' + ).trim(), + + link: $(element)?.find('a')?.attr('href') || '', + image: + $(element).find('a').find('img').attr('data-lazy-src') || + $(element).find('a').find('img').attr('data-src') || + $(element).find('a').find('img').attr('src') || + '', + }; + if (post.image.startsWith('//')) { + post.image = 'https:' + post.image; + } + posts.push(post); + }); + + // console.log(posts); + return posts; + } catch (error) { + console.error('vegaGetPosts error:', error); + return []; + } +} diff --git a/providers/vega/getStream.ts b/providers/vega/getStream.ts new file mode 100644 index 0000000..e009fdc --- /dev/null +++ b/providers/vega/getStream.ts @@ -0,0 +1,117 @@ +import {ProviderContext, Stream} from '../types'; + +const headers = { + Accept: + 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Cache-Control': 'no-store', + 'Accept-Language': 'en-US,en;q=0.9', + DNT: '1', + 'sec-ch-ua': + '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Dest': 'document', + 'Sec-Fetch-Mode': 'navigate', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + Cookie: + '_lscache_vary=62abf8b96599676eb8ec211cffaeb8ff; ext_name=ojplmecpdpgccookcobabopnaifgidhf; cf_clearance=n4Y1XTKZ5TfIMBNQuAXzerwKpx0U35KoOm3imfT0GpU-1732097818-1.2.1.1-ZeAnEu.8D9TSZHYDoj7vwo1A1rpdKl304ZpaBn_QbAQOr211JFAb7.JRQU3EL2eIy1Dfl8HhYvH7_259.22lUz8gbchHcQ8hvfuQXMtFMCbqDBLzjNUZa9stuk.39l28IcPhH9Z2szsf3SGtNI1sAfo66Djt7sOReLK3lHw9UkJp7BdGqt6a2X9qAc8EsAI3lE480Tmt0fkHv14Oc30LSbPB_WwFmiqAki2W.Gv9hV7TN_QBFESleTDlXd.6KGflfd4.KwWF7rpSRo_cgoc9ALLLIafpxHVbe7_g5r7zvpml_Pj8fEL75fw.1GBuy16bciHBuB8s_kahuJYUnhtQFFgfTQl8_Gn6KeovBWx.PJ7nFv5sklHUfAyBVq3t30xKe8ZDydsQ_G.yipfj_In5GmmWcXGb6E4.bioDOwW_sKLtxwdTQt7Nu.RkILX_mKvXNpyLqflIVj8G7X5E8I.unw', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0', +}; + +export async function vegaGetStream({ + link, + type, + signal, + providerContext, +}: { + link: string; + type: string; + signal: AbortSignal; + providerContext: ProviderContext; +}) { + const {axios, cheerio, extractors} = providerContext; + const {hubcloudExtracter} = extractors; + try { + const streamLinks: Stream[] = []; + console.log('dotlink', link); + if (type === 'movie') { + // vlink + const dotlinkRes = await axios(`${link}`, {headers}); + const dotlinkText = dotlinkRes.data; + // console.log('dotlinkText', dotlinkText); + const vlink = dotlinkText.match(/ { + const {axios, cheerio} = providerContext; + try { + const res = await axios.get(url); + const html = res.data; + let $ = cheerio.load(html); + const episodeLinks: EpisodeLink[] = []; + $( + 'strong:contains("Episode"),strong:contains("1080"),strong:contains("720"),strong:contains("480")', + ).map((i, element) => { + const title = $(element).text(); + const link = $(element) + .parent() + .parent() + .next('h4') + .find('a') + .attr('href'); + if (link && !title.includes('zip')) { + episodeLinks.push({ + title: title, + link, + }); + } + }); + return episodeLinks; + } catch (err) { + return [ + { + title: 'Server 1', + link: url, + }, + ]; + } +}; diff --git a/providers/world4u/world4uGetInfo.ts b/providers/world4u/world4uGetInfo.ts new file mode 100644 index 0000000..074f1f8 --- /dev/null +++ b/providers/world4u/world4uGetInfo.ts @@ -0,0 +1,81 @@ +import {Info, Link, ProviderContext} from '../types'; + +export const world4uGetInfo = async function ({ + link, + providerContext, +}: { + link: string; + providerContext: ProviderContext; +}): Promise { + try { + const {axios, cheerio} = providerContext; + const url = link; + const res = await axios.get(url); + const data = res.data; + const $ = cheerio.load(data); + const type = $('.entry-content') + .text() + .toLocaleLowerCase() + .includes('movie name') + ? 'movie' + : 'series'; + const imdbId = $('.imdb_left').find('a').attr('href')?.split('/')[4] || ''; + const title = $('.entry-content') + .find('strong:contains("Name")') + .children() + .remove() + .end() + .text() + .replace(':', ''); + const synopsis = $('.entry-content') + .find('p:contains("Synopsis"),p:contains("Plot"),p:contains("Story")') + .children() + .remove() + .end() + .text(); + const image = + $('.wp-caption').find('img').attr('data-src') || + $('.entry-content').find('img').attr('data-src') || + ''; + const links: Link[] = []; + $('.my-button').map((i, element) => { + const title = $(element).parent().parent().prev().text(); + const episodesLink = $(element).attr('href'); + const quality = title.match(/\b(480p|720p|1080p|2160p)\b/i)?.[0] || ''; + if (episodesLink && title) { + links.push({ + title, + episodesLink: type === 'series' ? episodesLink : '', + directLinks: + type === 'movie' + ? [ + { + link: episodesLink, + title, + type: 'movie', + }, + ] + : [], + quality, + }); + } + }); + return { + title, + synopsis, + image, + imdbId, + type, + linkList: links, + }; + } catch (err) { + return { + title: '', + synopsis: '', + image: '', + imdbId: '', + type: 'movie', + linkList: [], + }; + } +}; diff --git a/providers/world4u/world4uGetPosts.ts b/providers/world4u/world4uGetPosts.ts new file mode 100644 index 0000000..87bb9ca --- /dev/null +++ b/providers/world4u/world4uGetPosts.ts @@ -0,0 +1,77 @@ +import {Post, ProviderContext} from '../types'; + +export const world4uGetPosts = async function ({ + filter, + page, + // providerValue, + signal, + providerContext, +}: { + filter: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios, cheerio} = providerContext; + const baseUrl = await getBaseUrl('w4u'); + const url = `${baseUrl + filter}/page/${page}/`; + return posts({url, signal, axios, cheerio}); +}; + +export const world4uGetPostsSearch = async function ({ + searchQuery, + page, + // providerValue, + signal, + providerContext, +}: { + searchQuery: string; + page: number; + providerValue: string; + signal: AbortSignal; + providerContext: ProviderContext; +}): Promise { + const {getBaseUrl, axios, cheerio} = providerContext; + const baseUrl = await getBaseUrl('w4u'); + const url = `${baseUrl}/page/${page}/?s=${searchQuery}`; + return posts({url, signal, axios, cheerio}); +}; + +async function posts({ + url, + signal, + axios, + cheerio, +}: { + url: string; + signal: AbortSignal; + axios: ProviderContext['axios']; + cheerio: ProviderContext['cheerio']; +}): Promise { + try { + const res = await axios.get(url, {signal}); + const data = res.data; + const $ = cheerio.load(data); + const catalog: Post[] = []; + $('.recent-posts') + .children() + .map((i, element) => { + const title = $(element).find('.post-thumb').find('a').attr('title'); + const link = $(element).find('.post-thumb').find('a').attr('href'); + const image = + $(element).find('.post-thumb').find('img').attr('data-src') || + $(element).find('.post-thumb').find('img').attr('src'); + if (title && link && image) { + catalog.push({ + title: title.replace('Download', '').trim(), + link: link, + image: image, + }); + } + }); + return catalog; + } catch (err) { + return []; + } +} diff --git a/providers/world4u/world4uGetStream.ts b/providers/world4u/world4uGetStream.ts new file mode 100644 index 0000000..237fae5 --- /dev/null +++ b/providers/world4u/world4uGetStream.ts @@ -0,0 +1,211 @@ +import {Stream, ProviderContext} from '../types'; + +export const world4uGetStream = async function ({ + link: url, + type, + providerContext, +}: { + link: string; + type: string; + providerContext: ProviderContext; +}): Promise { + const {axios, cheerio} = providerContext; + const headers = { + 'sec-ch-ua': + '"Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + 'Sec-Fetch-Site': 'none', + 'Sec-Fetch-User': '?1', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0', + }; + + try { + if (type === 'movie') { + const linkRes = await axios.get(url, {headers}); + const linkData = linkRes.data; + const $ = cheerio.load(linkData); + url = $('strong:contains("INSTANT")').parent().attr('href') || url; + } + + // fastilinks + if (url.includes('fastilinks')) { + const fastilinksRes = await axios.get(url, {headers}); + const fastilinksData = fastilinksRes.data; + const $$ = cheerio.load(fastilinksData); + const fastilinksKey = $$( + 'input[name="_csrf_token_645a83a41868941e4692aa31e7235f2"]', + ).attr('value'); + console.log('fastilinksKey', fastilinksKey); + const fastilinksFormData = new FormData(); + fastilinksFormData.append( + '_csrf_token_645a83a41868941e4692aa31e7235f2', + fastilinksKey, + ); + const fastilinksRes2 = await fetch(url, { + method: 'POST', + headers: headers, + body: fastilinksFormData, + }); + const fastilinksHtml = await fastilinksRes2.text(); + // console.log('fastilinksHtml', fastilinksHtml); + const $$$ = cheerio.load(fastilinksHtml); + const fastilinksLink = + $$$('a:contains("mediafire")').attr('href') || + $$$('a:contains("photolinx")').attr('href'); + console.log('fastilinksLink', fastilinksLink); + url = fastilinksLink || url; + } + console.log('world4uGetStream', type, url); + + if (url.includes('photolinx')) { + console.log('photolinx', url); + // const photolinxBaseUrl = url.split('/').slice(0, 3).join('/'); + const photolinxRes = await axios.get(url, {headers}); + const photolinxData = photolinxRes.data; + const $$$ = cheerio.load(photolinxData); + const access_token = $$$('#generate_url').attr('data-token'); + const uid = $$$('#generate_url').attr('data-uid'); + const body = { + type: 'DOWNLOAD_GENERATE', + payload: { + access_token, + uid, + }, + }; + console.log('photolinxData', JSON.stringify(body)); + + const photolinxRes2 = await fetch('https://photolinx.shop/action', { + headers: { + 'sec-fetch-site': 'same-origin', + 'x-requested-with': 'xmlhttprequest', + cookie: 'PHPSESSID=9a8d855c700cf0711831c04960c2e2b4', + Referer: 'https://photolinx.shop/download/5mPkrBD0D2x', + 'Referrer-Policy': 'strict-origin-when-cross-origin', + }, + body: JSON.stringify(body), + method: 'POST', + }); + const photolinxData2 = await photolinxRes2.json(); + console.log('photolinxData2', photolinxData2); + const dwUrl = photolinxData2?.download_url; + if (dwUrl) { + const streamLinks = [ + { + server: 'Photolinx', + link: dwUrl, + type: 'mkv', + }, + ]; + return streamLinks; + } + } + + const res = await axios.get(url, {headers}); + const html = res.data; + const streamLinks: Stream[] = []; + let data = {download: ''}; + try { + const key = + html.match(/formData\.append\('key',\s*'(\d+)'\);/)?.[1] || ''; + console.log('key', key); + const formData = new FormData(); + formData.append('key', key); + const streamRes = await fetch(url, { + method: 'POST', + headers: headers, + body: formData, + }); + data = await streamRes.json(); + } catch (err) { + console.log('error in world4uGetStream', err); + } + + // console.log('streamRes', streamRes); + let $ = cheerio.load(html); + // console.log('data', html); + const mediafireUrl = + $('h1:contains("Download")').find('a').attr('href') || + $('.input.popsok').attr('href'); + console.log('mediafireUrl', mediafireUrl); + if (mediafireUrl) { + const directUrl = await axios.head(mediafireUrl); + const urlContentType = directUrl.headers['content-type']; + console.log('mfcontentType', urlContentType); + if (urlContentType && urlContentType.includes('video')) { + streamLinks.push({ + server: 'Mediafire', + link: mediafireUrl, + type: 'mkv', + }); + return streamLinks; + } else { + const repairRes = await axios.get(mediafireUrl, { + headers: { + Referer: url, + }, + }); + const repairHtml = repairRes.data; + + // Regex to match the window.location.href assignment in the script content + const hrefRegex = /window\.location\.href\s*=\s*['"]([^'"]+)['"]/; + const match = repairHtml.match(hrefRegex); + + // If a match is found, return the URL; otherwise return null + let downloadLInk = match ? match[1] : null; + console.log('downloadLInk', downloadLInk); + + if (downloadLInk) { + streamLinks.push({ + server: 'Mediafire', + link: downloadLInk, + type: 'mkv', + }); + } + return streamLinks; + } + } + + const requireRepairRes = await axios.head(data.download); + const contentType = requireRepairRes.headers['content-type']; + console.log('contentType', contentType); + if (contentType && contentType.includes('video')) { + streamLinks.push({ + server: 'Mediafire', + link: data.download, + type: 'mkv', + }); + return streamLinks; + } else { + const repairRes = await axios.get(data.download, { + headers: { + Referer: url, + }, + }); + const repairHtml = repairRes.data; + const $ = cheerio.load(repairHtml); + const repairLink = $('#continue-btn').attr('href'); + console.log('repairLink', 'https://www.mediafire.com' + repairLink); + const repairRequireRepairRes = await axios.get( + 'https://www.mediafire.com' + repairLink, + ); + const $$ = cheerio.load(repairRequireRepairRes.data); + const repairDownloadLink = $$('.input.popsok').attr('href'); + console.log('repairDownloadLink', repairDownloadLink); + if (repairDownloadLink) { + streamLinks.push({ + server: 'Mediafire', + link: repairDownloadLink, + type: 'mkv', + }); + } + } + + return streamLinks; + } catch (err) { + console.log(err); + return []; + } +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..d80a028 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "rootDir": "./providers", + "outDir": "./dist", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["providers/**/*"], + "exclude": ["node_modules", "dist"] +}