Code cleanup, only fetch stale blocked servers
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
bin/
|
bin/
|
||||||
config.yml
|
config.yml
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
blocked-servers.json
|
||||||
14
src/main.go
14
src/main.go
@@ -24,18 +24,20 @@ func init() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.Connect(config.Redis); err != nil {
|
r.SetEnabled(config.Cache.Enable)
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println("Successfully connected to Redis")
|
if config.Cache.Enable {
|
||||||
|
if err := r.Connect(config.Redis); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Successfully connected to Redis")
|
||||||
|
}
|
||||||
|
|
||||||
if err := GetBlockedServerList(); err != nil {
|
if err := GetBlockedServerList(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("Successfully retrieved EULA blocked servers")
|
|
||||||
|
|
||||||
if instanceID := os.Getenv("INSTANCE_ID"); len(instanceID) > 0 {
|
if instanceID := os.Getenv("INSTANCE_ID"); len(instanceID) > 0 {
|
||||||
value, err := strconv.ParseUint(instanceID, 10, 16)
|
value, err := strconv.ParseUint(instanceID, 10, 16)
|
||||||
|
|
||||||
|
|||||||
35
src/redis.go
35
src/redis.go
@@ -9,10 +9,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Redis struct {
|
type Redis struct {
|
||||||
Client *redis.Client
|
Enabled bool
|
||||||
|
Client *redis.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Redis) SetEnabled(value bool) {
|
||||||
|
r.Enabled = value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Redis) Connect(uri string) error {
|
func (r *Redis) Connect(uri string) error {
|
||||||
|
if !r.Enabled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
opts, err := redis.ParseURL(uri)
|
opts, err := redis.ParseURL(uri)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -29,6 +38,10 @@ func (r *Redis) Connect(uri string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Redis) Exists(key string) (bool, error) {
|
func (r *Redis) Exists(key string) (bool, error) {
|
||||||
|
if !r.Enabled {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -45,6 +58,10 @@ func (r *Redis) Exists(key string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Redis) GetString(key string) (string, error) {
|
func (r *Redis) GetString(key string) (string, error) {
|
||||||
|
if !r.Enabled {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -59,6 +76,10 @@ func (r *Redis) GetString(key string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Redis) GetBytes(key string) ([]byte, error) {
|
func (r *Redis) GetBytes(key string) ([]byte, error) {
|
||||||
|
if !r.Enabled {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -73,6 +94,10 @@ func (r *Redis) GetBytes(key string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Redis) Set(key string, value interface{}, ttl time.Duration) error {
|
func (r *Redis) Set(key string, value interface{}, ttl time.Duration) error {
|
||||||
|
if !r.Enabled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -81,6 +106,10 @@ func (r *Redis) Set(key string, value interface{}, ttl time.Duration) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Redis) SetJSON(key string, value interface{}, ttl time.Duration) error {
|
func (r *Redis) SetJSON(key string, value interface{}, ttl time.Duration) error {
|
||||||
|
if !r.Enabled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
data, err := json.Marshal(value)
|
data, err := json.Marshal(value)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -91,5 +120,9 @@ func (r *Redis) SetJSON(key string, value interface{}, ttl time.Duration) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Redis) Close() error {
|
func (r *Redis) Close() error {
|
||||||
|
if !r.Enabled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return r.Client.Close()
|
return r.Client.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
142
src/status.go
142
src/status.go
@@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/mcstatus-io/mcutil"
|
"github.com/mcstatus-io/mcutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StatusOffline struct {
|
type StatusResponse struct {
|
||||||
Online bool `json:"online"`
|
Online bool `json:"online"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Port uint16 `json:"port"`
|
Port uint16 `json:"port"`
|
||||||
@@ -16,28 +16,22 @@ type StatusOffline struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type JavaStatusResponse struct {
|
type JavaStatusResponse struct {
|
||||||
Online bool `json:"online"`
|
StatusResponse
|
||||||
Host string `json:"host"`
|
Version *JavaVersion `json:"version"`
|
||||||
Port uint16 `json:"port"`
|
Players JavaPlayers `json:"players"`
|
||||||
EULABlocked bool `json:"eula_blocked"`
|
MOTD MOTD `json:"motd"`
|
||||||
Version *JavaVersion `json:"version"`
|
Icon *string `json:"icon"`
|
||||||
Players JavaPlayers `json:"players"`
|
Mods []Mod `json:"mods"`
|
||||||
MOTD MOTD `json:"motd"`
|
|
||||||
Icon *string `json:"icon"`
|
|
||||||
Mods []Mod `json:"mods"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type BedrockStatusResponse struct {
|
type BedrockStatusResponse struct {
|
||||||
Online bool `json:"online"`
|
StatusResponse
|
||||||
Host string `json:"host"`
|
Version *BedrockVersion `json:"version"`
|
||||||
Port uint16 `json:"port"`
|
Players *BedrockPlayers `json:"players"`
|
||||||
EULABlocked bool `json:"eula_blocked"`
|
MOTD *MOTD `json:"motd"`
|
||||||
Version *BedrockVersion `json:"version"`
|
Gamemode *string `json:"gamemode"`
|
||||||
Players *BedrockPlayers `json:"players"`
|
ServerID *string `json:"server_id"`
|
||||||
MOTD *MOTD `json:"motd"`
|
Edition *string `json:"edition"`
|
||||||
Gamemode *string `json:"gamemode"`
|
|
||||||
ServerID *string `json:"server_id"`
|
|
||||||
Edition *string `json:"edition"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type JavaVersion struct {
|
type JavaVersion struct {
|
||||||
@@ -84,24 +78,20 @@ type Mod struct {
|
|||||||
func GetJavaStatus(host string, port uint16) (interface{}, error) {
|
func GetJavaStatus(host string, port uint16) (interface{}, error) {
|
||||||
cacheKey := fmt.Sprintf("java:%s-%d", host, port)
|
cacheKey := fmt.Sprintf("java:%s-%d", host, port)
|
||||||
|
|
||||||
if config.Cache.Enable {
|
cacheExists, err := r.Exists(cacheKey)
|
||||||
exists, err := r.Exists(cacheKey)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists {
|
if cacheExists {
|
||||||
return r.GetString(cacheKey)
|
return r.GetString(cacheKey)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response := FetchJavaStatus(host, port)
|
response := FetchJavaStatus(host, port)
|
||||||
|
|
||||||
if config.Cache.Enable {
|
if err := r.SetJSON(cacheKey, response, config.Cache.JavaCacheDuration); err != nil {
|
||||||
if err := r.SetJSON(cacheKey, response, config.Cache.JavaCacheDuration); err != nil {
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return response, nil
|
return response, nil
|
||||||
@@ -110,24 +100,20 @@ func GetJavaStatus(host string, port uint16) (interface{}, error) {
|
|||||||
func GetBedrockStatus(host string, port uint16) (interface{}, error) {
|
func GetBedrockStatus(host string, port uint16) (interface{}, error) {
|
||||||
cacheKey := fmt.Sprintf("bedrock:%s-%d", host, port)
|
cacheKey := fmt.Sprintf("bedrock:%s-%d", host, port)
|
||||||
|
|
||||||
if config.Cache.Enable {
|
cacheExists, err := r.Exists(cacheKey)
|
||||||
exists, err := r.Exists(cacheKey)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists {
|
if cacheExists {
|
||||||
return r.GetString(cacheKey)
|
return r.GetString(cacheKey)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response := FetchBedrockStatus(host, port)
|
response := FetchBedrockStatus(host, port)
|
||||||
|
|
||||||
if config.Cache.Enable {
|
if err := r.SetJSON(cacheKey, response, config.Cache.BedrockCacheDuration); err != nil {
|
||||||
if err := r.SetJSON(cacheKey, response, config.Cache.BedrockCacheDuration); err != nil {
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return response, nil
|
return response, nil
|
||||||
@@ -136,16 +122,14 @@ func GetBedrockStatus(host string, port uint16) (interface{}, error) {
|
|||||||
func GetServerIcon(host string, port uint16) ([]byte, error) {
|
func GetServerIcon(host string, port uint16) ([]byte, error) {
|
||||||
cacheKey := fmt.Sprintf("icon:%s-%d", host, port)
|
cacheKey := fmt.Sprintf("icon:%s-%d", host, port)
|
||||||
|
|
||||||
if config.Cache.Enable {
|
cacheExists, err := r.Exists(cacheKey)
|
||||||
exists, err := r.Exists(cacheKey)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if exists {
|
if cacheExists {
|
||||||
return r.GetBytes(cacheKey)
|
return r.GetBytes(cacheKey)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
icon := defaultIconBytes
|
icon := defaultIconBytes
|
||||||
@@ -162,10 +146,8 @@ func GetServerIcon(host string, port uint16) ([]byte, error) {
|
|||||||
icon = data
|
icon = data
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Cache.Enable {
|
if err := r.Set(cacheKey, icon, config.Cache.IconCacheDuration); err != nil {
|
||||||
if err := r.Set(cacheKey, icon, config.Cache.IconCacheDuration); err != nil {
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return icon, nil
|
return icon, nil
|
||||||
@@ -178,7 +160,7 @@ func FetchJavaStatus(host string, port uint16) interface{} {
|
|||||||
statusLegacy, err := mcutil.StatusLegacy(host, port)
|
statusLegacy, err := mcutil.StatusLegacy(host, port)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return StatusOffline{
|
return StatusResponse{
|
||||||
Online: false,
|
Online: false,
|
||||||
Host: host,
|
Host: host,
|
||||||
Port: port,
|
Port: port,
|
||||||
@@ -187,11 +169,13 @@ func FetchJavaStatus(host string, port uint16) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
response := JavaStatusResponse{
|
response := JavaStatusResponse{
|
||||||
Online: true,
|
StatusResponse: StatusResponse{
|
||||||
Host: host,
|
Online: true,
|
||||||
Port: port,
|
Host: host,
|
||||||
EULABlocked: IsBlockedAddress(host),
|
Port: port,
|
||||||
Version: nil,
|
EULABlocked: IsBlockedAddress(host),
|
||||||
|
},
|
||||||
|
Version: nil,
|
||||||
Players: JavaPlayers{
|
Players: JavaPlayers{
|
||||||
Online: statusLegacy.Players.Online,
|
Online: statusLegacy.Players.Online,
|
||||||
Max: statusLegacy.Players.Max,
|
Max: statusLegacy.Players.Max,
|
||||||
@@ -243,10 +227,12 @@ func FetchJavaStatus(host string, port uint16) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return JavaStatusResponse{
|
return JavaStatusResponse{
|
||||||
Online: true,
|
StatusResponse: StatusResponse{
|
||||||
Host: host,
|
Online: true,
|
||||||
Port: port,
|
Host: host,
|
||||||
EULABlocked: IsBlockedAddress(host),
|
Port: port,
|
||||||
|
EULABlocked: IsBlockedAddress(host),
|
||||||
|
},
|
||||||
Version: &JavaVersion{
|
Version: &JavaVersion{
|
||||||
NameRaw: status.Version.NameRaw,
|
NameRaw: status.Version.NameRaw,
|
||||||
NameClean: status.Version.NameClean,
|
NameClean: status.Version.NameClean,
|
||||||
@@ -272,7 +258,7 @@ func FetchBedrockStatus(host string, port uint16) interface{} {
|
|||||||
status, err := mcutil.StatusBedrock(host, port)
|
status, err := mcutil.StatusBedrock(host, port)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return StatusOffline{
|
return StatusResponse{
|
||||||
Online: false,
|
Online: false,
|
||||||
Host: host,
|
Host: host,
|
||||||
Port: port,
|
Port: port,
|
||||||
@@ -281,16 +267,18 @@ func FetchBedrockStatus(host string, port uint16) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
response := BedrockStatusResponse{
|
response := BedrockStatusResponse{
|
||||||
Online: true,
|
StatusResponse: StatusResponse{
|
||||||
Host: host,
|
Online: true,
|
||||||
Port: port,
|
Host: host,
|
||||||
EULABlocked: IsBlockedAddress(host),
|
Port: port,
|
||||||
Version: nil,
|
EULABlocked: IsBlockedAddress(host),
|
||||||
Players: nil,
|
},
|
||||||
MOTD: nil,
|
Version: nil,
|
||||||
Gamemode: status.Gamemode,
|
Players: nil,
|
||||||
ServerID: status.ServerID,
|
MOTD: nil,
|
||||||
Edition: status.Edition,
|
Gamemode: status.Gamemode,
|
||||||
|
ServerID: status.ServerID,
|
||||||
|
Edition: status.Edition,
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.Version != nil {
|
if status.Version != nil {
|
||||||
|
|||||||
65
src/util.go
65
src/util.go
@@ -4,20 +4,29 @@ import (
|
|||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
//go:embed icon.png
|
//go:embed icon.png
|
||||||
defaultIconBytes []byte
|
defaultIconBytes []byte
|
||||||
ipAddressRegExp = regexp.MustCompile("^\\d{1,3}(\\.\\d{1,3}){3}$")
|
ipAddressRegExp = regexp.MustCompile(`^\d{1,3}(\.\d{1,3}){3}$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type BlockedServersFile struct {
|
||||||
|
LastUpdated time.Time `json:"last_updated"`
|
||||||
|
Servers []string `json:"servers"`
|
||||||
|
}
|
||||||
|
|
||||||
func Contains[T comparable](arr []T, v T) bool {
|
func Contains[T comparable](arr []T, v T) bool {
|
||||||
for _, value := range arr {
|
for _, value := range arr {
|
||||||
if v == value {
|
if v == value {
|
||||||
@@ -29,6 +38,36 @@ func Contains[T comparable](arr []T, v T) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetBlockedServerList() error {
|
func GetBlockedServerList() error {
|
||||||
|
f, err := os.OpenFile("blocked-servers.json", os.O_CREATE|os.O_RDWR, 0777)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(f)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(data) > 0 {
|
||||||
|
var blockedServersFile BlockedServersFile
|
||||||
|
|
||||||
|
if err = json.Unmarshal(data, &blockedServersFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if time.Since(blockedServersFile.LastUpdated).Hours() < 24 {
|
||||||
|
blockedServersMutex.Lock()
|
||||||
|
blockedServers = blockedServersFile.Servers
|
||||||
|
blockedServersMutex.Unlock()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := http.Get("https://sessionserver.mojang.com/blockedservers")
|
resp, err := http.Get("https://sessionserver.mojang.com/blockedservers")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -39,6 +78,8 @@ func GetBlockedServerList() error {
|
|||||||
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Println("Successfully retrieved EULA blocked servers")
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
@@ -49,9 +90,27 @@ func GetBlockedServerList() error {
|
|||||||
|
|
||||||
blockedServersMutex.Lock()
|
blockedServersMutex.Lock()
|
||||||
blockedServers = strings.Split(string(body), "\n")
|
blockedServers = strings.Split(string(body), "\n")
|
||||||
blockedServersMutex.Unlock()
|
|
||||||
|
|
||||||
return nil
|
defer blockedServersMutex.Unlock()
|
||||||
|
|
||||||
|
if data, err = json.Marshal(BlockedServersFile{
|
||||||
|
LastUpdated: time.Now(),
|
||||||
|
Servers: blockedServers,
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = f.Truncate(0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = f.Seek(0, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = f.Write(data)
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsBlockedAddress(address string) bool {
|
func IsBlockedAddress(address string) bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user