Files
yt-dlp-bot/app/download.go
2026-03-05 21:42:56 -05:00

110 lines
3.2 KiB
Go

package main
import (
"fmt"
"log"
"github.com/bwmarrin/discordgo"
)
// startAsyncDownload initiates a download in a goroutine and handles progress updates
func startAsyncDownload(s *discordgo.Session, i *discordgo.InteractionCreate, requester, url, videoFormatID, videoFormatName, audioFormatID, audioFormatName, outputDir, tempDir string) {
progressChan := make(chan ProgressUpdate, 1)
resultChan := make(chan DownloadResult, 1)
// Start download in goroutine
go func() {
defer close(resultChan)
defer func() {
if r := recover(); r != nil {
// Handle panic from DownloadVideo
resultChan <- DownloadResult{
Success: false,
Message: fmt.Sprintf("❌ **Download Failed**: %v", r),
URL: url,
Format: fmt.Sprintf("video: %s, audio: %s", videoFormatID, audioFormatID),
Error: fmt.Errorf("%v", r),
}
}
}()
// Call DownloadVideo (it panics on error instead of returning error)
DownloadVideo(outputDir, tempDir, url, DownloadOptions{
EmbedThumbnail: true,
IncludeSubtitles: true,
VideoFormatID: videoFormatID,
AudioFormatID: audioFormatID,
}, progressChan)
// If we reach here, download was successful
resultChan <- DownloadResult{
Success: true,
Message: "✅ **Successfully Downloaded**",
URL: url,
Format: fmt.Sprintf("video: %s, audio: %s", videoFormatID, audioFormatID),
Error: nil,
}
}()
// Handle progress and results asynchronously
go func() {
_, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{
Content: ptr(fmt.Sprintf("%s **Starting Download**", loading_emoji)),
})
if err != nil {
log.Printf("Error updating interaction: %v", err)
}
for {
select {
case prog, ok := <-progressChan:
if !ok {
progressChan = nil
continue
}
var content string
if prog.Phase == "post-processing" {
content = fmt.Sprintf("%s **Post Processing**", loading_emoji)
} else {
var progressStr string
if prog.DownloadedBytes > 0 {
progressStr = formatBytes(prog.DownloadedBytes) + " downloaded"
} else {
progressStr = "starting..."
}
content = fmt.Sprintf("%s **Downloading Video**: %s", loading_emoji, progressStr)
}
_, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{
Content: ptr(content),
})
if err != nil {
log.Printf("Error updating progress: %v", err)
}
case result := <-resultChan:
if result.Success {
_, err = s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{
Content: ptr("✅ **Successfully Downloaded**"),
})
_, err = s.FollowupMessageCreate(i.Interaction, false, &discordgo.WebhookParams{
Content: fmt.Sprintf("## Video Downloaded \n**URL**: %s \n**Quality**: %s + %s \n**Requested By**: <@%s> \n", result.URL, videoFormatName, audioFormatName, requester),
})
if err != nil {
log.Printf("Error updating interaction: %v", err)
}
} else {
_, err = s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{
Content: ptr("❌ **Download Failed**: " + result.Message),
})
if err != nil {
log.Printf("Error updating interaction: %v", err)
}
}
return
}
}
}()
}