package client import ( "encoding/json" "errors" "fmt" "io" "net/http" "net/url" "strings" "time" "stereo.cat/backend/internal/auth" ) type Client struct { RedirectUri string ClientSecret string ClientId string } const api = "https://discord.com/api/v10" func New(redirectUri, clientId, clientSecret string) Client { return Client{ RedirectUri: redirectUri, ClientId: clientId, ClientSecret: clientSecret, } } func (c Client) GetUser(t auth.TokenResponse) (auth.User, error) { user := auth.User{ Blacklisted: false, CreatedAt: time.Now(), } req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/%s", api, "users/@me"), nil) if err != nil { return user, nil } req.Header.Add("Content-Type", "application/json") req.Header.Add("Authorization", "Bearer "+t.AccessToken) resp, err := http.DefaultClient.Do(req) if resp.StatusCode != http.StatusOK { bodyBytes, err := io.ReadAll(resp.Body) if err != nil { return user, err } return user, errors.New(string(bodyBytes)) } if err != nil { return user, err } defer resp.Body.Close() err = json.NewDecoder(resp.Body).Decode(&user) if err != nil { return user, err } return user, nil } func (c Client) ExchangeCode(code string) (auth.TokenResponse, error) { var tokenResponse auth.TokenResponse requestBody := url.Values{ "grant_type": {"authorization_code"}, "code": {code}, "redirect_uri": {c.RedirectUri}, } req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/%s", api, "/oauth2/token"), strings.NewReader(requestBody.Encode())) if err != nil { return tokenResponse, err } req.Header.Add("Content-Type", "application/x-www-form-urlencoded") req.SetBasicAuth(c.ClientId, c.ClientSecret) resp, err := http.DefaultClient.Do(req) if resp.StatusCode != http.StatusOK { bodyBytes, err := io.ReadAll(resp.Body) if err != nil { return tokenResponse, err } return tokenResponse, errors.New(string(bodyBytes)) } if err != nil { return tokenResponse, err } defer resp.Body.Close() err = json.NewDecoder(resp.Body).Decode(&tokenResponse) if err != nil { return tokenResponse, err } return tokenResponse, nil }