Skip to main content
Glama

YouTube MCP Server

by kevinwatt
utils.ts4.75 kB
import * as fs from 'fs'; import { spawn } from 'child_process'; import { randomBytes } from 'crypto'; /** * Validates if a given string is a valid URL. * * @param url - The URL string to validate * @returns True if the URL is valid, false otherwise * * @example * ```typescript * if (validateUrl('https://youtube.com/watch?v=...')) { * // URL is valid * } * ``` */ export function validateUrl(url: string): boolean { try { new URL(url); return true; } catch { return false; } } /** * Checks if a URL is from YouTube. * * @param url - The URL to check * @returns True if the URL is from YouTube, false otherwise * * @example * ```typescript * if (isYouTubeUrl('https://youtube.com/watch?v=...')) { * // URL is from YouTube * } * ``` */ export function isYouTubeUrl(url: string): boolean { try { const parsedUrl = new URL(url); return parsedUrl.hostname.includes('youtube.com') || parsedUrl.hostname.includes('youtu.be'); } catch { return false; } } /** * Safely cleans up a directory and its contents. * * @param directory - Path to the directory to clean up * @returns Promise that resolves when cleanup is complete * @throws {Error} When directory cannot be removed * * @example * ```typescript * try { * await safeCleanup('/path/to/temp/dir'); * } catch (error) { * console.error('Cleanup failed:', error); * } * ``` */ export async function safeCleanup(directory: string): Promise<void> { try { await fs.promises.rm(directory, { recursive: true, force: true }); } catch (error) { console.error(`Error cleaning up directory ${directory}:`, error); } } /** * Spawns a child process and returns its output as a promise. * * @param command - The command to execute * @param args - Array of command arguments * @returns Promise resolving to the command output * @throws {Error} When command execution fails * * @example * ```typescript * try { * const output = await _spawnPromise('yt-dlp', ['--version']); * console.log('yt-dlp version:', output); * } catch (error) { * console.error('Command failed:', error); * } * ``` */ export function _spawnPromise(command: string, args: string[]): Promise<string> { return new Promise((resolve, reject) => { const process = spawn(command, args); let output = ''; process.stdout.on('data', (data) => { output += data.toString(); }); process.stderr.on('data', (data) => { output += data.toString(); }); process.on('close', (code) => { if (code === 0) { resolve(output); } else { reject(new Error(`Failed with exit code: ${code}\n${output}`)); } }); }); } /** * Generates a formatted timestamp string for file naming. * * @returns Formatted timestamp string in the format 'YYYY-MM-DD_HH-mm-ss' * * @example * ```typescript * const timestamp = getFormattedTimestamp(); * console.log(timestamp); // '2024-03-20_12-30-00' * ``` */ export function getFormattedTimestamp(): string { return new Date().toISOString() .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}`; } /** * Cleans SRT subtitle content to produce a plain text transcript. * Removes timestamps, sequence numbers, and HTML tags. * * @param srtContent - Raw SRT subtitle content * @returns Cleaned transcript text * * @example * ```typescript * const cleanedText = cleanSubtitleToTranscript(srtContent); * console.log(cleanedText); // 'Hello world this is a transcript...' * ``` */ export function cleanSubtitleToTranscript(srtContent: string): string { return srtContent .split('\n') .filter(line => { const trimmed = line.trim(); // Remove empty lines if (!trimmed) return false; // Remove sequence numbers (lines that are just digits) if (/^\d+$/.test(trimmed)) return false; // Remove timestamp lines if (/^\d{2}:\d{2}:\d{2}[.,]\d{3}\s*-->\s*\d{2}:\d{2}:\d{2}[.,]\d{3}$/.test(trimmed)) return false; return true; }) .map(line => { // Remove HTML tags return line.replace(/<[^>]*>/g, ''); }) .join(' ') .replace(/\s+/g, ' ') .trim(); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kevinwatt/yt-dlp-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server