UNPKG

newpipe-extractor-js

Version:
199 lines 6.96 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.YoutubeLinkHandler = void 0; class YoutubeLinkHandler { acceptUrl(url) { try { this.getId(url); return true; } catch (error) { return false; } } getId(url) { try { // Handle scheme-specific URLs first const uri = new URL(url); const scheme = uri.protocol.replace(':', ''); if (scheme === 'vnd.youtube' || scheme === 'vnd.youtube.launch') { const schemeSpecificPart = uri.pathname; if (schemeSpecificPart.startsWith('//')) { const extractedId = this.extractId(schemeSpecificPart.substring(2)); if (extractedId) { return extractedId; } url = 'https:' + schemeSpecificPart; } else { return this.assertIsId(schemeSpecificPart); } } } catch (e) { // Continue with regular URL parsing } let urlObj; try { urlObj = new URL(url); } catch (e) { throw new Error('The given URL is not valid'); } const host = urlObj.hostname; let path = urlObj.pathname; // Remove leading "/" of URL-path if URL-path is given if (path.startsWith('/')) { path = path.substring(1); } if (!this.isValidYouTubeHost(host)) { if (host.toLowerCase() === 'googleads.g.doubleclick.net') { throw new Error('Error: found ad: ' + url); } throw new Error('The URL is not a YouTube URL'); } // Handle different host patterns switch (host.toUpperCase()) { case 'WWW.YOUTUBE-NOCOOKIE.COM': if (path.startsWith('embed/')) { return this.assertIsId(path.substring(6)); } break; case 'YOUTUBE.COM': case 'WWW.YOUTUBE.COM': case 'M.YOUTUBE.COM': case 'MUSIC.YOUTUBE.COM': if (path === 'attribution_link') { const uQueryValue = urlObj.searchParams.get('u'); if (uQueryValue) { const decodedURL = new URL('https://www.youtube.com' + uQueryValue); const viewQueryValue = decodedURL.searchParams.get('v'); return this.assertIsId(viewQueryValue); } } // Check subpaths const maybeId = this.getIdFromSubpathsInPath(path); if (maybeId) { return maybeId; } // Check 'v' parameter const viewQueryValue = urlObj.searchParams.get('v'); return this.assertIsId(viewQueryValue); case 'Y2U.BE': case 'YOUTU.BE': const vParam = urlObj.searchParams.get('v'); if (vParam) { return this.assertIsId(vParam); } return this.assertIsId(path); default: // Handle Invidious and other alternative frontends if (this.isAlternativeFrontend(host)) { const maybeIdAlt = this.getIdFromSubpathsInPath(path); if (maybeIdAlt) { return maybeIdAlt; } const vParamAlt = urlObj.searchParams.get('v'); return this.assertIsId(vParamAlt); } break; } throw new Error('Could not extract video ID from URL: ' + url); } getUrl(id) { return `https://www.youtube.com/watch?v=${id}`; } extractId(id) { if (!id) return null; const match = YoutubeLinkHandler.VIDEO_ID_REGEX.exec(id); return match ? match[1] : null; } assertIsId(id) { const extractedId = this.extractId(id); if (extractedId) { return extractedId; } throw new Error('The given string is not a YouTube video ID'); } getIdFromSubpathsInPath(path) { for (const subpath of YoutubeLinkHandler.SUBPATHS) { if (path.startsWith(subpath)) { const remainingPath = path.substring(subpath.length); // Extract video ID from remaining path const slashIndex = remainingPath.indexOf('/'); const videoId = slashIndex > 0 ? remainingPath.substring(0, slashIndex) : remainingPath; const extractedId = this.extractId(videoId); if (extractedId) { return extractedId; } } } return null; } isValidYouTubeHost(host) { const upperHost = host.toUpperCase(); // Main YouTube domains const youtubeDomains = [ 'YOUTUBE.COM', 'WWW.YOUTUBE.COM', 'M.YOUTUBE.COM', 'MUSIC.YOUTUBE.COM', 'WWW.YOUTUBE-NOCOOKIE.COM' ]; // Short URL domains const shortDomains = [ 'YOUTU.BE', 'Y2U.BE' ]; return youtubeDomains.includes(upperHost) || shortDomains.includes(upperHost) || this.isAlternativeFrontend(host); } isAlternativeFrontend(host) { const upperHost = host.toUpperCase(); // Alternative frontends (based on Java implementation) const altFrontends = [ 'HOOKTUBE.COM', 'INVIDIO.US', 'DEV.INVIDIO.US', 'WWW.INVIDIO.US', 'REDIRECT.INVIDIOUS.IO', 'INVIDIOUS.SNOPYTA.ORG', 'YEWTU.BE', 'TUBE.CONNECT.CAFE', 'TUBUS.EDUVID.ORG', 'INVIDIOUS.KAVIN.ROCKS', 'INVIDIOUS-US.KAVIN.ROCKS', 'PIPED.KAVIN.ROCKS', 'INVIDIOUS.SITE', 'VID.MINT.LGBT', 'INVIDIOU.SITE', 'INVIDIOUS.FDN.FR', 'INVIDIOUS.048596.XYZ', 'INVIDIOUS.ZEE.LI', 'VID.PUFFYAN.US', 'YTPRIVATE.COM', 'INVIDIOUS.NAMAZSO.EU', 'INVIDIOUS.SILKKY.CLOUD', 'INVIDIOUS.EXONIP.DE', 'INV.RIVERSIDE.ROCKS', 'INVIDIOUS.BLAMEFRAN.NET', 'INVIDIOUS.MOOMOO.ME', 'YTB.TROM.TF', 'YT.CYBERHOST.UK' ]; return altFrontends.includes(upperHost); } } exports.YoutubeLinkHandler = YoutubeLinkHandler; YoutubeLinkHandler.VIDEO_ID_REGEX = /^([a-zA-Z0-9_-]{11})/; YoutubeLinkHandler.SUBPATHS = [ 'embed/', 'live/', 'shorts/', 'watch/', 'v/', 'w/' ]; //# sourceMappingURL=YoutubeLinkHandler.js.map