Code improvements, move back from shared repo
This commit is contained in:
parent
5104fa754f
commit
65676c1683
@ -1,3 +1,4 @@
|
|||||||
|
environment: production
|
||||||
host: 127.0.0.1
|
host: 127.0.0.1
|
||||||
port: 3001
|
port: 3001
|
||||||
redis: redis://127.0.0.1:6379/0
|
redis: redis://127.0.0.1:6379/0
|
||||||
|
|||||||
15
go.mod
15
go.mod
@ -1,11 +1,11 @@
|
|||||||
module main
|
module main
|
||||||
|
|
||||||
go 1.18
|
go 1.19
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gofiber/fiber/v2 v2.37.0
|
github.com/go-redis/redis/v8 v8.11.5
|
||||||
|
github.com/gofiber/fiber/v2 v2.40.1
|
||||||
github.com/mcstatus-io/mcutil v0.0.0-20221217202354-00c1b98e931c
|
github.com/mcstatus-io/mcutil v0.0.0-20221217202354-00c1b98e931c
|
||||||
github.com/mcstatus-io/shared v1.0.4
|
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,10 +13,13 @@ 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/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||||
|
github.com/rivo/uniseg v0.2.0 // 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.41.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-20220829200755-d48e67d00261 // indirect
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
42
go.sum
42
go.sum
@ -7,47 +7,39 @@ 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.37.0 h1:KVboSQ7e0wDbSFXNjXKqoigwp9HYUqgWn4uGFaUO1P8=
|
github.com/gofiber/fiber/v2 v2.40.1 h1:pc7n9VVpGIqNsvg9IPLQhyFEMJL8gCs1kneH5D1pIl4=
|
||||||
github.com/gofiber/fiber/v2 v2.37.0/go.mod h1:xm3pDGlfE1xqVKb77iH8weLU0FFoTeWeK3nbiYM2Nh0=
|
github.com/gofiber/fiber/v2 v2.40.1/go.mod h1:Gko04sLksnHbzLSRBFWPFdzM9Ws9pRxvvIaohJK1dsk=
|
||||||
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-20220829055335-c1c2ef192eca h1:7cuzxW+L7ZsnZfhW5pL2QpCRduTmURKnBFfwREF8of4=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mcstatus-io/mcutil v0.0.0-20220829055335-c1c2ef192eca/go.mod h1:VUB87/x9EYITmQVXZO4eS+egaZOdvxId4IdpU4L5LoA=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||||
|
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/mcstatus-io/mcutil v0.0.0-20221217202354-00c1b98e931c h1:rsklIGzjSrY+V3WEEx8Mc6R9bQ1/v26tMr/fgoKo3tM=
|
github.com/mcstatus-io/mcutil v0.0.0-20221217202354-00c1b98e931c h1:rsklIGzjSrY+V3WEEx8Mc6R9bQ1/v26tMr/fgoKo3tM=
|
||||||
github.com/mcstatus-io/mcutil v0.0.0-20221217202354-00c1b98e931c/go.mod h1:VUB87/x9EYITmQVXZO4eS+egaZOdvxId4IdpU4L5LoA=
|
github.com/mcstatus-io/mcutil v0.0.0-20221217202354-00c1b98e931c/go.mod h1:VUB87/x9EYITmQVXZO4eS+egaZOdvxId4IdpU4L5LoA=
|
||||||
github.com/mcstatus-io/shared v0.0.0-20221023001202-042a64f3e9a8 h1:rELiwobCe1cWY6Plr3oArLYAPh41hZw1JvZz4h4Pvbw=
|
|
||||||
github.com/mcstatus-io/shared v0.0.0-20221023001202-042a64f3e9a8/go.mod h1:0CPc1P/GzYKF3mS7CkRP3Mo/uOjU4fmZVkm0AF1c6D8=
|
|
||||||
github.com/mcstatus-io/shared v0.0.0-20221217073539-81255189910f h1:ZroQAPCC/759RuKkyXvRa7yg+4QF9vMK68+bFabf+PA=
|
|
||||||
github.com/mcstatus-io/shared v0.0.0-20221217073539-81255189910f/go.mod h1:QnLKXHSdkVFWGpP4yu2rhlkxdRLW/SBQoR2qqi1lYRQ=
|
|
||||||
github.com/mcstatus-io/shared v0.0.0-20221217074644-8258241e8c44 h1:IE9w6dUXgr6aScK7P0Rt9jiX3ANz+g0c7ssAjCAp7/M=
|
|
||||||
github.com/mcstatus-io/shared v0.0.0-20221217074644-8258241e8c44/go.mod h1:QnLKXHSdkVFWGpP4yu2rhlkxdRLW/SBQoR2qqi1lYRQ=
|
|
||||||
github.com/mcstatus-io/shared v1.0.2 h1:GN4urv/n5QXuqC1q5OR+43QWb1JUhh1UP7dpEfLQL/c=
|
|
||||||
github.com/mcstatus-io/shared v1.0.2/go.mod h1:QnLKXHSdkVFWGpP4yu2rhlkxdRLW/SBQoR2qqi1lYRQ=
|
|
||||||
github.com/mcstatus-io/shared v1.0.3 h1:P90CtglbAli6sZLQqrYP7Zhr7bqJiiQOkntBM8q3wW4=
|
|
||||||
github.com/mcstatus-io/shared v1.0.3/go.mod h1:QnLKXHSdkVFWGpP4yu2rhlkxdRLW/SBQoR2qqi1lYRQ=
|
|
||||||
github.com/mcstatus-io/shared v1.0.4 h1:+bDerclkbl+d5qS5uakekrHn+RnmvBMwD0NY1O6+znY=
|
|
||||||
github.com/mcstatus-io/shared v1.0.4/go.mod h1:XuGB50gmf0XhdRCI4Lg09Z25rYKCNdlKSvr2/W7EK3o=
|
|
||||||
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/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
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.39.0 h1:lW8mGeM7yydOqZKmwyMTaz/PH/A+CLgtmmcjv+OORfU=
|
github.com/valyala/fasthttp v1.41.0 h1:zeR0Z1my1wDHTRiamBCXVglQdbUwgb9uWG3k1HQz6jY=
|
||||||
github.com/valyala/fasthttp v1.39.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
|
github.com/valyala/fasthttp v1.41.0/go.mod h1:f6VbjjoI3z1NDOZOv17o6RvtRSWxC77seBFc2uWtgiY=
|
||||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
|
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c h1:yKufUcDwucU5urd+50/Opbt4AYpqthk7wHpHok8f1lo=
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
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-20220728004956-3c1f35247d10/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-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
|
||||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/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=
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
Environment string `yaml:"environment"`
|
||||||
Host string `yaml:"host"`
|
Host string `yaml:"host"`
|
||||||
Port uint16 `yaml:"port"`
|
Port uint16 `yaml:"port"`
|
||||||
Redis string `yaml:"redis"`
|
Redis string `yaml:"redis"`
|
||||||
|
|||||||
BIN
src/icon.png
Normal file
BIN
src/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
24
src/main.go
24
src/main.go
@ -7,9 +7,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/logger"
|
||||||
"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 (
|
||||||
@ -21,7 +20,7 @@ var (
|
|||||||
return ctx.SendStatus(http.StatusInternalServerError)
|
return ctx.SendStatus(http.StatusInternalServerError)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
r *redis.Redis = redis.New()
|
r *Redis = &Redis{}
|
||||||
config *Config = &Config{}
|
config *Config = &Config{}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -38,7 +37,7 @@ func init() {
|
|||||||
log.Println("Successfully connected to Redis")
|
log.Println("Successfully connected to Redis")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := util.GetBlockedServerList(); err != nil {
|
if err := GetBlockedServerList(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,17 +49,18 @@ func init() {
|
|||||||
AllowMethods: "HEAD,OPTIONS,GET",
|
AllowMethods: "HEAD,OPTIONS,GET",
|
||||||
ExposeHeaders: "Content-Type,X-Cache-Time-Remaining",
|
ExposeHeaders: "Content-Type,X-Cache-Time-Remaining",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
if config.Environment == "development" {
|
||||||
|
app.Use(logger.New(logger.Config{
|
||||||
|
Format: "${time} ${ip}:${port} -> ${method} ${path} -> ${status}\n",
|
||||||
|
TimeFormat: "2006/01/02 15:04:05",
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
|
|
||||||
instanceID, err := GetInstanceID()
|
log.Printf("Listening on %s:%d\n", config.Host, config.Port)
|
||||||
|
log.Fatal(app.Listen(fmt.Sprintf("%s:%d", config.Host, config.Port)))
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Listening on %s:%d\n", config.Host, config.Port+instanceID)
|
|
||||||
log.Fatal(app.Listen(fmt.Sprintf("%s:%d", config.Host, config.Port+instanceID)))
|
|
||||||
}
|
}
|
||||||
|
|||||||
134
src/redis.go
Normal file
134
src/redis.go
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Redis struct {
|
||||||
|
Client *redis.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Redis) Connect(uri string) error {
|
||||||
|
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) Exists(key string) (bool, error) {
|
||||||
|
if r.Client == nil {
|
||||||
|
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 r.Client == nil {
|
||||||
|
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 r.Client == nil {
|
||||||
|
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 r.Client == nil {
|
||||||
|
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 r.Client == nil {
|
||||||
|
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) Increment(key string) error {
|
||||||
|
if r.Client == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
|
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
return r.Client.Incr(ctx, key).Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Redis) Close() error {
|
||||||
|
if r.Client == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Client.Close()
|
||||||
|
}
|
||||||
@ -9,8 +9,6 @@ import (
|
|||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/mcstatus-io/mcutil"
|
"github.com/mcstatus-io/mcutil"
|
||||||
"github.com/mcstatus-io/mcutil/options"
|
"github.com/mcstatus-io/mcutil/options"
|
||||||
"github.com/mcstatus-io/shared/status"
|
|
||||||
"github.com/mcstatus-io/shared/util"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SendVoteBody struct {
|
type SendVoteBody struct {
|
||||||
@ -50,7 +48,7 @@ func JavaStatusHandler(ctx *fiber.Ctx) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
response, expiresAt, err := status.GetJavaStatus(r, host, port, config.Cache.JavaCacheDuration)
|
response, expiresAt, err := GetJavaStatus(host, port)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -74,7 +72,7 @@ func BedrockStatusHandler(ctx *fiber.Ctx) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
response, expiresAt, err := status.GetBedrockStatus(r, host, port, config.Cache.BedrockCacheDuration)
|
response, expiresAt, err := GetBedrockStatus(host, port)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -94,7 +92,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 := status.GetServerIcon(r, host, port, config.Cache.IconCacheDuration)
|
icon, expiresAt, err := GetServerIcon(host, port)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -108,7 +106,7 @@ func IconHandler(ctx *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func DefaultIconHandler(ctx *fiber.Ctx) error {
|
func DefaultIconHandler(ctx *fiber.Ctx) error {
|
||||||
return ctx.Type("png").Send(util.DefaultIconBytes)
|
return ctx.Type("png").Send(defaultIconBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendVoteHandler(ctx *fiber.Ctx) error {
|
func SendVoteHandler(ctx *fiber.Ctx) error {
|
||||||
|
|||||||
417
src/status.go
Normal file
417
src/status.go
Normal file
@ -0,0 +1,417 @@
|
|||||||
|
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"`
|
||||||
|
RetrievedAt int64 `json:"retrieved_at"`
|
||||||
|
ExpiresAt int64 `json:"expires_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JavaStatusResponse struct {
|
||||||
|
StatusResponse
|
||||||
|
*JavaStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
type JavaStatus struct {
|
||||||
|
Version *JavaVersion `json:"version"`
|
||||||
|
Players JavaPlayers `json:"players"`
|
||||||
|
MOTD MOTD `json:"motd"`
|
||||||
|
Icon *string `json:"icon"`
|
||||||
|
Mods []Mod `json:"mods"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BedrockStatusResponse struct {
|
||||||
|
StatusResponse
|
||||||
|
*BedrockStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
type BedrockStatus struct {
|
||||||
|
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) (*JavaStatusResponse, *time.Duration, error) {
|
||||||
|
cacheKey := fmt.Sprintf("java:%s-%d", host, port)
|
||||||
|
|
||||||
|
exists, err := r.Exists(cacheKey)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
data, err := r.GetBytes(cacheKey)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var response JavaStatusResponse
|
||||||
|
|
||||||
|
if err = json.Unmarshal(data, &response); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ttl, err := r.TTL(cacheKey)
|
||||||
|
|
||||||
|
return &response, &ttl, err
|
||||||
|
}
|
||||||
|
|
||||||
|
response := FetchJavaStatus(host, port, config.Cache.JavaCacheDuration)
|
||||||
|
|
||||||
|
data, err := json.Marshal(response)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.Set(cacheKey, data, config.Cache.JavaCacheDuration); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBedrockStatus(host string, port uint16) (*BedrockStatusResponse, *time.Duration, error) {
|
||||||
|
cacheKey := fmt.Sprintf("bedrock:%s-%d", host, port)
|
||||||
|
|
||||||
|
exists, err := r.Exists(cacheKey)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
data, err := r.GetBytes(cacheKey)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var response BedrockStatusResponse
|
||||||
|
|
||||||
|
if err = json.Unmarshal(data, &response); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ttl, err := r.TTL(cacheKey)
|
||||||
|
|
||||||
|
return &response, &ttl, err
|
||||||
|
}
|
||||||
|
|
||||||
|
response := FetchBedrockStatus(host, port, config.Cache.BedrockCacheDuration)
|
||||||
|
|
||||||
|
data, err := json.Marshal(response)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.Set(cacheKey, data, config.Cache.BedrockCacheDuration); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetServerIcon(host string, port uint16) ([]byte, *time.Duration, error) {
|
||||||
|
cacheKey := fmt.Sprintf("icon:%s-%d", host, port)
|
||||||
|
|
||||||
|
exists, err := r.Exists(cacheKey)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
data, err := r.GetBytes(cacheKey)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ttl, err := r.TTL(cacheKey)
|
||||||
|
|
||||||
|
return data, &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, ttl time.Duration) *JavaStatusResponse {
|
||||||
|
status, err := mcutil.Status(host, port)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
statusLegacy, err := mcutil.StatusLegacy(host, port)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return &JavaStatusResponse{
|
||||||
|
StatusResponse: StatusResponse{
|
||||||
|
Online: false,
|
||||||
|
Host: host,
|
||||||
|
Port: port,
|
||||||
|
EULABlocked: IsBlockedAddress(host),
|
||||||
|
RetrievedAt: time.Now().UnixMilli(),
|
||||||
|
ExpiresAt: time.Now().Add(ttl).UnixMilli(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response := &JavaStatusResponse{
|
||||||
|
StatusResponse: StatusResponse{
|
||||||
|
Online: true,
|
||||||
|
Host: host,
|
||||||
|
Port: port,
|
||||||
|
EULABlocked: IsBlockedAddress(host),
|
||||||
|
RetrievedAt: time.Now().UnixMilli(),
|
||||||
|
ExpiresAt: time.Now().Add(ttl).UnixMilli(),
|
||||||
|
},
|
||||||
|
JavaStatus: &JavaStatus{
|
||||||
|
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),
|
||||||
|
RetrievedAt: time.Now().UnixMilli(),
|
||||||
|
ExpiresAt: time.Now().Add(ttl).UnixMilli(),
|
||||||
|
},
|
||||||
|
JavaStatus: &JavaStatus{
|
||||||
|
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, ttl time.Duration) *BedrockStatusResponse {
|
||||||
|
status, err := mcutil.StatusBedrock(host, port)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return &BedrockStatusResponse{
|
||||||
|
StatusResponse: StatusResponse{
|
||||||
|
Online: false,
|
||||||
|
Host: host,
|
||||||
|
Port: port,
|
||||||
|
EULABlocked: IsBlockedAddress(host),
|
||||||
|
RetrievedAt: time.Now().UnixMilli(),
|
||||||
|
ExpiresAt: time.Now().Add(ttl).UnixMilli(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response := &BedrockStatusResponse{
|
||||||
|
StatusResponse: StatusResponse{
|
||||||
|
Online: true,
|
||||||
|
Host: host,
|
||||||
|
Port: port,
|
||||||
|
EULABlocked: IsBlockedAddress(host),
|
||||||
|
RetrievedAt: time.Now().UnixMilli(),
|
||||||
|
ExpiresAt: time.Now().Add(ttl).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
|
||||||
|
}
|
||||||
113
src/util.go
113
src/util.go
@ -1,14 +1,109 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha1"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"io"
|
||||||
"os"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//go:embed icon.png
|
||||||
|
defaultIconBytes []byte
|
||||||
|
blockedServers *MutexArray[string] = nil
|
||||||
|
ipAddressRegExp *regexp.Regexp = regexp.MustCompile(`^\d{1,3}(\.\d{1,3}){3}$`)
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
@ -28,17 +123,3 @@ func ParseAddress(address string, defaultPort uint16) (string, uint16, error) {
|
|||||||
|
|
||||||
return result[0], uint16(port), nil
|
return result[0], uint16(port), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetInstanceID() (uint16, error) {
|
|
||||||
if instanceID := os.Getenv("INSTANCE_ID"); len(instanceID) > 0 {
|
|
||||||
value, err := strconv.ParseUint(instanceID, 10, 16)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return uint16(value), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user