feat: implement multiple folder ebook scanner and API handlers
- Create EbookScanner service with multiple folder support - Update scanner to handle array of folder paths instead of single path - Add EPUB metadata extraction for rich ebook information - Implement folder monitoring with fsnotify for real-time updates - Add API endpoints for folder management: - POST /api/auth/ebook-folders (add folder) - GET /api/auth/ebook-folders (list folders) - DELETE /api/auth/ebook-folders/:folderPath (remove folder) - Update scanner endpoints to accept folder_paths array - Add go-epub and fsnotify dependencies for metadata extraction and file watching
This commit is contained in:
@@ -315,6 +315,99 @@ func (h *AuthHandler) ListUsers(c echo.Context) error {
|
||||
return c.JSON(http.StatusOK, userList)
|
||||
}
|
||||
|
||||
type AddEbookFolderRequest struct {
|
||||
FolderPath string `json:"folder_path" validate:"required"`
|
||||
}
|
||||
|
||||
type EbookFolderResponse struct {
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"user_id"`
|
||||
FolderPath string `json:"folder_path"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
}
|
||||
|
||||
// AddEbookFolder handles POST /api/auth/ebook-folders
|
||||
func (h *AuthHandler) AddEbookFolder(c echo.Context) error {
|
||||
userID := c.Get("user_id").(string)
|
||||
userUUID, err := uuid.Parse(userID)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid user id"})
|
||||
}
|
||||
|
||||
var req AddEbookFolderRequest
|
||||
if err := c.Bind(&req); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid request"})
|
||||
}
|
||||
if err := c.Validate(&req); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
folder, err := h.db.AddUserEbookFolder(c.Request().Context(), database.AddUserEbookFolderParams{
|
||||
UserID: pgtype.UUID{Bytes: userUUID, Valid: true},
|
||||
FolderPath: req.FolderPath,
|
||||
})
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusCreated, EbookFolderResponse{
|
||||
ID: uuid.UUID(folder.ID.Bytes).String(),
|
||||
UserID: uuid.UUID(folder.UserID.Bytes).String(),
|
||||
FolderPath: folder.FolderPath,
|
||||
CreatedAt: folder.CreatedAt.Time.Format("2006-01-02T15:04:05Z07:00"),
|
||||
})
|
||||
}
|
||||
|
||||
// GetEbookFolders handles GET /api/auth/ebook-folders
|
||||
func (h *AuthHandler) GetEbookFolders(c echo.Context) error {
|
||||
userID := c.Get("user_id").(string)
|
||||
userUUID, err := uuid.Parse(userID)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid user id"})
|
||||
}
|
||||
|
||||
folders, err := h.db.GetUserEbookFolders(c.Request().Context(), pgtype.UUID{Bytes: userUUID, Valid: true})
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
var response []EbookFolderResponse
|
||||
for _, folder := range folders {
|
||||
response = append(response, EbookFolderResponse{
|
||||
ID: uuid.UUID(folder.ID.Bytes).String(),
|
||||
UserID: uuid.UUID(folder.UserID.Bytes).String(),
|
||||
FolderPath: folder.FolderPath,
|
||||
CreatedAt: folder.CreatedAt.Time.Format("2006-01-02T15:04:05Z07:00"),
|
||||
})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// DeleteEbookFolder handles DELETE /api/auth/ebook-folders/:folderPath
|
||||
func (h *AuthHandler) DeleteEbookFolder(c echo.Context) error {
|
||||
userID := c.Get("user_id").(string)
|
||||
userUUID, err := uuid.Parse(userID)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid user id"})
|
||||
}
|
||||
|
||||
folderPath := c.Param("folderPath")
|
||||
if folderPath == "" {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "folder path is required"})
|
||||
}
|
||||
|
||||
err = h.db.DeleteUserEbookFolder(c.Request().Context(), database.DeleteUserEbookFolderParams{
|
||||
UserID: pgtype.UUID{Bytes: userUUID, Valid: true},
|
||||
FolderPath: folderPath,
|
||||
})
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, map[string]string{"message": "ebook folder removed"})
|
||||
}
|
||||
|
||||
func (h *AuthHandler) generateJWT(userID string) (string, error) {
|
||||
claims := jwtgo.MapClaims{
|
||||
"user_id": userID,
|
||||
|
||||
Reference in New Issue
Block a user