Parent directory

downloads.go

3324 bytes
  1package handler
  2
  3import (
  4	"context"
  5	"fmt"
  6	"os"
  7	"path/filepath"
  8	"regexp"
  9	"strings"
 10)
 11
 12func sanitizeFilename(title string) string {
 13	title = strings.ReplaceAll(title, " ", "_")
 14
 15	reg := regexp.MustCompile(`[^a-zA-Z0-9_\-\.]`)
 16	title = reg.ReplaceAllString(title, "")
 17
 18	if len(title) > 200 {
 19		title = title[:200]
 20	}
 21
 22	return title
 23}
 24
 25func (h *handler) DownloadVideo(ctx context.Context, videoID string, resolution string) error {
 26	exists, err := h.db.HasVideo(ctx, videoID)
 27	if err != nil {
 28		return fmt.Errorf("failed to check video existence: %w", err)
 29	}
 30	if !exists {
 31		return fmt.Errorf("video not found")
 32	}
 33
 34	if err := h.db.SetVideoDownloadStatus(ctx, videoID, "pending"); err != nil {
 35		return fmt.Errorf("failed to set download status: %w", err)
 36	}
 37
 38	go h.performDownload(videoID, resolution)
 39
 40	return nil
 41}
 42
 43func (h *handler) performDownload(videoID string, resolution string) {
 44	ctx := context.Background()
 45
 46	video, err := h.db.GetVideo(ctx, videoID)
 47	if err != nil {
 48		h.log.Error("Failed to get video for download", "video_id", videoID, "error", err)
 49		if dbErr := h.db.SetVideoDownloadFailed(ctx, videoID, "Failed to get video info"); dbErr != nil {
 50			h.log.Error("Failed to update download status to failed", "video_id", videoID, "error", dbErr)
 51		}
 52		return
 53	}
 54
 55	if err := h.db.SetVideoDownloadStatus(ctx, videoID, "downloading"); err != nil {
 56		h.log.Error("Failed to update download status to downloading", "video_id", videoID, "error", err)
 57		return
 58	}
 59
 60	h.log.Info("Starting video download", "video_id", videoID, "title", video.Title, "resolution", resolution)
 61
 62	filePath, err := h.downloader.Download(ctx, videoID, video.Title, h.config.DownloadsDir, resolution)
 63	if err != nil {
 64		h.log.Error("Video download failed", "video_id", videoID, "error", err)
 65		if dbErr := h.db.SetVideoDownloadFailed(ctx, videoID, err.Error()); dbErr != nil {
 66			h.log.Error("Failed to update download status to failed", "video_id", videoID, "error", dbErr)
 67		}
 68		return
 69	}
 70
 71	if err := h.db.SetVideoDownloadCompleted(ctx, videoID, filePath); err != nil {
 72		h.log.Error("Failed to mark video as downloaded", "video_id", videoID, "error", err)
 73		os.Remove(filePath)
 74		if dbErr := h.db.SetVideoDownloadFailed(ctx, videoID, "Failed to update database"); dbErr != nil {
 75			h.log.Error("Failed to update download status to failed", "video_id", videoID, "error", dbErr)
 76		}
 77		return
 78	}
 79
 80	h.log.Info("Video downloaded successfully", "video_id", videoID, "path", filePath)
 81}
 82
 83func (h *handler) ServeVideoFile(ctx context.Context, videoID string) (filePath string, filename string, err error) {
 84	video, err := h.db.GetVideo(ctx, videoID)
 85	if err != nil {
 86		return "", "", fmt.Errorf("video not found: %w", err)
 87	}
 88
 89	if !video.IsDownloaded() || video.FilePath == nil {
 90		return "", "", fmt.Errorf("video not downloaded")
 91	}
 92
 93	if _, err := os.Stat(*video.FilePath); os.IsNotExist(err) {
 94		if dbErr := h.db.DeleteVideoFile(ctx, videoID); dbErr != nil {
 95			h.log.Error("Failed to clear missing file from database", "video_id", videoID, "error", dbErr)
 96		}
 97		return "", "", fmt.Errorf("file not found on disk")
 98	}
 99
100	sanitizedTitle := sanitizeFilename(video.Title)
101	if sanitizedTitle == "" {
102		sanitizedTitle = videoID
103	}
104	ext := filepath.Ext(*video.FilePath)
105	filename = sanitizedTitle + ext
106
107	return *video.FilePath, filename, nil
108}