From f88021fff692f08c78d3dfb9755f4997c172124c Mon Sep 17 00:00:00 2001 From: Jorrin Date: Fri, 29 Dec 2023 19:24:34 +0100 Subject: [PATCH 1/7] added ridomovies --- src/providers/all.ts | 6 ++ src/providers/embeds/closeload.ts | 67 +++++++++++++++++++ src/providers/embeds/ridoo.ts | 46 +++++++++++++ src/providers/sources/ridomovies/index.ts | 74 +++++++++++++++++++++ src/providers/sources/ridomovies/types.ts | 78 +++++++++++++++++++++++ 5 files changed, 271 insertions(+) create mode 100644 src/providers/embeds/closeload.ts create mode 100644 src/providers/embeds/ridoo.ts create mode 100644 src/providers/sources/ridomovies/index.ts create mode 100644 src/providers/sources/ridomovies/types.ts diff --git a/src/providers/all.ts b/src/providers/all.ts index d1e7885..e1a4ef0 100644 --- a/src/providers/all.ts +++ b/src/providers/all.ts @@ -14,8 +14,11 @@ import { remotestreamScraper } from '@/providers/sources/remotestream'; import { showboxScraper } from '@/providers/sources/showbox/index'; import { zoechipScraper } from '@/providers/sources/zoechip'; +import { closeLoadScraper } from './embeds/closeload'; +import { ridooScraper } from './embeds/ridoo'; import { smashyStreamDScraper } from './embeds/smashystream/dued'; import { smashyStreamFScraper } from './embeds/smashystream/video1'; +import { ridooMoviesScraper } from './sources/ridomovies'; import { smashyStreamScraper } from './sources/smashystream'; export function gatherAllSources(): Array { @@ -29,6 +32,7 @@ export function gatherAllSources(): Array { zoechipScraper, lookmovieScraper, smashyStreamScraper, + ridooMoviesScraper, ]; } @@ -44,5 +48,7 @@ export function gatherAllEmbeds(): Array { mixdropScraper, smashyStreamFScraper, smashyStreamDScraper, + ridooScraper, + closeLoadScraper, ]; } diff --git a/src/providers/embeds/closeload.ts b/src/providers/embeds/closeload.ts new file mode 100644 index 0000000..e8d47dd --- /dev/null +++ b/src/providers/embeds/closeload.ts @@ -0,0 +1,67 @@ +import { load } from 'cheerio'; +import { unpack } from 'unpacker'; + +import { flags } from '@/entrypoint/utils/targets'; +import { NotFoundError } from '@/utils/errors'; + +import { makeEmbed } from '../base'; +import { Caption, getCaptionTypeFromUrl, labelToLanguageCode } from '../captions'; + +const referer = 'https://ridomovies.tv/'; + +export const closeLoadScraper = makeEmbed({ + id: 'closeload', + name: 'CloseLoad', + rank: 501, + async scrape(ctx) { + const baseUrl = new URL(ctx.url).origin; + + const iframeRes = await ctx.proxiedFetcher(ctx.url, { + headers: { referer }, + }); + const iframeRes$ = load(iframeRes); + const captions: Caption[] = iframeRes$('track') + .map((_, el) => { + const track = iframeRes$(el); + const url = `${baseUrl}${track.attr('src')}`; + const label = track.attr('label') ?? ''; + const language = labelToLanguageCode(label); + const captionType = getCaptionTypeFromUrl(url); + + if (!language || !captionType) return null; + return { + id: url, + language, + hasCorsRestrictions: false, + type: captionType, + url, + }; + }) + .get() + .filter((x) => x !== null); + + const evalCode = iframeRes$('script') + .filter((_, el) => { + const script = iframeRes$(el); + return (script.attr('type') === 'text/javascript' && script.html()?.includes('eval')) ?? false; + }) + .html(); + if (!evalCode) throw new Error("Couldn't find eval code"); + const decoded = unpack(evalCode); + const regexPattern = /var\s+(\w+)\s*=\s*"([^"]+)";/g; + const base64EncodedUrl = regexPattern.exec(decoded)?.[2]; + if (!base64EncodedUrl) throw new NotFoundError('Unable to find source url'); + const url = atob(base64EncodedUrl); + return { + stream: [ + { + id: 'primary', + type: 'hls', + playlist: url, + captions, + flags: [flags.IP_LOCKED], + }, + ], + }; + }, +}); diff --git a/src/providers/embeds/ridoo.ts b/src/providers/embeds/ridoo.ts new file mode 100644 index 0000000..0473e9c --- /dev/null +++ b/src/providers/embeds/ridoo.ts @@ -0,0 +1,46 @@ +import { load } from 'cheerio'; +import { unpack } from 'unpacker'; + +import { flags } from '@/entrypoint/utils/targets'; +import { NotFoundError } from '@/utils/errors'; + +import { makeEmbed } from '../base'; + +const referer = 'https://ridomovies.tv/'; + +export const ridooScraper = makeEmbed({ + id: 'ridoo', + name: 'Ridoo', + rank: 500, + async scrape(ctx) { + const res = await ctx.proxiedFetcher(ctx.url, { + headers: { + referer, + }, + }); + const $ = load(res); + const evalCode = $('script') + .filter((_, el) => { + const script = $(el); + return (script.attr('type') === 'text/javascript' && script.html()?.includes('eval')) ?? false; + }) + .html(); + if (!evalCode) throw new Error(res); + const decoded = unpack(evalCode); + const regexPattern = /file:"([^"]+)"/g; + const url = regexPattern.exec(decoded)?.[1]; + if (!url) throw new NotFoundError('Unable to find source url'); + + return { + stream: [ + { + id: 'primary', + type: 'hls', + playlist: url, + captions: [], + flags: [flags.CORS_ALLOWED], + }, + ], + }; + }, +}); diff --git a/src/providers/sources/ridomovies/index.ts b/src/providers/sources/ridomovies/index.ts new file mode 100644 index 0000000..a7938f4 --- /dev/null +++ b/src/providers/sources/ridomovies/index.ts @@ -0,0 +1,74 @@ +import { load } from 'cheerio'; + +import { flags } from '@/entrypoint/utils/targets'; +import { SourcererEmbed, makeSourcerer } from '@/providers/base'; +import { closeLoadScraper } from '@/providers/embeds/closeload'; +import { ridooScraper } from '@/providers/embeds/ridoo'; +import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context'; +import { NotFoundError } from '@/utils/errors'; + +import { IframeSourceResult, SearchResult } from './types'; + +const ridoMoviesBase = `https://ridomovies.tv`; +const ridoMoviesApiBase = `${ridoMoviesBase}/core/api`; + +const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => { + const searchResult = await ctx.fetcher('/search', { + baseUrl: ridoMoviesApiBase, + query: { + q: encodeURIComponent(ctx.media.title), + }, + }); + const show = searchResult.data.items[0]; + + let iframeSourceUrl = `/${show.fullSlug}/videos`; + + if (ctx.media.type === 'show') { + const showPageResult = await ctx.fetcher(`/${show.fullSlug}`, { + baseUrl: ridoMoviesBase, + }); + const fullEpisodeSlug = `${show.fullSlug}/season-${ctx.media.season.number}/episode-${ctx.media.episode.number}`; + const regexPattern = new RegExp( + `\\\\"id\\\\":\\\\"(\\d+)\\\\"(?=.*?\\\\\\"fullSlug\\\\\\":\\\\\\"${fullEpisodeSlug}\\\\\\")`, + 'g', + ); + const matches = [...showPageResult.matchAll(regexPattern)]; + const episodeIds = matches.map((match) => match[1]); + if (episodeIds.length === 0) throw new NotFoundError('No watchable item found'); + const episodeId = episodeIds.at(-1); + iframeSourceUrl = `/episodes/${episodeId}/videos`; + } + + const iframeSource = await ctx.fetcher(iframeSourceUrl, { + baseUrl: ridoMoviesApiBase, + }); + const iframeSource$ = load(iframeSource.data[0].url); + const iframeUrl = iframeSource$('iframe').attr('data-src'); + if (!iframeUrl) throw new NotFoundError('No watchable item found'); + + const embeds: SourcererEmbed[] = []; + if (iframeUrl.includes('closeload')) { + embeds.push({ + embedId: closeLoadScraper.id, + url: iframeUrl, + }); + } + if (iframeUrl.includes('ridoo')) { + embeds.push({ + embedId: ridooScraper.id, + url: iframeUrl, + }); + } + return { + embeds, + }; +}; + +export const ridooMoviesScraper = makeSourcerer({ + id: 'ridomovies', + name: 'RidoMovies', + rank: 500, + flags: [flags.CORS_ALLOWED], + scrapeMovie: universalScraper, + scrapeShow: universalScraper, +}); diff --git a/src/providers/sources/ridomovies/types.ts b/src/providers/sources/ridomovies/types.ts new file mode 100644 index 0000000..a030738 --- /dev/null +++ b/src/providers/sources/ridomovies/types.ts @@ -0,0 +1,78 @@ +export interface Content { + id: string; + type: string; + slug: string; + title: string; + metaTitle: any; + metaDescription: any; + usersOnly: boolean; + userLevel: number; + vipOnly: boolean; + copyrighted: boolean; + status: string; + publishedAt: string; + createdAt: string; + updatedAt: string; + fullSlug: string; +} + +export interface Contentable { + id: string; + contentId: string; + revisionId: any; + originalTitle: string; + overview: string; + releaseDate: string; + releaseYear: string; + videoNote: any; + posterNote: any; + userRating: number; + imdbRating: number; + imdbVotes: number; + imdbId: string; + duration: number; + countryCode: string; + posterPath: string; + backdropPath: string; + apiPosterPath: string; + apiBackdropPath: string; + trailerUrl: string; + mpaaRating: string; + tmdbId: number; + manual: number; + directorId: number; + createdAt: string; + updatedAt: string; + content: Content; +} + +export interface SearchResultItem { + id: string; + type: string; + slug: string; + title: string; + metaTitle: any; + metaDescription: any; + usersOnly: boolean; + userLevel: number; + vipOnly: boolean; + copyrighted: boolean; + status: string; + publishedAt: string; + createdAt: string; + updatedAt: string; + fullSlug: string; + contentable: Contentable; +} + +export type SearchResult = { + data: { + items: SearchResultItem[]; + }; +}; + +export type IframeSourceResult = { + data: { + url: string; + }[]; +}; From 69e66ab855b9d445b1165668c4af802f4f3c275a Mon Sep 17 00:00:00 2001 From: Jorrin Date: Wed, 3 Jan 2024 13:55:11 +0100 Subject: [PATCH 2/7] proxied fetcher --- src/providers/embeds/ridoo.ts | 2 +- src/providers/sources/ridomovies/index.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/providers/embeds/ridoo.ts b/src/providers/embeds/ridoo.ts index 0473e9c..326fc34 100644 --- a/src/providers/embeds/ridoo.ts +++ b/src/providers/embeds/ridoo.ts @@ -25,7 +25,7 @@ export const ridooScraper = makeEmbed({ return (script.attr('type') === 'text/javascript' && script.html()?.includes('eval')) ?? false; }) .html(); - if (!evalCode) throw new Error(res); + if (!evalCode) throw new Error("Couldn't find eval code"); const decoded = unpack(evalCode); const regexPattern = /file:"([^"]+)"/g; const url = regexPattern.exec(decoded)?.[1]; diff --git a/src/providers/sources/ridomovies/index.ts b/src/providers/sources/ridomovies/index.ts index a7938f4..2335149 100644 --- a/src/providers/sources/ridomovies/index.ts +++ b/src/providers/sources/ridomovies/index.ts @@ -13,7 +13,7 @@ const ridoMoviesBase = `https://ridomovies.tv`; const ridoMoviesApiBase = `${ridoMoviesBase}/core/api`; const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => { - const searchResult = await ctx.fetcher('/search', { + const searchResult = await ctx.proxiedFetcher('/search', { baseUrl: ridoMoviesApiBase, query: { q: encodeURIComponent(ctx.media.title), @@ -24,7 +24,7 @@ const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => let iframeSourceUrl = `/${show.fullSlug}/videos`; if (ctx.media.type === 'show') { - const showPageResult = await ctx.fetcher(`/${show.fullSlug}`, { + const showPageResult = await ctx.proxiedFetcher(`/${show.fullSlug}`, { baseUrl: ridoMoviesBase, }); const fullEpisodeSlug = `${show.fullSlug}/season-${ctx.media.season.number}/episode-${ctx.media.episode.number}`; @@ -39,7 +39,7 @@ const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => iframeSourceUrl = `/episodes/${episodeId}/videos`; } - const iframeSource = await ctx.fetcher(iframeSourceUrl, { + const iframeSource = await ctx.proxiedFetcher(iframeSourceUrl, { baseUrl: ridoMoviesApiBase, }); const iframeSource$ = load(iframeSource.data[0].url); From cc400aebb716671769a73c34e0b2f359269009e1 Mon Sep 17 00:00:00 2001 From: Jorrin Date: Wed, 3 Jan 2024 14:02:08 +0100 Subject: [PATCH 3/7] ip locked ridoo --- src/providers/embeds/ridoo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/embeds/ridoo.ts b/src/providers/embeds/ridoo.ts index 326fc34..eeb770c 100644 --- a/src/providers/embeds/ridoo.ts +++ b/src/providers/embeds/ridoo.ts @@ -38,7 +38,7 @@ export const ridooScraper = makeEmbed({ type: 'hls', playlist: url, captions: [], - flags: [flags.CORS_ALLOWED], + flags: [flags.CORS_ALLOWED, flags.IP_LOCKED], }, ], }; From 2f892eec7b849831c4f88831a10ba7859a0fcf10 Mon Sep 17 00:00:00 2001 From: Jorrin Date: Thu, 4 Jan 2024 21:21:18 +0100 Subject: [PATCH 4/7] remove ip lock from ridoo --- src/providers/embeds/ridoo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/embeds/ridoo.ts b/src/providers/embeds/ridoo.ts index eeb770c..326fc34 100644 --- a/src/providers/embeds/ridoo.ts +++ b/src/providers/embeds/ridoo.ts @@ -38,7 +38,7 @@ export const ridooScraper = makeEmbed({ type: 'hls', playlist: url, captions: [], - flags: [flags.CORS_ALLOWED, flags.IP_LOCKED], + flags: [flags.CORS_ALLOWED], }, ], }; From 7e1c897e30995fb92eeef50dd5e9405352710b66 Mon Sep 17 00:00:00 2001 From: Jorrin Date: Fri, 5 Jan 2024 21:23:32 +0100 Subject: [PATCH 5/7] fix ranks and feedback --- src/providers/embeds/closeload.ts | 2 +- src/providers/embeds/ridoo.ts | 16 ++-------------- src/providers/sources/ridomovies/index.ts | 5 +++-- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/providers/embeds/closeload.ts b/src/providers/embeds/closeload.ts index e8d47dd..ebe842c 100644 --- a/src/providers/embeds/closeload.ts +++ b/src/providers/embeds/closeload.ts @@ -12,7 +12,7 @@ const referer = 'https://ridomovies.tv/'; export const closeLoadScraper = makeEmbed({ id: 'closeload', name: 'CloseLoad', - rank: 501, + rank: 106, async scrape(ctx) { const baseUrl = new URL(ctx.url).origin; diff --git a/src/providers/embeds/ridoo.ts b/src/providers/embeds/ridoo.ts index 326fc34..d7f5df5 100644 --- a/src/providers/embeds/ridoo.ts +++ b/src/providers/embeds/ridoo.ts @@ -1,6 +1,3 @@ -import { load } from 'cheerio'; -import { unpack } from 'unpacker'; - import { flags } from '@/entrypoint/utils/targets'; import { NotFoundError } from '@/utils/errors'; @@ -11,24 +8,15 @@ const referer = 'https://ridomovies.tv/'; export const ridooScraper = makeEmbed({ id: 'ridoo', name: 'Ridoo', - rank: 500, + rank: 105, async scrape(ctx) { const res = await ctx.proxiedFetcher(ctx.url, { headers: { referer, }, }); - const $ = load(res); - const evalCode = $('script') - .filter((_, el) => { - const script = $(el); - return (script.attr('type') === 'text/javascript' && script.html()?.includes('eval')) ?? false; - }) - .html(); - if (!evalCode) throw new Error("Couldn't find eval code"); - const decoded = unpack(evalCode); const regexPattern = /file:"([^"]+)"/g; - const url = regexPattern.exec(decoded)?.[1]; + const url = regexPattern.exec(res)?.[1]; if (!url) throw new NotFoundError('Unable to find source url'); return { diff --git a/src/providers/sources/ridomovies/index.ts b/src/providers/sources/ridomovies/index.ts index 2335149..f028875 100644 --- a/src/providers/sources/ridomovies/index.ts +++ b/src/providers/sources/ridomovies/index.ts @@ -16,10 +16,11 @@ const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => const searchResult = await ctx.proxiedFetcher('/search', { baseUrl: ridoMoviesApiBase, query: { - q: encodeURIComponent(ctx.media.title), + q: ctx.media.title, }, }); const show = searchResult.data.items[0]; + if (!show) throw new NotFoundError('No watchable item found'); let iframeSourceUrl = `/${show.fullSlug}/videos`; @@ -67,7 +68,7 @@ const universalScraper = async (ctx: MovieScrapeContext | ShowScrapeContext) => export const ridooMoviesScraper = makeSourcerer({ id: 'ridomovies', name: 'RidoMovies', - rank: 500, + rank: 105, flags: [flags.CORS_ALLOWED], scrapeMovie: universalScraper, scrapeShow: universalScraper, From c6c921f80b3cac136158b72b0be20f48761b785b Mon Sep 17 00:00:00 2001 From: Jorrin Date: Sun, 28 Jan 2024 00:29:52 +0100 Subject: [PATCH 6/7] add cors restriction to caption, add preferredHeaders --- src/providers/embeds/closeload.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/providers/embeds/closeload.ts b/src/providers/embeds/closeload.ts index ebe842c..7afa86a 100644 --- a/src/providers/embeds/closeload.ts +++ b/src/providers/embeds/closeload.ts @@ -32,7 +32,7 @@ export const closeLoadScraper = makeEmbed({ return { id: url, language, - hasCorsRestrictions: false, + hasCorsRestrictions: true, type: captionType, url, }; @@ -60,6 +60,10 @@ export const closeLoadScraper = makeEmbed({ playlist: url, captions, flags: [flags.IP_LOCKED], + preferredHeaders: { + Referer: 'https://closeload.top/', + Origin: 'https://closeload.top', + }, }, ], }; From 25dbadd9090251066bb84f49d625bb27634d3dd9 Mon Sep 17 00:00:00 2001 From: Jorrin Date: Sun, 28 Jan 2024 00:33:33 +0100 Subject: [PATCH 7/7] rename --- src/providers/embeds/closeload.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/embeds/closeload.ts b/src/providers/embeds/closeload.ts index 7afa86a..0235a49 100644 --- a/src/providers/embeds/closeload.ts +++ b/src/providers/embeds/closeload.ts @@ -60,7 +60,7 @@ export const closeLoadScraper = makeEmbed({ playlist: url, captions, flags: [flags.IP_LOCKED], - preferredHeaders: { + headers: { Referer: 'https://closeload.top/', Origin: 'https://closeload.top', },