UNPKG

yt-dlx

Version:

Effortless Audio-Video Downloader And Streamer!

197 lines 9.65 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = extract; const path_1 = __importDefault(require("path")); const colors_1 = __importDefault(require("colors")); const youtubei_1 = require("youtubei"); const zod_1 = require("zod"); const Agent_1 = __importDefault(require("../../../utils/Agent")); const youtubei_js_1 = require("youtubei.js"); const ZodSchema = zod_1.z.object({ query: zod_1.z.string().min(2), useTor: zod_1.z.boolean().optional(), verbose: zod_1.z.boolean().optional() }); function calculateUploadAgo(days) { const years = Math.floor(days / 365); const months = Math.floor((days % 365) / 30); const remainingDays = days % 30; const formattedString = `${years > 0 ? years + " years, " : ""}${months > 0 ? months + " months, " : ""}${remainingDays} days`; return { years, months, days: remainingDays, formatted: formattedString }; } function calculateVideoDuration(seconds) { const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const remainingSeconds = seconds % 60; const formattedString = `${hours > 0 ? hours + " hours, " : ""}${minutes > 0 ? minutes + " minutes, " : ""}${remainingSeconds} seconds`; return { hours, minutes, seconds: remainingSeconds, formatted: formattedString }; } function formatCount(count) { const abbreviations = ["K", "M", "B", "T"]; for (let i = abbreviations.length - 1; i >= 0; i--) { const size = Math.pow(10, (i + 1) * 3); if (size <= count) { const formattedCount = Math.round((count / size) * 10) / 10; return `${formattedCount}${abbreviations[i]}`; } } return `${count}`; } async function fetchCommentsByVideoId(videoId, verbose) { try { if (verbose) console.log(colors_1.default.green("@info:"), `Workspaceing comments for video ID: ${videoId}`); const youtubeInnertube = await youtubei_js_1.Innertube.create({ user_agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", cache: new youtubei_js_1.UniversalCache(true, path_1.default.join(process.cwd(), "YouTubeDLX")), }); const response = await youtubeInnertube.getComments(videoId); const comments = response.contents .map(thread => { const comment = thread?.comment; if (!comment || !comment.content?.text || !comment.published_time || !comment.author?.name) return null; return { comment_id: comment.comment_id || "", is_pinned: comment.is_pinned || false, comment: comment.content.text, published_time: comment.published_time, author_is_channel_owner: comment.author_is_channel_owner || false, creator_thumbnail_url: comment.creator_thumbnail_url || "", like_count: comment.like_count || 0, is_member: comment.is_member || false, author: comment.author.name, is_hearted: comment.is_hearted || false, is_liked: comment.is_liked || false, is_disliked: comment.is_disliked || false, reply_count: comment.reply_count || 0, hasReplies: thread.has_replies || false, }; }) .filter((item) => item !== null); if (comments.length === 0) { if (verbose) console.log(colors_1.default.red("@error:"), "No comments found for the video"); return null; } if (verbose) console.log(colors_1.default.green("@info:"), "Video comments fetched!"); return comments; } catch (error) { if (verbose) console.error(colors_1.default.red("@error: ") + error.message); return null; } } async function fetchVideoTranscript(videoId, verbose) { try { if (verbose) console.log(colors_1.default.green("@info:"), `Workspaceing transcript for video ID: ${videoId}`); const youtube = new youtubei_1.Client(); const captions = await youtube.getVideoTranscript(videoId); if (!captions) { if (verbose) console.log(colors_1.default.red("@error:"), "No transcript found for the video"); return null; } const transcript = captions.map(caption => ({ text: caption.text, start: caption.start, duration: caption.duration, segments: caption.segments.map(segment => ({ utf8: segment.utf8, tOffsetMs: segment.tOffsetMs, acAsrConf: segment.acAsrConf })), })); if (verbose) console.log(colors_1.default.green("@info:"), "Video transcript fetched!"); return transcript; } catch (error) { if (verbose) console.error(colors_1.default.red("@error: ") + error.message); return null; } } async function extract(options) { try { const { query, useTor, verbose } = ZodSchema.parse(options); const metaBody = await (0, Agent_1.default)({ query, verbose, useTor }); if (!metaBody) { throw new Error(`${colors_1.default.red("@error:")} Unable to get response!`); } if (!metaBody.metaData) { throw new Error(`${colors_1.default.red("@error:")} Metadata not found in the response!`); } let uploadDate; try { if (metaBody.metaData.upload_date) { uploadDate = new Date(metaBody.metaData.upload_date.replace(/(\d{4})(\d{2})(\d{2})/, "$1-$2-$3")); } } catch (error) { throw new Error(`${colors_1.default.red("@error:")} Failed to parse upload date: ${error instanceof Error ? error.message : String(error)}`); } const currentDate = new Date(); const daysAgo = uploadDate ? Math.floor((currentDate.getTime() - uploadDate.getTime()) / (1000 * 60 * 60 * 24)) : 0; const prettyDate = uploadDate?.toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric" }) || "N/A"; const uploadAgoObject = calculateUploadAgo(daysAgo); const videoTimeInSeconds = metaBody.metaData.duration; const videoDuration = calculateVideoDuration(videoTimeInSeconds); const viewCountFormatted = metaBody.metaData.view_count !== undefined ? formatCount(metaBody.metaData.view_count) : "N/A"; const likeCountFormatted = metaBody.metaData.like_count !== undefined ? formatCount(metaBody.metaData.like_count) : "N/A"; const commentCountFormatted = metaBody.metaData.comment_count !== undefined ? formatCount(metaBody.metaData.comment_count) : "N/A"; const channelFollowerCountFormatted = metaBody.metaData.channel_follower_count !== undefined ? formatCount(metaBody.metaData.channel_follower_count) : "N/A"; const commentsPromise = fetchCommentsByVideoId(metaBody.metaData.id, verbose ?? false); const transcriptPromise = fetchVideoTranscript(metaBody.metaData.id, verbose ?? false); const [comments, transcript] = await Promise.all([commentsPromise, transcriptPromise]); const payload = { BestAudioLow: metaBody.BestAudioLow, BestAudioHigh: metaBody.BestAudioHigh, BestVideoLow: metaBody.BestVideoLow, BestVideoHigh: metaBody.BestVideoHigh, AudioLowDRC: metaBody.AudioLowDRC, AudioHighDRC: metaBody.AudioHighDRC, AudioLow: metaBody.AudioLow, AudioHigh: metaBody.AudioHigh, VideoLowHDR: metaBody.VideoLowHDR, VideoHighHDR: metaBody.VideoHighHDR, VideoLow: metaBody.VideoLow, VideoHigh: metaBody.VideoHigh, ManifestLow: metaBody.ManifestLow, ManifestHigh: metaBody.ManifestHigh, meta_data: { ...metaBody.metaData, view_count_formatted: viewCountFormatted, like_count_formatted: likeCountFormatted, duration: videoDuration.seconds, upload_date: prettyDate, upload_ago: daysAgo, upload_ago_formatted: uploadAgoObject, comment_count_formatted: commentCountFormatted, channel_follower_count_formatted: channelFollowerCountFormatted, }, comments, transcript, }; if (verbose) console.log(colors_1.default.green("@info:"), "❣️ Thank you for using yt-dlx. Consider 🌟starring the GitHub repo https://github.com/yt-dlx."); return { data: payload }; } catch (error) { if (error instanceof zod_1.ZodError) { const errorMessage = `${colors_1.default.red("@error:")} Argument validation failed: ${error.errors.map(e => `${e.path.join(".")}: ${e.message}`).join(", ")}`; console.error(errorMessage); throw new Error(errorMessage); } else if (error instanceof Error) { console.error(error.message); throw error; } else { const unexpectedError = `${colors_1.default.red("@error:")} An unexpected error occurred: ${String(error)}`; console.error(unexpectedError); throw new Error(unexpectedError); } } finally { } } //# sourceMappingURL=Extract.js.map