package rest import ( "bytes" "encoding/json" "errors" "jinx/pkg/discord/entities" "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 entities.Snowflake, content string) error } var _ REST = &RESTImpl{} type RESTImpl struct { token string client *http.Client } func New(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 entities.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 }