feat(extractor): add Fastream via MediaFlow Proxy
This commit is contained in:
parent
5759a311aa
commit
f3f61c85cc
6 changed files with 95 additions and 0 deletions
17
src/extractor/Fastream.test.ts
Normal file
17
src/extractor/Fastream.test.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import winston from 'winston';
|
||||
import { createTestContext } from '../test';
|
||||
import { CountryCode } from '../types';
|
||||
import { FetcherMock } from '../utils';
|
||||
import { ExtractorRegistry } from './ExtractorRegistry';
|
||||
import { Fastream } from './Fastream';
|
||||
|
||||
const logger = winston.createLogger({ transports: [new winston.transports.Console({ level: 'nope' })] });
|
||||
const extractorRegistry = new ExtractorRegistry(logger, [new Fastream(new FetcherMock(`${__dirname}/__fixtures__/Fastream`))]);
|
||||
|
||||
const ctx = createTestContext({ mediaFlowProxyUrl: 'https://mediaflow-proxy.test', mediaFlowProxyPassword: 'asdfg' });
|
||||
|
||||
describe('Fastream', () => {
|
||||
test('fastream.to embed', async () => {
|
||||
expect(await extractorRegistry.handle(ctx, new URL('https://fastream.to/embed-3aooif4ozt10.html'), CountryCode.es)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
43
src/extractor/Fastream.ts
Normal file
43
src/extractor/Fastream.ts
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import { Context, CountryCode, Format, UrlResult } from '../types';
|
||||
import { buildMediaFlowProxyExtractorStreamUrl, Fetcher, guessHeightFromPlaylist, supportsMediaFlowProxy } from '../utils';
|
||||
import { Extractor } from './Extractor';
|
||||
|
||||
export class Fastream extends Extractor {
|
||||
public readonly id = 'fastream';
|
||||
|
||||
public readonly label = 'Fastream (via MediaFlow Proxy)';
|
||||
|
||||
public override readonly ttl = 0;
|
||||
|
||||
public override viaMediaFlowProxy = true;
|
||||
|
||||
private readonly fetcher: Fetcher;
|
||||
|
||||
public constructor(fetcher: Fetcher) {
|
||||
super();
|
||||
|
||||
this.fetcher = fetcher;
|
||||
}
|
||||
|
||||
public supports(ctx: Context, url: URL): boolean {
|
||||
return null !== url.host.match(/fastream/) && supportsMediaFlowProxy(ctx);
|
||||
}
|
||||
|
||||
protected async extractInternal(ctx: Context, url: URL, countryCode: CountryCode): Promise<UrlResult[]> {
|
||||
const playlistUrl = await buildMediaFlowProxyExtractorStreamUrl(ctx, this.fetcher, 'Fastream', url);
|
||||
|
||||
return [
|
||||
{
|
||||
url: playlistUrl,
|
||||
format: Format.hls,
|
||||
label: this.label,
|
||||
sourceId: `${this.id}_${countryCode}`,
|
||||
ttl: this.ttl,
|
||||
meta: {
|
||||
countryCodes: [countryCode],
|
||||
height: await guessHeightFromPlaylist(ctx, this.fetcher, playlistUrl),
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
}
|
||||
13
src/extractor/__fixtures__/Fastream/https:mediaflow-proxy.test-a27e0ed17a89171a46626397d1f1adf9
generated
Normal file
13
src/extractor/__fixtures__/Fastream/https:mediaflow-proxy.test-a27e0ed17a89171a46626397d1f1adf9
generated
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#EXTM3U
|
||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=318390,RESOLUTION=640x360,FRAME-RATE=25.000,CODECS="avc1.64001e,mp4a.40.2"
|
||||
https://mediaflow-proxy.test/proxy/hls/manifest.m3u8?api_password=asdfg&h_user-agent=Mozilla%2F5.0+%28X11%3B+Linux+x86_64%3B+rv%3A138.0%29+Gecko%2F20100101+Firefox%2F138.0&h_Accept=%2A%2F%2A&h_Connection=keep-alive&h_Accept-Language=en-US%2Cen%3Bq%3D0.5&h_referer=https%3A%2F%2Ffastream.to%2F&h_origin=https%3A%2F%2Ffastream.to&d=https%3A%2F%2Fs28.fastream.to%2Fhls2%2F09%2F00024%2F3aooif4ozt10_l%2Findex-v1-a1.m3u8%3Ft%3Dnw6_aeN6pDROuXsJQwyrJVm3qHKFedVfbTNj5LgXH-4%26s%3D1752863379%26e%3D43200%26v%3D1058373%26i%3D0.3%26sp%3D0
|
||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=648989,RESOLUTION=852x480,FRAME-RATE=25.000,CODECS="avc1.64001e,mp4a.40.2"
|
||||
https://mediaflow-proxy.test/proxy/hls/manifest.m3u8?api_password=asdfg&h_user-agent=Mozilla%2F5.0+%28X11%3B+Linux+x86_64%3B+rv%3A138.0%29+Gecko%2F20100101+Firefox%2F138.0&h_Accept=%2A%2F%2A&h_Connection=keep-alive&h_Accept-Language=en-US%2Cen%3Bq%3D0.5&h_referer=https%3A%2F%2Ffastream.to%2F&h_origin=https%3A%2F%2Ffastream.to&d=https%3A%2F%2Fs28.fastream.to%2Fhls2%2F09%2F00024%2F3aooif4ozt10_n%2Findex-v1-a1.m3u8%3Ft%3Dnw6_aeN6pDROuXsJQwyrJVm3qHKFedVfbTNj5LgXH-4%26s%3D1752863379%26e%3D43200%26v%3D1058373%26i%3D0.3%26sp%3D0
|
||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1231528,RESOLUTION=1280x720,FRAME-RATE=25.000,CODECS="avc1.64001f,mp4a.40.2"
|
||||
https://mediaflow-proxy.test/proxy/hls/manifest.m3u8?api_password=asdfg&h_user-agent=Mozilla%2F5.0+%28X11%3B+Linux+x86_64%3B+rv%3A138.0%29+Gecko%2F20100101+Firefox%2F138.0&h_Accept=%2A%2F%2A&h_Connection=keep-alive&h_Accept-Language=en-US%2Cen%3Bq%3D0.5&h_referer=https%3A%2F%2Ffastream.to%2F&h_origin=https%3A%2F%2Ffastream.to&d=https%3A%2F%2Fs28.fastream.to%2Fhls2%2F09%2F00024%2F3aooif4ozt10_h%2Findex-v1-a1.m3u8%3Ft%3Dnw6_aeN6pDROuXsJQwyrJVm3qHKFedVfbTNj5LgXH-4%26s%3D1752863379%26e%3D43200%26v%3D1058373%26i%3D0.3%26sp%3D0
|
||||
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=3193889,RESOLUTION=1920x1080,FRAME-RATE=25.000,CODECS="avc1.42001e,mp4a.40.2"
|
||||
https://mediaflow-proxy.test/proxy/hls/manifest.m3u8?api_password=asdfg&h_user-agent=Mozilla%2F5.0+%28X11%3B+Linux+x86_64%3B+rv%3A138.0%29+Gecko%2F20100101+Firefox%2F138.0&h_Accept=%2A%2F%2A&h_Connection=keep-alive&h_Accept-Language=en-US%2Cen%3Bq%3D0.5&h_referer=https%3A%2F%2Ffastream.to%2F&h_origin=https%3A%2F%2Ffastream.to&d=https%3A%2F%2Fs28.fastream.to%2Fhls2%2F09%2F00024%2F3aooif4ozt10_x%2Findex-v1-a1.m3u8%3Ft%3Dnw6_aeN6pDROuXsJQwyrJVm3qHKFedVfbTNj5LgXH-4%26s%3D1752863379%26e%3D43200%26v%3D1058373%26i%3D0.3%26sp%3D0
|
||||
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=21129,RESOLUTION=640x360,CODECS="avc1.64001e",URI="https://mediaflow-proxy.test/proxy/hls/manifest.m3u8?api_password=asdfg&h_user-agent=Mozilla%2F5.0+%28X11%3B+Linux+x86_64%3B+rv%3A138.0%29+Gecko%2F20100101+Firefox%2F138.0&h_Accept=%2A%2F%2A&h_Connection=keep-alive&h_Accept-Language=en-US%2Cen%3Bq%3D0.5&h_referer=https%3A%2F%2Ffastream.to%2F&h_origin=https%3A%2F%2Ffastream.to&d=https%3A%2F%2Fs28.fastream.to%2Fhls2%2F09%2F00024%2F3aooif4ozt10_l%2Fiframes-v1-a1.m3u8%3Ft%3Dnw6_aeN6pDROuXsJQwyrJVm3qHKFedVfbTNj5LgXH-4%26s%3D1752863379%26e%3D43200%26v%3D1058373%26i%3D0.3%26sp%3D0"
|
||||
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=37640,RESOLUTION=852x480,CODECS="avc1.64001e",URI="https://mediaflow-proxy.test/proxy/hls/manifest.m3u8?api_password=asdfg&h_user-agent=Mozilla%2F5.0+%28X11%3B+Linux+x86_64%3B+rv%3A138.0%29+Gecko%2F20100101+Firefox%2F138.0&h_Accept=%2A%2F%2A&h_Connection=keep-alive&h_Accept-Language=en-US%2Cen%3Bq%3D0.5&h_referer=https%3A%2F%2Ffastream.to%2F&h_origin=https%3A%2F%2Ffastream.to&d=https%3A%2F%2Fs28.fastream.to%2Fhls2%2F09%2F00024%2F3aooif4ozt10_n%2Fiframes-v1-a1.m3u8%3Ft%3Dnw6_aeN6pDROuXsJQwyrJVm3qHKFedVfbTNj5LgXH-4%26s%3D1752863379%26e%3D43200%26v%3D1058373%26i%3D0.3%26sp%3D0"
|
||||
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=63209,RESOLUTION=1280x720,CODECS="avc1.64001f",URI="https://mediaflow-proxy.test/proxy/hls/manifest.m3u8?api_password=asdfg&h_user-agent=Mozilla%2F5.0+%28X11%3B+Linux+x86_64%3B+rv%3A138.0%29+Gecko%2F20100101+Firefox%2F138.0&h_Accept=%2A%2F%2A&h_Connection=keep-alive&h_Accept-Language=en-US%2Cen%3Bq%3D0.5&h_referer=https%3A%2F%2Ffastream.to%2F&h_origin=https%3A%2F%2Ffastream.to&d=https%3A%2F%2Fs28.fastream.to%2Fhls2%2F09%2F00024%2F3aooif4ozt10_h%2Fiframes-v1-a1.m3u8%3Ft%3Dnw6_aeN6pDROuXsJQwyrJVm3qHKFedVfbTNj5LgXH-4%26s%3D1752863379%26e%3D43200%26v%3D1058373%26i%3D0.3%26sp%3D0"
|
||||
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=693070,RESOLUTION=1920x1080,CODECS="avc1.42001e",URI="https://mediaflow-proxy.test/proxy/hls/manifest.m3u8?api_password=asdfg&h_user-agent=Mozilla%2F5.0+%28X11%3B+Linux+x86_64%3B+rv%3A138.0%29+Gecko%2F20100101+Firefox%2F138.0&h_Accept=%2A%2F%2A&h_Connection=keep-alive&h_Accept-Language=en-US%2Cen%3Bq%3D0.5&h_referer=https%3A%2F%2Ffastream.to%2F&h_origin=https%3A%2F%2Ffastream.to&d=https%3A%2F%2Fs28.fastream.to%2Fhls2%2F09%2F00024%2F3aooif4ozt10_x%2Fiframes-v1-a1.m3u8%3Ft%3Dnw6_aeN6pDROuXsJQwyrJVm3qHKFedVfbTNj5LgXH-4%26s%3D1752863379%26e%3D43200%26v%3D1058373%26i%3D0.3%26sp%3D0"
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"destination_url":"https://s28.fastream.to/hls2/09/00024/3aooif4ozt10_,l,n,h,x,.urlset/master.m3u8?t=nw6_aeN6pDROuXsJQwyrJVm3qHKFedVfbTNj5LgXH-4&s=1752863379&e=43200&v=1058373&i=0.3&sp=0","request_headers":{"user-agent":"Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0","Accept":"*/*","Connection":"keep-alive","Accept-Language":"en-US,en;q=0.5","referer":"https://fastream.to/","origin":"https://fastream.to"},"mediaflow_proxy_url":"https://mediaflow-proxy.test/proxy/hls/manifest.m3u8","query_params":{"api_password":"asdfg"}}
|
||||
19
src/extractor/__snapshots__/Fastream.test.ts.snap
Normal file
19
src/extractor/__snapshots__/Fastream.test.ts.snap
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`Fastream fastream.to embed 1`] = `
|
||||
[
|
||||
{
|
||||
"format": "hls",
|
||||
"label": "Fastream (via MediaFlow Proxy)",
|
||||
"meta": {
|
||||
"countryCodes": [
|
||||
"es",
|
||||
],
|
||||
"height": 1080,
|
||||
},
|
||||
"sourceId": "fastream_es",
|
||||
"ttl": 0,
|
||||
"url": "https://mediaflow-proxy.test/proxy/hls/manifest.m3u8?api_password=asdfg&h_user-agent=Mozilla%2F5.0+%28X11%3B+Linux+x86_64%3B+rv%3A138.0%29+Gecko%2F20100101+Firefox%2F138.0&h_Accept=*%2F*&h_Connection=keep-alive&h_Accept-Language=en-US%2Cen%3Bq%3D0.5&h_referer=https%3A%2F%2Ffastream.to%2F&h_origin=https%3A%2F%2Ffastream.to&d=https%3A%2F%2Fs28.fastream.to%2Fhls2%2F09%2F00024%2F3aooif4ozt10_%2Cl%2Cn%2Ch%2Cx%2C.urlset%2Fmaster.m3u8%3Ft%3Dnw6_aeN6pDROuXsJQwyrJVm3qHKFedVfbTNj5LgXH-4%26s%3D1752863379%26e%3D43200%26v%3D1058373%26i%3D0.3%26sp%3D0",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
|
@ -3,6 +3,7 @@ import { DoodStream } from './DoodStream';
|
|||
import { Dropload } from './Dropload';
|
||||
import { ExternalUrl } from './ExternalUrl';
|
||||
import { Extractor } from './Extractor';
|
||||
import { Fastream } from './Fastream';
|
||||
import { KinoGer } from './KinoGer';
|
||||
import { Mixdrop } from './Mixdrop';
|
||||
import { Soaper } from './Soaper';
|
||||
|
|
@ -19,6 +20,7 @@ export * from './ExtractorRegistry';
|
|||
export const createExtractors = (fetcher: Fetcher): Extractor[] => [
|
||||
new DoodStream(fetcher),
|
||||
new Dropload(fetcher),
|
||||
new Fastream(fetcher),
|
||||
new KinoGer(fetcher),
|
||||
new Mixdrop(fetcher),
|
||||
new Soaper(fetcher),
|
||||
|
|
|
|||
Loading…
Reference in a new issue