From 23d69d26e07dab05bee0ee9afcc2c70f6c6545f3 Mon Sep 17 00:00:00 2001 From: Deluan Date: Fri, 31 Jul 2020 16:56:42 -0400 Subject: [PATCH] Add Bookmarks to Subsonic API --- persistence/playqueue_repository.go | 12 +++--- server/subsonic/api.go | 3 ++ server/subsonic/bookmarks.go | 62 ++++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/persistence/playqueue_repository.go b/persistence/playqueue_repository.go index 8d588c0d9..d092a7748 100644 --- a/persistence/playqueue_repository.go +++ b/persistence/playqueue_repository.go @@ -77,7 +77,7 @@ func (r *playQueueRepository) AddBookmark(userId, id, comment string, position i UpdatedAt: time.Now(), } - sel := r.newSelect().Column("id").Where(And{ + sel := r.newSelect().Column("*").Where(And{ Eq{"user_id": userId}, Eq{"items": ""}, Eq{"current": id}, @@ -89,11 +89,13 @@ func (r *playQueueRepository) AddBookmark(userId, id, comment string, position i return err } - if !prev.CreatedAt.IsZero() { + // If there is a previous bookmark, override + if prev.ID != "" { + bm.ID = prev.ID bm.CreatedAt = prev.CreatedAt } - _, err = r.put(prev.ID, bm) + _, err = r.put(bm.ID, bm) if err != nil { log.Error(r.ctx, "Error saving bookmark", "user", u.UserName, err, "mediaFileId", id, err) return err @@ -115,7 +117,7 @@ func (r *playQueueRepository) GetBookmarks(userId string) (model.Bookmarks, erro items := r.loadTracks(model.MediaFiles{{ID: pqs[i].Current}}) bms[i].Item = items[0] bms[i].Comment = pqs[i].Comment - bms[i].Position = int64(pqs[i].Position) + bms[i].Position = pqs[i].Position bms[i].CreatedAt = pqs[i].CreatedAt bms[i].UpdatedAt = pqs[i].UpdatedAt } @@ -217,7 +219,7 @@ func (r *playQueueRepository) loadTracks(tracks model.MediaFiles) model.MediaFil } func (r *playQueueRepository) clearPlayQueue(userId string) error { - return r.delete(Eq{"user_id": userId}) + return r.delete(And{Eq{"user_id": userId}, NotEq{"items": ""}}) } var _ model.PlayQueueRepository = (*playQueueRepository)(nil) diff --git a/server/subsonic/api.go b/server/subsonic/api.go index 65cfe9d97..158ccad94 100644 --- a/server/subsonic/api.go +++ b/server/subsonic/api.go @@ -113,6 +113,9 @@ func (api *Router) routes() http.Handler { r.Group(func(r chi.Router) { c := initBookmarksController(api) withPlayer := r.With(getPlayer(api.Players)) + H(withPlayer, "getBookmarks", c.GetBookmarks) + H(withPlayer, "createBookmark", c.CreateBookmark) + H(withPlayer, "deleteBookmark", c.DeleteBookmark) H(withPlayer, "getPlayQueue", c.GetPlayQueue) H(withPlayer, "savePlayQueue", c.SavePlayQueue) }) diff --git a/server/subsonic/bookmarks.go b/server/subsonic/bookmarks.go index 4fc24155d..1c1b54dde 100644 --- a/server/subsonic/bookmarks.go +++ b/server/subsonic/bookmarks.go @@ -18,6 +18,66 @@ func NewBookmarksController(ds model.DataStore) *BookmarksController { return &BookmarksController{ds: ds} } +func (c *BookmarksController) GetBookmarks(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) { + user, _ := request.UserFrom(r.Context()) + + repo := c.ds.PlayQueue(r.Context()) + bmks, err := repo.GetBookmarks(user.ID) + if err != nil { + return nil, NewError(responses.ErrorGeneric, "Internal Error") + } + + response := NewResponse() + response.Bookmarks = &responses.Bookmarks{} + for _, bmk := range bmks { + b := responses.Bookmark{ + Entry: []responses.Child{ChildFromMediaFile(r.Context(), bmk.Item)}, + Position: bmk.Position, + Username: user.UserName, + Comment: bmk.Comment, + Created: bmk.CreatedAt, + Changed: bmk.UpdatedAt, + } + response.Bookmarks.Bookmark = append(response.Bookmarks.Bookmark, b) + } + return response, nil +} + +func (c *BookmarksController) CreateBookmark(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) { + id, err := RequiredParamString(r, "id", "id parameter required") + if err != nil { + return nil, err + } + + comment := utils.ParamString(r, "comment") + position := utils.ParamInt64(r, "position", 0) + + user, _ := request.UserFrom(r.Context()) + + repo := c.ds.PlayQueue(r.Context()) + err = repo.AddBookmark(user.ID, id, comment, position) + if err != nil { + return nil, NewError(responses.ErrorGeneric, "Internal Error") + } + return NewResponse(), nil +} + +func (c *BookmarksController) DeleteBookmark(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) { + id, err := RequiredParamString(r, "id", "id parameter required") + if err != nil { + return nil, err + } + + user, _ := request.UserFrom(r.Context()) + + repo := c.ds.PlayQueue(r.Context()) + err = repo.DeleteBookmark(user.ID, id) + if err != nil { + return nil, NewError(responses.ErrorGeneric, "Internal Error") + } + return NewResponse(), nil +} + func (c *BookmarksController) GetPlayQueue(w http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) { user, _ := request.UserFrom(r.Context()) @@ -31,7 +91,7 @@ func (c *BookmarksController) GetPlayQueue(w http.ResponseWriter, r *http.Reques response.PlayQueue = &responses.PlayQueue{ Entry: ChildrenFromMediaFiles(r.Context(), pq.Items), Current: pq.Current, - Position: int64(pq.Position), + Position: pq.Position, Username: user.UserName, Changed: &pq.UpdatedAt, ChangedBy: pq.ChangedBy,