feat: initial implementation of uptodownbot

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.
This commit is contained in:
2026-06-25 14:22:48 +03:30
commit 05fcdf7458
26 changed files with 3302 additions and 0 deletions

163
internal/domain/types.go Normal file
View File

@@ -0,0 +1,163 @@
package domain
import "os/exec"
// MediaType represents the type of media the user wants to download.
type MediaType int
const (
MediaTypeAudio MediaType = iota + 1
MediaTypeVideo
MediaTypeVideoAudio
)
func (m MediaType) String() string {
switch m {
case MediaTypeAudio:
return "audio"
case MediaTypeVideo:
return "video"
case MediaTypeVideoAudio:
return "video_audio"
default:
return "unknown"
}
}
// Format represents a downloadable format from yt-dlp.
type Format struct {
ID string
Extension string
Width int
Height int
Resolution string
Filesize int64
Codec string
Bitrate string
Language string
IsAudioOnly bool
IsVideoOnly bool
HasAudio bool
HasVideo bool
}
// MediaInfo holds the full information about a downloadable media item.
type MediaInfo struct {
URL string
Title string
Duration float64
Formats []Format
Languages []string
IsPlaylist bool
PlaylistCount int
PlaylistEntries []PlaylistEntry
EstimatedSize int64
}
// PlaylistEntry represents a single entry in a playlist.
type PlaylistEntry struct {
ID string
Title string
URL string
Duration float64
}
// DownloadStatus represents the current state of a download job.
type DownloadStatus int
const (
StatusPending DownloadStatus = iota
StatusFetching
StatusDownloading
StatusProcessing
StatusCompleted
StatusFailed
StatusCancelled
)
func (s DownloadStatus) String() string {
switch s {
case StatusPending:
return "Pending"
case StatusFetching:
return "Fetching info"
case StatusDownloading:
return "Downloading"
case StatusProcessing:
return "Processing"
case StatusCompleted:
return "Completed"
case StatusFailed:
return "Failed"
case StatusCancelled:
return "Cancelled"
default:
return "Unknown"
}
}
// DownloadJob represents an active download process for a user.
type DownloadJob struct {
ID string
UserID int64
ChatID int64
MessageID int
URL string
MediaType MediaType
SelectedFormat *Format
Container string
Language string
Status DownloadStatus
Progress float64
Speed string
ETA string
FileSize int64
FilePath string
Title string
QuotaApplied bool
CancelCh chan struct{}
Cmd *exec.Cmd
}
// UserPreferences holds per-user default preferences.
type UserPreferences struct {
DefaultMediaType MediaType
DefaultQuality string
DefaultContainer string
DefaultLanguage string
}
// UserQuotas holds the quota usage and limits for a user.
type UserQuotas struct {
DailyLimitMB int64
DailyUsedMB int64
DailyDate string
WeeklyLimitMB int64
WeeklyUsedMB int64
WeekStart string
MonthlyLimitMB int64
MonthlyUsedMB int64
MonthStart string
}
// DownloadRecord is a completed download entry stored in history.
type DownloadRecord struct {
ID int64
UserID int64
URL string
Title string
MediaType string
FormatID string
Container string
FileSize int64
Status string
CreatedAt string
}
// PlaylistState tracks the user's current playlist selection flow.
type PlaylistState struct {
Entries []PlaylistEntry
Page int
PerPage int
Selected map[string]bool
}