- Add 'ask' option to audio/video quality settings (stored as '' in DB)
- Auto-select when both media type AND quality are set; show filtered
format picker when quality is Ask
- Auto-skip language picker when user has a matching language preference
- Remux audio-only downloads to m4a instead of webm for Telegram compat
- Update README to document the new flow and m4a audio output
- Add MediaTypeAsk (0) as the default, mapping old video_audio to Ask
- Show Video/Audio/Ask type picker when no default media type is set
- Auto-select matching format and skip picker when defaults are configured
- Add autoSelectVideoFormat / autoSelectAudioFormat helpers with closest-match
- Add buildFilteredFormatList for type-filtered format lists
- Add Media Type setting in settings UI (Ask/Video/Audio)
- Add --merge-output-format mp4 for video downloads via yt-dlp
- Fix formatLabelForDisplay to show Height fallback and Extension
- Add cookies volume mount to docker-compose.yml
- Document cookies setup and new features in README
- Remove playlist handler, keyboard, and all related callback routing
- Strip playlist parameter from YouTube Music radio URLs, reject pure playlists
- Send media preview before format selection prompt (correct ordering)
- Remove DetectPlaylist/GetPlaylistInfo methods (no longer needed)
- Remove IsPlaylist, PlaylistCount, PlaylistEntries from MediaInfo
- Remove PlaylistState struct, keep PlaylistEntry for search results
- Update README to reflect removal of playlist feature
- Add PIP_BREAK_SYSTEM_PACKAGES=1 to install hanime-plugin via pip
- Install Deno JS runtime required by the plugin's extractors
- Document plugin setup and JS runtime requirement in README
- Note plugin support in feature list
- Remove container picker UI, keyboard, settings, and ContainerOptions
entirely — yt-dlp handles container format automatically
- Remove Container field from DownloadJob struct and related references
- Extract buildFormatList helper to deduplicate format list building
between handleURLInput and handleBackStep
- Break runDownload into trackDownloadProgress + handleDownloadCompletion
- Add HTTP timeout (30s) to downloadFile helper
- Log applyQuota and AddHistory errors instead of discarding
- Log nil stepState warnings in all handler entry points
- Include job.StderrLog in download failure messages
- Add tests for buildFormatList, findFormatByID, determineMediaType,
and buildFormatString
- Update README with search, DRM fallback, and quota feature docs
- Remove unused strings import from keyboard.go
- 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
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.