- YouTube MP3/MP4: replaced dead savetube.media + ytdlpyton.nvlgroup.my.id with yt-dlp subprocess - Added find_ytdlp() + run_ytdlp_json() helpers with spawn_blocking for >64KB stdout - Fixed all resp['key'] -> resp.get('key') panics in Twitter, Spotify, KrakenFiles, Danbooru - Removed dead fetch_youtube_v2_mp3/mp4 + decrypt_savetube functions - ScraperError::Http -> AppError::ScraperError -> HTTP 502 instead of 500 - All endpoints now return graceful 502 with error message instead of crashing 500 Tested with real URLs: - YouTube MP3: 200, success, real audio URL extracted - YouTube MP4: 200, success, 48 format URLs extracted - TikTok: 200 (tikwm provider) - MediaFire: 200 (success)
Port downloaders from Shirokami-API (Node.js): - Instagram/Facebook (snapsave.app, downr.org fallback) - TikTok (tikwm.com) - YouTube MP4/MP3 (savetube.media, ydlp.yard.id) - Spotify, Twitter/X (api.lrm.tube) - Bilibili, Pinterest, MediaFire, Mega, TeraBox - PixelDrain, Threads, DoodStream, KrakenFiles - Danbooru, SoundCloud, Google Drive Domain layer: DownloadResult + MediaItem entities Application layer: 7 use-cases + detect_platform auto-detect Infrastructure: DownloaderRepository (22 fetch functions) Presentation: 21 handlers + DTO + OpenAPI schemas Also: upgrade OpenTelemetry to 0.28 (axum 0.7 conflict resolution)