From 0c7aa1756b06b5fba25f66d8c235947813599752 Mon Sep 17 00:00:00 2001 From: lonelil <51315646+lonelil@users.noreply.github.com> Date: Sat, 6 Apr 2024 15:53:28 +0800 Subject: [PATCH 01/10] add WarezCDN (broken) --- src/providers/all.ts | 4 + src/providers/embeds/warezcdn.ts | 128 +++++++++++++++++++++++ src/providers/sources/warezcdn/common.ts | 3 + src/providers/sources/warezcdn/index.ts | 74 +++++++++++++ 4 files changed, 209 insertions(+) create mode 100644 src/providers/embeds/warezcdn.ts create mode 100644 src/providers/sources/warezcdn/common.ts create mode 100644 src/providers/sources/warezcdn/index.ts diff --git a/src/providers/all.ts b/src/providers/all.ts index 63be995..2f01869 100644 --- a/src/providers/all.ts +++ b/src/providers/all.ts @@ -31,6 +31,7 @@ import { streamvidScraper } from './embeds/streamvid'; import { vidCloudScraper } from './embeds/vidcloud'; import { vidplayScraper } from './embeds/vidplay'; import { voeScraper } from './embeds/voe'; +import { warezcdnembedScraper } from './embeds/warezcdn'; import { wootlyScraper } from './embeds/wootly'; import { goojaraScraper } from './sources/goojara'; import { hdRezkaScraper } from './sources/hdrezka'; @@ -39,6 +40,7 @@ import { primewireScraper } from './sources/primewire'; import { ridooMoviesScraper } from './sources/ridomovies'; import { smashyStreamScraper } from './sources/smashystream'; import { vidSrcToScraper } from './sources/vidsrcto'; +import { warezcdnScraper } from './sources/warezcdn'; export function gatherAllSources(): Array { // all sources are gathered here @@ -58,6 +60,7 @@ export function gatherAllSources(): Array { goojaraScraper, hdRezkaScraper, primewireScraper, + warezcdnScraper, ]; } @@ -88,5 +91,6 @@ export function gatherAllEmbeds(): Array { droploadScraper, filelionsScraper, vTubeScraper, + warezcdnembedScraper, ]; } diff --git a/src/providers/embeds/warezcdn.ts b/src/providers/embeds/warezcdn.ts new file mode 100644 index 0000000..8223bfa --- /dev/null +++ b/src/providers/embeds/warezcdn.ts @@ -0,0 +1,128 @@ +import { makeEmbed } from '@/providers/base'; +import { warezcdnPlayerBase } from '@/providers/sources/warezcdn/common'; +import { EmbedScrapeContext } from '@/utils/context'; +import { NotFoundError } from '@/utils/errors'; + +import { Stream } from '../streams'; + +const cdnListing = [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64]; + +function decrypt(input: string) { + let output = atob(input); + + // Remove leading and trailing whitespaces + output = output.trim(); + + // Reverse the string + output = output.split('').reverse().join(''); + + // Get the last 5 characters and reverse them + let last = output.slice(-5); + last = last.split('').reverse().join(''); + + // Remove the last 5 characters from the original string + output = output.slice(0, -5); + + // Return the original string concatenated with the reversed last 5 characters + return `${output}${last}`; +} + +async function checkUrls(ctx: EmbedScrapeContext, fileId: string) { + for (const id of cdnListing) { + const url = `https://cloclo${id}.cloud.mail.ru/weblink/view/${fileId}`; + const response = await ctx.proxiedFetcher.full(url, { + method: 'GET', + headers: { + Range: 'bytes=0-1', + }, + }); + if (response.statusCode === 206) return url; + } + return null; +} + +async function getVideoOwlStream(ctx: EmbedScrapeContext, decryptedId: string) { + const sharePage = await ctx.proxiedFetcher('https://cloud.mail.ru/public/uaRH/2PYWcJRpH'); + + const cloudSettings = sharePage.match(/window\.cloudSettings=(\{.*?\})<\/script>/)?.[1]; + if (!cloudSettings) throw new NotFoundError('Failed to get cloudSettings'); + + const parsedCloudSettings = JSON.parse(JSON.stringify(cloudSettings)); + + console.log(parsedCloudSettings); + + const videoOwlUrl = parsedCloudSettings.dispatcher.videowl_view.url; + if (!videoOwlUrl) throw new NotFoundError('Failed to get videoOwlUrl'); + + return `${videoOwlUrl}/${btoa(decryptedId)}.m3u8?${new URLSearchParams({ + double_encode: '1', + })}`; +} + +async function getStream(ctx: EmbedScrapeContext, decryptedId: string): Promise { + try { + const streamUrl = await getVideoOwlStream(ctx, decryptedId); + console.log(streamUrl); + return { + id: 'primary', + type: 'hls', + flags: [], + captions: [], + playlist: streamUrl, + }; + } catch (err) { + console.error(err); + const streamUrl = await checkUrls(ctx, decryptedId); + return { + id: 'primary', + type: 'file', + flags: [], + captions: [], + qualities: { + unknown: { + type: 'mp4', + url: streamUrl!, + }, + }, + }; + } +} + +export const warezcdnembedScraper = makeEmbed({ + id: 'warezcdnembed', // WarezCDN is both a source and an embed host + name: 'WarezCDN', + rank: 82, + async scrape(ctx) { + const page = await ctx.proxiedFetcher(`/player.php?${new URLSearchParams({ id: ctx.url })}`, { + baseUrl: warezcdnPlayerBase, + headers: { + Referer: `${warezcdnPlayerBase}/getEmbed.php?${new URLSearchParams({ + id: ctx.url, + sv: 'warezcdn', + })}`, + }, + }); + const allowanceKey = page.match(/let allowanceKey = "(.*?)";/)?.[1]; + if (!allowanceKey) throw new NotFoundError('Failed to get allowanceKey'); + + const streamData = await ctx.proxiedFetcher('/functions.php', { + baseUrl: warezcdnPlayerBase, + method: 'POST', + body: new URLSearchParams({ + getVideo: ctx.url, + key: allowanceKey, + }), + }); + const stream = JSON.parse(streamData); + + if (!stream.id) throw new NotFoundError("can't get stream id"); + + const decryptedId = decrypt(stream.id); + + if (!decryptedId) throw new NotFoundError("can't get file id"); + + return { + stream: [await getStream(ctx, decryptedId)], + }; + }, +}); diff --git a/src/providers/sources/warezcdn/common.ts b/src/providers/sources/warezcdn/common.ts new file mode 100644 index 0000000..5fcde55 --- /dev/null +++ b/src/providers/sources/warezcdn/common.ts @@ -0,0 +1,3 @@ +export const warezcdnBase = 'https://embed.warezcdn.com'; +export const warezcdnApiBase = 'https://warezcdn.com/embed'; +export const warezcdnPlayerBase = 'https://warezcdn.com/player'; diff --git a/src/providers/sources/warezcdn/index.ts b/src/providers/sources/warezcdn/index.ts new file mode 100644 index 0000000..f2660dc --- /dev/null +++ b/src/providers/sources/warezcdn/index.ts @@ -0,0 +1,74 @@ +import { load } from 'cheerio'; + +import { SourcererEmbed, SourcererOutput, makeSourcerer } from '@/providers/base'; +import { mixdropScraper } from '@/providers/embeds/mixdrop'; +import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context'; +import { NotFoundError } from '@/utils/errors'; + +import { warezcdnApiBase, warezcdnBase } from './common'; + +const embeds = { + warezcdn: mixdropScraper.id, + mixdrop: mixdropScraper.id, +}; + +const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => { + if (!ctx.media.imdbId) throw new NotFoundError('This source requires IMDB id.'); + + let id = `filme/${ctx.media.imdbId}`; + if (ctx.media.type === 'show') + id = `serie/${ctx.media.imdbId}/${ctx.media.season.number}/${ctx.media.episode.number}`; + + const serversPage = await ctx.proxiedFetcher(`/${id}`, { + baseUrl: warezcdnBase, + }); + const $ = load(serversPage); + + const servers = await Promise.all( + $('.hostList.active [data-load-embed]') + .filter((_index, element) => { + const embed = $(element).attr('data-load-embed-host'); + return !!embed && !!embeds[embed as keyof typeof embeds]; + }) + .map(async (_index, element) => { + const embedHost = $(element).attr('data-load-embed-host'); + const embedId = embeds[embedHost as keyof typeof embeds]; + let embedUrl = $(element).attr('data-load-embed')!; + + if (embedHost === 'mixdrop') { + const params = new URLSearchParams({ + id: embedUrl, + sv: 'mixdrop', + }); + const realUrl = await ctx.proxiedFetcher(`/getPlay.php?${params}`, { + baseUrl: warezcdnApiBase, + headers: { + Referer: `${warezcdnApiBase}/getEmbed.php?${params}`, + }, + }); + + const realEmbedUrl = realUrl.match(/window\.location\.href="([^"]*)";/); + embedUrl = realEmbedUrl[1]; + } + + return { + embedId, + url: embedUrl, + } as SourcererEmbed; + }) + .get(), + ); + + return { + embeds: servers, + } as SourcererOutput; +}; + +export const warezcdnScraper = makeSourcerer({ + id: 'warezcdn', + name: 'WarezCDN', + rank: 81, + flags: [], + scrapeMovie: universalScraper, + scrapeShow: universalScraper, +}); From 51c58aae75ff74eafe904282f252c5ff46a81163 Mon Sep 17 00:00:00 2001 From: lonelil <51315646+lonelil@users.noreply.github.com> Date: Sun, 7 Apr 2024 22:53:52 +0800 Subject: [PATCH 02/10] split embeds --- src/providers/all.ts | 6 +- src/providers/embeds/warezcdn.ts | 128 ------------------------ src/providers/embeds/warezcdn/common.ts | 55 ++++++++++ src/providers/embeds/warezcdn/hls.ts | 44 ++++++++ src/providers/embeds/warezcdn/mp4.ts | 58 +++++++++++ src/providers/sources/warezcdn/index.ts | 73 +++++++------- 6 files changed, 198 insertions(+), 166 deletions(-) delete mode 100644 src/providers/embeds/warezcdn.ts create mode 100644 src/providers/embeds/warezcdn/common.ts create mode 100644 src/providers/embeds/warezcdn/hls.ts create mode 100644 src/providers/embeds/warezcdn/mp4.ts diff --git a/src/providers/all.ts b/src/providers/all.ts index 2f01869..e32790e 100644 --- a/src/providers/all.ts +++ b/src/providers/all.ts @@ -31,7 +31,8 @@ import { streamvidScraper } from './embeds/streamvid'; import { vidCloudScraper } from './embeds/vidcloud'; import { vidplayScraper } from './embeds/vidplay'; import { voeScraper } from './embeds/voe'; -import { warezcdnembedScraper } from './embeds/warezcdn'; +import { warezcdnembedHlsScraper } from './embeds/warezcdn/hls'; +import { warezcdnembedMp4Scraper } from './embeds/warezcdn/mp4'; import { wootlyScraper } from './embeds/wootly'; import { goojaraScraper } from './sources/goojara'; import { hdRezkaScraper } from './sources/hdrezka'; @@ -91,6 +92,7 @@ export function gatherAllEmbeds(): Array { droploadScraper, filelionsScraper, vTubeScraper, - warezcdnembedScraper, + warezcdnembedHlsScraper, + warezcdnembedMp4Scraper, ]; } diff --git a/src/providers/embeds/warezcdn.ts b/src/providers/embeds/warezcdn.ts deleted file mode 100644 index 8223bfa..0000000 --- a/src/providers/embeds/warezcdn.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { makeEmbed } from '@/providers/base'; -import { warezcdnPlayerBase } from '@/providers/sources/warezcdn/common'; -import { EmbedScrapeContext } from '@/utils/context'; -import { NotFoundError } from '@/utils/errors'; - -import { Stream } from '../streams'; - -const cdnListing = [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64]; - -function decrypt(input: string) { - let output = atob(input); - - // Remove leading and trailing whitespaces - output = output.trim(); - - // Reverse the string - output = output.split('').reverse().join(''); - - // Get the last 5 characters and reverse them - let last = output.slice(-5); - last = last.split('').reverse().join(''); - - // Remove the last 5 characters from the original string - output = output.slice(0, -5); - - // Return the original string concatenated with the reversed last 5 characters - return `${output}${last}`; -} - -async function checkUrls(ctx: EmbedScrapeContext, fileId: string) { - for (const id of cdnListing) { - const url = `https://cloclo${id}.cloud.mail.ru/weblink/view/${fileId}`; - const response = await ctx.proxiedFetcher.full(url, { - method: 'GET', - headers: { - Range: 'bytes=0-1', - }, - }); - if (response.statusCode === 206) return url; - } - return null; -} - -async function getVideoOwlStream(ctx: EmbedScrapeContext, decryptedId: string) { - const sharePage = await ctx.proxiedFetcher('https://cloud.mail.ru/public/uaRH/2PYWcJRpH'); - - const cloudSettings = sharePage.match(/window\.cloudSettings=(\{.*?\})<\/script>/)?.[1]; - if (!cloudSettings) throw new NotFoundError('Failed to get cloudSettings'); - - const parsedCloudSettings = JSON.parse(JSON.stringify(cloudSettings)); - - console.log(parsedCloudSettings); - - const videoOwlUrl = parsedCloudSettings.dispatcher.videowl_view.url; - if (!videoOwlUrl) throw new NotFoundError('Failed to get videoOwlUrl'); - - return `${videoOwlUrl}/${btoa(decryptedId)}.m3u8?${new URLSearchParams({ - double_encode: '1', - })}`; -} - -async function getStream(ctx: EmbedScrapeContext, decryptedId: string): Promise { - try { - const streamUrl = await getVideoOwlStream(ctx, decryptedId); - console.log(streamUrl); - return { - id: 'primary', - type: 'hls', - flags: [], - captions: [], - playlist: streamUrl, - }; - } catch (err) { - console.error(err); - const streamUrl = await checkUrls(ctx, decryptedId); - return { - id: 'primary', - type: 'file', - flags: [], - captions: [], - qualities: { - unknown: { - type: 'mp4', - url: streamUrl!, - }, - }, - }; - } -} - -export const warezcdnembedScraper = makeEmbed({ - id: 'warezcdnembed', // WarezCDN is both a source and an embed host - name: 'WarezCDN', - rank: 82, - async scrape(ctx) { - const page = await ctx.proxiedFetcher(`/player.php?${new URLSearchParams({ id: ctx.url })}`, { - baseUrl: warezcdnPlayerBase, - headers: { - Referer: `${warezcdnPlayerBase}/getEmbed.php?${new URLSearchParams({ - id: ctx.url, - sv: 'warezcdn', - })}`, - }, - }); - const allowanceKey = page.match(/let allowanceKey = "(.*?)";/)?.[1]; - if (!allowanceKey) throw new NotFoundError('Failed to get allowanceKey'); - - const streamData = await ctx.proxiedFetcher('/functions.php', { - baseUrl: warezcdnPlayerBase, - method: 'POST', - body: new URLSearchParams({ - getVideo: ctx.url, - key: allowanceKey, - }), - }); - const stream = JSON.parse(streamData); - - if (!stream.id) throw new NotFoundError("can't get stream id"); - - const decryptedId = decrypt(stream.id); - - if (!decryptedId) throw new NotFoundError("can't get file id"); - - return { - stream: [await getStream(ctx, decryptedId)], - }; - }, -}); diff --git a/src/providers/embeds/warezcdn/common.ts b/src/providers/embeds/warezcdn/common.ts new file mode 100644 index 0000000..3a18bb6 --- /dev/null +++ b/src/providers/embeds/warezcdn/common.ts @@ -0,0 +1,55 @@ +import { warezcdnPlayerBase } from '@/providers/sources/warezcdn/common'; +import { EmbedScrapeContext } from '@/utils/context'; +import { NotFoundError } from '@/utils/errors'; + +function decrypt(input: string) { + let output = atob(input); + + // Remove leading and trailing whitespaces + output = output.trim(); + + // Reverse the string + output = output.split('').reverse().join(''); + + // Get the last 5 characters and reverse them + let last = output.slice(-5); + last = last.split('').reverse().join(''); + + // Remove the last 5 characters from the original string + output = output.slice(0, -5); + + // Return the original string concatenated with the reversed last 5 characters + return `${output}${last}`; +} + +export async function getDecryptedId(ctx: EmbedScrapeContext) { + const page = await ctx.proxiedFetcher(`/player.php?${new URLSearchParams({ id: ctx.url })}`, { + baseUrl: warezcdnPlayerBase, + headers: { + Referer: `${warezcdnPlayerBase}/getEmbed.php?${new URLSearchParams({ + id: ctx.url, + sv: 'warezcdn', + })}`, + }, + }); + const allowanceKey = page.match(/let allowanceKey = "(.*?)";/)?.[1]; + if (!allowanceKey) throw new NotFoundError('Failed to get allowanceKey'); + + const streamData = await ctx.proxiedFetcher('/functions.php', { + baseUrl: warezcdnPlayerBase, + method: 'POST', + body: new URLSearchParams({ + getVideo: ctx.url, + key: allowanceKey, + }), + }); + const stream = JSON.parse(streamData); + + if (!stream.id) throw new NotFoundError("can't get stream id"); + + const decryptedId = decrypt(stream.id); + + if (!decryptedId) throw new NotFoundError("can't get file id"); + + return decryptedId; +} diff --git a/src/providers/embeds/warezcdn/hls.ts b/src/providers/embeds/warezcdn/hls.ts new file mode 100644 index 0000000..957dd07 --- /dev/null +++ b/src/providers/embeds/warezcdn/hls.ts @@ -0,0 +1,44 @@ +import { flags } from '@/entrypoint/utils/targets'; +import { makeEmbed } from '@/providers/base'; +import { EmbedScrapeContext } from '@/utils/context'; +import { NotFoundError } from '@/utils/errors'; + +import { getDecryptedId } from './common'; + +// Method found by atpn +async function getVideowlUrlStream(ctx: EmbedScrapeContext, decryptedId: string) { + const sharePage = await ctx.proxiedFetcher('https://cloud.mail.ru/public/uaRH/2PYWcJRpH'); + const regex = /"videowl_view":\{"count":"(\d+)","url":"([^"]+)"\}/g; + const videowlUrl = regex.exec(sharePage)?.[2]; + + if (!videowlUrl) throw new NotFoundError('Failed to get videoOwlUrl'); + + return `${videowlUrl}/${btoa(decryptedId)}.m3u8?${new URLSearchParams({ + double_encode: '1', + })}`; +} + +export const warezcdnembedHlsScraper = makeEmbed({ + id: 'warezcdnembedhls', // WarezCDN is both a source and an embed host + name: 'WarezCDN HLS', + rank: 82, + async scrape(ctx) { + const decryptedId = await getDecryptedId(ctx); + + if (!decryptedId) throw new NotFoundError("can't get file id"); + + const streamUrl = await getVideowlUrlStream(ctx, decryptedId); + + return { + stream: [ + { + id: 'primary', + type: 'hls', + flags: [flags.IP_LOCKED], + captions: [], + playlist: streamUrl, + }, + ], + }; + }, +}); diff --git a/src/providers/embeds/warezcdn/mp4.ts b/src/providers/embeds/warezcdn/mp4.ts new file mode 100644 index 0000000..53b85dd --- /dev/null +++ b/src/providers/embeds/warezcdn/mp4.ts @@ -0,0 +1,58 @@ +import { makeEmbed } from '@/providers/base'; +import { EmbedScrapeContext } from '@/utils/context'; +import { NotFoundError } from '@/utils/errors'; + +import { getDecryptedId } from './common'; + +const cdnListing = [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64]; + +async function checkUrls(ctx: EmbedScrapeContext, fileId: string) { + for (const id of cdnListing) { + const url = `https://cloclo${id}.cloud.mail.ru/weblink/view/${fileId}`; + const response = await ctx.proxiedFetcher.full(url, { + method: 'GET', + headers: { + Range: 'bytes=0-1', + }, + }); + if (response.statusCode === 206) return url; + } + return null; +} + +export const warezcdnembedMp4Scraper = makeEmbed({ + id: 'warezcdnembedmp4', // WarezCDN is both a source and an embed host + name: 'WarezCDN MP4', + rank: 83, + disabled: true, // crashes movie-web player, disabling for now + async scrape(ctx) { + const decryptedId = await getDecryptedId(ctx); + + if (!decryptedId) throw new NotFoundError("can't get file id"); + + const streamUrl = await checkUrls(ctx, decryptedId); + + if (!streamUrl) throw new NotFoundError("can't get stream id"); + + return { + stream: [ + { + id: 'primary', + captions: [], + qualities: { + unknown: { + type: 'mp4', + url: streamUrl, + }, + }, + type: 'file', + flags: [], + headers: { + Origin: 'https://cloud.mail.ru', + Referer: 'https://cloud.mail.ru/', + }, + }, + ], + }; + }, +}); diff --git a/src/providers/sources/warezcdn/index.ts b/src/providers/sources/warezcdn/index.ts index f2660dc..6925855 100644 --- a/src/providers/sources/warezcdn/index.ts +++ b/src/providers/sources/warezcdn/index.ts @@ -2,16 +2,13 @@ import { load } from 'cheerio'; import { SourcererEmbed, SourcererOutput, makeSourcerer } from '@/providers/base'; import { mixdropScraper } from '@/providers/embeds/mixdrop'; +import { warezcdnembedHlsScraper } from '@/providers/embeds/warezcdn/hls'; +import { warezcdnembedMp4Scraper } from '@/providers/embeds/warezcdn/mp4'; import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context'; import { NotFoundError } from '@/utils/errors'; import { warezcdnApiBase, warezcdnBase } from './common'; -const embeds = { - warezcdn: mixdropScraper.id, - mixdrop: mixdropScraper.id, -}; - const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => { if (!ctx.media.imdbId) throw new NotFoundError('This source requires IMDB id.'); @@ -24,43 +21,47 @@ const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => }); const $ = load(serversPage); - const servers = await Promise.all( - $('.hostList.active [data-load-embed]') - .filter((_index, element) => { - const embed = $(element).attr('data-load-embed-host'); - return !!embed && !!embeds[embed as keyof typeof embeds]; - }) - .map(async (_index, element) => { - const embedHost = $(element).attr('data-load-embed-host'); - const embedId = embeds[embedHost as keyof typeof embeds]; - let embedUrl = $(element).attr('data-load-embed')!; + const embedsHost = $('.hostList.active [data-load-embed]').get(); - if (embedHost === 'mixdrop') { - const params = new URLSearchParams({ - id: embedUrl, - sv: 'mixdrop', - }); - const realUrl = await ctx.proxiedFetcher(`/getPlay.php?${params}`, { - baseUrl: warezcdnApiBase, - headers: { - Referer: `${warezcdnApiBase}/getEmbed.php?${params}`, - }, - }); + const embeds: SourcererEmbed[] = []; - const realEmbedUrl = realUrl.match(/window\.location\.href="([^"]*)";/); - embedUrl = realEmbedUrl[1]; - } + embedsHost.forEach(async (element) => { + const embedHost = $(element).attr('data-load-embed-host')!; + const embedUrl = $(element).attr('data-load-embed')!; - return { - embedId, + if (embedHost === 'mixdrop') { + const params = new URLSearchParams({ + id: embedUrl, + sv: 'mixdrop', + }); + const realUrl = await ctx.proxiedFetcher(`/getPlay.php?${params}`, { + baseUrl: warezcdnApiBase, + headers: { + Referer: `${warezcdnApiBase}/getEmbed.php?${params}`, + }, + }); + + const realEmbedUrl = realUrl.match(/window\.location\.href="([^"]*)";/); + embeds.push({ + embedId: mixdropScraper.id, + url: realEmbedUrl[1], + }); + } else if (embedHost === 'warezcdn') { + embeds.push( + { + embedId: warezcdnembedHlsScraper.id, url: embedUrl, - } as SourcererEmbed; - }) - .get(), - ); + }, + { + embedId: warezcdnembedMp4Scraper.id, + url: embedUrl, + }, + ); + } + }); return { - embeds: servers, + embeds, } as SourcererOutput; }; From 1a754ad95171578318ba247ee120ac05ba5a017c Mon Sep 17 00:00:00 2001 From: lonelil <51315646+lonelil@users.noreply.github.com> Date: Mon, 8 Apr 2024 15:05:41 +0800 Subject: [PATCH 03/10] fix hls url format --- src/providers/embeds/warezcdn/hls.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/embeds/warezcdn/hls.ts b/src/providers/embeds/warezcdn/hls.ts index 957dd07..827bf94 100644 --- a/src/providers/embeds/warezcdn/hls.ts +++ b/src/providers/embeds/warezcdn/hls.ts @@ -13,7 +13,7 @@ async function getVideowlUrlStream(ctx: EmbedScrapeContext, decryptedId: string) if (!videowlUrl) throw new NotFoundError('Failed to get videoOwlUrl'); - return `${videowlUrl}/${btoa(decryptedId)}.m3u8?${new URLSearchParams({ + return `${videowlUrl}/0p/${btoa(decryptedId)}.m3u8?${new URLSearchParams({ double_encode: '1', })}`; } From c17b74c8ba5b333f7057030123ed0e07dde242d3 Mon Sep 17 00:00:00 2001 From: lonelil <51315646+lonelil@users.noreply.github.com> Date: Thu, 11 Apr 2024 19:23:46 +0800 Subject: [PATCH 04/10] use worker proxy --- src/providers/embeds/warezcdn/common.ts | 2 ++ src/providers/embeds/warezcdn/mp4.ts | 12 +++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/providers/embeds/warezcdn/common.ts b/src/providers/embeds/warezcdn/common.ts index 3a18bb6..47dfed0 100644 --- a/src/providers/embeds/warezcdn/common.ts +++ b/src/providers/embeds/warezcdn/common.ts @@ -53,3 +53,5 @@ export async function getDecryptedId(ctx: EmbedScrapeContext) { return decryptedId; } + +export const warezcdnWorkerProxy = 'https://workerproxy.warezcdn.workers.dev'; diff --git a/src/providers/embeds/warezcdn/mp4.ts b/src/providers/embeds/warezcdn/mp4.ts index 53b85dd..d4a5cff 100644 --- a/src/providers/embeds/warezcdn/mp4.ts +++ b/src/providers/embeds/warezcdn/mp4.ts @@ -2,7 +2,7 @@ import { makeEmbed } from '@/providers/base'; import { EmbedScrapeContext } from '@/utils/context'; import { NotFoundError } from '@/utils/errors'; -import { getDecryptedId } from './common'; +import { getDecryptedId, warezcdnWorkerProxy } from './common'; const cdnListing = [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64]; @@ -24,7 +24,7 @@ export const warezcdnembedMp4Scraper = makeEmbed({ id: 'warezcdnembedmp4', // WarezCDN is both a source and an embed host name: 'WarezCDN MP4', rank: 83, - disabled: true, // crashes movie-web player, disabling for now + disabled: false, async scrape(ctx) { const decryptedId = await getDecryptedId(ctx); @@ -42,15 +42,13 @@ export const warezcdnembedMp4Scraper = makeEmbed({ qualities: { unknown: { type: 'mp4', - url: streamUrl, + url: `${warezcdnWorkerProxy}/?${new URLSearchParams({ + url: streamUrl, + })}`, }, }, type: 'file', flags: [], - headers: { - Origin: 'https://cloud.mail.ru', - Referer: 'https://cloud.mail.ru/', - }, }, ], }; From 9ba05ab99109d9b6b7efb48b30373acf58eb0187 Mon Sep 17 00:00:00 2001 From: lonelil <51315646+lonelil@users.noreply.github.com> Date: Thu, 11 Apr 2024 19:29:35 +0800 Subject: [PATCH 05/10] add types --- src/providers/embeds/warezcdn/common.ts | 2 +- src/providers/embeds/warezcdn/hls.ts | 2 +- src/providers/sources/warezcdn/index.ts | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/providers/embeds/warezcdn/common.ts b/src/providers/embeds/warezcdn/common.ts index 47dfed0..5c944d7 100644 --- a/src/providers/embeds/warezcdn/common.ts +++ b/src/providers/embeds/warezcdn/common.ts @@ -35,7 +35,7 @@ export async function getDecryptedId(ctx: EmbedScrapeContext) { const allowanceKey = page.match(/let allowanceKey = "(.*?)";/)?.[1]; if (!allowanceKey) throw new NotFoundError('Failed to get allowanceKey'); - const streamData = await ctx.proxiedFetcher('/functions.php', { + const streamData = await ctx.proxiedFetcher('/functions.php', { baseUrl: warezcdnPlayerBase, method: 'POST', body: new URLSearchParams({ diff --git a/src/providers/embeds/warezcdn/hls.ts b/src/providers/embeds/warezcdn/hls.ts index 827bf94..1fbbef3 100644 --- a/src/providers/embeds/warezcdn/hls.ts +++ b/src/providers/embeds/warezcdn/hls.ts @@ -7,7 +7,7 @@ import { getDecryptedId } from './common'; // Method found by atpn async function getVideowlUrlStream(ctx: EmbedScrapeContext, decryptedId: string) { - const sharePage = await ctx.proxiedFetcher('https://cloud.mail.ru/public/uaRH/2PYWcJRpH'); + const sharePage = await ctx.proxiedFetcher('https://cloud.mail.ru/public/uaRH/2PYWcJRpH'); const regex = /"videowl_view":\{"count":"(\d+)","url":"([^"]+)"\}/g; const videowlUrl = regex.exec(sharePage)?.[2]; diff --git a/src/providers/sources/warezcdn/index.ts b/src/providers/sources/warezcdn/index.ts index 6925855..e504e41 100644 --- a/src/providers/sources/warezcdn/index.ts +++ b/src/providers/sources/warezcdn/index.ts @@ -16,7 +16,7 @@ const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => if (ctx.media.type === 'show') id = `serie/${ctx.media.imdbId}/${ctx.media.season.number}/${ctx.media.episode.number}`; - const serversPage = await ctx.proxiedFetcher(`/${id}`, { + const serversPage = await ctx.proxiedFetcher(`/${id}`, { baseUrl: warezcdnBase, }); const $ = load(serversPage); @@ -34,7 +34,7 @@ const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => id: embedUrl, sv: 'mixdrop', }); - const realUrl = await ctx.proxiedFetcher(`/getPlay.php?${params}`, { + const realUrl = await ctx.proxiedFetcher(`/getPlay.php?${params}`, { baseUrl: warezcdnApiBase, headers: { Referer: `${warezcdnApiBase}/getEmbed.php?${params}`, @@ -42,6 +42,7 @@ const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => }); const realEmbedUrl = realUrl.match(/window\.location\.href="([^"]*)";/); + if (!realEmbedUrl) throw new Error('Could not find embed url'); embeds.push({ embedId: mixdropScraper.id, url: realEmbedUrl[1], From cffbc844e0e65035aa3750705f29bfbefd5d5f38 Mon Sep 17 00:00:00 2001 From: lonelil <51315646+lonelil@users.noreply.github.com> Date: Thu, 11 Apr 2024 22:06:53 +0800 Subject: [PATCH 06/10] complete requested changes --- src/providers/embeds/warezcdn/common.ts | 7 ++++--- src/providers/embeds/warezcdn/mp4.ts | 3 ++- src/providers/sources/warezcdn/common.ts | 1 + src/providers/sources/warezcdn/index.ts | 13 +++++++------ 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/providers/embeds/warezcdn/common.ts b/src/providers/embeds/warezcdn/common.ts index 5c944d7..2762ed8 100644 --- a/src/providers/embeds/warezcdn/common.ts +++ b/src/providers/embeds/warezcdn/common.ts @@ -23,7 +23,7 @@ function decrypt(input: string) { } export async function getDecryptedId(ctx: EmbedScrapeContext) { - const page = await ctx.proxiedFetcher(`/player.php?${new URLSearchParams({ id: ctx.url })}`, { + const page = await ctx.proxiedFetcher(`/player.php`, { baseUrl: warezcdnPlayerBase, headers: { Referer: `${warezcdnPlayerBase}/getEmbed.php?${new URLSearchParams({ @@ -31,6 +31,9 @@ export async function getDecryptedId(ctx: EmbedScrapeContext) { sv: 'warezcdn', })}`, }, + query: { + id: ctx.url, + }, }); const allowanceKey = page.match(/let allowanceKey = "(.*?)";/)?.[1]; if (!allowanceKey) throw new NotFoundError('Failed to get allowanceKey'); @@ -53,5 +56,3 @@ export async function getDecryptedId(ctx: EmbedScrapeContext) { return decryptedId; } - -export const warezcdnWorkerProxy = 'https://workerproxy.warezcdn.workers.dev'; diff --git a/src/providers/embeds/warezcdn/mp4.ts b/src/providers/embeds/warezcdn/mp4.ts index d4a5cff..caac7ae 100644 --- a/src/providers/embeds/warezcdn/mp4.ts +++ b/src/providers/embeds/warezcdn/mp4.ts @@ -1,8 +1,9 @@ import { makeEmbed } from '@/providers/base'; +import { warezcdnWorkerProxy } from '@/providers/sources/warezcdn/common'; import { EmbedScrapeContext } from '@/utils/context'; import { NotFoundError } from '@/utils/errors'; -import { getDecryptedId, warezcdnWorkerProxy } from './common'; +import { getDecryptedId } from './common'; const cdnListing = [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64]; diff --git a/src/providers/sources/warezcdn/common.ts b/src/providers/sources/warezcdn/common.ts index 5fcde55..83e94bc 100644 --- a/src/providers/sources/warezcdn/common.ts +++ b/src/providers/sources/warezcdn/common.ts @@ -1,3 +1,4 @@ export const warezcdnBase = 'https://embed.warezcdn.com'; export const warezcdnApiBase = 'https://warezcdn.com/embed'; export const warezcdnPlayerBase = 'https://warezcdn.com/player'; +export const warezcdnWorkerProxy = 'https://workerproxy.warezcdn.workers.dev'; diff --git a/src/providers/sources/warezcdn/index.ts b/src/providers/sources/warezcdn/index.ts index e504e41..bad2438 100644 --- a/src/providers/sources/warezcdn/index.ts +++ b/src/providers/sources/warezcdn/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import { SourcererEmbed, SourcererOutput, makeSourcerer } from '@/providers/base'; +import { SourcererEmbed, makeSourcerer } from '@/providers/base'; import { mixdropScraper } from '@/providers/embeds/mixdrop'; import { warezcdnembedHlsScraper } from '@/providers/embeds/warezcdn/hls'; import { warezcdnembedMp4Scraper } from '@/providers/embeds/warezcdn/mp4'; @@ -30,15 +30,16 @@ const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => const embedUrl = $(element).attr('data-load-embed')!; if (embedHost === 'mixdrop') { - const params = new URLSearchParams({ + const params = { id: embedUrl, sv: 'mixdrop', - }); - const realUrl = await ctx.proxiedFetcher(`/getPlay.php?${params}`, { + }; + const realUrl = await ctx.proxiedFetcher(`/getPlay.php`, { baseUrl: warezcdnApiBase, headers: { - Referer: `${warezcdnApiBase}/getEmbed.php?${params}`, + Referer: `${warezcdnApiBase}/getEmbed.php?${new URLSearchParams(params)}`, }, + query: params, }); const realEmbedUrl = realUrl.match(/window\.location\.href="([^"]*)";/); @@ -63,7 +64,7 @@ const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => return { embeds, - } as SourcererOutput; + }; }; export const warezcdnScraper = makeSourcerer({ From 089c6aa6ce08b962c965d2c96d8ea555e0a577fe Mon Sep 17 00:00:00 2001 From: lonelil <51315646+lonelil@users.noreply.github.com> Date: Fri, 12 Apr 2024 01:11:29 +0800 Subject: [PATCH 07/10] add flag and change rank --- src/providers/embeds/warezcdn/hls.ts | 2 +- src/providers/embeds/warezcdn/mp4.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/providers/embeds/warezcdn/hls.ts b/src/providers/embeds/warezcdn/hls.ts index 1fbbef3..2e49852 100644 --- a/src/providers/embeds/warezcdn/hls.ts +++ b/src/providers/embeds/warezcdn/hls.ts @@ -21,7 +21,7 @@ async function getVideowlUrlStream(ctx: EmbedScrapeContext, decryptedId: string) export const warezcdnembedHlsScraper = makeEmbed({ id: 'warezcdnembedhls', // WarezCDN is both a source and an embed host name: 'WarezCDN HLS', - rank: 82, + rank: 83, async scrape(ctx) { const decryptedId = await getDecryptedId(ctx); diff --git a/src/providers/embeds/warezcdn/mp4.ts b/src/providers/embeds/warezcdn/mp4.ts index caac7ae..ada781d 100644 --- a/src/providers/embeds/warezcdn/mp4.ts +++ b/src/providers/embeds/warezcdn/mp4.ts @@ -1,3 +1,4 @@ +import { flags } from '@/entrypoint/utils/targets'; import { makeEmbed } from '@/providers/base'; import { warezcdnWorkerProxy } from '@/providers/sources/warezcdn/common'; import { EmbedScrapeContext } from '@/utils/context'; @@ -24,7 +25,7 @@ async function checkUrls(ctx: EmbedScrapeContext, fileId: string) { export const warezcdnembedMp4Scraper = makeEmbed({ id: 'warezcdnembedmp4', // WarezCDN is both a source and an embed host name: 'WarezCDN MP4', - rank: 83, + rank: 82, disabled: false, async scrape(ctx) { const decryptedId = await getDecryptedId(ctx); @@ -49,7 +50,7 @@ export const warezcdnembedMp4Scraper = makeEmbed({ }, }, type: 'file', - flags: [], + flags: [flags.CORS_ALLOWED], }, ], }; From 94bfcd0c316ede250bd917eda575d1a183da289c Mon Sep 17 00:00:00 2001 From: Jorrin Date: Thu, 11 Apr 2024 20:42:37 +0200 Subject: [PATCH 08/10] skip validation check for warezcdnmp4 --- src/providers/sources/warezcdn/index.ts | 3 ++- src/runners/individualRunner.ts | 4 ++-- src/runners/runner.ts | 4 ++-- src/utils/valid.ts | 11 ++++++++++- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/providers/sources/warezcdn/index.ts b/src/providers/sources/warezcdn/index.ts index bad2438..1c9ad00 100644 --- a/src/providers/sources/warezcdn/index.ts +++ b/src/providers/sources/warezcdn/index.ts @@ -1,5 +1,6 @@ import { load } from 'cheerio'; +import { flags } from '@/entrypoint/utils/targets'; import { SourcererEmbed, makeSourcerer } from '@/providers/base'; import { mixdropScraper } from '@/providers/embeds/mixdrop'; import { warezcdnembedHlsScraper } from '@/providers/embeds/warezcdn/hls'; @@ -71,7 +72,7 @@ export const warezcdnScraper = makeSourcerer({ id: 'warezcdn', name: 'WarezCDN', rank: 81, - flags: [], + flags: [flags.CORS_ALLOWED], scrapeMovie: universalScraper, scrapeShow: universalScraper, }); diff --git a/src/runners/individualRunner.ts b/src/runners/individualRunner.ts index 6c7e452..b309180 100644 --- a/src/runners/individualRunner.ts +++ b/src/runners/individualRunner.ts @@ -71,7 +71,7 @@ export async function scrapeInvidualSource( // only check for playable streams if there are streams, and if there are no embeds if (output.stream && output.stream.length > 0 && output.embeds.length === 0) { - const playableStreams = await validatePlayableStreams(output.stream, ops); + const playableStreams = await validatePlayableStreams(output.stream, ops, sourceScraper.id); if (playableStreams.length === 0) throw new NotFoundError('No playable streams found'); output.stream = playableStreams; } @@ -112,7 +112,7 @@ export async function scrapeIndividualEmbed( .filter((stream) => flagsAllowedInFeatures(ops.features, stream.flags)); if (output.stream.length === 0) throw new NotFoundError('No streams found'); - const playableStreams = await validatePlayableStreams(output.stream, ops); + const playableStreams = await validatePlayableStreams(output.stream, ops, embedScraper.id); if (playableStreams.length === 0) throw new NotFoundError('No playable streams found'); output.stream = playableStreams; diff --git a/src/runners/runner.ts b/src/runners/runner.ts index c3bc9eb..c5f5de3 100644 --- a/src/runners/runner.ts +++ b/src/runners/runner.ts @@ -104,7 +104,7 @@ export async function runAllProviders(list: ProviderList, ops: ProviderRunnerOpt // return stream is there are any if (output.stream?.[0]) { - const playableStream = await validatePlayableStream(output.stream[0], ops); + const playableStream = await validatePlayableStream(output.stream[0], ops, source.id); if (!playableStream) throw new NotFoundError('No streams found'); return { sourceId: source.id, @@ -151,7 +151,7 @@ export async function runAllProviders(list: ProviderList, ops: ProviderRunnerOpt if (embedOutput.stream.length === 0) { throw new NotFoundError('No streams found'); } - const playableStream = await validatePlayableStream(embedOutput.stream[0], ops); + const playableStream = await validatePlayableStream(embedOutput.stream[0], ops, embed.embedId); if (!playableStream) throw new NotFoundError('No streams found'); embedOutput.stream = [playableStream]; } catch (error) { diff --git a/src/utils/valid.ts b/src/utils/valid.ts index fb9ef0f..e4ea664 100644 --- a/src/utils/valid.ts +++ b/src/utils/valid.ts @@ -1,7 +1,10 @@ +import { warezcdnembedMp4Scraper } from '@/providers/embeds/warezcdn/mp4'; import { Stream } from '@/providers/streams'; import { IndividualEmbedRunnerOptions } from '@/runners/individualRunner'; import { ProviderRunnerOptions } from '@/runners/runner'; +const SKIP_VALIDATION_CHECK_IDS = [warezcdnembedMp4Scraper.id]; + export function isValidStream(stream: Stream | undefined): boolean { if (!stream) return false; if (stream.type === 'hls') { @@ -21,7 +24,10 @@ export function isValidStream(stream: Stream | undefined): boolean { export async function validatePlayableStream( stream: Stream, ops: ProviderRunnerOptions | IndividualEmbedRunnerOptions, + sourcererId: string, ): Promise { + if (SKIP_VALIDATION_CHECK_IDS.includes(sourcererId)) return stream; + if (stream.type === 'hls') { const result = await ops.proxiedFetcher.full(stream.playlist, { method: 'GET', @@ -63,8 +69,11 @@ export async function validatePlayableStream( export async function validatePlayableStreams( streams: Stream[], ops: ProviderRunnerOptions | IndividualEmbedRunnerOptions, + sourcererId: string, ): Promise { - return (await Promise.all(streams.map((stream) => validatePlayableStream(stream, ops)))).filter( + if (SKIP_VALIDATION_CHECK_IDS.includes(sourcererId)) return streams; + + return (await Promise.all(streams.map((stream) => validatePlayableStream(stream, ops, sourcererId)))).filter( (v) => v !== null, ) as Stream[]; } From 79a8fdca6d591070ef7b3bf7d04144a8ef9f91fb Mon Sep 17 00:00:00 2001 From: lonelil <51315646+lonelil@users.noreply.github.com> Date: Fri, 12 Apr 2024 16:56:14 +0800 Subject: [PATCH 09/10] fix series --- src/providers/sources/warezcdn/common.ts | 22 ++++ src/providers/sources/warezcdn/index.ts | 160 ++++++++++++++--------- src/providers/sources/warezcdn/types.ts | 16 +++ 3 files changed, 136 insertions(+), 62 deletions(-) create mode 100644 src/providers/sources/warezcdn/types.ts diff --git a/src/providers/sources/warezcdn/common.ts b/src/providers/sources/warezcdn/common.ts index 83e94bc..56d23e8 100644 --- a/src/providers/sources/warezcdn/common.ts +++ b/src/providers/sources/warezcdn/common.ts @@ -1,4 +1,26 @@ +import { ScrapeContext } from '@/utils/context'; + export const warezcdnBase = 'https://embed.warezcdn.com'; export const warezcdnApiBase = 'https://warezcdn.com/embed'; export const warezcdnPlayerBase = 'https://warezcdn.com/player'; export const warezcdnWorkerProxy = 'https://workerproxy.warezcdn.workers.dev'; + +export async function getExternalPlayerUrl(ctx: ScrapeContext, embedId: string, embedUrl: string) { + const params = { + id: embedUrl, + sv: embedId, + }; + const realUrl = await ctx.proxiedFetcher(`/getPlay.php`, { + baseUrl: warezcdnApiBase, + headers: { + Referer: `${warezcdnApiBase}/getEmbed.php?${new URLSearchParams(params)}`, + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36', + }, + query: params, + }); + + const realEmbedUrl = realUrl.match(/window\.location\.href="([^"]*)";/); + if (!realEmbedUrl) throw new Error('Could not find embed url'); + return realEmbedUrl[1]; +} diff --git a/src/providers/sources/warezcdn/index.ts b/src/providers/sources/warezcdn/index.ts index 1c9ad00..f27b052 100644 --- a/src/providers/sources/warezcdn/index.ts +++ b/src/providers/sources/warezcdn/index.ts @@ -5,74 +5,110 @@ import { SourcererEmbed, makeSourcerer } from '@/providers/base'; import { mixdropScraper } from '@/providers/embeds/mixdrop'; import { warezcdnembedHlsScraper } from '@/providers/embeds/warezcdn/hls'; import { warezcdnembedMp4Scraper } from '@/providers/embeds/warezcdn/mp4'; -import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context'; import { NotFoundError } from '@/utils/errors'; -import { warezcdnApiBase, warezcdnBase } from './common'; - -const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => { - if (!ctx.media.imdbId) throw new NotFoundError('This source requires IMDB id.'); - - let id = `filme/${ctx.media.imdbId}`; - if (ctx.media.type === 'show') - id = `serie/${ctx.media.imdbId}/${ctx.media.season.number}/${ctx.media.episode.number}`; - - const serversPage = await ctx.proxiedFetcher(`/${id}`, { - baseUrl: warezcdnBase, - }); - const $ = load(serversPage); - - const embedsHost = $('.hostList.active [data-load-embed]').get(); - - const embeds: SourcererEmbed[] = []; - - embedsHost.forEach(async (element) => { - const embedHost = $(element).attr('data-load-embed-host')!; - const embedUrl = $(element).attr('data-load-embed')!; - - if (embedHost === 'mixdrop') { - const params = { - id: embedUrl, - sv: 'mixdrop', - }; - const realUrl = await ctx.proxiedFetcher(`/getPlay.php`, { - baseUrl: warezcdnApiBase, - headers: { - Referer: `${warezcdnApiBase}/getEmbed.php?${new URLSearchParams(params)}`, - }, - query: params, - }); - - const realEmbedUrl = realUrl.match(/window\.location\.href="([^"]*)";/); - if (!realEmbedUrl) throw new Error('Could not find embed url'); - embeds.push({ - embedId: mixdropScraper.id, - url: realEmbedUrl[1], - }); - } else if (embedHost === 'warezcdn') { - embeds.push( - { - embedId: warezcdnembedHlsScraper.id, - url: embedUrl, - }, - { - embedId: warezcdnembedMp4Scraper.id, - url: embedUrl, - }, - ); - } - }); - - return { - embeds, - }; -}; +import { getExternalPlayerUrl, warezcdnBase } from './common'; +import { SerieAjaxResponse } from './types'; export const warezcdnScraper = makeSourcerer({ id: 'warezcdn', name: 'WarezCDN', rank: 81, flags: [flags.CORS_ALLOWED], - scrapeMovie: universalScraper, - scrapeShow: universalScraper, + scrapeMovie: async (ctx) => { + if (!ctx.media.imdbId) throw new NotFoundError('This source requires IMDB id.'); + + const serversPage = await ctx.proxiedFetcher(`/filme/${ctx.media.imdbId}`, { + baseUrl: warezcdnBase, + }); + const $ = load(serversPage); + + const embedsHost = $('.hostList.active [data-load-embed]').get(); + + const embeds: SourcererEmbed[] = []; + + embedsHost.forEach(async (element) => { + const embedHost = $(element).attr('data-load-embed-host')!; + const embedUrl = $(element).attr('data-load-embed')!; + + if (embedHost === 'mixdrop') { + const realEmbedUrl = await getExternalPlayerUrl(ctx, 'mixdrop', embedUrl); + if (!realEmbedUrl) throw new Error('Could not find embed url'); + embeds.push({ + embedId: mixdropScraper.id, + url: realEmbedUrl, + }); + } else if (embedHost === 'warezcdn') { + embeds.push( + { + embedId: warezcdnembedHlsScraper.id, + url: embedUrl, + }, + { + embedId: warezcdnembedMp4Scraper.id, + url: embedUrl, + }, + ); + } + }); + + return { + embeds, + }; + }, + scrapeShow: async (ctx) => { + if (!ctx.media.imdbId) throw new NotFoundError('This source requires IMDB id.'); + + const url = `${warezcdnBase}/serie/${ctx.media.imdbId}/${ctx.media.season.number}/${ctx.media.episode.number}`; + + const serversPage = await ctx.proxiedFetcher(url); + + const episodeId = serversPage.match(/\$\('\[data-load-episode-content="(\d+)"\]'\)/)?.[1]; + + if (!episodeId) throw new NotFoundError('Failed to find episode id'); + + const streamsData = await ctx.proxiedFetcher(`/serieAjax.php`, { + method: 'POST', + baseUrl: warezcdnBase, + body: new URLSearchParams({ + getAudios: episodeId, + }), + headers: { + Origin: warezcdnBase, + Referer: url, + 'X-Requested-With': 'XMLHttpRequest', + }, + }); + + const streams: SerieAjaxResponse = JSON.parse(streamsData); + const list = streams.list['0']; + const embeds: SourcererEmbed[] = []; + + // 3 means ok + if (list.mixdropStatus === '3') { + const realEmbedUrl = await getExternalPlayerUrl(ctx, 'mixdrop', list.id); + if (!realEmbedUrl) throw new Error('Could not find embed url'); + embeds.push({ + embedId: mixdropScraper.id, + url: realEmbedUrl, + }); + } + + if (list.warezcdnStatus === '3') { + embeds.push( + { + embedId: warezcdnembedHlsScraper.id, + url: list.id, + }, + { + embedId: warezcdnembedMp4Scraper.id, + url: list.id, + }, + ); + } + + return { + embeds, + }; + }, }); diff --git a/src/providers/sources/warezcdn/types.ts b/src/providers/sources/warezcdn/types.ts new file mode 100644 index 0000000..38711ff --- /dev/null +++ b/src/providers/sources/warezcdn/types.ts @@ -0,0 +1,16 @@ +interface Data { + id: string; + audio: string; + mixdropStatus: string; + fembedStatus: string; + streamtapeStatus: string; + warezcdnStatus: string; +} + +type List = { + [key: string]: Data; +}; + +export interface SerieAjaxResponse { + list: List; +} From 0a2259b1f4a8d6c67b6e031256b9433b966b41c9 Mon Sep 17 00:00:00 2001 From: lonelil <51315646+lonelil@users.noreply.github.com> Date: Fri, 12 Apr 2024 16:59:51 +0800 Subject: [PATCH 10/10] remove user-agent --- src/providers/sources/warezcdn/common.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/providers/sources/warezcdn/common.ts b/src/providers/sources/warezcdn/common.ts index 56d23e8..182b2b6 100644 --- a/src/providers/sources/warezcdn/common.ts +++ b/src/providers/sources/warezcdn/common.ts @@ -14,8 +14,6 @@ export async function getExternalPlayerUrl(ctx: ScrapeContext, embedId: string, baseUrl: warezcdnApiBase, headers: { Referer: `${warezcdnApiBase}/getEmbed.php?${new URLSearchParams(params)}`, - 'User-Agent': - 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36', }, query: params, });