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, url, videoFormatID, audioFormatID, 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: "Video Downloaded Successfully!", URL: url, Format: fmt.Sprintf("video: %s, audio: %s", videoFormatID, audioFormatID), Error: nil, } }() // Handle progress and results asynchronously go func() { // First update the original ephemeral message with "Processing..." _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{ Content: ptr(fmt.Sprintf("šŸ”„ Processing download...\nURL: %s\nVideo: %s\nAudio: %s", url, videoFormatID, audioFormatID)), }) if err != nil { log.Printf("Error updating interaction: %v", err) } for { select { case prog, ok := <-progressChan: if !ok { progressChan = nil continue } // Update message w/ phase and real time progress phaseEmoji := "ā¬" if prog.Phase == "post-processing" { phaseEmoji = "āš™ļø" } content := fmt.Sprintf("%s %s\n%s @ %s [eta: %s]\nšŸ“„ %s", phaseEmoji, prog.Phase, prog.Status, prog.Percent, prog.ETA, prog.Filename) _, err := s.InteractionResponseEdit(i.Interaction, &discordgo.WebhookEdit{ Content: ptr(content), }) if err != nil { log.Printf("Error updating progress: %v", err) } case result := <-resultChan: // Handle completion if result.Success { _, err = s.FollowupMessageCreate(i.Interaction, false, &discordgo.WebhookParams{ Content: "šŸ“„ Video downloaded: " + result.URL, }) 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 } } }() }