package api import ( "fmt" "net/http" "os" "path/filepath" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" "reichard.io/antholume/database" "reichard.io/antholume/metadata" ) func (api *API) createDownloadDocumentHandler(errorFunc func(*gin.Context, int, string)) func(*gin.Context) { return func(c *gin.Context) { var rDoc requestDocumentID if err := c.ShouldBindUri(&rDoc); err != nil { log.Error("Invalid URI Bind") errorFunc(c, http.StatusBadRequest, "Invalid Request") return } // Get Document document, err := api.db.Queries.GetDocument(api.db.Ctx, rDoc.DocumentID) if err != nil { log.Error("GetDocument DB Error:", err) errorFunc(c, http.StatusBadRequest, "Unknown Document") return } if document.Filepath == nil { log.Error("Document Doesn't Have File:", rDoc.DocumentID) errorFunc(c, http.StatusBadRequest, "Document Doesn't Exist") return } // Derive Basepath basepath := filepath.Join(api.cfg.DataPath, "documents") if document.Basepath != nil && *document.Basepath != "" { basepath = *document.Basepath } // Derive Storage Location filePath := filepath.Join(basepath, *document.Filepath) // Validate File Exists _, err = os.Stat(filePath) if os.IsNotExist(err) { log.Error("File should but doesn't exist: ", err) errorFunc(c, http.StatusBadRequest, "Document Doesn't Exist") return } // Force Download c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filepath.Base(*document.Filepath))) c.File(filePath) } } func (api *API) createGetCoverHandler(errorFunc func(*gin.Context, int, string)) func(*gin.Context) { return func(c *gin.Context) { var rDoc requestDocumentID if err := c.ShouldBindUri(&rDoc); err != nil { log.Error("Invalid URI Bind") errorFunc(c, http.StatusNotFound, "Invalid cover.") return } // Validate Document Exists in DB document, err := api.db.Queries.GetDocument(api.db.Ctx, rDoc.DocumentID) if err != nil { log.Error("GetDocument DB Error:", err) errorFunc(c, http.StatusInternalServerError, fmt.Sprintf("GetDocument DB Error: %v", err)) return } // Handle Identified Document if document.Coverfile != nil { if *document.Coverfile == "UNKNOWN" { c.FileFromFS("assets/images/no-cover.jpg", http.FS(api.assets)) return } // Derive Path safePath := filepath.Join(api.cfg.DataPath, "covers", *document.Coverfile) // Validate File Exists _, err = os.Stat(safePath) if err != nil { log.Error("File should but doesn't exist: ", err) c.FileFromFS("assets/images/no-cover.jpg", http.FS(api.assets)) return } c.File(safePath) return } // Attempt Metadata var coverDir string = filepath.Join(api.cfg.DataPath, "covers") var coverFile string = "UNKNOWN" // Identify Documents & Save Covers metadataResults, err := metadata.SearchMetadata(metadata.SOURCE_GBOOK, metadata.MetadataInfo{ Title: document.Title, Author: document.Author, }) if err == nil && len(metadataResults) > 0 && metadataResults[0].ID != nil { firstResult := metadataResults[0] // Save Cover fileName, err := metadata.CacheCover(*firstResult.ID, coverDir, document.ID, false) if err == nil { coverFile = *fileName } // Store First Metadata Result if _, err = api.db.Queries.AddMetadata(api.db.Ctx, database.AddMetadataParams{ DocumentID: document.ID, Title: firstResult.Title, Author: firstResult.Author, Description: firstResult.Description, Gbid: firstResult.ID, Olid: nil, Isbn10: firstResult.ISBN10, Isbn13: firstResult.ISBN13, }); err != nil { log.Error("AddMetadata DB Error:", err) } } // Upsert Document if _, err = api.db.Queries.UpsertDocument(api.db.Ctx, database.UpsertDocumentParams{ ID: document.ID, Coverfile: &coverFile, }); err != nil { log.Warn("UpsertDocument DB Error:", err) } // Return Unknown Cover if coverFile == "UNKNOWN" { c.FileFromFS("assets/images/no-cover.jpg", http.FS(api.assets)) return } coverFilePath := filepath.Join(coverDir, coverFile) c.File(coverFilePath) } }