From 944b0211c67a4d57f810d2a72f426d46a5a663c4 Mon Sep 17 00:00:00 2001 From: kevinwatt Date: Sun, 23 Feb 2025 05:53:58 +0800 Subject: [PATCH] feat: add random filename fallback when filename cannot be retrieved - Add generateRandomFilename utility function - Modify downloadVideo to use random filename when yt-dlp fails to get filename - Update version to 0.6.26 --- package.json | 2 +- src/index.mts | 2 +- src/modules/utils.ts | 19 +++++++++++++++++++ src/modules/video.ts | 26 +++++++++++++++----------- 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 951da8e..40c35b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kevinwatt/yt-dlp-mcp", - "version": "0.6.25", + "version": "0.6.26", "description": "An MCP server implementation that integrates with yt-dlp, providing video and audio content download capabilities (e.g. YouTube, Facebook, Tiktok, etc.) for LLMs.", "keywords": [ "mcp", diff --git a/src/index.mts b/src/index.mts index 4e521ec..2310dc1 100644 --- a/src/index.mts +++ b/src/index.mts @@ -17,7 +17,7 @@ import { downloadVideo } from "./modules/video.js"; import { downloadAudio } from "./modules/audio.js"; import { listSubtitles, downloadSubtitles } from "./modules/subtitle.js"; -const VERSION = '0.6.25'; +const VERSION = '0.6.26'; /** * Validate system configuration diff --git a/src/modules/utils.ts b/src/modules/utils.ts index b177e06..70d897f 100644 --- a/src/modules/utils.ts +++ b/src/modules/utils.ts @@ -1,5 +1,6 @@ import * as fs from 'fs'; import { spawn } from 'child_process'; +import { randomBytes } from 'crypto'; /** * Validates if a given string is a valid URL. @@ -126,4 +127,22 @@ export function getFormattedTimestamp(): string { .replace(/[:.]/g, '-') .replace('T', '_') .split('.')[0]; +} + +/** + * Generates a random filename with timestamp prefix. + * + * @param extension - Optional file extension (default: 'mp4') + * @returns A random filename with timestamp + * + * @example + * ```typescript + * const filename = generateRandomFilename('mp3'); + * console.log(filename); // '2024-03-20_12-30-00_a1b2c3d4.mp3' + * ``` + */ +export function generateRandomFilename(extension: string = 'mp4'): string { + const timestamp = getFormattedTimestamp(); + const randomId = randomBytes(4).toString('hex'); + return `${timestamp}_${randomId}.${extension}`; } \ No newline at end of file diff --git a/src/modules/video.ts b/src/modules/video.ts index 5e43b78..bf30821 100644 --- a/src/modules/video.ts +++ b/src/modules/video.ts @@ -5,7 +5,8 @@ import { _spawnPromise, validateUrl, getFormattedTimestamp, - isYouTubeUrl + isYouTubeUrl, + generateRandomFilename } from "./utils.js"; /** @@ -76,27 +77,30 @@ export async function downloadVideo( format = "bestvideo[height>=720]+bestaudio/best[height>=720]/best"; } } - - // 使用安全的文件名模板 - const outputTemplate = path.join( - userDownloadsDir, - sanitizeFilename(`%(title)s [%(id)s] ${timestamp}`, config.file) + '.%(ext)s' - ); - // Get expected filename + let outputTemplate: string; let expectedFilename: string; + try { + // 嘗試獲取檔案名稱 + outputTemplate = path.join( + userDownloadsDir, + sanitizeFilename(`%(title)s [%(id)s] ${timestamp}`, config.file) + '.%(ext)s' + ); + expectedFilename = await _spawnPromise("yt-dlp", [ "--get-filename", "-f", format, "--output", outputTemplate, url ]); + expectedFilename = expectedFilename.trim(); } catch (error) { - throw new Error(`Failed to get filename: ${error instanceof Error ? error.message : String(error)}`); + // 如果無法獲取檔案名稱,使用隨機檔案名 + const randomFilename = generateRandomFilename('mp4'); + outputTemplate = path.join(userDownloadsDir, randomFilename); + expectedFilename = randomFilename; } - - expectedFilename = expectedFilename.trim(); // Download with progress info try {