update
Some checks failed
Pipeline: Test, Lint, Build / Get version info (push) Has been cancelled
Pipeline: Test, Lint, Build / Lint Go code (push) Has been cancelled
Pipeline: Test, Lint, Build / Test Go code (push) Has been cancelled
Pipeline: Test, Lint, Build / Test JS code (push) Has been cancelled
Pipeline: Test, Lint, Build / Lint i18n files (push) Has been cancelled
Pipeline: Test, Lint, Build / Check Docker configuration (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (darwin/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (darwin/arm64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/386) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v5) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v6) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v7) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (windows/386) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (windows/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Push to GHCR (push) Has been cancelled
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Has been cancelled
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Has been cancelled
Pipeline: Test, Lint, Build / Build Windows installers (push) Has been cancelled
Pipeline: Test, Lint, Build / Package/Release (push) Has been cancelled
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
POEditor import / update-translations (push) Has been cancelled
Some checks failed
Pipeline: Test, Lint, Build / Get version info (push) Has been cancelled
Pipeline: Test, Lint, Build / Lint Go code (push) Has been cancelled
Pipeline: Test, Lint, Build / Test Go code (push) Has been cancelled
Pipeline: Test, Lint, Build / Test JS code (push) Has been cancelled
Pipeline: Test, Lint, Build / Lint i18n files (push) Has been cancelled
Pipeline: Test, Lint, Build / Check Docker configuration (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (darwin/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (darwin/arm64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/386) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v5) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v6) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm/v7) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (linux/arm64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (windows/386) (push) Has been cancelled
Pipeline: Test, Lint, Build / Build (windows/amd64) (push) Has been cancelled
Pipeline: Test, Lint, Build / Push to GHCR (push) Has been cancelled
Pipeline: Test, Lint, Build / Push to Docker Hub (push) Has been cancelled
Pipeline: Test, Lint, Build / Cleanup digest artifacts (push) Has been cancelled
Pipeline: Test, Lint, Build / Build Windows installers (push) Has been cancelled
Pipeline: Test, Lint, Build / Package/Release (push) Has been cancelled
Pipeline: Test, Lint, Build / Upload Linux PKG (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
POEditor import / update-translations (push) Has been cancelled
This commit is contained in:
208
server/subsonic/bookmarks.go
Normal file
208
server/subsonic/bookmarks.go
Normal file
@@ -0,0 +1,208 @@
|
||||
package subsonic
|
||||
|
||||
import (
|
||||
"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 {
|
||||
return newResponse(), nil
|
||||
}
|
||||
|
||||
response := newResponse()
|
||||
var currentID string
|
||||
if 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 := 0
|
||||
for i, id := range ids {
|
||||
if id == currentID {
|
||||
currentIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
return newResponse(), nil
|
||||
}
|
||||
|
||||
response := newResponse()
|
||||
|
||||
var index *int
|
||||
if 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 error
|
||||
var currentIndex int
|
||||
|
||||
if 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
|
||||
}
|
||||
Reference in New Issue
Block a user