mirror of
https://github.com/p-stream/providers.git
synced 2026-04-21 13:42:18 +00:00
add wyzie subs
This commit is contained in:
parent
1aa5a7c554
commit
3d9efcc8f8
6 changed files with 138 additions and 31 deletions
|
|
@ -93,7 +93,8 @@
|
||||||
"nanoid": "^3.3.8",
|
"nanoid": "^3.3.8",
|
||||||
"node-fetch": "^3.3.2",
|
"node-fetch": "^3.3.2",
|
||||||
"set-cookie-parser": "^2.7.1",
|
"set-cookie-parser": "^2.7.1",
|
||||||
"unpacker": "^1.0.1"
|
"unpacker": "^1.0.1",
|
||||||
|
"wyzie-lib": "^2.2.1"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.14.4"
|
"packageManager": "pnpm@9.14.4"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,9 @@ importers:
|
||||||
unpacker:
|
unpacker:
|
||||||
specifier: ^1.0.1
|
specifier: ^1.0.1
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
|
wyzie-lib:
|
||||||
|
specifier: ^2.2.1
|
||||||
|
version: 2.2.1
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@nabla/vite-plugin-eslint':
|
'@nabla/vite-plugin-eslint':
|
||||||
specifier: ^2.0.5
|
specifier: ^2.0.5
|
||||||
|
|
@ -2525,6 +2528,9 @@ packages:
|
||||||
utf-8-validate:
|
utf-8-validate:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
wyzie-lib@2.2.1:
|
||||||
|
resolution: {integrity: sha512-oZtJnCTQCqLZimlD1Ex195+8e21/G5BWhixCE5/4Of77AI9igmIQCo/thWngOsdOufcnzvzTPYkWoNDxHc5lQg==}
|
||||||
|
|
||||||
y18n@5.0.8:
|
y18n@5.0.8:
|
||||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
@ -5225,6 +5231,8 @@ snapshots:
|
||||||
|
|
||||||
ws@8.18.0: {}
|
ws@8.18.0: {}
|
||||||
|
|
||||||
|
wyzie-lib@2.2.1: {}
|
||||||
|
|
||||||
y18n@5.0.8: {}
|
y18n@5.0.8: {}
|
||||||
|
|
||||||
yallist@4.0.0: {}
|
yallist@4.0.0: {}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ export type Caption = {
|
||||||
type: CaptionType;
|
type: CaptionType;
|
||||||
id: string; // only unique per stream
|
id: string; // only unique per stream
|
||||||
opensubtitles?: boolean;
|
opensubtitles?: boolean;
|
||||||
|
wyziesubs?: boolean;
|
||||||
url: string;
|
url: string;
|
||||||
hasCorsRestrictions: boolean;
|
hasCorsRestrictions: boolean;
|
||||||
language: string;
|
language: string;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import { NotFoundError } from '@/utils/errors';
|
||||||
import { addOpenSubtitlesCaptions } from '@/utils/opensubtitles';
|
import { addOpenSubtitlesCaptions } from '@/utils/opensubtitles';
|
||||||
import { requiresProxy, setupProxy } from '@/utils/proxy';
|
import { requiresProxy, setupProxy } from '@/utils/proxy';
|
||||||
import { isValidStream, validatePlayableStreams } from '@/utils/valid';
|
import { isValidStream, validatePlayableStreams } from '@/utils/valid';
|
||||||
|
import { addWyzieCaptions } from '@/utils/wyziesubs';
|
||||||
|
|
||||||
export type IndividualSourceRunnerOptions = {
|
export type IndividualSourceRunnerOptions = {
|
||||||
features: FeatureMap;
|
features: FeatureMap;
|
||||||
|
|
@ -92,18 +93,33 @@ export async function scrapeInvidualSource(
|
||||||
if (playableStreams.length === 0) throw new NotFoundError('No playable streams found');
|
if (playableStreams.length === 0) throw new NotFoundError('No playable streams found');
|
||||||
|
|
||||||
// opensubtitles
|
// opensubtitles
|
||||||
if (!ops.disableOpensubtitles)
|
if (!ops.disableOpensubtitles) {
|
||||||
for (const playableStream of playableStreams) {
|
for (const playableStream of playableStreams) {
|
||||||
playableStream.captions = await addOpenSubtitlesCaptions(
|
// Try Wyzie subs first
|
||||||
playableStream.captions,
|
if (ops.media.imdbId) {
|
||||||
ops,
|
playableStream.captions = await addWyzieCaptions(
|
||||||
btoa(
|
playableStream.captions,
|
||||||
`${ops.media.imdbId}${
|
ops.media.tmdbId,
|
||||||
ops.media.type === 'show' ? `.${ops.media.season.number}.${ops.media.episode.number}` : ''
|
ops.media.imdbId,
|
||||||
}`,
|
ops.media.type === 'show' ? ops.media.season.number : undefined,
|
||||||
),
|
ops.media.type === 'show' ? ops.media.episode.number : undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Fall back to OpenSubtitles if no Wyzie subs found
|
||||||
|
if (!playableStream.captions.some((caption) => caption.wyziesubs)) {
|
||||||
|
playableStream.captions = await addOpenSubtitlesCaptions(
|
||||||
|
playableStream.captions,
|
||||||
|
ops,
|
||||||
|
btoa(
|
||||||
|
`${ops.media.imdbId}${
|
||||||
|
ops.media.type === 'show' ? `.${ops.media.season.number}.${ops.media.episode.number}` : ''
|
||||||
|
}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
output.stream = playableStreams;
|
output.stream = playableStreams;
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import { reorderOnIdList } from '@/utils/list';
|
||||||
import { addOpenSubtitlesCaptions } from '@/utils/opensubtitles';
|
import { addOpenSubtitlesCaptions } from '@/utils/opensubtitles';
|
||||||
import { requiresProxy, setupProxy } from '@/utils/proxy';
|
import { requiresProxy, setupProxy } from '@/utils/proxy';
|
||||||
import { isValidStream, validatePlayableStream } from '@/utils/valid';
|
import { isValidStream, validatePlayableStream } from '@/utils/valid';
|
||||||
|
import { addWyzieCaptions } from '@/utils/wyziesubs';
|
||||||
|
|
||||||
export type RunOutput = {
|
export type RunOutput = {
|
||||||
sourceId: string;
|
sourceId: string;
|
||||||
|
|
@ -116,16 +117,31 @@ export async function runAllProviders(list: ProviderList, ops: ProviderRunnerOpt
|
||||||
if (!playableStream) throw new NotFoundError('No streams found');
|
if (!playableStream) throw new NotFoundError('No streams found');
|
||||||
|
|
||||||
// opensubtitles
|
// opensubtitles
|
||||||
if (!ops.disableOpensubtitles)
|
if (!ops.disableOpensubtitles) {
|
||||||
playableStream.captions = await addOpenSubtitlesCaptions(
|
if (ops.media.imdbId) {
|
||||||
playableStream.captions,
|
// Try Wyzie subs first
|
||||||
ops,
|
playableStream.captions = await addWyzieCaptions(
|
||||||
btoa(
|
playableStream.captions,
|
||||||
`${ops.media.imdbId}${
|
ops.media.tmdbId,
|
||||||
ops.media.type === 'show' ? `.${ops.media.season.number}.${ops.media.episode.number}` : ''
|
ops.media.imdbId,
|
||||||
}`,
|
ops.media.type === 'show' ? ops.media.season.number : undefined,
|
||||||
),
|
ops.media.type === 'show' ? ops.media.episode.number : undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Fall back to OpenSubtitles if no Wyzie subs found
|
||||||
|
if (!playableStream.captions.some((caption) => caption.wyziesubs)) {
|
||||||
|
playableStream.captions = await addOpenSubtitlesCaptions(
|
||||||
|
playableStream.captions,
|
||||||
|
ops,
|
||||||
|
btoa(
|
||||||
|
`${ops.media.imdbId}${
|
||||||
|
ops.media.type === 'show' ? `.${ops.media.season.number}.${ops.media.episode.number}` : ''
|
||||||
|
}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sourceId: source.id,
|
sourceId: source.id,
|
||||||
|
|
@ -179,16 +195,31 @@ export async function runAllProviders(list: ProviderList, ops: ProviderRunnerOpt
|
||||||
if (!playableStream) throw new NotFoundError('No streams found');
|
if (!playableStream) throw new NotFoundError('No streams found');
|
||||||
|
|
||||||
// opensubtitles
|
// opensubtitles
|
||||||
if (!ops.disableOpensubtitles)
|
if (!ops.disableOpensubtitles) {
|
||||||
playableStream.captions = await addOpenSubtitlesCaptions(
|
if (ops.media.imdbId) {
|
||||||
playableStream.captions,
|
// Try Wyzie subs first
|
||||||
ops,
|
playableStream.captions = await addWyzieCaptions(
|
||||||
btoa(
|
playableStream.captions,
|
||||||
`${ops.media.imdbId}${
|
ops.media.tmdbId,
|
||||||
ops.media.type === 'show' ? `.${ops.media.season.number}.${ops.media.episode.number}` : ''
|
ops.media.imdbId,
|
||||||
}`,
|
ops.media.type === 'show' ? ops.media.season.number : undefined,
|
||||||
),
|
ops.media.type === 'show' ? ops.media.episode.number : undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Fall back to OpenSubtitles if no Wyzie subs found
|
||||||
|
if (!playableStream.captions.some((caption) => caption.wyziesubs)) {
|
||||||
|
playableStream.captions = await addOpenSubtitlesCaptions(
|
||||||
|
playableStream.captions,
|
||||||
|
ops,
|
||||||
|
btoa(
|
||||||
|
`${ops.media.imdbId}${
|
||||||
|
ops.media.type === 'show' ? `.${ops.media.season.number}.${ops.media.episode.number}` : ''
|
||||||
|
}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
embedOutput.stream = [playableStream];
|
embedOutput.stream = [playableStream];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const updateParams: UpdateEvent = {
|
const updateParams: UpdateEvent = {
|
||||||
|
|
|
||||||
50
src/utils/wyziesubs.ts
Normal file
50
src/utils/wyziesubs.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { type SubtitleData, searchSubtitles } from 'wyzie-lib';
|
||||||
|
|
||||||
|
import { Caption } from '@/providers/captions';
|
||||||
|
|
||||||
|
export async function addWyzieCaptions(
|
||||||
|
captions: Caption[],
|
||||||
|
tmdbId: string | number,
|
||||||
|
imdbId: string,
|
||||||
|
season?: number,
|
||||||
|
episode?: number,
|
||||||
|
): Promise<Caption[]> {
|
||||||
|
try {
|
||||||
|
const searchParams: any = {
|
||||||
|
format: 'srt',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prefer TMDB ID if available, otherwise use IMDB ID
|
||||||
|
if (tmdbId) {
|
||||||
|
// Convert TMDB ID to number if it's a string
|
||||||
|
searchParams.tmdb_id = typeof tmdbId === 'string' ? parseInt(tmdbId, 10) : tmdbId;
|
||||||
|
} else if (imdbId) {
|
||||||
|
// Remove 'tt' prefix from IMDB ID if present
|
||||||
|
searchParams.imdb_id = imdbId.replace(/^tt/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add season and episode if provided (for TV shows)
|
||||||
|
if (season && episode) {
|
||||||
|
searchParams.season = season;
|
||||||
|
searchParams.episode = episode;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Searching Wyzie subtitles with params:', searchParams);
|
||||||
|
const wyzieSubtitles: SubtitleData[] = await searchSubtitles(searchParams);
|
||||||
|
console.log('Found Wyzie subtitles:', wyzieSubtitles);
|
||||||
|
|
||||||
|
const wyzieCaptions: Caption[] = wyzieSubtitles.map((subtitle) => ({
|
||||||
|
id: subtitle.id,
|
||||||
|
url: subtitle.url,
|
||||||
|
type: subtitle.format as 'srt' | 'vtt',
|
||||||
|
hasCorsRestrictions: false,
|
||||||
|
language: subtitle.language,
|
||||||
|
wyziesubs: true,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return [...captions, ...wyzieCaptions];
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching Wyzie subtitles:', error);
|
||||||
|
return captions;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue