mirror of
https://github.com/movie-web/providers.git
synced 2025-09-13 10:33:25 +00:00
82 lines
2.8 KiB
TypeScript
82 lines
2.8 KiB
TypeScript
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.proxiedFetcher<SearchResult>('/search', {
|
|
baseUrl: ridoMoviesApiBase,
|
|
query: {
|
|
q: ctx.media.title,
|
|
},
|
|
});
|
|
const mediaData = searchResult.data.items.map((movieEl) => {
|
|
const name = movieEl.title;
|
|
const year = movieEl.contentable.releaseYear;
|
|
const fullSlug = movieEl.fullSlug;
|
|
return { name, year, fullSlug };
|
|
});
|
|
const targetMedia = mediaData.find((m) => m.name === ctx.media.title && m.year === ctx.media.releaseYear.toString());
|
|
if (!targetMedia?.fullSlug) throw new NotFoundError('No watchable item found');
|
|
|
|
let iframeSourceUrl = `/${targetMedia.fullSlug}/videos`;
|
|
|
|
if (ctx.media.type === 'show') {
|
|
const showPageResult = await ctx.proxiedFetcher<string>(`/${targetMedia.fullSlug}`, {
|
|
baseUrl: ridoMoviesBase,
|
|
});
|
|
const fullEpisodeSlug = `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.proxiedFetcher<IframeSourceResult>(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: 100,
|
|
flags: [flags.CORS_ALLOWED],
|
|
scrapeMovie: universalScraper,
|
|
scrapeShow: universalScraper,
|
|
});
|