Last active
December 6, 2025 20:23
-
-
Save donal56/dc37300469cec5aa15d3deb0f12b3ad2 to your computer and use it in GitHub Desktop.
(agumation-utilities) Descarga videos del aguringu FC. Es necesario agregar los enlaces en links.txt y las credenciales del sitio junto con la api key de deepl en properties.js. Youtube-dl debe estar instalado y disponible en el path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const deepl = require('deepl-node'); | |
| const puppeteer = require('puppeteer'); | |
| const util = require('util'); | |
| const exec = util.promisify(require('child_process').exec); | |
| const fs = require('fs'); | |
| const properties = require('./properties.js'); | |
| // Datos del club | |
| const baseUrl = "https://aguri-onishi.com"; | |
| const loginUrl = baseUrl + "/signin"; | |
| const { user, pass } = properties.aguringu; | |
| // Datos de DeepL | |
| const { apiKey } = properties.deepl; | |
| const translator = new deepl.Translator(apiKey); | |
| // Otras constantes | |
| const iframeDomain = "player-api.p.uliza.jp"; | |
| const streamOrigin = "https://vms-api.p.uliza.jp/v1/prog-index.m3u8"; | |
| const indexPageIdentifier = "/categories/"; | |
| const seenStreams = new Set(); | |
| (async () => { | |
| // Inicializar | |
| printLn("===RUNNING==="); | |
| const browser = await puppeteer.launch({ | |
| headless: "new", | |
| //devtools: true | |
| }); | |
| const page = await browser.newPage(); | |
| // Iniciar sesión | |
| await page.goto(loginUrl); | |
| await page.waitForSelector('#jsLoadingAnimation', { hidden: true }); | |
| await page.click("#user_login"); | |
| await page.keyboard.type(user); | |
| await page.click("#user_password"); | |
| await page.keyboard.type(pass); | |
| await page.click(".signin-form + div input[type=submit]"); | |
| await page.waitForSelector('#mains') | |
| .then(() => printLn("===LOGGED IN===")) | |
| .catch(() => printLn("FAILED: Verify your credentials", 2)); | |
| // Escuchar solicitudes de red del frame del reproductor | |
| page.on('framenavigated', async frame => { | |
| try { | |
| const frameClient = await frame._client(); | |
| await frameClient.send('Network.enable'); | |
| frameClient.on('Network.requestWillBeSent', request => { | |
| const streamUrl = request.request.url; | |
| if (streamUrl.startsWith(streamOrigin) && !seenStreams.has(streamUrl)) { | |
| seenStreams.add(streamUrl); | |
| printLn("Stream found", 3); | |
| downloadVideo(page, streamUrl); | |
| } | |
| }); | |
| } catch (err) { } | |
| }); | |
| // Visitar cada video | |
| const urlsToDownload = await getLinksToDownload(page); | |
| for (index in urlsToDownload) { | |
| printLn("Start " + urlsToDownload[index]); | |
| await page.goto(urlsToDownload[index]); | |
| await page.waitForSelector('#jsLoadingAnimation', { hidden: true }); | |
| const iframeHandle = await page.waitForSelector(`iframe[src*="${iframeDomain}"]`); | |
| const frame = await iframeHandle.contentFrame(); | |
| await frame.waitForSelector("video"); | |
| try { | |
| await frame.waitForNavigation({timeout: 10_000, waitUntil: 'networkidle2'}); | |
| } | |
| catch(err) {} | |
| } | |
| // Finalizar | |
| await browser.close(); | |
| printLn("===END===", 3); | |
| async function downloadVideo(page, videoUrl) { | |
| // El formato es '#131_今年も一年' | |
| const untranslatedTitle = await page.$eval(".title", el => el.textContent.trim().replace("_", " ")); | |
| const translationJob = await translator.translateText(untranslatedTitle, "JA", "EN-US"); | |
| // El formato es '2024.12.30' | |
| const publishedDate = await page.$eval(".time", el => el.textContent.replaceAll(".", "-")); | |
| // Comando final | |
| const fileName = translationJob.text.replaceAll("\"", "'").replaceAll(".", "") + " " + publishedDate + ".mp4"; | |
| const filePath = "./downloads/" + fileName; | |
| const command = "yt-dlp --referer " + baseUrl + " -o \"" + filePath + "\" \"" + videoUrl + "\""; | |
| printLn(command, 3); | |
| const {stdout, stderr } = await exec(command); | |
| if (stderr) { | |
| printLn("Error: " + stderr, 2); | |
| } | |
| else { | |
| if (stdout.trim().endsWith("has already been downloaded")) { | |
| printLn("Already downloaded, skipping", 3); | |
| } | |
| else { | |
| printLn("Completed succesfully", 1); | |
| } | |
| } | |
| } | |
| async function getLinksToDownload(page) { | |
| const file = fs.readFileSync('links.txt', 'utf-8'); | |
| const lines = file.split(/\r?\n/); | |
| let expanded = []; | |
| for (const link of lines) { | |
| if (link.includes(indexPageIdentifier)) { | |
| const subLinks = await detectIndexPageUrls(page, link); | |
| expanded = [...expanded, ...subLinks]; | |
| } else { | |
| expanded.push(link); | |
| } | |
| } | |
| printLn("Links detected: " + expanded, 3) | |
| return expanded; | |
| } | |
| async function detectIndexPageUrls(page, indexPageUrl) { | |
| await page.goto(indexPageUrl); | |
| await page.waitForSelector('#jsLoadingAnimation', { hidden: true }); | |
| const hrefs = await page.$$eval('.details-voice .thumb-list-item a', (nodes, baseUrl2) => | |
| nodes.map(a => new URL(a.getAttribute('href'), baseUrl2).href) | |
| , baseUrl); | |
| return hrefs; | |
| } | |
| })(); | |
| /** | |
| * Print to console | |
| * @param message | |
| * @param style - color style of the message | |
| * 0 - Primary | |
| * 1 - Success | |
| * 2 - Error | |
| * 3 - Muted | |
| */ | |
| function printLn(message, style = 0) { | |
| // Formatos de consola | |
| const styleReset = "\x1b[0m"; | |
| const stylePrimary = "\x1b[42m%s\x1b[37m"; | |
| const styleSuccess = "\x1b[4m%s\x1b[32m"; | |
| const styleError = "\x1b[4m%s\x1b[31m"; | |
| const styleMuted = "\x1b[2m%s\x1b[4m"; | |
| const styles = [stylePrimary, styleSuccess, styleError, styleMuted]; | |
| console.info(styles[style], message, styleReset); | |
| console.info(""); | |
| } | |
| async function takeScreenshot(page) { | |
| let url = page.url().replaceAll("/", "_"); | |
| url = url.replaceAll(":", "_"); | |
| await page.screenshot({ path: "ss_" + Date.now() + "_" + url + ".png" }); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "dependencies": { | |
| "deepl": "^1.0.13", | |
| "deepl-node": "^1.7.1", | |
| "puppeteer": "^19.2.2" | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var properties = { | |
| deepl : { | |
| apiKey: "REPLACE_ME" | |
| }, | |
| aguringu : { | |
| user: "REPLACE_ME", | |
| pass: "REPLACE_ME" | |
| } | |
| }; | |
| module.exports = properties; |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Requerimentos: ffmpeg
Instrucciones:
npm install.node aguringu-downloader.js