Add POST options

Signed-off-by: Etzelia <etzelia@hotmail.com>
master
Etzelia 2020-10-05 22:21:20 -05:00
parent 4069709a59
commit f9037f9598
No known key found for this signature in database
GPG Key ID: 708511AE7ABC5314
9 changed files with 143 additions and 49 deletions

51
ban.go
View File

@ -5,13 +5,28 @@ import (
"time" "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 // Ban is a Minecraft ban
type Ban struct { type Ban struct {
Target string `json:"target"` Kick
Source string `jso:"source"` Source string `json:"source"`
Reason string `json:"reason"` Created int64 `json:"created"`
Created int64 `json:"created"` }
Expiration int64 `json:"expiration"`
// Ban is a Minecraft ban with an expiration
type TempBan struct {
Ban
Expiration int64 `json:"expiration"`
} }
// CreatedTime is Created converted to a time.Time // 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 // ExpirationTime is Expiration converted to a time.Time
func (b *Ban) ExpirationTime() time.Time { func (t *TempBan) ExpirationTime() time.Time {
return time.Unix(b.Expiration/1000, 0) return time.Unix(t.Expiration/1000, 0)
} }
// Bans gets a list of Ban from a ServerAPI instance // Bans gets a list of Ban from a ServerAPI instance
func (c *Client) Bans() (bans Ban, err error) { 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)
} }

View File

@ -1,6 +1,7 @@
package serverapi package serverapi
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -10,49 +11,53 @@ import (
// Client is a client aimed at a specific ServerAPI endpoint // Client is a client aimed at a specific ServerAPI endpoint
type Client struct { type Client struct {
Endpoint string endpoint string
Options *ClientOptions http *http.Client
token string
} }
// ClientOptions are options that can be set for a Client // ClientOption is options for a Client
type ClientOptions struct { type ClientOption func(c *Client)
HTTP *http.Client
Password string 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 // NewClient returns a new Client for making ServerAPI requests
func NewClient(endpoint string, options *ClientOptions) *Client { func NewClient(endpoint string, opts ...ClientOption) *Client {
if options == nil {
options = DefaultOptions
}
endpoint = strings.TrimSuffix(endpoint, "/") endpoint = strings.TrimSuffix(endpoint, "/")
return &Client{ c := &Client{
Endpoint: endpoint, endpoint: endpoint,
Options: options, 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 { // WithToken is a ClientOption for setting the token of a Client
req, err := http.NewRequest(http.MethodGet, endpoint, nil) func WithToken(token string) ClientOption {
if err != nil { return func(c *Client) {
return fmt.Errorf("new JSON request: %v", err) 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 { if err != nil {
return fmt.Errorf("sending request: %v", err) 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) 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
}

25
custom.go 100644
View File

@ -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)
}

View File

@ -25,14 +25,14 @@ type Worlds []*World
// GraphQL returns a gql.Client for a ServerAPI instance // GraphQL returns a gql.Client for a ServerAPI instance
func (c *Client) GraphQL() *gql.Client { func (c *Client) GraphQL() *gql.Client {
return gql.NewClient(fmt.Sprintf("%s/graphql", c.Endpoint), &gql.ClientOptions{ return gql.NewClient(fmt.Sprintf("%s/graphql", c.endpoint), &gql.ClientOptions{
HTTP: c.Options.HTTP, HTTP: c.http,
}) })
} }
// GraphQLRequest returns a pre-filled gql.Request with the password set // GraphQLRequest returns a pre-filled gql.Request with the password set
func (c *Client) GraphQLRequest(query string) *gql.Request { func (c *Client) GraphQLRequest(query string) *gql.Request {
req := gql.NewRequest(query) req := gql.NewRequest(query)
req.Header.Add("X-ServerAPI-Password", c.Options.Password) req.Header.Add("X-ServerAPI-Token", c.token)
return req return req
} }

View File

@ -13,5 +13,5 @@ type Ping struct {
// Ping returns a Ping // Ping returns a Ping
func (c *Client) Ping() (ping *Ping, err error) { 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)
} }

View File

@ -10,5 +10,5 @@ type Player struct {
// Players returns a list of Player from a ServerAPI instance // Players returns a list of Player from a ServerAPI instance
func (c *Client) Players() (players Players, err error) { 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)
} }

View File

@ -12,5 +12,5 @@ type Plugin struct {
// Plugins returns a list of Plugin from a ServerAPI instance // Plugins returns a list of Plugin from a ServerAPI instance
func (c *Client) Plugins() (plugins Plugins, err error) { 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)
} }

2
tps.go
View File

@ -10,5 +10,5 @@ type TPS struct {
// TPS returns TPS from a ServerAPI instance // TPS returns TPS from a ServerAPI instance
func (c *Client) TPS() (tps *TPS, err error) { 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)
} }

View File

@ -48,10 +48,10 @@ func (w *World) FullTimeHours() int64 {
// World returns a single World from a ServerAPI instance // World returns a single World from a ServerAPI instance
func (c *Client) World(name string) (world *World, err error) { 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 // Worlds returns a list of World from a ServerAPI instance
func (c *Client) Worlds() (worlds Worlds, err error) { 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)
} }