From f09c99b02113c2d06df4dbd0147da3c4c56a0525 Mon Sep 17 00:00:00 2001 From: TPN Date: Thu, 23 May 2024 14:46:57 +0000 Subject: [PATCH] i hate lint --- src/providers/captions.ts | 6 +- src/runners/individualRunner.ts | 96 +++++++++++----------------- src/runners/runner.ts | 109 +++++++++++++------------------- src/utils/opensubtitles.ts | 33 ++++------ 4 files changed, 94 insertions(+), 150 deletions(-) diff --git a/src/providers/captions.ts b/src/providers/captions.ts index a5b5906..d64dcc2 100644 --- a/src/providers/captions.ts +++ b/src/providers/captions.ts @@ -1,8 +1,8 @@ -import ISO6391 from "iso-639-1"; +import ISO6391 from 'iso-639-1'; export const captionTypes = { - srt: "srt", - vtt: "vtt", + srt: 'srt', + vtt: 'vtt', }; export type CaptionType = keyof typeof captionTypes; diff --git a/src/runners/individualRunner.ts b/src/runners/individualRunner.ts index 5c1c790..da7fca9 100644 --- a/src/runners/individualRunner.ts +++ b/src/runners/individualRunner.ts @@ -1,13 +1,13 @@ -import { IndividualScraperEvents } from "@/entrypoint/utils/events"; -import { ScrapeMedia } from "@/entrypoint/utils/media"; -import { FeatureMap, flagsAllowedInFeatures } from "@/entrypoint/utils/targets"; -import { UseableFetcher } from "@/fetchers/types"; -import { EmbedOutput, SourcererOutput } from "@/providers/base"; -import { ProviderList } from "@/providers/get"; -import { ScrapeContext } from "@/utils/context"; -import { NotFoundError } from "@/utils/errors"; -import { addOpenSubtitlesCaptions } from "@/utils/opensubtitles"; -import { isValidStream, validatePlayableStreams } from "@/utils/valid"; +import { IndividualScraperEvents } from '@/entrypoint/utils/events'; +import { ScrapeMedia } from '@/entrypoint/utils/media'; +import { FeatureMap, flagsAllowedInFeatures } from '@/entrypoint/utils/targets'; +import { UseableFetcher } from '@/fetchers/types'; +import { EmbedOutput, SourcererOutput } from '@/providers/base'; +import { ProviderList } from '@/providers/get'; +import { ScrapeContext } from '@/utils/context'; +import { NotFoundError } from '@/utils/errors'; +import { addOpenSubtitlesCaptions } from '@/utils/opensubtitles'; +import { isValidStream, validatePlayableStreams } from '@/utils/valid'; export type IndividualSourceRunnerOptions = { features: FeatureMap; @@ -20,14 +20,12 @@ export type IndividualSourceRunnerOptions = { export async function scrapeInvidualSource( list: ProviderList, - ops: IndividualSourceRunnerOptions + ops: IndividualSourceRunnerOptions, ): Promise { const sourceScraper = list.sources.find((v) => ops.id === v.id); - if (!sourceScraper) throw new Error("Source with ID not found"); - if (ops.media.type === "movie" && !sourceScraper.scrapeMovie) - throw new Error("Source is not compatible with movies"); - if (ops.media.type === "show" && !sourceScraper.scrapeShow) - throw new Error("Source is not compatible with shows"); + if (!sourceScraper) throw new Error('Source with ID not found'); + if (ops.media.type === 'movie' && !sourceScraper.scrapeMovie) throw new Error('Source is not compatible with movies'); + if (ops.media.type === 'show' && !sourceScraper.scrapeShow) throw new Error('Source is not compatible with shows'); const contextBase: ScrapeContext = { fetcher: ops.fetcher, @@ -36,18 +34,18 @@ export async function scrapeInvidualSource( ops.events?.update?.({ id: sourceScraper.id, percentage: val, - status: "pending", + status: 'pending', }); }, }; let output: SourcererOutput | null = null; - if (ops.media.type === "movie" && sourceScraper.scrapeMovie) + if (ops.media.type === 'movie' && sourceScraper.scrapeMovie) output = await sourceScraper.scrapeMovie({ ...contextBase, media: ops.media, }); - else if (ops.media.type === "show" && sourceScraper.scrapeShow) + else if (ops.media.type === 'show' && sourceScraper.scrapeShow) output = await sourceScraper.scrapeShow({ ...contextBase, media: ops.media, @@ -60,7 +58,7 @@ export async function scrapeInvidualSource( .filter((stream) => flagsAllowedInFeatures(ops.features, stream.flags)); } - if (!output) throw new Error("output is null"); + if (!output) throw new Error('output is null'); // filter output with only valid embeds that are not disabled output.embeds = output.embeds.filter((embed) => { @@ -71,29 +69,19 @@ export async function scrapeInvidualSource( // opensubtitles for (const embed of output.embeds) - embed.url = `${embed.url}${btoa("MEDIA=")}${btoa( + embed.url = `${embed.url}${btoa('MEDIA=')}${btoa( `${ops.media.imdbId}${ - ops.media.type === "show" - ? `.${ops.media.season.number}.${ops.media.episode.number}` - : "" - }` + ops.media.type === 'show' ? `.${ops.media.season.number}.${ops.media.episode.number}` : '' + }`, )}`; - if ( - (!output.stream || output.stream.length === 0) && - output.embeds.length === 0 - ) - throw new NotFoundError("No streams found"); + if ((!output.stream || output.stream.length === 0) && output.embeds.length === 0) + throw new NotFoundError('No streams found'); // 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, - sourceScraper.id - ); - if (playableStreams.length === 0) - throw new NotFoundError("No playable streams found"); + const playableStreams = await validatePlayableStreams(output.stream, ops, sourceScraper.id); + if (playableStreams.length === 0) throw new NotFoundError('No playable streams found'); // opensubtitles for (const playableStream of playableStreams) { @@ -102,11 +90,9 @@ export async function scrapeInvidualSource( ops, btoa( `${ops.media.imdbId}${ - ops.media.type === "show" - ? `.${ops.media.season.number}.${ops.media.episode.number}` - : "" - }` - ) + ops.media.type === 'show' ? `.${ops.media.season.number}.${ops.media.episode.number}` : '' + }`, + ), ); } output.stream = playableStreams; @@ -125,15 +111,14 @@ export type IndividualEmbedRunnerOptions = { export async function scrapeIndividualEmbed( list: ProviderList, - ops: IndividualEmbedRunnerOptions + ops: IndividualEmbedRunnerOptions, ): Promise { const embedScraper = list.embeds.find((v) => ops.id === v.id); - if (!embedScraper) throw new Error("Embed with ID not found"); + if (!embedScraper) throw new Error('Embed with ID not found'); let url = ops.url; let media; - if (ops.url.includes(btoa("MEDIA="))) - [url, media] = url.split(btoa("MEDIA=")); + if (ops.url.includes(btoa('MEDIA='))) [url, media] = url.split(btoa('MEDIA=')); const output = await embedScraper.scrape({ fetcher: ops.fetcher, @@ -143,7 +128,7 @@ export async function scrapeIndividualEmbed( ops.events?.update?.({ id: embedScraper.id, percentage: val, - status: "pending", + status: 'pending', }); }, }); @@ -151,23 +136,14 @@ export async function scrapeIndividualEmbed( output.stream = output.stream .filter((stream) => isValidStream(stream)) .filter((stream) => flagsAllowedInFeatures(ops.features, stream.flags)); - if (output.stream.length === 0) throw new NotFoundError("No streams found"); + if (output.stream.length === 0) throw new NotFoundError('No streams found'); - const playableStreams = await validatePlayableStreams( - output.stream, - ops, - embedScraper.id - ); - if (playableStreams.length === 0) - throw new NotFoundError("No playable streams found"); + const playableStreams = await validatePlayableStreams(output.stream, ops, embedScraper.id); + if (playableStreams.length === 0) throw new NotFoundError('No playable streams found'); if (media) for (const playableStream of playableStreams) - playableStream.captions = await addOpenSubtitlesCaptions( - playableStream.captions, - ops, - media - ); + playableStream.captions = await addOpenSubtitlesCaptions(playableStream.captions, ops, media); output.stream = playableStreams; diff --git a/src/runners/runner.ts b/src/runners/runner.ts index f05830f..e6dea21 100644 --- a/src/runners/runner.ts +++ b/src/runners/runner.ts @@ -1,15 +1,15 @@ -import { FullScraperEvents, UpdateEvent } from "@/entrypoint/utils/events"; -import { ScrapeMedia } from "@/entrypoint/utils/media"; -import { FeatureMap, flagsAllowedInFeatures } from "@/entrypoint/utils/targets"; -import { UseableFetcher } from "@/fetchers/types"; -import { EmbedOutput, SourcererOutput } from "@/providers/base"; -import { ProviderList } from "@/providers/get"; -import { Stream } from "@/providers/streams"; -import { ScrapeContext } from "@/utils/context"; -import { NotFoundError } from "@/utils/errors"; -import { reorderOnIdList } from "@/utils/list"; -import { addOpenSubtitlesCaptions } from "@/utils/opensubtitles"; -import { isValidStream, validatePlayableStream } from "@/utils/valid"; +import { FullScraperEvents, UpdateEvent } from '@/entrypoint/utils/events'; +import { ScrapeMedia } from '@/entrypoint/utils/media'; +import { FeatureMap, flagsAllowedInFeatures } from '@/entrypoint/utils/targets'; +import { UseableFetcher } from '@/fetchers/types'; +import { EmbedOutput, SourcererOutput } from '@/providers/base'; +import { ProviderList } from '@/providers/get'; +import { Stream } from '@/providers/streams'; +import { ScrapeContext } from '@/utils/context'; +import { NotFoundError } from '@/utils/errors'; +import { reorderOnIdList } from '@/utils/list'; +import { addOpenSubtitlesCaptions } from '@/utils/opensubtitles'; +import { isValidStream, validatePlayableStream } from '@/utils/valid'; export type RunOutput = { sourceId: string; @@ -38,20 +38,15 @@ export type ProviderRunnerOptions = { media: ScrapeMedia; }; -export async function runAllProviders( - list: ProviderList, - ops: ProviderRunnerOptions -): Promise { - const sources = reorderOnIdList(ops.sourceOrder ?? [], list.sources).filter( - (source) => { - if (ops.media.type === "movie") return !!source.scrapeMovie; - if (ops.media.type === "show") return !!source.scrapeShow; - return false; - } - ); +export async function runAllProviders(list: ProviderList, ops: ProviderRunnerOptions): Promise { + const sources = reorderOnIdList(ops.sourceOrder ?? [], list.sources).filter((source) => { + if (ops.media.type === 'movie') return !!source.scrapeMovie; + if (ops.media.type === 'show') return !!source.scrapeShow; + return false; + }); const embeds = reorderOnIdList(ops.embedOrder ?? [], list.embeds); const embedIds = embeds.map((embed) => embed.id); - let lastId = ""; + let lastId = ''; const contextBase: ScrapeContext = { fetcher: ops.fetcher, @@ -60,7 +55,7 @@ export async function runAllProviders( ops.events?.update?.({ id: lastId, percentage: val, - status: "pending", + status: 'pending', }); }, }; @@ -76,12 +71,12 @@ export async function runAllProviders( // run source scrapers let output: SourcererOutput | null = null; try { - if (ops.media.type === "movie" && source.scrapeMovie) + if (ops.media.type === 'movie' && source.scrapeMovie) output = await source.scrapeMovie({ ...contextBase, media: ops.media, }); - else if (ops.media.type === "show" && source.scrapeShow) + else if (ops.media.type === 'show' && source.scrapeShow) output = await source.scrapeShow({ ...contextBase, media: ops.media, @@ -89,18 +84,16 @@ export async function runAllProviders( if (output) { output.stream = (output.stream ?? []) .filter(isValidStream) - .filter((stream) => - flagsAllowedInFeatures(ops.features, stream.flags) - ); + .filter((stream) => flagsAllowedInFeatures(ops.features, stream.flags)); } if (!output || (!output.stream?.length && !output.embeds.length)) { - throw new NotFoundError("No streams found"); + throw new NotFoundError('No streams found'); } } catch (error) { const updateParams: UpdateEvent = { id: source.id, percentage: 100, - status: error instanceof NotFoundError ? "notfound" : "failure", + status: error instanceof NotFoundError ? 'notfound' : 'failure', reason: error instanceof NotFoundError ? error.message : undefined, error: error instanceof NotFoundError ? undefined : error, }; @@ -108,16 +101,12 @@ export async function runAllProviders( ops.events?.update?.(updateParams); continue; } - if (!output) throw new Error("Invalid media type"); + if (!output) throw new Error('Invalid media type'); // return stream is there are any if (output.stream?.[0]) { - const playableStream = await validatePlayableStream( - output.stream[0], - ops, - source.id - ); - if (!playableStream) throw new NotFoundError("No streams found"); + const playableStream = await validatePlayableStream(output.stream[0], ops, source.id); + if (!playableStream) throw new NotFoundError('No streams found'); // opensubtitles playableStream.captions = await addOpenSubtitlesCaptions( @@ -125,11 +114,9 @@ export async function runAllProviders( ops, btoa( `${ops.media.imdbId}${ - ops.media.type === "show" - ? `.${ops.media.season.number}.${ops.media.episode.number}` - : "" - }` - ) + ops.media.type === 'show' ? `.${ops.media.season.number}.${ops.media.episode.number}` : '' + }`, + ), ); return { @@ -144,14 +131,12 @@ export async function runAllProviders( const e = list.embeds.find((v) => v.id === embed.embedId); return e && !e.disabled; }) - .sort( - (a, b) => embedIds.indexOf(a.embedId) - embedIds.indexOf(b.embedId) - ); + .sort((a, b) => embedIds.indexOf(a.embedId) - embedIds.indexOf(b.embedId)); if (sortedEmbeds.length > 0) { ops.events?.discoverEmbeds?.({ embeds: sortedEmbeds.map((embed, i) => ({ - id: [source.id, i].join("-"), + id: [source.id, i].join('-'), embedScraperId: embed.embedId, })), sourceId: source.id, @@ -160,10 +145,10 @@ export async function runAllProviders( for (const [ind, embed] of sortedEmbeds.entries()) { const scraper = embeds.find((v) => v.id === embed.embedId); - if (!scraper) throw new Error("Invalid embed returned"); + if (!scraper) throw new Error('Invalid embed returned'); // run embed scraper - const id = [source.id, ind].join("-"); + const id = [source.id, ind].join('-'); ops.events?.start?.(id); lastId = id; @@ -175,18 +160,12 @@ export async function runAllProviders( }); embedOutput.stream = embedOutput.stream .filter(isValidStream) - .filter((stream) => - flagsAllowedInFeatures(ops.features, stream.flags) - ); + .filter((stream) => flagsAllowedInFeatures(ops.features, stream.flags)); if (embedOutput.stream.length === 0) { - throw new NotFoundError("No streams found"); + throw new NotFoundError('No streams found'); } - const playableStream = await validatePlayableStream( - embedOutput.stream[0], - ops, - embed.embedId - ); - if (!playableStream) throw new NotFoundError("No streams found"); + const playableStream = await validatePlayableStream(embedOutput.stream[0], ops, embed.embedId); + if (!playableStream) throw new NotFoundError('No streams found'); // opensubtitles playableStream.captions = await addOpenSubtitlesCaptions( @@ -194,18 +173,16 @@ export async function runAllProviders( ops, btoa( `${ops.media.imdbId}${ - ops.media.type === "show" - ? `.${ops.media.season.number}.${ops.media.episode.number}` - : "" - }` - ) + ops.media.type === 'show' ? `.${ops.media.season.number}.${ops.media.episode.number}` : '' + }`, + ), ); embedOutput.stream = [playableStream]; } catch (error) { const updateParams: UpdateEvent = { id: source.id, percentage: 100, - status: error instanceof NotFoundError ? "notfound" : "failure", + status: error instanceof NotFoundError ? 'notfound' : 'failure', reason: error instanceof NotFoundError ? error.message : undefined, error: error instanceof NotFoundError ? undefined : error, }; diff --git a/src/utils/opensubtitles.ts b/src/utils/opensubtitles.ts index e380261..559536c 100644 --- a/src/utils/opensubtitles.ts +++ b/src/utils/opensubtitles.ts @@ -1,44 +1,35 @@ -import { - Caption, - labelToLanguageCode, - removeDuplicatedLanguages, -} from "@/providers/captions"; -import { IndividualEmbedRunnerOptions } from "@/runners/individualRunner"; -import { ProviderRunnerOptions } from "@/runners/runner"; +import { Caption, labelToLanguageCode, removeDuplicatedLanguages } from '@/providers/captions'; +import { IndividualEmbedRunnerOptions } from '@/runners/individualRunner'; +import { ProviderRunnerOptions } from '@/runners/runner'; export async function addOpenSubtitlesCaptions( captions: Caption[], ops: ProviderRunnerOptions | IndividualEmbedRunnerOptions, - media: string + media: string, ): Promise { try { const [imdbId, season, episode] = atob(media) - .split(".") + .split('.') .map((x, i) => (i === 0 ? x : Number(x) || null)); if (!imdbId) return captions; const Res: { LanguageName: string; SubDownloadLink: string; - SubFormat: "srt" | "vtt"; + SubFormat: 'srt' | 'vtt'; }[] = await ops.proxiedFetcher( `https://rest.opensubtitles.org/search/${ - season && episode ? `episode-${episode}/` : "" - }imdbid-${(imdbId as string).slice(2)}${ - season && episode ? `/season-${season}` : "" - }`, + season && episode ? `episode-${episode}/` : '' + }imdbid-${(imdbId as string).slice(2)}${season && episode ? `/season-${season}` : ''}`, { headers: { - "X-User-Agent": "VLSub 0.10.2", + 'X-User-Agent': 'VLSub 0.10.2', }, - } + }, ); const openSubtilesCaptions: Caption[] = []; for (const caption of Res) { - const url = caption.SubDownloadLink.replace(".gz", "").replace( - "download/", - "download/subencoding-utf8/" - ); + const url = caption.SubDownloadLink.replace('.gz', '').replace('download/', 'download/subencoding-utf8/'); const language = labelToLanguageCode(caption.LanguageName); if (!url || !language) continue; else @@ -46,7 +37,7 @@ export async function addOpenSubtitlesCaptions( id: url, opensubtitles: true, url, - type: caption.SubFormat || "srt", + type: caption.SubFormat || 'srt', hasCorsRestrictions: false, language, });