Use shared code base

This commit is contained in:
Jacob Gunther
2022-08-30 20:56:54 -05:00
parent 02a843be5e
commit 4807a92b63
8 changed files with 32 additions and 630 deletions

9
go.mod
View File

@@ -3,9 +3,8 @@ module main
go 1.18 go 1.18
require ( require (
github.com/go-redis/redis/v8 v8.11.5 github.com/gofiber/fiber/v2 v2.37.0
github.com/gofiber/fiber/v2 v2.36.0 github.com/mcstatus-io/shared v0.0.0-20220831015146-c4896270e6f6
github.com/mcstatus-io/mcutil v0.0.0-20220829055335-c1c2ef192eca
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
@@ -13,9 +12,11 @@ require (
github.com/andybalholm/brotli v1.0.4 // indirect github.com/andybalholm/brotli v1.0.4 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/klauspost/compress v1.15.9 // indirect github.com/klauspost/compress v1.15.9 // indirect
github.com/mcstatus-io/mcutil v0.0.0-20220829055335-c1c2ef192eca // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.39.0 // indirect github.com/valyala/fasthttp v1.39.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect
golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24 // indirect golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect
) )

17
go.sum
View File

@@ -7,23 +7,20 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/gofiber/fiber/v2 v2.36.0 h1:1qLMe5rhXFLPa2SjK10Wz7WFgLwYi4TYg7XrjztJHqA= github.com/gofiber/fiber/v2 v2.37.0 h1:KVboSQ7e0wDbSFXNjXKqoigwp9HYUqgWn4uGFaUO1P8=
github.com/gofiber/fiber/v2 v2.36.0/go.mod h1:tgCr+lierLwLoVHHO/jn3Niannv34WRkQETU8wiL9fQ= github.com/gofiber/fiber/v2 v2.37.0/go.mod h1:xm3pDGlfE1xqVKb77iH8weLU0FFoTeWeK3nbiYM2Nh0=
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY= github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/mcstatus-io/mcutil v0.0.0-20220819164348-a0bb9bd8df56 h1:FZg8KfK/9b/Jp3BtZ3KgcS0iXkqPWn80cZrc6IUe1ps=
github.com/mcstatus-io/mcutil v0.0.0-20220819164348-a0bb9bd8df56/go.mod h1:VUB87/x9EYITmQVXZO4eS+egaZOdvxId4IdpU4L5LoA=
github.com/mcstatus-io/mcutil v0.0.0-20220825201801-d3b6a8b30b56 h1:XtoLxtSRzXYWnLxYfkq+oJTUg0i43dltU4LQxXtr7rk=
github.com/mcstatus-io/mcutil v0.0.0-20220825201801-d3b6a8b30b56/go.mod h1:VUB87/x9EYITmQVXZO4eS+egaZOdvxId4IdpU4L5LoA=
github.com/mcstatus-io/mcutil v0.0.0-20220829055335-c1c2ef192eca h1:7cuzxW+L7ZsnZfhW5pL2QpCRduTmURKnBFfwREF8of4= github.com/mcstatus-io/mcutil v0.0.0-20220829055335-c1c2ef192eca h1:7cuzxW+L7ZsnZfhW5pL2QpCRduTmURKnBFfwREF8of4=
github.com/mcstatus-io/mcutil v0.0.0-20220829055335-c1c2ef192eca/go.mod h1:VUB87/x9EYITmQVXZO4eS+egaZOdvxId4IdpU4L5LoA= github.com/mcstatus-io/mcutil v0.0.0-20220829055335-c1c2ef192eca/go.mod h1:VUB87/x9EYITmQVXZO4eS+egaZOdvxId4IdpU4L5LoA=
github.com/mcstatus-io/shared v0.0.0-20220831015146-c4896270e6f6 h1:vs4Gqv9mjXw369ap2mM7SN3u306n7u35x+nbeLpsoX0=
github.com/mcstatus-io/shared v0.0.0-20220831015146-c4896270e6f6/go.mod h1:0CPc1P/GzYKF3mS7CkRP3Mo/uOjU4fmZVkm0AF1c6D8=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.38.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
github.com/valyala/fasthttp v1.39.0 h1:lW8mGeM7yydOqZKmwyMTaz/PH/A+CLgtmmcjv+OORfU= github.com/valyala/fasthttp v1.39.0 h1:lW8mGeM7yydOqZKmwyMTaz/PH/A+CLgtmmcjv+OORfU=
github.com/valyala/fasthttp v1.39.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= github.com/valyala/fasthttp v1.39.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
@@ -37,10 +34,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 h1:Sx/u41w+OwrInGdEckYmEuU5gHoGSL4QbDz3S9s6j4U= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24 h1:TyKJRhyo17yWxOMCTHKWrc5rddHORMlnZ/j57umaUd8=
golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -8,6 +8,8 @@ import (
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors" "github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/recover" "github.com/gofiber/fiber/v2/middleware/recover"
"github.com/mcstatus-io/shared/redis"
"github.com/mcstatus-io/shared/util"
) )
var ( var (
@@ -19,9 +21,8 @@ var (
return ctx.SendStatus(http.StatusInternalServerError) return ctx.SendStatus(http.StatusInternalServerError)
}, },
}) })
r *Redis = &Redis{} r *redis.Redis = redis.New()
config *Config = &Config{} config *Config = &Config{}
blockedServers *MutexArray[string] = nil
) )
func init() { func init() {
@@ -29,13 +30,17 @@ func init() {
log.Fatal(err) log.Fatal(err)
} }
r.SetEnabled(config.Cache.Enable)
if config.Cache.Enable {
if err := r.Connect(config.Redis); err != nil { if err := r.Connect(config.Redis); err != nil {
log.Fatal(err) log.Fatal(err)
} }
log.Println("Successfully connected to Redis") log.Println("Successfully connected to Redis")
}
if err := GetBlockedServerList(); err != nil { if err := util.GetBlockedServerList(); err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@@ -1,170 +0,0 @@
package main
import (
"context"
"time"
"github.com/go-redis/redis/v8"
)
type Redis struct {
Client *redis.Client
}
func (r *Redis) Connect(uri string) error {
if !config.Cache.Enable {
return nil
}
opts, err := redis.ParseURL(uri)
if err != nil {
return err
}
r.Client = redis.NewClient(opts)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
return r.Client.Ping(ctx).Err()
}
func (r *Redis) GetCacheString(key string) (bool, string, time.Duration, error) {
exists, err := r.Exists(key)
if err != nil {
return false, "", 0, err
}
if !exists {
return false, "", 0, nil
}
value, err := r.GetString(key)
if err != nil {
return true, "", 0, err
}
ttl, err := r.TTL(key)
return true, value, ttl, err
}
func (r *Redis) GetCacheBytes(key string) (bool, []byte, time.Duration, error) {
exists, err := r.Exists(key)
if err != nil {
return false, nil, 0, err
}
if !exists {
return false, nil, 0, nil
}
value, err := r.GetBytes(key)
if err != nil {
return true, nil, 0, err
}
ttl, err := r.TTL(key)
return true, value, ttl, err
}
func (r *Redis) Exists(key string) (bool, error) {
if !config.Cache.Enable {
return false, nil
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
res := r.Client.Exists(ctx, key)
if err := res.Err(); err != nil {
return false, err
}
val, err := res.Result()
return val == 1, err
}
func (r *Redis) TTL(key string) (time.Duration, error) {
if !config.Cache.Enable {
return 0, nil
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
res := r.Client.TTL(ctx, key)
if err := res.Err(); err != nil {
return 0, err
}
return res.Result()
}
func (r *Redis) GetString(key string) (string, error) {
if !config.Cache.Enable {
return "", nil
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
res := r.Client.Get(ctx, key)
if err := res.Err(); err != nil {
return "", nil
}
return res.Result()
}
func (r *Redis) GetBytes(key string) ([]byte, error) {
if !config.Cache.Enable {
return nil, nil
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
res := r.Client.Get(ctx, key)
if err := res.Err(); err != nil {
return nil, err
}
return res.Bytes()
}
func (r *Redis) Set(key string, value interface{}, ttl time.Duration) error {
if !config.Cache.Enable {
return nil
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
return r.Client.Set(ctx, key, value, ttl).Err()
}
func (r *Redis) Close() error {
if !config.Cache.Enable {
return nil
}
return r.Client.Close()
}

View File

@@ -5,6 +5,8 @@ import (
"strconv" "strconv"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/mcstatus-io/shared/status"
"github.com/mcstatus-io/shared/util"
) )
func init() { func init() {
@@ -27,7 +29,7 @@ func JavaStatusHandler(ctx *fiber.Ctx) error {
return ctx.Status(http.StatusBadRequest).SendString("Invalid address value") return ctx.Status(http.StatusBadRequest).SendString("Invalid address value")
} }
response, expiresAt, err := GetJavaStatus(host, port) response, expiresAt, err := status.GetJavaStatus(r, host, port, config.Cache.JavaCacheDuration)
if err != nil { if err != nil {
return err return err
@@ -37,7 +39,7 @@ func JavaStatusHandler(ctx *fiber.Ctx) error {
ctx.Set("X-Cache-Time-Remaining", strconv.Itoa(int(expiresAt.Seconds()))) ctx.Set("X-Cache-Time-Remaining", strconv.Itoa(int(expiresAt.Seconds())))
} }
return ctx.Type("json").SendString(response) return ctx.JSON(response)
} }
func BedrockStatusHandler(ctx *fiber.Ctx) error { func BedrockStatusHandler(ctx *fiber.Ctx) error {
@@ -47,7 +49,7 @@ func BedrockStatusHandler(ctx *fiber.Ctx) error {
return ctx.Status(http.StatusBadRequest).SendString("Invalid address value") return ctx.Status(http.StatusBadRequest).SendString("Invalid address value")
} }
response, expiresAt, err := GetBedrockStatus(host, port) response, expiresAt, err := status.GetBedrockStatus(r, host, port, config.Cache.BedrockCacheDuration)
if err != nil { if err != nil {
return err return err
@@ -57,7 +59,7 @@ func BedrockStatusHandler(ctx *fiber.Ctx) error {
ctx.Set("X-Cache-Time-Remaining", strconv.Itoa(int(expiresAt.Seconds()))) ctx.Set("X-Cache-Time-Remaining", strconv.Itoa(int(expiresAt.Seconds())))
} }
return ctx.Type("json").SendString(response) return ctx.JSON(response)
} }
func IconHandler(ctx *fiber.Ctx) error { func IconHandler(ctx *fiber.Ctx) error {
@@ -67,7 +69,7 @@ func IconHandler(ctx *fiber.Ctx) error {
return ctx.Status(http.StatusBadRequest).SendString("Invalid address value") return ctx.Status(http.StatusBadRequest).SendString("Invalid address value")
} }
icon, expiresAt, err := GetServerIcon(host, port) icon, expiresAt, err := status.GetServerIcon(r, host, port, config.Cache.IconCacheDuration)
if err != nil { if err != nil {
return err return err
@@ -81,7 +83,7 @@ func IconHandler(ctx *fiber.Ctx) error {
} }
func DefaultIconHandler(ctx *fiber.Ctx) error { func DefaultIconHandler(ctx *fiber.Ctx) error {
return ctx.Type("png").Send(defaultIconBytes) return ctx.Type("png").Send(util.DefaultIconBytes)
} }
func NotFoundHandler(ctx *fiber.Ctx) error { func NotFoundHandler(ctx *fiber.Ctx) error {

View File

@@ -1,335 +0,0 @@
package main
import (
"encoding/base64"
"encoding/json"
"fmt"
"strings"
"time"
"github.com/mcstatus-io/mcutil"
)
type StatusResponse struct {
Online bool `json:"online"`
Host string `json:"host"`
Port uint16 `json:"port"`
EULABlocked bool `json:"eula_blocked"`
}
type JavaStatusResponse struct {
StatusResponse
Version *JavaVersion `json:"version"`
Players JavaPlayers `json:"players"`
MOTD MOTD `json:"motd"`
Icon *string `json:"icon"`
Mods []Mod `json:"mods"`
}
type BedrockStatusResponse struct {
StatusResponse
Version *BedrockVersion `json:"version"`
Players *BedrockPlayers `json:"players"`
MOTD *MOTD `json:"motd"`
Gamemode *string `json:"gamemode"`
ServerID *string `json:"server_id"`
Edition *string `json:"edition"`
}
type JavaVersion struct {
NameRaw string `json:"name_raw"`
NameClean string `json:"name_clean"`
NameHTML string `json:"name_html"`
Protocol int `json:"protocol"`
}
type BedrockVersion struct {
Name *string `json:"name"`
Protocol *int64 `json:"protocol"`
}
type JavaPlayers struct {
Online int `json:"online"`
Max int `json:"max"`
List []Player `json:"list"`
}
type BedrockPlayers struct {
Online *int64 `json:"online"`
Max *int64 `json:"max"`
}
type Player struct {
UUID string `json:"uuid"`
NameRaw string `json:"name_raw"`
NameClean string `json:"name_clean"`
NameHTML string `json:"name_html"`
}
type MOTD struct {
Raw string `json:"raw"`
Clean string `json:"clean"`
HTML string `json:"html"`
}
type Mod struct {
Name string `json:"name"`
Version string `json:"version"`
}
func GetJavaStatus(host string, port uint16) (string, *time.Duration, error) {
cacheKey := fmt.Sprintf("java:%s-%d", host, port)
exists, value, ttl, err := r.GetCacheString(cacheKey)
if exists {
return value, &ttl, err
}
response, err := json.Marshal(FetchJavaStatus(host, port))
if err != nil {
return "", nil, err
}
if err := r.Set(cacheKey, response, config.Cache.JavaCacheDuration); err != nil {
return "", nil, err
}
return string(response), nil, nil
}
func GetBedrockStatus(host string, port uint16) (string, *time.Duration, error) {
cacheKey := fmt.Sprintf("bedrock:%s-%d", host, port)
exists, value, ttl, err := r.GetCacheString(cacheKey)
if exists {
return value, &ttl, err
}
response, err := json.Marshal(FetchBedrockStatus(host, port))
if err != nil {
return "", nil, err
}
if err := r.Set(cacheKey, response, config.Cache.BedrockCacheDuration); err != nil {
return "", nil, err
}
return string(response), nil, nil
}
func GetServerIcon(host string, port uint16) ([]byte, *time.Duration, error) {
cacheKey := fmt.Sprintf("icon:%s-%d", host, port)
exists, value, ttl, err := r.GetCacheBytes(cacheKey)
if exists {
return value, &ttl, err
}
icon := defaultIconBytes
status, err := mcutil.Status(host, port)
if err == nil && status.Favicon != nil && strings.HasPrefix(*status.Favicon, "data:image/png;base64,") {
data, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(*status.Favicon, "data:image/png;base64,"))
if err != nil {
return nil, nil, err
}
icon = data
}
if err := r.Set(cacheKey, icon, config.Cache.IconCacheDuration); err != nil {
return nil, nil, err
}
return icon, nil, nil
}
func FetchJavaStatus(host string, port uint16) interface{} {
status, err := mcutil.Status(host, port)
if err != nil {
statusLegacy, err := mcutil.StatusLegacy(host, port)
if err != nil {
return StatusResponse{
Online: false,
Host: host,
Port: port,
EULABlocked: IsBlockedAddress(host),
}
}
response := JavaStatusResponse{
StatusResponse: StatusResponse{
Online: true,
Host: host,
Port: port,
EULABlocked: IsBlockedAddress(host),
},
Version: nil,
Players: JavaPlayers{
Online: statusLegacy.Players.Online,
Max: statusLegacy.Players.Max,
List: make([]Player, 0),
},
MOTD: MOTD{
Raw: statusLegacy.MOTD.Raw,
Clean: statusLegacy.MOTD.Clean,
HTML: statusLegacy.MOTD.HTML,
},
Icon: nil,
Mods: make([]Mod, 0),
}
if statusLegacy.Version != nil {
response.Version = &JavaVersion{
NameRaw: statusLegacy.Version.NameRaw,
NameClean: statusLegacy.Version.NameClean,
NameHTML: statusLegacy.Version.NameHTML,
Protocol: statusLegacy.Version.Protocol,
}
}
return response
}
playerList := make([]Player, 0)
if status.Players.Sample != nil {
for _, player := range status.Players.Sample {
playerList = append(playerList, Player{
UUID: player.ID,
NameRaw: player.NameRaw,
NameClean: player.NameClean,
NameHTML: player.NameHTML,
})
}
}
modList := make([]Mod, 0)
if status.ModInfo != nil {
for _, mod := range status.ModInfo.Mods {
modList = append(modList, Mod{
Name: mod.ID,
Version: mod.Version,
})
}
}
return JavaStatusResponse{
StatusResponse: StatusResponse{
Online: true,
Host: host,
Port: port,
EULABlocked: IsBlockedAddress(host),
},
Version: &JavaVersion{
NameRaw: status.Version.NameRaw,
NameClean: status.Version.NameClean,
NameHTML: status.Version.NameHTML,
Protocol: status.Version.Protocol,
},
Players: JavaPlayers{
Online: status.Players.Online,
Max: status.Players.Max,
List: playerList,
},
MOTD: MOTD{
Raw: status.MOTD.Raw,
Clean: status.MOTD.Clean,
HTML: status.MOTD.HTML,
},
Icon: status.Favicon,
Mods: modList,
}
}
func FetchBedrockStatus(host string, port uint16) interface{} {
status, err := mcutil.StatusBedrock(host, port)
if err != nil {
return StatusResponse{
Online: false,
Host: host,
Port: port,
EULABlocked: IsBlockedAddress(host),
}
}
response := BedrockStatusResponse{
StatusResponse: StatusResponse{
Online: true,
Host: host,
Port: port,
EULABlocked: IsBlockedAddress(host),
},
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
}

View File

@@ -1,91 +1,14 @@
package main package main
import ( import (
"crypto/sha1"
_ "embed" _ "embed"
"encoding/hex"
"fmt" "fmt"
"io"
"log" "log"
"net/http"
"os" "os"
"regexp"
"strconv" "strconv"
"strings" "strings"
"sync"
) )
var (
//go:embed icon.png
defaultIconBytes []byte
ipAddressRegExp = regexp.MustCompile(`^\d{1,3}(\.\d{1,3}){3}$`)
)
func GetBlockedServerList() error {
resp, err := http.Get("https://sessionserver.mojang.com/blockedservers")
if err != nil {
return err
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
blockedServers = &MutexArray[string]{
List: strings.Split(string(body), "\n"),
Mutex: &sync.Mutex{},
}
return nil
}
func IsBlockedAddress(address string) bool {
split := strings.Split(strings.ToLower(address), ".")
isIPAddress := ipAddressRegExp.MatchString(address)
for k := range split {
newAddress := ""
switch k {
case 0:
{
newAddress = strings.Join(split, ".")
break
}
default:
{
if isIPAddress {
newAddress = fmt.Sprintf("%s.*", strings.Join(split[0:len(split)-k], "."))
} else {
newAddress = fmt.Sprintf("*.%s", strings.Join(split[k:], "."))
}
break
}
}
newAddressBytes := sha1.Sum([]byte(newAddress))
newAddressHash := hex.EncodeToString(newAddressBytes[:])
if blockedServers.Has(newAddressHash) {
return true
}
}
return false
}
func ParseAddress(address string, defaultPort uint16) (string, uint16, error) { func ParseAddress(address string, defaultPort uint16) (string, uint16, error) {
result := strings.SplitN(address, ":", 2) result := strings.SplitN(address, ":", 2)
@@ -119,22 +42,3 @@ func GetInstanceID() (uint16, error) {
return 0, nil return 0, nil
} }
type MutexArray[K comparable] struct {
List []K
Mutex *sync.Mutex
}
func (m *MutexArray[K]) Has(value K) bool {
m.Mutex.Lock()
defer m.Mutex.Unlock()
for _, v := range m.List {
if v == value {
return true
}
}
return false
}