Add beatmap rank requests
This commit is contained in:
parent
9e57fedd80
commit
26435c1195
|
@ -48,6 +48,7 @@ func initialCaretaker(c *gin.Context, f func(md common.MethodData) common.CodeMe
|
||||||
RequestData: data,
|
RequestData: data,
|
||||||
C: c,
|
C: c,
|
||||||
Doggo: doggo,
|
Doggo: doggo,
|
||||||
|
R: red,
|
||||||
}
|
}
|
||||||
if token != "" {
|
if token != "" {
|
||||||
tokenReal, exists := GetTokenFull(token, db)
|
tokenReal, exists := GetTokenFull(token, db)
|
||||||
|
|
11
app/start.go
11
app/start.go
|
@ -13,12 +13,14 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/serenize/snaker"
|
"github.com/serenize/snaker"
|
||||||
|
"gopkg.in/redis.v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
db *sqlx.DB
|
db *sqlx.DB
|
||||||
cf common.Conf
|
cf common.Conf
|
||||||
doggo *statsd.Client
|
doggo *statsd.Client
|
||||||
|
red *redis.Client
|
||||||
)
|
)
|
||||||
|
|
||||||
var commonClusterfucks = map[string]string{
|
var commonClusterfucks = map[string]string{
|
||||||
|
@ -65,6 +67,13 @@ func Start(conf common.Conf, dbO *sqlx.DB) *gin.Engine {
|
||||||
doggo.Incr("requests", nil, 1)
|
doggo.Incr("requests", nil, 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// redis
|
||||||
|
red = redis.NewClient(&redis.Options{
|
||||||
|
Addr: conf.RedisAddr,
|
||||||
|
Password: conf.RedisPassword,
|
||||||
|
DB: conf.RedisDB,
|
||||||
|
})
|
||||||
|
|
||||||
api := r.Group("/api")
|
api := r.Group("/api")
|
||||||
{
|
{
|
||||||
p := api.Group("/")
|
p := api.Group("/")
|
||||||
|
@ -119,7 +128,7 @@ func Start(conf common.Conf, dbO *sqlx.DB) *gin.Engine {
|
||||||
gv1.POST("/friends/del", Method(v1.FriendsDelPOST, common.PrivilegeWrite))
|
gv1.POST("/friends/del", Method(v1.FriendsDelPOST, common.PrivilegeWrite))
|
||||||
gv1.POST("/users/self/settings", Method(v1.UsersSelfSettingsPOST, common.PrivilegeWrite))
|
gv1.POST("/users/self/settings", Method(v1.UsersSelfSettingsPOST, common.PrivilegeWrite))
|
||||||
gv1.POST("/users/self/userpage", Method(v1.UserSelfUserpagePOST, common.PrivilegeWrite))
|
gv1.POST("/users/self/userpage", Method(v1.UserSelfUserpagePOST, common.PrivilegeWrite))
|
||||||
//gv1.POST("/beatmaps/rank_requests", Method(v1.BeatmapRankRequestsSubmitPOST, 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))
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"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"
|
"git.zxq.co/ripple/rippleapi/limit"
|
||||||
)
|
)
|
||||||
|
@ -106,26 +105,45 @@ func BeatmapRankRequestsSubmitPOST(md common.MethodData) common.CodeMessager {
|
||||||
return common.SimpleResponse(403, "It's not possible to do a rank request at this time.")
|
return common.SimpleResponse(403, "It's not possible to do a rank request at this time.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.SetID == 0 {
|
w := common.
|
||||||
d.SetID, err = beatmapget.Beatmap(d.ID)
|
Where("beatmap_id = ?", strconv.Itoa(d.ID)).Or().
|
||||||
} else {
|
Where("beatmapset_id = ?", strconv.Itoa(d.SetID))
|
||||||
err = beatmapget.Set(d.SetID)
|
|
||||||
|
var ranked int
|
||||||
|
err = md.DB.QueryRow("SELECT ranked FROM beatmaps "+w.Clause+" LIMIT 1", w.Params...).Scan(&ranked)
|
||||||
|
if ranked >= 2 {
|
||||||
|
return common.SimpleResponse(406, "That beatmap is already ranked.")
|
||||||
}
|
}
|
||||||
if err == beatmapget.ErrBeatmapNotFound {
|
|
||||||
return common.SimpleResponse(404, "That beatmap could not be found anywhere!")
|
switch err {
|
||||||
}
|
case nil:
|
||||||
if err != nil {
|
// move on
|
||||||
|
case sql.ErrNoRows:
|
||||||
|
if d.SetID != 0 {
|
||||||
|
md.R.Publish("ripple:beatmap_updates:sets", strconv.Itoa(d.SetID))
|
||||||
|
} else {
|
||||||
|
md.R.Publish("ripple:beatmap_updates:single", strconv.Itoa(d.ID))
|
||||||
|
}
|
||||||
|
default:
|
||||||
md.Err(err)
|
md.Err(err)
|
||||||
return Err500
|
return Err500
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// type and value of beatmap rank request
|
||||||
|
t := "b"
|
||||||
|
v := d.ID
|
||||||
|
if d.SetID != 0 {
|
||||||
|
t = "s"
|
||||||
|
v = d.SetID
|
||||||
|
}
|
||||||
err = md.DB.QueryRow("SELECT 1 FROM rank_requests WHERE bid = ? AND type = ? AND time > ?",
|
err = md.DB.QueryRow("SELECT 1 FROM rank_requests WHERE bid = ? AND type = ? AND time > ?",
|
||||||
d.SetID, "s", time.Now().Unix()).Scan(new(int))
|
v, t, time.Now().Add(-time.Hour*24).Unix()).Scan(new(int))
|
||||||
|
|
||||||
|
// error handling
|
||||||
switch err {
|
switch err {
|
||||||
case sql.ErrNoRows:
|
case sql.ErrNoRows:
|
||||||
break
|
break
|
||||||
case nil:
|
case nil:
|
||||||
// TODO: return beatmap
|
|
||||||
// we're returning a success because if the request was already sent in the past 24
|
// 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.
|
// hours, it's as if the user submitted it.
|
||||||
return common.SimpleResponse(200, "Your request has been submitted.")
|
return common.SimpleResponse(200, "Your request has been submitted.")
|
||||||
|
@ -136,12 +154,11 @@ func BeatmapRankRequestsSubmitPOST(md common.MethodData) common.CodeMessager {
|
||||||
|
|
||||||
_, err = md.DB.Exec(
|
_, err = md.DB.Exec(
|
||||||
"INSERT INTO rank_requests (userid, bid, type, time, blacklisted) VALUES (?, ?, ?, ?, 0)",
|
"INSERT INTO rank_requests (userid, bid, type, time, blacklisted) VALUES (?, ?, ?, ?, 0)",
|
||||||
md.ID(), d.SetID, "s", time.Now().Unix())
|
md.ID(), v, t, time.Now().Unix())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
md.Err(err)
|
md.Err(err)
|
||||||
return Err500
|
return Err500
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: return beatmap
|
|
||||||
return common.SimpleResponse(200, "Your request has been submitted.")
|
return common.SimpleResponse(200, "Your request has been submitted.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,9 @@ type Conf struct {
|
||||||
BeatmapRequestsPerUser int
|
BeatmapRequestsPerUser int
|
||||||
RankQueueSize int
|
RankQueueSize int
|
||||||
OsuAPIKey string
|
OsuAPIKey string
|
||||||
|
RedisAddr string
|
||||||
|
RedisPassword string
|
||||||
|
RedisDB int
|
||||||
}
|
}
|
||||||
|
|
||||||
var cachedConf *Conf
|
var cachedConf *Conf
|
||||||
|
@ -43,6 +46,7 @@ func Load() (c Conf, halt bool) {
|
||||||
HanayoKey: "Potato",
|
HanayoKey: "Potato",
|
||||||
BeatmapRequestsPerUser: 2,
|
BeatmapRequestsPerUser: 2,
|
||||||
RankQueueSize: 25,
|
RankQueueSize: 25,
|
||||||
|
RedisAddr: "localhost:6379",
|
||||||
}, "api.conf")
|
}, "api.conf")
|
||||||
fmt.Println("Please compile the configuration file (api.conf).")
|
fmt.Println("Please compile the configuration file (api.conf).")
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/DataDog/datadog-go/statsd"
|
"github.com/DataDog/datadog-go/statsd"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
|
"gopkg.in/redis.v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MethodData is a struct containing the data passed over to an API method.
|
// MethodData is a struct containing the data passed over to an API method.
|
||||||
|
@ -15,6 +16,7 @@ type MethodData struct {
|
||||||
RequestData RequestData
|
RequestData RequestData
|
||||||
C *gin.Context
|
C *gin.Context
|
||||||
Doggo *statsd.Client
|
Doggo *statsd.Client
|
||||||
|
R *redis.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// Err logs an error into gin.
|
// Err logs an error into gin.
|
||||||
|
|
|
@ -5,6 +5,7 @@ package common
|
||||||
type WhereClause struct {
|
type WhereClause struct {
|
||||||
Clause string
|
Clause string
|
||||||
Params []interface{}
|
Params []interface{}
|
||||||
|
useOr bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Where adds a new WHERE clause to the WhereClause.
|
// Where adds a new WHERE clause to the WhereClause.
|
||||||
|
@ -26,10 +27,26 @@ func (w *WhereClause) addWhere() {
|
||||||
if w.Clause == "" {
|
if w.Clause == "" {
|
||||||
w.Clause += "WHERE "
|
w.Clause += "WHERE "
|
||||||
} else {
|
} else {
|
||||||
|
if w.useOr {
|
||||||
|
w.Clause += " OR "
|
||||||
|
return
|
||||||
|
}
|
||||||
w.Clause += " AND "
|
w.Clause += " AND "
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Or enables using OR instead of AND
|
||||||
|
func (w *WhereClause) Or() *WhereClause {
|
||||||
|
w.useOr = true
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
// And enables using AND instead of OR
|
||||||
|
func (w *WhereClause) And() *WhereClause {
|
||||||
|
w.useOr = false
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
// In generates an IN clause.
|
// In generates an IN clause.
|
||||||
// initial is the initial part, e.g. "users.id".
|
// initial is the initial part, e.g. "users.id".
|
||||||
// Fields are the possible values.
|
// Fields are the possible values.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user