From dae1b36bfa188643d66e93d65b53f12a2e44f3f7 Mon Sep 17 00:00:00 2001 From: Jacob Gunther Date: Sun, 17 Mar 2024 23:17:38 -0500 Subject: [PATCH 1/7] Connect MongoDB and require authentication --- config.example.yml | 1 + go.mod | 10 +++ go.sum | 51 +++++++++++- src/config.go | 24 +++--- src/main.go | 16 +++- src/mongo.go | 198 +++++++++++++++++++++++++++++++++++++++++++++ src/routes.go | 15 ++-- src/util.go | 83 +++++++++++++++++++ 8 files changed, 376 insertions(+), 22 deletions(-) create mode 100644 src/mongo.go diff --git a/config.example.yml b/config.example.yml index 4b64841..55c8b95 100644 --- a/config.example.yml +++ b/config.example.yml @@ -1,6 +1,7 @@ environment: development host: 0.0.0.0 port: 3001 +mongodb: ${MONGO_URL} # Use an environment variable to define the Redis URL redis: ${REDIS_URL} # Use an environment variable to define the Redis URL cache: enable_locks: true diff --git a/go.mod b/go.mod index 03fbb0e..c207f63 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/gofiber/fiber/v2 v2.52.2 github.com/mcstatus-io/mcutil/v3 v3.3.0 github.com/redis/go-redis/v9 v9.5.1 + go.mongodb.org/mongo-driver v1.14.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -15,6 +16,7 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect + github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -22,9 +24,17 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/montanaflynn/stats v0.7.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.52.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.2 // indirect + github.com/xdg-go/stringprep v1.0.4 // indirect + github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/sync v0.6.0 // indirect golang.org/x/sys v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect ) diff --git a/go.sum b/go.sum index 067c5a3..8c4e815 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,7 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= @@ -14,7 +15,10 @@ github.com/go-redsync/redsync/v4 v4.12.1 h1:hCtdZ45DJxMxNdPiby5GlQwOKQmcka2587Y4 github.com/go-redsync/redsync/v4 v4.12.1/go.mod h1:sn72ojgeEhxUuRjrliK0NRrB0Zl6kOZ3BDvNN3P2jAY= github.com/gofiber/fiber/v2 v2.52.2 h1:b0rYH6b06Df+4NyrbdptQL8ifuxw/Tf2DgfkZkDaxEo= github.com/gofiber/fiber/v2 v2.52.2/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -33,6 +37,8 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mcstatus-io/mcutil/v3 v3.3.0 h1:FnI0hzmCtYGOlYARcdVTqNS+5iYqyo/t/U6YDpBmc8c= github.com/mcstatus-io/mcutil/v3 v3.3.0/go.mod h1:f1hgiUD3WoNmeZdN1AXYASSEO7yPxVEsLCGXnPkK6p4= +github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= +github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/redis/rueidis v1.0.19 h1:s65oWtotzlIFN8eMPhyYwxlwLR1lUdhza2KtWprKYSo= @@ -46,11 +52,54 @@ github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7g github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= +github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= +github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= +github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= +go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/src/config.go b/src/config.go index 8eda8f7..4c208e7 100644 --- a/src/config.go +++ b/src/config.go @@ -15,6 +15,7 @@ var ( Environment: "production", Host: "127.0.0.1", Port: 3001, + MongoDB: nil, Redis: nil, Cache: ConfigCache{ EnableLocks: true, @@ -22,18 +23,17 @@ var ( BedrockStatusDuration: time.Minute, IconDuration: time.Minute * 15, }, - AccessControl: ConfigAccessControl{}, } ) // Config represents the application configuration. type Config struct { - Environment string `yaml:"environment"` - Host string `yaml:"host"` - Port uint16 `yaml:"port"` - Redis *string `yaml:"redis"` - Cache ConfigCache `yaml:"cache"` - AccessControl ConfigAccessControl `yaml:"access_control"` + Environment string `yaml:"environment"` + Host string `yaml:"host"` + Port uint16 `yaml:"port"` + MongoDB *string `yaml:"mongodb"` + Redis *string `yaml:"redis"` + Cache ConfigCache `yaml:"cache"` } // ConfigCache represents the caching durations of various responses. @@ -44,12 +44,6 @@ type ConfigCache struct { IconDuration time.Duration `yaml:"icon_duration"` } -// ConfigAccessControl is the configuration for the CORS headers -type ConfigAccessControl struct { - Enable bool `yaml:"enable"` - AllowedOrigins []string `yaml:"allowed_origins"` -} - // ReadFile reads the configuration from the given file and overrides values using environment variables. func (c *Config) ReadFile(file string) error { data, err := os.ReadFile(file) @@ -99,5 +93,9 @@ func (c *Config) overrideWithEnvVars() error { c.Redis = &value } + if value := os.Getenv("MONGO_URL"); value != "" { + c.MongoDB = &value + } + return nil } diff --git a/src/main.go b/src/main.go index b3b055d..22cbf7e 100644 --- a/src/main.go +++ b/src/main.go @@ -25,9 +25,10 @@ var ( return ctx.SendStatus(http.StatusInternalServerError) }, }) - r *Redis = &Redis{} - config *Config = DefaultConfig - instanceID uint16 = 0 + r *Redis = &Redis{} + db *MongoDB = &MongoDB{} + config *Config = DefaultConfig + instanceID uint16 = 0 ) func init() { @@ -51,6 +52,14 @@ func init() { log.Println("Successfully retrieved EULA blocked servers") + if config.MongoDB != nil { + if err = db.Connect(); err != nil { + log.Fatalf("Failed to connect to MongoDB: %v", err) + } + + log.Println("Successfully connected to MongoDB") + } + if config.Redis != nil { if err = r.Connect(); err != nil { log.Fatalf("Failed to connect to Redis: %v", err) @@ -72,6 +81,7 @@ func init() { func main() { defer r.Close() + defer db.Close() if err := app.Listen(fmt.Sprintf("%s:%d", config.Host, config.Port+instanceID)); err != nil { panic(err) diff --git a/src/mongo.go b/src/mongo.go new file mode 100644 index 0000000..020e149 --- /dev/null +++ b/src/mongo.go @@ -0,0 +1,198 @@ +package main + +import ( + "context" + "errors" + "net/url" + "strings" + "time" + + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" +) + +var ( + CollectionApplications string = "applications" + CollectionTokens string = "tokens" + CollectionRequestLog string = "request_log" + + ErrMongoNotConnected error = errors.New("cannot use method as MongoDB is not connected") +) + +type MongoDB struct { + Client *mongo.Client + Database *mongo.Database +} + +type Application struct { + ID string `bson:"_id" json:"id"` + Name string `bson:"name" json:"name"` + ShortDescription string `bson:"shortDescription" json:"shortDescription"` + User string `bson:"user" json:"user"` + Token string `bson:"token" json:"token"` + TotalRequests uint64 `bson:"totalRequests" json:"totalRequests"` + CreatedAt time.Time `bson:"createdAt" json:"createdAt"` +} + +type Token struct { + ID string `bson:"_id" json:"id"` + Name string `bson:"name" json:"name"` + Token string `bson:"token" json:"token"` + TotalRequests uint64 `bson:"totalRequests" json:"totalRequests"` + Application string `bson:"application" json:"application"` + CreatedAt time.Time `bson:"createdAt" json:"createdAt"` + LastUsedAt time.Time `bson:"lastUsedAt" json:"lastUsedAt"` +} + +func (c *MongoDB) Connect() error { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + + defer cancel() + + parsedURI, err := url.Parse(*config.MongoDB) + + if err != nil { + return err + } + + client, err := mongo.Connect(ctx, options.Client().ApplyURI(*config.MongoDB)) + + if err != nil { + return err + } + + c.Client = client + c.Database = client.Database(strings.TrimPrefix(parsedURI.Path, "/")) + + return nil +} + +func (c *MongoDB) GetTokenByToken(token string) (*Token, error) { + if c.Client == nil { + return nil, ErrMongoNotConnected + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + + defer cancel() + + cur := c.Database.Collection(CollectionTokens).FindOne(ctx, bson.M{"token": token}) + + if err := cur.Err(); err != nil { + if errors.Is(err, mongo.ErrNoDocuments) { + return nil, nil + } + + return nil, err + } + + var result Token + + if err := cur.Decode(&result); err != nil { + return nil, err + } + + return &result, nil +} + +func (c *MongoDB) GetApplicationByID(id string) (*Application, error) { + if c.Client == nil { + return nil, ErrMongoNotConnected + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + + defer cancel() + + cur := c.Database.Collection(CollectionApplications).FindOne(ctx, bson.M{"_id": id}) + + if err := cur.Err(); err != nil { + if errors.Is(err, mongo.ErrNoDocuments) { + return nil, nil + } + + return nil, err + } + + var result Application + + if err := cur.Decode(&result); err != nil { + return nil, err + } + + return &result, nil +} + +func (c *MongoDB) UpdateToken(id string, update bson.M) error { + if c.Client == nil { + return ErrMongoNotConnected + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + + defer cancel() + + _, err := c.Database.Collection(CollectionTokens).UpdateOne( + ctx, + bson.M{"_id": id}, + update, + ) + + return err +} + +func (c *MongoDB) IncrementApplicationRequestCount(id string) error { + if c.Client == nil { + return ErrMongoNotConnected + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + + defer cancel() + + _, err := c.Database.Collection(CollectionApplications).UpdateOne( + ctx, + bson.M{"_id": id}, + bson.M{ + "$inc": bson.M{ + "totalRequests": 1, + }, + }, + ) + + return err +} + +func (c *MongoDB) UpsertRequestLog(query, update bson.M) error { + if c.Client == nil { + return ErrMongoNotConnected + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + + defer cancel() + + _, err := c.Database.Collection(CollectionRequestLog).UpdateOne( + ctx, + query, + update, + &options.UpdateOptions{ + Upsert: PointerOf(true), + }, + ) + + return err +} + +func (c *MongoDB) Close() error { + if c.Client == nil { + return nil + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + + defer cancel() + + return c.Client.Disconnect(ctx) +} diff --git a/src/routes.go b/src/routes.go index 21df249..6c6cb1c 100644 --- a/src/routes.go +++ b/src/routes.go @@ -6,7 +6,6 @@ import ( "main/src/assets" "net/http" "strconv" - "strings" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/cors" @@ -26,15 +25,13 @@ func init() { Data: assets.Favicon, })) - if config.AccessControl.Enable { + if config.Environment == "development" { app.Use(cors.New(cors.Config{ - AllowOrigins: strings.Join(config.AccessControl.AllowedOrigins, ","), + AllowOrigins: "*", AllowMethods: "HEAD,OPTIONS,GET,POST", ExposeHeaders: "X-Cache-Hit,X-Cache-Time-Remaining", })) - } - if config.Environment == "development" { app.Use(logger.New(logger.Config{ Format: "${time} ${ip}:${port} -> ${status}: ${method} ${path} (${latency})\n", TimeFormat: "2006/01/02 15:04:05", @@ -68,6 +65,14 @@ func JavaStatusHandler(ctx *fiber.Ctx) error { return ctx.Status(http.StatusBadRequest).SendString("Invalid address value") } + authorized, err := Authenticate(ctx) + + // This check should work for both scenarios, because nil should be returned if the user + // is unauthorized, and err will be nil in that case. + if err != nil || !authorized { + return err + } + if err = r.Increment(fmt.Sprintf("java-hits:%s-%d", host, port)); err != nil { return err } diff --git a/src/util.go b/src/util.go index e26f76d..99f6a30 100644 --- a/src/util.go +++ b/src/util.go @@ -1,6 +1,7 @@ package main import ( + "crypto/rand" "crypto/sha1" _ "embed" "encoding/hex" @@ -19,6 +20,7 @@ import ( "time" "github.com/gofiber/fiber/v2" + "go.mongodb.org/mongo-driver/bson" ) var ( @@ -248,6 +250,7 @@ func GetVoteOptions(ctx *fiber.Ctx) (*VoteOptions, error) { return &result, nil } +// GetStatusOptions returns the options for status routes, with the default values filled in. func GetStatusOptions(ctx *fiber.Ctx) (*StatusOptions, error) { result := &StatusOptions{} @@ -292,6 +295,70 @@ func GetCacheKey(host string, port uint16, opts *StatusOptions) string { return SHA256(values.Encode()) } +// Authenticate checks and requires authentication for the current request, by finding the token. +func Authenticate(ctx *fiber.Ctx) (bool, error) { + if config.MongoDB == nil { + return true, nil + } + + authToken := ctx.Get("Authorization") + + if len(authToken) < 1 { + if err := ctx.Status(http.StatusUnauthorized).SendString("Missing 'Authorization' header in request"); err != nil { + return false, err + } + + return false, nil + } + + token, err := db.GetTokenByToken(authToken) + + if err != nil { + return false, err + } + + if token == nil { + if err := ctx.Status(http.StatusUnauthorized).SendString("Invalid or expired authorization token, please generate another one in the dashboard"); err != nil { + return false, err + } + + return false, nil + } + + if err = db.IncrementApplicationRequestCount(token.Application); err != nil { + return false, err + } + + if err = db.UpdateToken( + token.ID, + bson.M{ + "$inc": bson.M{"requestCount": 1}, + "$set": bson.M{"lastUsedAt": time.Now().UTC()}, + }, + ); err != nil { + return false, err + } + + if err = db.UpsertRequestLog( + bson.M{ + "application": token.Application, + "timestamp": GetStartOfHour(), + }, + bson.M{ + "$setOnInsert": bson.M{ + "_id": RandomHexString(16), + }, + "$inc": bson.M{ + "requestCount": 1, + }, + }, + ); err != nil { + return false, err + } + + return true, nil +} + // SHA256 returns the result of hashing the input value using SHA256 algorithm. func SHA256(input string) string { result := sha1.Sum([]byte(input)) @@ -325,3 +392,19 @@ func Map[I, O any](arr []I, f func(I) O) []O { return result } + +// GetStartOfHour returns the current date and time rounded down to the start of the hour. +func GetStartOfHour() time.Time { + return time.Now().UTC().Truncate(time.Hour) +} + +// RandomHexString returns a random hexadecimal string with the specified byte length. +func RandomHexString(byteLength int) string { + data := make([]byte, byteLength) + + if _, err := rand.Read(data); err != nil { + panic(err) + } + + return hex.EncodeToString(data) +} From c1c77e7f64f7ba4c77a6097c21ba7901dd2f2137 Mon Sep 17 00:00:00 2001 From: Jacob Gunther Date: Tue, 19 Mar 2024 20:11:32 -0500 Subject: [PATCH 2/7] chore: update dependencies --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c207f63..d1ab35f 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/go-redsync/redsync/v4 v4.12.1 github.com/gofiber/fiber/v2 v2.52.2 - github.com/mcstatus-io/mcutil/v3 v3.3.0 + github.com/mcstatus-io/mcutil/v3 v3.4.0 github.com/redis/go-redis/v9 v9.5.1 go.mongodb.org/mongo-driver v1.14.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 8c4e815..5f6f109 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mcstatus-io/mcutil/v3 v3.3.0 h1:FnI0hzmCtYGOlYARcdVTqNS+5iYqyo/t/U6YDpBmc8c= -github.com/mcstatus-io/mcutil/v3 v3.3.0/go.mod h1:f1hgiUD3WoNmeZdN1AXYASSEO7yPxVEsLCGXnPkK6p4= +github.com/mcstatus-io/mcutil/v3 v3.4.0 h1:mYELJ+lP6mWqL+bt2W9JIUMmfSZtrfBogBZ2p3HsCPQ= +github.com/mcstatus-io/mcutil/v3 v3.4.0/go.mod h1:f1hgiUD3WoNmeZdN1AXYASSEO7yPxVEsLCGXnPkK6p4= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= From 24d0102648959fe250a358e93953821e6e2b9bfd Mon Sep 17 00:00:00 2001 From: Jacob Gunther Date: Mon, 20 May 2024 18:15:00 -0500 Subject: [PATCH 3/7] Allow backwards compatibility of Votifier votes --- go.mod | 29 ++++++++++++------------ go.sum | 63 ++++++++++++++++++++++++++++----------------------- src/routes.go | 45 ++++++++++-------------------------- src/util.go | 22 +++++------------- 4 files changed, 68 insertions(+), 91 deletions(-) diff --git a/go.mod b/go.mod index d1ab35f..4c22a32 100644 --- a/go.mod +++ b/go.mod @@ -1,40 +1,41 @@ module main -go 1.18 +go 1.22 + +toolchain go1.22.3 require ( - github.com/go-redsync/redsync/v4 v4.12.1 - github.com/gofiber/fiber/v2 v2.52.2 - github.com/mcstatus-io/mcutil/v3 v3.4.0 + github.com/go-redsync/redsync/v4 v4.13.0 + github.com/gofiber/fiber/v2 v2.52.4 + github.com/mcstatus-io/mcutil/v3 v3.6.0 github.com/redis/go-redis/v9 v9.5.1 - go.mongodb.org/mongo-driver v1.14.0 + go.mongodb.org/mongo-driver v1.15.0 gopkg.in/yaml.v3 v3.0.1 ) require ( github.com/andybalholm/brotli v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/compress v1.17.8 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/montanaflynn/stats v0.7.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.52.0 // indirect + github.com/valyala/fasthttp v1.53.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect - github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect + github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76 // indirect + golang.org/x/crypto v0.23.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect ) diff --git a/go.sum b/go.sum index 5f6f109..58e784e 100644 --- a/go.sum +++ b/go.sum @@ -1,24 +1,31 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= -github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-redis/redis/v7 v7.4.1 h1:PASvf36gyUpr2zdOUS/9Zqc80GbM+9BDyiJSJDDOrTI= +github.com/go-redis/redis/v7 v7.4.1/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= 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-redsync/redsync/v4 v4.12.1 h1:hCtdZ45DJxMxNdPiby5GlQwOKQmcka2587Y466qPqlA= -github.com/go-redsync/redsync/v4 v4.12.1/go.mod h1:sn72ojgeEhxUuRjrliK0NRrB0Zl6kOZ3BDvNN3P2jAY= -github.com/gofiber/fiber/v2 v2.52.2 h1:b0rYH6b06Df+4NyrbdptQL8ifuxw/Tf2DgfkZkDaxEo= -github.com/gofiber/fiber/v2 v2.52.2/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= +github.com/go-redsync/redsync/v4 v4.13.0 h1:49X6GJfnbLGaIpBBREM/zA4uIMDXKAh1NDkvQ1EkZKA= +github.com/go-redsync/redsync/v4 v4.13.0/go.mod h1:HMW4Q224GZQz6x1Xc7040Yfgacukdzu7ifTDAKiyErQ= +github.com/gofiber/fiber/v2 v2.52.4 h1:P+T+4iK7VaqUsq2PALYEfBBo6bJZ4q3FP8cZ84EggTM= +github.com/gofiber/fiber/v2 v2.52.4/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws= +github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -26,8 +33,8 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -35,21 +42,23 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mcstatus-io/mcutil/v3 v3.4.0 h1:mYELJ+lP6mWqL+bt2W9JIUMmfSZtrfBogBZ2p3HsCPQ= -github.com/mcstatus-io/mcutil/v3 v3.4.0/go.mod h1:f1hgiUD3WoNmeZdN1AXYASSEO7yPxVEsLCGXnPkK6p4= +github.com/mcstatus-io/mcutil/v3 v3.6.0 h1:IJqIXMtVtz1yUcMKxnrUIcAlChm/OTNAPzyb16TTwLk= +github.com/mcstatus-io/mcutil/v3 v3.6.0/go.mod h1:6Rv4qnejaTezu/feuQ2M4131phQxw0Q4C5h3An/iNxI= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/redis/rueidis v1.0.19 h1:s65oWtotzlIFN8eMPhyYwxlwLR1lUdhza2KtWprKYSo= +github.com/redis/rueidis v1.0.19/go.mod h1:8B+r5wdnjwK3lTFml5VtxjzGOQAC+5UmujoD12pDrEo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM= +github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8= 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/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0= -github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ= +github.com/valyala/fasthttp v1.53.0 h1:lW/+SUkOxCx2vlIu0iaImv4JLrVRnbbkpCoaawvA4zc= +github.com/valyala/fasthttp v1.53.0/go.mod h1:6dt4/8olwq9QARP/TDuPmWyWcl4byhpvTJ4AAtcz+QM= 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/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= @@ -58,48 +67,46 @@ github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= -github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= +github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76 h1:tBiBTKHnIjovYoLX/TPkcf+OjqqKGQrPtGT3Foz+Pgo= +github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76/go.mod h1:SQliXeA7Dhkt//vS29v3zpbEwoa+zb2Cn5xj5uO4K5U= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= -go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= +go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= +go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/src/routes.go b/src/routes.go index 6c6cb1c..3cb8ec1 100644 --- a/src/routes.go +++ b/src/routes.go @@ -167,41 +167,20 @@ func SendVoteHandler(ctx *fiber.Ctx) error { return ctx.Status(http.StatusBadRequest).SendString(err.Error()) } - switch opts.Version { - case 1: - { - c, cancel := context.WithTimeout(context.Background(), opts.Timeout) + c, cancel := context.WithTimeout(context.Background(), opts.Timeout) - defer cancel() + defer cancel() - if err = mcutil.SendVote(c, opts.Host, opts.Port, options.Vote{ - PublicKey: opts.PublicKey, - ServiceName: opts.ServiceName, - Username: opts.Username, - IPAddress: opts.IPAddress, - Timestamp: opts.Timestamp, - Timeout: opts.Timeout, - }); err != nil { - return ctx.Status(http.StatusBadRequest).SendString(err.Error()) - } - } - case 2: - { - c, cancel := context.WithTimeout(context.Background(), opts.Timeout) - - defer cancel() - - if err = mcutil.SendVote(c, opts.Host, opts.Port, options.Vote{ - ServiceName: opts.ServiceName, - Username: opts.Username, - Token: opts.Token, - UUID: opts.UUID, - Timestamp: opts.Timestamp, - Timeout: opts.Timeout, - }); err != nil { - return ctx.Status(http.StatusBadRequest).SendString(err.Error()) - } - } + if err = mcutil.SendVote(c, opts.Host, opts.Port, options.Vote{ + PublicKey: opts.PublicKey, + Token: opts.Token, + ServiceName: opts.ServiceName, + Username: opts.Username, + IPAddress: opts.IPAddress, + Timestamp: opts.Timestamp, + Timeout: opts.Timeout, + }); err != nil { + return ctx.Status(http.StatusBadRequest).SendString(err.Error()) } return ctx.Status(http.StatusOK).SendString("The vote was successfully sent to the server") diff --git a/src/util.go b/src/util.go index 99f6a30..02e8a13 100644 --- a/src/util.go +++ b/src/util.go @@ -154,15 +154,6 @@ func ParseAddress(address string, defaultPort uint16) (string, uint16, error) { func GetVoteOptions(ctx *fiber.Ctx) (*VoteOptions, error) { result := VoteOptions{} - // Version - { - result.Version = ctx.QueryInt("version", 2) - - if result.Version < 0 || result.Version > 2 { - return nil, fmt.Errorf("invalid 'version' query parameter: %d", result.Version) - } - } - // Host { result.Host = ctx.Query("host") @@ -206,18 +197,12 @@ func GetVoteOptions(ctx *fiber.Ctx) (*VoteOptions, error) { { result.PublicKey = ctx.Query("publickey") - if result.Version == 1 && len(result.PublicKey) < 1 { - return nil, fmt.Errorf("invalid 'publickey' query parameter: %s", result.PublicKey) - } + log.Println(result.PublicKey) } // Token { result.Token = ctx.Query("token") - - if result.Version == 2 && len(result.Token) < 1 { - return nil, fmt.Errorf("invalid 'token' query parameter: %s", result.Token) - } } // IP Address @@ -247,6 +232,11 @@ func GetVoteOptions(ctx *fiber.Ctx) (*VoteOptions, error) { result.Timeout = time.Duration(math.Max(float64(time.Second)*ctx.QueryFloat("timeout", 5.0), float64(time.Millisecond*250))) } + // Test token and public key parameters + if len(result.Token) < 1 && len(result.PublicKey) < 1 { + return nil, errors.New("query parameter 'token', 'publickey' or both must have a value, but both were empty") + } + return &result, nil } From c99367619156acb29af6492b3a161f868e827f30 Mon Sep 17 00:00:00 2001 From: Jacob Gunther Date: Mon, 20 May 2024 18:18:54 -0500 Subject: [PATCH 4/7] Remove Version property from vote options --- src/util.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/util.go b/src/util.go index 02e8a13..884d4be 100644 --- a/src/util.go +++ b/src/util.go @@ -31,7 +31,6 @@ var ( // VoteOptions is the options provided as query parameters to the vote route. type VoteOptions struct { - Version int IPAddress string Host string Port uint16 From a7c9a7df728de1bf9f9f7310223d3dfc714812a6 Mon Sep 17 00:00:00 2001 From: Jacob Gunther Date: Thu, 13 Jun 2024 19:02:32 -0500 Subject: [PATCH 5/7] Remove extra debug logging --- src/util.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/util.go b/src/util.go index 884d4be..905f9f4 100644 --- a/src/util.go +++ b/src/util.go @@ -195,8 +195,6 @@ func GetVoteOptions(ctx *fiber.Ctx) (*VoteOptions, error) { // Public Key { result.PublicKey = ctx.Query("publickey") - - log.Println(result.PublicKey) } // Token From c7a9bc87e4f6a7a45387318414e334f94dbe3ab3 Mon Sep 17 00:00:00 2001 From: Jacob Gunther Date: Fri, 14 Jun 2024 10:50:27 -0500 Subject: [PATCH 6/7] Add token ID to request log data --- src/mongo.go | 16 ++++++++-------- src/util.go | 1 + 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/mongo.go b/src/mongo.go index 020e149..4e523ce 100644 --- a/src/mongo.go +++ b/src/mongo.go @@ -31,18 +31,18 @@ type Application struct { ShortDescription string `bson:"shortDescription" json:"shortDescription"` User string `bson:"user" json:"user"` Token string `bson:"token" json:"token"` - TotalRequests uint64 `bson:"totalRequests" json:"totalRequests"` + RequestCount uint64 `bson:"requestCount" json:"requestCount"` CreatedAt time.Time `bson:"createdAt" json:"createdAt"` } type Token struct { - ID string `bson:"_id" json:"id"` - Name string `bson:"name" json:"name"` - Token string `bson:"token" json:"token"` - TotalRequests uint64 `bson:"totalRequests" json:"totalRequests"` - Application string `bson:"application" json:"application"` - CreatedAt time.Time `bson:"createdAt" json:"createdAt"` - LastUsedAt time.Time `bson:"lastUsedAt" json:"lastUsedAt"` + ID string `bson:"_id" json:"id"` + Name string `bson:"name" json:"name"` + Token string `bson:"token" json:"token"` + RequestCount uint64 `bson:"requestCount" json:"requestCount"` + Application string `bson:"application" json:"application"` + CreatedAt time.Time `bson:"createdAt" json:"createdAt"` + LastUsedAt time.Time `bson:"lastUsedAt" json:"lastUsedAt"` } func (c *MongoDB) Connect() error { diff --git a/src/util.go b/src/util.go index 905f9f4..67bf49c 100644 --- a/src/util.go +++ b/src/util.go @@ -330,6 +330,7 @@ func Authenticate(ctx *fiber.Ctx) (bool, error) { bson.M{ "application": token.Application, "timestamp": GetStartOfHour(), + "token": token.ID, }, bson.M{ "$setOnInsert": bson.M{ From eeffc54ca4f4a674619a5606d036e593ae2b501d Mon Sep 17 00:00:00 2001 From: Jacob Gunther Date: Thu, 18 Jul 2024 13:24:11 -0500 Subject: [PATCH 7/7] Update mcutil library --- go.mod | 18 ++++---- go.sum | 42 ++++++++--------- src/routes.go | 36 ++++++++------- src/status.go | 124 +++++++++++++++++++++++++++++++------------------- src/util.go | 3 +- 5 files changed, 126 insertions(+), 97 deletions(-) diff --git a/go.mod b/go.mod index 4c22a32..e000893 100644 --- a/go.mod +++ b/go.mod @@ -6,10 +6,10 @@ toolchain go1.22.3 require ( github.com/go-redsync/redsync/v4 v4.13.0 - github.com/gofiber/fiber/v2 v2.52.4 - github.com/mcstatus-io/mcutil/v3 v3.6.0 - github.com/redis/go-redis/v9 v9.5.1 - go.mongodb.org/mongo-driver v1.15.0 + github.com/gofiber/fiber/v2 v2.52.5 + github.com/mcstatus-io/mcutil/v4 v4.0.0-20240718180705-427b3bcbde17 + github.com/redis/go-redis/v9 v9.5.4 + go.mongodb.org/mongo-driver v1.16.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -21,21 +21,21 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/klauspost/compress v1.17.8 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/montanaflynn/stats v0.7.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.53.0 // indirect + github.com/valyala/fasthttp v1.55.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76 // indirect - golang.org/x/crypto v0.23.0 // indirect + golang.org/x/crypto v0.25.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect ) diff --git a/go.sum b/go.sum index 58e784e..a236214 100644 --- a/go.sum +++ b/go.sum @@ -18,14 +18,14 @@ github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-redsync/redsync/v4 v4.13.0 h1:49X6GJfnbLGaIpBBREM/zA4uIMDXKAh1NDkvQ1EkZKA= github.com/go-redsync/redsync/v4 v4.13.0/go.mod h1:HMW4Q224GZQz6x1Xc7040Yfgacukdzu7ifTDAKiyErQ= -github.com/gofiber/fiber/v2 v2.52.4 h1:P+T+4iK7VaqUsq2PALYEfBBo6bJZ4q3FP8cZ84EggTM= -github.com/gofiber/fiber/v2 v2.52.4/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= +github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo= +github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws= github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -33,8 +33,8 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= -github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -42,12 +42,12 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mcstatus-io/mcutil/v3 v3.6.0 h1:IJqIXMtVtz1yUcMKxnrUIcAlChm/OTNAPzyb16TTwLk= -github.com/mcstatus-io/mcutil/v3 v3.6.0/go.mod h1:6Rv4qnejaTezu/feuQ2M4131phQxw0Q4C5h3An/iNxI= +github.com/mcstatus-io/mcutil/v4 v4.0.0-20240718180705-427b3bcbde17 h1:gdlFoHcepuGydv0yE29hrpdxIarTm0Z+8taA4QMndNw= +github.com/mcstatus-io/mcutil/v4 v4.0.0-20240718180705-427b3bcbde17/go.mod h1:yC91WInI1U2GAMFWgpPgsAULPVS2o+4JCZbiiWhHwxM= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= -github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/redis/go-redis/v9 v9.5.4 h1:vOFYDKKVgrI5u++QvnMT7DksSMYg7Aw/Np4vLJLKLwY= +github.com/redis/go-redis/v9 v9.5.4/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/redis/rueidis v1.0.19 h1:s65oWtotzlIFN8eMPhyYwxlwLR1lUdhza2KtWprKYSo= github.com/redis/rueidis v1.0.19/go.mod h1:8B+r5wdnjwK3lTFml5VtxjzGOQAC+5UmujoD12pDrEo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -57,8 +57,8 @@ github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08Yu github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8= 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/fasthttp v1.53.0 h1:lW/+SUkOxCx2vlIu0iaImv4JLrVRnbbkpCoaawvA4zc= -github.com/valyala/fasthttp v1.53.0/go.mod h1:6dt4/8olwq9QARP/TDuPmWyWcl4byhpvTJ4AAtcz+QM= +github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8= +github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM= 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/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= @@ -70,12 +70,12 @@ github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gi github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76 h1:tBiBTKHnIjovYoLX/TPkcf+OjqqKGQrPtGT3Foz+Pgo= github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76/go.mod h1:SQliXeA7Dhkt//vS29v3zpbEwoa+zb2Cn5xj5uO4K5U= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= -go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= +go.mongodb.org/mongo-driver v1.16.0 h1:tpRsfBJMROVHKpdGyc1BBEzzjDUWjItxbVSZ8Ls4BQ4= +go.mongodb.org/mongo-driver v1.16.0/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -91,22 +91,20 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/src/routes.go b/src/routes.go index 3cb8ec1..a015ea9 100644 --- a/src/routes.go +++ b/src/routes.go @@ -6,14 +6,16 @@ import ( "main/src/assets" "net/http" "strconv" + "strings" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/cors" "github.com/gofiber/fiber/v2/middleware/favicon" "github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/fiber/v2/middleware/recover" - "github.com/mcstatus-io/mcutil/v3" - "github.com/mcstatus-io/mcutil/v3/options" + "github.com/mcstatus-io/mcutil/v4/options" + "github.com/mcstatus-io/mcutil/v4/util" + "github.com/mcstatus-io/mcutil/v4/vote" ) func init() { @@ -53,15 +55,15 @@ func PingHandler(ctx *fiber.Ctx) error { // JavaStatusHandler returns the status of the Java edition Minecraft server specified in the address parameter. func JavaStatusHandler(ctx *fiber.Ctx) error { + address := strings.ToLower(ctx.Params("address")) + opts, err := GetStatusOptions(ctx) if err != nil { return err } - host, port, err := ParseAddress(ctx.Params("address"), 25565) - - if err != nil { + if _, _, err := util.ParseAddress(address); err != nil { return ctx.Status(http.StatusBadRequest).SendString("Invalid address value") } @@ -73,11 +75,11 @@ func JavaStatusHandler(ctx *fiber.Ctx) error { return err } - if err = r.Increment(fmt.Sprintf("java-hits:%s-%d", host, port)); err != nil { + if err = r.Increment(fmt.Sprintf("java-hits:%s", address)); err != nil { return err } - response, expiresAt, err := GetJavaStatus(host, port, opts) + response, expiresAt, err := GetJavaStatus(address, opts) if err != nil { return err @@ -94,23 +96,23 @@ func JavaStatusHandler(ctx *fiber.Ctx) error { // BedrockStatusHandler returns the status of the Bedrock edition Minecraft server specified in the address parameter. func BedrockStatusHandler(ctx *fiber.Ctx) error { + address := strings.ToLower(ctx.Params("address")) + opts, err := GetStatusOptions(ctx) if err != nil { return err } - host, port, err := ParseAddress(ctx.Params("address"), 19132) - - if err != nil { + if _, _, err := util.ParseAddress(address); err != nil { return ctx.Status(http.StatusBadRequest).SendString("Invalid address value") } - if err = r.Increment(fmt.Sprintf("bedrock-hits:%s-%d", host, port)); err != nil { + if err = r.Increment(fmt.Sprintf("bedrock-hits:%s", address)); err != nil { return err } - response, expiresAt, err := GetBedrockStatus(host, port, opts) + response, expiresAt, err := GetBedrockStatus(address, opts) if err != nil { return err @@ -127,19 +129,19 @@ func BedrockStatusHandler(ctx *fiber.Ctx) error { // IconHandler returns the server icon for the specified Java edition Minecraft server. func IconHandler(ctx *fiber.Ctx) error { + address := strings.ToLower(ctx.Params("address")) + opts, err := GetStatusOptions(ctx) if err != nil { return err } - host, port, err := ParseAddress(ctx.Params("address"), 25565) - - if err != nil { + if _, _, err := util.ParseAddress(address); err != nil { return ctx.Status(http.StatusBadRequest).SendString("Invalid address value") } - icon, expiresAt, err := GetServerIcon(host, port, opts) + icon, expiresAt, err := GetServerIcon(address, opts) if err != nil { return err @@ -171,7 +173,7 @@ func SendVoteHandler(ctx *fiber.Ctx) error { defer cancel() - if err = mcutil.SendVote(c, opts.Host, opts.Port, options.Vote{ + if err = vote.SendVote(c, opts.Host, opts.Port, options.Vote{ PublicKey: opts.PublicKey, Token: opts.Token, ServiceName: opts.ServiceName, diff --git a/src/status.go b/src/status.go index 06887e0..aac1075 100644 --- a/src/status.go +++ b/src/status.go @@ -12,10 +12,12 @@ import ( "sync" "time" - "github.com/mcstatus-io/mcutil/v3" - "github.com/mcstatus-io/mcutil/v3/formatting" - "github.com/mcstatus-io/mcutil/v3/options" - "github.com/mcstatus-io/mcutil/v3/response" + "github.com/mcstatus-io/mcutil/v4/formatting" + "github.com/mcstatus-io/mcutil/v4/options" + "github.com/mcstatus-io/mcutil/v4/query" + "github.com/mcstatus-io/mcutil/v4/response" + "github.com/mcstatus-io/mcutil/v4/status" + "github.com/mcstatus-io/mcutil/v4/util" ) // BaseStatus is the base response properties for returning any status response from the API. @@ -124,8 +126,8 @@ type SRVRecord struct { } // GetJavaStatus returns the status response of a Java Edition server, either using cache or fetching a fresh status. -func GetJavaStatus(host string, port uint16, opts *StatusOptions) (*JavaStatusResponse, time.Duration, error) { - cacheKey := GetCacheKey(host, port, opts) +func GetJavaStatus(host string, opts *StatusOptions) (*JavaStatusResponse, time.Duration, error) { + cacheKey := GetCacheKey(host, opts) // Wait for any other processes to finish fetching the status of this server if config.Cache.EnableLocks { @@ -154,7 +156,11 @@ func GetJavaStatus(host string, port uint16, opts *StatusOptions) (*JavaStatusRe // Fetch a fresh status from the server itself { - response := FetchJavaStatus(host, port, opts) + response, err := FetchJavaStatus(host, opts) + + if err != nil { + return nil, 0, err + } data, err := json.Marshal(response) @@ -166,13 +172,13 @@ func GetJavaStatus(host string, port uint16, opts *StatusOptions) (*JavaStatusRe return nil, 0, err } - return &response, 0, nil + return response, 0, nil } } // GetBedrockStatus returns the status response of a Bedrock Edition server, either using cache or fetching a fresh status. -func GetBedrockStatus(host string, port uint16, opts *StatusOptions) (*BedrockStatusResponse, time.Duration, error) { - cacheKey := GetCacheKey(host, port, nil) +func GetBedrockStatus(host string, opts *StatusOptions) (*BedrockStatusResponse, time.Duration, error) { + cacheKey := GetCacheKey(host, nil) // Wait for any other processes to finish fetching the status of this server if config.Cache.EnableLocks { @@ -201,7 +207,11 @@ func GetBedrockStatus(host string, port uint16, opts *StatusOptions) (*BedrockSt // Fetch a fresh status from the server itself { - response := FetchBedrockStatus(host, port, opts) + response, err := FetchBedrockStatus(host, opts) + + if err != nil { + return nil, 0, err + } data, err := json.Marshal(response) @@ -213,13 +223,13 @@ func GetBedrockStatus(host string, port uint16, opts *StatusOptions) (*BedrockSt 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. -func GetServerIcon(host string, port uint16, opts *StatusOptions) ([]byte, time.Duration, error) { - cacheKey := GetCacheKey(host, port, nil) +func GetServerIcon(host string, opts *StatusOptions) ([]byte, time.Duration, error) { + cacheKey := GetCacheKey(host, nil) // Fetch the cached icon if it exists { @@ -244,7 +254,7 @@ func GetServerIcon(host string, port uint16, opts *StatusOptions) ([]byte, time. defer cancel() - status, err := mcutil.Status(ctx, host, port) + status, err := status.Modern(ctx, host) 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,")) @@ -268,15 +278,15 @@ func GetServerIcon(host string, port uint16, opts *StatusOptions) ([]byte, time. } // FetchJavaStatus fetches fresh information about a Java Edition Minecraft server. -func FetchJavaStatus(host string, port uint16, opts *StatusOptions) JavaStatusResponse { +func FetchJavaStatus(host string, opts *StatusOptions) (*JavaStatusResponse, error) { var ( err error srvRecord *net.SRV resolvedHost string = host ipAddress *string - statusResult *response.JavaStatus - legacyStatusResult *response.JavaStatusLegacy - queryResult *response.FullQuery + statusResult *response.StatusModern + legacyStatusResult *response.StatusLegacy + queryResult *response.QueryFull wg sync.WaitGroup ) @@ -291,7 +301,7 @@ func FetchJavaStatus(host string, port uint16, opts *StatusOptions) JavaStatusRe // Lookup the SRV record { - srvRecord, err = mcutil.LookupSRV("tcp", host) + srvRecord, err = util.LookupSRV(host) if err == nil && srvRecord != nil { resolvedHost = strings.Trim(srvRecord.Target, ".") @@ -318,7 +328,7 @@ func FetchJavaStatus(host string, port uint16, opts *StatusOptions) JavaStatusRe // Retrieve the post-netty rewrite Java Edition status (Minecraft 1.8+) { go func() { - statusResult, _ = mcutil.Status(statusContext, host, port, options.JavaStatus{ + statusResult, _ = status.Modern(statusContext, host, options.StatusModern{ EnableSRV: true, Timeout: opts.Timeout - time.Millisecond*100, ProtocolVersion: 47, @@ -342,7 +352,7 @@ func FetchJavaStatus(host string, port uint16, opts *StatusOptions) JavaStatusRe // Retrieve the pre-netty rewrite Java Edition status (Minecraft 1.7 and below) { go func() { - legacyStatusResult, _ = mcutil.StatusLegacy(legacyContext, host, port, options.JavaStatusLegacy{ + legacyStatusResult, _ = status.Legacy(legacyContext, host, options.StatusLegacy{ EnableSRV: true, Timeout: opts.Timeout - time.Millisecond*100, ProtocolVersion: 47, @@ -361,7 +371,7 @@ func FetchJavaStatus(host string, port uint16, opts *StatusOptions) JavaStatusRe // Retrieve the query information (if it is available) if opts.Query { go func() { - queryResult, _ = mcutil.FullQuery(queryContext, host, port, options.Query{ + queryResult, _ = query.Full(queryContext, host, options.Query{ Timeout: opts.Timeout - time.Millisecond*100, }) @@ -371,14 +381,14 @@ func FetchJavaStatus(host string, port uint16, opts *StatusOptions) JavaStatusRe wg.Wait() - return BuildJavaResponse(host, port, statusResult, legacyStatusResult, queryResult, srvRecord, ipAddress) + return BuildJavaResponse(host, statusResult, legacyStatusResult, queryResult, srvRecord, ipAddress) } // FetchBedrockStatus fetches a fresh status of a Bedrock Edition server. -func FetchBedrockStatus(host string, port uint16, opts *StatusOptions) BedrockStatusResponse { +func FetchBedrockStatus(host string, opts *StatusOptions) (*BedrockStatusResponse, error) { var ( ipAddress *string - status *response.BedrockStatus + result *response.StatusBedrock ) // Resolve the connection hostname to an IP address @@ -396,19 +406,29 @@ func FetchBedrockStatus(host string, port uint16, opts *StatusOptions) BedrockSt defer cancel() - status, _ = mcutil.StatusBedrock(ctx, host, port) + result, _ = status.Bedrock(ctx, host) } - return BuildBedrockResponse(host, port, status, ipAddress) + return BuildBedrockResponse(host, result, ipAddress) } // BuildJavaResponse builds the response data from the status and query information. -func BuildJavaResponse(host string, port uint16, status *response.JavaStatus, legacyStatus *response.JavaStatusLegacy, query *response.FullQuery, srvRecord *net.SRV, ipAddress *string) (result JavaStatusResponse) { - result = JavaStatusResponse{ +func BuildJavaResponse(host string, status *response.StatusModern, legacyStatus *response.StatusLegacy, query *response.QueryFull, srvRecord *net.SRV, ipAddress *string) (result *JavaStatusResponse, err error) { + hostname, port, err := util.ParseAddress(host) + + if err != nil { + return nil, err + } + + if port == nil { + port = PointerOf(uint16(util.DefaultJavaPort)) + } + + result = &JavaStatusResponse{ BaseStatus: BaseStatus{ Online: false, - Host: host, - Port: port, + Host: hostname, + Port: *port, IPAddress: ipAddress, EULABlocked: IsBlockedAddress(host), RetrievedAt: time.Now().UnixMilli(), @@ -423,9 +443,9 @@ func BuildJavaResponse(host string, port uint16, status *response.JavaStatus, le result.JavaStatus = &JavaStatus{ Version: &JavaVersion{ - NameRaw: status.Version.NameRaw, - NameClean: status.Version.NameClean, - NameHTML: status.Version.NameHTML, + NameRaw: status.Version.Name.Raw, + NameClean: status.Version.Name.Clean, + NameHTML: status.Version.Name.HTML, Protocol: status.Version.Protocol, }, Players: JavaPlayers{ @@ -447,9 +467,9 @@ func BuildJavaResponse(host string, port uint16, status *response.JavaStatus, le for _, player := range status.Players.Sample { result.Players.List = append(result.Players.List, Player{ UUID: player.ID, - NameRaw: player.NameRaw, - NameClean: player.NameClean, - NameHTML: player.NameHTML, + NameRaw: player.Name.Raw, + NameClean: player.Name.Clean, + NameHTML: player.Name.HTML, }) } } @@ -458,8 +478,8 @@ func BuildJavaResponse(host string, port uint16, status *response.JavaStatus, le result.Icon = status.Favicon } - if status.ModInfo != nil { - for _, mod := range status.ModInfo.Mods { + if status.Mods != nil { + for _, mod := range status.Mods.List { result.Mods = append(result.Mods, Mod{ Name: mod.ID, Version: mod.Version, @@ -488,9 +508,9 @@ func BuildJavaResponse(host string, port uint16, status *response.JavaStatus, le if legacyStatus.Version != nil { result.Version = &JavaVersion{ - NameRaw: legacyStatus.Version.NameRaw, - NameClean: legacyStatus.Version.NameClean, - NameHTML: legacyStatus.Version.NameHTML, + NameRaw: legacyStatus.Version.Name.Raw, + NameClean: legacyStatus.Version.Name.Clean, + NameHTML: legacyStatus.Version.Name.HTML, Protocol: legacyStatus.Version.Protocol, } } @@ -600,12 +620,22 @@ func BuildJavaResponse(host string, port uint16, status *response.JavaStatus, le } // BuildBedrockResponse builds the response data from the status information. -func BuildBedrockResponse(host string, port uint16, status *response.BedrockStatus, ipAddress *string) (result BedrockStatusResponse) { - result = BedrockStatusResponse{ +func BuildBedrockResponse(host string, status *response.StatusBedrock, ipAddress *string) (result *BedrockStatusResponse, err error) { + hostname, port, err := util.ParseAddress(host) + + if err != nil { + return nil, err + } + + if port == nil { + port = PointerOf(uint16(util.DefaultBedrockPort)) + } + + result = &BedrockStatusResponse{ BaseStatus: BaseStatus{ Online: false, - Host: host, - Port: port, + Host: hostname, + Port: *port, IPAddress: ipAddress, EULABlocked: IsBlockedAddress(host), RetrievedAt: time.Now().UnixMilli(), diff --git a/src/util.go b/src/util.go index 67bf49c..9b5774d 100644 --- a/src/util.go +++ b/src/util.go @@ -270,10 +270,9 @@ func GetInstanceID() (uint16, error) { } // GetCacheKey generates a unique key used for caching status results in Redis. -func GetCacheKey(host string, port uint16, opts *StatusOptions) string { +func GetCacheKey(host string, opts *StatusOptions) string { values := &url.Values{} values.Set("host", host) - values.Set("port", strconv.FormatUint(uint64(port), 10)) if opts != nil { values.Set("query", strconv.FormatBool(opts.Query))