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") } }