Add vidsrc.su

This commit is contained in:
TPN 2025-01-10 10:12:25 +00:00
parent f5a8df4c01
commit ef7a4c8bde
5 changed files with 712 additions and 534 deletions

View file

@ -76,7 +76,7 @@
"spinnies": "^0.5.1",
"tsc-alias": "^1.8.10",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.7.2",
"typescript": "^5.7.3",
"vite": "^5.4.11",
"vite-node": "^1.6.0",
"vite-plugin-dts": "^3.9.1",
@ -87,8 +87,9 @@
"cookie": "^0.6.0",
"crypto-js": "^4.2.0",
"form-data": "^4.0.1",
"hls-parser": "^0.13.3",
"hls-parser": "^0.13.5",
"iso-639-1": "^3.1.3",
"json5": "^2.2.3",
"nanoid": "^3.3.8",
"node-fetch": "^3.3.2",
"set-cookie-parser": "^2.7.1",

File diff suppressed because it is too large Load diff

View file

@ -95,6 +95,7 @@ async function runActualScraping(
if (source.type === 'embed') {
return providers.runEmbedScraper({
disableOpensubtitles: true,
url: options.url,
id: source.id,
});
@ -110,6 +111,7 @@ async function runActualScraping(
}
return providers.runSourceScraper({
disableOpensubtitles: true,
media,
id: source.id,
});

View file

@ -31,6 +31,7 @@ import { remotestreamScraper } from '@/providers/sources/remotestream';
import { showboxScraper } from '@/providers/sources/showbox/index';
import { tugaflixScraper } from '@/providers/sources/tugaflix';
import { vidsrcScraper } from '@/providers/sources/vidsrc/index';
import { vidsrcsuScraper } from '@/providers/sources/vidsrcsu';
import { whvxScraper } from '@/providers/sources/whvx';
import { zoechipScraper } from '@/providers/sources/zoechip';
@ -104,6 +105,7 @@ export function gatherAllSources(): Array<Sourcerer> {
fsharetvScraper,
redStarScraper,
bombtheirishScraper,
vidsrcsuScraper,
];
}

View file

@ -0,0 +1,59 @@
import JSON5 from 'json5';
import { flags } from '@/entrypoint/utils/targets';
import { SourcererOutput, makeSourcerer } from '@/providers/base';
import { Caption, labelToLanguageCode } from '@/providers/captions';
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
import { NotFoundError } from '@/utils/errors';
async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promise<SourcererOutput> {
const embedPage = await ctx.proxiedFetcher(
`https://vidsrc.su/embed/${ctx.media.type === 'movie' ? `movie/${ctx.media.tmdbId}` : `tv/${ctx.media.tmdbId}/${ctx.media.season.number}/${ctx.media.episode.number}`}`,
);
const serverDataMatch = embedPage.match(/const fixedServers = +(\[.*?\])/s);
if (!serverDataMatch[1]) throw new NotFoundError('No data found');
// const servers: { label: string; url: string }[] = JSON.parse(serverDataMatch[1].replace(/([a-zA-Z0-9_]+): /g, '"$1":').replace(/'/g, '"').replace(/,\s*\]$/, ']'))
const servers: { label: string; url: string }[] = JSON5.parse(serverDataMatch[1]);
let playlist;
// we only want flixhq which is server 1 and server 2
servers.forEach((server) => {
if (['Server 1', 'Server 2'].includes(server.label) && server.url) playlist = server.url;
});
if (!playlist) throw new NotFoundError('No flixhq playlist found');
const captionsDataMatch = embedPage.match(/const subtitles = +(\[.*?\])/s);
const captions: Caption[] = [];
if (captionsDataMatch[1]) {
const captionsData: { label: string; file: string }[] = JSON5.parse(captionsDataMatch[1]);
for (const caption of captionsData) {
const language = labelToLanguageCode(caption.label);
if (!language) continue;
captions.push({
id: caption.file,
url: caption.file,
type: 'vtt',
hasCorsRestrictions: false,
language,
});
}
}
return {
embeds: [],
stream: [
{
id: 'primary',
playlist,
type: 'hls',
flags: [flags.CORS_ALLOWED],
captions,
},
],
};
}
export const vidsrcsuScraper = makeSourcerer({
id: 'vidsrcsu',
name: 'vidsrc.su (FlixHQ)',
rank: 229,
flags: [flags.CORS_ALLOWED],
scrapeMovie: comboScraper,
scrapeShow: comboScraper,
});