Add builder for adding custom sources

This commit is contained in:
mrjvs 2023-12-25 01:00:19 +01:00
parent b70d9aaaf7
commit 4a557b8140
46 changed files with 251 additions and 97 deletions

View File

@ -3,7 +3,7 @@ module.exports = {
browser: true,
},
extends: ['airbnb-base', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'],
ignorePatterns: ['lib/*', 'tests/*', '/*.js', '/*.ts', '/**/*.test.ts', 'test/*'],
ignorePatterns: ['lib/*', 'tests/*', '/*.js', '/*.ts', '/src/__test__/*', '/**/*.test.ts', 'test/*'],
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json',

View File

@ -1,5 +1,6 @@
import { mockEmbeds, mockSources } from '@/__test__/providerTests';
import { FeatureMap } from '@/main/targets';
import { getBuiltinEmbeds, getBuiltinSources } from '@/entrypoint/providers';
import { FeatureMap } from '@/entrypoint/utils/targets';
import { getProviders } from '@/providers/get';
import { vi, describe, it, expect, afterEach } from 'vitest';
@ -19,7 +20,10 @@ describe('getProviders()', () => {
it('should return providers', () => {
mocks.gatherAllEmbeds.mockReturnValue([mockEmbeds.embedD]);
mocks.gatherAllSources.mockReturnValue([mockSources.sourceA, mockSources.sourceB]);
expect(getProviders(features)).toEqual({
expect(getProviders(features, {
embeds: getBuiltinEmbeds(),
sources: getBuiltinSources(),
})).toEqual({
sources: [mockSources.sourceA, mockSources.sourceB],
embeds: [mockEmbeds.embedD],
});
@ -28,7 +32,10 @@ describe('getProviders()', () => {
it('should filter out disabled providers', () => {
mocks.gatherAllEmbeds.mockReturnValue([mockEmbeds.embedD, mockEmbeds.embedEDisabled]);
mocks.gatherAllSources.mockReturnValue([mockSources.sourceA, mockSources.sourceCDisabled, mockSources.sourceB]);
expect(getProviders(features)).toEqual({
expect(getProviders(features,{
embeds: getBuiltinEmbeds(),
sources: getBuiltinSources(),
})).toEqual({
sources: [mockSources.sourceA, mockSources.sourceB],
embeds: [mockEmbeds.embedD],
});
@ -37,31 +44,46 @@ describe('getProviders()', () => {
it('should throw on duplicate ids in sources', () => {
mocks.gatherAllEmbeds.mockReturnValue([]);
mocks.gatherAllSources.mockReturnValue([mockSources.sourceAHigherRank, mockSources.sourceA, mockSources.sourceB]);
expect(() => getProviders(features)).toThrowError();
expect(() => getProviders(features,{
embeds: getBuiltinEmbeds(),
sources: getBuiltinSources(),
})).toThrowError();
});
it('should throw on duplicate ids in embeds', () => {
mocks.gatherAllEmbeds.mockReturnValue([mockEmbeds.embedD, mockEmbeds.embedDHigherRank, mockEmbeds.embedA]);
mocks.gatherAllSources.mockReturnValue([]);
expect(() => getProviders(features)).toThrowError();
expect(() => getProviders(features,{
embeds: getBuiltinEmbeds(),
sources: getBuiltinSources(),
})).toThrowError();
});
it('should throw on duplicate ids between sources and embeds', () => {
mocks.gatherAllEmbeds.mockReturnValue([mockEmbeds.embedD, mockEmbeds.embedA]);
mocks.gatherAllSources.mockReturnValue([mockSources.sourceA, mockSources.sourceB]);
expect(() => getProviders(features)).toThrowError();
expect(() => getProviders(features,{
embeds: getBuiltinEmbeds(),
sources: getBuiltinSources(),
})).toThrowError();
});
it('should throw on duplicate rank between sources and embeds', () => {
mocks.gatherAllEmbeds.mockReturnValue([mockEmbeds.embedD, mockEmbeds.embedA]);
mocks.gatherAllSources.mockReturnValue([mockSources.sourceA, mockSources.sourceB]);
expect(() => getProviders(features)).toThrowError();
expect(() => getProviders(features,{
embeds: getBuiltinEmbeds(),
sources: getBuiltinSources(),
})).toThrowError();
});
it('should not throw with same rank between sources and embeds', () => {
mocks.gatherAllEmbeds.mockReturnValue([mockEmbeds.embedD, mockEmbeds.embedHSameRankAsSourceA]);
mocks.gatherAllSources.mockReturnValue([mockSources.sourceA, mockSources.sourceB]);
expect(getProviders(features)).toEqual({
expect(getProviders(features,{
embeds: getBuiltinEmbeds(),
sources: getBuiltinSources(),
})).toEqual({
sources: [mockSources.sourceA, mockSources.sourceB],
embeds: [mockEmbeds.embedD, mockEmbeds.embedHSameRankAsSourceA],
});

View File

@ -1,6 +1,6 @@
import { mockEmbeds, mockSources } from '@/__test__/providerTests';
import { makeProviders } from '@/main/builder';
import { targets } from '@/main/targets';
import { makeProviders } from '@/entrypoint/declare';
import { targets } from '@/entrypoint/utils/targets';
import { afterEach, describe, expect, it, vi } from 'vitest';
const mocks = await vi.hoisted(async () => (await import('../providerTests.ts')).makeProviderMocks());

View File

@ -1,6 +1,6 @@
import { mockEmbeds, mockSources } from '@/__test__/providerTests';
import { makeProviders } from '@/main/builder';
import { targets } from '@/main/targets';
import { makeProviders } from '@/entrypoint/declare';
import { targets } from '@/entrypoint/utils/targets';
import { afterEach, describe, expect, it, vi } from 'vitest';
const mocks = await vi.hoisted(async () => (await import('../providerTests.ts')).makeProviderMocks());

View File

@ -1,4 +1,4 @@
import { FeatureMap, Flags, flags, flagsAllowedInFeatures } from "@/main/targets";
import { FeatureMap, Flags, flags, flagsAllowedInFeatures } from "@/entrypoint/utils/targets";
import { describe, it, expect } from "vitest";
describe('flagsAllowedInFeatures()', () => {

93
src/entrypoint/builder.ts Normal file
View File

@ -0,0 +1,93 @@
import { ProviderControls, makeControls } from '@/entrypoint/controls';
import { getBuiltinEmbeds, getBuiltinSources } from '@/entrypoint/providers';
import { Targets, getTargetFeatures } from '@/entrypoint/utils/targets';
import { Fetcher } from '@/fetchers/types';
import { Embed, Sourcerer } from '@/providers/base';
import { getProviders } from '@/providers/get';
export type ProviderBuilder = {
setTarget(target: Targets): ProviderBuilder;
setFetcher(fetcher: Fetcher): ProviderBuilder;
setProxiedFetcher(fetcher: Fetcher): ProviderBuilder;
addSource(scraper: Sourcerer): ProviderBuilder;
addSource(name: string): ProviderBuilder;
addEmbed(scraper: Embed): ProviderBuilder;
addEmbed(name: string): ProviderBuilder;
addBuiltinProviders(): ProviderBuilder;
enableConsistentIpForRequests(): ProviderBuilder;
build(): ProviderControls;
};
export function buildProviders(): ProviderBuilder {
let consistentIpForRequests = false;
let target: Targets | null = null;
let fetcher: Fetcher | null = null;
let proxiedFetcher: Fetcher | null = null;
const embeds: Embed[] = [];
const sources: Sourcerer[] = [];
const builtinSources = getBuiltinSources();
const builtinEmbeds = getBuiltinEmbeds();
return {
enableConsistentIpForRequests() {
consistentIpForRequests = true;
return this;
},
setFetcher(f) {
fetcher = f;
return this;
},
setProxiedFetcher(f) {
proxiedFetcher = f;
return this;
},
setTarget(t) {
target = t;
return this;
},
addSource(input) {
if (typeof input !== 'string') {
sources.push(input);
return this;
}
const matchingSource = builtinSources.find((v) => v.id === input);
if (!matchingSource) throw new Error('Source not found');
sources.push(matchingSource);
return this;
},
addEmbed(input) {
if (typeof input !== 'string') {
embeds.push(input);
return this;
}
const matchingEmbed = builtinEmbeds.find((v) => v.id === input);
if (!matchingEmbed) throw new Error('Embed not found');
embeds.push(matchingEmbed);
return this;
},
addBuiltinProviders() {
sources.push(...builtinSources);
embeds.push(...builtinEmbeds);
return this;
},
build() {
if (!target) throw new Error('Target not set');
if (!fetcher) throw new Error('Fetcher not set');
const features = getTargetFeatures(target, consistentIpForRequests);
const list = getProviders(features, {
embeds,
sources,
});
return makeControls({
fetcher,
proxiedFetcher: proxiedFetcher ?? undefined,
embeds: list.embeds,
sources: list.sources,
features,
});
},
};
}

View File

@ -1,28 +1,19 @@
import { FullScraperEvents, IndividualScraperEvents } from '@/entrypoint/utils/events';
import { ScrapeMedia } from '@/entrypoint/utils/media';
import { MetaOutput, getAllEmbedMetaSorted, getAllSourceMetaSorted, getSpecificId } from '@/entrypoint/utils/meta';
import { FeatureMap } from '@/entrypoint/utils/targets';
import { makeFullFetcher } from '@/fetchers/common';
import { Fetcher } from '@/fetchers/types';
import { FullScraperEvents, IndividualScraperEvents } from '@/main/events';
import { scrapeIndividualEmbed, scrapeInvidualSource } from '@/main/individualRunner';
import { ScrapeMedia } from '@/main/media';
import { MetaOutput, getAllEmbedMetaSorted, getAllSourceMetaSorted, getSpecificId } from '@/main/meta';
import { RunOutput, runAllProviders } from '@/main/runner';
import { Targets, flags, getTargetFeatures } from '@/main/targets';
import { EmbedOutput, SourcererOutput } from '@/providers/base';
import { getProviders } from '@/providers/get';
import { Embed, EmbedOutput, Sourcerer, SourcererOutput } from '@/providers/base';
import { scrapeIndividualEmbed, scrapeInvidualSource } from '@/runners/individualRunner';
import { RunOutput, runAllProviders } from '@/runners/runner';
export interface ProviderBuilderOptions {
// fetcher, every web request gets called through here
export interface ProviderControlsInput {
fetcher: Fetcher;
// proxied fetcher, if the scraper needs to access a CORS proxy. this fetcher will be called instead
// of the normal fetcher. Defaults to the normal fetcher.
proxiedFetcher?: Fetcher;
// target of where the streams will be used
target: Targets;
// Set this to true, if the requests will have the same IP as
// the device that the stream will be played on
consistentIpForRequests?: boolean;
features: FeatureMap;
sources: Sourcerer[];
embeds: Embed[];
}
export interface RunnerOptions {
@ -84,12 +75,14 @@ export interface ProviderControls {
listEmbeds(): MetaOutput[];
}
export function makeProviders(ops: ProviderBuilderOptions): ProviderControls {
const features = getTargetFeatures(ops.target);
if (!ops.consistentIpForRequests) features.disallowed.push(flags.IP_LOCKED);
const list = getProviders(features);
export function makeControls(ops: ProviderControlsInput): ProviderControls {
const list = {
embeds: ops.embeds,
sources: ops.sources,
};
const providerRunnerOps = {
features,
features: ops.features,
fetcher: makeFullFetcher(ops.fetcher),
proxiedFetcher: makeFullFetcher(ops.proxiedFetcher ?? ops.fetcher),
};

37
src/entrypoint/declare.ts Normal file
View File

@ -0,0 +1,37 @@
import { makeControls } from '@/entrypoint/controls';
import { getBuiltinEmbeds, getBuiltinSources } from '@/entrypoint/providers';
import { Targets, getTargetFeatures } from '@/entrypoint/utils/targets';
import { Fetcher } from '@/fetchers/types';
import { getProviders } from '@/providers/get';
export interface ProviderMakerOptions {
// fetcher, every web request gets called through here
fetcher: Fetcher;
// proxied fetcher, if the scraper needs to access a CORS proxy. this fetcher will be called instead
// of the normal fetcher. Defaults to the normal fetcher.
proxiedFetcher?: Fetcher;
// target of where the streams will be used
target: Targets;
// Set this to true, if the requests will have the same IP as
// the device that the stream will be played on
consistentIpForRequests?: boolean;
}
export function makeProviders(ops: ProviderMakerOptions) {
const features = getTargetFeatures(ops.target, ops.consistentIpForRequests ?? false);
const list = getProviders(features, {
embeds: getBuiltinEmbeds(),
sources: getBuiltinSources(),
});
return makeControls({
embeds: list.embeds,
sources: list.sources,
features,
fetcher: ops.fetcher,
proxiedFetcher: ops.proxiedFetcher,
});
}

View File

@ -0,0 +1,10 @@
import { gatherAllEmbeds, gatherAllSources } from '@/providers/all';
import { Embed, Sourcerer } from '@/providers/base';
export function getBuiltinSources(): Sourcerer[] {
return gatherAllSources();
}
export function getBuiltinEmbeds(): Embed[] {
return gatherAllEmbeds();
}

View File

@ -1,4 +1,4 @@
import { MediaTypes } from '@/main/media';
import { MediaTypes } from '@/entrypoint/utils/media';
import { Embed, Sourcerer } from '@/providers/base';
import { ProviderList } from '@/providers/get';

View File

@ -49,8 +49,10 @@ export const targetToFeatures: Record<Targets, FeatureMap> = {
},
};
export function getTargetFeatures(target: Targets): FeatureMap {
return targetToFeatures[target];
export function getTargetFeatures(target: Targets, consistentIpForRequests: boolean): FeatureMap {
const features = targetToFeatures[target];
if (!consistentIpForRequests) features.disallowed.push(flags.IP_LOCKED);
return features;
}
export function flagsAllowedInFeatures(features: FeatureMap, inputFlags: Flags[]): boolean {

View File

@ -1,21 +1,19 @@
export type { EmbedOutput, SourcererOutput } from '@/providers/base';
export type { Stream, StreamFile, FileBasedStream, HlsBasedStream, Qualities } from '@/providers/streams';
export type { Fetcher, FetcherOptions } from '@/fetchers/types';
export type { RunOutput } from '@/main/runner';
export type { MetaOutput } from '@/main/meta';
export type { FullScraperEvents } from '@/main/events';
export type { Targets, Flags } from '@/main/targets';
export type { MediaTypes, ShowMedia, ScrapeMedia, MovieMedia } from '@/main/media';
export type {
ProviderBuilderOptions,
ProviderControls,
RunnerOptions,
EmbedRunnerOptions,
SourceRunnerOptions,
} from '@/main/builder';
export type { RunOutput } from '@/runners/runner';
export type { MetaOutput } from '@/entrypoint/utils/meta';
export type { FullScraperEvents } from '@/entrypoint/utils/events';
export type { Targets, Flags } from '@/entrypoint/utils/targets';
export type { MediaTypes, ShowMedia, ScrapeMedia, MovieMedia } from '@/entrypoint/utils/media';
export type { ProviderControls, RunnerOptions, EmbedRunnerOptions, SourceRunnerOptions } from '@/entrypoint/controls';
export type { ProviderBuilder } from '@/entrypoint/builder';
export type { ProviderMakerOptions } from '@/entrypoint/declare';
export { NotFoundError } from '@/utils/errors';
export { makeProviders } from '@/main/builder';
export { makeProviders } from '@/entrypoint/declare';
export { buildProviders } from '@/entrypoint/builder';
export { getBuiltinEmbeds, getBuiltinSources } from '@/entrypoint/providers';
export { makeStandardFetcher } from '@/fetchers/standardFetch';
export { makeSimpleProxyFetcher } from '@/fetchers/simpleProxy';
export { flags, targets } from '@/main/targets';
export { flags, targets } from '@/entrypoint/utils/targets';

View File

@ -1,4 +1,4 @@
import { Flags } from '@/main/targets';
import { Flags } from '@/entrypoint/utils/targets';
import { Stream } from '@/providers/streams';
import { EmbedScrapeContext, MovieScrapeContext, ShowScrapeContext } from '@/utils/context';

View File

@ -1,4 +1,4 @@
import { MediaTypes } from '@/main/media';
import { MediaTypes } from '@/entrypoint/utils/media';
export const febBoxBase = `https://www.febbox.com`;

View File

@ -1,4 +1,4 @@
import { MediaTypes } from '@/main/media';
import { MediaTypes } from '@/entrypoint/utils/media';
import { FebboxFileList, febBoxBase } from '@/providers/embeds/febbox/common';
import { EmbedScrapeContext } from '@/utils/context';

View File

@ -1,5 +1,5 @@
import { MediaTypes } from '@/main/media';
import { flags } from '@/main/targets';
import { MediaTypes } from '@/entrypoint/utils/media';
import { flags } from '@/entrypoint/utils/targets';
import { makeEmbed } from '@/providers/base';
import { parseInputUrl } from '@/providers/embeds/febbox/common';
import { getStreams } from '@/providers/embeds/febbox/fileList';

View File

@ -1,4 +1,4 @@
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { makeEmbed } from '@/providers/base';
import { parseInputUrl } from '@/providers/embeds/febbox/common';
import { getStreamQualities } from '@/providers/embeds/febbox/qualities';

View File

@ -1,4 +1,4 @@
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { makeEmbed } from '@/providers/base';
export const mp4uploadScraper = makeEmbed({

View File

@ -1,6 +1,6 @@
import { load } from 'cheerio';
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { makeEmbed } from '@/providers/base';
type DPlayerSourcesResponse = {

View File

@ -1,4 +1,4 @@
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { makeEmbed } from '@/providers/base';
import { Caption, getCaptionTypeFromUrl, labelToLanguageCode } from '@/providers/captions';

View File

@ -3,7 +3,7 @@ import Base64 from 'crypto-js/enc-base64';
import Utf8 from 'crypto-js/enc-utf8';
import FormData from 'form-data';
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { makeEmbed } from '@/providers/base';
import { StreamFile } from '@/providers/streams';
import { EmbedScrapeContext } from '@/utils/context';

View File

@ -1,6 +1,6 @@
import crypto from 'crypto-js';
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { makeEmbed } from '@/providers/base';
import { Caption, getCaptionTypeFromUrl, labelToLanguageCode } from '@/providers/captions';

View File

@ -1,6 +1,6 @@
import * as unpacker from 'unpacker';
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { makeEmbed } from '@/providers/base';
const packedRegex = /(eval\(function\(p,a,c,k,e,d\).*\)\)\))/;

View File

@ -1,5 +1,4 @@
import { FeatureMap, flagsAllowedInFeatures } from '@/main/targets';
import { gatherAllEmbeds, gatherAllSources } from '@/providers/all';
import { FeatureMap, flagsAllowedInFeatures } from '@/entrypoint/utils/targets';
import { Embed, Sourcerer } from '@/providers/base';
import { hasDuplicates } from '@/utils/predicates';
@ -8,9 +7,9 @@ export interface ProviderList {
embeds: Embed[];
}
export function getProviders(features: FeatureMap): ProviderList {
const sources = gatherAllSources().filter((v) => !v?.disabled);
const embeds = gatherAllEmbeds().filter((v) => !v?.disabled);
export function getProviders(features: FeatureMap, list: ProviderList): ProviderList {
const sources = list.sources.filter((v) => !v?.disabled);
const embeds = list.embeds.filter((v) => !v?.disabled);
const combined = [...sources, ...embeds];
const anyDuplicateId = hasDuplicates(combined.map((v) => v.id));

View File

@ -1,4 +1,4 @@
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { makeSourcerer } from '@/providers/base';
import { upcloudScraper } from '@/providers/embeds/upcloud';
import { getFlixhqMovieSources, getFlixhqShowSources, getFlixhqSourceDetails } from '@/providers/sources/flixhq/scrape';

View File

@ -1,6 +1,6 @@
import { load } from 'cheerio';
import { MovieMedia, ShowMedia } from '@/main/media';
import { MovieMedia, ShowMedia } from '@/entrypoint/utils/media';
import { flixHqBase } from '@/providers/sources/flixhq/common';
import { ScrapeContext } from '@/utils/context';
import { NotFoundError } from '@/utils/errors';

View File

@ -1,6 +1,6 @@
import { load } from 'cheerio';
import { MovieMedia, ShowMedia } from '@/main/media';
import { MovieMedia, ShowMedia } from '@/entrypoint/utils/media';
import { flixHqBase } from '@/providers/sources/flixhq/common';
import { compareMedia, compareTitle } from '@/utils/compare';
import { ScrapeContext } from '@/utils/context';

View File

@ -1,6 +1,6 @@
import { load } from 'cheerio';
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { makeSourcerer } from '@/providers/base';
import { upcloudScraper } from '@/providers/embeds/upcloud';
import { NotFoundError } from '@/utils/errors';

View File

@ -1,6 +1,6 @@
import { load } from 'cheerio';
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { makeSourcerer } from '@/providers/base';
import { NotFoundError } from '@/utils/errors';

View File

@ -1,4 +1,4 @@
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { SourcererOutput, makeSourcerer } from '@/providers/base';
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
import { NotFoundError } from '@/utils/errors';

View File

@ -1,4 +1,4 @@
import { MovieMedia } from '@/main/media';
import { MovieMedia } from '@/entrypoint/utils/media';
// ! Types
interface BaseConfig {

View File

@ -1,4 +1,4 @@
import { MovieMedia, ShowMedia } from '@/main/media';
import { MovieMedia, ShowMedia } from '@/entrypoint/utils/media';
import { compareMedia } from '@/utils/compare';
import { ScrapeContext } from '@/utils/context';
import { NotFoundError } from '@/utils/errors';

View File

@ -1,4 +1,4 @@
import { MovieMedia, ShowMedia } from '@/main/media';
import { MovieMedia, ShowMedia } from '@/entrypoint/utils/media';
import { ScrapeContext } from '@/utils/context';
import { StreamsDataResult } from './type';

View File

@ -1,4 +1,4 @@
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { makeSourcerer } from '@/providers/base';
import { NotFoundError } from '@/utils/errors';

View File

@ -1,4 +1,4 @@
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { SourcererOutput, makeSourcerer } from '@/providers/base';
import { febboxHlsScraper } from '@/providers/embeds/febbox/hls';
import { febboxMp4Scraper } from '@/providers/embeds/febbox/mp4';

View File

@ -1,6 +1,6 @@
import { load } from 'cheerio';
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { SourcererEmbed, SourcererOutput, makeSourcerer } from '@/providers/base';
import { smashyStreamDScraper } from '@/providers/embeds/smashystream/dued';
import { smashyStreamFScraper } from '@/providers/embeds/smashystream/video1';

View File

@ -1,4 +1,4 @@
import { flags } from '@/main/targets';
import { flags } from '@/entrypoint/utils/targets';
import { makeSourcerer } from '@/providers/base';
import { scrapeMovie } from '@/providers/sources/zoechip/scrape-movie';
import { scrapeShow } from '@/providers/sources/zoechip/scrape-show';

View File

@ -1,6 +1,6 @@
import { load } from 'cheerio';
import { ShowMedia } from '@/main/media';
import { ShowMedia } from '@/entrypoint/utils/media';
import { ZoeChipSourceDetails, zoeBase } from '@/providers/sources/zoechip/common';
import { MovieScrapeContext, ScrapeContext, ShowScrapeContext } from '@/utils/context';

View File

@ -1,6 +1,6 @@
import { load } from 'cheerio';
import { MovieMedia, ShowMedia } from '@/main/media';
import { MovieMedia, ShowMedia } from '@/entrypoint/utils/media';
import { zoeBase } from '@/providers/sources/zoechip/common';
import { compareMedia } from '@/utils/compare';
import { ScrapeContext } from '@/utils/context';

View File

@ -1,4 +1,4 @@
import { Flags } from '@/main/targets';
import { Flags } from '@/entrypoint/utils/targets';
import { Caption } from '@/providers/captions';
export type StreamFile = {

View File

@ -1,7 +1,7 @@
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 { IndividualScraperEvents } from '@/main/events';
import { ScrapeMedia } from '@/main/media';
import { FeatureMap, flagsAllowedInFeatures } from '@/main/targets';
import { EmbedOutput, SourcererOutput } from '@/providers/base';
import { ProviderList } from '@/providers/get';
import { ScrapeContext } from '@/utils/context';

View File

@ -1,7 +1,7 @@
import { FullScraperEvents } from '@/entrypoint/utils/events';
import { ScrapeMedia } from '@/entrypoint/utils/media';
import { FeatureMap, flagsAllowedInFeatures } from '@/entrypoint/utils/targets';
import { UseableFetcher } from '@/fetchers/types';
import { FullScraperEvents } from '@/main/events';
import { ScrapeMedia } from '@/main/media';
import { FeatureMap, flagsAllowedInFeatures } from '@/main/targets';
import { EmbedOutput, SourcererOutput } from '@/providers/base';
import { ProviderList } from '@/providers/get';
import { Stream } from '@/providers/streams';

View File

@ -1,4 +1,4 @@
import { CommonMedia } from '@/main/media';
import { CommonMedia } from '@/entrypoint/utils/media';
export function normalizeTitle(title: string): string {
return title

View File

@ -1,5 +1,5 @@
import { MovieMedia, ShowMedia } from '@/entrypoint/utils/media';
import { UseableFetcher } from '@/fetchers/types';
import { MovieMedia, ShowMedia } from '@/main/media';
export type ScrapeContext = {
proxiedFetcher: <T>(...params: Parameters<UseableFetcher<T>>) => ReturnType<UseableFetcher<T>>;