/
main.go
133 lines (119 loc) · 4 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package main
import (
"encoding/json"
"flag"
"fmt"
"net/http"
"net/url"
"github.com/bg5t/mydiscordgo"
"github.com/joho/godotenv"
"golang.org/x/oauth2"
)
var oauthConfig = oauth2.Config{
Endpoint: oauth2.Endpoint{
AuthURL: "https://discord.com/oauth2/authorize",
TokenURL: "https://discord.com/api/oauth2/token",
},
Scopes: []string{"identify", "role_connections.write"},
}
var (
appID = flag.String("app", "", "Application ID")
token = flag.String("token", "", "Application token")
clientSecret = flag.String("secret", "", "OAuth2 secret")
redirectURL = flag.String("redirect", "", "OAuth2 Redirect URL")
)
func init() {
flag.Parse()
godotenv.Load()
oauthConfig.ClientID = *appID
oauthConfig.ClientSecret = *clientSecret
oauthConfig.RedirectURL, _ = url.JoinPath(*redirectURL, "/linked-roles-callback")
}
func main() {
s, _ := discordgo.New("Bot " + *token)
_, err := s.ApplicationRoleConnectionMetadataUpdate(*appID, []*discordgo.ApplicationRoleConnectionMetadata{
{
Type: discordgo.ApplicationRoleConnectionMetadataIntegerGreaterThanOrEqual,
Key: "loc",
Name: "Lines of Code",
NameLocalizations: map[discordgo.Locale]string{},
Description: "Total lines of code written",
DescriptionLocalizations: map[discordgo.Locale]string{},
},
{
Type: discordgo.ApplicationRoleConnectionMetadataBooleanEqual,
Key: "gopher",
Name: "Gopher",
NameLocalizations: map[discordgo.Locale]string{},
Description: "Writes in Go",
DescriptionLocalizations: map[discordgo.Locale]string{},
},
{
Type: discordgo.ApplicationRoleConnectionMetadataDatetimeGreaterThanOrEqual,
Key: "first_line",
Name: "First line written",
NameLocalizations: map[discordgo.Locale]string{},
Description: "Days since the first line of code",
DescriptionLocalizations: map[discordgo.Locale]string{},
},
})
if err != nil {
panic(err)
}
fmt.Println("Updated application metadata")
http.HandleFunc("/linked-roles", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "no-cache")
// Redirect the user to Discord OAuth2 page.
http.Redirect(w, r, oauthConfig.AuthCodeURL("random-state"), http.StatusMovedPermanently)
})
http.HandleFunc("/linked-roles-callback", func(w http.ResponseWriter, r *http.Request) {
q := r.URL.Query()
// A safeguard against CSRF attacks.
// Usually tied to requesting user or random.
// NOTE: Hardcoded for the sake of the example.
if q["state"][0] != "random-state" {
return
}
// Fetch the tokens with code we've received.
tokens, err := oauthConfig.Exchange(r.Context(), q["code"][0])
if err != nil {
w.Write([]byte(err.Error()))
return
}
// Construct a temporary session with user's OAuth2 access_token.
ts, _ := discordgo.New("Bearer " + tokens.AccessToken)
// Retrive the user data.
u, err := ts.User("@me")
if err != nil {
w.Write([]byte(err.Error()))
return
}
// Fetch external metadata...
// NOTE: Hardcoded for the sake of the example.
metadata := map[string]string{
"gopher": "1", // 1 for true, 0 for false
"loc": "10000",
"first_line": "1970-01-01", // YYYY-MM-DD
}
// And submit it back to discord.
_, err = ts.UserApplicationRoleConnectionUpdate(*appID, &discordgo.ApplicationRoleConnection{
PlatformName: "Discord Gophers",
PlatformUsername: u.Username,
Metadata: metadata,
})
if err != nil {
w.Write([]byte(err.Error()))
return
}
// Retrieve it to check if everything is ok.
info, err := ts.UserApplicationRoleConnection(*appID)
if err != nil {
w.Write([]byte(err.Error()))
return
}
jsonMetadata, _ := json.Marshal(info.Metadata)
// And show it to the user.
w.Write([]byte(fmt.Sprintf("Your updated metadata is: %s", jsonMetadata)))
})
http.ListenAndServe(":8010", nil)
}