Handle exporting playlists as m3u files

This commit is contained in:
Deluan 2020-08-22 12:15:26 -04:00
parent 8fa5544af7
commit 366054e8cc
2 changed files with 63 additions and 15 deletions

View File

@ -104,24 +104,12 @@ func (app *Router) RX(r chi.Router, pathPrefix string, constructor rest.Reposito
type restHandler = func(rest.RepositoryConstructor, ...rest.Logger) http.HandlerFunc
func (app *Router) addPlaylistTrackRoute(r chi.Router) {
// Add a middleware to capture the playlistId
wrapper := func(f restHandler) http.HandlerFunc {
return func(res http.ResponseWriter, req *http.Request) {
c := func(ctx context.Context) rest.Repository {
plsRepo := app.ds.Resource(ctx, model.Playlist{})
plsId := chi.URLParam(req, "playlistId")
return plsRepo.(model.PlaylistRepository).Tracks(plsId)
}
f(c).ServeHTTP(res, req)
}
}
r.Route("/playlist/{playlistId}/tracks", func(r chi.Router) {
r.Get("/", wrapper(rest.GetAll))
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
getPlaylist(app.ds)(w, r)
})
r.Route("/{id}", func(r chi.Router) {
r.Use(UrlParams)
r.Get("/", wrapper(rest.Get))
r.Put("/", func(w http.ResponseWriter, r *http.Request) {
reorderItem(app.ds)(w, r)
})

View File

@ -1,16 +1,76 @@
package app
import (
"context"
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
"github.com/deluan/navidrome/log"
"github.com/deluan/navidrome/model"
"github.com/deluan/navidrome/utils"
"github.com/deluan/rest"
"github.com/go-chi/chi"
)
func getPlaylist(ds model.DataStore) http.HandlerFunc {
// Add a middleware to capture the playlistId
wrapper := func(handler restHandler) http.HandlerFunc {
return func(res http.ResponseWriter, req *http.Request) {
constructor := func(ctx context.Context) rest.Repository {
plsRepo := ds.Playlist(ctx)
plsId := chi.URLParam(req, "playlistId")
return plsRepo.(model.PlaylistRepository).Tracks(plsId)
}
handler(constructor).ServeHTTP(res, req)
}
}
return func(w http.ResponseWriter, r *http.Request) {
accept := r.Header.Get("accept")
if strings.ToLower(accept) == "audio/x-mpegurl" {
handleExportPlaylist(ds)(w, r)
return
}
wrapper(rest.GetAll)(w, r)
}
}
func handleExportPlaylist(ds model.DataStore) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
plsRepo := ds.Playlist(ctx)
plsId := chi.URLParam(r, "playlistId")
pls, err := plsRepo.Get(plsId)
if err == model.ErrNotFound {
log.Warn("Playlist not found", "playlistId", plsId)
http.Error(w, "not found", http.StatusNotFound)
return
}
if err != nil {
log.Error("Error retrieving the playlist", "playlistId", plsId, err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "audio/x-mpegurl")
// TODO: Move this and the import playlist logic to `core`
w.Write([]byte("#EXTM3U\n"))
for _, t := range pls.Tracks {
header := fmt.Sprintf("#EXTINF:%.f,%s - %s\n", t.Duration, t.Artist, t.Title)
line := t.Path + "\n"
_, err := w.Write([]byte(header + line))
if err != nil {
log.Error(ctx, "Error sending playlist", "name", pls.Name)
}
}
}
}
func deleteFromPlaylist(ds model.DataStore) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
playlistId := utils.ParamString(r, ":playlistId")