diff --git a/go.mod b/go.mod index df97507..22afc50 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( github.com/go-redsync/redsync/v4 v4.8.1 github.com/gofiber/fiber/v2 v2.48.0 - github.com/mcstatus-io/mcutil v1.3.1 + github.com/mcstatus-io/mcutil v1.4.0 github.com/redis/go-redis/v9 v9.0.5 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index 699d1f6..cf9be39 100644 --- a/go.sum +++ b/go.sum @@ -68,6 +68,8 @@ github.com/mcstatus-io/mcutil v1.3.0 h1:NjvwCQXPqBBuPKs5WLrfyg76y3lpNo/c1KwMWN2k github.com/mcstatus-io/mcutil v1.3.0/go.mod h1:VPWRCaYXfQheaTt4XJGYOGFzrp2E+B8g393SQiYO5mA= github.com/mcstatus-io/mcutil v1.3.1 h1:S7k/3xpvFjSmFKNZ6QW260q11HRaPSQCSMCEBqmV5X4= github.com/mcstatus-io/mcutil v1.3.1/go.mod h1:VPWRCaYXfQheaTt4XJGYOGFzrp2E+B8g393SQiYO5mA= +github.com/mcstatus-io/mcutil v1.4.0 h1:UpEaOm/PGIDcPFQqAXY14uhsgaclM3ZsEf6ojuAXZGE= +github.com/mcstatus-io/mcutil v1.4.0/go.mod h1:VPWRCaYXfQheaTt4XJGYOGFzrp2E+B8g393SQiYO5mA= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= diff --git a/src/routes.go b/src/routes.go index e2cd434..b9091a3 100644 --- a/src/routes.go +++ b/src/routes.go @@ -120,7 +120,18 @@ func SendVoteHandler(ctx *fiber.Ctx) error { switch opts.Version { case 1: - return ctx.Status(http.StatusNotImplemented).SendString("Votifier version 1 is currently not supported") + { + if err = mcutil.SendLegacyVote(opts.Host, opts.Port, options.LegacyVote{ + PublicKey: opts.PublicKey, + ServiceName: opts.ServiceName, + Username: opts.Username, + IPAddress: opts.IPAddress, + Timestamp: opts.Timestamp, + Timeout: time.Second * 5, + }); err != nil { + return ctx.Status(http.StatusBadRequest).SendString(err.Error()) + } + } case 2: { if err = mcutil.SendVote(opts.Host, opts.Port, options.Vote{ diff --git a/src/status.go b/src/status.go index 6f0ec0a..f241fdb 100644 --- a/src/status.go +++ b/src/status.go @@ -189,27 +189,22 @@ func GetBedrockStatus(host string, port uint16) (*BedrockStatusResponse, time.Du } } - var ( - err error = nil - response *BedrockStatusResponse = nil - data []byte = nil - ) - // Fetch a fresh status from the server itself { - response = FetchBedrockStatus(host, port) + response := FetchBedrockStatus(host, port) - if data, err = json.Marshal(response); err != nil { + data, err := json.Marshal(response) + + if err != nil { return nil, 0, err } - } - // Put the status into the cache for future requests - if err = r.Set(fmt.Sprintf("bedrock:%s", cacheKey), data, conf.Cache.BedrockStatusDuration); err != nil { - return nil, 0, err - } + if err = r.Set(fmt.Sprintf("bedrock:%s", cacheKey), data, conf.Cache.BedrockStatusDuration); err != nil { + return nil, 0, err + } - return response, 0, nil + return &response, 0, nil + } } // GetServerIcon returns the icon image of a Java Edition server, either using cache or fetching a fresh image. @@ -303,94 +298,10 @@ func FetchJavaStatus(host string, port uint16, enableQuery bool) JavaStatusRespo } // FetchBedrockStatus fetches a fresh status of a Bedrock Edition server. -func FetchBedrockStatus(host string, port uint16) *BedrockStatusResponse { - status, err := mcutil.StatusBedrock(host, port) +func FetchBedrockStatus(host string, port uint16) BedrockStatusResponse { + status, _ := mcutil.StatusBedrock(host, port) - if err != nil { - return &BedrockStatusResponse{ - BaseStatus: BaseStatus{ - Online: false, - Host: host, - Port: port, - EULABlocked: IsBlockedAddress(host), - RetrievedAt: time.Now().UnixMilli(), - ExpiresAt: time.Now().Add(conf.Cache.BedrockStatusDuration).UnixMilli(), - }, - } - } - - response := &BedrockStatusResponse{ - BaseStatus: BaseStatus{ - Online: true, - Host: host, - Port: port, - EULABlocked: IsBlockedAddress(host), - RetrievedAt: time.Now().UnixMilli(), - ExpiresAt: time.Now().Add(conf.Cache.BedrockStatusDuration).UnixMilli(), - }, - BedrockStatus: &BedrockStatus{ - Version: nil, - Players: nil, - MOTD: nil, - Gamemode: status.Gamemode, - ServerID: status.ServerID, - Edition: status.Edition, - }, - } - - if status.Version != nil { - if response.Version == nil { - response.Version = &BedrockVersion{ - Name: nil, - Protocol: nil, - } - } - - response.Version.Name = status.Version - } - - if status.ProtocolVersion != nil { - if response.Version == nil { - response.Version = &BedrockVersion{ - Name: nil, - Protocol: nil, - } - } - - response.Version.Protocol = status.ProtocolVersion - } - - if status.OnlinePlayers != nil { - if response.Players == nil { - response.Players = &BedrockPlayers{ - Online: nil, - Max: nil, - } - } - - response.Players.Online = status.OnlinePlayers - } - - if status.MaxPlayers != nil { - if response.Players == nil { - response.Players = &BedrockPlayers{ - Online: nil, - Max: nil, - } - } - - response.Players.Max = status.MaxPlayers - } - - if status.MOTD != nil { - response.MOTD = &MOTD{ - Raw: status.MOTD.Raw, - Clean: status.MOTD.Clean, - HTML: status.MOTD.HTML, - } - } - - return response + return BuildBedrockResponse(host, port, status) } // BuildJavaResponse builds the response data from the status and query information. @@ -580,3 +491,94 @@ func BuildJavaResponse(host string, port uint16, status interface{}, query *resp return } + +// BuildBedrockResponse builds the response data from the status information. +func BuildBedrockResponse(host string, port uint16, status interface{}) (result BedrockStatusResponse) { + result = BedrockStatusResponse{ + BaseStatus: BaseStatus{ + Online: true, + Host: host, + Port: port, + EULABlocked: IsBlockedAddress(host), + RetrievedAt: time.Now().UnixMilli(), + ExpiresAt: time.Now().Add(conf.Cache.BedrockStatusDuration).UnixMilli(), + }, + BedrockStatus: nil, + } + + if status == nil { + return + } + + switch s := status.(type) { + case *response.BedrockStatus: + { + result.BedrockStatus = &BedrockStatus{ + Version: nil, + Players: nil, + MOTD: nil, + Gamemode: s.Gamemode, + ServerID: s.ServerID, + Edition: s.Edition, + } + + if s.Version != nil { + if result.Version == nil { + result.Version = &BedrockVersion{ + Name: nil, + Protocol: nil, + } + } + + result.Version.Name = s.Version + } + + if s.ProtocolVersion != nil { + if result.Version == nil { + result.Version = &BedrockVersion{ + Name: nil, + Protocol: nil, + } + } + + result.Version.Protocol = s.ProtocolVersion + } + + if s.OnlinePlayers != nil { + if result.Players == nil { + result.Players = &BedrockPlayers{ + Online: nil, + Max: nil, + } + } + + result.Players.Online = s.OnlinePlayers + } + + if s.MaxPlayers != nil { + if result.Players == nil { + result.Players = &BedrockPlayers{ + Online: nil, + Max: nil, + } + } + + result.Players.Max = s.MaxPlayers + } + + if s.MOTD != nil { + result.MOTD = &MOTD{ + Raw: s.MOTD.Raw, + Clean: s.MOTD.Clean, + HTML: s.MOTD.HTML, + } + } + + break + } + default: + panic(fmt.Errorf("unknown status type: %T", status)) + } + + return +} diff --git a/src/util.go b/src/util.go index 7bf7eb3..f02ac23 100644 --- a/src/util.go +++ b/src/util.go @@ -29,12 +29,14 @@ var ( // VoteOptions is the options provided as query parameters to the vote route. type VoteOptions struct { Version int + IPAddress string Host string Port uint16 ServiceName string Username string UUID string Token string + PublicKey string Timestamp time.Time } @@ -190,15 +192,29 @@ func ParseVoteOptions(ctx *fiber.Ctx) (*VoteOptions, error) { // TODO check for properly formatted UUID } + // Public Key + { + result.PublicKey = ctx.Query("publickey") + + if result.Version == 1 && len(result.PublicKey) < 1 { + return nil, fmt.Errorf("invalid 'publickey' query parameter: %s", result.PublicKey) + } + } + // Token { result.Token = ctx.Query("token") - if len(result.Token) < 1 { + if result.Version == 2 && len(result.Token) < 1 { return nil, fmt.Errorf("invalid 'token' query parameter: %s", result.Token) } } + // IP Address + { + result.IPAddress = ctx.Query("ip", ctx.IP()) + } + // Timestamp { value := ctx.Query("timestamp")