Files
uptodownbot/internal/domain/types.go
db123 cd27b4d28d feat: add thumbnail preview, audio-only detection, /download command, tests, and bugfixes
- Add thumbnail preview with metadata (title, uploader, duration) before download
- Auto-detect audio-only sites (Spotify, SoundCloud, etc.) and skip type selection
- Add /download command for feature parity with UI button
- Fix yt-dlp defer bug: StatusFailed was overwritten to StatusCompleted
- Fix handleURLInput using editText with msgID=0 (now uses sendWithKB)
- Fix filename detection: use job ID prefix for reliable file finding
- Fix double answerCb between handleBackStep and handleDownloadPrompt
- Fix runDownload unused msgID parameter
- Fix context for download goroutine (use context.Background)
- Remove unused startWebhook h parameter
- Remove dead buildToggleKeyboard function
- Add formatBytes, formatDuration, formatLabelForDisplay tests
- Add IsAudioOnlyContent, MediaType.String tests
- Add repo integration tests (users, preferences, quotas, history, delete)
- Add cmd/bot tests (parseAllowedUsers, env helpers)
- Add edge case tests for progress parser
- Add zero/negative safety guard in formatDuration
- Add .gitea, TODO.md, opencode.json to gitignore
2026-06-25 15:07:31 +03:30

176 lines
3.5 KiB
Go

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
Uploader string
Thumbnail string
Duration float64
Formats []Format
Languages []string
IsPlaylist bool
PlaylistCount int
PlaylistEntries []PlaylistEntry
EstimatedSize int64
}
// IsAudioOnlyContent returns true when no format carries a video stream.
func (m *MediaInfo) IsAudioOnlyContent() bool {
for _, f := range m.Formats {
if f.HasVideo {
return false
}
}
return len(m.Formats) > 0
}
// 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
}