Add Votifier 1 support, clean up code

This commit is contained in:
Jacob Gunther
2023-08-13 20:08:49 -05:00
parent 06da2df1b0
commit f7b9a06503
5 changed files with 135 additions and 104 deletions

2
go.mod
View File

@@ -5,7 +5,7 @@ go 1.19
require ( require (
github.com/go-redsync/redsync/v4 v4.8.1 github.com/go-redsync/redsync/v4 v4.8.1
github.com/gofiber/fiber/v2 v2.48.0 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 github.com/redis/go-redis/v9 v9.0.5
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )

2
go.sum
View File

@@ -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.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 h1:S7k/3xpvFjSmFKNZ6QW260q11HRaPSQCSMCEBqmV5X4=
github.com/mcstatus-io/mcutil v1.3.1/go.mod h1:VPWRCaYXfQheaTt4XJGYOGFzrp2E+B8g393SQiYO5mA= 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.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= 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= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=

View File

@@ -120,7 +120,18 @@ func SendVoteHandler(ctx *fiber.Ctx) error {
switch opts.Version { switch opts.Version {
case 1: 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: case 2:
{ {
if err = mcutil.SendVote(opts.Host, opts.Port, options.Vote{ if err = mcutil.SendVote(opts.Host, opts.Port, options.Vote{

View File

@@ -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 // 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 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 { if err = r.Set(fmt.Sprintf("bedrock:%s", cacheKey), data, conf.Cache.BedrockStatusDuration); err != nil {
return nil, 0, err 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. // 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. // FetchBedrockStatus fetches a fresh status of a Bedrock Edition server.
func FetchBedrockStatus(host string, port uint16) *BedrockStatusResponse { func FetchBedrockStatus(host string, port uint16) BedrockStatusResponse {
status, err := mcutil.StatusBedrock(host, port) status, _ := mcutil.StatusBedrock(host, port)
if err != nil { return BuildBedrockResponse(host, port, status)
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
} }
// BuildJavaResponse builds the response data from the status and query information. // 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 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
}

View File

@@ -29,12 +29,14 @@ var (
// VoteOptions is the options provided as query parameters to the vote route. // VoteOptions is the options provided as query parameters to the vote route.
type VoteOptions struct { type VoteOptions struct {
Version int Version int
IPAddress string
Host string Host string
Port uint16 Port uint16
ServiceName string ServiceName string
Username string Username string
UUID string UUID string
Token string Token string
PublicKey string
Timestamp time.Time Timestamp time.Time
} }
@@ -190,15 +192,29 @@ func ParseVoteOptions(ctx *fiber.Ctx) (*VoteOptions, error) {
// TODO check for properly formatted UUID // 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 // Token
{ {
result.Token = ctx.Query("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) return nil, fmt.Errorf("invalid 'token' query parameter: %s", result.Token)
} }
} }
// IP Address
{
result.IPAddress = ctx.Query("ip", ctx.IP())
}
// Timestamp // Timestamp
{ {
value := ctx.Query("timestamp") value := ctx.Query("timestamp")