diff options
| author | NeKz <NeKzor@users.noreply.github.com> | 2024-11-16 08:24:03 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-11-16 10:24:03 +0300 |
| commit | 5fb47b69d895fcbe98fc714b47057b0051387e05 (patch) | |
| tree | 0de4a1bd6a55d08c04f6153dc08a7e178aa71e52 /rankings/fetch.go | |
| parent | fix/frontend: broken youtube url (#231) (diff) | |
| download | lphub-5fb47b69d895fcbe98fc714b47057b0051387e05.tar.gz lphub-5fb47b69d895fcbe98fc714b47057b0051387e05.tar.bz2 lphub-5fb47b69d895fcbe98fc714b47057b0051387e05.zip | |
feat/rankings: fetch profiles faster and improvements (#234)v1.0.2
Diffstat (limited to 'rankings/fetch.go')
| -rw-r--r-- | rankings/fetch.go | 81 |
1 files changed, 61 insertions, 20 deletions
diff --git a/rankings/fetch.go b/rankings/fetch.go index ee5d5bb..cf04e81 100644 --- a/rankings/fetch.go +++ b/rankings/fetch.go | |||
| @@ -9,9 +9,10 @@ import ( | |||
| 9 | "net/http" | 9 | "net/http" |
| 10 | "os" | 10 | "os" |
| 11 | "strconv" | 11 | "strconv" |
| 12 | "strings" | ||
| 12 | ) | 13 | ) |
| 13 | 14 | ||
| 14 | func fetchLeaderboard(records *[]Record, overrides *map[string]map[string]int) *map[string]*Player { | 15 | func fetchLeaderboard(records []Record, overrides map[string]map[string]int, useCache bool) map[string]*Player { |
| 15 | log.Println("fetching leaderboard") | 16 | log.Println("fetching leaderboard") |
| 16 | players := map[string]*Player{} | 17 | players := map[string]*Player{} |
| 17 | // first init players map with records from portal gun and doors | 18 | // first init players map with records from portal gun and doors |
| @@ -20,8 +21,8 @@ func fetchLeaderboard(records *[]Record, overrides *map[string]map[string]int) * | |||
| 20 | end := 5000 | 21 | end := 5000 |
| 21 | 22 | ||
| 22 | for fetchAnotherPage { | 23 | for fetchAnotherPage { |
| 23 | portalGunEntries := fetchRecordsFromMap(47459, 0, 5000) | 24 | portalGunEntries := fetchRecordsFromMap(47459, 0, 5000, useCache) |
| 24 | fetchAnotherPage = portalGunEntries.needsAnotherPage(&(*records)[0]) | 25 | fetchAnotherPage = portalGunEntries.needsAnotherPage(&records[0]) |
| 25 | if fetchAnotherPage { | 26 | if fetchAnotherPage { |
| 26 | start = end + 1 | 27 | start = end + 1 |
| 27 | end = start + 5000 | 28 | end = start + 5000 |
| @@ -49,8 +50,8 @@ func fetchLeaderboard(records *[]Record, overrides *map[string]map[string]int) * | |||
| 49 | end = 5000 | 50 | end = 5000 |
| 50 | 51 | ||
| 51 | for fetchAnotherPage { | 52 | for fetchAnotherPage { |
| 52 | doorsEntries := fetchRecordsFromMap(47740, start, end) | 53 | doorsEntries := fetchRecordsFromMap(47740, start, end, useCache) |
| 53 | fetchAnotherPage = doorsEntries.needsAnotherPage(&(*records)[51]) | 54 | fetchAnotherPage = doorsEntries.needsAnotherPage(&records[51]) |
| 54 | if fetchAnotherPage { | 55 | if fetchAnotherPage { |
| 55 | start = end + 1 | 56 | start = end + 1 |
| 56 | end = start + 5000 | 57 | end = start + 5000 |
| @@ -83,7 +84,7 @@ func fetchLeaderboard(records *[]Record, overrides *map[string]map[string]int) * | |||
| 83 | } | 84 | } |
| 84 | } | 85 | } |
| 85 | 86 | ||
| 86 | for _, record := range *records { | 87 | for _, record := range records { |
| 87 | if record.MapID == 47459 || record.MapID == 47740 { | 88 | if record.MapID == 47459 || record.MapID == 47740 { |
| 88 | continue | 89 | continue |
| 89 | } | 90 | } |
| @@ -93,7 +94,7 @@ func fetchLeaderboard(records *[]Record, overrides *map[string]map[string]int) * | |||
| 93 | end := 5000 | 94 | end := 5000 |
| 94 | 95 | ||
| 95 | for fetchAnotherPage { | 96 | for fetchAnotherPage { |
| 96 | entries := fetchRecordsFromMap(record.MapID, start, end) | 97 | entries := fetchRecordsFromMap(record.MapID, start, end, useCache) |
| 97 | fetchAnotherPage = entries.needsAnotherPage(&record) | 98 | fetchAnotherPage = entries.needsAnotherPage(&record) |
| 98 | if fetchAnotherPage { | 99 | if fetchAnotherPage { |
| 99 | start = end + 1 | 100 | start = end + 1 |
| @@ -106,11 +107,11 @@ func fetchLeaderboard(records *[]Record, overrides *map[string]map[string]int) * | |||
| 106 | } | 107 | } |
| 107 | score := entry.Score | 108 | score := entry.Score |
| 108 | if entry.Score < record.MapWR { | 109 | if entry.Score < record.MapWR { |
| 109 | _, ok := (*overrides)[entry.SteamID] | 110 | _, ok := overrides[entry.SteamID] |
| 110 | if ok { | 111 | if ok { |
| 111 | _, ok := (*overrides)[entry.SteamID][strconv.Itoa(record.MapID)] | 112 | _, ok := overrides[entry.SteamID][strconv.Itoa(record.MapID)] |
| 112 | if ok { | 113 | if ok { |
| 113 | score = (*overrides)[entry.SteamID][strconv.Itoa(record.MapID)] | 114 | score = overrides[entry.SteamID][strconv.Itoa(record.MapID)] |
| 114 | } else { | 115 | } else { |
| 115 | continue // ban | 116 | continue // ban |
| 116 | } | 117 | } |
| @@ -136,28 +137,60 @@ func fetchLeaderboard(records *[]Record, overrides *map[string]map[string]int) * | |||
| 136 | } | 137 | } |
| 137 | 138 | ||
| 138 | } | 139 | } |
| 139 | return &players | 140 | return players |
| 140 | } | 141 | } |
| 141 | 142 | ||
| 142 | func fetchRecordsFromMap(mapID int, start int, end int) *Leaderboard { | 143 | func fetchRecordsFromMap(mapID int, start int, end int, useCache bool) *Leaderboard { |
| 143 | resp, err := http.Get(fmt.Sprintf("https://steamcommunity.com/stats/Portal2/leaderboards/%d?xml=1&start=%d&end=%d", mapID, start, end)) | 144 | var filename string |
| 145 | if useCache { | ||
| 146 | filename := fmt.Sprintf("./cache/lb_%d_%d_%d.xml", mapID, start, end) | ||
| 147 | log.Println("from cache", filename) | ||
| 148 | file, _ := os.ReadFile(filename) | ||
| 149 | if file != nil { | ||
| 150 | leaderboard := Leaderboard{} | ||
| 151 | err := xml.Unmarshal(file, &leaderboard) | ||
| 152 | if err != nil { | ||
| 153 | log.Fatalln("failed to unmarshal cache.", err.Error()) | ||
| 154 | } | ||
| 155 | return &leaderboard | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | url := fmt.Sprintf("https://steamcommunity.com/stats/Portal2/leaderboards/%d?xml=1&start=%d&end=%d", mapID, start, end) | ||
| 160 | resp, err := http.Get(url) | ||
| 161 | log.Println("fetched", url, ":", resp.StatusCode) | ||
| 144 | if err != nil { | 162 | if err != nil { |
| 145 | log.Fatalln(err.Error()) | 163 | log.Fatalln("failed to fetch leaderboard.", err.Error()) |
| 146 | } | 164 | } |
| 147 | respBytes, err := io.ReadAll(resp.Body) | 165 | respBytes, err := io.ReadAll(resp.Body) |
| 148 | if err != nil { | 166 | if err != nil { |
| 149 | log.Fatalln(err.Error()) | 167 | log.Fatalln("failed to read leadeboard body.", err.Error()) |
| 150 | } | 168 | } |
| 151 | leaderboard := Leaderboard{} | 169 | leaderboard := Leaderboard{} |
| 152 | err = xml.Unmarshal(respBytes, &leaderboard) | 170 | err = xml.Unmarshal(respBytes, &leaderboard) |
| 153 | if err != nil { | 171 | if err != nil { |
| 154 | log.Fatalln(err.Error()) | 172 | log.Println(string(respBytes)) |
| 173 | log.Fatalln("failed to unmarshal leaderboard.", err.Error()) | ||
| 155 | } | 174 | } |
| 175 | |||
| 176 | if useCache { | ||
| 177 | if err = os.WriteFile(filename, respBytes, 0644); err != nil { | ||
| 178 | log.Fatalln("failed write to file.", err.Error()) | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 156 | return &leaderboard | 182 | return &leaderboard |
| 157 | } | 183 | } |
| 158 | 184 | ||
| 159 | func fetchPlayerInfo(player *Player) { | 185 | func fetchPlayerInfo(players []*Player) { |
| 160 | url := fmt.Sprintf("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key=%s&steamids=%s", os.Getenv("API_KEY"), player.SteamID) | 186 | log.Println("fetching info for", len(players), "players") |
| 187 | |||
| 188 | ids := make([]string, len(players)) | ||
| 189 | for _, player := range players { | ||
| 190 | ids = append(ids, player.SteamID) | ||
| 191 | } | ||
| 192 | |||
| 193 | url := fmt.Sprintf("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key=%s&steamids=%s", os.Getenv("API_KEY"), strings.Join(ids, ",")) | ||
| 161 | resp, err := http.Get(url) | 194 | resp, err := http.Get(url) |
| 162 | if err != nil { | 195 | if err != nil { |
| 163 | log.Fatalln(err.Error()) | 196 | log.Fatalln(err.Error()) |
| @@ -167,6 +200,7 @@ func fetchPlayerInfo(player *Player) { | |||
| 167 | log.Fatalln(err.Error()) | 200 | log.Fatalln(err.Error()) |
| 168 | } | 201 | } |
| 169 | type PlayerSummary struct { | 202 | type PlayerSummary struct { |
| 203 | SteamID string `json:"steamid"` | ||
| 170 | PersonaName string `json:"personaname"` | 204 | PersonaName string `json:"personaname"` |
| 171 | AvatarFull string `json:"avatarfull"` | 205 | AvatarFull string `json:"avatarfull"` |
| 172 | } | 206 | } |
| @@ -180,6 +214,13 @@ func fetchPlayerInfo(player *Player) { | |||
| 180 | if err := json.Unmarshal(body, &data); err != nil { | 214 | if err := json.Unmarshal(body, &data); err != nil { |
| 181 | log.Fatalln(err.Error()) | 215 | log.Fatalln(err.Error()) |
| 182 | } | 216 | } |
| 183 | player.AvatarLink = data.Response.Players[0].AvatarFull | 217 | |
| 184 | player.Username = data.Response.Players[0].PersonaName | 218 | for _, profile := range data.Response.Players { |
| 219 | for _, player := range players { | ||
| 220 | if player.SteamID == profile.SteamID { | ||
| 221 | player.AvatarLink = profile.AvatarFull | ||
| 222 | player.Username = profile.PersonaName | ||
| 223 | } | ||
| 224 | } | ||
| 225 | } | ||
| 185 | } | 226 | } |