- Split single sync.Mutex into per-map mutexes (activeJobs, stepStates,
rateLimiter, pendingInput, cancelFuncs) to reduce contention
- Add download semaphore (channel-buffered, 3 concurrent) as worker pool
- Add cancelFuncs map with context cancellation wired into download
goroutines for clean shutdown
- Replace playlist busy-poll (500ms sleep loop) with synchronous
runDownload + Done channel for completion tracking
- Use full UUID for job IDs instead of 8-char prefix
- Download thumbnail URL to temp file before sending (InputFileUpload)
- Change MAX_FILE_SIZE_MB default from 2000 to 50
- Clean up cancel funcs after normal download completion
- Add in-memory LRU cache (200 entries, 30 min TTL) to yt-dlp Client for
GetMediaInfo and GetPlaylistInfo results, avoiding redundant yt-dlp calls
for the same URL within a session
- Add YouTube (/search) and YouTube Music (/music) search with paginated
results (5 per page), user selects a result to start the download flow
- Add SearchState type, new search.go handler, search results keyboard with
< > navigation and New Search button
- Add Search button to main menu keyboard
- Update help text with new commands
Add StderrLog field to DownloadJob and collect all stderr lines during
download. Log the captured stderr output when a download fails to help
diagnose exit code 2 errors (geo-restrictions, auth, etc.).
- Rename 'Format' button to 'Quality' in settings (audio_quality/video_quality)
- Add DefaultAudioContainer and DefaultVideoContainer to UserPreferences
- Container settings now has Audio/Video sub-pickers (mp3/m4a/opus vs mp4/mkv/webm)
- Add migration 003 for new container columns
- Update repo layer and playlist flow for new fields
- Update back routing: back_quality, back_container
- Replace Type/Quality settings with single Format button -> Audio/Video sub-pickers
- Each sub-picker shows format options (bitrates for audio, resolutions for video)
- Replace DefaultQuality with DefaultAudioFormat/DefaultVideoFormat in UserPreferences
- Add DB migration 002 for new preference columns
- Update repo layer SQL queries for new schema
- Update playlist flow to use new preference fields
- Fix missing deleteaccount and delaccount_ callback routing
- Add back_format routing for format picker navigation
- Replace type/quality selection flow with unified format list (video+audio combined)
- Add independent audio/video format picking: video-only formats prompt for audio track,
audio-only formats offer optional video addition (skip when content is audio-only)
- Fix formatKeyboard to use format IDs as callback data instead of display labels
- Remove dead mediaTypeKeyboard function
- Fix double-close panic in readProgress (caller is sole owner of updates channel)
- Add FormatString field to DownloadJob for composite format specs (e.g. '137+140')
- Change quota calculation from sum of all format sizes to max single format size
- Fix 'Delete all data' button to use danger style with proper text
- Clean up routePrefixedCallback: remove type_/quality_, add format_/secondary_ routes
- Fix back navigation to rebuild format IDs list
Telegram bot for downloading media from any site using yt-dlp.
Supports audio/video/both, quality selection, language picker,
container format selection, playlist pagination, progress updates,
per-user quotas, user preferences, download history, cancel at any step,
polling and webhook modes, proxy support, and SQLite persistence.