From 63a6c3807980217a7a78981ec77a4167c8c27210 Mon Sep 17 00:00:00 2001 From: William P Date: Tue, 10 Feb 2026 22:00:34 -0500 Subject: [PATCH] create download.go for async download function --- app/download.go | 105 ++++++++++++++++++++++++++++++++++++++++++++++++ app/main.go | 97 -------------------------------------------- 2 files changed, 105 insertions(+), 97 deletions(-) create mode 100644 app/download.go diff --git a/app/download.go b/app/download.go new file mode 100644 index 0000000..3a73f93 --- /dev/null +++ b/app/download.go @@ -0,0 +1,105 @@ +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 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, 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 + } + } + }() +} diff --git a/app/main.go b/app/main.go index 77d8780..9eff50e 100644 --- a/app/main.go +++ b/app/main.go @@ -12,103 +12,6 @@ import ( "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 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, 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 - } - } - }() -} - func main() { out_dir := os.Getenv("OUT_PATH")