This commit is contained in:
Pas 2025-03-27 11:52:52 -06:00
parent aef3887293
commit b618e2387c
3 changed files with 337 additions and 0 deletions

View file

@ -1,6 +1,20 @@
import { Embed, Sourcerer } from '@/providers/base';
import { doodScraper } from '@/providers/embeds/dood';
import { mixdropScraper } from '@/providers/embeds/mixdrop';
import {
riveAsiacloudScraper,
riveEe3Scraper,
riveFastxScraper,
riveFilmechoScraper,
riveG1Scraper,
riveG2Scraper,
riveGhostScraper,
riveGuruScraper,
riveHydraxScraper,
riveKageScraper,
riveNovaScraper,
rivePutafilmeScraper,
} from '@/providers/embeds/rive';
import { turbovidScraper } from '@/providers/embeds/turbovid';
import { upcloudScraper } from '@/providers/embeds/upcloud';
import { autoembedScraper } from '@/providers/sources/autoembed';
@ -9,6 +23,7 @@ import { ee3Scraper } from '@/providers/sources/ee3';
import { fsharetvScraper } from '@/providers/sources/fsharetv';
import { insertunitScraper } from '@/providers/sources/insertunit';
import { mp4hydraScraper } from '@/providers/sources/mp4hydra';
import { riveScraper } from '@/providers/sources/rive';
import { tugaflixScraper } from '@/providers/sources/tugaflix';
import { vidsrcsuScraper } from '@/providers/sources/vidsrcsu';
@ -88,6 +103,7 @@ export function gatherAllSources(): Array<Sourcerer> {
coitusScraper,
streamboxScraper,
nunflixScraper,
riveScraper,
];
}
@ -134,5 +150,17 @@ export function gatherAllEmbeds(): Array<Embed> {
FedAPIPrivateScraper,
FedAPISharedScraper,
FedDBScraper,
riveAsiacloudScraper,
riveEe3Scraper,
riveFastxScraper,
riveFilmechoScraper,
riveG1Scraper,
riveG2Scraper,
riveGhostScraper,
riveGuruScraper,
riveHydraxScraper,
riveKageScraper,
riveNovaScraper,
rivePutafilmeScraper,
];
}

View file

@ -0,0 +1,113 @@
import { flags } from '@/entrypoint/utils/targets';
import { makeEmbed } from '@/providers/base';
const providers = [
{
id: 'rive-hydrax',
rank: 270,
},
{
id: 'rive-fastx',
rank: 269,
},
{
id: 'rive-filmecho',
rank: 268,
},
{
id: 'rive-nova',
rank: 267,
},
{
id: 'rive-guru',
rank: 266,
},
{
id: 'rive-g1',
rank: 265,
},
{
id: 'rive-g2',
rank: 264,
},
{
id: 'rive-ee3',
rank: 263,
},
{
id: 'rive-ghost',
rank: 262,
},
{
id: 'rive-putafilme',
rank: 261,
},
{
id: 'rive-asiacloud',
rank: 260,
},
{
id: 'rive-kage',
rank: 259,
},
];
function embed(provider: { id: string; rank: number; disabled?: boolean }) {
return makeEmbed({
id: provider.id,
name: provider.id
.split('-')
.map((word) => word[0].toUpperCase() + word.slice(1))
.join(' '),
disabled: provider.disabled,
rank: provider.rank,
async scrape(ctx) {
const isHLS = ctx.url.includes('.m3u8') || ctx.url.includes('hls') || ctx.url.includes('playlist');
if (isHLS) {
return {
stream: [
{
id: 'primary',
type: 'hls',
playlist: ctx.url,
flags: [flags.CORS_ALLOWED],
captions: [],
},
],
};
}
return {
stream: [
{
id: 'primary',
type: 'file',
qualities: {
unknown: {
type: 'mp4',
url: ctx.url,
},
},
flags: [flags.CORS_ALLOWED],
captions: [],
},
],
};
},
});
}
export const [
riveHydraxScraper,
riveFastxScraper,
riveFilmechoScraper,
riveNovaScraper,
riveGuruScraper,
riveG1Scraper,
riveG2Scraper,
riveEe3Scraper,
riveGhostScraper,
rivePutafilmeScraper,
riveAsiacloudScraper,
riveKageScraper,
] = providers.map(embed);

View file

@ -0,0 +1,196 @@
import { flags } from '@/entrypoint/utils/targets';
import { SourcererEmbed, SourcererOutput, makeSourcerer } from '@/providers/base';
import { MovieScrapeContext, ShowScrapeContext } from '@/utils/context';
import { NotFoundError } from '@/utils/errors';
const baseUrl = 'https://rivestream.org';
function generateSecretKey(id: number | string) {
const keyArray = [
'I',
'3LZu',
'M2V3',
'4EXX',
's4',
'yRy',
'oqMz',
'ysE',
'RT',
'iSI',
'zlc',
'H',
'YNp',
'5vR6',
'h9S',
'R',
'jo',
'F',
'h2',
'W8',
'i',
'sz09',
'Xom',
'gpU',
'q',
'6Qvg',
'Cu',
'5Zaz',
'VK',
'od',
'FGY4',
'eu',
'D5Q',
'smH',
'11eq',
'QrXs',
'3',
'L3',
'YhlP',
'c',
'Z',
'YT',
'bnsy',
'5',
'fcL',
'L22G',
'r8',
'J',
'4',
'gnK',
];
// Handle undefined/null input
if (typeof id === 'undefined' || id === null) {
return 'rive';
}
// Convert to number and calculate array index
const numericId = typeof id === 'string' ? parseInt(id, 10) : Number(id);
const index = numericId % keyArray.length;
// Handle NaN cases (invalid number conversion)
if (Number.isNaN(index)) {
return 'rive';
}
return keyArray[index];
}
function processProxiedURL(url: string): string {
if (url.includes('orbitproxy')) {
try {
const urlParts = url.split(/orbitproxy\.[^/]+\//);
if (urlParts.length >= 2) {
const encryptedPart = urlParts[1].split('.m3u8')[0];
try {
const decodedData = Buffer.from(encryptedPart, 'base64').toString('utf-8');
const jsonData = JSON.parse(decodedData);
const originalUrl = jsonData.u;
const referer = jsonData.r || '';
const encodedUrl = encodeURIComponent(originalUrl);
const encodedHeaders = encodeURIComponent(
JSON.stringify({
referer,
}),
);
const proxyUrl = `https://m3u8.wafflehacker.io/m3u8-proxy?url=${encodedUrl}&headers=${encodedHeaders}`;
return proxyUrl;
} catch (jsonError) {
console.error('Error decoding/parsing orbitproxy data:', jsonError);
}
}
} catch (error) {
console.error('Error processing orbitproxy URL:', error);
}
}
return url;
}
async function comboScraper(ctx: MovieScrapeContext | ShowScrapeContext): Promise<SourcererOutput> {
const tmdbId = ctx.media.tmdbId;
const secret = generateSecretKey(tmdbId);
const servers = [
'hydrax',
'fastx',
'filmecho',
'nova',
'guru',
'g1',
'g2',
'ee3',
'ghost',
'putafilme',
'asiacloud',
'kage',
];
const route =
ctx.media.type === 'show'
? `/api/backendfetch?requestID=tvVideoProvider&id=${tmdbId}&season=${ctx.media.season.number}&episode=${ctx.media.episode.number}&secretKey=${secret}&service=`
: `/api/backendfetch?requestID=movieVideoProvider&id=${tmdbId}&secretKey=${secret}&service=`;
ctx.progress(20);
const embeds: SourcererEmbed[] = [];
const processedServers = new Set<string>();
await Promise.all(
servers.map(async (server) => {
try {
const url = baseUrl + route + server;
const response = await ctx.proxiedFetcher(url, {
headers: {
Referer: baseUrl,
},
});
const data = typeof response === 'string' ? JSON.parse(response) : response;
if (!data?.data || !data?.data?.sources?.length) {
return;
}
data.data.sources.forEach((source: any) => {
const processedUrl = processProxiedURL(source.url);
const serverKey = `rive-${server}`;
if (!processedServers.has(serverKey)) {
processedServers.add(serverKey);
embeds.push({
embedId: serverKey,
url: processedUrl,
});
}
});
} catch (error) {
console.error(`Error fetching Rive ${server}:`, error);
}
}),
);
ctx.progress(90);
if (!embeds.length) {
throw new NotFoundError('No embeds found from Rive');
}
return {
embeds,
};
}
export const riveScraper = makeSourcerer({
id: 'rive',
name: 'Rive',
rank: 130,
flags: [flags.CORS_ALLOWED],
scrapeMovie: comboScraper,
scrapeShow: comboScraper,
});