OverviewFilesCommitsIssuesDocsReleasesPeers

stremio-vsembed / node_helper / prorcp_dump.mjs

58 lines · javascript ref:
// prorcp_dump.mjs — capture the prorcp URL, then dump what the player page contains.
import { chromium } from 'playwright';
const log = (...a) => console.error('[dump]', ...a);
const UA = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
const AD = /devilyquondam|dtscout|histats|\/cuid\/|popunder|propeller|adsco|doubleclick|onclick\.|popads|\/rum\?/i;
const EMBED = process.argv[2];

const browser = await chromium.launch({ headless: true, args: ['--no-sandbox'] });
const ctx = await browser.newContext({ userAgent: UA });
await ctx.route('**/*', r => AD.test(r.request().url()) ? r.abort() : r.continue());

const p1 = await ctx.newPage();
let rcp = null;
p1.on('framenavigated', f => { const u = f.url(); if (/\/rcp\//i.test(u) && !/prorcp/i.test(u) && !rcp) rcp = u; });
await p1.setExtraHTTPHeaders({ Referer: 'https://netoda.tech/' });
await p1.goto(EMBED, { waitUntil: 'domcontentloaded', timeout: 30000 }).catch(e => log('warn', e.message));
for (let i = 0; i < 16 && !rcp; i++) await p1.waitForTimeout(1000);
await p1.close().catch(() => {});
if (!rcp) { await browser.close(); console.log(JSON.stringify({ error: 'no rcp' })); process.exit(3); }
log('rcp ok');

const p = await ctx.newPage();
await p.setExtraHTTPHeaders({ Referer: EMBED });
await p.goto(rcp, { waitUntil: 'domcontentloaded', timeout: 30000 }).catch(e => log('warn', e.message));
await p.waitForTimeout(2500);

// dump the rcp page's own HTML around the base64.js/script tags
const rcpHtml = await p.content().catch(() => '');
log('--- rcp page scripts ---');
for (const m of rcpHtml.matchAll(/<script[^>]*>/gi)) log('  ', m[0].slice(0, 160));
const b64 = rcpHtml.match(/base64\.js[^"'<\s]*/i);
log('  base64 ref:', b64 ? b64[0] : 'NONE');

await p.evaluate(() => { const el = document.querySelector('#pl_but'); if (el) el.click(); }).catch(() => {});
await p.waitForTimeout(6000);

const pf = p.frames().find(f => /prorcp/i.test(f.url()));
log('prorcp frame:', pf ? 'YES' : 'NO');
if (pf) {
  const html = await pf.content().catch(e => 'ERR ' + e.message);
  log('prorcp html length:', html.length);
  log('--- prorcp: file/src/m3u8 hits ---');
  for (const re of [/file\s*:\s*['"][^'"]{0,120}/gi, /src\s*:\s*['"][^'"]{0,120}/gi, /https?:\/\/[^'"\s]{0,120}m3u8[^'"\s]{0,40}/gi, /id\s*=\s*["'][^"']{0,40}["']/gi]) {
    const hits = [...html.matchAll(re)].slice(0, 6).map(m => m[0]);
    if (hits.length) log('  ', re.source.slice(0, 30), '=>', JSON.stringify(hits));
  }
  log('--- prorcp: script srcs ---');
  for (const m of [...html.matchAll(/<script[^>]*src=["']([^"']+)["']/gi)].slice(0, 12)) log('   ', m[1].slice(0, 120));
  log('--- prorcp: first 600 chars of body text ---');
  const t = await pf.evaluate(() => ((document.body && document.body.innerText) || '').replace(/\s+/g, ' ').slice(0, 600)).catch(e => 'ERR ' + e.message);
  log('   ', t);
  log('--- prorcp: inline script head (1500) ---');
  const inline = html.match(/<script(?![^>]*src)[^>]*>([\s\S]{0,1500})/i);
  log(inline ? inline[1] : 'none');
}
await browser.close().catch(() => {});
console.log(JSON.stringify({ ok: true }));