import got from 'got'; import * as cheerio from 'cheerio'; import { TwitterDlArgsSchema, TwitterDLResponseSchema, TwitterDlSchema } from '../types/twitter-v1.js'; import { DEFAULT_HEADERS } from '../constant.js'; import { stringifyCookies, generateTokenId } from './util.js'; export async function twitterdl(url) { if (!url || typeof url !== 'string') { throw new Error("Invalid or missing URL parameter."); } TwitterDlArgsSchema.parse([url]); const idMatch = url.match(/status\/(\d+)/) || url.match(/(\d+)/); if (!idMatch) { throw new Error("Invalid Twitter URL: Cannot extract tweet ID."); } const id = idMatch[1]; const token = generateTokenId(id); try { const data = await got(`https://api.redketchup.io/tweetAttachments-v6?id=${encodeURIComponent(token)}`, { headers: { ...DEFAULT_HEADERS, origin: 'https://redketchup.io', referer: 'https://redketchup.io/', } }).json(); if (!data || !data.includes || !data.includes.media) { throw new Error("Invalid API response: Missing media data."); } const json = TwitterDLResponseSchema.parse(data); const videos = json.includes.media .filter((m) => m.type === 'video') .flatMap((m) => m.variants) .filter((v) => v.content_type !== 'application/x-mpegURL'); const result = Array.isArray(videos) ? videos : [videos]; return result // return TwitterDlSchema.parse(result); } catch (error) { console.error("Error fetching Twitter video:", error.message); throw new Error("Failed to fetch Twitter video. Please try again later."); } }