114 lines
9.1 KiB
JavaScript
114 lines
9.1 KiB
JavaScript
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();
|