feat: configure languages instead of handlers
just feels more natural and helps maintainence. handlers should be an internal thing.
This commit is contained in:
parent
d368b3a9de
commit
5b389ada9e
16 changed files with 57 additions and 29 deletions
|
|
@ -29,13 +29,14 @@ export class StreamController {
|
|||
const ctx: Context = {
|
||||
id: res.getHeader('X-Request-ID') as string,
|
||||
ip: req.ip as string,
|
||||
config,
|
||||
};
|
||||
|
||||
this.logger.info(`Search stream for type "${type}" and id "${id}"`, ctx);
|
||||
|
||||
const selectedHandlers = this.handlers.filter(handler => handler.id in config);
|
||||
const handlers = this.handlers.filter(handler => handler.languages.filter(language => language in ctx.config).length);
|
||||
|
||||
const streams = await this.streamResolver.resolve(ctx, selectedHandlers, type, id);
|
||||
const streams = await this.streamResolver.resolve(ctx, handlers, type, id);
|
||||
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.send(JSON.stringify({ streams }));
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const fetcher = new Fetcher();
|
|||
const extractorRegistry = new ExtractorRegistry(logger, fetcher);
|
||||
|
||||
describe('ExtractorRegistry', () => {
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1' };
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1', config: { de: 'on' } };
|
||||
|
||||
test('returns undefined when no extractor can be found', async () => {
|
||||
const urlResult = await extractorRegistry.handle(ctx, new URL('https://some-url.test'), 'en');
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const logger = winston.createLogger({ transports: [new winston.transports.Consol
|
|||
// @ts-expect-error No constructor args needed
|
||||
const fetcher = new Fetcher();
|
||||
const handler = new CineHDPlus(fetcher, new ExtractorRegistry(logger, fetcher));
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1' };
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1', config: { es: 'on', mx: 'on' } };
|
||||
|
||||
describe('CineHDPlus', () => {
|
||||
test('does not handle non imdb series', async () => {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const logger = winston.createLogger({ transports: [new winston.transports.Consol
|
|||
// @ts-expect-error No constructor args needed
|
||||
const fetcher = new Fetcher();
|
||||
const handler = new Eurostreaming(fetcher, new ExtractorRegistry(logger, fetcher));
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1' };
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1', config: { it: 'on' } };
|
||||
|
||||
describe('Eurostreaming', () => {
|
||||
test('does not handle non imdb series', async () => {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const logger = winston.createLogger({ transports: [new winston.transports.Consol
|
|||
// @ts-expect-error No constructor args needed
|
||||
const fetcher = new Fetcher();
|
||||
const handler = new Frembed(fetcher, new ExtractorRegistry(logger, fetcher));
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1' };
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1', config: { fr: 'on' } };
|
||||
|
||||
describe('Frembed', () => {
|
||||
test('does not handle non imdb series', async () => {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const logger = winston.createLogger({ transports: [new winston.transports.Consol
|
|||
// @ts-expect-error No constructor args needed
|
||||
const fetcher = new Fetcher();
|
||||
const handler = new FrenchCloud(fetcher, new ExtractorRegistry(logger, fetcher));
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1' };
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1', config: { fr: 'on' } };
|
||||
|
||||
describe('FrenchCloud', () => {
|
||||
test('does not handle non imdb movies', async () => {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const logger = winston.createLogger({ transports: [new winston.transports.Consol
|
|||
// @ts-expect-error No constructor args needed
|
||||
const fetcher = new Fetcher();
|
||||
const handler = new KinoKiste(fetcher, new ExtractorRegistry(logger, fetcher));
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1' };
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1', config: { de: 'on' } };
|
||||
|
||||
describe('KinoKiste', () => {
|
||||
test('does not handle non imdb series', async () => {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const logger = winston.createLogger({ transports: [new winston.transports.Consol
|
|||
// @ts-expect-error No constructor args needed
|
||||
const fetcher = new Fetcher();
|
||||
const handler = new MeineCloud(fetcher, new ExtractorRegistry(logger, fetcher));
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1' };
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1', config: { de: 'on' } };
|
||||
|
||||
describe('MeineCloud', () => {
|
||||
test('does not handle non imdb movies', async () => {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const logger = winston.createLogger({ transports: [new winston.transports.Consol
|
|||
// @ts-expect-error No constructor args needed
|
||||
const fetcher = new Fetcher();
|
||||
const handler = new MostraGuarda(fetcher, new ExtractorRegistry(logger, fetcher));
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1' };
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1', config: { it: 'on' } };
|
||||
|
||||
describe('MostraGuarda', () => {
|
||||
test('does not handle non imdb movies', async () => {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const logger = winston.createLogger({ transports: [new winston.transports.Consol
|
|||
// @ts-expect-error No constructor args needed
|
||||
const fetcher = new Fetcher();
|
||||
const handler = new VerHdLink(fetcher, new ExtractorRegistry(logger, fetcher));
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1' };
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1', config: { es: 'on', mx: 'on' } };
|
||||
|
||||
describe('VerHdLink', () => {
|
||||
test('does not handle non imdb movies', async () => {
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ export class VerHdLink implements Handler {
|
|||
$('._player-mirrors')
|
||||
.map((_i, el) => {
|
||||
let countryCode = undefined;
|
||||
if ($(el).hasClass('latino')) {
|
||||
if ($(el).hasClass('latino') && 'mx' in ctx.config) {
|
||||
countryCode = 'mx';
|
||||
} else if ($(el).hasClass('castellano')) {
|
||||
} else if ($(el).hasClass('castellano') && 'es' in ctx.config) {
|
||||
countryCode = 'es';
|
||||
} else {
|
||||
return [];
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { Manifest, ManifestConfig } from 'stremio-addon-sdk';
|
|||
export interface Context {
|
||||
id: string;
|
||||
ip: string;
|
||||
config: Config;
|
||||
}
|
||||
|
||||
export type ManifestWithConfig = Manifest & { config: ManifestConfig[] };
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const axiosMock = new AxiosMockAdapter(axios);
|
|||
const fetcher = new Fetcher(axios, winston.createLogger({ transports: [new winston.transports.Console({ level: 'nope' })] }));
|
||||
|
||||
describe('fetch', () => {
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1' };
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1', config: { de: 'on' } };
|
||||
|
||||
test('text passes successful response through setting headers', async () => {
|
||||
axiosMock.onGet().reply(200, 'some text');
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ jest.mock('../utils/Fetcher');
|
|||
|
||||
const logger = winston.createLogger({ transports: [new winston.transports.Console({ level: 'nope' })] });
|
||||
const streamResolver = new StreamResolver(logger);
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1' };
|
||||
const ctx: Context = { id: 'id', ip: '127.0.0.1', config: { de: 'on', it: 'on' } };
|
||||
|
||||
// @ts-expect-error No constructor args needed
|
||||
const fetcher = new Fetcher();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import winston from 'winston';
|
||||
import { buildManifest } from './manifest';
|
||||
import { KinoKiste } from '../handler';
|
||||
import { KinoKiste, MeineCloud, VerHdLink } from '../handler';
|
||||
import { Fetcher } from './Fetcher';
|
||||
import { ExtractorRegistry } from '../extractor';
|
||||
|
||||
|
|
@ -16,17 +16,35 @@ describe('buildManifest', () => {
|
|||
});
|
||||
|
||||
test('has unchecked handler without a config', () => {
|
||||
const manifest = buildManifest([new KinoKiste(fetcher, new ExtractorRegistry(logger, fetcher))], {});
|
||||
const extractorRegistry = new ExtractorRegistry(logger, fetcher);
|
||||
const handlers = [
|
||||
new VerHdLink(fetcher, extractorRegistry),
|
||||
new KinoKiste(fetcher, extractorRegistry),
|
||||
new MeineCloud(fetcher, extractorRegistry),
|
||||
];
|
||||
|
||||
expect(manifest.config).toHaveLength(1);
|
||||
expect(manifest.config[0]?.default).toBeUndefined();
|
||||
const manifest = buildManifest(handlers, {});
|
||||
|
||||
expect(manifest.config).toStrictEqual([
|
||||
{ key: 'de', type: 'checkbox', title: '🇩🇪 (KinoKiste, MeineCloud)' },
|
||||
{ key: 'es', type: 'checkbox', title: '🇪🇸 (VerHdLink)' },
|
||||
{ key: 'mx', type: 'checkbox', title: '🇲🇽 (VerHdLink)' },
|
||||
]);
|
||||
});
|
||||
|
||||
test('has checked handler with appropriate config', () => {
|
||||
const kinokiste = new KinoKiste(fetcher, new ExtractorRegistry(logger, fetcher));
|
||||
const manifest = buildManifest([kinokiste], { [kinokiste.id]: 'on' });
|
||||
const extractorRegistry = new ExtractorRegistry(logger, fetcher);
|
||||
const handlers = [
|
||||
new VerHdLink(fetcher, extractorRegistry),
|
||||
new KinoKiste(fetcher, extractorRegistry),
|
||||
new MeineCloud(fetcher, extractorRegistry),
|
||||
];
|
||||
const manifest = buildManifest(handlers, { de: 'on' });
|
||||
|
||||
expect(manifest.config).toHaveLength(1);
|
||||
expect(manifest.config[0]?.default).toBe('checked');
|
||||
expect(manifest.config).toStrictEqual([
|
||||
{ key: 'de', type: 'checkbox', title: '🇩🇪 (KinoKiste, MeineCloud)', default: 'checked' },
|
||||
{ key: 'es', type: 'checkbox', title: '🇪🇸 (VerHdLink)' },
|
||||
{ key: 'mx', type: 'checkbox', title: '🇲🇽 (VerHdLink)' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -25,14 +25,22 @@ export const buildManifest = (handlers: Handler[], config: Config): ManifestWith
|
|||
config: [],
|
||||
};
|
||||
|
||||
const languageHandlers: Record<string, Handler[]> = {};
|
||||
handlers.forEach((handler) => {
|
||||
manifest.config.push({
|
||||
key: handler.id,
|
||||
type: 'checkbox',
|
||||
title: `${handler.languages.map(language => flag(language)).join(' ')} | ${handler.label} (${handler.contentTypes.map(contentType => contentType.replace('movie', 'movies')).join(', ')})`,
|
||||
...(handler.id in config && { default: 'checked' }),
|
||||
});
|
||||
handler.languages.forEach(language => languageHandlers[language] = [...(languageHandlers[language] ?? []), handler]);
|
||||
});
|
||||
|
||||
const sortedLanguageHandlers = Object.entries(languageHandlers)
|
||||
.sort(([languageA], [languageB]) => languageA.localeCompare(languageB));
|
||||
|
||||
for (const [language, handlers] of sortedLanguageHandlers) {
|
||||
manifest.config.push({
|
||||
key: language,
|
||||
type: 'checkbox',
|
||||
title: `${flag(language)} (${handlers.map(handler => handler.label).join(', ')})`,
|
||||
...(language in config && { default: 'checked' }),
|
||||
});
|
||||
}
|
||||
|
||||
return manifest;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue