diff --git a/server/file.go b/server/file.go index efd466f..508ba23 100644 --- a/server/file.go +++ b/server/file.go @@ -3,6 +3,7 @@ package server import ( "log/slog" "net/http" + "path/filepath" ) func handleFile(w http.ResponseWriter, r *http.Request) { @@ -13,28 +14,39 @@ func handleFile(w http.ResponseWriter, r *http.Request) { } // TODO check if worker is working on a task involving this file - var path string - err := db.QueryRow(r.Context(), "SELECT path FROM files WHERE id = $1", id).Scan(&path) + var fpath string + var libraryID int + err := db.QueryRow(r.Context(), "SELECT path, library_id FROM files WHERE id = $1", id).Scan(&fpath, &libraryID) if err != nil { - http.Error(w, "Error Getting Path: "+err.Error(), http.StatusBadRequest) - slog.ErrorContext(r.Context(), "Getting Path", "err", err) + http.Error(w, "Error Getting File Path: "+err.Error(), http.StatusBadRequest) + slog.ErrorContext(r.Context(), "Getting File Path", "err", err) return } - slog.InfoContext(r.Context(), "Serving File Download", "id", id, "path", path) + var lpath string + err = db.QueryRow(r.Context(), "SELECT path FROM libraries WHERE id = $1", libraryID).Scan(&lpath) + if err != nil { + http.Error(w, "Error Getting Library Path: "+err.Error(), http.StatusBadRequest) + slog.ErrorContext(r.Context(), "Getting Library Path", "err", err) + return + } + + fullPath := filepath.Join(lpath, fpath) + + slog.InfoContext(r.Context(), "Serving File Download", "id", id, "path", fullPath) // had timeout issues - http.ServeFile(w, r, path) + http.ServeFile(w, r, fullPath) /* - reader, err := os.Open(path) + reader, err := os.Open(fullPath) if err != nil { http.Error(w, "Error Opening File: "+err.Error(), http.StatusInternalServerError) slog.ErrorContext(r.Context(), "Opening File", "err", err) return } - w.Header().Set("Content-Disposition", "attachment;filename="+filepath.Base(path)) + w.Header().Set("Content-Disposition", "attachment;filename="+filepath.Base(fullPath)) _, err = io.Copy(w, reader) if err != nil { http.Error(w, "Copy File: "+err.Error(), http.StatusBadRequest) diff --git a/server/scan.go b/server/scan.go index 1404a54..7035241 100644 --- a/server/scan.go +++ b/server/scan.go @@ -31,6 +31,8 @@ func handleScan(w http.ResponseWriter, r *http.Request) { return } + full := r.FormValue("full") == "on" + var name string var path string var enabled bool @@ -42,7 +44,7 @@ func handleScan(w http.ResponseWriter, r *http.Request) { } scanCtx := context.Background() - go scan(scanCtx, id) + go scan(scanCtx, id, full) message := "Scan Started" @@ -77,9 +79,18 @@ func scanStatus(w http.ResponseWriter, r *http.Request) { } } -func scan(ctx context.Context, id string) { +func scan(ctx context.Context, id string, full bool) { slog.InfoContext(ctx, "Starting Scan", "id", id) + // TODO Scan settings: + // - Auto Queue Healthcheck for Changed Files + // - Auto Queue Healthcheck for New Files + // - Auto Queue Transcode for New Files + // - Auto Queue Transcode for Changed Files (? Instead have library setting to queue transcode for changed files on healthcheck success) + // - Auto Queue Health/Transcode for Unkown Status ? (might result in requeue loop) + // - Schedule Scans Periodically + // - Add File Monitoring for Setting Changed status and triggering tasks + var name string var lpath string var enabled bool @@ -122,9 +133,9 @@ func scan(ctx context.Context, id string) { } err = filepath.Walk(lpath, - func(path string, info os.FileInfo, err error) error { + func(fullPath string, info os.FileInfo, err error) error { if errors.Is(err, os.ErrPermission) { - slog.WarnContext(ctx, "Permission Denied While Scanning File", "path", path) + slog.WarnContext(ctx, "Permission Denied While Scanning File", "path", fullPath) return nil } else if err != nil { return err @@ -135,13 +146,13 @@ func scan(ctx context.Context, id string) { return nil } - if !slices.Contains(videoFileExtensions, filepath.Ext(path)) { - slog.InfoContext(ctx, "Skipping non video file", "path", path) + if !slices.Contains(videoFileExtensions, filepath.Ext(fullPath)) { + slog.InfoContext(ctx, "Skipping non video file", "path", fullPath) return nil } - slog.InfoContext(ctx, "Hashing File", "path", path, "size", info.Size()) + slog.InfoContext(ctx, "Hashing File", "path", fullPath, "size", info.Size()) - file, err := os.Open(path) + file, err := os.Open(fullPath) if err != nil { return fmt.Errorf("Opening File: %w", err) } @@ -152,17 +163,22 @@ func scan(ctx context.Context, id string) { } newMD5 := hash.Sum(nil) - slog.InfoContext(ctx, "File MD5", "path", path, "size", info.Size(), "md5", newMD5) + slog.InfoContext(ctx, "File MD5", "path", fullPath, "size", info.Size(), "md5", newMD5) + + fPath, err := filepath.Rel(lpath, fullPath) + if err != nil { + return fmt.Errorf("Getting Relative Path: %w", err) + } var fileID int var oldMD5 []byte var health constants.FileHealth - err = tx.QueryRow(ctx, "SELECT id, md5, health FROM files WHERE library_id = $1 AND path = $2", id, path).Scan(&fileID, &oldMD5, &health) + err = tx.QueryRow(ctx, "SELECT id, md5, health FROM files WHERE library_id = $1 AND path = $2", id, fPath).Scan(&fileID, &oldMD5, &health) if errors.Is(err, pgx.ErrNoRows) { // File Does not Exist Yet - slog.InfoContext(ctx, "File is New", "path", path) - _, err = tx.Exec(ctx, "INSERT INTO files (library_id, path, size, status, health, md5) VALUES ($1, $2, $3, $4, $5, $6)", id, path, info.Size(), constants.FILE_STATUS_EXISTS, constants.FILE_HEALTH_UNKNOWN, newMD5) + slog.InfoContext(ctx, "File is New", "path", fullPath) + _, err = tx.Exec(ctx, "INSERT INTO files (library_id, path, size, status, health, md5) VALUES ($1, $2, $3, $4, $5, $6)", id, fullPath, info.Size(), constants.FILE_STATUS_EXISTS, constants.FILE_HEALTH_UNKNOWN, newMD5) if err != nil { return fmt.Errorf("Add New File to DB: %w", err) } @@ -192,5 +208,7 @@ func scan(ctx context.Context, id string) { slog.ErrorContext(ctx, "Error Committing Changes", "err", err) return } + + // TODO, create health and transcode tasks if requested slog.InfoContext(ctx, "Scan Done", "id", id) }