102 lines
2.3 KiB
Go
102 lines
2.3 KiB
Go
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")
|
|
}
|
|
}
|