chore: improve results format and refactor name/title generation

This commit is contained in:
WebStreamr 2025-06-02 15:31:15 +00:00
parent 120fb2896f
commit e4dd16e9d1
No known key found for this signature in database
4 changed files with 103 additions and 68 deletions

View file

@ -5,6 +5,7 @@ import bytes from 'bytes';
import { Context, UrlResult } from '../types';
import { Handler } from '../handler';
import { NotFoundError } from '../error';
import { languageFromCountryCode } from './languageFromCountryCode';
export class StreamResolver {
private readonly logger: winston.Logger;
@ -68,51 +69,57 @@ export class StreamResolver {
this.logger.info(`Return ${urlResults.length} streams`, ctx);
streams.push(
...urlResults.map((urlResult) => {
let name = 'WebStreamr';
if (urlResult.meta.countryCode) {
name += ` ${flag(urlResult.meta.countryCode)}`;
}
if (urlResult.meta.height) {
name += ` ${urlResult.meta.height}p`;
}
if (urlResult.isExternal) {
name += ` external`;
}
const titleSecondLineEntries: string[] = [];
if (urlResult.meta.bytes) {
titleSecondLineEntries.push(`💾 ${bytes.format(urlResult.meta.bytes, { unitSeparator: ' ' })}`);
}
titleSecondLineEntries.push(`⚙️ ${urlResult.label}`);
const titleLines = [];
if (urlResult.meta.title) {
titleLines.push(urlResult.meta.title);
}
titleLines.push(titleSecondLineEntries.join(' '));
if (urlResult.blocked) {
titleLines.push('Request was blocked.');
}
const title = titleLines.join('\n');
return {
[urlResult.isExternal ? 'externalUrl' : 'url']: urlResult.url.href,
name,
title,
behaviorHints: {
...(urlResult.sourceId && { bingeGroup: `webstreamr-${urlResult.sourceId}` }),
...(urlResult.requestHeaders !== undefined && {
notWebReady: true,
proxyHeaders: { request: urlResult.requestHeaders },
}),
...(urlResult.meta.bytes && { videoSize: urlResult.meta.bytes }),
},
};
}),
...urlResults.map(urlResult => ({
[urlResult.isExternal ? 'externalUrl' : 'url']: urlResult.url.href,
name: this.buildName(urlResult),
title: this.buildTitle(urlResult),
behaviorHints: {
...(urlResult.sourceId && { bingeGroup: `webstreamr-${urlResult.sourceId}` }),
...(urlResult.requestHeaders !== undefined && {
notWebReady: true,
proxyHeaders: { request: urlResult.requestHeaders },
}),
...(urlResult.meta.bytes && { videoSize: urlResult.meta.bytes }),
},
})),
);
return streams;
};
private readonly buildName = (urlResult: UrlResult): string => {
let name = process.env['MANIFEST_NAME'] || 'WebStreamr';
name += urlResult.meta.height ? ` ${urlResult.meta.height}P` : ' N/A';
if (urlResult.isExternal) {
name += ` ⚠️ external`;
}
return name;
};
private readonly buildTitle = (urlResult: UrlResult): string => {
const titleLines = [];
if (urlResult.meta.title) {
titleLines.push(`📂 ${urlResult.meta.title}`);
}
if (urlResult.meta.bytes) {
titleLines.push(`💾 ${bytes.format(urlResult.meta.bytes, { unitSeparator: ' ' })}`);
}
if (urlResult.meta.countryCode) {
titleLines.push(`🌐 ${languageFromCountryCode(urlResult.meta.countryCode)} ${flag(urlResult.meta.countryCode)}`);
}
titleLines.push(`🔗 ${urlResult.label}`);
if (urlResult.blocked) {
titleLines.push('⚠️ Request was blocked.');
}
return titleLines.join('\n');
};
}

View file

@ -5,9 +5,10 @@ exports[`resolve adds Cloudflare blocked info 1`] = `
{
"behaviorHints": {},
"externalUrl": "https://example.com/",
"name": "WebStreamr 🇩🇪 external",
"title": "⚙️ example.com
Request was blocked.",
"name": "WebStreamr N/A ⚠️ external",
"title": "🌐 German 🇩🇪
🔗 example.com
⚠️ Request was blocked.",
},
]
`;
@ -19,9 +20,11 @@ exports[`resolve returns sorted results 1`] = `
"bingeGroup": "webstreamr-dropload_de",
"videoSize": 1395864371,
},
"name": "WebStreamr 🇩🇪 1080p",
"title": "des-teufels-bad-2024
💾 1.3 GB ⚙️ Dropload",
"name": "WebStreamr 1080P",
"title": "📂 des-teufels-bad-2024
💾 1.3 GB
🌐 German 🇩🇪
🔗 Dropload",
"url": "https://srv27.dropload.io/hls2/01/00197/lyo2h1snpe5c_h/master.m3u8?t=qTZsRGIMnUjXsQ4o2LRLlsT4tGG1AdJrRBRDGttNLPM&s=1746903744&e=14400&f=987607&i=0.0&sp=0&ii=130.61.236.204",
},
{
@ -29,9 +32,11 @@ exports[`resolve returns sorted results 1`] = `
"bingeGroup": "webstreamr-dropload_it",
"videoSize": 1181116006,
},
"name": "WebStreamr 🇮🇹 720p",
"title": "the-devils-bath-2024-sd-sub-ita
💾 1.1 GB ⚙️ Dropload",
"name": "WebStreamr 720P",
"title": "📂 the-devils-bath-2024-sd-sub-ita
💾 1.1 GB
🌐 Italian 🇮🇹
🔗 Dropload",
"url": "https://srv34.dropload.io/hls2/01/00200/xsr90y2ltdyx_h/master.m3u8?t=avFOZ-10hDxo6__iaoSUrq7o4yY3ldLw6XDlXxpXF8E&s=1747059001&e=14400&f=1004116&srv=srv24&i=0.0&sp=0&ii=130.61.236.204&p1=srv24&p2=srv24",
},
{
@ -39,9 +44,11 @@ exports[`resolve returns sorted results 1`] = `
"bingeGroup": "webstreamr-supervideo_it",
"videoSize": 1181116006,
},
"name": "WebStreamr 🇮🇹 720p",
"title": "the devils bath 2024 sub ita
💾 1.1 GB ⚙️ SuperVideo",
"name": "WebStreamr 720P",
"title": "📂 the devils bath 2024 sub ita
💾 1.1 GB
🌐 Italian 🇮🇹
🔗 SuperVideo",
"url": "https://hfs279.serversicuro.cc/hls/,dnzpejj427g4a3gyvbth53rxqewqgqqzp3wr6zwutysvud7zroar3cb75d3q,.urlset/master.m3u8",
},
{
@ -49,9 +56,11 @@ exports[`resolve returns sorted results 1`] = `
"bingeGroup": "webstreamr-supervideo_de",
"videoSize": 1073741824,
},
"name": "WebStreamr 🇩🇪 720p",
"title": "des teufels bad 2024
💾 1 GB ⚙️ SuperVideo",
"name": "WebStreamr 720P",
"title": "📂 des teufels bad 2024
💾 1 GB
🌐 German 🇩🇪
🔗 SuperVideo",
"url": "https://hfs290.serversicuro.cc/hls/,dnzpfi3d27g4a3gyvbmh5klwtl65qh654hyjtgupd6p56thhyqu6ra3olbfa,.urlset/master.m3u8",
},
{
@ -64,9 +73,10 @@ exports[`resolve returns sorted results 1`] = `
},
},
},
"name": "WebStreamr 🇩🇪",
"title": "des-teufels-bad-2024
⚙️ DoodStream",
"name": "WebStreamr N/A",
"title": "📂 des-teufels-bad-2024
🌐 German 🇩🇪
🔗 DoodStream",
"url": "https://aa360cc.cloudatacdn.com/u5kjv4jxytd3sdgge5uogji5dg4huat2pxrm2qibdbm5rtpmbzgb5tornooa/k9wk0js17e~mocked-random-string?token=7uebebipnnhusa4xnyea1er4&expiry=639837296000",
},
{
@ -79,9 +89,10 @@ exports[`resolve returns sorted results 1`] = `
},
},
},
"name": "WebStreamr 🇮🇹",
"title": "the-devils-bath-2024-sd-sub-ita
⚙️ DoodStream",
"name": "WebStreamr N/A",
"title": "📂 the-devils-bath-2024-sd-sub-ita
🌐 Italian 🇮🇹
🔗 DoodStream",
"url": "https://kk892as.cloudatacdn.com/u5kj7j7s27d3sdgge5woezkbi4pu672wktq3aqujw47rbpl3xog2gtqnw2xa/awn9rgotuu~mocked-random-string?token=aw2v2d8uhbrj2ky54d573ujk&expiry=639837296000",
},
{
@ -89,16 +100,18 @@ exports[`resolve returns sorted results 1`] = `
"bingeGroup": "webstreamr-external_de",
},
"externalUrl": "https://mixdrop.ag/e/3nzwveprim63or6",
"name": "WebStreamr 🇩🇪 external",
"title": "⚙️ mixdrop.ag",
"name": "WebStreamr N/A ⚠️ external",
"title": "🌐 German 🇩🇪
🔗 mixdrop.ag",
},
{
"behaviorHints": {
"bingeGroup": "webstreamr-external_it",
},
"externalUrl": "https://mixdrop.ag/e/vk196d6xfzwwo1",
"name": "WebStreamr 🇮🇹 external",
"title": "⚙️ mixdrop.ag",
"name": "WebStreamr N/A ⚠️ external",
"title": "🌐 Italian 🇮🇹
🔗 mixdrop.ag",
},
]
`;

View file

@ -2,5 +2,6 @@ export * from './Fetcher';
export * from './StreamResolver';
export * from './embed';
export * from './imdb';
export * from './languageFromCountryCode';
export * from './manifest';
export * from './tmdb';

View file

@ -0,0 +1,14 @@
import { CountryCode } from '../types';
const countryCodeLanguageMap: Record<CountryCode, string> = {
de: 'German',
en: 'English',
es: 'Castilian Spanish',
fr: 'French',
it: 'Italian',
mx: 'Latin American Spanish',
};
export const languageFromCountryCode = (countryCode: CountryCode) => {
return countryCodeLanguageMap[countryCode];
};