Implemented World of Warcraft - Game Data APIs - PvP Season API
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.env
|
||||||
|
*.json
|
||||||
91
battlenet/battlenet.go
Normal file
91
battlenet/battlenet.go
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package battlenet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
STATIC string = "static"
|
||||||
|
DYNAMIC string = "dynamic"
|
||||||
|
PROFILE string = "profile"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
US string = "us"
|
||||||
|
EU string = "eu"
|
||||||
|
KR string = "kr"
|
||||||
|
TW string = "tw"
|
||||||
|
)
|
||||||
|
|
||||||
|
type clientCredentialsAPI struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
TokenType string `json:"token_type"`
|
||||||
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
Sub string `json:"sub"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BattleNetAPIParams struct {
|
||||||
|
UrlOrEndpoint string
|
||||||
|
Namespace string
|
||||||
|
Region string
|
||||||
|
Token string
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAccessToken(clientID string, clientSecret string) clientCredentialsAPI {
|
||||||
|
const authenticationUrl string = "https://oauth.battle.net/token"
|
||||||
|
resp, err := http.Post(authenticationUrl, "application/x-www-form-urlencoded", strings.NewReader(fmt.Sprintf("grant_type=client_credentials&client_id=%s&client_secret=%s", clientID, clientSecret)))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
fmt.Println(resp.Status)
|
||||||
|
panic("Failed to get access token")
|
||||||
|
}
|
||||||
|
var credentials clientCredentialsAPI
|
||||||
|
err = json.Unmarshal(respBody, &credentials)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
panic("Failed to parse access token response")
|
||||||
|
}
|
||||||
|
fmt.Println("Access Token: ", credentials.AccessToken)
|
||||||
|
return credentials
|
||||||
|
}
|
||||||
|
|
||||||
|
func BattleNetAPI(params BattleNetAPIParams) []byte {
|
||||||
|
var requestURL string
|
||||||
|
if strings.HasPrefix(params.UrlOrEndpoint, "http") {
|
||||||
|
requestURL = params.UrlOrEndpoint
|
||||||
|
} else {
|
||||||
|
var baseURL string = fmt.Sprintf("https://%s.api.blizzard.com", params.Region)
|
||||||
|
requestURL = fmt.Sprintf("%s%s?namespace=%s-%s", baseURL, params.UrlOrEndpoint, params.Namespace, params.Region)
|
||||||
|
}
|
||||||
|
fmt.Println(requestURL)
|
||||||
|
req, err := http.NewRequest("GET", requestURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", params.Token))
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
fmt.Println(resp.Status)
|
||||||
|
panic("Failed to process the request")
|
||||||
|
}
|
||||||
|
return (respBody)
|
||||||
|
}
|
||||||
52
example/main.go
Normal file
52
example/main.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"battlenetapi/battlenet"
|
||||||
|
"battlenetapi/wow/gamedata"
|
||||||
|
|
||||||
|
"github.com/joho/godotenv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Load the .env file
|
||||||
|
err := godotenv.Load(".env")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error loading .env file")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authenticate with the BattleNet API
|
||||||
|
clientID := os.Getenv("CLIENT_ID")
|
||||||
|
clientSecret := os.Getenv("CLIENT_SECRET")
|
||||||
|
credentials := battlenet.GetAccessToken(clientID, clientSecret)
|
||||||
|
|
||||||
|
// Get the current PVP season
|
||||||
|
params := battlenet.BattleNetAPIParams{
|
||||||
|
UrlOrEndpoint: gamedata.PvpSeasonIndexEndpoint,
|
||||||
|
Namespace: battlenet.DYNAMIC,
|
||||||
|
Region: battlenet.US,
|
||||||
|
Token: credentials.AccessToken,
|
||||||
|
}
|
||||||
|
response := battlenet.BattleNetAPI(params)
|
||||||
|
var pvpIndex gamedata.PvpSeasonIndexAPI
|
||||||
|
json.Unmarshal(response, &pvpIndex)
|
||||||
|
|
||||||
|
// Get the leaderboards for the current PVP season and Bracket
|
||||||
|
shuffleOrBlitz := fmt.Sprintf("blitz-%s", gamedata.ClassDemonHunterHavoc)
|
||||||
|
params.UrlOrEndpoint = fmt.Sprintf(gamedata.PvpLeaderboardEndpoint, pvpIndex.CurrentSeason.ID, shuffleOrBlitz)
|
||||||
|
response = battlenet.BattleNetAPI(params)
|
||||||
|
file, err := os.Create(fmt.Sprintf("pvp_season_%d_leaderboard-bracket_%s.json", pvpIndex.CurrentSeason.ID, shuffleOrBlitz))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error creating file:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
_, err = file.Write(response)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error writing data to file:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module battlenetapi
|
||||||
|
|
||||||
|
go 1.24.1
|
||||||
|
|
||||||
|
require github.com/joho/godotenv v1.5.1
|
||||||
2
go.sum
Normal file
2
go.sum
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
126
wow/gamedata/pvpseasonapi.go
Normal file
126
wow/gamedata/pvpseasonapi.go
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
package gamedata
|
||||||
|
|
||||||
|
const (
|
||||||
|
PvpSeasonIndexEndpoint string = "/data/wow/pvp-season/index"
|
||||||
|
PvpSeasonEndpoint string = "/data/wow/pvp-season/%d"
|
||||||
|
PvpLeaderboardIndexEndpoint string = "/data/wow/pvp-season/%d/pvp-leaderboard/index"
|
||||||
|
PvpLeaderboardEndpoint string = "/data/wow/pvp-season/%d/pvp-leaderboard/%s"
|
||||||
|
PvpRewardsIndexEndpoint string = "/data/wow/pvp-season/%d/pvp-reward/index"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Bracket2v2 string = "2v2"
|
||||||
|
Bracket3v3 string = "3v3"
|
||||||
|
BracketRBG string = "rbg"
|
||||||
|
ClassDeathKnightBlood string = "deathknight-blood"
|
||||||
|
ClassDeathKnightFrost string = "deathknight-frost"
|
||||||
|
ClassDeathKnightUnholy string = "deathknight-unholy"
|
||||||
|
ClassDemonHunterHavoc string = "demonhunter-havoc"
|
||||||
|
ClassDemonHunterVengeance string = "demonhunter-vengeance"
|
||||||
|
ClassDruidBalance string = "druid-balance"
|
||||||
|
ClassDruidFeral string = "druid-feral"
|
||||||
|
ClassDruidGuardian string = "druid-guardian"
|
||||||
|
ClassDruidRestoration string = "druid-restoration"
|
||||||
|
ClassEvokerAugmentation string = "evoker-augmentation"
|
||||||
|
ClassEvokerDevasation string = "evoker-devastation"
|
||||||
|
ClassEvokerPreservation string = "evoker-preservation"
|
||||||
|
ClassHunterBeastMastery string = "hunter-beastmastery"
|
||||||
|
ClassHunterMarksmanship string = "hunter-marksmanship"
|
||||||
|
ClassHunterSurvival string = "hunter-survival"
|
||||||
|
ClassMageArcane string = "mage-arcane"
|
||||||
|
ClassMageFire string = "mage-fire"
|
||||||
|
ClassMageFrost string = "mage-frost"
|
||||||
|
ClassMonkBrewmaster string = "monk-brewmaster"
|
||||||
|
ClassMonkMistweaver string = "monk-mistweaver"
|
||||||
|
ClassMonkWindwalker string = "monk-windwalker"
|
||||||
|
ClassPaladinHoly string = "paladin-holy"
|
||||||
|
ClassPaladinProtection string = "paladin-protection"
|
||||||
|
ClassPaladinRetribution string = "paladin-retribution"
|
||||||
|
ClassPriestDiscipline string = "priest-discipline"
|
||||||
|
ClassPriestHoly string = "priest-holy"
|
||||||
|
ClassPriestShadow string = "priest-shadow"
|
||||||
|
ClassRogueAssassination string = "rogue-assassination"
|
||||||
|
ClassRogueOutlaw string = "rogue-outlaw"
|
||||||
|
ClassRogueSubtlety string = "rogue-subtlety"
|
||||||
|
ClassShamanElemental string = "shaman-elemental"
|
||||||
|
ClassShamanEnhancement string = "shaman-enhancement"
|
||||||
|
ClassShamanRestoration string = "shaman-restoration"
|
||||||
|
ClassWarlockAffliction string = "warlock-affliction"
|
||||||
|
ClassWarlockDemonology string = "warlock-demonology"
|
||||||
|
ClassWarlockDestruction string = "warlock-destruction"
|
||||||
|
ClassWarriorArms string = "warrior-arms"
|
||||||
|
ClassWarriorFury string = "warrior-fury"
|
||||||
|
ClassWarriorProtection string = "warrior-protection"
|
||||||
|
)
|
||||||
|
|
||||||
|
type href struct {
|
||||||
|
Href string `json:"href"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type idAndKey struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Key href `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type idAndType struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PvpSeasonIndexAPI struct {
|
||||||
|
Seasons []idAndKey `json:"seasons"`
|
||||||
|
CurrentSeason idAndKey `json:"current_season"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PvpSeasonAPI struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Leaderboards href `json:"leaderboards"`
|
||||||
|
Rewards href `json:"rewards"`
|
||||||
|
SeasonStartTimestamp int `json:"season_start_timestamp"`
|
||||||
|
SeasonEndTimestamp int `json:"season_end_timestamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PvpLeaderboardAPI struct {
|
||||||
|
Season idAndKey `json:"season"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Bracket idAndType `json:"bracket"`
|
||||||
|
Entries []struct {
|
||||||
|
Character struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
ID int `json:"id"`
|
||||||
|
Realm struct {
|
||||||
|
Key href `json:"key"`
|
||||||
|
ID int `json:"id"`
|
||||||
|
Slug string `json:"slug"`
|
||||||
|
} `json:"realm"`
|
||||||
|
} `json:"character"`
|
||||||
|
Faction struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
} `json:"faction"`
|
||||||
|
Rank int `json:"rank"`
|
||||||
|
Rating int `json:"rating"`
|
||||||
|
SeasonMatchStatistics struct {
|
||||||
|
Played int `json:"played"`
|
||||||
|
Won int `json:"won"`
|
||||||
|
Lost int `json:"lost"`
|
||||||
|
} `json:"season_match_statistics"`
|
||||||
|
Tier idAndKey `json:"tier"`
|
||||||
|
} `json:"entries"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PvpRewardsIndexAPI struct {
|
||||||
|
Season idAndKey `json:"season"`
|
||||||
|
Rewards struct {
|
||||||
|
Bracket idAndType `json:"bracket"`
|
||||||
|
Achievement struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Key href `json:"key"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"achievement"`
|
||||||
|
RatingCutOff int `json:"rating_cutoff"`
|
||||||
|
Faction struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"faction"`
|
||||||
|
} `json:"rewards"`
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user