)",
134 | sponsorUserLink,
135 | oldPriceInDollar,
136 | oldSponsorType,
137 | priceInDollar,
138 | sponsorType,
139 | date.Unix(),
140 | date.Unix(),
141 | )
142 | default:
143 | w.WriteHeader(200)
144 | fprintln(w, "Ok")
145 | return
146 | }
147 |
148 | succeeded := sendWebhook(message)
149 | if !succeeded {
150 | w.WriteHeader(http.StatusBadGateway)
151 | fprintln(w, "Failed to execute webhook")
152 | }
153 |
154 | w.WriteHeader(http.StatusOK)
155 | fprintln(w, "Ok")
156 | }
157 |
158 | func verifySignature(message []byte, messageMAC string) bool {
159 | mac := hmac.New(sha256.New, Secret)
160 | mac.Write(message)
161 | expectedMAC := "sha256=" + hex.EncodeToString(mac.Sum(nil))
162 | return hmac.Equal([]byte(messageMAC), []byte(expectedMAC))
163 | }
164 |
165 | func main() {
166 | http.Handle("/", http.FileServer(http.Dir("./static")))
167 | http.HandleFunc("/webhook", handleWebhook)
168 |
169 | fmt.Println("Listening on port", Port)
170 | panic(http.ListenAndServe(":"+Port, nil))
171 | }
172 |
--------------------------------------------------------------------------------
/sponsors-webhook.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=
3 |
4 | [Service]
5 | Type=exec
6 | Restart=always
7 | ExecStartPre=go build
8 | ExecStart=%h/SponsorsWebhook/sponsors-webhook
9 | WorkingDirectory=%h/SponsorsWebhook
10 | EnvironmentFile=%h/SponsorsWebhook/.env
11 |
12 | [Install]
13 | WantedBy=default.target
--------------------------------------------------------------------------------
/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | GitHub Sponsor Webhook
4 |
5 | https://github.com/Vendicated/SponsorsWebhook
--------------------------------------------------------------------------------
/types.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | const (
4 | ActionTypeCreated = "created"
5 | ActionTypeCancelled = "cancelled"
6 | ActionTypePendingCancellation = "pending_cancellation"
7 | ActionTypePendingTierChange = "pending_tier_change"
8 | ActionTypeTierChanged = "tier_changed"
9 | )
10 |
11 | type Tier struct {
12 | IsOneTime bool `json:"is_one_time"`
13 | MonthlyPriceInDollars int `json:"monthly_price_in_dollars"`
14 | }
15 |
16 | type SponsorShipEvent struct {
17 | Action string `json:"action"`
18 | Sponsorship struct {
19 | PrivacyLevel string `json:"privacy_level"`
20 | Sponsor struct {
21 | AvatarUrl string `json:"avatar_url"`
22 | HtmlUrl string `json:"html_url"`
23 | UserName string `json:"login"`
24 | } `json:"sponsor"`
25 | Tier Tier `json:"tier"`
26 | } `json:"sponsorship"`
27 | EffectiveDate string `json:"effective_date"`
28 | Changes struct {
29 | Tier struct {
30 | From Tier `json:"from"`
31 | } `json:"tier"`
32 | } `json:"changes"`
33 | }
34 |
35 | type DiscordWebhookPayload struct {
36 | Content string `json:"content"`
37 | AvatarUrl string `json:"avatar_url,omitempty"`
38 | Username string `json:"username,omitempty"`
39 | AllowedMentions struct {
40 | Parse []string `json:"parse"`
41 | } `json:"allowed_mentions"`
42 | }
43 |
--------------------------------------------------------------------------------