diff --git a/app/start.go b/app/start.go index cfd0a6e..a40d227 100644 --- a/app/start.go +++ b/app/start.go @@ -2,6 +2,7 @@ package app import ( "fmt" + "time" "github.com/DataDog/datadog-go/statsd" fhr "github.com/buaazp/fasthttprouter" @@ -67,6 +68,9 @@ func Start(conf common.Conf, dbO *sqlx.DB) *fhr.Router { // start websocket websockets.Start(red, db) + // start load achievements + go v1.LoadAchievementsEvery(db, time.Minute*10) + // peppyapi { r.Peppy("/api/get_user", peppy.GetUser) @@ -87,6 +91,7 @@ func Start(conf common.Conf, dbO *sqlx.DB) *fhr.Router { r.Method("/api/v1/users", v1.UsersGET) r.Method("/api/v1/users/whatid", v1.UserWhatsTheIDGET) r.Method("/api/v1/users/full", v1.UserFullGET) + r.Method("/api/v1/users/achievements", v1.UserAchievementsGET) r.Method("/api/v1/users/userpage", v1.UserUserpageGET) r.Method("/api/v1/users/lookup", v1.UserLookupGET) r.Method("/api/v1/users/scores/best", v1.UserScoresBestGET) diff --git a/app/v1/user_achievements.go b/app/v1/user_achievements.go new file mode 100644 index 0000000..6f7b1db --- /dev/null +++ b/app/v1/user_achievements.go @@ -0,0 +1,83 @@ +package v1 + +import ( + "database/sql" + "fmt" + "time" + + "github.com/jmoiron/sqlx" + "zxq.co/ripple/rippleapi/common" +) + +// Achievement represents an achievement in the database. +type Achievement struct { + ID int `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Icon string `json:"icon"` +} + +// LoadAchievementsEvery reloads the achievements in the database every given +// amount of time. +func LoadAchievementsEvery(db *sqlx.DB, d time.Duration) { + for { + err := db.Select(&achievs, + "SELECT id, name, description, icon FROM achievements ORDER BY id ASC") + if err != nil { + fmt.Println("LoadAchievements error", err) + common.GenericError(err) + } + time.Sleep(d) + } +} + +var achievs []Achievement + +type userAchievement struct { + Achievement + Achieved bool `json:"achieved"` +} + +type userAchievementsResponse struct { + common.ResponseBase + Achievements []userAchievement `json:"achievements"` +} + +// UserAchievementsGET handles requests for retrieving the achievements of a +// given user. +func UserAchievementsGET(md common.MethodData) common.CodeMessager { + shouldRet, whereClause, param := whereClauseUser(md, "users") + if shouldRet != nil { + return *shouldRet + } + var ids []int + err := md.DB.Select(&ids, `SELECT ua.achievement_id FROM users_achievements ua +INNER JOIN users ON users.id = ua.user_id +WHERE `+whereClause, param) + switch { + case err == sql.ErrNoRows: + return common.SimpleResponse(404, "No such user!") + case err != nil: + md.Err(err) + return Err500 + } + all := md.HasQuery("all") + resp := userAchievementsResponse{Achievements: make([]userAchievement, 0, len(achievs))} + for _, ach := range achievs { + achieved := inInt(ach.ID, ids) + if all || achieved { + resp.Achievements = append(resp.Achievements, userAchievement{ach, achieved}) + } + } + resp.Code = 200 + return resp +} + +func inInt(i int, js []int) bool { + for _, j := range js { + if i == j { + return true + } + } + return false +} diff --git a/common/method_data.go b/common/method_data.go index 6e0e171..edffb78 100644 --- a/common/method_data.go +++ b/common/method_data.go @@ -77,6 +77,11 @@ func WSErr(err error) { }, nil, nil) } +// GenericError is just an error. Can't make a good description. +func GenericError(err error) { + _err(err, nil, nil, nil) +} + func _err(err error, tags map[string]string, user *raven.User, c *fasthttp.RequestCtx) { if RavenClient == nil { fmt.Println("ERROR!!!!")