From 2d1648f119a7b84beefa192fd7c043fa205b2cb4 Mon Sep 17 00:00:00 2001 From: Jacob Gunther Date: Fri, 24 Feb 2023 12:51:29 -0600 Subject: [PATCH] Move Yggdrasil methods to this repo --- go.mod | 1 - go.sum | 2 - src/util.go | 7 +-- src/yggdrasil.go | 139 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 src/yggdrasil.go diff --git a/go.mod b/go.mod index 7543c65..7cd6560 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/gofiber/fiber/v2 v2.40.1 github.com/joho/godotenv v1.4.0 github.com/mineatar-io/skin-render v1.0.1 - github.com/mineatar-io/yggdrasil v1.0.1 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index f62ba53..ed589f7 100644 --- a/go.sum +++ b/go.sum @@ -50,8 +50,6 @@ github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWV github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mineatar-io/skin-render v1.0.1 h1:ukZCagxGuaZM+E16h7XY+xGI+xlnI5R0EfEW0y+BIxs= github.com/mineatar-io/skin-render v1.0.1/go.mod h1:DkRV/kQmFokYp6n6KDcbSRA3EnEJnUW39GgTwPnYygQ= -github.com/mineatar-io/yggdrasil v1.0.1 h1:z9kBhmgSnbciS1Vf38Dy6MVbeUkNtKQsJARFXpb2eUQ= -github.com/mineatar-io/yggdrasil v1.0.1/go.mod h1:3WBd9LCY8AUy5rhftfp5hWGSE3VWfAIaSZS5rHROpJo= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= diff --git a/src/util.go b/src/util.go index f9e0ab7..8857b9d 100644 --- a/src/util.go +++ b/src/util.go @@ -14,7 +14,6 @@ import ( "github.com/gofiber/fiber/v2" "github.com/mineatar-io/skin-render" - "github.com/mineatar-io/yggdrasil" ) type QueryParams struct { @@ -47,7 +46,7 @@ func LookupUUID(value string) (string, bool, error) { return cache, true, nil } - profile, err := yggdrasil.UsernameToUUID(value) + profile, err := UsernameToUUID(value) if err != nil { return "", false, err @@ -113,7 +112,7 @@ func GetPlayerSkin(uuid string) (*image.NRGBA, bool, error) { return cache, slim, nil } - textures, err := yggdrasil.GetProfileTextures(uuid) + textures, err := GetProfileTextures(uuid) if err != nil { return nil, false, err @@ -141,7 +140,7 @@ func GetPlayerSkin(uuid string) (*image.NRGBA, bool, error) { return skin.GetDefaultSkin(slim), slim, nil } - texturesResult, err := yggdrasil.GetDecodedTexturesValue(value) + texturesResult, err := GetDecodedTexturesValue(value) if err != nil { return nil, false, err diff --git a/src/yggdrasil.go b/src/yggdrasil.go new file mode 100644 index 0000000..6e1a61e --- /dev/null +++ b/src/yggdrasil.go @@ -0,0 +1,139 @@ +package main + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" +) + +type MinecraftProfile struct { + Username string `json:"name"` + UUID string `json:"id"` +} + +type MinecraftProfileTextures struct { + UUID string `json:"id"` + Username string `json:"name"` + Legacy bool `json:"legacy"` + Properties []struct { + Name string `json:"name"` + Value string `json:"value"` + Signature string `json:"signature,omitempty"` + } `json:"properties"` +} + +type MinecraftDecodedTextures struct { + Timestamp int64 `json:"timestamp"` + UUID string `json:"uuid"` + Username string `json:"username"` + SignatureRequired bool `json:"signatureRequired"` + Textures struct { + Skin struct { + URL string `json:"url"` + Metadata struct { + Model string `json:"model"` + } `json:"metadata,omitempty"` + } `json:"SKIN,omitempty"` + Cape struct { + URL string `json:"url"` + } `json:"CAPE,omitempty"` + } `json:"textures"` +} + +func UsernameToUUID(username string) (*MinecraftProfile, error) { + req, err := http.NewRequest("GET", fmt.Sprintf("https://api.mojang.com/users/profiles/minecraft/%s", username), nil) + + if err != nil { + return nil, err + } + + req.Header.Set("User-Agent", "mineatar.io Skin Render API") + + resp, err := http.DefaultClient.Do(req) + + if err != nil { + return nil, err + } + + if resp.StatusCode != http.StatusOK { + if resp.StatusCode == http.StatusNoContent || resp.StatusCode == http.StatusNotFound { + return nil, nil + } + + return nil, fmt.Errorf("yggdrasil: unexpected response: %s", resp.Status) + } + + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + + if err != nil { + return nil, err + } + + response := &MinecraftProfile{} + + if err = json.Unmarshal(body, response); err != nil { + return nil, err + } + + return response, nil +} + +func GetProfileTextures(uuid string) (*MinecraftProfileTextures, error) { + req, err := http.NewRequest("GET", fmt.Sprintf("https://sessionserver.mojang.com/session/minecraft/profile/%s", uuid), nil) + + if err != nil { + return nil, err + } + + req.Header.Set("User-Agent", "mineatar.io Skin Render API") + + resp, err := http.DefaultClient.Do(req) + + if err != nil { + return nil, err + } + + if resp.StatusCode != 200 { + if resp.StatusCode == 204 { + return nil, nil + } + + return nil, fmt.Errorf("yggdrasil: unexpected response: %s", resp.Status) + } + + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + + if err != nil { + return nil, err + } + + response := &MinecraftProfileTextures{} + + if err = json.Unmarshal(body, response); err != nil { + return nil, err + } + + return response, nil +} + +func GetDecodedTexturesValue(value string) (*MinecraftDecodedTextures, error) { + rawResult, err := base64.StdEncoding.DecodeString(value) + + if err != nil { + return nil, err + } + + result := &MinecraftDecodedTextures{} + + if err = json.Unmarshal(rawResult, result); err != nil { + return nil, err + } + + return result, nil +}