From 2f289d93d0ae1cbb62becaeaad9c39915b70803e Mon Sep 17 00:00:00 2001 From: Isra Date: Thu, 28 Sep 2023 15:55:02 -0500 Subject: [PATCH] provider: showbox.media --- src/providers/all.ts | 7 ++- src/providers/embeds/febBox.ts | 58 ++++++++++++++++++++++ src/providers/sources/flixhq/search.ts | 2 +- src/providers/sources/showbox/index.ts | 66 ++++++++++++++++++++++++++ src/utils/compare.ts | 10 +--- 5 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 src/providers/embeds/febBox.ts create mode 100644 src/providers/sources/showbox/index.ts diff --git a/src/providers/all.ts b/src/providers/all.ts index 968b61d..65383c7 100644 --- a/src/providers/all.ts +++ b/src/providers/all.ts @@ -1,4 +1,5 @@ import { Embed, Sourcerer } from '@/providers/base'; +import { febBoxScraper } from '@/providers/embeds/febBox'; import { mp4uploadScraper } from '@/providers/embeds/mp4upload'; import { streamsbScraper } from '@/providers/embeds/streamsb'; import { upcloudScraper } from '@/providers/embeds/upcloud'; @@ -8,12 +9,14 @@ import { kissAsianScraper } from '@/providers/sources/kissasian/index'; import { remotestreamScraper } from '@/providers/sources/remotestream'; import { superStreamScraper } from '@/providers/sources/superstream/index'; +import { showBoxScraper } from './sources/showbox'; + export function gatherAllSources(): Array { // all sources are gathered here - return [flixhqScraper, remotestreamScraper, kissAsianScraper, superStreamScraper, goMoviesScraper]; + return [flixhqScraper, remotestreamScraper, kissAsianScraper, superStreamScraper, goMoviesScraper, showBoxScraper]; } export function gatherAllEmbeds(): Array { // all embeds are gathered here - return [upcloudScraper, mp4uploadScraper, streamsbScraper]; + return [upcloudScraper, mp4uploadScraper, streamsbScraper, febBoxScraper]; } diff --git a/src/providers/embeds/febBox.ts b/src/providers/embeds/febBox.ts new file mode 100644 index 0000000..ce7e5e9 --- /dev/null +++ b/src/providers/embeds/febBox.ts @@ -0,0 +1,58 @@ +import { flags } from '@/main/targets'; +import { makeEmbed } from '@/providers/base'; +import { NotFoundError } from '@/utils/errors'; + +const febBoxBase = `https://www.febbox.com`; + +export const febBoxScraper = makeEmbed({ + id: 'febBox', + name: 'FebBox', + rank: 160, + async scrape(ctx) { + const shareKey = ctx.url.split('/')[4]; + const streams = await ctx.fetcher<{ + data?: { + file_list?: { + fid?: string; + }[]; + }; + }>('/file/file_share_list', { + baseUrl: febBoxBase, + query: { + share_key: shareKey, + pwd: '', + }, + }); + + const fid = streams?.data?.file_list?.[0]?.fid; + if (!fid) throw new NotFoundError('no result found'); + + const formParams = new URLSearchParams(); + formParams.append('fid', fid); + formParams.append('share_key', shareKey); + + const player = await ctx.fetcher('/file/player', { + baseUrl: febBoxBase, + body: formParams, + method: 'POST', + }); + + const sourcesMatch = player?.match(/var sources = (\[[^\]]+\]);/); + const qualities = sourcesMatch ? JSON.parse(sourcesMatch[0].replace('var sources = ', '').replace(';', '')) : null; + + if (!qualities) throw new NotFoundError('no result found'); + + return { + stream: { + type: 'file', + flags: [flags.NO_CORS], + qualities: { + '360': { + type: 'mp4', + url: qualities[0].file, + }, + }, + }, + }; + }, +}); diff --git a/src/providers/sources/flixhq/search.ts b/src/providers/sources/flixhq/search.ts index cea1b14..90517f6 100644 --- a/src/providers/sources/flixhq/search.ts +++ b/src/providers/sources/flixhq/search.ts @@ -23,7 +23,7 @@ export async function getFlixhqId(ctx: ScrapeContext, media: MovieMedia | ShowMe return { id, title, - year: +year, + year: parseInt(year, 10), }; }); diff --git a/src/providers/sources/showbox/index.ts b/src/providers/sources/showbox/index.ts new file mode 100644 index 0000000..ed8a82c --- /dev/null +++ b/src/providers/sources/showbox/index.ts @@ -0,0 +1,66 @@ +// https://www.febbox.com/file/file_share_list?share_key=${id}&pwd= > data.file_list[0].fid +// https://www.febbox.com/file/player FORM: {hare_key} > "parse js" + +import { load } from 'cheerio'; + +import { flags } from '@/main/targets'; +import { makeSourcerer } from '@/providers/base'; +import { febBoxScraper } from '@/providers/embeds/febBox'; +import { compareMedia } from '@/utils/compare'; +import { NotFoundError } from '@/utils/errors'; + +const showboxBase = `https://www.showbox.media`; + +export const showBoxScraper = makeSourcerer({ + id: 'showBox', + name: 'ShowBox', + rank: 20, + flags: [flags.NO_CORS], + async scrapeMovie(ctx) { + const search = await ctx.fetcher('/search', { + baseUrl: showboxBase, + query: { + keyword: ctx.media.title, + }, + }); + + const searchPage = load(search); + const result = searchPage('.film-name > a') + .toArray() + .map((el) => { + const titleContainer = el.parent?.parent; + if (!titleContainer) return; + const year = searchPage(titleContainer).find('.fdi-item').first().text(); + + return { + title: el.attribs.title, + path: el.attribs.href, + year: !year.includes('SS') ? parseInt(year, 10) : undefined, + }; + }) + .find((v) => v && compareMedia(ctx.media, v.title, v.year ? v.year : undefined)); + + if (!result?.path) throw new NotFoundError('no result found'); + + const febboxResult = await ctx.fetcher<{ + data?: { link?: string }; + }>('/index/share_link', { + baseUrl: showboxBase, + query: { + id: result.path.split('/')[3], + type: '1', + }, + }); + + if (!febboxResult?.data?.link) throw new NotFoundError('no result found'); + + return { + embeds: [ + { + embedId: febBoxScraper.id, + url: febboxResult.data.link, + }, + ], + }; + }, +}); diff --git a/src/utils/compare.ts b/src/utils/compare.ts index ba1b5e4..8cce7da 100644 --- a/src/utils/compare.ts +++ b/src/utils/compare.ts @@ -12,14 +12,8 @@ export function compareTitle(a: string, b: string): boolean { return normalizeTitle(a) === normalizeTitle(b); } -export function compareMedia(media: CommonMedia, title: string, releaseYear?: number, compareYear?: boolean): boolean { +export function compareMedia(media: CommonMedia, title: string, releaseYear?: number): boolean { // if no year is provided, count as if its the correct year - let isSameYear: boolean; - if (!compareYear) { - isSameYear = true; - } else { - isSameYear = releaseYear === undefined ? true : media.releaseYear === releaseYear; - } - + const isSameYear = releaseYear === undefined ? true : media.releaseYear === releaseYear; return compareTitle(media.title, title) && isSameYear; }