home to your local SPACEGIRL 馃挮 arimelody.space
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at dev 108 lines 3.7 kB view raw
1package discord 2 3import ( 4 "arimelody-web/model" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "net/http" 9 "net/url" 10 "strings" 11) 12 13const API_ENDPOINT = "https://discord.com/api/v10" 14 15type ( 16 AccessTokenResponse struct { 17 AccessToken string `json:"access_token"` 18 TokenType string `json:"token_type"` 19 ExpiresIn int `json:"expires_in"` 20 RefreshToken string `json:"refresh_token"` 21 Scope string `json:"scope"` 22 } 23 24 AuthInfoResponse struct { 25 Application struct { 26 ID string `json:"id"` 27 Name string `json:"name"` 28 Icon string `json:"icon"` 29 Description string `json:"description"` 30 Hook bool `json:"hook"` 31 BotPublic bool `json:"bot_public"` 32 BotRequireCodeGrant bool `json:"bot_require_code_grant"` 33 VerifyKey string `json:"verify_key"` 34 } `json:"application"` 35 Scopes []string `json:"scopes"` 36 Expires string `json:"expires"` 37 User DiscordUser `json:"user"` 38 } 39 40 DiscordUser struct { 41 ID string `json:"id"` 42 Username string `json:"username"` 43 Avatar string `json:"avatar"` 44 Discriminator string `json:"discriminator"` 45 GlobalName string `json:"global_name"` 46 PublicFlags int `json:"public_flags"` 47 } 48) 49 50func GetOAuthTokenFromCode(app *model.AppState, code string) (string, error) { 51 // let's get an oauth token! 52 req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/oauth2/token", API_ENDPOINT), 53 strings.NewReader(url.Values{ 54 "client_id": {app.Config.Discord.ClientID}, 55 "client_secret": {app.Config.Discord.Secret}, 56 "grant_type": {"authorization_code"}, 57 "code": {code}, 58 "redirect_uri": {GetOAuthCallbackURI(app.Config.BaseUrl)}, 59 }.Encode())) 60 req.Header.Add("Content-Type", "application/x-www-form-urlencoded") 61 62 res, err := http.DefaultClient.Do(req) 63 if err != nil { 64 return "", errors.New(fmt.Sprintf("Failed while contacting discord API: %s", err)) 65 } 66 67 oauth := AccessTokenResponse{} 68 69 err = json.NewDecoder(res.Body).Decode(&oauth) 70 if err != nil { 71 return "", errors.New(fmt.Sprintf("Failed to parse OAuth response data from discord: %s\n", err)) 72 } 73 res.Body.Close() 74 75 return oauth.AccessToken, nil 76} 77 78func GetDiscordUserFromAuth(token string) (DiscordUser, error) { 79 // let's get authorisation information! 80 req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/oauth2/@me", API_ENDPOINT), nil) 81 req.Header.Add("Authorization", "Bearer " + token) 82 83 res, err := http.DefaultClient.Do(req) 84 if err != nil { 85 return DiscordUser{}, errors.New(fmt.Sprintf("Failed to retrieve discord auth information: %s\n", err)) 86 } 87 88 auth_info := AuthInfoResponse{} 89 err = json.NewDecoder(res.Body).Decode(&auth_info) 90 if err != nil { 91 return DiscordUser{}, errors.New(fmt.Sprintf("Failed to parse auth information from discord: %s\n", err)) 92 } 93 defer res.Body.Close() 94 95 return auth_info.User, nil 96} 97 98func GetOAuthCallbackURI(baseURL string) string { 99 return fmt.Sprintf("%s/admin/login", baseURL) 100} 101 102func GetRedirectURI(app *model.AppState) string { 103 return fmt.Sprintf( 104 "https://discord.com/oauth2/authorize?client_id=%s&response_type=code&redirect_uri=%s&scope=identify", 105 app.Config.Discord.ClientID, 106 GetOAuthCallbackURI(app.Config.BaseUrl), 107 ) 108}