diff --git a/src/extractor/DoodStream.ts b/src/extractor/DoodStream.ts index 7eb2bc0..918972e 100644 --- a/src/extractor/DoodStream.ts +++ b/src/extractor/DoodStream.ts @@ -2,7 +2,7 @@ import randomstring from 'randomstring'; import * as cheerio from 'cheerio'; import { Extractor } from './Extractor'; import { Fetcher, guessFromTitle } from '../utils'; -import { Context, CountryCode, UrlResult } from '../types'; +import { Context, CountryCode, Format, UrlResult } from '../types'; import { NotFoundError } from '../error'; export class DoodStream extends Extractor { @@ -52,6 +52,7 @@ export class DoodStream extends Extractor { return [ { url: mp4Url, + format: Format.mp4, label: this.label, sourceId: `${this.id}_${countryCode}`, ttl: this.ttl, diff --git a/src/extractor/Dropload.ts b/src/extractor/Dropload.ts index 59a5cf6..32b49c9 100644 --- a/src/extractor/Dropload.ts +++ b/src/extractor/Dropload.ts @@ -2,7 +2,7 @@ import bytes from 'bytes'; import * as cheerio from 'cheerio'; import { Extractor } from './Extractor'; import { extractUrlFromPacked, Fetcher } from '../utils'; -import { Context, CountryCode, UrlResult } from '../types'; +import { Context, CountryCode, Format, UrlResult } from '../types'; import { NotFoundError } from '../error'; export class Dropload extends Extractor { @@ -41,6 +41,7 @@ export class Dropload extends Extractor { return [ { url: extractUrlFromPacked(html, [/sources:\[{file:"(.*?)"/]), + format: Format.hls, label: this.label, sourceId: `${this.id}_${countryCode}`, ttl: this.ttl, diff --git a/src/extractor/ExternalUrl.ts b/src/extractor/ExternalUrl.ts index db587ba..9483a92 100644 --- a/src/extractor/ExternalUrl.ts +++ b/src/extractor/ExternalUrl.ts @@ -1,6 +1,6 @@ import { Extractor } from './Extractor'; import { Fetcher, showExternalUrls } from '../utils'; -import { Context, CountryCode, UrlResult } from '../types'; +import { Context, CountryCode, Format, UrlResult } from '../types'; export class ExternalUrl extends Extractor { public readonly id = 'external'; @@ -32,6 +32,7 @@ export class ExternalUrl extends Extractor { return [ { url: url, + format: Format.unknown, isExternal: true, label: `${url.host}`, sourceId: `${this.id}_${countryCode}`, diff --git a/src/extractor/Extractor.ts b/src/extractor/Extractor.ts index 1851963..a9bbd13 100644 --- a/src/extractor/Extractor.ts +++ b/src/extractor/Extractor.ts @@ -1,4 +1,4 @@ -import { Context, CountryCode, UrlResult } from '../types'; +import { Context, CountryCode, Format, UrlResult } from '../types'; import { NotFoundError } from '../error'; export abstract class Extractor { @@ -27,6 +27,7 @@ export abstract class Extractor { return [ { url, + format: Format.unknown, isExternal: true, error, label: this.label, diff --git a/src/extractor/Fsst.ts b/src/extractor/Fsst.ts index 01b3320..afbf293 100644 --- a/src/extractor/Fsst.ts +++ b/src/extractor/Fsst.ts @@ -1,7 +1,7 @@ import * as cheerio from 'cheerio'; import { Extractor } from './Extractor'; import { Fetcher } from '../utils'; -import { Context, CountryCode, UrlResult } from '../types'; +import { Context, CountryCode, Format, UrlResult } from '../types'; export class Fsst extends Extractor { public readonly id = 'fsst'; @@ -35,6 +35,7 @@ export class Fsst extends Extractor { return { url: new URL(fileHref), + format: Format.mp4, label: this.label, sourceId: `${this.id}_${countryCode}_${index}`, meta: { diff --git a/src/extractor/KinoGer.ts b/src/extractor/KinoGer.ts index cb7b419..c29f853 100644 --- a/src/extractor/KinoGer.ts +++ b/src/extractor/KinoGer.ts @@ -1,7 +1,7 @@ import crypto from 'crypto'; import { Extractor } from './Extractor'; import { Fetcher, guessFromTitle } from '../utils'; -import { Context, CountryCode, UrlResult } from '../types'; +import { Context, CountryCode, Format, UrlResult } from '../types'; /** @see https://github.com/Gujal00/ResolveURL/blob/master/script.module.resolveurl/lib/resolveurl/plugins/kinoger.py */ export class KinoGer extends Extractor { @@ -41,6 +41,7 @@ export class KinoGer extends Extractor { return [ { url: new URL(cf), + format: Format.hls, label: this.label, sourceId: `${this.id}_${countryCode}`, ttl: this.ttl, diff --git a/src/extractor/Mixdrop.ts b/src/extractor/Mixdrop.ts index fef3172..14d606e 100644 --- a/src/extractor/Mixdrop.ts +++ b/src/extractor/Mixdrop.ts @@ -2,7 +2,7 @@ import bytes from 'bytes'; import * as cheerio from 'cheerio'; import { Extractor } from './Extractor'; import { buildMediaFlowProxyUrl, Fetcher, hasMediaFlowProxy } from '../utils'; -import { Context, CountryCode, UrlResult } from '../types'; +import { Context, CountryCode, Format, UrlResult } from '../types'; import { NotFoundError } from '../error'; export class Mixdrop extends Extractor { @@ -40,6 +40,7 @@ export class Mixdrop extends Extractor { return [ { url: buildMediaFlowProxyUrl(ctx.config, 'Mixdrop', url), + format: Format.mp4, label: this.label, sourceId: `${this.id}_${countryCode}`, ttl: this.ttl, diff --git a/src/extractor/Soaper.ts b/src/extractor/Soaper.ts index 78ecb0c..71518a2 100644 --- a/src/extractor/Soaper.ts +++ b/src/extractor/Soaper.ts @@ -1,6 +1,6 @@ import { Extractor } from './Extractor'; import { Fetcher, guessFromPlaylist } from '../utils'; -import { Context, CountryCode, UrlResult } from '../types'; +import { Context, CountryCode, Format, UrlResult } from '../types'; interface SoaperInfoResponsePartial { val: string; @@ -53,6 +53,7 @@ export class Soaper extends Extractor { return [ { url: m3u8Url, + format: Format.hls, label: this.label, sourceId: `${this.id}_${countryCode}`, ttl: this.ttl, diff --git a/src/extractor/SuperVideo.ts b/src/extractor/SuperVideo.ts index f182f87..cc27125 100644 --- a/src/extractor/SuperVideo.ts +++ b/src/extractor/SuperVideo.ts @@ -2,7 +2,7 @@ import bytes from 'bytes'; import * as cheerio from 'cheerio'; import { Extractor } from './Extractor'; import { extractUrlFromPacked, Fetcher } from '../utils'; -import { Context, CountryCode, UrlResult } from '../types'; +import { Context, CountryCode, Format, UrlResult } from '../types'; import { NotFoundError } from '../error'; export class SuperVideo extends Extractor { @@ -45,6 +45,7 @@ export class SuperVideo extends Extractor { return [ { url: extractUrlFromPacked(html, [/sources:\[{file:"(.*?)"/]), + format: Format.hls, label: this.label, sourceId: `${this.id}_${countryCode}`, ttl: this.ttl, diff --git a/src/extractor/VidSrc.ts b/src/extractor/VidSrc.ts index d6bc1b5..78a9615 100644 --- a/src/extractor/VidSrc.ts +++ b/src/extractor/VidSrc.ts @@ -2,7 +2,7 @@ import * as cheerio from 'cheerio'; import slugify from 'slugify'; import { Extractor } from './Extractor'; import { Fetcher, guessFromPlaylist } from '../utils'; -import { Context, CountryCode, UrlResult } from '../types'; +import { Context, CountryCode, Format, UrlResult } from '../types'; import { NotFoundError } from '../error'; export class VidSrc extends Extractor { @@ -50,6 +50,7 @@ export class VidSrc extends Extractor { return { url: m3u8Url, + format: Format.hls, label: `${this.label} (${serverName})`, sourceId: `${this.id}_${slugify(serverName)}_${countryCode}`, ttl: this.ttl, diff --git a/src/extractor/__snapshots__/DoodStream.test.ts.snap b/src/extractor/__snapshots__/DoodStream.test.ts.snap index c68ada1..65eef59 100644 --- a/src/extractor/__snapshots__/DoodStream.test.ts.snap +++ b/src/extractor/__snapshots__/DoodStream.test.ts.snap @@ -3,6 +3,7 @@ exports[`DoodStream can guess height from title 1`] = ` [ { + "format": "mp4", "label": "DoodStream", "meta": { "countryCode": "fr", @@ -22,6 +23,7 @@ exports[`DoodStream can guess height from title 1`] = ` exports[`DoodStream dood.to 1`] = ` [ { + "format": "mp4", "label": "DoodStream", "meta": { "bytes": 791702409, @@ -41,6 +43,7 @@ exports[`DoodStream dood.to 1`] = ` exports[`DoodStream doodster 1`] = ` [ { + "format": "mp4", "label": "DoodStream", "meta": { "countryCode": "de", diff --git a/src/extractor/__snapshots__/Dropload.test.ts.snap b/src/extractor/__snapshots__/Dropload.test.ts.snap index b3f6b28..f15118a 100644 --- a/src/extractor/__snapshots__/Dropload.test.ts.snap +++ b/src/extractor/__snapshots__/Dropload.test.ts.snap @@ -3,6 +3,7 @@ exports[`Dropload dropload.io 1`] = ` [ { + "format": "hls", "label": "Dropload", "meta": { "bytes": 1395864371, diff --git a/src/extractor/__snapshots__/ExternalUrl.test.ts.snap b/src/extractor/__snapshots__/ExternalUrl.test.ts.snap index 305cb12..d230895 100644 --- a/src/extractor/__snapshots__/ExternalUrl.test.ts.snap +++ b/src/extractor/__snapshots__/ExternalUrl.test.ts.snap @@ -5,6 +5,7 @@ exports[`ExternalUrl 404 - not found 1`] = `[]`; exports[`ExternalUrl johnalwayssame.com with title 1`] = ` [ { + "format": "unknown", "isExternal": true, "label": "johnalwayssame.com", "meta": { @@ -21,6 +22,7 @@ exports[`ExternalUrl johnalwayssame.com with title 1`] = ` exports[`ExternalUrl netu.fanstream.us 1`] = ` [ { + "format": "unknown", "isExternal": true, "label": "netu.fanstream.us", "meta": { diff --git a/src/extractor/__snapshots__/ExtractorRegistry.test.ts.snap b/src/extractor/__snapshots__/ExtractorRegistry.test.ts.snap index bd42ff5..f762115 100644 --- a/src/extractor/__snapshots__/ExtractorRegistry.test.ts.snap +++ b/src/extractor/__snapshots__/ExtractorRegistry.test.ts.snap @@ -5,6 +5,7 @@ exports[`ExtractorRegistry returns error result from extractor 1`] = `[]`; exports[`ExtractorRegistry returns external URLs if enabled by config 1`] = ` [ { + "format": "unknown", "isExternal": true, "label": "mixdrop.ag", "meta": { @@ -22,6 +23,7 @@ exports[`ExtractorRegistry returns external url for error 1`] = ` { "error": [Error: Fetcher error: 403: Forbidden ], + "format": "unknown", "isExternal": true, "label": "Dropload", "meta": { @@ -38,6 +40,7 @@ exports[`ExtractorRegistry returns external url for error with title 1`] = ` { "error": [Error: Fetcher error: 403: Forbidden ], + "format": "unknown", "isExternal": true, "label": "Dropload", "meta": { diff --git a/src/extractor/__snapshots__/Fsst.test.ts.snap b/src/extractor/__snapshots__/Fsst.test.ts.snap index 6c6c174..c1013ae 100644 --- a/src/extractor/__snapshots__/Fsst.test.ts.snap +++ b/src/extractor/__snapshots__/Fsst.test.ts.snap @@ -3,6 +3,7 @@ exports[`Fsst Blood & Sinners 1`] = ` [ { + "format": "mp4", "label": "Fsst", "meta": { "countryCode": "de", @@ -13,6 +14,7 @@ exports[`Fsst Blood & Sinners 1`] = ` "url": "https://www.secvideo1.online/get_file/16/a135ab46b1243e41c0282c16d7cdcbcdf0faf7ee79/900000/900576/900576_360p.mp4/", }, { + "format": "mp4", "label": "Fsst", "meta": { "countryCode": "de", @@ -23,6 +25,7 @@ exports[`Fsst Blood & Sinners 1`] = ` "url": "https://www.secvideo1.online/get_file/16/801a42b7ac11f7e08101fe8c3cb537045ddf5c9b19/900000/900576/900576_720p.mp4/", }, { + "format": "mp4", "label": "Fsst", "meta": { "countryCode": "de", @@ -38,6 +41,7 @@ exports[`Fsst Blood & Sinners 1`] = ` exports[`Fsst Dead City 1`] = ` [ { + "format": "mp4", "label": "Fsst", "meta": { "countryCode": "de", @@ -48,6 +52,7 @@ exports[`Fsst Dead City 1`] = ` "url": "https://www.secvideo1.online/get_file/9/99510c9abde68b5e82b08cd2391724050c8e47cc86/901000/901994/901994_360p.mp4/", }, { + "format": "mp4", "label": "Fsst", "meta": { "countryCode": "de", @@ -58,6 +63,7 @@ exports[`Fsst Dead City 1`] = ` "url": "https://www.secvideo1.online/get_file/9/868ae0229e543e7a9a6f7cf4b3df88f45a49aa11fa/901000/901994/901994_720p.mp4/", }, { + "format": "mp4", "label": "Fsst", "meta": { "countryCode": "de", @@ -73,6 +79,7 @@ exports[`Fsst Dead City 1`] = ` exports[`Fsst How to Train Your Dragon 1`] = ` [ { + "format": "mp4", "label": "Fsst", "meta": { "countryCode": "de", diff --git a/src/extractor/__snapshots__/KinoGer.test.ts.snap b/src/extractor/__snapshots__/KinoGer.test.ts.snap index c2e8f92..63fafd8 100644 --- a/src/extractor/__snapshots__/KinoGer.test.ts.snap +++ b/src/extractor/__snapshots__/KinoGer.test.ts.snap @@ -3,6 +3,7 @@ exports[`KinoGer Blood & Sinners 1`] = ` [ { + "format": "hls", "label": "KinoGer", "meta": { "countryCode": "de", @@ -21,6 +22,7 @@ exports[`KinoGer Blood & Sinners 1`] = ` exports[`KinoGer Dead City 1`] = ` [ { + "format": "hls", "label": "KinoGer", "meta": { "countryCode": "de", diff --git a/src/extractor/__snapshots__/Mixdrop.test.ts.snap b/src/extractor/__snapshots__/Mixdrop.test.ts.snap index 2f0a88d..98b748a 100644 --- a/src/extractor/__snapshots__/Mixdrop.test.ts.snap +++ b/src/extractor/__snapshots__/Mixdrop.test.ts.snap @@ -5,6 +5,7 @@ exports[`Mixdrop deleted or expired file 1`] = `[]`; exports[`Mixdrop mixdrop.my /e/ 1`] = ` [ { + "format": "mp4", "label": "Mixdrop (via MediaFlow Proxy)", "meta": { "bytes": 1059806248, diff --git a/src/extractor/__snapshots__/Soaper.test.ts.snap b/src/extractor/__snapshots__/Soaper.test.ts.snap index 3cfa450..992ef3a 100644 --- a/src/extractor/__snapshots__/Soaper.test.ts.snap +++ b/src/extractor/__snapshots__/Soaper.test.ts.snap @@ -3,6 +3,7 @@ exports[`Soaper Black Mirror 1`] = ` [ { + "format": "hls", "label": "Soaper", "meta": { "countryCode": "en", @@ -19,6 +20,7 @@ exports[`Soaper Black Mirror 1`] = ` exports[`Soaper Full Metal Jacket 1`] = ` [ { + "format": "hls", "label": "Soaper", "meta": { "countryCode": "en", @@ -35,6 +37,7 @@ exports[`Soaper Full Metal Jacket 1`] = ` exports[`Soaper last of us s2e3 1`] = ` [ { + "format": "hls", "label": "Soaper", "meta": { "countryCode": "de", diff --git a/src/extractor/__snapshots__/SuperVideo.test.ts.snap b/src/extractor/__snapshots__/SuperVideo.test.ts.snap index 6037af2..28608e3 100644 --- a/src/extractor/__snapshots__/SuperVideo.test.ts.snap +++ b/src/extractor/__snapshots__/SuperVideo.test.ts.snap @@ -5,6 +5,7 @@ exports[`SuperVideo deleted or expired file 1`] = `[]`; exports[`SuperVideo embed only 1`] = ` [ { + "format": "hls", "label": "SuperVideo", "meta": { "countryCode": "it", @@ -20,6 +21,7 @@ exports[`SuperVideo embed only 1`] = ` exports[`SuperVideo supervideo.cc /e/ 1`] = ` [ { + "format": "hls", "label": "SuperVideo", "meta": { "bytes": 1073741824, @@ -37,6 +39,7 @@ exports[`SuperVideo supervideo.cc /e/ 1`] = ` exports[`SuperVideo supervideo.tv /embed-/ 1`] = ` [ { + "format": "hls", "label": "SuperVideo", "meta": { "bytes": 219571814, diff --git a/src/extractor/__snapshots__/VidSrc.test.ts.snap b/src/extractor/__snapshots__/VidSrc.test.ts.snap index f278642..61a4166 100644 --- a/src/extractor/__snapshots__/VidSrc.test.ts.snap +++ b/src/extractor/__snapshots__/VidSrc.test.ts.snap @@ -3,6 +3,7 @@ exports[`VidSrc Black Mirror 1`] = ` [ { + "format": "hls", "label": "VidSrc (CloudStream Pro)", "meta": { "countryCode": "en", @@ -19,6 +20,7 @@ exports[`VidSrc Black Mirror 1`] = ` exports[`VidSrc Full Metal Jacket 1`] = ` [ { + "format": "hls", "label": "VidSrc (CloudStream Pro)", "meta": { "countryCode": "en", diff --git a/src/types.ts b/src/types.ts index 123e4d5..84597a9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -33,13 +33,21 @@ export interface Meta { title?: string; } +export enum Format { + hls = 'hls', + mp4 = 'mp4', + unknown = 'unknown', +} + export interface UrlResult { url: URL; + format: Format; isExternal?: boolean; error?: unknown; label: string; sourceId: string; ttl?: number; meta: Meta; + notWebReady?: boolean; requestHeaders?: Record; } diff --git a/src/utils/StreamResolver.test.ts b/src/utils/StreamResolver.test.ts index bd6dc02..e7b7438 100644 --- a/src/utils/StreamResolver.test.ts +++ b/src/utils/StreamResolver.test.ts @@ -2,9 +2,9 @@ import { ContentType } from 'stremio-addon-sdk'; import winston from 'winston'; import { createExtractors, Extractor, ExtractorRegistry } from '../extractor'; import { StreamResolver } from './StreamResolver'; -import { Source, SourceResult, MeineCloud, MostraGuarda } from '../source'; -import { BlockedReason, CountryCode, UrlResult } from '../types'; -import { BlockedError, HttpError, NotFoundError, QueueIsFullError, TimeoutError, TooManyTimeoutsError, TooManyRequestsError } from '../error'; +import { MeineCloud, MostraGuarda, Source, SourceResult } from '../source'; +import { BlockedReason, CountryCode, Format, UrlResult } from '../types'; +import { BlockedError, HttpError, NotFoundError, QueueIsFullError, TimeoutError, TooManyRequestsError, TooManyTimeoutsError } from '../error'; import { ImdbId } from './id'; import { FetcherMock } from './FetcherMock'; import { createTestContext } from '../test'; @@ -92,6 +92,7 @@ describe('resolve', () => { [ { url: new URL('https://example.com'), + format: Format.unknown, isExternal: true, error: new BlockedError(BlockedReason.cloudflare_challenge, {}), label: 'hoster.com', @@ -102,6 +103,7 @@ describe('resolve', () => { }, { url: new URL('https://example.com'), + format: Format.unknown, isExternal: true, error: new BlockedError(BlockedReason.unknown, {}), label: 'hoster.com', @@ -112,6 +114,7 @@ describe('resolve', () => { }, { url: new URL('https://example.com'), + format: Format.unknown, isExternal: true, error: new TooManyRequestsError(10), label: 'hoster.com', @@ -122,6 +125,7 @@ describe('resolve', () => { }, { url: new URL('https://example.com'), + format: Format.unknown, isExternal: true, error: new TooManyTimeoutsError(), label: 'hoster.com', @@ -132,6 +136,7 @@ describe('resolve', () => { }, { url: new URL('https://example2.com'), + format: Format.unknown, isExternal: true, error: new TypeError(), label: 'hoster.com', @@ -142,6 +147,7 @@ describe('resolve', () => { }, { url: new URL('https://example2.com'), + format: Format.unknown, isExternal: true, error: new TimeoutError(), label: 'hoster.com', @@ -152,6 +158,7 @@ describe('resolve', () => { }, { url: new URL('https://example3.com'), + format: Format.unknown, isExternal: true, error: new QueueIsFullError(), label: 'hoster.com', @@ -162,6 +169,7 @@ describe('resolve', () => { }, { url: new URL('https://example4.com'), + format: Format.unknown, isExternal: true, error: new HttpError(500, 'Internal Server Error', { 'x-foo': 'bar' }), label: 'hoster.com', diff --git a/src/utils/StreamResolver.ts b/src/utils/StreamResolver.ts index 94b17d9..45b053c 100644 --- a/src/utils/StreamResolver.ts +++ b/src/utils/StreamResolver.ts @@ -1,7 +1,7 @@ import { ContentType, Stream } from 'stremio-addon-sdk'; import winston from 'winston'; import bytes from 'bytes'; -import { Context, UrlResult } from '../types'; +import { Context, Format, UrlResult } from '../types'; import { Source } from '../source'; import { BlockedError, @@ -9,8 +9,8 @@ import { NotFoundError, QueueIsFullError, TimeoutError, - TooManyTimeoutsError, TooManyRequestsError, + TooManyTimeoutsError, } from '../error'; import { flagFromCountryCode } from './language'; import { envGetAppName } from './env'; @@ -107,6 +107,7 @@ export class StreamResolver { title: this.buildTitle(ctx, urlResult), behaviorHints: { ...(urlResult.sourceId && { bingeGroup: `webstreamr-${urlResult.sourceId}` }), + ...((urlResult.format !== Format.mp4 || urlResult.url.protocol !== 'https:') && { notWebReady: true }), ...(urlResult.requestHeaders !== undefined && { notWebReady: true, proxyHeaders: { request: urlResult.requestHeaders }, diff --git a/src/utils/__snapshots__/StreamResolver.test.ts.snap b/src/utils/__snapshots__/StreamResolver.test.ts.snap index a7495c7..028ad2b 100644 --- a/src/utils/__snapshots__/StreamResolver.test.ts.snap +++ b/src/utils/__snapshots__/StreamResolver.test.ts.snap @@ -4,56 +4,72 @@ exports[`resolve adds error info 1`] = ` { "streams": [ { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "http://localhost/", "name": "WebStreamr 🇩🇪", "title": "🔗 hoster.com ⚠️ Request was blocked.", }, { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "http://localhost/", "name": "WebStreamr 🇩🇪", "title": "🔗 hoster.com ⚠️ Request was blocked.", }, { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "http://localhost/", "name": "WebStreamr 🇩🇪", "title": "🔗 hoster.com 🚦 Request was rate-limited. Please try again later or consider self-hosting.", }, { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "http://localhost/", "name": "WebStreamr 🇩🇪", "title": "🔗 hoster.com 🚦 Too many recent timeouts. Please try again later.", }, { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "http://localhost/", "name": "WebStreamr 🇩🇪", "title": "🔗 hoster.com ❌ Request failed. Request-id: test.", }, { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "http://localhost/", "name": "WebStreamr 🇩🇪", "title": "🔗 hoster.com 🐢 Request timed out.", }, { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "http://localhost/", "name": "WebStreamr 🇩🇪", "title": "🔗 hoster.com ⏳ Request queue is full. Please try again later or consider self-hosting.", }, { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "http://localhost/", "name": "WebStreamr 🇩🇪", "title": "🔗 hoster.com @@ -67,56 +83,72 @@ exports[`resolve adds error info 2`] = ` { "streams": [ { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "https://example.com/", "name": "WebStreamr 🇩🇪 ⚠️ external", "title": "🔗 hoster.com ⚠️ Request was blocked.", }, { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "https://example.com/", "name": "WebStreamr 🇩🇪 ⚠️ external", "title": "🔗 hoster.com ⚠️ Request was blocked.", }, { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "https://example.com/", "name": "WebStreamr 🇩🇪 ⚠️ external", "title": "🔗 hoster.com 🚦 Request was rate-limited. Please try again later or consider self-hosting.", }, { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "https://example.com/", "name": "WebStreamr 🇩🇪 ⚠️ external", "title": "🔗 hoster.com 🚦 Too many recent timeouts. Please try again later.", }, { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "https://example2.com/", "name": "WebStreamr 🇩🇪 ⚠️ external", "title": "🔗 hoster.com ❌ Request failed. Request-id: test.", }, { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "https://example2.com/", "name": "WebStreamr 🇩🇪 ⚠️ external", "title": "🔗 hoster.com 🐢 Request timed out.", }, { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "https://example3.com/", "name": "WebStreamr 🇩🇪 ⚠️ external", "title": "🔗 hoster.com ⏳ Request queue is full. Please try again later or consider self-hosting.", }, { - "behaviorHints": {}, + "behaviorHints": { + "notWebReady": true, + }, "externalUrl": "https://example4.com/", "name": "WebStreamr 🇩🇪 ⚠️ external", "title": "🔗 hoster.com @@ -164,6 +196,7 @@ exports[`resolve returns sorted results 1`] = ` { "behaviorHints": { "bingeGroup": "webstreamr-dropload_de", + "notWebReady": true, "videoSize": 1395864371, }, "name": "WebStreamr 🇩🇪 1080p", @@ -174,6 +207,7 @@ exports[`resolve returns sorted results 1`] = ` { "behaviorHints": { "bingeGroup": "webstreamr-dropload_it", + "notWebReady": true, "videoSize": 1181116006, }, "name": "WebStreamr 🇮🇹 720p", @@ -184,6 +218,7 @@ exports[`resolve returns sorted results 1`] = ` { "behaviorHints": { "bingeGroup": "webstreamr-supervideo_it", + "notWebReady": true, "videoSize": 1181116006, }, "name": "WebStreamr 🇮🇹 720p", @@ -194,6 +229,7 @@ exports[`resolve returns sorted results 1`] = ` { "behaviorHints": { "bingeGroup": "webstreamr-supervideo_de", + "notWebReady": true, "videoSize": 1073741824, }, "name": "WebStreamr 🇩🇪 720p", @@ -240,6 +276,7 @@ exports[`resolve returns sorted results 2`] = ` { "behaviorHints": { "bingeGroup": "webstreamr-dropload_de", + "notWebReady": true, "videoSize": 1395864371, }, "name": "WebStreamr 🇩🇪 1080p", @@ -250,6 +287,7 @@ exports[`resolve returns sorted results 2`] = ` { "behaviorHints": { "bingeGroup": "webstreamr-dropload_it", + "notWebReady": true, "videoSize": 1181116006, }, "name": "WebStreamr 🇮🇹 720p", @@ -260,6 +298,7 @@ exports[`resolve returns sorted results 2`] = ` { "behaviorHints": { "bingeGroup": "webstreamr-supervideo_it", + "notWebReady": true, "videoSize": 1181116006, }, "name": "WebStreamr 🇮🇹 720p", @@ -270,6 +309,7 @@ exports[`resolve returns sorted results 2`] = ` { "behaviorHints": { "bingeGroup": "webstreamr-supervideo_de", + "notWebReady": true, "videoSize": 1073741824, }, "name": "WebStreamr 🇩🇪 720p", @@ -311,6 +351,7 @@ exports[`resolve returns sorted results 2`] = ` { "behaviorHints": { "bingeGroup": "webstreamr-external_de", + "notWebReady": true, }, "externalUrl": "https://mixdrop.ag/e/3nzwveprim63or6", "name": "WebStreamr 🇩🇪 ⚠️ external", @@ -319,6 +360,7 @@ exports[`resolve returns sorted results 2`] = ` { "behaviorHints": { "bingeGroup": "webstreamr-external_it", + "notWebReady": true, }, "externalUrl": "https://mixdrop.ag/e/vk196d6xfzwwo1", "name": "WebStreamr 🇮🇹 ⚠️ external",