Add /api/v1/beatmaps

This commit is contained in:
Howl 2016-06-08 19:55:52 +02:00
parent 155fbabbbc
commit 9b821e3230
3 changed files with 117 additions and 25 deletions

View File

@ -40,6 +40,7 @@ func Start(conf common.Conf, dbO *sql.DB) *gin.Engine {
gv1.GET("/users/scores/best", Method(v1.UserScoresBestGET, common.PrivilegeRead)) gv1.GET("/users/scores/best", Method(v1.UserScoresBestGET, common.PrivilegeRead))
gv1.GET("/users/scores/recent", Method(v1.UserScoresRecentGET, common.PrivilegeRead)) gv1.GET("/users/scores/recent", Method(v1.UserScoresRecentGET, common.PrivilegeRead))
gv1.GET("/badges", Method(v1.BadgesGET, common.PrivilegeRead)) gv1.GET("/badges", Method(v1.BadgesGET, common.PrivilegeRead))
gv1.GET("/beatmaps", Method(v1.BeatmapGET, common.PrivilegeRead))
// ReadConfidential privilege required // ReadConfidential privilege required
gv1.GET("/friends", Method(v1.FriendsGET, common.PrivilegeReadConfidential)) gv1.GET("/friends", Method(v1.FriendsGET, common.PrivilegeReadConfidential))

View File

@ -1,20 +1,26 @@
package v1 package v1
import "git.zxq.co/ripple/rippleapi/common" import (
"database/sql"
"strconv"
"time"
"git.zxq.co/ripple/rippleapi/common"
)
type beatmap struct { type beatmap struct {
BeatmapID int `json:"beatmap_id"` BeatmapID int `json:"beatmap_id"`
BeatmapsetID int `json:"beatmapset_id"` BeatmapsetID int `json:"beatmapset_id"`
BeatmapMD5 string `json:"beatmap_md5"` BeatmapMD5 string `json:"beatmap_md5"`
SongName string `json:"song_name"` SongName string `json:"song_name"`
AR float32 `json:"ar"` AR float32 `json:"ar"`
OD float32 `json:"od"` OD float32 `json:"od"`
Difficulty float64 `json:"difficulty"` Difficulty float64 `json:"difficulty"`
MaxCombo int `json:"max_combo"` MaxCombo int `json:"max_combo"`
HitLength int `json:"hit_length"` HitLength int `json:"hit_length"`
Ranked int `json:"ranked"` Ranked int `json:"ranked"`
RankedStatusFrozen int `json:"ranked_status_frozen"` RankedStatusFrozen int `json:"ranked_status_frozen"`
LatestUpdate int `json:"latest_update"` LatestUpdate time.Time `json:"latest_update"`
} }
type beatmapMayOrMayNotExist struct { type beatmapMayOrMayNotExist struct {
@ -29,11 +35,11 @@ type beatmapMayOrMayNotExist struct {
HitLength *int HitLength *int
Ranked *int Ranked *int
RankedStatusFrozen *int RankedStatusFrozen *int
LatestUpdate *int LatestUpdate *time.Time
} }
func (b *beatmapMayOrMayNotExist) toBeatmap() *beatmap { func (b *beatmapMayOrMayNotExist) toBeatmap() *beatmap {
if b.BeatmapID == nil { if b == nil || b.BeatmapID == nil {
return nil return nil
} }
return &beatmap{ return &beatmap{
@ -62,7 +68,7 @@ type beatmapSetResponse struct {
} }
type beatmapSetStatusData struct { type beatmapSetStatusData struct {
BeatmapSetID int `json:"beatmapset_id"` BeatmapsetID int `json:"beatmapset_id"`
BeatmapID int `json:"beatmap_id"` BeatmapID int `json:"beatmap_id"`
RankedStatus int `json:"ranked_status"` RankedStatus int `json:"ranked_status"`
Frozen int `json:"frozen"` Frozen int `json:"frozen"`
@ -75,7 +81,7 @@ func BeatmapSetStatusPOST(md common.MethodData) common.CodeMessager {
md.RequestData.Unmarshal(&req) md.RequestData.Unmarshal(&req)
var miss []string var miss []string
if req.BeatmapSetID == 0 && req.BeatmapID == 0 { if req.BeatmapsetID == 0 && req.BeatmapID == 0 {
miss = append(miss, "beatmapset_id or beatmap_id") miss = append(miss, "beatmapset_id or beatmap_id")
} }
if len(miss) != 0 { if len(miss) != 0 {
@ -91,7 +97,7 @@ func BeatmapSetStatusPOST(md common.MethodData) common.CodeMessager {
var ( var (
whereClause = "beatmapset_id" whereClause = "beatmapset_id"
param = req.BeatmapSetID param = req.BeatmapsetID
) )
if req.BeatmapID != 0 { if req.BeatmapID != 0 {
whereClause = "beatmap_id" whereClause = "beatmap_id"
@ -102,8 +108,87 @@ func BeatmapSetStatusPOST(md common.MethodData) common.CodeMessager {
SET ranked = ?, ranked_status_freezed = ? SET ranked = ?, ranked_status_freezed = ?
WHERE `+whereClause+` = ?`, req.RankedStatus, req.Frozen, param) WHERE `+whereClause+` = ?`, req.RankedStatus, req.Frozen, param)
// TODO: replace with beatmapSetResponse when implemented if whereClause == "beatmapset_id" {
return common.ResponseBase{ return getSet(md, param)
Code: 200,
} }
return getBeatmap(md, param)
}
// BeatmapGET retrieves a beatmap.
func BeatmapGET(md common.MethodData) common.CodeMessager {
if md.C.Query("s") == "" && md.C.Query("b") == "" {
return common.SimpleResponse(400, "Must pass either querystring param 'b' or 's'")
}
setID, _ := strconv.Atoi(md.C.Query("s"))
if setID != 0 {
return getSet(md, setID)
}
beatmapID, _ := strconv.Atoi(md.C.Query("b"))
if beatmapID != 0 {
return getBeatmap(md, beatmapID)
}
return common.SimpleResponse(400, "Please pass either a valid beatmapset ID or a valid beatmap ID")
}
const baseBeatmapSelect = `
SELECT
beatmap_id, beatmapset_id, beatmap_md5,
song_name, ar, od, difficulty, max_combo,
hit_length, ranked, ranked_status_freezed,
latest_update
FROM beatmaps
`
func getSet(md common.MethodData, setID int) common.CodeMessager {
rows, err := md.DB.Query(baseBeatmapSelect+"WHERE beatmapset_id = ?", setID)
if err != nil {
md.Err(err)
return Err500
}
var r beatmapSetResponse
for rows.Next() {
var (
b beatmap
rawLatestUpdate int64
)
err = rows.Scan(
&b.BeatmapID, &b.BeatmapsetID, &b.BeatmapMD5,
&b.SongName, &b.AR, &b.OD, &b.Difficulty, &b.MaxCombo,
&b.HitLength, &b.Ranked, &b.RankedStatusFrozen,
&rawLatestUpdate,
)
if err != nil {
md.Err(err)
continue
}
b.LatestUpdate = time.Unix(rawLatestUpdate, 0)
r.Beatmaps = append(r.Beatmaps, b)
}
r.Code = 200
return r
}
func getBeatmap(md common.MethodData, beatmapID int) common.CodeMessager {
var (
b beatmap
rawLatestUpdate int64
)
err := md.DB.QueryRow(baseBeatmapSelect+"WHERE beatmap_id = ? LIMIT 1", beatmapID).Scan(
&b.BeatmapID, &b.BeatmapsetID, &b.BeatmapMD5,
&b.SongName, &b.AR, &b.OD, &b.Difficulty, &b.MaxCombo,
&b.HitLength, &b.Ranked, &b.RankedStatusFrozen,
&rawLatestUpdate,
)
switch {
case err == sql.ErrNoRows:
return common.SimpleResponse(404, "That beatmap could not be found!")
case err != nil:
md.Err(err)
return Err500
}
b.LatestUpdate = time.Unix(rawLatestUpdate, 0)
var r beatmapResponse
r.Code = 200
r.beatmap = b
return r
} }

View File

@ -128,9 +128,10 @@ func scoresPuts(md common.MethodData, whereClause string, params ...interface{})
var scores []userScore var scores []userScore
for rows.Next() { for rows.Next() {
var ( var (
us userScore us userScore
t string t string
b beatmapMayOrMayNotExist b beatmapMayOrMayNotExist
rawLatestUpdate *int64
) )
err = rows.Scan( err = rows.Scan(
&us.ID, &us.BeatmapMD5, &us.Score, &us.ID, &us.BeatmapMD5, &us.Score,
@ -143,7 +144,7 @@ func scoresPuts(md common.MethodData, whereClause string, params ...interface{})
&b.BeatmapID, &b.BeatmapsetID, &b.BeatmapMD5, &b.BeatmapID, &b.BeatmapsetID, &b.BeatmapMD5,
&b.SongName, &b.AR, &b.OD, &b.Difficulty, &b.SongName, &b.AR, &b.OD, &b.Difficulty,
&b.MaxCombo, &b.HitLength, &b.Ranked, &b.MaxCombo, &b.HitLength, &b.Ranked,
&b.RankedStatusFrozen, &b.LatestUpdate, &b.RankedStatusFrozen, &rawLatestUpdate,
) )
if err != nil { if err != nil {
md.Err(err) md.Err(err)
@ -155,6 +156,11 @@ func scoresPuts(md common.MethodData, whereClause string, params ...interface{})
md.Err(err) md.Err(err)
return Err500 return Err500
} }
if rawLatestUpdate != nil {
// fml i should have used an inner join
xd := time.Unix(*rawLatestUpdate, 0)
b.LatestUpdate = &xd
}
us.Beatmap = b.toBeatmap() us.Beatmap = b.toBeatmap()
scores = append(scores, us) scores = append(scores, us)
} }