Merge branch 'dev-0.1.2' into 'master'

0.1.2

See merge request goscrobble/goscrobble-api!5
This commit is contained in:
Daniel Mason 2022-01-05 22:30:00 +00:00
commit 1298bf9a7a
6 changed files with 147 additions and 82 deletions

View File

@ -1,6 +1,7 @@
# 0.1.2
- Add docker-compose file for local dev
- Implemented top listeners for artist/album endpoints to match track
- Add recent endpoint
# 0.1.1
- Cached all config values

View File

@ -130,54 +130,56 @@ func getAlbumByUUID(uuid string) (Album, error) {
}
// getTopUsersForAlbumUUID - Returns list of top users for a track
func getTopUsersForAlbumUUID(trackUUID string, limit int, page int) (TopUserResponse, error) {
func getTopUsersForAlbumUUID(albumUUID string, limit int, page int) (TopUserResponse, error) {
response := TopUserResponse{}
// TODO: Implement this
// var count int
var count int
// total, err := getDbCount(
// "SELECT COUNT(*) FROM `scrobbles` WHERE `album` = UUID_TO_BIN(?, true) GROUP BY `album`, `user`", trackUUID)
total, err := getDbCount(
"SELECT COUNT(*) FROM `scrobbles` "+
"JOIN `track_album` ON `track_album`.`track` = `scrobbles`.`track` "+
"WHERE `track_album`.`album` = UUID_TO_BIN(?, true);", albumUUID)
// if err != nil {
// log.Printf("Failed to fetch scrobble count: %+v", err)
// return response, errors.New("Failed to fetch combined scrobbles")
// }
if err != nil {
log.Printf("Failed to fetch scrobble count: %+v", err)
return response, errors.New("Failed to fetch combined scrobbles")
}
// rows, err := db.Query(
// "SELECT BIN_TO_UUID(`scrobbles`.`user`, true), `users`.`username`, COUNT(*) "+
// "FROM `scrobbles` "+
// "JOIN `users` ON `scrobbles`.`user` = `users`.`uuid` "+
// "WHERE `track` = UUID_TO_BIN(?, true) "+
// "GROUP BY `scrobbles`.`user` "+
// "ORDER BY COUNT(*) DESC LIMIT ?",
// trackUUID, limit)
rows, err := db.Query(
"SELECT BIN_TO_UUID(`scrobbles`.`user`, true), `users`.`username`, COUNT(*) "+
"FROM `scrobbles` "+
"JOIN `users` ON `scrobbles`.`user` = `users`.`uuid` "+
"JOIN `track_album` ON `track_album`.`track` = `scrobbles`.`track` "+
"WHERE `track_album`.`album` = UUID_TO_BIN(?, true) "+
"GROUP BY `scrobbles`.`user` "+
"ORDER BY COUNT(*) DESC LIMIT ?",
albumUUID, limit)
// if err != nil {
// log.Printf("Failed to fetch scrobbles: %+v", err)
// return response, errors.New("Failed to fetch combined scrobbles")
// }
// defer rows.Close()
if err != nil {
log.Printf("Failed to fetch scrobbles: %+v", err)
return response, errors.New("Failed to fetch combined scrobbles")
}
defer rows.Close()
// for rows.Next() {
// item := TopUserResponseItem{}
// err := rows.Scan(&item.UserUUID, &item.UserName, &item.Count)
// if err != nil {
// log.Printf("Failed to fetch scrobbles: %+v", err)
// return response, errors.New("Failed to fetch combined scrobbles")
// }
// count++
// response.Items = append(response.Items, item)
// }
for rows.Next() {
item := TopUserResponseItem{}
err := rows.Scan(&item.UserUUID, &item.UserName, &item.Count)
if err != nil {
log.Printf("Failed to fetch scrobbles: %+v", err)
return response, errors.New("Failed to fetch combined scrobbles")
}
count++
response.Items = append(response.Items, item)
}
// err = rows.Err()
// if err != nil {
// log.Printf("Failed to fetch scrobbles: %+v", err)
// return response, errors.New("Failed to fetch scrobbles")
// }
err = rows.Err()
if err != nil {
log.Printf("Failed to fetch scrobbles: %+v", err)
return response, errors.New("Failed to fetch scrobbles")
}
// response.Meta.Count = count
// response.Meta.Total = total
// response.Meta.Page = page
response.Meta.Count = count
response.Meta.Total = total
response.Meta.Page = page
return response, nil
}

View File

@ -166,56 +166,57 @@ func getTopArtists(userUuid string) (TopArtists, error) {
}
// getTopUsersForArtistUUID - Returns list of top users for a track
func getTopUsersForArtistUUID(trackUUID string, limit int, page int) (TopUserResponse, error) {
func getTopUsersForArtistUUID(artistUUID string, limit int, page int) (TopUserResponse, error) {
response := TopUserResponse{}
// TODO: Implement
var count int
// var count int
total, err := getDbCount(
"SELECT COUNT(*) FROM `scrobbles` "+
"JOIN `track_artist` ON `track_artist`.`track` = `scrobbles`.`track` "+
"WHERE `track_artist`.`artist` = UUID_TO_BIN(?, true);", artistUUID)
// total, err := getDbCount(
// "SELECT COUNT(*) FROM `scrobbles` WHERE `track` = UUID_TO_BIN(?, true) GROUP BY `track`, `user`", trackUUID)
if err != nil {
log.Printf("Failed to fetch scrobble count: %+v", err)
return response, errors.New("Failed to fetch combined scrobbles")
}
// if err != nil {
// log.Printf("Failed to fetch scrobble count: %+v", err)
// return response, errors.New("Failed to fetch combined scrobbles")
// }
rows, err := db.Query(
"SELECT BIN_TO_UUID(`scrobbles`.`user`, true), `users`.`username`, COUNT(*) "+
"FROM `scrobbles` "+
"JOIN `users` ON `scrobbles`.`user` = `users`.`uuid` "+
"JOIN `track_artist` ON `track_artist`.`track` = `scrobbles`.`track` "+
"WHERE `track_artist`.`artist` = UUID_TO_BIN(?, true) "+
"GROUP BY `scrobbles`.`user` "+
"ORDER BY COUNT(*) DESC LIMIT ?",
artistUUID, limit)
// rows, err := db.Query(
// "SELECT BIN_TO_UUID(`scrobbles`.`user`, true), `users`.`username`, COUNT(*) "+
// "FROM `scrobbles` "+
// "JOIN `users` ON `scrobbles`.`user` = `users`.`uuid` "+
// "WHERE `track` = UUID_TO_BIN(?, true) "+
// "GROUP BY `scrobbles`.`user` "+
// "ORDER BY COUNT(*) DESC LIMIT ?",
// trackUUID, limit)
if err != nil {
log.Printf("Failed to fetch scrobbles: %+v", err)
return response, errors.New("Failed to fetch combined scrobbles")
}
defer rows.Close()
// if err != nil {
// log.Printf("Failed to fetch scrobbles: %+v", err)
// return response, errors.New("Failed to fetch combined scrobbles")
// }
// defer rows.Close()
for rows.Next() {
item := TopUserResponseItem{}
err := rows.Scan(&item.UserUUID, &item.UserName, &item.Count)
if err != nil {
log.Printf("Failed to fetch scrobbles: %+v", err)
return response, errors.New("Failed to fetch combined scrobbles")
}
count++
response.Items = append(response.Items, item)
}
// for rows.Next() {
// item := TopUserResponseItem{}
// err := rows.Scan(&item.UserUUID, &item.UserName, &item.Count)
// if err != nil {
// log.Printf("Failed to fetch scrobbles: %+v", err)
// return response, errors.New("Failed to fetch combined scrobbles")
// }
// count++
// response.Items = append(response.Items, item)
// }
err = rows.Err()
if err != nil {
log.Printf("Failed to fetch scrobbles: %+v", err)
return response, errors.New("Failed to fetch scrobbles")
}
// err = rows.Err()
// if err != nil {
// log.Printf("Failed to fetch scrobbles: %+v", err)
// return response, errors.New("Failed to fetch scrobbles")
// }
// response.Meta.Count = count
// response.Meta.Total = total
// response.Meta.Page = page
response.Meta.Count = count
response.Meta.Total = total
response.Meta.Page = page
return response, nil
}

View File

@ -35,6 +35,7 @@ type ScrobbleResponseItem struct {
Album string `json:"album"`
Track ScrobbleTrackItem `json:"track"`
Source string `json:"source"`
User ScrobbleTrackItem `json:"user"`
}
type ScrobbleTrackItem struct {
@ -127,3 +128,49 @@ func checkIfScrobbleExists(userUuid string, timestamp time.Time, source string)
return count != 0
}
func getRecentScrobbles() (ScrobbleResponse, error) {
scrobbleReq := ScrobbleResponse{}
var count int
limit := 50
rows, err := db.Query(
"SELECT BIN_TO_UUID(`scrobbles`.`uuid`, true), `scrobbles`.`created_at`, BIN_TO_UUID(`artists`.`uuid`, true), `artists`.`name`, `albums`.`name`, BIN_TO_UUID(`tracks`.`uuid`, true), `tracks`.`name`, `scrobbles`.`source`, BIN_TO_UUID(`scrobbles`.`user`, true), `users`.`username` FROM `scrobbles` "+
"JOIN tracks ON scrobbles.track = tracks.uuid "+
"JOIN track_artist ON track_artist.track = tracks.uuid "+
"JOIN track_album ON track_album.track = tracks.uuid "+
"JOIN artists ON track_artist.artist = artists.uuid "+
"JOIN albums ON track_album.album = albums.uuid "+
"JOIN users ON scrobbles.user = users.uuid "+
"GROUP BY scrobbles.uuid, albums.uuid "+
"ORDER BY scrobbles.created_at DESC LIMIT ?", limit)
if err != nil {
log.Printf("Failed to fetch scrobbles: %+v", err)
return scrobbleReq, errors.New("Failed to fetch scrobbles")
}
defer rows.Close()
for rows.Next() {
item := ScrobbleResponseItem{}
err := rows.Scan(&item.UUID, &item.Timestamp, &item.Artist.UUID, &item.Artist.Name, &item.Album, &item.Track.UUID, &item.Track.Name, &item.Source, &item.User.UUID, &item.User.Name)
if err != nil {
log.Printf("Failed to fetch scrobbles: %+v", err)
return scrobbleReq, errors.New("Failed to fetch scrobbles")
}
count++
scrobbleReq.Items = append(scrobbleReq.Items, item)
}
err = rows.Err()
if err != nil {
log.Printf("Failed to fetch scrobbles: %+v", err)
return scrobbleReq, errors.New("Failed to fetch scrobbles")
}
scrobbleReq.Meta.Count = count
scrobbleReq.Meta.Total = 50
scrobbleReq.Meta.Page = 1
return scrobbleReq, nil
}

View File

@ -72,6 +72,8 @@ func HandleRequests(port string) {
// No Auth
v1.HandleFunc("/stats", limitMiddleware(handleStats, lightLimiter)).Methods("GET")
v1.HandleFunc("/recent", limitMiddleware(handleRecentScrobbles, lightLimiter)).Methods("GET")
v1.HandleFunc("/profile/{username}", limitMiddleware(getProfile, lightLimiter)).Methods("GET")
v1.HandleFunc("/artists/top/{uuid}", limitMiddleware(getArtists, lightLimiter)).Methods("GET")
@ -844,3 +846,15 @@ func getServerInfo(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write(js)
}
func handleRecentScrobbles(w http.ResponseWriter, r *http.Request) {
scrobbleList, err := getRecentScrobbles()
if err != nil {
throwOkError(w, err.Error())
return
}
json, _ := json.Marshal(&scrobbleList)
w.WriteHeader(http.StatusOK)
w.Write(json)
}

View File

@ -302,7 +302,7 @@ func getTopUsersForTrackUUID(trackUUID string, limit int, page int) (TopUserResp
var count int
total, err := getDbCount(
"SELECT COUNT(*) FROM `scrobbles` WHERE `track` = UUID_TO_BIN(?, true) GROUP BY `track`, `user`", trackUUID)
"SELECT COUNT(*) FROM `scrobbles` WHERE `track` = UUID_TO_BIN(?, true)", trackUUID)
if err != nil {
log.Printf("Failed to fetch scrobble count: %+v", err)