package subsonicimport ("errors""net/http""time""github.com/navidrome/navidrome/model""github.com/navidrome/navidrome/model/request""github.com/navidrome/navidrome/server/subsonic/responses""github.com/navidrome/navidrome/utils/req""github.com/navidrome/navidrome/utils/slice")func (api *Router) GetBookmarks(r *http.Request) (*responses.Subsonic, error) {user, _ := request.UserFrom(r.Context())repo := api.ds.MediaFile(r.Context())bookmarks, err := repo.GetBookmarks()if err != nil {return nil, err}response := newResponse()response.Bookmarks = &responses.Bookmarks{}response.Bookmarks.Bookmark = slice.Map(bookmarks, func(bmk model.Bookmark) responses.Bookmark {return responses.Bookmark{Entry: childFromMediaFile(r.Context(), bmk.Item),Position: bmk.Position,Username: user.UserName,Comment: bmk.Comment,Created: bmk.CreatedAt,Changed: bmk.UpdatedAt,}})return response, nil}func (api *Router) CreateBookmark(r *http.Request) (*responses.Subsonic, error) {p := req.Params(r)id, err := p.String("id")if err != nil {return nil, err}comment, _ := p.String("comment")position := p.Int64Or("position", 0)repo := api.ds.MediaFile(r.Context())err = repo.AddBookmark(id, comment, position)if err != nil {return nil, err}return newResponse(), nil}func (api *Router) DeleteBookmark(r *http.Request) (*responses.Subsonic, error) {p := req.Params(r)id, err := p.String("id")if err != nil {return nil, err}repo := api.ds.MediaFile(r.Context())err = repo.DeleteBookmark(id)if err != nil {return nil, err}return newResponse(), nil}func (api *Router) GetPlayQueue(r *http.Request) (*responses.Subsonic, error) {user, _ := request.UserFrom(r.Context())repo := api.ds.PlayQueue(r.Context())pq, err := repo.RetrieveWithMediaFiles(user.ID)if err != nil && !errors.Is(err, model.ErrNotFound) {return nil, err}if pq == nil || len(pq.Items) == 0 {response := newResponse()response.PlayQueue = &responses.PlayQueue{Username: user.UserName,}return response, nil}response := newResponse()var currentID stringif pq.Current >= 0 && pq.Current < len(pq.Items) {currentID = pq.Items[pq.Current].ID}response.PlayQueue = &responses.PlayQueue{Entry: slice.MapWithArg(pq.Items, r.Context(), childFromMediaFile),Current: currentID,Position: pq.Position,Username: user.UserName,Changed: pq.UpdatedAt,ChangedBy: pq.ChangedBy,}return response, nil}func (api *Router) SavePlayQueue(r *http.Request) (*responses.Subsonic, error) {p := req.Params(r)ids, _ := p.Strings("id")currentID, _ := p.String("current")position := p.Int64Or("position", 0)user, _ := request.UserFrom(r.Context())client, _ := request.ClientFrom(r.Context())items := slice.Map(ids, func(id string) model.MediaFile {return model.MediaFile{ID: id}})currentIndex := 0for i, id := range ids {if id == currentID {currentIndex = ibreak}}pq := &model.PlayQueue{UserID: user.ID,Current: currentIndex,Position: position,ChangedBy: client,Items: items,CreatedAt: time.Time{},UpdatedAt: time.Time{},}repo := api.ds.PlayQueue(r.Context())err := repo.Store(pq)if err != nil {return nil, err}return newResponse(), nil}func (api *Router) GetPlayQueueByIndex(r *http.Request) (*responses.Subsonic, error) {user, _ := request.UserFrom(r.Context())repo := api.ds.PlayQueue(r.Context())pq, err := repo.RetrieveWithMediaFiles(user.ID)if err != nil && !errors.Is(err, model.ErrNotFound) {return nil, err}if pq == nil || len(pq.Items) == 0 {response := newResponse()response.PlayQueueByIndex = &responses.PlayQueueByIndex{Username: user.UserName,}return response, nil}response := newResponse()var index *intif len(pq.Items) > 0 {index = &pq.Current}response.PlayQueueByIndex = &responses.PlayQueueByIndex{Entry: slice.MapWithArg(pq.Items, r.Context(), childFromMediaFile),CurrentIndex: index,Position: pq.Position,Username: user.UserName,Changed: pq.UpdatedAt,ChangedBy: pq.ChangedBy,}return response, nil}func (api *Router) SavePlayQueueByIndex(r *http.Request) (*responses.Subsonic, error) {p := req.Params(r)ids, _ := p.Strings("id")position := p.Int64Or("position", 0)var err errorvar currentIndex intif len(ids) > 0 {currentIndex, err = p.Int("currentIndex")if err != nil || currentIndex < 0 || currentIndex >= len(ids) {return nil, newError(responses.ErrorMissingParameter, "missing parameter index, err: %s", err)}}items := slice.Map(ids, func(id string) model.MediaFile {return model.MediaFile{ID: id}})user, _ := request.UserFrom(r.Context())client, _ := request.ClientFrom(r.Context())pq := &model.PlayQueue{UserID: user.ID,Current: currentIndex,Position: position,ChangedBy: client,Items: items,CreatedAt: time.Time{},UpdatedAt: time.Time{},}repo := api.ds.PlayQueue(r.Context())err = repo.Store(pq)if err != nil {return nil, err}return newResponse(), nil}