rank requests stuff, temporarily disabled

This commit is contained in:
Howl 2016-09-20 18:14:02 +02:00
parent 42ff99bcc7
commit 3262bbea74
4 changed files with 122 additions and 15 deletions

View File

@ -101,6 +101,7 @@ func Start(conf common.Conf, dbO *sqlx.DB) *gin.Engine {
// Write privilege required // Write privilege required
gv1.GET("/friends/add", Method(v1.FriendsAddGET, common.PrivilegeWrite)) gv1.GET("/friends/add", Method(v1.FriendsAddGET, common.PrivilegeWrite))
gv1.GET("/friends/del", Method(v1.FriendsDelGET, common.PrivilegeWrite)) gv1.GET("/friends/del", Method(v1.FriendsDelGET, common.PrivilegeWrite))
//gv1.POST("/beatmaps/rank_requests", Method(v1.BeatmapRankRequestsSubmitPOST, common.PrivilegeWrite))
// Admin: beatmap // Admin: beatmap
gv1.POST("/beatmaps/set_status", Method(v1.BeatmapSetStatusPOST, common.PrivilegeBeatmap)) gv1.POST("/beatmaps/set_status", Method(v1.BeatmapSetStatusPOST, common.PrivilegeBeatmap))

View File

@ -1,19 +1,22 @@
package v1 package v1
import ( import (
"database/sql"
"strconv" "strconv"
"time" "time"
"git.zxq.co/ripple/rippleapi/beatmapget"
"git.zxq.co/ripple/rippleapi/common" "git.zxq.co/ripple/rippleapi/common"
"git.zxq.co/ripple/rippleapi/limit"
) )
type rankRequestsStatusResponse struct { type rankRequestsStatusResponse struct {
common.ResponseBase common.ResponseBase
QueueSize int `json:"queue_size"` QueueSize int `json:"queue_size"`
MaxPeruser int `json:"max_per_user"` MaxPerUser int `json:"max_per_user"`
Submitted int `json:"submitted"` Submitted int `json:"submitted"`
SubmittedByUser int `json:"submitted_by_user"` SubmittedByUser *int `json:"submitted_by_user,omitempty"`
CanSubmit bool `json:"can_submit"` CanSubmit *bool `json:"can_submit,omitempty"`
NextExpiration *time.Time `json:"next_expiration"` NextExpiration *time.Time `json:"next_expiration"`
} }
@ -26,6 +29,9 @@ func BeatmapRankRequestsStatusGET(md common.MethodData) common.CodeMessager {
return Err500 return Err500
} }
var r rankRequestsStatusResponse var r rankRequestsStatusResponse
if md.ID() != 0 {
r.SubmittedByUser = new(int)
}
isFirst := true isFirst := true
for rows.Next() { for rows.Next() {
var ( var (
@ -37,9 +43,13 @@ func BeatmapRankRequestsStatusGET(md common.MethodData) common.CodeMessager {
md.Err(err) md.Err(err)
continue continue
} }
// if the user submitted this rank request, increase the number of
// rank requests submitted by this user
if user == md.ID() { if user == md.ID() {
r.SubmittedByUser++ (*r.SubmittedByUser)++
} }
// also, if this is the first result, it means it will be the next to
// expire.
if isFirst { if isFirst {
x := time.Time(timestamp) x := time.Time(timestamp)
r.NextExpiration = &x r.NextExpiration = &x
@ -48,8 +58,87 @@ func BeatmapRankRequestsStatusGET(md common.MethodData) common.CodeMessager {
r.Submitted++ r.Submitted++
} }
r.QueueSize = c.RankQueueSize r.QueueSize = c.RankQueueSize
r.MaxPeruser = c.BeatmapRequestsPerUser r.MaxPerUser = c.BeatmapRequestsPerUser
r.CanSubmit = r.Submitted < r.QueueSize && r.SubmittedByUser < r.MaxPeruser if md.ID() != 0 {
x := r.Submitted < r.QueueSize && *r.SubmittedByUser < r.MaxPerUser
r.CanSubmit = &x
}
r.Code = 200 r.Code = 200
return r return r
} }
type submitRequestData struct {
ID int `json:"id"`
SetID int `json:"set_id"`
}
// BeatmapRankRequestsSubmitPOST submits a new beatmap for ranking approval.
func BeatmapRankRequestsSubmitPOST(md common.MethodData) common.CodeMessager {
var d submitRequestData
err := md.RequestData.Unmarshal(&d)
if err != nil {
return ErrBadJSON
}
// check json data is present
if d.ID == 0 && d.SetID == 0 {
return ErrMissingField("id|set_id")
}
// you've been rate limited
if !limit.NonBlockingRequest("rankrequest:u:"+strconv.Itoa(md.ID()), 5) {
return common.SimpleResponse(429, "You may only try to request 5 beatmaps per minute.")
}
if !limit.NonBlockingRequest("rankrequest:ip:"+md.C.ClientIP(), 8) {
return common.SimpleResponse(429, "You may only try to request 8 beatmaps per minute from the same IP.")
}
// find out from BeatmapRankRequestsStatusGET if we can submit beatmaps.
statusRaw := BeatmapRankRequestsStatusGET(md)
status, ok := statusRaw.(rankRequestsStatusResponse)
if !ok {
// if it's not a rankRequestsStatusResponse, it means it's an error
return statusRaw
}
if !*status.CanSubmit {
return common.SimpleResponse(403, "It's not possible to do a rank request at this time.")
}
if d.SetID == 0 {
d.SetID, err = beatmapget.Beatmap(d.ID)
} else {
err = beatmapget.Set(d.SetID)
}
if err == beatmapget.ErrBeatmapNotFound {
return common.SimpleResponse(404, "That beatmap could not be found anywhere!")
}
if err != nil {
md.Err(err)
return Err500
}
err = md.DB.QueryRow("SELECT 1 FROM rank_requests WHERE bid = ? AND type = ? AND time > ?",
d.SetID, "s", time.Now().Unix()).Scan(new(int))
switch err {
case sql.ErrNoRows:
break
case nil:
// TODO: return beatmap
// we're returning a success because if the request was already sent in the past 24
// hours, it's as if the user submitted it.
return common.SimpleResponse(200, "Your request has been submitted.")
default:
md.Err(err)
return Err500
}
_, err = md.DB.Exec(
"INSERT INTO rank_requests (userid, bid, type, time, blacklisted) VALUES (?, ?, ?, ?, 0)",
md.ID(), d.SetID, "s", time.Now().Unix())
if err != nil {
md.Err(err)
return Err500
}
// TODO: return beatmap
return common.SimpleResponse(200, "Your request has been submitted.")
}

View File

@ -119,8 +119,7 @@ func UpdateRequired(b *BeatmapDefiningQuality) (bool, error) {
expire *= 6 expire *= 6
} }
if expire != 0 && time.Now().After(time.Time(data.LatestUpdate).Add(expire)) && if expire != 0 && time.Now().After(time.Time(data.LatestUpdate).Add(expire)) && !data.Frozen {
!data.Frozen {
return true, nil return true, nil
} }
return false, nil return false, nil

View File

@ -1,6 +1,8 @@
package beatmapget package beatmapget
import ( import (
"database/sql"
"errors"
"time" "time"
"git.zxq.co/ripple/rippleapi/common" "git.zxq.co/ripple/rippleapi/common"
@ -13,28 +15,44 @@ func Set(s int) error {
lastUpdated common.UnixTimestamp lastUpdated common.UnixTimestamp
ranked int ranked int
) )
err := DB.QueryRow("SELECT last_updated, ranked FROM beatmaps WHERE beatmapset_id = ? LIMIT 1", s). err := DB.QueryRow("SELECT latest_update, ranked FROM beatmaps WHERE beatmapset_id = ? LIMIT 1", s).
Scan(&lastUpdated, &ranked) Scan(&lastUpdated, &ranked)
if err != nil { if err != nil && err != sql.ErrNoRows {
return err return err
} }
return set(s, lastUpdated, ranked) return set(s, lastUpdated, ranked)
} }
// ErrBeatmapNotFound is returned by Beatmap if a beatmap could not be found.
var ErrBeatmapNotFound = errors.New("beatmapget: beatmap not found")
// Beatmap check if an update is required for all beatmaps in the set // Beatmap check if an update is required for all beatmaps in the set
// containing this beatmap. // containing this beatmap.
func Beatmap(b int) error { func Beatmap(b int) (int, error) {
var ( var (
setID int setID int
lastUpdated common.UnixTimestamp lastUpdated common.UnixTimestamp
ranked int ranked int
) )
err := DB.QueryRow("SELECT beatmapset_id, last_updated, ranked FROM beatmaps WHERE beatmap_id = ? LIMIT 1", b). err := DB.QueryRow("SELECT beatmapset_id, latest_update, ranked FROM beatmaps WHERE beatmap_id = ? LIMIT 1", b).
Scan(&setID, &lastUpdated, &ranked) Scan(&setID, &lastUpdated, &ranked)
switch err {
case nil:
return setID, set(setID, lastUpdated, ranked)
case sql.ErrNoRows:
beatmaps, err := Client.GetBeatmaps(osuapi.GetBeatmapsOpts{
BeatmapID: b,
})
if err != nil { if err != nil {
return err return 0, err
}
if len(beatmaps) == 0 {
return 0, ErrBeatmapNotFound
}
return beatmaps[0].BeatmapSetID, set(beatmaps[0].BeatmapSetID, common.UnixTimestamp(time.Time{}), 0)
default:
return setID, err
} }
return set(setID, lastUpdated, ranked)
} }
func set(s int, updated common.UnixTimestamp, ranked int) error { func set(s int, updated common.UnixTimestamp, ranked int) error {