fix: improve subsonic client compatibility

This commit is contained in:
2026-04-03 21:16:40 +03:00
parent a054192e45
commit 0b10dfe055
3 changed files with 166 additions and 23 deletions

View File

@@ -36,6 +36,7 @@ type Track struct {
Title string `json:"title"`
ArtistName string `json:"artistName"`
AlbumTitle string `json:"albumTitle"`
Genre string `json:"genre"`
TrackNumber int `json:"trackNumber"`
DurationSecs int `json:"durationSeconds"`
BitrateKbps int `json:"bitrateKbps"`
@@ -269,7 +270,7 @@ func (s *Service) AlbumByID(ctx context.Context, id string) (AlbumDetail, error)
func (s *Service) Tracks(ctx context.Context, limit int) ([]Track, error) {
rows, err := s.db.QueryContext(
ctx,
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(t.track_number, 0),
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(al.genre, ''), COALESCE(t.track_number, 0),
COALESCE(t.duration_seconds, 0), COALESCE(t.bitrate_kbps, 0), t.file_path, COALESCE(t.content_type, ''), COALESCE(al.cover_art_id, '')
FROM tracks t
JOIN artists a ON a.id = t.artist_id
@@ -293,6 +294,7 @@ func (s *Service) Tracks(ctx context.Context, limit int) ([]Track, error) {
&track.Title,
&track.ArtistName,
&track.AlbumTitle,
&track.Genre,
&track.TrackNumber,
&track.DurationSecs,
&track.BitrateKbps,
@@ -313,7 +315,7 @@ func (s *Service) TrackByID(ctx context.Context, id string) (Track, error) {
err := s.db.QueryRowContext(
ctx,
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(t.track_number, 0),
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(al.genre, ''), COALESCE(t.track_number, 0),
COALESCE(t.duration_seconds, 0), COALESCE(t.bitrate_kbps, 0), t.file_path, COALESCE(t.content_type, ''), COALESCE(al.cover_art_id, '')
FROM tracks t
JOIN artists a ON a.id = t.artist_id
@@ -327,6 +329,7 @@ func (s *Service) TrackByID(ctx context.Context, id string) (Track, error) {
&track.Title,
&track.ArtistName,
&track.AlbumTitle,
&track.Genre,
&track.TrackNumber,
&track.DurationSecs,
&track.BitrateKbps,
@@ -415,6 +418,36 @@ func (s *Service) Genres(ctx context.Context) ([]GenreSummary, error) {
return genres, rows.Err()
}
func (s *Service) SongsByGenre(ctx context.Context, genre string, count, offset int) ([]Track, error) {
if count <= 0 {
count = 50
}
if offset < 0 {
offset = 0
}
rows, err := s.db.QueryContext(
ctx,
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(al.genre, ''), COALESCE(t.track_number, 0),
COALESCE(t.duration_seconds, 0), COALESCE(t.bitrate_kbps, 0), t.file_path, COALESCE(t.content_type, ''), COALESCE(al.cover_art_id, '')
FROM tracks t
JOIN artists a ON a.id = t.artist_id
JOIN albums al ON al.id = t.album_id
WHERE LOWER(TRIM(COALESCE(al.genre, ''))) = LOWER(TRIM(?))
ORDER BY a.name ASC, al.year DESC, al.title ASC, t.disc_number ASC, t.track_number ASC
LIMIT ? OFFSET ?`,
genre,
count,
offset,
)
if err != nil {
return nil, fmt.Errorf("query songs by genre: %w", err)
}
defer rows.Close()
return scanTracks(rows)
}
func (s *Service) Star(ctx context.Context, userID string, trackIDs, albumIDs, artistIDs []string) error {
return s.updateFavorites(ctx, userID, trackIDs, albumIDs, artistIDs, true)
}
@@ -463,7 +496,7 @@ func (s *Service) RecentTracks(ctx context.Context, userID string, limit int) ([
if userID != "" {
rows, err := s.db.QueryContext(
ctx,
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(t.track_number, 0),
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(al.genre, ''), COALESCE(t.track_number, 0),
COALESCE(t.duration_seconds, 0), COALESCE(t.bitrate_kbps, 0), t.file_path, COALESCE(t.content_type, ''), COALESCE(al.cover_art_id, '')
FROM tracks t
JOIN artists a ON a.id = t.artist_id
@@ -488,7 +521,7 @@ func (s *Service) RecentTracks(ctx context.Context, userID string, limit int) ([
rows, err := s.db.QueryContext(
ctx,
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(t.track_number, 0),
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(al.genre, ''), COALESCE(t.track_number, 0),
COALESCE(t.duration_seconds, 0), COALESCE(t.bitrate_kbps, 0), t.file_path, COALESCE(t.content_type, ''), COALESCE(al.cover_art_id, '')
FROM tracks t
JOIN artists a ON a.id = t.artist_id
@@ -617,7 +650,7 @@ func (s *Service) albumsByArtistID(ctx context.Context, artistID string) ([]Albu
func (s *Service) tracksByAlbumID(ctx context.Context, albumID string) ([]Track, error) {
rows, err := s.db.QueryContext(
ctx,
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(t.track_number, 0),
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(al.genre, ''), COALESCE(t.track_number, 0),
COALESCE(t.duration_seconds, 0), COALESCE(t.bitrate_kbps, 0), t.file_path, COALESCE(t.content_type, ''), COALESCE(al.cover_art_id, '')
FROM tracks t
JOIN artists a ON a.id = t.artist_id
@@ -697,8 +730,8 @@ func (s *Service) searchAlbums(ctx context.Context, pattern string, limit int) (
func (s *Service) searchTracks(ctx context.Context, pattern string, limit int) ([]Track, error) {
rows, err := s.db.QueryContext(
ctx,
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(t.track_number, 0),
COALESCE(t.duration_seconds, 0), t.file_path, COALESCE(t.content_type, ''), COALESCE(al.cover_art_id, '')
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(al.genre, ''), COALESCE(t.track_number, 0),
COALESCE(t.duration_seconds, 0), COALESCE(t.bitrate_kbps, 0), t.file_path, COALESCE(t.content_type, ''), COALESCE(al.cover_art_id, '')
FROM tracks t
JOIN artists a ON a.id = t.artist_id
JOIN albums al ON al.id = t.album_id
@@ -817,7 +850,7 @@ func (s *Service) starredAlbums(ctx context.Context, userID string) ([]Album, er
func (s *Service) starredTracks(ctx context.Context, userID string) ([]Track, error) {
rows, err := s.db.QueryContext(
ctx,
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(t.track_number, 0),
`SELECT t.id, t.album_id, t.artist_id, t.title, a.name, al.title, COALESCE(al.genre, ''), COALESCE(t.track_number, 0),
COALESCE(t.duration_seconds, 0), COALESCE(t.bitrate_kbps, 0), t.file_path, COALESCE(t.content_type, ''), COALESCE(al.cover_art_id, '')
FROM favorites f
JOIN tracks t ON t.id = f.entity_id
@@ -846,6 +879,7 @@ func scanTracks(rows *sql.Rows) ([]Track, error) {
&track.Title,
&track.ArtistName,
&track.AlbumTitle,
&track.Genre,
&track.TrackNumber,
&track.DurationSecs,
&track.BitrateKbps,