taggart

Simple golang tagging filesystem webapp
Log | Files | Refs

commit 79d02d2c714ae396aa780551bb8c50d9931ae0e9
parent 203c498531d7359475fca41271345978300cfada
Author: breadcat <breadcat@users.noreply.github.com>
Date:   Wed, 24 Sep 2025 14:50:47 +0100

Add videos using yt-dlp

Diffstat:
Mmain.go | 69+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtemplates/add.html | 6++++++
2 files changed, 75 insertions(+), 0 deletions(-)

diff --git a/main.go b/main.go @@ -230,6 +230,7 @@ func main() { http.HandleFunc("/", listFilesHandler) http.HandleFunc("/add", uploadHandler) + http.HandleFunc("/add-yt", ytdlpHandler) http.HandleFunc("/upload-url", uploadFromURLHandler) http.HandleFunc("/file/", fileRouter) http.HandleFunc("/tags", tagsHandler) @@ -955,6 +956,74 @@ func settingsHandler(w http.ResponseWriter, r *http.Request) { tmpl.ExecuteTemplate(w, "settings.html", pageData) } +// yt-dlp Handler +func ytdlpHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Redirect(w, r, "/upload", http.StatusSeeOther) + return + } + + videoURL := r.FormValue("url") + if videoURL == "" { + http.Error(w, "No URL provided", http.StatusBadRequest) + return + } + + // Step 1: Get the expected filename first + outTemplate := filepath.Join(config.UploadDir, "%(title)s.%(ext)s") + filenameCmd := exec.Command("yt-dlp", "-f", "mp4", "-o", outTemplate, "--get-filename", videoURL) + filenameBytes, err := filenameCmd.Output() + if err != nil { + http.Error(w, fmt.Sprintf("Failed to get filename: %v", err), http.StatusInternalServerError) + return + } + expectedFilename := strings.TrimSpace(string(filenameBytes)) + + // Enforce strict duplicate check + finalFilename, finalPath, err := checkFileConflictStrict(expectedFilename) + if err != nil { + http.Error(w, err.Error(), http.StatusConflict) + return + } + finalTemplate := filepath.Join(config.UploadDir, finalFilename) + + // Step 2: Download with yt-dlp to the final path + downloadCmd := exec.Command("yt-dlp", "-f", "mp4", "-o", finalTemplate, videoURL) + downloadCmd.Stdout = os.Stdout + downloadCmd.Stderr = os.Stderr + if err := downloadCmd.Run(); err != nil { + http.Error(w, fmt.Sprintf("Failed to download video: %v", err), http.StatusInternalServerError) + return + } + + // Step 3: Process video (codec detection and potential re-encoding) + // Create a temporary path for processing + tempPath := finalPath + ".tmp" + os.Rename(finalPath, tempPath) // Move downloaded file to temp location + + processedPath, warningMsg, err := processVideoFile(tempPath, finalPath) + if err != nil { + os.Remove(tempPath) // Clean up + http.Error(w, fmt.Sprintf("Failed to process video: %v", err), http.StatusInternalServerError) + return + } + + // Step 4: Save to database + id, err := saveFileToDatabase(finalFilename, processedPath) + if err != nil { + os.Remove(processedPath) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Step 5: Redirect with optional warning + redirectURL := fmt.Sprintf("/file/%d", id) + if warningMsg != "" { + redirectURL += "?warning=" + url.QueryEscape(warningMsg) + } + http.Redirect(w, r, redirectURL, http.StatusSeeOther) +} + // Parse file ID ranges like "1-3,6,9" into a slice of integers func parseFileIDRange(rangeStr string) ([]int, error) { var fileIDs []int diff --git a/templates/add.html b/templates/add.html @@ -12,4 +12,10 @@ <button type="submit">Add File</button> </form> +<h2>Upload from yt-dlp</h2> +<form action="/add-yt" method="POST"> + <label for="url">Video URL:</label> + <input type="text" name="url" id="url" required> + <button type="submit">Add Video</button> +</form> {{template "_footer"}} \ No newline at end of file