From b3312c1fcf39d7f52bd7c55107fbb37437843d13 Mon Sep 17 00:00:00 2001 From: Sch8ill Date: Mon, 8 Jan 2024 21:59:51 +0100 Subject: [PATCH] fix non standard UUIDs in slp response --- slp/response.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/slp/response.go b/slp/response.go index 70462a2..0fdfe18 100644 --- a/slp/response.go +++ b/slp/response.go @@ -5,9 +5,12 @@ import ( "encoding/json" "errors" "fmt" + "regexp" "strings" ) +const MaxUUIDLen int = 32 + // Response represents the Server List Ping (SLP) response. type Response struct { // Documentation link: @@ -47,6 +50,27 @@ type Player struct { ID string `json:"id"` } +// UnmarshalJSON unmarshalls a player into a Player. +// It ensures that the player is parsed successfully, even if the ID is not a string. +// Not all Minecraft servers respond with correct player IDs. +// For example 2b2t.org: {"name":"ยง6In-game: 326","id":[0,1,0,1]} +func (p *Player) UnmarshalJSON(b []byte) error { + var raw map[string]json.RawMessage + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + + if err := json.Unmarshal(raw["name"], &p.Name); err != nil { + return err + } + + if err := json.Unmarshal(raw["id"], &p.ID); err != nil { + p.ID = formatUUID(string(raw["id"])) + } + + return nil +} + // ForgeData represents Forge mod data in the SLP response. type ForgeData struct { Channels []ForgeChannel `json:"channels"` @@ -190,3 +214,20 @@ func (r *Response) Icon() ([]byte, error) { return iconBytes, nil } + +// formatMinecraftUUID formats the given string as a Minecraft UUID. +func formatUUID(input string) string { + // Remove non-hex characters + re := regexp.MustCompile("[^a-fA-F0-9]") + cleaned := re.ReplaceAllString(input, "") + + if len(cleaned) > 32 { + cleaned = cleaned[:32] + } + + for len(cleaned) < 32 { + cleaned = cleaned + "0" + } + + return cleaned[:8] + "-" + cleaned[8:12] + "-" + cleaned[12:16] + "-" + cleaned[16:20] + "-" + cleaned[20:] +}