diff --git a/app/start.go b/app/start.go index 13dd0c1..ddb12d8 100644 --- a/app/start.go +++ b/app/start.go @@ -44,6 +44,7 @@ func Start(conf common.Conf, dbO *sql.DB) *gin.Engine { gv1.GET("/users/scores/recent", Method(v1.UserScoresRecentGET, common.PrivilegeRead)) gv1.GET("/badges", Method(v1.BadgesGET, common.PrivilegeRead)) gv1.GET("/beatmaps", Method(v1.BeatmapGET, common.PrivilegeRead)) + gv1.GET("/leaderboard", Method(v1.LeaderboardGET, common.PrivilegeRead)) // ReadConfidential privilege required gv1.GET("/friends", Method(v1.FriendsGET, common.PrivilegeReadConfidential)) diff --git a/app/v1/doc.go b/app/v1/doc.go index 53c38b0..5b1009c 100644 --- a/app/v1/doc.go +++ b/app/v1/doc.go @@ -35,7 +35,7 @@ func DocGET(md common.MethodData) common.CodeMessager { err := rows.Scan(&f.ID, &f.DocName, &f.Public, &f.IsRule) if err != nil { md.Err(err) - return Err500 + continue } r.Files = append(r.Files, f) } diff --git a/app/v1/leaderboard.go b/app/v1/leaderboard.go new file mode 100644 index 0000000..e1e8a17 --- /dev/null +++ b/app/v1/leaderboard.go @@ -0,0 +1,78 @@ +package v1 + +import ( + "fmt" + "time" + + "git.zxq.co/ripple/rippleapi/common" +) + +type leaderboardUser struct { + userData + ChosenMode modeData `json:"chosen_mode"` + PlayStyle int `json:"play_style"` + FavouriteMode int `json:"favourite_mode"` +} + +type leaderboardResponse struct { + common.ResponseBase + Users []leaderboardUser `json:"users"` +} + +const lbUserQuery = ` +SELECT + users.id, users.username, users.register_datetime, users.rank, users.latest_activity, + + users_stats.username_aka, users_stats.country, users_stats.show_country, + users_stats.play_style, users_stats.favourite_mode, + + users_stats.ranked_score_%[1]s, users_stats.total_score_%[1]s, users_stats.playcount_%[1]s, + users_stats.replays_watched_%[1]s, users_stats.total_hits_%[1]s, + users_stats.avg_accuracy_%[1]s, users_stats.pp_%[1]s, leaderboard_%[1]s.position as %[1]s_position +FROM leaderboard_%[1]s +INNER JOIN users ON users.id = leaderboard_%[1]s.user +INNER JOIN users_stats ON users_stats.id = leaderboard_%[1]s.user +%[2]s` + +// LeaderboardGET gets the leaderboard. +func LeaderboardGET(md common.MethodData) common.CodeMessager { + m := getMode(md.C.Query("mode")) + query := fmt.Sprintf(lbUserQuery, m, `WHERE users.allowed = '1' ORDER BY leaderboard_`+m+`.position `+ + common.Paginate(md.C.Query("p"), md.C.Query("l"), 100)) + rows, err := md.DB.Query(query) + if err != nil { + md.Err(err) + return Err500 + } + var resp leaderboardResponse + for rows.Next() { + var ( + u leaderboardUser + register int64 + latestActivity int64 + showCountry bool + ) + err := rows.Scan( + &u.ID, &u.Username, ®ister, &u.Rank, &latestActivity, + + &u.UsernameAKA, &u.Country, &showCountry, + &u.PlayStyle, &u.FavouriteMode, + + &u.ChosenMode.RankedScore, &u.ChosenMode.TotalScore, &u.ChosenMode.PlayCount, + &u.ChosenMode.ReplaysWatched, &u.ChosenMode.TotalHits, + &u.ChosenMode.Accuracy, &u.ChosenMode.PP, &u.ChosenMode.GlobalLeaderboardRank, + ) + if err != nil { + md.Err(err) + continue + } + if !showCountry { + u.Country = "XX" + } + u.RegisteredOn = time.Unix(register, 0) + u.LatestActivity = time.Unix(latestActivity, 0) + resp.Users = append(resp.Users, u) + } + resp.Code = 200 + return resp +} diff --git a/app/v1/user.go b/app/v1/user.go index 5297ea8..81c068d 100644 --- a/app/v1/user.go +++ b/app/v1/user.go @@ -12,7 +12,6 @@ import ( ) type userData struct { - common.ResponseBase ID int `json:"id"` Username string `json:"username"` UsernameAKA string `json:"username_aka"` @@ -41,9 +40,14 @@ LIMIT 1` return userPuts(md, md.DB.QueryRow(query, param)) } +type userPutsUserData struct { + common.ResponseBase + userData +} + func userPuts(md common.MethodData, row *sql.Row) common.CodeMessager { var err error - var user userData + var user userPutsUserData var ( registeredOn int64