mirror of
https://github.com/riwiwa/muzi.git
synced 2026-03-04 00:51:59 -08:00
fix same tracks in different album not appearing in track page
This commit is contained in:
@@ -394,6 +394,58 @@ func GetSongByName(userId int, title string, artistId int) (Song, error) {
|
|||||||
return song, nil
|
return song, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSongsByName(userId int, title string, artistId int) ([]Song, error) {
|
||||||
|
var query string
|
||||||
|
var args []interface{}
|
||||||
|
if artistId > 0 {
|
||||||
|
query = `SELECT id, user_id, title, artist_id, album_id, duration_ms, spotify_id, musicbrainz_id
|
||||||
|
FROM songs WHERE user_id = $1 AND title = $2 AND artist_id = $3 ORDER BY id`
|
||||||
|
args = []interface{}{userId, title, artistId}
|
||||||
|
} else {
|
||||||
|
query = `SELECT id, user_id, title, artist_id, album_id, duration_ms, spotify_id, musicbrainz_id
|
||||||
|
FROM songs WHERE user_id = $1 AND title = $2 ORDER BY id`
|
||||||
|
args = []interface{}{userId, title}
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := Pool.Query(context.Background(), query, args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var songs []Song
|
||||||
|
for rows.Next() {
|
||||||
|
var song Song
|
||||||
|
var artistIdVal, albumIdVal pgtype.Int4
|
||||||
|
var durationMs *int
|
||||||
|
var spotifyIdPg, musicbrainzIdPg pgtype.Text
|
||||||
|
|
||||||
|
err := rows.Scan(
|
||||||
|
&song.Id, &song.UserId, &song.Title, &artistIdVal, &albumIdVal,
|
||||||
|
&durationMs, &spotifyIdPg, &musicbrainzIdPg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if artistIdVal.Status == pgtype.Present {
|
||||||
|
song.ArtistId = int(artistIdVal.Int)
|
||||||
|
}
|
||||||
|
if albumIdVal.Status == pgtype.Present {
|
||||||
|
song.AlbumId = int(albumIdVal.Int)
|
||||||
|
}
|
||||||
|
if durationMs != nil {
|
||||||
|
song.DurationMs = *durationMs
|
||||||
|
}
|
||||||
|
if spotifyIdPg.Status == pgtype.Present {
|
||||||
|
song.SpotifyId = spotifyIdPg.String
|
||||||
|
}
|
||||||
|
if musicbrainzIdPg.Status == pgtype.Present {
|
||||||
|
song.MusicbrainzId = musicbrainzIdPg.String
|
||||||
|
}
|
||||||
|
songs = append(songs, song)
|
||||||
|
}
|
||||||
|
return songs, nil
|
||||||
|
}
|
||||||
|
|
||||||
func UpdateSong(id int, title string, durationMs int, spotifyId, musicbrainzId string) error {
|
func UpdateSong(id int, title string, durationMs int, spotifyId, musicbrainzId string) error {
|
||||||
_, err := Pool.Exec(context.Background(),
|
_, err := Pool.Exec(context.Background(),
|
||||||
`UPDATE songs SET title = $1, duration_ms = $2, spotify_id = $3, musicbrainz_id = $4 WHERE id = $5`,
|
`UPDATE songs SET title = $1, duration_ms = $2, spotify_id = $3, musicbrainz_id = $4 WHERE id = $5`,
|
||||||
@@ -673,3 +725,41 @@ func GetHistoryForAlbum(userId, albumId int, limit, offset int) ([]ScrobbleEntry
|
|||||||
}
|
}
|
||||||
return entries, nil
|
return entries, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSongStatsForSongs(userId int, songIds []int) (int, error) {
|
||||||
|
if len(songIds) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
var count int
|
||||||
|
err := Pool.QueryRow(context.Background(),
|
||||||
|
"SELECT COUNT(*) FROM history WHERE user_id = $1 AND song_id = ANY($2)",
|
||||||
|
userId, songIds).Scan(&count)
|
||||||
|
return count, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetHistoryForSongs(userId int, songIds []int, limit, offset int) ([]ScrobbleEntry, error) {
|
||||||
|
if len(songIds) == 0 {
|
||||||
|
return []ScrobbleEntry{}, nil
|
||||||
|
}
|
||||||
|
rows, err := Pool.Query(context.Background(),
|
||||||
|
`SELECT h.timestamp, h.song_name, h.album_name, h.ms_played, h.platform,
|
||||||
|
(SELECT name FROM artists WHERE id = h.artist_id) as artist_name
|
||||||
|
FROM history h WHERE h.user_id = $1 AND h.song_id = ANY($2)
|
||||||
|
ORDER BY h.timestamp DESC LIMIT $3 OFFSET $4`,
|
||||||
|
userId, songIds, limit, offset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var entries []ScrobbleEntry
|
||||||
|
for rows.Next() {
|
||||||
|
var e ScrobbleEntry
|
||||||
|
err := rows.Scan(&e.Timestamp, &e.SongName, &e.AlbumName, &e.MsPlayed, &e.Platform, &e.ArtistName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
entries = append(entries, e)
|
||||||
|
}
|
||||||
|
return entries, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td><a href="/profile/{{$username}}/artist/{{urlquery .ArtistName}}">{{.ArtistName}}</a></td>
|
<td><a href="/profile/{{$username}}/artist/{{urlquery .ArtistName}}">{{.ArtistName}}</a></td>
|
||||||
<td><a href="/profile/{{$username}}/song/{{urlquery .ArtistName}}/{{urlquery .SongName}}">{{.SongName}}</a></td>
|
<td><a href="/profile/{{$username}}/song/{{urlquery .ArtistName}}/{{urlquery .SongName}}">{{.SongName}}</a></td>
|
||||||
<td><a href="/profile/{{$username}}/album/{{urlquery .AlbumName}}">{{.AlbumName}}</a></td>
|
<td><a href="/profile/{{$username}}/album/{{urlquery .ArtistName}}/{{urlquery .AlbumName}}">{{.AlbumName}}</a></td>
|
||||||
<td title="{{formatTimestampFull .Timestamp}}">{{formatTimestamp .Timestamp}}</td>
|
<td title="{{formatTimestampFull .Timestamp}}">{{formatTimestamp .Timestamp}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
{{if .Artist.Name}}
|
{{if .Artist.Name}}
|
||||||
<h2><a href="/profile/{{.Username}}/artist/{{urlquery .Artist.Name}}">{{.Artist.Name}}</a></h2>
|
<h2><a href="/profile/{{.Username}}/artist/{{urlquery .Artist.Name}}">{{.Artist.Name}}</a></h2>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .Album.Title}}
|
{{range .Albums}}
|
||||||
<h3><a href="/profile/{{.Username}}/album/{{urlquery .Artist.Name}}/{{urlquery .Album.Title}}">{{.Album.Title}}</a></h3>
|
<h3><a href="/profile/{{$.Username}}/album/{{urlquery $.Artist.Name}}/{{urlquery .Title}}">{{.Title}}</a></h3>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="profile-top-blank">
|
<div class="profile-top-blank">
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td><a href="/profile/{{$username}}/artist/{{urlquery .ArtistName}}">{{.ArtistName}}</a></td>
|
<td><a href="/profile/{{$username}}/artist/{{urlquery .ArtistName}}">{{.ArtistName}}</a></td>
|
||||||
<td><a href="/profile/{{$username}}/song/{{urlquery .ArtistName}}/{{urlquery .SongName}}">{{.SongName}}</a></td>
|
<td><a href="/profile/{{$username}}/song/{{urlquery .ArtistName}}/{{urlquery .SongName}}">{{.SongName}}</a></td>
|
||||||
<td><a href="/profile/{{$username}}/album/{{urlquery .AlbumName}}">{{.AlbumName}}</a></td>
|
<td><a href="/profile/{{$username}}/album/{{urlquery .ArtistName}}/{{urlquery .AlbumName}}">{{.AlbumName}}</a></td>
|
||||||
<td title="{{formatTimestampFull .Timestamp}}">{{formatTimestamp .Timestamp}}</td>
|
<td title="{{formatTimestampFull .Timestamp}}">{{formatTimestamp .Timestamp}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ type SongData struct {
|
|||||||
Username string
|
Username string
|
||||||
Song db.Song
|
Song db.Song
|
||||||
Artist db.Artist
|
Artist db.Artist
|
||||||
Album db.Album
|
Albums []db.Album
|
||||||
ListenCount int
|
ListenCount int
|
||||||
Times []db.ScrobbleEntry
|
Times []db.ScrobbleEntry
|
||||||
Page int
|
Page int
|
||||||
@@ -151,11 +151,11 @@ func songPageHandler() http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
song, err := db.GetSongByName(userId, songTitle, artist.Id)
|
songs, err := db.GetSongsByName(userId, songTitle, artist.Id)
|
||||||
if err != nil {
|
if err != nil || len(songs) == 0 {
|
||||||
songs, _, searchErr := db.SearchSongs(userId, songTitle)
|
songList, _, searchErr := db.SearchSongs(userId, songTitle)
|
||||||
if searchErr == nil && len(songs) > 0 {
|
if searchErr == nil && len(songList) > 0 {
|
||||||
song = songs[0]
|
songs = songList
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(os.Stderr, "Cannot find song %s: %v\n", songTitle, err)
|
fmt.Fprintf(os.Stderr, "Cannot find song %s: %v\n", songTitle, err)
|
||||||
http.Error(w, "Song not found", http.StatusNotFound)
|
http.Error(w, "Song not found", http.StatusNotFound)
|
||||||
@@ -163,10 +163,19 @@ func songPageHandler() http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
song := songs[0]
|
||||||
artist, _ = db.GetArtistById(song.ArtistId)
|
artist, _ = db.GetArtistById(song.ArtistId)
|
||||||
var album db.Album
|
|
||||||
if song.AlbumId > 0 {
|
var songIds []int
|
||||||
album, _ = db.GetAlbumById(song.AlbumId)
|
var albums []db.Album
|
||||||
|
seenAlbums := make(map[int]bool)
|
||||||
|
for _, s := range songs {
|
||||||
|
songIds = append(songIds, s.Id)
|
||||||
|
if s.AlbumId > 0 && !seenAlbums[s.AlbumId] {
|
||||||
|
seenAlbums[s.AlbumId] = true
|
||||||
|
album, _ := db.GetAlbumById(s.AlbumId)
|
||||||
|
albums = append(albums, album)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pageStr := r.URL.Query().Get("page")
|
pageStr := r.URL.Query().Get("page")
|
||||||
@@ -183,12 +192,12 @@ func songPageHandler() http.HandlerFunc {
|
|||||||
lim := 15
|
lim := 15
|
||||||
off := (pageInt - 1) * lim
|
off := (pageInt - 1) * lim
|
||||||
|
|
||||||
listenCount, err := db.GetSongStats(userId, song.Id)
|
listenCount, err := db.GetSongStatsForSongs(userId, songIds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Cannot get song stats: %v\n", err)
|
fmt.Fprintf(os.Stderr, "Cannot get song stats: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
entries, err := db.GetHistoryForSong(userId, song.Id, lim, off)
|
entries, err := db.GetHistoryForSongs(userId, songIds, lim, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Cannot get history for song: %v\n", err)
|
fmt.Fprintf(os.Stderr, "Cannot get history for song: %v\n", err)
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
@@ -199,7 +208,7 @@ func songPageHandler() http.HandlerFunc {
|
|||||||
Username: username,
|
Username: username,
|
||||||
Song: song,
|
Song: song,
|
||||||
Artist: artist,
|
Artist: artist,
|
||||||
Album: album,
|
Albums: albums,
|
||||||
ListenCount: listenCount,
|
ListenCount: listenCount,
|
||||||
Times: entries,
|
Times: entries,
|
||||||
Page: pageInt,
|
Page: pageInt,
|
||||||
|
|||||||
Reference in New Issue
Block a user