Files

114 lines
9.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const { check, done, req } = require('./_setup');
const errors = req('src/youtube/errors');
const ID = 'ERROR: [youtube] jNQXAC9IVRw: ';
// Chaque ligne du tableau de research-ytdlp.md §5 (+ variantes réelles)
const CASES = [
// Bot check (apostrophe typographique et droite)
[ID + 'Sign in to confirm you’re not a bot. Use --cookies-from-browser or --cookies for the authentication. See https://github.com/yt-dlp/yt-dlp/wiki/FAQ#how-do-i-pass-cookies-to-yt-dlp for how to manually pass cookies.', 'BOT_CHECK'],
[ID + "Sign in to confirm you're not a bot. This helps protect our community. Learn more", 'BOT_CHECK'],
['ERROR: [youtube] abc: Sign in to confirm youre not a bot', 'BOT_CHECK'],
// IP bloquée
[ID + 'All player responses are invalid. Your IP is likely being blocked by Youtube', 'IP_BLOCKED'],
// Captcha
[ID + 'YouTube is requiring a captcha challenge before playback', 'CAPTCHA'],
// Rate limit
[ID + "This content isn't available, try again later. The current session has been rate-limited by YouTube for up to an hour. It is recommended to use `-t sleep` to add a delay between video requests", 'RATE_LIMITED'],
[ID + 'This content isn’t available, try again later.', 'RATE_LIMITED'],
// 403 au téléchargement
['ERROR: unable to download video data: HTTP Error 403: Forbidden', 'HTTP_403'],
['[download] Got error: HTTP Error 403: Forbidden. Retrying (1/3)...', 'HTTP_403'],
['ERROR: [download] Giving up after 3 retries: HTTP Error 403: Forbidden', 'HTTP_403'],
// 429
['ERROR: [youtube] abc: Unable to download API page: HTTP Error 429: Too Many Requests', 'HTTP_429'],
// Âge
[ID + 'Sign in to confirm your age. This video may be inappropriate for some users.', 'AGE_RESTRICTED'],
[ID + 'This video is age-restricted and only available on YouTube', 'AGE_RESTRICTED'],
// Connexion / membres
[ID + 'Login details are needed to download this content', 'LOGIN_REQUIRED'],
[ID + "This video is available to this channel's members on level: Member (or any higher level). Join this channel to get access to members-only content like this video, and other exclusive perks.", 'MEMBERS_ONLY'],
[ID + 'Join this channel to get access to members-only content like this video, and other exclusive perks.', 'MEMBERS_ONLY'],
// Privée
[ID + "Private video. Sign in if you've been granted access to this video", 'PRIVATE'],
// Indisponible
[ID + 'Video unavailable', 'UNAVAILABLE'],
[ID + 'Video unavailable. This content isn’t available.', 'UNAVAILABLE'],
[ID + 'This video is unavailable', 'UNAVAILABLE'],
[ID + 'Video unavailable. This video has been removed by the uploader', 'UNAVAILABLE'],
// Géo
[ID + 'The uploader has not made this video available in your country', 'GEO_BLOCKED'],
// PO token (avertissement seul)
['WARNING: [youtube] jNQXAC9IVRw: mweb client https formats require a GVS PO Token which was not provided. They will be skipped as they may yield HTTP Error 403. You can manually pass a GVS PO Token for this client with --extractor-args "youtube:po_token=mweb.gvs+XXX".', 'POT_MISSING'],
// SABR
['WARNING: [youtube] jNQXAC9IVRw: Some web client https formats have been skipped as they are missing a URL. YouTube may have enabled the SABR-only streaming experiment for your account.', 'SABR'],
['WARNING: [youtube] jNQXAC9IVRw: Some tv client https formats have been skipped as they are missing a url. YouTube may have enabled the SABR-only streaming experiment for the current session.', 'SABR'],
['[debug] [youtube] YouTube is forcing SABR streaming for this client.', 'SABR'],
// Défi JS
['WARNING: [youtube] jNQXAC9IVRw: n challenge solving failed: Some formats may be missing. Ensure you have a supported JavaScript runtime and challenge solver script distribution installed.', 'JS_CHALLENGE'],
['WARNING: [youtube] jNQXAC9IVRw: Signature solving failed: Some formats may be missing.', 'JS_CHALLENGE'],
['WARNING: [youtube] No supported JavaScript runtime could be found. Only deno is enabled by default', 'JS_CHALLENGE'],
// Format
['ERROR: [youtube] jNQXAC9IVRw: Requested format is not available. Use --list-formats for a list of available formats', 'FORMAT_UNAVAILABLE'],
// Page à recharger
[ID + 'The page needs to be reloaded.', 'PAGE_RELOAD'],
// Cookies tournés
['WARNING: [youtube] The provided YouTube account cookies are no longer valid. They have likely been rotated in the browser as a security measure. For tips on how to effectively export YouTube cookies, refer to https://github.com/yt-dlp/yt-dlp/wiki/Extractors#exporting-youtube-cookies .', 'COOKIES_ROTATED'],
// Fichier vide
['ERROR: The downloaded file is empty', 'EMPTY_DOWNLOAD'],
// Binaire absent / délai
['spawn yt-dlp ENOENT', 'BINARY_MISSING'],
['ERROR: yt-dlp introuvable (ENOENT)', 'BINARY_MISSING'],
['ERROR: [youtube] abc: Unable to download webpage: <urlopen error timed out> (caused by URLError(TimeoutError(\'timed out\')))', 'TIMEOUT'],
['aucune donnée après 20s', 'TIMEOUT'],
// Informations seules
['WARNING: [youtube] Skipping client "visionos" since it does not support cookies', 'UNKNOWN'],
['ERROR: Login with OAuth is no longer supported', 'UNKNOWN'],
['', 'UNKNOWN'],
];
console.log('# Tableau des messages');
for (const [text, expected] of CASES) {
const r = errors.classify(text);
check(`${expected.padEnd(18)} <- ${text.slice(0, 90)}`, r.cls === expected, r);
}
console.log('# Combinaisons (ligne par ligne)');
{
// L'ancien bug : un bloc contenant [youtube] était ignoré. Ici l'erreur est noyée dans du bruit.
const noisy = [
'[youtube] Extracting URL: https://www.youtube.com/watch?v=jNQXAC9IVRw',
'[youtube] jNQXAC9IVRw: Downloading webpage',
'WARNING: [youtube] jNQXAC9IVRw: mweb client https formats require a GVS PO Token which was not provided.',
'ERROR: [youtube] jNQXAC9IVRw: Sign in to confirm you’re not a bot. Use --cookies-from-browser or --cookies for the authentication.',
].join('\r\n');
const r = errors.classify(noisy);
check('ERROR prime sur WARNING (BOT_CHECK, indice POT)', r.cls === 'BOT_CHECK' && r.hints.includes('POT_MISSING') && r.retry === 'route', r);
check('message sans préfixe ERROR:', r.message.startsWith('[youtube] jNQXAC9IVRw: Sign in'), r.message);
const rootCause = 'WARNING: [youtube] x: n challenge solving failed: Some formats may be missing.\nERROR: [youtube] x: Requested format is not available. Use --list-formats';
check('format indisponible + défi JS -> JS_CHALLENGE', errors.classify(rootCause).cls === 'JS_CHALLENGE');
const sabrEmpty = 'WARNING: [youtube] x: Some web client https formats have been skipped as they are missing a URL. YouTube may have enabled the SABR-only streaming experiment\nERROR: The downloaded file is empty';
check('fichier vide + SABR -> SABR', errors.classify(sabrEmpty).cls === 'SABR');
const rotatedBot = 'WARNING: [youtube] The provided YouTube account cookies are no longer valid.\nERROR: [youtube] x: Sign in to confirm you’re not a bot.';
const rb = errors.classify(rotatedBot);
check('rotation + bot : cls BOT_CHECK, drapeau cookiesRotated', rb.cls === 'BOT_CHECK' && rb.cookiesRotated === true, rb);
const rotatedOnly = errors.classify('WARNING: [youtube] The provided YouTube account cookies are no longer valid.');
check('rotation seule -> COOKIES_ROTATED', rotatedOnly.cls === 'COOKIES_ROTATED' && rotatedOnly.cookiesRotated, rotatedOnly);
const retry403 = '[download] Got error: HTTP Error 403: Forbidden. Retrying (1/3)...\n[download] Got error: HTTP Error 403: Forbidden. Retrying (2/3)...\nERROR: unable to download video data: HTTP Error 403: Forbidden';
check('403 avec réessais -> HTTP_403 (retry client)', errors.classify(retry403).cls === 'HTTP_403' && errors.classify(retry403).retry === 'client');
check('un WARNING citant "HTTP Error 403" n\'est pas une ligne d\'erreur', errors.isErrorLine('WARNING: [youtube] x: mweb client https formats require a GVS PO Token which was not provided. They will be skipped as they may yield HTTP Error 403.') === false);
check('tableau de lignes accepté', errors.classify(['x', 'ERROR: Private video']).cls === 'PRIVATE');
check('chaque classe a une action', errors.CLASSES.every(c => ['route', 'cookies', 'client', 'none'].includes(errors.RETRY[c])));
}
console.log('# sanitize');
{
const s = errors.sanitize('[debug] Command-line config: [\'--cookies\', \'C:\\\\Temp\\\\chopin-ytc-AbC123\\\\cookies.txt\', \'--proxy\', \'http://user:secret@warp:1080\'] --cookies /tmp/chopin-ytc-x1/cookies.txt Cookie: SID=abcdef; HSID=zzz Authorization: SAPISIDHASH 123_abc SAPISID=VALUE123 __Secure-3PSID=SECRETVALUE po_token=mweb.gvs+AAAAAAAAAAAA');
check('aucun secret', !/secret|abcdef|VALUE123|SECRETVALUE|AAAAAAAAAAAA|123_abc|AbC123|x1\//.test(s), s);
check('proxy masqué', s.includes('http://***@warp:1080'), s);
check('texte normal inchangé', errors.sanitize('ERROR: [youtube] abc: Video unavailable') === 'ERROR: [youtube] abc: Video unavailable');
check('null -> ""', errors.sanitize(null) === '');
}
done();