added rounds endpoint

This commit is contained in:
2021-10-17 17:44:57 +02:00
parent 4c23d49a22
commit f8579f9768
2 changed files with 89 additions and 30 deletions

102
main.go
View File

@@ -17,6 +17,7 @@ import (
"github.com/gorilla/handlers" "github.com/gorilla/handlers"
"github.com/gorilla/mux" "github.com/gorilla/mux"
_ "github.com/lib/pq" _ "github.com/lib/pq"
"github.com/markus-wa/demoinfocs-golang/v2/pkg/demoinfocs/common"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/wercker/journalhook" "github.com/wercker/journalhook"
@@ -409,6 +410,58 @@ func getMatchParse(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusAccepted) w.WriteHeader(http.StatusAccepted)
} }
func getMatchRounds(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", conf.Httpd.CORSAllowDomains)
id := mux.Vars(r)["id"]
if id == "" {
w.WriteHeader(http.StatusBadRequest)
return
}
matchId, err := strconv.ParseUint(id, 10, 64)
if err != nil {
log.Infof("[GMR] Error parsing matchID %s: %v", id, err)
w.WriteHeader(http.StatusBadRequest)
return
}
db.Lock.RLock()
tStats, err := db.Client.Stats.Query().Where(stats.HasMatchesWith(match.ID(matchId))).All(context.Background())
db.Lock.RUnlock()
if err != nil {
log.Infof("[GMR] match %d not found: %+v", matchId, err)
w.WriteHeader(http.StatusNotFound)
return
}
resp := map[uint]map[string][]uint{}
for _, stat := range tStats {
db.Lock.RLock()
tRoundStats, err := stat.QueryRoundStats().All(context.Background())
db.Lock.RUnlock()
if err != nil {
log.Warningf("[GMR] Unable to get RoundStats for player %d: %v", stat.PlayerStats, err)
continue
}
for _, rStat := range tRoundStats {
if _, ok := resp[rStat.Round]; !ok {
resp[rStat.Round] = map[string][]uint{}
}
resp[rStat.Round][strconv.FormatUint(stat.PlayerStats, 10)] = []uint{rStat.Equipment, rStat.Spent, rStat.Bank}
}
}
err = utils.SendJSON(resp, w)
if err != nil {
log.Errorf("[GMR] JSON: %+v", err)
w.WriteHeader(http.StatusInternalServerError)
}
}
func getMatchWeapons(w http.ResponseWriter, r *http.Request) { func getMatchWeapons(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", conf.Httpd.CORSAllowDomains) w.Header().Set("Access-Control-Allow-Origin", conf.Httpd.CORSAllowDomains)
id := mux.Vars(r)["id"] id := mux.Vars(r)["id"]
@@ -425,8 +478,6 @@ func getMatchWeapons(w http.ResponseWriter, r *http.Request) {
return return
} }
mResponse := make([]*utils.WeaponResponse, 0)
db.Lock.RLock() db.Lock.RLock()
tStats, err := db.Client.Stats.Query().Where(stats.HasMatchesWith(match.ID(matchId))).All(context.Background()) tStats, err := db.Client.Stats.Query().Where(stats.HasMatchesWith(match.ID(matchId))).All(context.Background())
db.Lock.RUnlock() db.Lock.RUnlock()
@@ -436,28 +487,39 @@ func getMatchWeapons(w http.ResponseWriter, r *http.Request) {
return return
} }
mResponse := struct {
EquipmentMap map[int]string `json:"equipment_map,omitempty"`
Stats []map[string]map[string][][]int `json:"stats,omitempty"`
}{
EquipmentMap: map[int]string{},
Stats: []map[string]map[string][][]int{},
}
for _, stat := range tStats { for _, stat := range tStats {
db.Lock.RLock() db.Lock.RLock()
mWs, err := stat.QueryWeaponStats().All(context.Background()) mWs, err := stat.QueryWeaponStats().All(context.Background())
db.Lock.RUnlock() db.Lock.RUnlock()
if err != nil { if err != nil {
log.Warningf("[GMW] Unbale to get WeaponStats for player %d: %v", stat.PlayerStats, err) log.Warningf("[GMW] Unable to get WeaponStats for player %d: %v", stat.PlayerStats, err)
continue continue
} }
mWr := &utils.WeaponResponse{ mWr := map[string]map[string][][]int{}
Player: &utils.PlayerResponse{SteamID64: stat.PlayerStats}, playerId := strconv.FormatUint(stat.PlayerStats, 10)
}
for _, wr := range mWs { for _, wr := range mWs {
mWr.Eq = append(mWr.Eq, &utils.EqResponse{ if _, exists := mWr[strconv.FormatUint(stat.PlayerStats, 10)]; !exists {
Victim: wr.Victim, mWr[playerId] = map[string][][]int{}
Type: wr.EqType, }
HitGroup: wr.HitGroup,
Dmg: wr.Dmg, victim := strconv.FormatUint(wr.Victim, 10)
}) mWr[playerId][victim] = append(mWr[playerId][victim], []int{wr.EqType, wr.HitGroup, int(wr.Dmg)})
if _, exist := mResponse.EquipmentMap[wr.EqType]; !exist {
mResponse.EquipmentMap[wr.EqType] = common.EquipmentType(wr.EqType).String()
}
} }
mResponse = append(mResponse, mWr) mResponse.Stats = append(mResponse.Stats, mWr)
} }
err = utils.SendJSON(mResponse, w) err = utils.SendJSON(mResponse, w)
@@ -478,7 +540,7 @@ func getMatch(w http.ResponseWriter, r *http.Request) {
matchId, err := strconv.ParseUint(id, 10, 64) matchId, err := strconv.ParseUint(id, 10, 64)
if err != nil { if err != nil {
log.Infof("[GM] Unbale to parse matchID %s: %v", id, err) log.Infof("[GM] Unable to parse matchID %s: %v", id, err)
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
return return
} }
@@ -601,9 +663,12 @@ func getMatch(w http.ResponseWriter, r *http.Request) {
} }
/* /*
/player/<id> GET player internal or if not found: steamAPI data + overall stats /player/<id> GET player details (last 10 matches)
/player/trackme POST id, authcode, [sharecode] /player/<id>/track POST Track player FORM_DATA: authcode, [sharecode]
/match/<id> GET CSGO-GC response + internal data if parsed <- may be big (ALL RELEVANT DATA) /player/<id>/track DELETE Stop tracking player FORM_DATA: authcode
/match/<id> GET details for match <id>
/match/<id>/weapons GET weapon-stats for match <id>
/match/<id>/rounds GET round-stats for match <id>
/match/parse/<sharecode> GET parses sharecode provided /match/parse/<sharecode> GET parses sharecode provided
*/ */
func main() { func main() {
@@ -685,7 +750,7 @@ func main() {
// start housekeeper // start housekeeper
go housekeeping() go housekeeping()
// Define routes // routes
router = mux.NewRouter().StrictSlash(true) router = mux.NewRouter().StrictSlash(true)
router.HandleFunc("/player/{id}", getPlayer).Methods(http.MethodGet, http.MethodOptions) router.HandleFunc("/player/{id}", getPlayer).Methods(http.MethodGet, http.MethodOptions)
router.HandleFunc("/player/{id}/track", postPlayerTrack).Methods(http.MethodPost, http.MethodOptions) router.HandleFunc("/player/{id}/track", postPlayerTrack).Methods(http.MethodPost, http.MethodOptions)
@@ -693,6 +758,7 @@ func main() {
router.HandleFunc("/match/parse/{sharecode}", getMatchParse).Methods(http.MethodGet, http.MethodOptions) router.HandleFunc("/match/parse/{sharecode}", getMatchParse).Methods(http.MethodGet, http.MethodOptions)
router.HandleFunc("/match/{id:[0-9]{19}}", getMatch).Methods(http.MethodGet, http.MethodOptions) router.HandleFunc("/match/{id:[0-9]{19}}", getMatch).Methods(http.MethodGet, http.MethodOptions)
router.HandleFunc("/match/{id:[0-9]{19}}/weapons", getMatchWeapons).Methods(http.MethodGet, http.MethodOptions) router.HandleFunc("/match/{id:[0-9]{19}}/weapons", getMatchWeapons).Methods(http.MethodGet, http.MethodOptions)
router.HandleFunc("/match/{id:[0-9]{19}}/rounds", getMatchRounds).Methods(http.MethodGet, http.MethodOptions)
router.Use(mux.CORSMethodMiddleware(router)) router.Use(mux.CORSMethodMiddleware(router))
loggedRouter := handlers.LoggingHandler(os.Stdout, router) loggedRouter := handlers.LoggingHandler(os.Stdout, router)
proxyRouter := handlers.ProxyHeaders(loggedRouter) proxyRouter := handlers.ProxyHeaders(loggedRouter)

View File

@@ -153,26 +153,19 @@ type StatsResponse struct {
type PlayerResponse struct { type PlayerResponse struct {
SteamID64 uint64 `json:"steamid64,string"` SteamID64 uint64 `json:"steamid64,string"`
Name string `json:"name"` Name string `json:"name,omitempty"`
Avatar string `json:"avatar"` Avatar string `json:"avatar,omitempty"`
VAC bool `json:"vac"` VAC bool `json:"vac"`
VACDate *time.Time `json:"vac_date,omitempty"` VACDate *time.Time `json:"vac_date,omitempty"`
Tracked bool `json:"tracked"` Tracked bool `json:"tracked"`
VanityURL string `json:"vanity_url,omitempty"` VanityURL string `json:"vanity_url,omitempty"`
MatchStats MatchStats `json:"match_stats,omitempty"` MatchStats *MatchStats `json:"match_stats,omitempty"`
Matches []*MatchResponse `json:"matches,omitempty"` Matches []*MatchResponse `json:"matches,omitempty"`
} }
type EqResponse struct {
Victim uint64 `json:"victim"`
Type int `json:"type"`
HitGroup int `json:"hit_group"`
Dmg uint `json:"dmg"`
}
type WeaponResponse struct { type WeaponResponse struct {
Player *PlayerResponse `json:"player"` Player *PlayerResponse `json:"player"`
Eq []*EqResponse `json:"eq,omitempty"` Eq map[string][][]int `json:"eq,omitempty"`
} }
type MatchResponse struct { type MatchResponse struct {