hudly/mcplayer.go

102 lines
2.3 KiB
Go
Raw Normal View History

2024-10-16 18:45:19 -06:00
package main
import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"regexp"
)
type Property struct {
Name string `json:"name"`
Value string `json:"value"`
Signature string `json:"signature"`
}
type MCPlayer struct {
Username string
UUID string
AvatarURL string
SkinTexture string
Properties []Property
}
func isValidUUID(id string) bool {
r := regexp.MustCompile(`^[a-fA-F0-9]{32}$|^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$`)
return r.MatchString(id)
}
func isValidUsername(name string) bool {
r := regexp.MustCompile(`^[a-zA-Z0-9_]{3,16}$`)
return r.MatchString(name)
}
func fetchFromPlayerDB(id string) (*MCPlayer, error) {
url := fmt.Sprintf("https://playerdb.co/api/player/minecraft/%s", id)
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var result map[string]interface{}
err = json.Unmarshal(body, &result)
if err != nil {
return nil, err
}
if result["success"].(bool) == false {
return nil, fmt.Errorf("player not found (playerdb): %s", id)
}
data := result["data"].(map[string]interface{})
player := data["player"].(map[string]interface{})
properties := player["properties"].([]interface{})
mcPlayer := &MCPlayer{
Username: player["username"].(string),
UUID: player["id"].(string),
AvatarURL: player["avatar"].(string),
SkinTexture: player["skin_texture"].(string),
}
for _, p := range properties {
prop := p.(map[string]interface{})
mcPlayer.Properties = append(mcPlayer.Properties, Property{
Name: prop["name"].(string),
Value: prop["value"].(string),
Signature: prop["signature"].(string),
})
}
return mcPlayer, nil
}
func FetchMCPlayer(id string) (*MCPlayer, error) {
// TODO: Implement mojang API as the fallback
// TODO: Catch Nicks (propagate nick catcher through to HypixelAPI)
if isValidUUID(id) {
player, err := fetchFromPlayerDB(id)
if err != nil {
return nil, err
}
return player, nil
} else if isValidUsername(id) {
player, err := fetchFromPlayerDB(id)
if err != nil {
return nil, err
}
return player, nil
} else {
return nil, errors.New("invalid input: not a valid UUID or username")
}
}