-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdiscord_webhook.go
137 lines (124 loc) · 3.76 KB
/
discord_webhook.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
134
135
136
137
package discord
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"strconv"
"strings"
"time"
)
// Returns a timestamp for the footer according to Discord's format (ISO8601)
func GetTimestamp() string {
return time.Now().UTC().Format("2006-01-02T15:04:05-0700")
}
// Transforms hex to decimal (required for webhooks)
func GetColor(hexColor string) int {
hexColor = strings.Replace(hexColor, "#", "", -1)
decimalColor, err := strconv.ParseInt(hexColor, 16, 64)
if err != nil {
return 0
}
return int(decimalColor)
}
type Webhook struct {
Content string `json:"content,omitempty"`
Username string `json:"username,omitempty"`
AvatarUrl string `json:"avatar_url,omitempty"`
Tts bool `json:"tts,omitempty"`
Embeds []Embed `json:"embeds,omitempty"`
}
type Embed struct {
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
Url string `json:"url,omitempty"`
Timestamp string `json:"timestamp,omitempty"`
Color int `json:"color,omitempty"`
Footer EmbedFooter `json:"footer,omitempty"`
Image EmbedImage `json:"image,omitempty"`
Thumbnail EmbedThumbnail `json:"thumbnail,omitempty"`
Video EmbedVideo `json:"video,omitempty"`
Provider EmbedProvider `json:"provider,omitempty"`
Author EmbedAuthor `json:"author,omitempty"`
Fields []EmbedFields `json:"fields,omitempty"`
}
type EmbedFooter struct {
Text string `json:"text,omitempty"`
IconUrl string `json:"icon_url,omitempty"`
ProxyIconUrl string `json:"proxy_icon_url,omitempty"`
}
type EmbedImage struct {
Url string `json:"url,omitempty"`
ProxyUrl string `json:"proxy_url,omitempty"`
Height int `json:"height,omitempty"`
Width int `json:"width,omitempty"`
}
type EmbedThumbnail struct {
Url string `json:"url,omitempty"`
ProxyUrl string `json:"proxy_url,omitempty"`
Height int `json:"height,omitempty"`
Width int `json:"width,omitempty"`
}
type EmbedVideo struct {
Url string `json:"url,omitempty"`
ProxyUrl string `json:"proxy_url,omitempty"`
Height int `json:"height,omitempty"`
Width int `json:"width,omitempty"`
}
type EmbedProvider struct {
Name string `json:"name,omitempty"`
Url string `json:"url,omitempty"`
}
type EmbedAuthor struct {
Name string `json:"name,omitempty"`
Url string `json:"url,omitempty"`
IconUrl string `json:"icon_url,omitempty"`
ProxyIconUrl string `json:"proxy_icon_url,omitempty"`
}
type EmbedFields struct {
Name string `json:"name,omitempty"`
Value string `json:"value,omitempty"`
Inline bool `json:"inline,omitempty"`
}
// Execute the webhook request
func SendWebhook(webookUrl string, client *http.Client, webhook *Webhook, retryOnRateLimit bool) error {
if webhook == nil {
return errors.New("webhook is nil")
}
if webhook.Content == "" && len(webhook.Embeds) == 0 {
return errors.New("You must attach atleast one of these: Content; Embeds")
}
if len(webhook.Embeds) > 10 {
return errors.New("Maximum number of embeds per webhook is 10")
}
jsonData, err := json.Marshal(webhook)
if err != nil {
return err
}
for {
res, err := client.Post(webookUrl, "application/json", bytes.NewBuffer(jsonData))
if err != nil {
return err
}
switch res.StatusCode {
case 204:
res.Body.Close()
return nil
case 429:
res.Body.Close()
if !retryOnRateLimit {
return errors.New("Webhook ratelimited")
}
timeout, err := strconv.Atoi(res.Header.Get("retry-after"))
if err != nil {
time.Sleep(5 * time.Second)
} else {
time.Sleep(time.Duration(timeout) * time.Millisecond)
}
default:
res.Body.Close()
return errors.New(fmt.Sprintf("Bad request (Status %d)", res.StatusCode))
}
}
}