mirror of
https://github.com/p-stream/providers.git
synced 2026-04-21 05:02:25 +00:00
add 1stream
This commit is contained in:
parent
e05d259b02
commit
045e3d4e59
4 changed files with 403 additions and 0 deletions
|
|
@ -19,6 +19,17 @@ import { mp4hydraScraper } from '@/providers/sources/mp4hydra';
|
||||||
import { tugaflixScraper } from '@/providers/sources/tugaflix';
|
import { tugaflixScraper } from '@/providers/sources/tugaflix';
|
||||||
import { vidsrcsuScraper } from '@/providers/sources/vidsrcsu';
|
import { vidsrcsuScraper } from '@/providers/sources/vidsrcsu';
|
||||||
|
|
||||||
|
import {
|
||||||
|
oneServerAnimepaheEmbed,
|
||||||
|
oneServerAnizoneEmbed,
|
||||||
|
oneServerAutoembedEmbed,
|
||||||
|
oneServerFlixhqEmbed,
|
||||||
|
oneServerFoxstreamEmbed,
|
||||||
|
oneServerGokuEmbed,
|
||||||
|
oneServerHianimeEmbed,
|
||||||
|
oneServerPrimeboxEmbed,
|
||||||
|
oneServerVidsrcsuEmbed,
|
||||||
|
} from './embeds/1server';
|
||||||
import {
|
import {
|
||||||
autoembedBengaliScraper,
|
autoembedBengaliScraper,
|
||||||
autoembedEnglishScraper,
|
autoembedEnglishScraper,
|
||||||
|
|
@ -66,6 +77,7 @@ import {
|
||||||
xprimePrimenetEmbed,
|
xprimePrimenetEmbed,
|
||||||
xprimeStreamboxEmbed,
|
xprimeStreamboxEmbed,
|
||||||
} from './embeds/xprime';
|
} from './embeds/xprime';
|
||||||
|
import { oneServerScraper } from './sources/1server';
|
||||||
import { EightStreamScraper } from './sources/8stream';
|
import { EightStreamScraper } from './sources/8stream';
|
||||||
import { coitusScraper } from './sources/coitus';
|
import { coitusScraper } from './sources/coitus';
|
||||||
import { ConsumetScraper } from './sources/consumet';
|
import { ConsumetScraper } from './sources/consumet';
|
||||||
|
|
@ -115,6 +127,7 @@ export function gatherAllSources(): Array<Sourcerer> {
|
||||||
xprimeScraper,
|
xprimeScraper,
|
||||||
ConsumetScraper,
|
ConsumetScraper,
|
||||||
hianimeScraper,
|
hianimeScraper,
|
||||||
|
oneServerScraper,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -173,5 +186,14 @@ export function gatherAllEmbeds(): Array<Embed> {
|
||||||
hianimeHd2DubEmbed,
|
hianimeHd2DubEmbed,
|
||||||
hianimeHd1SubEmbed,
|
hianimeHd1SubEmbed,
|
||||||
hianimeHd2SubEmbed,
|
hianimeHd2SubEmbed,
|
||||||
|
oneServerAutoembedEmbed,
|
||||||
|
oneServerVidsrcsuEmbed,
|
||||||
|
oneServerPrimeboxEmbed,
|
||||||
|
oneServerFoxstreamEmbed,
|
||||||
|
oneServerFlixhqEmbed,
|
||||||
|
oneServerGokuEmbed,
|
||||||
|
oneServerHianimeEmbed,
|
||||||
|
oneServerAnimepaheEmbed,
|
||||||
|
oneServerAnizoneEmbed,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
295
src/providers/embeds/1server.ts
Normal file
295
src/providers/embeds/1server.ts
Normal file
|
|
@ -0,0 +1,295 @@
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
import { flags } from '@/entrypoint/utils/targets';
|
||||||
|
import { EmbedOutput, makeEmbed } from '@/providers/base';
|
||||||
|
import { NotFoundError } from '@/utils/errors';
|
||||||
|
|
||||||
|
const baseUrl = 'https://flix.1anime.app';
|
||||||
|
|
||||||
|
const languageMap: Record<string, string> = {
|
||||||
|
'chinese - hong kong': 'zh',
|
||||||
|
'chinese - traditional': 'zh',
|
||||||
|
czech: 'cs',
|
||||||
|
danish: 'da',
|
||||||
|
dutch: 'nl',
|
||||||
|
english: 'en',
|
||||||
|
'english - sdh': 'en',
|
||||||
|
finnish: 'fi',
|
||||||
|
french: 'fr',
|
||||||
|
german: 'de',
|
||||||
|
greek: 'el',
|
||||||
|
hungarian: 'hu',
|
||||||
|
italian: 'it',
|
||||||
|
korean: 'ko',
|
||||||
|
norwegian: 'no',
|
||||||
|
polish: 'pl',
|
||||||
|
portuguese: 'pt',
|
||||||
|
'portuguese - brazilian': 'pt',
|
||||||
|
romanian: 'ro',
|
||||||
|
'spanish - european': 'es',
|
||||||
|
'spanish - latin american': 'es',
|
||||||
|
swedish: 'sv',
|
||||||
|
turkish: 'tr',
|
||||||
|
اَلْعَرَبِيَّةُ: 'ar',
|
||||||
|
বাংলা: 'bn',
|
||||||
|
filipino: 'tl',
|
||||||
|
indonesia: 'id',
|
||||||
|
اردو: 'ur',
|
||||||
|
};
|
||||||
|
|
||||||
|
function createProxyUrl(originalUrl: string, referer?: string): string {
|
||||||
|
const encodedUrl = encodeURIComponent(originalUrl);
|
||||||
|
const encodedHeaders = encodeURIComponent(
|
||||||
|
JSON.stringify({
|
||||||
|
referer,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return `https://proxy.fifthwit.net/m3u8-proxy?url=${encodedUrl}&headers=${encodedHeaders}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function processProxiedURL(url: string): string {
|
||||||
|
// Handle orbitproxy URLs
|
||||||
|
if (url.includes('orbitproxy')) {
|
||||||
|
try {
|
||||||
|
const urlParts = url.split(/orbitproxy\.[^/]+\//);
|
||||||
|
if (urlParts.length >= 2) {
|
||||||
|
const encryptedPart = urlParts[1].split('.m3u8')[0];
|
||||||
|
try {
|
||||||
|
const decodedData =
|
||||||
|
typeof window !== 'undefined'
|
||||||
|
? atob(encryptedPart)
|
||||||
|
: Buffer.from(encryptedPart, 'base64').toString('utf-8');
|
||||||
|
|
||||||
|
const jsonData = JSON.parse(decodedData);
|
||||||
|
const originalUrl = jsonData.u;
|
||||||
|
const referer = jsonData.r || '';
|
||||||
|
|
||||||
|
return createProxyUrl(originalUrl, referer);
|
||||||
|
} catch (jsonError) {
|
||||||
|
console.error('Error decoding/parsing orbitproxy data:', jsonError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error processing orbitproxy URL:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle other proxied URLs
|
||||||
|
if (url.includes('/m3u8-proxy?url=')) {
|
||||||
|
return url.replace(/https:\/\/[^/]+\/m3u8-proxy/, 'https://proxy.fifthwit.net/m3u8-proxy');
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isOnionflixerUrl(url: string): boolean {
|
||||||
|
return url.includes('onionflixer');
|
||||||
|
}
|
||||||
|
|
||||||
|
function processSubtitles(subtitles: any[] | undefined): any[] {
|
||||||
|
const captions = [];
|
||||||
|
|
||||||
|
if (subtitles && Array.isArray(subtitles)) {
|
||||||
|
for (const sub of subtitles) {
|
||||||
|
const url = sub.url || sub.file;
|
||||||
|
const lang = sub.lang || sub.label || 'unknown';
|
||||||
|
|
||||||
|
if (url) {
|
||||||
|
captions.push({
|
||||||
|
type: sub.type || 'vtt',
|
||||||
|
url,
|
||||||
|
language: languageMap[lang.toLowerCase()] || lang.toLowerCase() || 'unknown',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return captions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function processApiResponse(response: any, ctx: any): EmbedOutput {
|
||||||
|
if (!response) {
|
||||||
|
throw new NotFoundError('No response received');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.error) {
|
||||||
|
throw new NotFoundError(`${response.error}${response.hint ? ` - ${response.hint}` : ''}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle array responses (multiple provider options)
|
||||||
|
if (Array.isArray(response)) {
|
||||||
|
for (const item of response) {
|
||||||
|
// Handle format with headers and sources array
|
||||||
|
if (item.headers && item.sources && Array.isArray(item.sources)) {
|
||||||
|
const bestSource = item.sources.find((s: any) => s.isM3U8);
|
||||||
|
if (bestSource && bestSource.url) {
|
||||||
|
const playlistUrl = processProxiedURL(bestSource.url);
|
||||||
|
const captions = processSubtitles(item.subtitles);
|
||||||
|
|
||||||
|
return {
|
||||||
|
stream: [
|
||||||
|
{
|
||||||
|
id: 'primary',
|
||||||
|
type: 'hls',
|
||||||
|
playlist: playlistUrl,
|
||||||
|
flags: [flags.CORS_ALLOWED],
|
||||||
|
captions,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle format with source.provider and source.files
|
||||||
|
if (item.source && item.source.files && Array.isArray(item.source.files)) {
|
||||||
|
const bestFile = item.source.files.find((f: any) => f.type === 'hls' || f.file.includes('.m3u8'));
|
||||||
|
if (bestFile && bestFile.file) {
|
||||||
|
const playlistUrl = processProxiedURL(bestFile.file);
|
||||||
|
const captions = processSubtitles(item.source.subtitles);
|
||||||
|
|
||||||
|
return {
|
||||||
|
stream: [
|
||||||
|
{
|
||||||
|
id: 'primary',
|
||||||
|
type: 'hls',
|
||||||
|
playlist: playlistUrl,
|
||||||
|
flags: [flags.CORS_ALLOWED],
|
||||||
|
captions,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle original format with sources object
|
||||||
|
const sourcesObj = response.sources;
|
||||||
|
if (sourcesObj) {
|
||||||
|
let bestSource = null;
|
||||||
|
|
||||||
|
// Look through all providers in the sources object
|
||||||
|
for (const provider in sourcesObj) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(sourcesObj, provider)) {
|
||||||
|
const providerSources = sourcesObj[provider];
|
||||||
|
if (providerSources && providerSources.length > 0) {
|
||||||
|
// Find the highest quality non-onionflixer source
|
||||||
|
for (const source of providerSources) {
|
||||||
|
if (source.url && source.isM3U8 && !isOnionflixerUrl(source.url)) {
|
||||||
|
bestSource = source;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we found a good source, no need to check other providers
|
||||||
|
if (bestSource) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no non-onionflixer source was found, use the first available one
|
||||||
|
if (!bestSource) {
|
||||||
|
for (const provider in sourcesObj) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(sourcesObj, provider)) {
|
||||||
|
const providerSources = sourcesObj[provider];
|
||||||
|
if (providerSources && providerSources.length > 0) {
|
||||||
|
bestSource = providerSources[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestSource && bestSource.url) {
|
||||||
|
const playlistUrl = processProxiedURL(bestSource.url);
|
||||||
|
const captions = processSubtitles(response.subtitles);
|
||||||
|
|
||||||
|
ctx.progress(100);
|
||||||
|
|
||||||
|
return {
|
||||||
|
stream: [
|
||||||
|
{
|
||||||
|
id: 'primary',
|
||||||
|
type: 'hls',
|
||||||
|
playlist: createProxyUrl(playlistUrl, ctx.referer),
|
||||||
|
flags: [flags.CORS_ALLOWED],
|
||||||
|
captions,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotFoundError('No valid stream URL found in response');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MOVIE & TV PROVIDERS */
|
||||||
|
const movieTvProviders = [
|
||||||
|
{ id: 'autoembed', name: 'Autoembed', rank: 165 },
|
||||||
|
{ id: 'vidsrcsu', name: 'vidsrc.su', rank: 164 },
|
||||||
|
{ id: 'primebox', name: 'Primebox', rank: 162, disabled: true },
|
||||||
|
{ id: 'foxstream', name: 'Foxstream', rank: 161, disabled: true },
|
||||||
|
{ id: 'flixhq', name: 'FlixHQ', rank: 166 },
|
||||||
|
{ id: 'goku', name: 'Goku', rank: 163, disabled: true },
|
||||||
|
];
|
||||||
|
|
||||||
|
const createMovieTvEmbed = (provider: { id: string; name: string; rank: number; disabled?: boolean }) =>
|
||||||
|
makeEmbed({
|
||||||
|
id: `oneserver-${provider.id}`,
|
||||||
|
name: provider.name,
|
||||||
|
rank: provider.rank,
|
||||||
|
disabled: provider.disabled,
|
||||||
|
async scrape(ctx) {
|
||||||
|
const query = JSON.parse(ctx.url);
|
||||||
|
const apiUrl =
|
||||||
|
query.type === 'movie'
|
||||||
|
? `${baseUrl}/movie/${provider.id}/${query.tmdbId}`
|
||||||
|
: `${baseUrl}/tv/${provider.id}/${query.tmdbId}/${query.season}/${query.episode}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await ctx.fetcher(apiUrl);
|
||||||
|
ctx.progress(50);
|
||||||
|
return processApiResponse(response, ctx);
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof NotFoundError) throw error;
|
||||||
|
throw new NotFoundError(`Failed to fetch from ${provider.id}: ${error}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const [
|
||||||
|
oneServerAutoembedEmbed,
|
||||||
|
oneServerVidsrcsuEmbed,
|
||||||
|
oneServerPrimeboxEmbed,
|
||||||
|
oneServerFoxstreamEmbed,
|
||||||
|
oneServerFlixhqEmbed,
|
||||||
|
oneServerGokuEmbed,
|
||||||
|
] = movieTvProviders.map(createMovieTvEmbed);
|
||||||
|
|
||||||
|
/* ANIME PROVIDERS */
|
||||||
|
const animeProviders = [
|
||||||
|
{ id: 'hianime', name: 'Hianime', rank: 269 },
|
||||||
|
{ id: 'animepahe', name: 'Animepahe', rank: 268 },
|
||||||
|
{ id: 'anizone', name: 'Anizone', rank: 267 },
|
||||||
|
];
|
||||||
|
|
||||||
|
const createAnimeEmbed = (provider: { id: string; name: string; rank: number }) =>
|
||||||
|
makeEmbed({
|
||||||
|
id: `oneserver-${provider.id}`,
|
||||||
|
name: provider.name,
|
||||||
|
rank: provider.rank,
|
||||||
|
async scrape(ctx) {
|
||||||
|
const query = JSON.parse(ctx.url);
|
||||||
|
const apiUrl = `${baseUrl}/anime/${provider.id}/${query.anilistId}${query.episode ? `/${query.episode}` : ''}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await ctx.fetcher(apiUrl);
|
||||||
|
return processApiResponse(response, ctx);
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof NotFoundError) throw error;
|
||||||
|
throw new NotFoundError(`Failed to fetch from ${provider.id}: ${error}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const [oneServerHianimeEmbed, oneServerAnimepaheEmbed, oneServerAnizoneEmbed] =
|
||||||
|
animeProviders.map(createAnimeEmbed);
|
||||||
66
src/providers/sources/1server.ts
Normal file
66
src/providers/sources/1server.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
import { flags } from '@/entrypoint/utils/targets';
|
||||||
|
import { SourcererOutput, makeSourcerer } from '@/providers/base';
|
||||||
|
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
|
||||||
|
|
||||||
|
async function comboScraper(ctx: ShowScrapeContext | MovieScrapeContext): Promise<SourcererOutput> {
|
||||||
|
const query = {
|
||||||
|
type: ctx.media.type,
|
||||||
|
title: ctx.media.title,
|
||||||
|
tmdbId: ctx.media.tmdbId.toString(),
|
||||||
|
...(ctx.media.type === 'show' && {
|
||||||
|
season: ctx.media.season.number,
|
||||||
|
episode: ctx.media.episode.number,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
const embeds = [
|
||||||
|
{
|
||||||
|
embedId: 'oneserver-autoembed',
|
||||||
|
url: JSON.stringify(query),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
embedId: 'oneserver-vidsrcsu',
|
||||||
|
url: JSON.stringify(query),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
embedId: 'oneserver-primebox',
|
||||||
|
url: JSON.stringify(query),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
embedId: 'oneserver-foxstream',
|
||||||
|
url: JSON.stringify(query),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
embedId: 'oneserver-flixhq',
|
||||||
|
url: JSON.stringify(query),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
embedId: 'oneserver-goku',
|
||||||
|
url: JSON.stringify(query),
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// embedId: 'oneserver-hianime',
|
||||||
|
// url: JSON.stringify(query),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// embedId: 'oneserver-animepahe',
|
||||||
|
// url: JSON.stringify(query),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// embedId: 'oneserver-anizone',
|
||||||
|
// url: JSON.stringify(query),
|
||||||
|
// },
|
||||||
|
];
|
||||||
|
|
||||||
|
return { embeds };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const oneServerScraper = makeSourcerer({
|
||||||
|
id: '1server',
|
||||||
|
name: '1Server',
|
||||||
|
rank: 165,
|
||||||
|
disabled: false,
|
||||||
|
flags: [flags.CORS_ALLOWED],
|
||||||
|
scrapeMovie: comboScraper,
|
||||||
|
scrapeShow: comboScraper,
|
||||||
|
});
|
||||||
|
|
@ -1,5 +1,16 @@
|
||||||
// import { alphaScraper, deltaScraper } from '@/providers/embeds/nsbx';
|
// import { alphaScraper, deltaScraper } from '@/providers/embeds/nsbx';
|
||||||
// import { astraScraper, novaScraper, orionScraper } from '@/providers/embeds/whvx';
|
// import { astraScraper, novaScraper, orionScraper } from '@/providers/embeds/whvx';
|
||||||
|
import {
|
||||||
|
oneServerAnimepaheEmbed,
|
||||||
|
oneServerAnizoneEmbed,
|
||||||
|
oneServerAutoembedEmbed,
|
||||||
|
oneServerFlixhqEmbed,
|
||||||
|
oneServerFoxstreamEmbed,
|
||||||
|
oneServerGokuEmbed,
|
||||||
|
oneServerHianimeEmbed,
|
||||||
|
oneServerPrimeboxEmbed,
|
||||||
|
oneServerVidsrcsuEmbed,
|
||||||
|
} from '@/providers/embeds/1server';
|
||||||
import {
|
import {
|
||||||
ConsumetStreamSBScraper,
|
ConsumetStreamSBScraper,
|
||||||
ConsumetStreamTapeScraper,
|
ConsumetStreamTapeScraper,
|
||||||
|
|
@ -51,6 +62,15 @@ const SKIP_VALIDATION_CHECK_IDS = [
|
||||||
hianimeHd1SubEmbed.id,
|
hianimeHd1SubEmbed.id,
|
||||||
hianimeHd2DubEmbed.id,
|
hianimeHd2DubEmbed.id,
|
||||||
hianimeHd2SubEmbed.id,
|
hianimeHd2SubEmbed.id,
|
||||||
|
oneServerAutoembedEmbed.id,
|
||||||
|
oneServerVidsrcsuEmbed.id,
|
||||||
|
oneServerPrimeboxEmbed.id,
|
||||||
|
oneServerFoxstreamEmbed.id,
|
||||||
|
oneServerFlixhqEmbed.id,
|
||||||
|
oneServerGokuEmbed.id,
|
||||||
|
oneServerHianimeEmbed.id,
|
||||||
|
oneServerAnimepaheEmbed.id,
|
||||||
|
oneServerAnizoneEmbed.id,
|
||||||
];
|
];
|
||||||
|
|
||||||
export function isValidStream(stream: Stream | undefined): boolean {
|
export function isValidStream(stream: Stream | undefined): boolean {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue