Add beatmap rank requests
This commit is contained in:
		@@ -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().
 | 
				
			||||||
 | 
							Where("beatmapset_id = ?", strconv.Itoa(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.")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch err {
 | 
				
			||||||
 | 
						case nil:
 | 
				
			||||||
 | 
							// move on
 | 
				
			||||||
 | 
						case sql.ErrNoRows:
 | 
				
			||||||
 | 
							if d.SetID != 0 {
 | 
				
			||||||
 | 
								md.R.Publish("ripple:beatmap_updates:sets", strconv.Itoa(d.SetID))
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
		err = beatmapget.Set(d.SetID)
 | 
								md.R.Publish("ripple:beatmap_updates:single", strconv.Itoa(d.ID))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	if err == beatmapget.ErrBeatmapNotFound {
 | 
						default:
 | 
				
			||||||
		return common.SimpleResponse(404, "That beatmap could not be found anywhere!")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		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.
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user