chore: rename handler to source
This commit is contained in:
parent
013fb4084f
commit
b4b8581383
45 changed files with 108 additions and 108 deletions
|
|
@ -1,18 +1,18 @@
|
|||
import { Request, Response, Router } from 'express';
|
||||
import { landingTemplate } from '../landingTemplate';
|
||||
import { buildManifest, getDefaultConfig } from '../utils';
|
||||
import { Handler } from '../handler';
|
||||
import { Source } from '../source';
|
||||
import { Config } from '../types';
|
||||
|
||||
export class ConfigureController {
|
||||
public readonly router: Router;
|
||||
|
||||
private readonly handlers: Handler[];
|
||||
private readonly sources: Source[];
|
||||
|
||||
constructor(handlers: Handler[]) {
|
||||
constructor(sources: Source[]) {
|
||||
this.router = Router();
|
||||
|
||||
this.handlers = handlers;
|
||||
this.sources = sources;
|
||||
|
||||
this.router.get('/configure', this.getConfigure.bind(this));
|
||||
this.router.get('/:config/configure', this.getConfigure.bind(this));
|
||||
|
|
@ -21,7 +21,7 @@ export class ConfigureController {
|
|||
private readonly getConfigure = (req: Request, res: Response) => {
|
||||
const config: Config = JSON.parse(req.params['config'] || JSON.stringify(getDefaultConfig()));
|
||||
|
||||
const manifest = buildManifest(this.handlers, config);
|
||||
const manifest = buildManifest(this.sources, config);
|
||||
|
||||
res.setHeader('content-type', 'text/html');
|
||||
res.send(landingTemplate(manifest));
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
import { Request, Response, Router } from 'express';
|
||||
import { buildManifest, getDefaultConfig } from '../utils';
|
||||
import { Handler } from '../handler';
|
||||
import { Source } from '../source';
|
||||
import { Config } from '../types';
|
||||
|
||||
export class ManifestController {
|
||||
public readonly router: Router;
|
||||
|
||||
private readonly handlers: Handler[];
|
||||
private readonly sources: Source[];
|
||||
|
||||
constructor(handlers: Handler[]) {
|
||||
constructor(sources: Source[]) {
|
||||
this.router = Router();
|
||||
|
||||
this.handlers = handlers;
|
||||
this.sources = sources;
|
||||
|
||||
this.router.get('/manifest.json', this.getManifest.bind(this));
|
||||
this.router.get('/:config/manifest.json', this.getManifest.bind(this));
|
||||
|
|
@ -20,7 +20,7 @@ export class ManifestController {
|
|||
private readonly getManifest = (req: Request, res: Response) => {
|
||||
const config: Config = JSON.parse(req.params['config'] || JSON.stringify(getDefaultConfig()));
|
||||
|
||||
const manifest = buildManifest(this.handlers, config);
|
||||
const manifest = buildManifest(this.sources, config);
|
||||
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.send(manifest);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Request, Response, Router } from 'express';
|
||||
import winston from 'winston';
|
||||
import { Handler } from '../handler';
|
||||
import { Source } from '../source';
|
||||
import { Config, Context } from '../types';
|
||||
import { envIsProd, getDefaultConfig, ImdbId, StreamResolver } from '../utils';
|
||||
import { ContentType } from 'stremio-addon-sdk';
|
||||
|
|
@ -9,14 +9,14 @@ export class StreamController {
|
|||
public readonly router: Router;
|
||||
|
||||
private readonly logger: winston.Logger;
|
||||
private readonly handlers: Handler[];
|
||||
private readonly sources: Source[];
|
||||
private readonly streamResolver: StreamResolver;
|
||||
|
||||
constructor(logger: winston.Logger, handlers: Handler[], streams: StreamResolver) {
|
||||
constructor(logger: winston.Logger, sources: Source[], streams: StreamResolver) {
|
||||
this.router = Router();
|
||||
|
||||
this.logger = logger;
|
||||
this.handlers = handlers;
|
||||
this.sources = sources;
|
||||
this.streamResolver = streams;
|
||||
|
||||
this.router.get('/:config/stream/:type/:id.json', this.getStream.bind(this));
|
||||
|
|
@ -35,9 +35,9 @@ export class StreamController {
|
|||
|
||||
this.logger.info(`Search stream for type "${type}" and id "${id}" for ip ${ctx.ip}`, ctx);
|
||||
|
||||
const handlers = this.handlers.filter(handler => handler.countryCodes.filter(countryCode => countryCode in ctx.config).length);
|
||||
const sources = this.sources.filter(handler => handler.countryCodes.filter(countryCode => countryCode in ctx.config).length);
|
||||
|
||||
const { streams, ttl } = await this.streamResolver.resolve(ctx, handlers, type, ImdbId.fromString(id));
|
||||
const { streams, ttl } = await this.streamResolver.resolve(ctx, sources, type, ImdbId.fromString(id));
|
||||
|
||||
if (ttl && envIsProd()) {
|
||||
res.setHeader('Cache-Control', `max-age=${ttl / 1000}, public`);
|
||||
|
|
|
|||
14
src/index.ts
14
src/index.ts
|
|
@ -1,7 +1,7 @@
|
|||
import express, { NextFunction, Request, Response } from 'express';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import winston from 'winston';
|
||||
import { CineHDPlus, Frembed, FrenchCloud, Handler, KinoGer, MeineCloud, MostraGuarda, Soaper, StreamKiste, VerHdLink, VidSrc } from './handler';
|
||||
import { CineHDPlus, Frembed, FrenchCloud, Source, KinoGer, MeineCloud, MostraGuarda, Soaper, StreamKiste, VerHdLink, VidSrc } from './source';
|
||||
import { createExtractors, ExtractorRegistry } from './extractor';
|
||||
import { ConfigureController, ManifestController, StreamController } from './controller';
|
||||
import { envGet, envIsProd, Fetcher, StreamResolver, tmdbFetch, TmdbId } from './utils';
|
||||
|
|
@ -19,7 +19,7 @@ const logger = winston.createLogger({
|
|||
|
||||
const fetcher = new Fetcher(logger);
|
||||
|
||||
const handlers: Handler[] = [
|
||||
const sources: Source[] = [
|
||||
// EN
|
||||
new Soaper(fetcher),
|
||||
new VidSrc(fetcher),
|
||||
|
|
@ -54,12 +54,12 @@ addon.use((_req: Request, res: Response, next: NextFunction) => {
|
|||
next();
|
||||
});
|
||||
|
||||
addon.use('/', (new ConfigureController(handlers)).router);
|
||||
addon.use('/', (new ManifestController(handlers)).router);
|
||||
addon.use('/', (new ConfigureController(sources)).router);
|
||||
addon.use('/', (new ManifestController(sources)).router);
|
||||
|
||||
const extractorRegistry = new ExtractorRegistry(logger, createExtractors(fetcher));
|
||||
const streamResolver = new StreamResolver(logger, extractorRegistry);
|
||||
addon.use('/', (new StreamController(logger, handlers, streamResolver)).router);
|
||||
addon.use('/', (new StreamController(logger, sources, streamResolver)).router);
|
||||
|
||||
addon.get('/', (_req: Request, res: Response) => {
|
||||
res.redirect('/configure');
|
||||
|
|
@ -86,7 +86,7 @@ const cacheWarmup = async () => {
|
|||
}
|
||||
});
|
||||
for (const id of movieIds) {
|
||||
await streamResolver.resolve(ctx, handlers, 'movie', new TmdbId(id, undefined, undefined));
|
||||
await streamResolver.resolve(ctx, sources, 'movie', new TmdbId(id, undefined, undefined));
|
||||
}
|
||||
logger.info(`warmed up cache with ${movieIds.length} movies`, ctx);
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ const cacheWarmup = async () => {
|
|||
}
|
||||
});
|
||||
for (const id of tvShowIds) {
|
||||
await streamResolver.resolve(ctx, handlers, 'series', new TmdbId(id, 1, 1));
|
||||
await streamResolver.resolve(ctx, sources, 'series', new TmdbId(id, 1, 1));
|
||||
}
|
||||
logger.info(`warmed up cache with ${tvShowIds.length} tv shows`, ctx);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { ContentType } from 'stremio-addon-sdk';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { Handler, HandleResult } from './types';
|
||||
import { Source, SourceResult } from './types';
|
||||
import { Fetcher, getImdbId, Id, ImdbId } from '../utils';
|
||||
import { Context, CountryCode } from '../types';
|
||||
|
||||
export class CineHDPlus implements Handler {
|
||||
export class CineHDPlus implements Source {
|
||||
readonly id = 'cinehdplus';
|
||||
|
||||
readonly label = 'CineHDPlus';
|
||||
|
|
@ -19,7 +19,7 @@ export class CineHDPlus implements Handler {
|
|||
this.fetcher = fetcher;
|
||||
}
|
||||
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<HandleResult[]> => {
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<SourceResult[]> => {
|
||||
const imdbId = await getImdbId(ctx, this.fetcher, id);
|
||||
|
||||
const seriesPageUrl = await this.fetchSeriesPageUrl(ctx, imdbId);
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { ContentType } from 'stremio-addon-sdk';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { Handler, HandleResult } from './types';
|
||||
import { Source, SourceResult } from './types';
|
||||
import { Fetcher, getImdbId, Id, ImdbId } from '../utils';
|
||||
import { Context, CountryCode } from '../types';
|
||||
|
||||
export class Eurostreaming implements Handler {
|
||||
export class Eurostreaming implements Source {
|
||||
readonly id = 'eurostreaming';
|
||||
|
||||
readonly label = 'Eurostreaming';
|
||||
|
|
@ -19,7 +19,7 @@ export class Eurostreaming implements Handler {
|
|||
this.fetcher = fetcher;
|
||||
}
|
||||
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<HandleResult[]> => {
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<SourceResult[]> => {
|
||||
const imdbId = await getImdbId(ctx, this.fetcher, id);
|
||||
|
||||
const seriesPageUrl = await this.fetchSeriesPageUrl(ctx, imdbId);
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import { ContentType } from 'stremio-addon-sdk';
|
||||
import { Handler, HandleResult } from './types';
|
||||
import { Source, SourceResult } from './types';
|
||||
import { Fetcher, getTmdbId, Id } from '../utils';
|
||||
import { Context, CountryCode } from '../types';
|
||||
|
||||
export class Frembed implements Handler {
|
||||
export class Frembed implements Source {
|
||||
readonly id = 'frembed';
|
||||
|
||||
readonly label = 'Frembed';
|
||||
|
|
@ -18,7 +18,7 @@ export class Frembed implements Handler {
|
|||
this.fetcher = fetcher;
|
||||
}
|
||||
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<HandleResult[]> => {
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<SourceResult[]> => {
|
||||
const tmdbId = await getTmdbId(ctx, this.fetcher, id);
|
||||
|
||||
const apiUrl = new URL(`https://frembed.space/api/series?id=${tmdbId.id}&sa=${tmdbId.season}&epi=${tmdbId.episode}&idType=tmdb`);
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { ContentType } from 'stremio-addon-sdk';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { Handler, HandleResult } from './types';
|
||||
import { Source, SourceResult } from './types';
|
||||
import { Fetcher, getImdbId, Id } from '../utils';
|
||||
import { Context, CountryCode } from '../types';
|
||||
|
||||
export class FrenchCloud implements Handler {
|
||||
export class FrenchCloud implements Source {
|
||||
readonly id = 'frenchcloud';
|
||||
|
||||
readonly label = 'FrenchCloud';
|
||||
|
|
@ -19,7 +19,7 @@ export class FrenchCloud implements Handler {
|
|||
this.fetcher = fetcher;
|
||||
}
|
||||
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<HandleResult[]> => {
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<SourceResult[]> => {
|
||||
const imdbId = await getImdbId(ctx, this.fetcher, id);
|
||||
|
||||
const pageUrl = new URL(`https://frenchcloud.cam/movie/${imdbId.id}`);
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { ContentType } from 'stremio-addon-sdk';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { Handler, HandleResult } from './types';
|
||||
import { Source, SourceResult } from './types';
|
||||
import { Fetcher, getTmdbId, getTmdbMovieDetails, getTmdbTvDetails, Id, TmdbId } from '../utils';
|
||||
import { Context, CountryCode } from '../types';
|
||||
|
||||
export class KinoGer implements Handler {
|
||||
export class KinoGer implements Source {
|
||||
readonly id = 'kinoger';
|
||||
|
||||
readonly label = 'KinoGer';
|
||||
|
|
@ -21,7 +21,7 @@ export class KinoGer implements Handler {
|
|||
this.fetcher = fetcher;
|
||||
}
|
||||
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<HandleResult[]> => {
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<SourceResult[]> => {
|
||||
const tmdbId = await getTmdbId(ctx, this.fetcher, id);
|
||||
|
||||
const [keyword, year] = await this.getKeywordAndYear(ctx, tmdbId);
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { ContentType } from 'stremio-addon-sdk';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { Handler, HandleResult } from './types';
|
||||
import { Source, SourceResult } from './types';
|
||||
import { Fetcher, getImdbId, Id } from '../utils';
|
||||
import { Context, CountryCode } from '../types';
|
||||
|
||||
export class MeineCloud implements Handler {
|
||||
export class MeineCloud implements Source {
|
||||
readonly id = 'meinecloud';
|
||||
|
||||
readonly label = 'MeineCloud';
|
||||
|
|
@ -19,7 +19,7 @@ export class MeineCloud implements Handler {
|
|||
this.fetcher = fetcher;
|
||||
}
|
||||
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<HandleResult[]> => {
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<SourceResult[]> => {
|
||||
const imdbId = await getImdbId(ctx, this.fetcher, id);
|
||||
|
||||
const pageUrl = new URL(`https://meinecloud.click/movie/${imdbId.id}`);
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { ContentType } from 'stremio-addon-sdk';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { Handler, HandleResult } from './types';
|
||||
import { Source, SourceResult } from './types';
|
||||
import { Fetcher, getImdbId, Id } from '../utils';
|
||||
import { Context, CountryCode } from '../types';
|
||||
|
||||
export class MostraGuarda implements Handler {
|
||||
export class MostraGuarda implements Source {
|
||||
readonly id = 'mostraguarda';
|
||||
|
||||
readonly label = 'MostraGuarda';
|
||||
|
|
@ -19,7 +19,7 @@ export class MostraGuarda implements Handler {
|
|||
this.fetcher = fetcher;
|
||||
}
|
||||
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<HandleResult[]> => {
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<SourceResult[]> => {
|
||||
const imdbId = await getImdbId(ctx, this.fetcher, id);
|
||||
|
||||
const pageUrl = new URL(`https://mostraguarda.stream/movie/${imdbId.id}`);
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { ContentType } from 'stremio-addon-sdk';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { Handler, HandleResult } from './types';
|
||||
import { Source, SourceResult } from './types';
|
||||
import { Fetcher, getTmdbId, getTmdbMovieDetails, getTmdbTvDetails, Id, TmdbId } from '../utils';
|
||||
import { Context, CountryCode } from '../types';
|
||||
|
||||
export class Soaper implements Handler {
|
||||
export class Soaper implements Source {
|
||||
readonly id = 'soaper';
|
||||
|
||||
readonly label = 'Soaper';
|
||||
|
|
@ -21,7 +21,7 @@ export class Soaper implements Handler {
|
|||
this.fetcher = fetcher;
|
||||
}
|
||||
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<HandleResult[]> => {
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<SourceResult[]> => {
|
||||
const tmdbId = await getTmdbId(ctx, this.fetcher, id);
|
||||
|
||||
const [keyword, year, hrefPrefix] = await this.getKeywordYearAndHrefPrefix(ctx, tmdbId);
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { ContentType } from 'stremio-addon-sdk';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { Handler, HandleResult } from './types';
|
||||
import { Source, SourceResult } from './types';
|
||||
import { ImdbId, Fetcher, getImdbId, Id } from '../utils';
|
||||
import { Context, CountryCode } from '../types';
|
||||
|
||||
export class StreamKiste implements Handler {
|
||||
export class StreamKiste implements Source {
|
||||
readonly id = 'streamkiste';
|
||||
|
||||
readonly label = 'StreamKiste';
|
||||
|
|
@ -19,7 +19,7 @@ export class StreamKiste implements Handler {
|
|||
this.fetcher = fetcher;
|
||||
}
|
||||
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<HandleResult[]> => {
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<SourceResult[]> => {
|
||||
const imdbId = await getImdbId(ctx, this.fetcher, id);
|
||||
|
||||
const seriesPageUrl = await this.fetchSeriesPageUrl(ctx, imdbId);
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { ContentType } from 'stremio-addon-sdk';
|
||||
import * as cheerio from 'cheerio';
|
||||
import { Handler, HandleResult } from './types';
|
||||
import { Source, SourceResult } from './types';
|
||||
import { Fetcher, getImdbId, Id } from '../utils';
|
||||
import { Context, CountryCode } from '../types';
|
||||
|
||||
export class VerHdLink implements Handler {
|
||||
export class VerHdLink implements Source {
|
||||
readonly id = 'verhdlink';
|
||||
|
||||
readonly label = 'VerHdLink';
|
||||
|
|
@ -19,7 +19,7 @@ export class VerHdLink implements Handler {
|
|||
this.fetcher = fetcher;
|
||||
}
|
||||
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<HandleResult[]> => {
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<SourceResult[]> => {
|
||||
const imdbId = await getImdbId(ctx, this.fetcher, id);
|
||||
|
||||
const pageUrl = new URL(`https://verhdlink.cam/movie/${imdbId.id}`);
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import { ContentType } from 'stremio-addon-sdk';
|
||||
import { Handler, HandleResult } from './types';
|
||||
import { Source, SourceResult } from './types';
|
||||
import { Fetcher, getImdbId, Id } from '../utils';
|
||||
import { Context, CountryCode } from '../types';
|
||||
|
||||
export class VidSrc implements Handler {
|
||||
export class VidSrc implements Source {
|
||||
readonly id = 'vidsrc';
|
||||
|
||||
readonly label = 'VidSrc';
|
||||
|
|
@ -20,7 +20,7 @@ export class VidSrc implements Handler {
|
|||
this.fetcher = fetcher;
|
||||
}
|
||||
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<HandleResult[]> => {
|
||||
readonly handle = async (ctx: Context, _type: string, id: Id): Promise<SourceResult[]> => {
|
||||
const imdbId = await getImdbId(ctx, this.fetcher, id);
|
||||
|
||||
const url = imdbId.season
|
||||
|
|
@ -2,14 +2,14 @@ import { ContentType } from 'stremio-addon-sdk';
|
|||
import { Context, CountryCode } from '../types';
|
||||
import { Id } from '../utils';
|
||||
|
||||
export interface HandleResult {
|
||||
export interface SourceResult {
|
||||
countryCode: CountryCode;
|
||||
referer?: URL;
|
||||
title?: string;
|
||||
url: URL;
|
||||
}
|
||||
|
||||
export interface Handler {
|
||||
export interface Source {
|
||||
readonly id: string;
|
||||
|
||||
readonly label: string;
|
||||
|
|
@ -18,5 +18,5 @@ export interface Handler {
|
|||
|
||||
readonly countryCodes: CountryCode[];
|
||||
|
||||
readonly handle: (ctx: Context, type: ContentType, id: Id) => Promise<(HandleResult[])>;
|
||||
readonly handle: (ctx: Context, type: ContentType, id: Id) => Promise<(SourceResult[])>;
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ import { ContentType } from 'stremio-addon-sdk';
|
|||
import winston from 'winston';
|
||||
import { createExtractors, Extractor, ExtractorRegistry } from '../extractor';
|
||||
import { StreamResolver } from './StreamResolver';
|
||||
import { Handler, HandleResult, MeineCloud, MostraGuarda } from '../handler';
|
||||
import { Source, SourceResult, MeineCloud, MostraGuarda } from '../source';
|
||||
import { Fetcher } from './Fetcher';
|
||||
import { BlockedReason, Context, CountryCode, TIMEOUT, UrlResult } from '../types';
|
||||
import { BlockedError, HttpError, NotFoundError, QueueIsFullError } from '../error';
|
||||
|
|
@ -19,7 +19,7 @@ const meineCloud = new MeineCloud(fetcher);
|
|||
const mostraGuarda = new MostraGuarda(fetcher);
|
||||
|
||||
describe('resolve', () => {
|
||||
test('returns info as stream if no handlers were configured', async () => {
|
||||
test('returns info as stream if no sources were configured', async () => {
|
||||
const streamResolver = new StreamResolver(logger, new ExtractorRegistry(logger, createExtractors(fetcher)));
|
||||
|
||||
const streams = await streamResolver.resolve(ctx, [], 'movie', new ImdbId('tt123456789', undefined, undefined));
|
||||
|
|
@ -27,7 +27,7 @@ describe('resolve', () => {
|
|||
expect(streams).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('returns handler errors as stream', async () => {
|
||||
test('returns source errors as stream', async () => {
|
||||
const fetcherSpy = jest.spyOn(fetcher, 'text').mockRejectedValue('ups, an error occurred.');
|
||||
const streamResolver = new StreamResolver(logger, new ExtractorRegistry(logger, createExtractors(fetcher)));
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ describe('resolve', () => {
|
|||
fetcherSpy.mockRestore();
|
||||
});
|
||||
|
||||
test('returns empty array if no handler found anything', async () => {
|
||||
test('returns empty array if no source found anything', async () => {
|
||||
const streamResolver = new StreamResolver(logger, new ExtractorRegistry(logger, createExtractors(fetcher)));
|
||||
|
||||
const streams = await streamResolver.resolve(ctx, [meineCloud, mostraGuarda], 'movie', new ImdbId('tt12345678', undefined, undefined));
|
||||
|
|
@ -46,7 +46,7 @@ describe('resolve', () => {
|
|||
expect(streams).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('returns empty array if no handler supported the type', async () => {
|
||||
test('returns empty array if no source supported the type', async () => {
|
||||
const streamResolver = new StreamResolver(logger, new ExtractorRegistry(logger, createExtractors(fetcher)));
|
||||
|
||||
const streams = await streamResolver.resolve(ctx, [meineCloud, mostraGuarda], 'series', new ImdbId('tt12345678', 1, 1));
|
||||
|
|
@ -63,7 +63,7 @@ describe('resolve', () => {
|
|||
});
|
||||
|
||||
test('adds error info', async () => {
|
||||
class MockHandler implements Handler {
|
||||
class MockHandler implements Source {
|
||||
readonly id = 'mockhandler';
|
||||
|
||||
readonly label = 'MockHandler';
|
||||
|
|
@ -72,7 +72,7 @@ describe('resolve', () => {
|
|||
|
||||
readonly countryCodes: CountryCode[] = [CountryCode.de];
|
||||
|
||||
readonly handle = async (): Promise<HandleResult[]> => {
|
||||
readonly handle = async (): Promise<SourceResult[]> => {
|
||||
return [{ countryCode: CountryCode.de, url: new URL('https://example.com') }];
|
||||
};
|
||||
}
|
||||
|
|
@ -163,7 +163,7 @@ describe('resolve', () => {
|
|||
});
|
||||
|
||||
test('ignores not found errors', async () => {
|
||||
const mockHandler: Handler = {
|
||||
const mockHandler: Source = {
|
||||
id: 'mockhandler',
|
||||
label: 'MockHandler',
|
||||
contentTypes: ['movie'],
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { ContentType, Stream } from 'stremio-addon-sdk';
|
|||
import winston from 'winston';
|
||||
import bytes from 'bytes';
|
||||
import { Context, TIMEOUT, UrlResult } from '../types';
|
||||
import { Handler } from '../handler';
|
||||
import { Source } from '../source';
|
||||
import { BlockedError, HttpError, NotFoundError, QueueIsFullError } from '../error';
|
||||
import { flagFromCountryCode, languageFromCountryCode } from './language';
|
||||
import { envGetAppName } from './env';
|
||||
|
|
@ -23,13 +23,13 @@ export class StreamResolver {
|
|||
this.extractorRegistry = extractorRegistry;
|
||||
}
|
||||
|
||||
readonly resolve = async (ctx: Context, handlers: Handler[], type: ContentType, id: Id): Promise<ResolveResponse> => {
|
||||
if (handlers.length === 0) {
|
||||
readonly resolve = async (ctx: Context, sources: Source[], type: ContentType, id: Id): Promise<ResolveResponse> => {
|
||||
if (sources.length === 0) {
|
||||
return {
|
||||
streams: [
|
||||
{
|
||||
name: 'WebStreamr',
|
||||
title: '⚠️ No handlers found. Please re-configure the plugin.',
|
||||
title: '⚠️ No sources found. Please re-configure the plugin.',
|
||||
ytId: 'E4WlUXrJgy4',
|
||||
},
|
||||
],
|
||||
|
|
@ -40,7 +40,7 @@ export class StreamResolver {
|
|||
|
||||
let handlerErrorOccurred = false;
|
||||
const urlResults: UrlResult[] = [];
|
||||
const handlerPromises = handlers.map(async (handler) => {
|
||||
const handlerPromises = sources.map(async (handler) => {
|
||||
if (!handler.contentTypes.includes(type)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`resolve adds error info 1`] = `
|
||||
{
|
||||
|
|
@ -117,39 +117,26 @@ exports[`resolve ignores not found errors 1`] = `
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`resolve returns empty array if no handler found anything 1`] = `
|
||||
exports[`resolve returns empty array if no source found anything 1`] = `
|
||||
{
|
||||
"streams": [],
|
||||
"ttl": 900000,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`resolve returns empty array if no handler supported the type 1`] = `
|
||||
exports[`resolve returns empty array if no source supported the type 1`] = `
|
||||
{
|
||||
"streams": [],
|
||||
"ttl": 900000,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`resolve returns handler errors as stream 1`] = `
|
||||
exports[`resolve returns info as stream if no sources were configured 1`] = `
|
||||
{
|
||||
"streams": [
|
||||
{
|
||||
"name": "WebStreamr",
|
||||
"title": "🔗 MeineCloud
|
||||
❌ Request failed. Request-id: id.",
|
||||
"ytId": "E4WlUXrJgy4",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`resolve returns info as stream if no handlers were configured 1`] = `
|
||||
{
|
||||
"streams": [
|
||||
{
|
||||
"name": "WebStreamr",
|
||||
"title": "⚠️ No handlers found. Please re-configure the plugin.",
|
||||
"title": "⚠️ No sources found. Please re-configure the plugin.",
|
||||
"ytId": "E4WlUXrJgy4",
|
||||
},
|
||||
],
|
||||
|
|
@ -263,3 +250,16 @@ exports[`resolve returns sorted results 1`] = `
|
|||
"ttl": 900000,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`resolve returns source errors as stream 1`] = `
|
||||
{
|
||||
"streams": [
|
||||
{
|
||||
"name": "WebStreamr",
|
||||
"title": "🔗 MeineCloud
|
||||
❌ Request failed. Request-id: id.",
|
||||
"ytId": "E4WlUXrJgy4",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`buildManifest has checked handler with appropriate config 1`] = `
|
||||
exports[`buildManifest has checked source with appropriate config 1`] = `
|
||||
[
|
||||
{
|
||||
"default": "checked",
|
||||
|
|
@ -26,7 +26,7 @@ exports[`buildManifest has checked handler with appropriate config 1`] = `
|
|||
]
|
||||
`;
|
||||
|
||||
exports[`buildManifest has unchecked handler without a config 1`] = `
|
||||
exports[`buildManifest has unchecked source without a config 1`] = `
|
||||
[
|
||||
{
|
||||
"key": "de",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { buildManifest } from './manifest';
|
||||
import { StreamKiste, MeineCloud, VerHdLink } from '../handler';
|
||||
import { StreamKiste, MeineCloud, VerHdLink } from '../source';
|
||||
import { Fetcher } from './Fetcher';
|
||||
jest.mock('../utils/Fetcher');
|
||||
|
||||
|
|
@ -7,25 +7,25 @@ jest.mock('../utils/Fetcher');
|
|||
const fetcher = new Fetcher();
|
||||
|
||||
describe('buildManifest', () => {
|
||||
test('has unchecked handler without a config', () => {
|
||||
const handlers = [
|
||||
test('has unchecked source without a config', () => {
|
||||
const sources = [
|
||||
new VerHdLink(fetcher),
|
||||
new StreamKiste(fetcher),
|
||||
new MeineCloud(fetcher),
|
||||
];
|
||||
|
||||
const manifest = buildManifest(handlers, {});
|
||||
const manifest = buildManifest(sources, {});
|
||||
|
||||
expect(manifest.config).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('has checked handler with appropriate config', () => {
|
||||
const handlers = [
|
||||
test('has checked source with appropriate config', () => {
|
||||
const sources = [
|
||||
new VerHdLink(fetcher),
|
||||
new StreamKiste(fetcher),
|
||||
new MeineCloud(fetcher),
|
||||
];
|
||||
const manifest = buildManifest(handlers, { de: 'on' });
|
||||
const manifest = buildManifest(sources, { de: 'on' });
|
||||
|
||||
expect(manifest.config).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { Handler } from '../handler';
|
||||
import { Source } from '../source';
|
||||
import { Config, CountryCode, ManifestWithConfig } from '../types';
|
||||
import { envGetAppId, envGetAppName } from './env';
|
||||
import { flagFromCountryCode, languageFromCountryCode } from './language';
|
||||
|
||||
const typedEntries = <T extends object>(obj: T): [keyof T, T[keyof T]][] => (Object.entries(obj) as [keyof T, T[keyof T]][]);
|
||||
|
||||
export const buildManifest = (handlers: Handler[], config: Config): ManifestWithConfig => {
|
||||
export const buildManifest = (sources: Source[], config: Config): ManifestWithConfig => {
|
||||
const manifest: ManifestWithConfig = {
|
||||
id: envGetAppId(),
|
||||
version: '0.28.0', // x-release-please-version
|
||||
|
|
@ -33,19 +33,19 @@ export const buildManifest = (handlers: Handler[], config: Config): ManifestWith
|
|||
},
|
||||
};
|
||||
|
||||
const countryCodeHandlers: Partial<Record<CountryCode, Handler[]>> = {};
|
||||
handlers.forEach((handler) => {
|
||||
handler.countryCodes.forEach(countryCode => countryCodeHandlers[countryCode] = [...(countryCodeHandlers[countryCode] ?? []), handler]);
|
||||
const countryCodeSources: Partial<Record<CountryCode, Source[]>> = {};
|
||||
sources.forEach((handler) => {
|
||||
handler.countryCodes.forEach(countryCode => countryCodeSources[countryCode] = [...(countryCodeSources[countryCode] ?? []), handler]);
|
||||
});
|
||||
|
||||
const sortedLanguageHandlers = typedEntries(countryCodeHandlers)
|
||||
const sortedLanguageSources = typedEntries(countryCodeSources)
|
||||
.sort(([countryCodeA], [countryCodeB]) => countryCodeA.localeCompare(countryCodeB));
|
||||
|
||||
for (const [countryCode, handlers] of sortedLanguageHandlers) {
|
||||
for (const [countryCode, sources] of sortedLanguageSources) {
|
||||
manifest.config.push({
|
||||
key: countryCode,
|
||||
type: 'checkbox',
|
||||
title: `${languageFromCountryCode(countryCode)} ${flagFromCountryCode(countryCode)} (${(handlers as Handler[]).map(handler => handler.label).join(', ')})`,
|
||||
title: `${languageFromCountryCode(countryCode)} ${flagFromCountryCode(countryCode)} (${(sources as Source[]).map(handler => handler.label).join(', ')})`,
|
||||
...(countryCode in config && { default: 'checked' }),
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue