feat(subsonic): support public playlists
When multiple people share the same instance, they might want to share their playlists between them. This allows people to mark playlists as public, and to listen to public playlists from other people. Listeners will also know who owns the playlist, to help avoid confusion and make this feature a bit nicer. Subsonic restrict updating playlists only to owners, this honors that behavior, but adding flexibility could be achieved easily.
This commit is contained in:
@@ -23,6 +23,8 @@ func playlistRender(c *Controller, playlist *db.Playlist) *spec.Playlist {
|
|||||||
Comment: playlist.Comment,
|
Comment: playlist.Comment,
|
||||||
Created: playlist.CreatedAt,
|
Created: playlist.CreatedAt,
|
||||||
SongCount: playlist.TrackCount,
|
SongCount: playlist.TrackCount,
|
||||||
|
Public: playlist.IsPublic,
|
||||||
|
Owner: user.Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
trackIDs := playlist.GetItems()
|
trackIDs := playlist.GetItems()
|
||||||
@@ -48,7 +50,7 @@ func playlistRender(c *Controller, playlist *db.Playlist) *spec.Playlist {
|
|||||||
func (c *Controller) ServeGetPlaylists(r *http.Request) *spec.Response {
|
func (c *Controller) ServeGetPlaylists(r *http.Request) *spec.Response {
|
||||||
user := r.Context().Value(CtxUser).(*db.User)
|
user := r.Context().Value(CtxUser).(*db.User)
|
||||||
var playlists []*db.Playlist
|
var playlists []*db.Playlist
|
||||||
c.DB.Where("user_id=?", user.ID).Find(&playlists)
|
c.DB.Where("user_id=?", user.ID).Or("is_public=?", true).Find(&playlists)
|
||||||
sub := spec.NewResponse()
|
sub := spec.NewResponse()
|
||||||
sub.Playlists = &spec.Playlists{
|
sub.Playlists = &spec.Playlists{
|
||||||
List: make([]*spec.Playlist, len(playlists)),
|
List: make([]*spec.Playlist, len(playlists)),
|
||||||
@@ -90,6 +92,9 @@ func (c *Controller) ServeCreatePlaylist(r *http.Request) *spec.Response {
|
|||||||
FirstOrCreate(&playlist)
|
FirstOrCreate(&playlist)
|
||||||
|
|
||||||
// update meta info
|
// update meta info
|
||||||
|
if playlist.UserID != 0 && playlist.UserID != user.ID {
|
||||||
|
return spec.NewResponse()
|
||||||
|
}
|
||||||
playlist.UserID = user.ID
|
playlist.UserID = user.ID
|
||||||
if val, err := params.Get("name"); err == nil {
|
if val, err := params.Get("name"); err == nil {
|
||||||
playlist.Name = val
|
playlist.Name = val
|
||||||
@@ -123,6 +128,9 @@ func (c *Controller) ServeUpdatePlaylist(r *http.Request) *spec.Response {
|
|||||||
FirstOrCreate(&playlist)
|
FirstOrCreate(&playlist)
|
||||||
|
|
||||||
// update meta info
|
// update meta info
|
||||||
|
if playlist.UserID != 0 && playlist.UserID != user.ID {
|
||||||
|
return spec.NewResponse()
|
||||||
|
}
|
||||||
playlist.UserID = user.ID
|
playlist.UserID = user.ID
|
||||||
if val, err := params.Get("name"); err == nil {
|
if val, err := params.Get("name"); err == nil {
|
||||||
playlist.Name = val
|
playlist.Name = val
|
||||||
@@ -130,6 +138,9 @@ func (c *Controller) ServeUpdatePlaylist(r *http.Request) *spec.Response {
|
|||||||
if val, err := params.Get("comment"); err == nil {
|
if val, err := params.Get("comment"); err == nil {
|
||||||
playlist.Comment = val
|
playlist.Comment = val
|
||||||
}
|
}
|
||||||
|
if val, err := params.GetBool("public"); err == nil {
|
||||||
|
playlist.IsPublic = val
|
||||||
|
}
|
||||||
trackIDs := playlist.GetItems()
|
trackIDs := playlist.GetItems()
|
||||||
|
|
||||||
// delete items
|
// delete items
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ func (db *DB) Migrate(ctx MigrationContext) error {
|
|||||||
construct(ctx, "202201042236", migrateArtistGuessedFolder),
|
construct(ctx, "202201042236", migrateArtistGuessedFolder),
|
||||||
construct(ctx, "202202092013", migrateArtistCover),
|
construct(ctx, "202202092013", migrateArtistCover),
|
||||||
construct(ctx, "202202121809", migrateAlbumRootDirAgain),
|
construct(ctx, "202202121809", migrateAlbumRootDirAgain),
|
||||||
|
construct(ctx, "202202241218", migratePublicPlaylist),
|
||||||
}
|
}
|
||||||
|
|
||||||
return gormigrate.
|
return gormigrate.
|
||||||
@@ -327,3 +328,7 @@ func migrateArtistCover(tx *gorm.DB, ctx MigrationContext) error {
|
|||||||
func migrateAlbumRootDirAgain(tx *gorm.DB, ctx MigrationContext) error {
|
func migrateAlbumRootDirAgain(tx *gorm.DB, ctx MigrationContext) error {
|
||||||
return migrateAlbumRootDir(tx, ctx)
|
return migrateAlbumRootDir(tx, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func migratePublicPlaylist(tx *gorm.DB, ctx MigrationContext) error {
|
||||||
|
return tx.AutoMigrate(Playlist{}).Error
|
||||||
|
}
|
||||||
|
|||||||
@@ -247,6 +247,7 @@ type Playlist struct {
|
|||||||
Comment string
|
Comment string
|
||||||
TrackCount int
|
TrackCount int
|
||||||
Items string
|
Items string
|
||||||
|
IsPublic bool `sql:"default: null"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Playlist) GetItems() []int {
|
func (p *Playlist) GetItems() []int {
|
||||||
|
|||||||
Reference in New Issue
Block a user