mirror of
https://github.com/p-stream/providers.git
synced 2026-04-21 14:52:19 +00:00
add voe
This commit is contained in:
parent
e6b1a7ada8
commit
0b4220861f
2 changed files with 107 additions and 0 deletions
|
|
@ -68,6 +68,7 @@ import {
|
||||||
VidsrcsuServer9Scraper,
|
VidsrcsuServer9Scraper,
|
||||||
} from './embeds/vidsrcsu';
|
} from './embeds/vidsrcsu';
|
||||||
import { viperScraper } from './embeds/viper';
|
import { viperScraper } from './embeds/viper';
|
||||||
|
import { voeScraper } from './embeds/voe';
|
||||||
import { warezcdnembedHlsScraper } from './embeds/warezcdn/hls';
|
import { warezcdnembedHlsScraper } from './embeds/warezcdn/hls';
|
||||||
import { warezcdnembedMp4Scraper } from './embeds/warezcdn/mp4';
|
import { warezcdnembedMp4Scraper } from './embeds/warezcdn/mp4';
|
||||||
import { warezPlayerScraper } from './embeds/warezcdn/warezplayer';
|
import { warezPlayerScraper } from './embeds/warezcdn/warezplayer';
|
||||||
|
|
@ -217,5 +218,6 @@ export function gatherAllEmbeds(): Array<Embed> {
|
||||||
filelionsScraper,
|
filelionsScraper,
|
||||||
droploadScraper,
|
droploadScraper,
|
||||||
supervideoScraper,
|
supervideoScraper,
|
||||||
|
voeScraper,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
105
src/providers/embeds/voe.ts
Normal file
105
src/providers/embeds/voe.ts
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
import { flags } from '@/entrypoint/utils/targets';
|
||||||
|
import { makeEmbed } from '@/providers/base';
|
||||||
|
import { NotFoundError } from '@/utils/errors';
|
||||||
|
|
||||||
|
const userAgent =
|
||||||
|
'Mozilla/5.0 (Linux; Android 11; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Mobile Safari/537.36';
|
||||||
|
|
||||||
|
function cleanSymbols(s: string): string {
|
||||||
|
let result = s;
|
||||||
|
for (const p of ['@$', '^^', '~@', '%?', '*~', '!!', '#&']) {
|
||||||
|
result = result.replaceAll(p, '_');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanUnderscores(s: string): string {
|
||||||
|
return s.replace(/_/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function shiftBack(s: string, n: number): string {
|
||||||
|
return Array.from(s)
|
||||||
|
.map((c) => String.fromCharCode(c.charCodeAt(0) - n))
|
||||||
|
.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
function rot13(str: string): string {
|
||||||
|
return str.replace(/[a-zA-Z]/g, (c) => {
|
||||||
|
const base = c <= 'Z' ? 65 : 97;
|
||||||
|
return String.fromCharCode(((c.charCodeAt(0) - base + 13) % 26) + base);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const voeScraper = makeEmbed({
|
||||||
|
id: 'voe',
|
||||||
|
name: 'Voe',
|
||||||
|
rank: 180,
|
||||||
|
flags: [flags.IP_LOCKED],
|
||||||
|
async scrape(ctx) {
|
||||||
|
const url = ctx.url;
|
||||||
|
const defaultDomain = (() => {
|
||||||
|
try {
|
||||||
|
const u = new URL(url);
|
||||||
|
return `${u.protocol}//${u.host}/`;
|
||||||
|
} catch {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
const headers: Record<string, string> = {
|
||||||
|
'User-Agent': userAgent,
|
||||||
|
};
|
||||||
|
if (defaultDomain) {
|
||||||
|
headers.Referer = defaultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
let html = await ctx.proxiedFetcher<string>(url, { headers });
|
||||||
|
|
||||||
|
// Handle redirect page
|
||||||
|
if (html.includes('Redirecting...')) {
|
||||||
|
const match = html.match(/href\s*=\s*'(.*?)';/);
|
||||||
|
if (!match) throw new NotFoundError('Redirect target not found');
|
||||||
|
const redirectUrl = match[1];
|
||||||
|
html = await ctx.proxiedFetcher<string>(redirectUrl, { headers });
|
||||||
|
}
|
||||||
|
|
||||||
|
const jsonScriptMatch = html.match(/<script[^>]+type=["']application\/json["'][^>]*>([\s\S]*?)<\/script>/i);
|
||||||
|
if (!jsonScriptMatch) throw new NotFoundError('Obfuscated script not found');
|
||||||
|
|
||||||
|
const obfuscatedScript = jsonScriptMatch[1];
|
||||||
|
const encodedMatch = obfuscatedScript.match(/\["(.*?)"\]/);
|
||||||
|
if (!encodedMatch) throw new NotFoundError('Encoded data not found');
|
||||||
|
|
||||||
|
const encodedData = encodedMatch[1];
|
||||||
|
|
||||||
|
// Decoding steps
|
||||||
|
let decoded = rot13(encodedData);
|
||||||
|
decoded = cleanSymbols(decoded);
|
||||||
|
decoded = cleanUnderscores(decoded);
|
||||||
|
decoded = Buffer.from(decoded, 'base64').toString('utf-8');
|
||||||
|
decoded = shiftBack(decoded, 3);
|
||||||
|
decoded = decoded.split('').reverse().join('');
|
||||||
|
decoded = Buffer.from(decoded, 'base64').toString('utf-8');
|
||||||
|
|
||||||
|
const json = JSON.parse(decoded);
|
||||||
|
const videoUrl = json?.source;
|
||||||
|
if (!videoUrl) throw new NotFoundError('No video URL found');
|
||||||
|
|
||||||
|
return {
|
||||||
|
stream: [
|
||||||
|
{
|
||||||
|
id: 'primary',
|
||||||
|
type: 'hls',
|
||||||
|
playlist: videoUrl,
|
||||||
|
flags: [flags.IP_LOCKED],
|
||||||
|
captions: [],
|
||||||
|
headers: {
|
||||||
|
Referer: defaultDomain || url,
|
||||||
|
Origin: defaultDomain?.replace(/\/$/, '') || new URL(url).origin,
|
||||||
|
'User-Agent': userAgent,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue