about summary refs log tree commit diff
path: root/pkg/discord/rest.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/discord/rest.go')
-rw-r--r--pkg/discord/rest.go111
1 files changed, 111 insertions, 0 deletions
diff --git a/pkg/discord/rest.go b/pkg/discord/rest.go
new file mode 100644
index 0000000..438d8d1
--- /dev/null
+++ b/pkg/discord/rest.go
@@ -0,0 +1,111 @@
+package discord
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"net/http"
+	"time"
+)
+
+const DISCORD_URl = "https://discord.com/api/v9/"
+const USER_AGENT = "DiscordBot (https://jinx.rnrd.eu/, v0.0.0) Jinx"
+
+type REST interface {
+	Gateway() (string, error)
+
+	SendMessage(channelID Snowflake, content string) error
+}
+
+var _ REST = &RESTImpl{}
+
+type RESTImpl struct {
+	token  string
+	client *http.Client
+}
+
+func NewREST(token string) *RESTImpl {
+	return &RESTImpl{
+		token: token,
+		client: &http.Client{
+			Timeout: time.Second * 5,
+		},
+	}
+}
+
+func (r *RESTImpl) Gateway() (string, error) {
+	type gatewayResponse struct {
+		URL string `json:"url"`
+	}
+
+	res, err := request[gatewayResponse](r, "GET", url("gateway"), nil)
+	if err != nil {
+		return "", err
+	}
+
+	return res.URL + "?v=9&encoding=json", nil
+}
+
+func (r *RESTImpl) SendMessage(channelID Snowflake, content string) error {
+	msg := struct {
+		Content string `json:"content"`
+	}{
+		Content: content,
+	}
+
+	_, err := request[any](r, "POST", url("channels/"+string(channelID)+"/messages"), msg)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func request[D any](r *RESTImpl, method string, url string, data any) (*D, error) {
+	var raw []byte
+	if data != nil {
+		var err error
+		raw, err = json.Marshal(data)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	req, err := http.NewRequest(method, url, bytes.NewBuffer(raw))
+	if err != nil {
+		return nil, err
+	}
+
+	req.Header.Set("Authorization", r.token)
+	req.Header.Set("Content-Type", "application/json")
+	req.Header.Set("User-Agent", USER_AGENT)
+
+	resp, err := r.client.Do(req)
+	if err != nil {
+		return nil, err
+	}
+
+	defer resp.Body.Close()
+
+	switch resp.StatusCode {
+	case 200:
+	default:
+		return nil, errors.New("unexpected status code: " + resp.Status)
+	}
+
+	var buf bytes.Buffer
+	if _, err = buf.ReadFrom(resp.Body); err != nil {
+		return nil, err
+	}
+
+	var res D
+	if err = json.Unmarshal(buf.Bytes(), &res); err != nil {
+		return nil, err
+	}
+
+	return &res, nil
+}
+
+func url(path string) string {
+	return DISCORD_URl + path
+}