feat(source): add Movix

This commit is contained in:
WebStreamr 2025-07-13 19:21:13 +00:00
parent 5e13042c71
commit ca0db32d19
No known key found for this signature in database
7 changed files with 209 additions and 1 deletions

View file

@ -5,7 +5,7 @@ import { v4 as uuidv4 } from 'uuid';
import winston from 'winston';
import { ConfigureController, ManifestController, StreamController } from './controller';
import { createExtractors, ExtractorRegistry } from './extractor';
import { CineHDPlus, Cuevana, Eurostreaming, Frembed, FrenchCloud, KinoGer, MegaKino, MeineCloud, MostraGuarda, Soaper, Source, StreamKiste, VerHdLink, VidSrc, VixSrc } from './source';
import { CineHDPlus, Cuevana, Eurostreaming, Frembed, FrenchCloud, KinoGer, MegaKino, MeineCloud, MostraGuarda, Movix, Soaper, Source, StreamKiste, VerHdLink, VidSrc, VixSrc } from './source';
import { envGet, envIsProd, Fetcher, StreamResolver } from './utils';
const logger = winston.createLogger({
@ -47,6 +47,7 @@ const sources: Source[] = [
// FR
new Frembed(fetcher),
new FrenchCloud(fetcher),
new Movix(fetcher),
// IT
new Eurostreaming(fetcher),
new MostraGuarda(fetcher),

23
src/source/Movix.test.ts Normal file
View file

@ -0,0 +1,23 @@
import { createTestContext } from '../test';
import { FetcherMock, TmdbId } from '../utils';
import { Movix } from './Movix';
const ctx = createTestContext({ fr: 'on' });
describe('Movix', () => {
let handler: Movix;
beforeEach(() => {
handler = new Movix(new FetcherMock(`${__dirname}/__fixtures__/Movix`));
});
test('handle tmdb black mirror s4e2', async () => {
const streams = await handler.handle(ctx, 'series', new TmdbId(42009, 4, 2));
expect(streams).toMatchSnapshot();
});
test('handle battle royal', async () => {
const streams = await handler.handle(ctx, 'movie', new TmdbId(3176, undefined, undefined));
expect(streams).toMatchSnapshot();
});
});

45
src/source/Movix.ts Normal file
View file

@ -0,0 +1,45 @@
import { ContentType } from 'stremio-addon-sdk';
import { Context, CountryCode } from '../types';
import { Fetcher, getTmdbId, Id } from '../utils';
import { Source, SourceResult } from './types';
interface MovixApiData {
player_links: { decoded_url: string }[];
}
export class Movix implements Source {
public readonly id = 'movix';
public readonly label = 'Movix';
public readonly contentTypes: ContentType[] = ['movie', 'series'];
public readonly countryCodes: CountryCode[] = [CountryCode.fr];
private readonly baseUrl = 'https://api.movix.site';
private readonly fetcher: Fetcher;
public constructor(fetcher: Fetcher) {
this.fetcher = fetcher;
}
public async handle(ctx: Context, _type: string, id: Id): Promise<SourceResult[]> {
const tmdbId = await getTmdbId(ctx, this.fetcher, id);
const apiUrl = tmdbId.season
? new URL(`/api/tmdb/tv/${tmdbId.id}?season=${tmdbId.season}&episode=${tmdbId.episode}`, this.baseUrl)
: new URL(`/api/tmdb/movie/${tmdbId.id}`, this.baseUrl);
const json = JSON.parse(await this.fetcher.text(ctx, apiUrl));
const data: MovixApiData = tmdbId.season ? json['current_episode'] : json;
const urls: URL[] = data['player_links'].map(({ decoded_url }) => new URL(decoded_url));
const title = tmdbId.season
? `${json['tmdb_details']['title']} ${tmdbId.season}x${tmdbId.episode}`
: json['tmdb_details']['title'];
return urls.map(url => ({ countryCode: CountryCode.fr, title, url }));
};
}

View file

@ -0,0 +1 @@
{"tmdb_details":{"id":3176,"title":"Battle Royale","original_title":"バトル・ロワイアル","release_date":"2000-12-16","poster_path":"/laUmjb39U6glMrOKyaco4QPeGaC.jpg","backdrop_path":"/amBvmIshdsSkOtvVIgxl7YSQ9Dg.jpg","overview":"Dans un avenir proche, les élèves de la classe B de 3ème du collège Shiroiwa ont été amenés sur une île déserte par une armée mystérieuse. Un adulte surgit tout à coup devant eux : leur ancien professeur Kitano. Il leur annonce qu'ils vont participer à un jeu de massacre dont la règle consiste à s'entretuer. Seul le dernier des survivants pourra regagner son foyer. Kitano leur présente deux nouveaux élèves très inquiétants. Des coups de feu retentissent pour convaincre les incrédules. Selon la loi de réforme de l'éducation pour le nouveau siècle, ce sacrifice permettra de former des adultes sains. Abandonnés chacun à son sort avec de la nourriture et une arme, les adolescents disposent d'un délai de trois jours pour s'entretuer.","vote_average":7.284},"iframe_src":"https://lecteurvideo.com/embed.php?id=17959&ads=true","player_links":[{"decoded_url":"https://lecteur6.com/video/18085327b86002fc604c323b9a07f997","quality":"Vidéo HD / PAS DE PUBLICITE 2","language":"French"},{"decoded_url":"https://vidoza.net/embed-55hvynbdyqvc.html","quality":"Vid Vidéo 6 / PAS DE PUBLICITE","language":"French"},{"decoded_url":"https://wishonly.site/e/kykhuv6tscs8","quality":"Wish Vidéo 4 / PAS DE PUBLICITE","language":"French"},{"decoded_url":"https://darkibox.com/embed-5ghz7myucfjq.html","quality":"Darki Vidéo HD / PAS DE PUBLICITE","language":"French"},{"decoded_url":"https://supervideo.cc/e/uieh17bid0ce","quality":"Super Vidéo HD / PAS DE PUBLICITE","language":"French"},{"decoded_url":"https://dood.li/e/gha75crrm8nf","quality":"Doodstream Vidéo 9 / Le serveur vidéo contient des publicités","language":"French"},{"decoded_url":"https://filemoon.sx/e/c5lhlypfasmm","quality":"FileMon Vidéo 10 / Le serveur vidéo contient des publicités","language":"French"},{"decoded_url":"https://voe.sx/e/aghpmosgkhsu","quality":"VoeSx Vidéo 11 / Le serveur vidéo contient des publicités","language":"French"},{"decoded_url":"http://vidmoly.me/embed-79w00r2qv88n.html","quality":"VidMoly Vidéo 12 / Le serveur vidéo contient des publicités","language":"French"},{"decoded_url":"https://waaw.to/f/JWzt5eJSbpu8","quality":"Netu Vidéo 14 / Le serveur vidéo contient des publicités","language":"French"},{"decoded_url":"https://veev.to/e/lu4c24e3aetf","quality":"Veed / Le serveur vidéo contient des publicités","language":"French"},{"decoded_url":"https://listeamed.net/e/eL2157Kzw8m5rw4","quality":"VidGuard / Le serveur vidéo contient des publicités","language":"French"}]}

View file

@ -0,0 +1 @@
{"tmdb_details":{"id":42009,"title":"Black Mirror","original_title":"Black Mirror","release_date":"2011-12-04","poster_path":"/9acfIYfBuB4GFVROipM9YrqxsXd.jpg","backdrop_path":"/dg3OindVAGZBjlT3xYKqIAdukPL.jpg","overview":"Les histoires tordues se succèdent dans cette série d'anthologie hallucinante qui révèle les plus grandes innovations de l'humanité, mais aussi ses côtés les plus sombres.","vote_average":8.284},"seasons":[{"season_number":1,"name":"Black Mirror - Season 1","data_id":"73065","post_id":"19799","episodes":[]},{"season_number":2,"name":"Black Mirror - Season 2","data_id":"73066","post_id":"19799","episodes":[]},{"season_number":3,"name":"Black Mirror - Season 3","data_id":"73067","post_id":"19799","episodes":[]},{"season_number":4,"name":"Black Mirror - Season 4","data_id":"73068","post_id":"19799","episodes":[]},{"season_number":5,"name":"Black Mirror - Season 5","data_id":"73069","post_id":"19799","episodes":[]},{"season_number":6,"name":"Black Mirror - Season 6","data_id":"73070","post_id":"19799","episodes":[]},{"season_number":7,"name":"Black Mirror - Season 7","data_id":"229573","post_id":"19799","episodes":[]}],"current_episode":{"season_number":4,"episode_number":2,"title":"Black Mirror","iframe_src":"https://lecteurvideo.com/embed.php?id=17320&ads=true","player_links":[{"decoded_url":"https://uqload.net/embed-xjmhb7rbzdjh.html","quality":"Uqload Vidéo 8 / Le serveur vidéo contient des publicités","language":"French"},{"decoded_url":"https://lulustream.com/e/c3defa2cbtmm","quality":"LuluStream / PAS DE PUBLICITE","language":"French"},{"decoded_url":"https://wishonly.site/e/bzfdmjlrsqxk","quality":"Wish Vidéo 4 / PAS DE PUBLICITE","language":"French"},{"decoded_url":"https://vidoza.net/embed-i2e8gn4m64e1.html","quality":"Vid Vidéo 6 / PAS DE PUBLICITE","language":"French"},{"decoded_url":"https://filemoon.sx/e/0iuzfpt5cbx6","quality":"FileMon Vidéo 10 / Le serveur vidéo contient des publicités","language":"French"},{"decoded_url":"https://voe.sx/e/mustkdlxo67t","quality":"VoeSx Vidéo 11 / Le serveur vidéo contient des publicités","language":"French"},{"decoded_url":"http://vidmoly.me/embed-2rls953tvhxc.html","quality":"VidMoly Vidéo 12 / Le serveur vidéo contient des publicités","language":"French"},{"decoded_url":"https://waaw.to/f/GdQ6mHpxPdd8","quality":"Netu Vidéo 14 / Le serveur vidéo contient des publicités","language":"French"},{"decoded_url":"https://veev.to/e/nifwerilwo0i","quality":"Veed / Le serveur vidéo contient des publicités","language":"French"},{"decoded_url":"https://listeamed.net/e/8ozgENePwdLxmjA","quality":"VidGuard / Le serveur vidéo contient des publicités","language":"French"},{"decoded_url":"https://coflix.upn.one/#x63hig","quality":"coflix.upn","language":"French"},{"decoded_url":"https://do7go.com/e/2zn4y7ueq1ta","quality":"do7go","language":"French"},{"decoded_url":"https://movearnpre.com/embed/eiel2p4z74kp","quality":"movearnpre","language":"French"}]}}

View file

@ -0,0 +1,136 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`Movix handle battle royal 1`] = `
[
{
"countryCode": "fr",
"title": "Battle Royale",
"url": "https://lecteur6.com/video/18085327b86002fc604c323b9a07f997",
},
{
"countryCode": "fr",
"title": "Battle Royale",
"url": "https://vidoza.net/embed-55hvynbdyqvc.html",
},
{
"countryCode": "fr",
"title": "Battle Royale",
"url": "https://wishonly.site/e/kykhuv6tscs8",
},
{
"countryCode": "fr",
"title": "Battle Royale",
"url": "https://darkibox.com/embed-5ghz7myucfjq.html",
},
{
"countryCode": "fr",
"title": "Battle Royale",
"url": "https://supervideo.cc/e/uieh17bid0ce",
},
{
"countryCode": "fr",
"title": "Battle Royale",
"url": "https://dood.li/e/gha75crrm8nf",
},
{
"countryCode": "fr",
"title": "Battle Royale",
"url": "https://filemoon.sx/e/c5lhlypfasmm",
},
{
"countryCode": "fr",
"title": "Battle Royale",
"url": "https://voe.sx/e/aghpmosgkhsu",
},
{
"countryCode": "fr",
"title": "Battle Royale",
"url": "http://vidmoly.me/embed-79w00r2qv88n.html",
},
{
"countryCode": "fr",
"title": "Battle Royale",
"url": "https://waaw.to/f/JWzt5eJSbpu8",
},
{
"countryCode": "fr",
"title": "Battle Royale",
"url": "https://veev.to/e/lu4c24e3aetf",
},
{
"countryCode": "fr",
"title": "Battle Royale",
"url": "https://listeamed.net/e/eL2157Kzw8m5rw4",
},
]
`;
exports[`Movix handle tmdb black mirror s4e2 1`] = `
[
{
"countryCode": "fr",
"title": "Black Mirror 4x2",
"url": "https://uqload.net/embed-xjmhb7rbzdjh.html",
},
{
"countryCode": "fr",
"title": "Black Mirror 4x2",
"url": "https://lulustream.com/e/c3defa2cbtmm",
},
{
"countryCode": "fr",
"title": "Black Mirror 4x2",
"url": "https://wishonly.site/e/bzfdmjlrsqxk",
},
{
"countryCode": "fr",
"title": "Black Mirror 4x2",
"url": "https://vidoza.net/embed-i2e8gn4m64e1.html",
},
{
"countryCode": "fr",
"title": "Black Mirror 4x2",
"url": "https://filemoon.sx/e/0iuzfpt5cbx6",
},
{
"countryCode": "fr",
"title": "Black Mirror 4x2",
"url": "https://voe.sx/e/mustkdlxo67t",
},
{
"countryCode": "fr",
"title": "Black Mirror 4x2",
"url": "http://vidmoly.me/embed-2rls953tvhxc.html",
},
{
"countryCode": "fr",
"title": "Black Mirror 4x2",
"url": "https://waaw.to/f/GdQ6mHpxPdd8",
},
{
"countryCode": "fr",
"title": "Black Mirror 4x2",
"url": "https://veev.to/e/nifwerilwo0i",
},
{
"countryCode": "fr",
"title": "Black Mirror 4x2",
"url": "https://listeamed.net/e/8ozgENePwdLxmjA",
},
{
"countryCode": "fr",
"title": "Black Mirror 4x2",
"url": "https://coflix.upn.one/#x63hig",
},
{
"countryCode": "fr",
"title": "Black Mirror 4x2",
"url": "https://do7go.com/e/2zn4y7ueq1ta",
},
{
"countryCode": "fr",
"title": "Black Mirror 4x2",
"url": "https://movearnpre.com/embed/eiel2p4z74kp",
},
]
`;

View file

@ -7,6 +7,7 @@ export * from './KinoGer';
export * from './MegaKino';
export * from './MeineCloud';
export * from './MostraGuarda';
export * from './Movix';
export * from './Soaper';
export * from './StreamKiste';
export * from './VerHdLink';