diff --git a/src/providers/embeds/dood.ts b/src/providers/embeds/dood.ts index 4b6d413..d977fdc 100644 --- a/src/providers/embeds/dood.ts +++ b/src/providers/embeds/dood.ts @@ -1,37 +1,26 @@ +import { customAlphabet } from 'nanoid'; + import { flags } from '@/entrypoint/utils/targets'; import { makeEmbed } from '@/providers/base'; +const nanoid = customAlphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', 10); + export const doodScraper = makeEmbed({ id: 'dood', name: 'dood', rank: 173, async scrape(ctx) { - function makeTheFunny() { - let result = ''; - const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - const charactersLength = characters.length; - - for (let i = 0; i < 10; i++) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)); - } - - return result; - } - const baseUrl = 'https://do0od.com'; const id = ctx.url.split('/d/')[1] || ctx.url.split('/e/')[1]; - console.log(id); const doodData = await ctx.proxiedFetcher(`/e/${id}`, { method: 'GET', baseUrl, }); - // console.log(doodData); - - const dataForLater = doodData.split(`a+"?token=`)[1].split(`"`)[0]; - const path = doodData.split(`$.get('/pass_md5`)[1].split(`'`)[0]; + const dataForLater = doodData.match(/a\+"\?token=([^"]+)/)?.[1]; + const path = doodData.match(/\$\.get\('\/pass_md5([^']+)/)?.[1]; const doodPage = await ctx.proxiedFetcher(`/pass_md5/${path}`, { headers: { @@ -41,39 +30,28 @@ export const doodScraper = makeEmbed({ baseUrl, }); - console.log(`${baseUrl}/pass_md5/${path}`); + const downloadURL = `${doodPage}${nanoid()}?token=${dataForLater}${Date.now()}`; - console.log(doodPage); + if (!downloadURL) throw new Error('dood source not found'); - // const doodPage = await ctx.proxiedFetcher(`/download/${path}`, { method: 'GET', baseUrl }); - // console.log(doodPage); - const downloadURL = `${doodPage}${makeTheFunny()}?token=${dataForLater}${Date.now()}`; - - if (downloadURL) { - return { - stream: [ - { - id: 'primary', - type: 'file', - url: downloadURL, - flags: [flags.CORS_ALLOWED], - captions: [], - qualities: { - unknown: { - type: 'mp4', - url: downloadURL, - preferredHeaders: { - referer: 'https://do0od.com/', - 'content-type': 'video/mp4', - range: 'bytes=0-', - }, + return { + stream: [ + { + id: 'primary', + type: 'file', + flags: [], + captions: [], + qualities: { + unknown: { + type: 'mp4', + url: downloadURL, + headers: { + referer: 'https://do0od.com/', }, }, }, - ], - }; - } - - throw new Error('wootly source not found'); + }, + ], + }; }, }); diff --git a/src/providers/embeds/wootly.ts b/src/providers/embeds/wootly.ts index d02962d..701fae9 100644 --- a/src/providers/embeds/wootly.ts +++ b/src/providers/embeds/wootly.ts @@ -15,7 +15,7 @@ export const wootlyScraper = makeEmbed({ readHeaders: ['Set-Cookie'], }); - const wootssesCookie = wootlyData.headers.get('Set-Cookie')?.split(';')[0].split('wootsses=')[1]; + const wootssesCookie = wootlyData.headers.get('Set-Cookie')?.match(/wootsses=([^;]+)/)?.[1]; let $ = load(wootlyData.body); // load the html data const iframeSrc = $('iframe').attr('src') ?? ''; @@ -28,7 +28,7 @@ export const wootlyScraper = makeEmbed({ }, }); - const woozCookie = woozCookieRequest.headers.get('Set-Cookie')?.split(';')[0].split('wooz=')[1]; + const woozCookie = woozCookieRequest.headers.get('Set-Cookie')?.match(/wooz=([^;]+)/)?.[1]; const iframeData = await ctx.proxiedFetcher(iframeSrc, { method: 'POST', @@ -45,8 +45,10 @@ export const wootlyScraper = makeEmbed({ // Regular expressions to match the variables - const tk = scriptText.split('tk=')[1].split(';')[0].replaceAll('"', '').replaceAll(' ', ''); - const vd = scriptText.split('vd=')[1].split(',')[0].replaceAll('"', '').replaceAll(' ', ''); + const tk = scriptText.match(/tk=([^;]+)/)?.[0].replace(/tk=|["\s]/g, ''); + const vd = scriptText.match(/vd=([^,]+)/)?.[0].replace(/vd=|["\s]/g, ''); + + if (!tk || !vd) throw new Error('wootly source not found'); const url = await ctx.proxiedFetcher(`/grabd`, { baseUrl, @@ -57,26 +59,24 @@ export const wootlyScraper = makeEmbed({ }, }); - if (url) { - return { - stream: [ - { - id: 'primary', - type: 'file', - url, - flags: [flags.CORS_ALLOWED, flags.IP_LOCKED], - captions: [], - qualities: { - unknown: { - type: 'mp4', - url, - }, + if (!url) throw new Error('wootly source not found'); + + return { + stream: [ + { + id: 'primary', + type: 'file', + url, + flags: [flags.IP_LOCKED], + captions: [], + qualities: { + unknown: { + type: 'mp4', + url, }, }, - ], - }; - } - - throw new Error('wootly source not found'); + }, + ], + }; }, }); diff --git a/src/providers/sources/goojara/getEmbeds.ts b/src/providers/sources/goojara/getEmbeds.ts index d0a96a4..de2148a 100644 --- a/src/providers/sources/goojara/getEmbeds.ts +++ b/src/providers/sources/goojara/getEmbeds.ts @@ -8,16 +8,14 @@ export async function getEmbeds(ctx: ScrapeContext, id: string): Promise href && href.includes('https://ww1.goojara.to/go.php')); - const embeds = await Promise.all( - embedRedirectURLs.map((url) => - ctx.fetcher - .full(url, { - headers: { - cookie: `aGooz=${aGoozCookie}; ${RandomCookieName}=${RandomCookieValue};`, - Referer: 'https://ww1.goojara.to/eJwD5z', - }, - method: 'GET', - }) - .then((result) => { - if (result) { - const embedId = ['wootly', 'upstream', 'mixdrop', 'dood'].find((a) => result.finalUrl.includes(a)); - return embedId ? { embedId, url: result.finalUrl } : null; - } - return null; - }) - .catch(() => null), + const embedPages = await Promise.all( + embedRedirectURLs.map( + (url) => + ctx.fetcher + .full(url, { + headers: { + cookie: `aGooz=${aGoozCookie}; ${RandomCookieName}=${RandomCookieValue};`, + Referer: 'https://ww1.goojara.to/eJwD5z', + }, + method: 'GET', + }) + .catch(() => null), // Handle errors gracefully ), - ).then((results) => results.filter((result) => result !== null) as EmbedsResult); + ); - return embeds; + // Initialize an array to hold the results + const results = []; + + // Process each page result + for (const result of embedPages) { + // Ensure there's a result to process + if (result) { + // Attempt to find a matching embed ID + const embedId = ['wootly', 'upstream', 'mixdrop', 'dood'].find((a) => result.finalUrl.includes(a)); + // If an embed ID is found, push the result to the results array + if (embedId) { + results.push({ embedId, url: result.finalUrl }); + } + } + } + + return results; } diff --git a/src/providers/sources/goojara/index.ts b/src/providers/sources/goojara/index.ts index bd1e03f..ea85d3d 100644 --- a/src/providers/sources/goojara/index.ts +++ b/src/providers/sources/goojara/index.ts @@ -22,7 +22,7 @@ async function universalScraper(ctx: ShowScrapeContext | MovieScrapeContext): Pr export const goojaraScraper = makeSourcerer({ id: 'goojara', name: 'goojara', - rank: 69, + rank: 225, flags: [], scrapeShow: universalScraper, scrapeMovie: universalScraper, diff --git a/src/providers/sources/goojara/type.ts b/src/providers/sources/goojara/type.ts index 732ba4e..b4b4751 100644 --- a/src/providers/sources/goojara/type.ts +++ b/src/providers/sources/goojara/type.ts @@ -1,33 +1,8 @@ -// ! Types -interface BaseConfig { - /** The website's slug. Formatted as `1839578-person-of-interest-2011` */ - slug: string; - /** Type of request */ - type: 'show' | 'movie'; - /** Hash */ - hash: string; - /** Hash expiry */ - expires: number; -} -interface TvConfig extends BaseConfig { - /** Type of request */ - type: 'show'; - /** The episode ID for a TV show. Given in search and URL */ - episodeId: string; -} -interface MovieConfig extends BaseConfig { - /** Type of request */ - type: 'movie'; - /** Movie's id */ - slug: string; -} -export type Config = MovieConfig | TvConfig; - export type EmbedsResult = { embedId: string; url: string }[]; export interface Result { title: string; - slug: any; + slug: string; year: string; type: string; id_movie?: string; diff --git a/src/providers/sources/goojara/util.ts b/src/providers/sources/goojara/util.ts index 0fcba4b..4922ffa 100644 --- a/src/providers/sources/goojara/util.ts +++ b/src/providers/sources/goojara/util.ts @@ -1,4 +1,5 @@ import { load } from 'cheerio'; +import { stringify } from 'crypto-js/enc-base64'; import { MovieMedia, ShowMedia } from '@/entrypoint/utils/media'; import { compareMedia } from '@/utils/compare'; @@ -8,30 +9,24 @@ import { NotFoundError } from '@/utils/errors'; import { getEmbeds } from './getEmbeds'; import { EmbedsResult, Result } from './type'; +let data; + +// The cookie for this headerData doesn't matter, Goojara just checks it's there. T const headersData = { - accept: '*/*', - 'accept-language': 'en-US,en;q=0.9', 'content-type': 'application/x-www-form-urlencoded', - 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"', - 'sec-ch-ua-mobile': '?0', - 'sec-ch-ua-platform': '"Windows"', - 'sec-fetch-dest': 'empty', - 'sec-fetch-mode': 'cors', - 'sec-fetch-site': 'same-origin', cookie: `aGooz=t9pmkdtef1b3lg3pmo1u2re816; bd9aa48e=0d7b89e8c79844e9df07a2; _b414=2151C6B12E2A88379AFF2C0DD65AC8298DEC2BF4; 9d287aaa=8f32ad589e1c4288fe152f`, Referer: 'https://www.goojara.to/', - 'Referrer-Policy': 'strict-origin-when-cross-origin', }; export async function searchAndFindMedia( ctx: ScrapeContext, media: MovieMedia | ShowMedia, ): Promise { - const data = await ctx.fetcher(`/xhrr.php`, { + data = await ctx.fetcher(`/xhrr.php`, { baseUrl: 'https://www.goojara.to', headers: headersData, method: 'POST', - body: `q=${media.title}`, + body: new URLSearchParams({ q: media.title }), }); const $ = load(data); @@ -48,6 +43,8 @@ export async function searchAndFindMedia( const year = yearMatch ? yearMatch[1] : ''; const slug = $(element).find('a').attr('href')?.split('/')[3]; + if (!slug) throw new NotFoundError('Not found'); + if (media.type === type) { results.push({ title, year, slug, type }); } @@ -68,7 +65,7 @@ export async function scrapeIds( if (media.type === 'movie') { id = result.slug; } else if (media.type === 'show') { - const data = await ctx.fetcher(`/${result.slug}`, { + data = await ctx.fetcher(`/${result.slug}`, { baseUrl: 'https://www.goojara.to', headers: headersData, method: 'GET', @@ -76,18 +73,20 @@ export async function scrapeIds( const $1 = load(data); - const dataId = $1('#seon').data('id'); + const dataId = $1('#seon').attr('data-id'); - const data2 = await ctx.fetcher(`/xhrc.php`, { + if (!dataId) throw NotFoundError; + + data = await ctx.fetcher(`/xhrc.php`, { baseUrl: 'https://ww1.goojara.to', headers: headersData, method: 'POST', - body: `s=${media.season.number}&t=${dataId}`, + body: new URLSearchParams({ s: media.season.number.toString(), t: dataId }), }); let episodeId = ''; - const $2 = load(data2); + const $2 = load(data); $2('.seho').each((index, element) => { // Extracting the episode number as a string