mirror of
https://github.com/movie-web/providers.git
synced 2025-09-13 13:33:25 +00:00
running sources/embeds + media input
This commit is contained in:
12
README.md
12
README.md
@@ -15,3 +15,15 @@ features:
|
|||||||
> TODO documentation: how to use + usecases
|
> TODO documentation: how to use + usecases
|
||||||
|
|
||||||
> TODO documentation: examples on how to make a custom fetcher
|
> TODO documentation: examples on how to make a custom fetcher
|
||||||
|
|
||||||
|
> TODO functionality: running individual scrapers
|
||||||
|
|
||||||
|
> TODO functionality: running all scrapers
|
||||||
|
|
||||||
|
> TODO functionality: choose environment (for browser, for native)
|
||||||
|
|
||||||
|
> TODO functionality: show which types are supported for scraper in meta
|
||||||
|
|
||||||
|
> TODO content: add all scrapers/providers
|
||||||
|
|
||||||
|
> TODO tests: add tests
|
||||||
|
19
docs/basic.js
Normal file
19
docs/basic.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
async function example() {
|
||||||
|
const providers = makeProviders({
|
||||||
|
fetcher: makeStandardFetcher(fetch),
|
||||||
|
});
|
||||||
|
|
||||||
|
const source = await providers.runAll({
|
||||||
|
media: {
|
||||||
|
title: 'Spider-Man: Across the Spider-Verse',
|
||||||
|
releaseYear: 2023,
|
||||||
|
imbdId: 'tt9362722',
|
||||||
|
tmdbId: '569094',
|
||||||
|
type: 'movie',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!source) throw new Error("Couldn't find a stream");
|
||||||
|
if (source.stream.type === 'file') return source.stream.qualities['1080']?.url;
|
||||||
|
if (source.stream.type === 'hls') return source.stream.playlist;
|
||||||
|
}
|
@@ -1 +1,2 @@
|
|||||||
|
export { makeStandardFetcher } from '@/fetchers/standardFetch';
|
||||||
export { ProviderBuilderOptions, ProviderControls, makeProviders } from '@/main/builder';
|
export { ProviderBuilderOptions, ProviderControls, makeProviders } from '@/main/builder';
|
||||||
|
@@ -1,12 +1,10 @@
|
|||||||
import { Fetcher } from '@/fetchers/types';
|
import { Fetcher } from '@/fetchers/types';
|
||||||
import { FullScraperEvents, SingleScraperEvents } from '@/main/events';
|
import { FullScraperEvents } from '@/main/events';
|
||||||
|
import { ScrapeMedia } from '@/main/media';
|
||||||
import { MetaOutput, getAllEmbedMetaSorted, getAllSourceMetaSorted, getSpecificId } from '@/main/meta';
|
import { MetaOutput, getAllEmbedMetaSorted, getAllSourceMetaSorted, getSpecificId } from '@/main/meta';
|
||||||
import { ProviderRunnerOptions, RunOutput, SourceRunOutput, runAllProviders } from '@/main/runner';
|
import { RunOutput, runAllProviders } from '@/main/runner';
|
||||||
import { getProviders } from '@/providers/all';
|
import { getProviders } from '@/providers/all';
|
||||||
|
|
||||||
// TODO meta data input (tmdb id, imdb id, title, release year)
|
|
||||||
// TODO actually running scrapers
|
|
||||||
|
|
||||||
export interface ProviderBuilderOptions {
|
export interface ProviderBuilderOptions {
|
||||||
// fetcher, every web request gets called through here
|
// fetcher, every web request gets called through here
|
||||||
fetcher: Fetcher;
|
fetcher: Fetcher;
|
||||||
@@ -16,13 +14,24 @@ export interface ProviderBuilderOptions {
|
|||||||
proxiedFetcher?: Fetcher;
|
proxiedFetcher?: Fetcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RunnerOptions {
|
||||||
|
// overwrite the order of sources to run. list of ids
|
||||||
|
sourceOrder?: string[];
|
||||||
|
|
||||||
|
// overwrite the order of embeds to run. list of ids
|
||||||
|
embedOrder?: string[];
|
||||||
|
|
||||||
|
// object of event functions
|
||||||
|
events?: FullScraperEvents;
|
||||||
|
|
||||||
|
// the media you want to see sources from
|
||||||
|
media: ScrapeMedia;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ProviderControls {
|
export interface ProviderControls {
|
||||||
// Run all providers one by one. in order of rank (highest first)
|
// Run all providers one by one. in order of rank (highest first)
|
||||||
// returns the stream, or null if none found
|
// returns the stream, or null if none found
|
||||||
runAll(cbs: FullScraperEvents): Promise<RunOutput | null>;
|
runAll(runnerOps: RunnerOptions): Promise<RunOutput | null>;
|
||||||
|
|
||||||
// Run a source provider
|
|
||||||
runSource(id: string, cbs: SingleScraperEvents): Promise<SourceRunOutput>;
|
|
||||||
|
|
||||||
// get meta data about a source or embed.
|
// get meta data about a source or embed.
|
||||||
getMetadata(id: string): MetaOutput | null;
|
getMetadata(id: string): MetaOutput | null;
|
||||||
@@ -36,14 +45,17 @@ export interface ProviderControls {
|
|||||||
|
|
||||||
export function makeProviders(ops: ProviderBuilderOptions): ProviderControls {
|
export function makeProviders(ops: ProviderBuilderOptions): ProviderControls {
|
||||||
const list = getProviders();
|
const list = getProviders();
|
||||||
const providerRunnerOps: ProviderRunnerOptions = {
|
const providerRunnerOps = {
|
||||||
fetcher: ops.fetcher,
|
fetcher: ops.fetcher,
|
||||||
proxiedFetcher: ops.proxiedFetcher ?? ops.fetcher,
|
proxiedFetcher: ops.proxiedFetcher ?? ops.fetcher,
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
runAll(cbs) {
|
runAll(runnerOps: RunnerOptions) {
|
||||||
return runAllProviders(providerRunnerOps, cbs);
|
return runAllProviders({
|
||||||
|
...providerRunnerOps,
|
||||||
|
...runnerOps,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
getMetadata(id) {
|
getMetadata(id) {
|
||||||
return getSpecificId(list, id);
|
return getSpecificId(list, id);
|
||||||
|
26
src/main/media.ts
Normal file
26
src/main/media.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
export type CommonMedia = {
|
||||||
|
title: string;
|
||||||
|
releaseYear: number;
|
||||||
|
imbdId: string;
|
||||||
|
tmdbId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MediaTypes = 'show' | 'movie';
|
||||||
|
|
||||||
|
export type ShowMedia = CommonMedia & {
|
||||||
|
type: 'show';
|
||||||
|
episode: {
|
||||||
|
number: number;
|
||||||
|
tmdbId: string;
|
||||||
|
};
|
||||||
|
season: {
|
||||||
|
number: number;
|
||||||
|
tmdbId: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MovieMedia = CommonMedia & {
|
||||||
|
type: 'movie';
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ScrapeMedia = ShowMedia | MovieMedia;
|
@@ -1,5 +1,6 @@
|
|||||||
import { Fetcher } from '@/fetchers/types';
|
import { Fetcher } from '@/fetchers/types';
|
||||||
import { FullScraperEvents } from '@/main/events';
|
import { FullScraperEvents } from '@/main/events';
|
||||||
|
import { ScrapeMedia } from '@/main/media';
|
||||||
import { Stream } from '@/providers/streams';
|
import { Stream } from '@/providers/streams';
|
||||||
|
|
||||||
export type RunOutput = {
|
export type RunOutput = {
|
||||||
@@ -22,9 +23,13 @@ export type EmbedRunOutput = {
|
|||||||
export type ProviderRunnerOptions = {
|
export type ProviderRunnerOptions = {
|
||||||
fetcher: Fetcher;
|
fetcher: Fetcher;
|
||||||
proxiedFetcher: Fetcher;
|
proxiedFetcher: Fetcher;
|
||||||
|
sourceOrder?: string[];
|
||||||
|
embedOrder?: string[];
|
||||||
|
events?: FullScraperEvents;
|
||||||
|
media: ScrapeMedia;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function runAllProviders(_ops: ProviderRunnerOptions, _cbs: FullScraperEvents): Promise<RunOutput | null> {
|
export async function runAllProviders(_ops: ProviderRunnerOptions): Promise<RunOutput | null> {
|
||||||
return {
|
return {
|
||||||
sourceId: '123',
|
sourceId: '123',
|
||||||
stream: {
|
stream: {
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import { MovieMedia, ShowMedia } from '@/main/media';
|
||||||
import { Stream } from '@/providers/streams';
|
import { Stream } from '@/providers/streams';
|
||||||
import { EmbedScrapeContext, ScrapeContext } from '@/utils/context';
|
import { EmbedScrapeContext, ScrapeContext } from '@/utils/context';
|
||||||
|
|
||||||
@@ -14,7 +15,8 @@ export type Sourcerer = {
|
|||||||
name: string; // displayed in the UI
|
name: string; // displayed in the UI
|
||||||
rank: number; // the higher the number, the earlier it gets put on the queue
|
rank: number; // the higher the number, the earlier it gets put on the queue
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
scrape: (input: ScrapeContext) => Promise<SourcererOutput>;
|
scrapeMovie?: (input: ScrapeContext & { media: MovieMedia }) => Promise<SourcererOutput>;
|
||||||
|
scrapeShow: (input: ScrapeContext & { media: ShowMedia }) => Promise<SourcererOutput>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function makeSourcerer(state: Sourcerer): Sourcerer | null {
|
export function makeSourcerer(state: Sourcerer): Sourcerer | null {
|
||||||
|
28
src/providers/sources/flixhq.ts
Normal file
28
src/providers/sources/flixhq.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { makeSourcerer } from '@/providers/base';
|
||||||
|
|
||||||
|
export const flixHq = makeSourcerer({
|
||||||
|
id: 'flixhq',
|
||||||
|
name: 'FlixHQ',
|
||||||
|
rank: 500,
|
||||||
|
|
||||||
|
async scrapeShow(_input) {
|
||||||
|
return {
|
||||||
|
embeds: [],
|
||||||
|
stream: {
|
||||||
|
type: 'file',
|
||||||
|
qualities: {
|
||||||
|
'360': {
|
||||||
|
type: 'mp4',
|
||||||
|
url: 'blabal.mp4',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
async scrapeMovie(_input) {
|
||||||
|
return {
|
||||||
|
embeds: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
Reference in New Issue
Block a user