Implemented World of Warcraft - Game Data APIs - PvP Season API

This commit is contained in:
2025-03-20 23:34:58 -05:00
commit ccc8eb0da1
6 changed files with 278 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.env
*.json

91
battlenet/battlenet.go Normal file
View 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
View 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
View File

@@ -0,0 +1,5 @@
module battlenetapi
go 1.24.1
require github.com/joho/godotenv v1.5.1

2
go.sum Normal file
View 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=

View 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"`
}