- Add Next.js app structure with base configs, linting, and formatting - Implement LiveKit Meet page, types, and utility functions - Add Docker, Compose, and deployment scripts for backend and token server - Provide E2E and smoke test scaffolding with Puppeteer and Playwright helpers - Include CSS modules and global styles for UI - Add postMessage and studio integration utilities - Update package.json with dependencies and scripts for development and testing
85 lines
3.2 KiB
JavaScript
85 lines
3.2 KiB
JavaScript
// browserless_connect.mjs
|
|
// Conecta a un browserless remoto vía WebSocket y ejecuta el flujo en http://localhost:5175
|
|
// Uso: node --input-type=module browserless_connect.mjs
|
|
|
|
import puppeteer from 'puppeteer-core';
|
|
|
|
const BROWSERLESS_WSS = process.env.BROWSERLESS_WS || 'wss://browserless.bfzqqk.easypanel.host?token=e2e098863b912f6a178b68e71ec3c58d';
|
|
const BROADCAST_URL = process.env.BROADCAST_URL || 'http://localhost:5175';
|
|
|
|
function byTextXPath(text){
|
|
return `//*[contains(translate(normalize-space(string(.)), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '${text.toLowerCase()}')]`;
|
|
}
|
|
async function clickByText(page, text){
|
|
const els = await page.$x(byTextXPath(text));
|
|
if(els && els.length){ await els[0].click(); return true; }
|
|
return false;
|
|
}
|
|
|
|
(async ()=>{
|
|
console.log('Connecting to browserless at', BROWSERLESS_WSS);
|
|
const browser = await puppeteer.connect({ browserWSEndpoint: BROWSERLESS_WSS, defaultViewport: null, timeout: 60000 });
|
|
try{
|
|
const page = await browser.newPage();
|
|
page.on('console', msg => console.log('PAGE:', msg.text()));
|
|
|
|
console.log('Navigating to', BROADCAST_URL);
|
|
await page.goto(BROADCAST_URL, { waitUntil: 'networkidle2', timeout: 60000 });
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Try click 'Entrar al Estudio'
|
|
if(await clickByText(page, 'Entrar al Estudio')){
|
|
console.log('Clicked Entrar al Estudio');
|
|
await page.waitForTimeout(2000);
|
|
} else {
|
|
console.log('Entrar al Estudio not found, trying create-flow');
|
|
// open modal buttons
|
|
const opened = await (async ()=>{
|
|
if(await clickByText(page, 'Crear transmisión')) return true;
|
|
if(await clickByText(page, 'Crear transmisión en vivo')) return true;
|
|
if(await clickByText(page, 'Nueva transmisión')) return true;
|
|
if(await clickByText(page, 'Crear')) return true;
|
|
if(await clickByText(page, 'Transmitir')) return true;
|
|
return false;
|
|
})();
|
|
if(opened){
|
|
console.log('Modal opened, trying skip and start');
|
|
await page.waitForTimeout(800);
|
|
await clickByText(page, 'Omitir por ahora').catch(()=>{});
|
|
// fill input
|
|
const inputs = await page.$$('input');
|
|
for(const inp of inputs){
|
|
try{
|
|
const box = await inp.boundingBox();
|
|
if(box){
|
|
await inp.focus();
|
|
await page.keyboard.type('Transmitir', {delay:100});
|
|
break;
|
|
}
|
|
}catch(e){}
|
|
}
|
|
await clickByText(page, 'Empezar ahora').catch(()=>{});
|
|
await page.waitForTimeout(800);
|
|
await clickByText(page, 'Entrar al Estudio').catch(()=>{});
|
|
await page.waitForTimeout(1500);
|
|
} else {
|
|
console.log('Could not open modal - aborting flow');
|
|
}
|
|
}
|
|
|
|
const shot = '/tmp/browserless_final.png';
|
|
await page.screenshot({ path: shot, fullPage: true }).catch(e=>console.log('screenshot failed', e));
|
|
console.log('Screenshot saved to', shot);
|
|
|
|
// keep page open briefly so browserless trace available
|
|
await page.waitForTimeout(2000);
|
|
await browser.disconnect();
|
|
console.log('Disconnected');
|
|
}catch(err){
|
|
console.error('Error during flow:', err);
|
|
try{ await browser.disconnect(); }catch(e){}
|
|
process.exitCode = 1;
|
|
}
|
|
})();
|
|
|