refactor: rename bulk operations from /api/books/ to /api/media-items/
- Rename routes: /api/books/bulk-{delete,update} → /api/media-items/bulk-{delete,update}
- Rename route: /api/books/:uuid/download → /api/media-items/:uuid/download
- Update request fields: book_ids → media_item_ids
- Update response fields: success → deleted/updated
- Update result fields: book_id → media_item_id
- Update collection handler: success → added
This change improves API semantic correctness as the system handles
multiple media types (ebooks, comics, manga), not just books.
BREAKING CHANGE: All bulk operation endpoints and field names renamed
This commit is contained in:
@@ -810,7 +810,7 @@ func (h *CollectionHandler) HandleBulkAddBooks(c echo.Context) error {
|
||||
return c.JSON(http.StatusOK, map[string]interface{}{
|
||||
"results": results,
|
||||
"total": len(results),
|
||||
"success": successCount,
|
||||
"added": successCount,
|
||||
"failed": failedCount,
|
||||
})
|
||||
}
|
||||
|
||||
+59
-59
@@ -341,30 +341,30 @@ func (h *MediaHandler) ClearShelf(c echo.Context) error {
|
||||
|
||||
// Bulk Operations
|
||||
|
||||
// POST /api/books/bulk-delete
|
||||
// Bulk delete books
|
||||
// POST /api/media-items/bulk-delete
|
||||
// Bulk delete media items
|
||||
func (h *MediaHandler) HandleBulkDelete(c echo.Context) error {
|
||||
var req struct {
|
||||
BookIDs []string `json:"book_ids" validate:"required"`
|
||||
MediaItemIDs []string `json:"media_item_ids" validate:"required"`
|
||||
}
|
||||
|
||||
if err := c.Bind(&req); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request"})
|
||||
}
|
||||
|
||||
if len(req.BookIDs) == 0 {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "book_ids required"})
|
||||
if len(req.MediaItemIDs) == 0 {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "media_item_ids required"})
|
||||
}
|
||||
|
||||
results := make([]map[string]interface{}, 0)
|
||||
successCount := 0
|
||||
failedCount := 0
|
||||
|
||||
for _, bookIDStr := range req.BookIDs {
|
||||
bookID, err := uuid.Parse(bookIDStr)
|
||||
for _, mediaIDStr := range req.MediaItemIDs {
|
||||
mediaID, err := uuid.Parse(mediaIDStr)
|
||||
if err != nil {
|
||||
results = append(results, map[string]interface{}{
|
||||
"book_id": bookIDStr,
|
||||
"media_item_id": mediaIDStr,
|
||||
"status": "error",
|
||||
"error": "Invalid UUID",
|
||||
})
|
||||
@@ -372,23 +372,23 @@ func (h *MediaHandler) HandleBulkDelete(c echo.Context) error {
|
||||
continue
|
||||
}
|
||||
|
||||
bookUUID := pgtype.UUID{Bytes: bookID, Valid: true}
|
||||
mediaUUID := pgtype.UUID{Bytes: mediaID, Valid: true}
|
||||
|
||||
book, err := h.db.GetMediaItem(c.Request().Context(), bookUUID)
|
||||
media, err := h.db.GetMediaItem(c.Request().Context(), mediaUUID)
|
||||
if err != nil {
|
||||
results = append(results, map[string]interface{}{
|
||||
"book_id": bookIDStr,
|
||||
"media_item_id": mediaIDStr,
|
||||
"status": "error",
|
||||
"error": "Book not found",
|
||||
"error": "Media item not found",
|
||||
})
|
||||
failedCount++
|
||||
continue
|
||||
}
|
||||
|
||||
err = h.db.DeleteMediaItem(c.Request().Context(), bookUUID)
|
||||
err = h.db.DeleteMediaItem(c.Request().Context(), mediaUUID)
|
||||
if err != nil {
|
||||
results = append(results, map[string]interface{}{
|
||||
"book_id": bookIDStr,
|
||||
"media_item_id": mediaIDStr,
|
||||
"status": "error",
|
||||
"error": err.Error(),
|
||||
})
|
||||
@@ -396,12 +396,12 @@ func (h *MediaHandler) HandleBulkDelete(c echo.Context) error {
|
||||
continue
|
||||
}
|
||||
|
||||
if book.FilePath != "" {
|
||||
os.Remove(book.FilePath)
|
||||
if media.FilePath != "" {
|
||||
os.Remove(media.FilePath)
|
||||
}
|
||||
|
||||
results = append(results, map[string]interface{}{
|
||||
"book_id": bookIDStr,
|
||||
"media_item_id": mediaIDStr,
|
||||
"status": "success",
|
||||
})
|
||||
successCount++
|
||||
@@ -409,18 +409,18 @@ func (h *MediaHandler) HandleBulkDelete(c echo.Context) error {
|
||||
|
||||
return c.JSON(http.StatusOK, map[string]interface{}{
|
||||
"results": results,
|
||||
"total": len(req.BookIDs),
|
||||
"success": successCount,
|
||||
"total": len(req.MediaItemIDs),
|
||||
"deleted": successCount,
|
||||
"failed": failedCount,
|
||||
})
|
||||
}
|
||||
|
||||
// POST /api/books/bulk-update
|
||||
// Bulk update book metadata
|
||||
// POST /api/media-items/bulk-update
|
||||
// Bulk update media item metadata
|
||||
func (h *MediaHandler) HandleBulkUpdate(c echo.Context) error {
|
||||
var req struct {
|
||||
Updates []struct {
|
||||
BookID string `json:"book_id" validate:"required"`
|
||||
MediaItemUpdates []struct {
|
||||
MediaItemID string `json:"media_item_id" validate:"required"`
|
||||
Updates struct {
|
||||
Title *string `json:"title,omitempty"`
|
||||
Author *string `json:"author,omitempty"`
|
||||
@@ -428,26 +428,26 @@ func (h *MediaHandler) HandleBulkUpdate(c echo.Context) error {
|
||||
Language *string `json:"language,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
} `json:"updates"`
|
||||
} `json:"updates" validate:"required"`
|
||||
} `json:"media_item_updates" validate:"required"`
|
||||
}
|
||||
|
||||
if err := c.Bind(&req); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request"})
|
||||
}
|
||||
|
||||
if len(req.Updates) == 0 {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "updates required"})
|
||||
if len(req.MediaItemUpdates) == 0 {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "media_item_updates required"})
|
||||
}
|
||||
|
||||
results := make([]map[string]interface{}, 0)
|
||||
successCount := 0
|
||||
failedCount := 0
|
||||
|
||||
for _, update := range req.Updates {
|
||||
bookID, err := uuid.Parse(update.BookID)
|
||||
for _, update := range req.MediaItemUpdates {
|
||||
mediaID, err := uuid.Parse(update.MediaItemID)
|
||||
if err != nil {
|
||||
results = append(results, map[string]interface{}{
|
||||
"book_id": update.BookID,
|
||||
"media_item_id": update.MediaItemID,
|
||||
"status": "error",
|
||||
"error": "Invalid UUID",
|
||||
})
|
||||
@@ -455,42 +455,42 @@ func (h *MediaHandler) HandleBulkUpdate(c echo.Context) error {
|
||||
continue
|
||||
}
|
||||
|
||||
bookUUID := pgtype.UUID{Bytes: bookID, Valid: true}
|
||||
mediaUUID := pgtype.UUID{Bytes: mediaID, Valid: true}
|
||||
|
||||
existingBook, err := h.db.GetMediaItem(c.Request().Context(), bookUUID)
|
||||
existingMedia, err := h.db.GetMediaItem(c.Request().Context(), mediaUUID)
|
||||
if err != nil {
|
||||
results = append(results, map[string]interface{}{
|
||||
"book_id": update.BookID,
|
||||
"media_item_id": update.MediaItemID,
|
||||
"status": "error",
|
||||
"error": "Book not found",
|
||||
"error": "Media item not found",
|
||||
})
|
||||
failedCount++
|
||||
continue
|
||||
}
|
||||
|
||||
updateParams := database.UpdateMediaItemParams{
|
||||
ID: bookUUID,
|
||||
Title: existingBook.Title,
|
||||
Author: existingBook.Author,
|
||||
Genre: existingBook.Genre,
|
||||
Language: existingBook.Language,
|
||||
Tags: existingBook.Tags,
|
||||
TagsSearch: existingBook.TagsSearch,
|
||||
Description: existingBook.Description,
|
||||
Publisher: existingBook.Publisher,
|
||||
CopyrightYear: existingBook.CopyrightYear,
|
||||
Isbn: existingBook.Isbn,
|
||||
Series: existingBook.Series,
|
||||
SeriesNumber: existingBook.SeriesNumber,
|
||||
Asin: existingBook.Asin,
|
||||
DatePublished: existingBook.DatePublished,
|
||||
Contributors: existingBook.Contributors,
|
||||
ContributorsSearch: existingBook.ContributorsSearch,
|
||||
Edition: existingBook.Edition,
|
||||
PageCount: existingBook.PageCount,
|
||||
GoodreadsID: existingBook.GoodreadsID,
|
||||
OpenlibraryID: existingBook.OpenlibraryID,
|
||||
CoverImagePath: existingBook.CoverImagePath,
|
||||
ID: mediaUUID,
|
||||
Title: existingMedia.Title,
|
||||
Author: existingMedia.Author,
|
||||
Genre: existingMedia.Genre,
|
||||
Language: existingMedia.Language,
|
||||
Tags: existingMedia.Tags,
|
||||
TagsSearch: existingMedia.TagsSearch,
|
||||
Description: existingMedia.Description,
|
||||
Publisher: existingMedia.Publisher,
|
||||
CopyrightYear: existingMedia.CopyrightYear,
|
||||
Isbn: existingMedia.Isbn,
|
||||
Series: existingMedia.Series,
|
||||
SeriesNumber: existingMedia.SeriesNumber,
|
||||
Asin: existingMedia.Asin,
|
||||
DatePublished: existingMedia.DatePublished,
|
||||
Contributors: existingMedia.Contributors,
|
||||
ContributorsSearch: existingMedia.ContributorsSearch,
|
||||
Edition: existingMedia.Edition,
|
||||
PageCount: existingMedia.PageCount,
|
||||
GoodreadsID: existingMedia.GoodreadsID,
|
||||
OpenlibraryID: existingMedia.OpenlibraryID,
|
||||
CoverImagePath: existingMedia.CoverImagePath,
|
||||
}
|
||||
|
||||
if update.Updates.Title != nil {
|
||||
@@ -515,7 +515,7 @@ func (h *MediaHandler) HandleBulkUpdate(c echo.Context) error {
|
||||
_, err = h.db.UpdateMediaItem(c.Request().Context(), updateParams)
|
||||
if err != nil {
|
||||
results = append(results, map[string]interface{}{
|
||||
"book_id": update.BookID,
|
||||
"media_item_id": update.MediaItemID,
|
||||
"status": "error",
|
||||
"error": err.Error(),
|
||||
})
|
||||
@@ -524,7 +524,7 @@ func (h *MediaHandler) HandleBulkUpdate(c echo.Context) error {
|
||||
}
|
||||
|
||||
results = append(results, map[string]interface{}{
|
||||
"book_id": update.BookID,
|
||||
"media_item_id": update.MediaItemID,
|
||||
"status": "success",
|
||||
})
|
||||
successCount++
|
||||
@@ -532,8 +532,8 @@ func (h *MediaHandler) HandleBulkUpdate(c echo.Context) error {
|
||||
|
||||
return c.JSON(http.StatusOK, map[string]interface{}{
|
||||
"results": results,
|
||||
"total": len(req.Updates),
|
||||
"success": successCount,
|
||||
"total": len(req.MediaItemUpdates),
|
||||
"updated": successCount,
|
||||
"failed": failedCount,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func registerMediaRoutes(cfg *Config) {
|
||||
admin.DELETE("/media-items/:id", cfg.MediaHandler.DeleteMediaItem)
|
||||
|
||||
// Download route (public)
|
||||
e.GET("/api/books/:uuid/download", cfg.MediaHandler.DownloadBook)
|
||||
e.GET("/api/media-items/:uuid/download", cfg.MediaHandler.DownloadBook)
|
||||
|
||||
// Shelf management (protected)
|
||||
protected.POST("/devices/:id/shelves", cfg.MediaHandler.AddToShelf)
|
||||
@@ -56,8 +56,8 @@ func registerMediaRoutes(cfg *Config) {
|
||||
protected.DELETE("/devices/:id/shelves", cfg.MediaHandler.RemoveFromShelf)
|
||||
protected.DELETE("/devices/:id/shelves/clear", cfg.MediaHandler.ClearShelf)
|
||||
|
||||
// Bulk book operations (protected)
|
||||
books := protected.Group("/books")
|
||||
books.POST("/bulk-delete", cfg.MediaHandler.HandleBulkDelete)
|
||||
books.POST("/bulk-update", cfg.MediaHandler.HandleBulkUpdate)
|
||||
// Bulk media operations (protected)
|
||||
mediaItems := protected.Group("/media-items")
|
||||
mediaItems.POST("/bulk-delete", cfg.MediaHandler.HandleBulkDelete)
|
||||
mediaItems.POST("/bulk-update", cfg.MediaHandler.HandleBulkUpdate)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user