From f9037f95985a08ade01d73bcbcdc3e50a184fc15 Mon Sep 17 00:00:00 2001 From: Etzelia Date: Mon, 5 Oct 2020 22:21:20 -0500 Subject: [PATCH] Add POST options Signed-off-by: Etzelia --- ban.go | 51 +++++++++++++++++++++++----- client.go | 98 ++++++++++++++++++++++++++++++++++++------------------ custom.go | 25 ++++++++++++++ graphql.go | 6 ++-- ping.go | 2 +- player.go | 2 +- plugin.go | 2 +- tps.go | 2 +- world.go | 4 +-- 9 files changed, 143 insertions(+), 49 deletions(-) create mode 100644 custom.go diff --git a/ban.go b/ban.go index 68ae822..822f3e3 100644 --- a/ban.go +++ b/ban.go @@ -5,13 +5,28 @@ import ( "time" ) +// Unban is a Minecraft pardon +type Unban struct { + Target string `json:"target"` +} + +// Kick is a Minecraft kick +type Kick struct { + Unban + Reason string `json:"reason"` +} + // Ban is a Minecraft ban type Ban struct { - Target string `json:"target"` - Source string `jso:"source"` - Reason string `json:"reason"` - Created int64 `json:"created"` - Expiration int64 `json:"expiration"` + Kick + Source string `json:"source"` + Created int64 `json:"created"` +} + +// Ban is a Minecraft ban with an expiration +type TempBan struct { + Ban + Expiration int64 `json:"expiration"` } // CreatedTime is Created converted to a time.Time @@ -20,11 +35,31 @@ func (b *Ban) CreatedTime() time.Time { } // ExpirationTime is Expiration converted to a time.Time -func (b *Ban) ExpirationTime() time.Time { - return time.Unix(b.Expiration/1000, 0) +func (t *TempBan) ExpirationTime() time.Time { + return time.Unix(t.Expiration/1000, 0) } // Bans gets a list of Ban from a ServerAPI instance func (c *Client) Bans() (bans Ban, err error) { - return bans, c.json(fmt.Sprintf("%s/bans", c.Endpoint), &bans) + return bans, c.jsonGET(fmt.Sprintf("%s/bans", c.endpoint), &bans) +} + +// Kick kicks a player +func (c *Client) Kick(k Kick) (int, error) { + return c.jsonPOST(fmt.Sprintf("%s/kick", c.endpoint), k) +} + +// Ban bans a player +func (c *Client) Ban(b Ban) (int, error) { + return c.jsonPOST(fmt.Sprintf("%s/ban", c.endpoint), b) +} + +// TempBan temporarily bans a player +func (c *Client) TempBan(t TempBan) (int, error) { + return c.jsonPOST(fmt.Sprintf("%s/ban", c.endpoint), t) +} + +// Unban pardons a player +func (c *Client) Unban(u Unban) (int, error) { + return c.jsonPOST(fmt.Sprintf("%s/unban", c.endpoint), u) } diff --git a/client.go b/client.go index 28bbd13..1858996 100644 --- a/client.go +++ b/client.go @@ -1,6 +1,7 @@ package serverapi import ( + "bytes" "encoding/json" "fmt" "io/ioutil" @@ -10,49 +11,53 @@ import ( // Client is a client aimed at a specific ServerAPI endpoint type Client struct { - Endpoint string - Options *ClientOptions + endpoint string + http *http.Client + token string } -// ClientOptions are options that can be set for a Client -type ClientOptions struct { - HTTP *http.Client - Password string +// ClientOption is options for a Client +type ClientOption func(c *Client) + +var defaultHeader = http.Header{ + "Content-Type": []string{"application/json; charset=utf-8"}, + "Accept": []string{"application/json; charset=utf-8"}, } -var ( - // DefaultOptions are the default set of ClientOptions for a Client - DefaultOptions = &ClientOptions{ - HTTP: http.DefaultClient, - } - - defaultHeader = http.Header{ - "Content-Type": []string{"application/json; charset=utf-8"}, - "Accept": []string{"application/json; charset=utf-8"}, - } -) - // NewClient returns a new Client for making ServerAPI requests -func NewClient(endpoint string, options *ClientOptions) *Client { - if options == nil { - options = DefaultOptions - } +func NewClient(endpoint string, opts ...ClientOption) *Client { endpoint = strings.TrimSuffix(endpoint, "/") - return &Client{ - Endpoint: endpoint, - Options: options, + c := &Client{ + endpoint: endpoint, + http: http.DefaultClient, + token: "", + } + for _, opt := range opts { + opt(c) + } + return c +} + +// WithHTTP is a ClientOption for setting the http.Client of a Client +func WithHTTP(http *http.Client) ClientOption { + return func(c *Client) { + c.http = http } } -func (c *Client) json(endpoint string, obj interface{}) error { - req, err := http.NewRequest(http.MethodGet, endpoint, nil) - if err != nil { - return fmt.Errorf("new JSON request: %v", err) +// WithToken is a ClientOption for setting the token of a Client +func WithToken(token string) ClientOption { + return func(c *Client) { + c.token = token } - req.Header = defaultHeader - req.Header.Add("X-ServerAPI-Password", c.Options.Password) +} - res, err := c.Options.HTTP.Do(req) +func (c *Client) jsonGET(endpoint string, obj interface{}) error { + req, err := c.newRequest(endpoint, http.MethodGet, nil) + if err != nil { + return err + } + res, err := c.http.Do(req) if err != nil { return fmt.Errorf("sending request: %v", err) } @@ -64,3 +69,32 @@ func (c *Client) json(endpoint string, obj interface{}) error { return json.Unmarshal(body, obj) } + +func (c *Client) jsonPOST(endpoint string, obj interface{}) (int, error) { + body, err := json.Marshal(obj) + if err != nil { + return -1, err + } + + req, err := c.newRequest(endpoint, http.MethodPost, body) + if err != nil { + return -1, err + } + + res, err := c.http.Do(req) + if err != nil { + return -1, fmt.Errorf("sending request: %v", err) + } + + return res.StatusCode, nil +} + +func (c *Client) newRequest(endpoint, method string, body []byte) (*http.Request, error) { + req, err := http.NewRequest(method, endpoint, bytes.NewBuffer(body)) + if err != nil { + return nil, fmt.Errorf("new JSON request: %v", err) + } + req.Header = defaultHeader + req.Header.Add("X-ServerAPI-Token", c.token) + return req, nil +} diff --git a/custom.go b/custom.go new file mode 100644 index 0000000..0fbd682 --- /dev/null +++ b/custom.go @@ -0,0 +1,25 @@ +package serverapi + +import "fmt" + +// Broadcast is a server-wide message +type Broadcast struct { + From string `json:"from"` + Message string `json:"message"` +} + +// Broadcast sends a message to the server +func (c *Client) Broadcast(b Broadcast) (int, error) { + return c.jsonPOST(fmt.Sprintf("%s/broadcast", c.endpoint), b) +} + +// Custom is for edge-cases +type Custom struct { + Command string `json:"command"` + Args []string `json:"args"` +} + +// Custom sends a custom command to the server +func (c *Client) Custom(cu Custom) (int, error) { + return c.jsonPOST(fmt.Sprintf("%s/custom", c.endpoint), cu) +} diff --git a/graphql.go b/graphql.go index 73aec67..c99aeb1 100644 --- a/graphql.go +++ b/graphql.go @@ -25,14 +25,14 @@ type Worlds []*World // GraphQL returns a gql.Client for a ServerAPI instance func (c *Client) GraphQL() *gql.Client { - return gql.NewClient(fmt.Sprintf("%s/graphql", c.Endpoint), &gql.ClientOptions{ - HTTP: c.Options.HTTP, + return gql.NewClient(fmt.Sprintf("%s/graphql", c.endpoint), &gql.ClientOptions{ + HTTP: c.http, }) } // GraphQLRequest returns a pre-filled gql.Request with the password set func (c *Client) GraphQLRequest(query string) *gql.Request { req := gql.NewRequest(query) - req.Header.Add("X-ServerAPI-Password", c.Options.Password) + req.Header.Add("X-ServerAPI-Token", c.token) return req } diff --git a/ping.go b/ping.go index 620528f..83d18d4 100644 --- a/ping.go +++ b/ping.go @@ -13,5 +13,5 @@ type Ping struct { // Ping returns a Ping func (c *Client) Ping() (ping *Ping, err error) { - return ping, c.json(fmt.Sprintf("%s/ping", c.Endpoint), &ping) + return ping, c.jsonGET(fmt.Sprintf("%s/ping", c.endpoint), &ping) } diff --git a/player.go b/player.go index 907ab6c..8ac1200 100644 --- a/player.go +++ b/player.go @@ -10,5 +10,5 @@ type Player struct { // Players returns a list of Player from a ServerAPI instance func (c *Client) Players() (players Players, err error) { - return players, c.json(fmt.Sprintf("%s/players", c.Endpoint), &players) + return players, c.jsonGET(fmt.Sprintf("%s/players", c.endpoint), &players) } diff --git a/plugin.go b/plugin.go index 2ec6539..1d75de2 100644 --- a/plugin.go +++ b/plugin.go @@ -12,5 +12,5 @@ type Plugin struct { // Plugins returns a list of Plugin from a ServerAPI instance func (c *Client) Plugins() (plugins Plugins, err error) { - return plugins, c.json(fmt.Sprintf("%s/plugins", c.Endpoint), &plugins) + return plugins, c.jsonGET(fmt.Sprintf("%s/plugins", c.endpoint), &plugins) } diff --git a/tps.go b/tps.go index e65329f..4011026 100644 --- a/tps.go +++ b/tps.go @@ -10,5 +10,5 @@ type TPS struct { // TPS returns TPS from a ServerAPI instance func (c *Client) TPS() (tps *TPS, err error) { - return tps, c.json(fmt.Sprintf("%s/tps", c.Endpoint), &tps) + return tps, c.jsonGET(fmt.Sprintf("%s/tps", c.endpoint), &tps) } diff --git a/world.go b/world.go index 62e7bcd..9c819c5 100644 --- a/world.go +++ b/world.go @@ -48,10 +48,10 @@ func (w *World) FullTimeHours() int64 { // World returns a single World from a ServerAPI instance func (c *Client) World(name string) (world *World, err error) { - return world, c.json(fmt.Sprintf("%s/worlds/%s", c.Endpoint, name), &world) + return world, c.jsonGET(fmt.Sprintf("%s/worlds/%s", c.endpoint, name), &world) } // Worlds returns a list of World from a ServerAPI instance func (c *Client) Worlds() (worlds Worlds, err error) { - return worlds, c.json(fmt.Sprintf("%s/worlds", c.Endpoint), &worlds) + return worlds, c.jsonGET(fmt.Sprintf("%s/worlds", c.endpoint), &worlds) }