|
@@ -38,6 +38,7 @@ var (
|
|
|
ErrPruneDaysBounds = errors.New("the number of days should be more than or equal to 1")
|
|
|
ErrGuildNoIcon = errors.New("guild does not have an icon set")
|
|
|
ErrGuildNoSplash = errors.New("guild does not have a splash set")
|
|
|
+ ErrUnauthorized = errors.New("HTTP request was unauthorized. This could be because the provided token was not a bot token. Please add \"Bot \" to the start of your token. https://discordapp.com/developers/docs/reference#authentication-example-bot-token-authorization-header")
|
|
|
)
|
|
|
|
|
|
|
|
@@ -89,7 +90,7 @@ func (s *Session) RequestWithLockedBucket(method, urlStr, contentType string, b
|
|
|
|
|
|
req.Header.Set("Content-Type", contentType)
|
|
|
|
|
|
- req.Header.Set("User-Agent", fmt.Sprintf("DiscordBot (https://github.com/bwmarrin/discordgo, v%s)", VERSION))
|
|
|
+ req.Header.Set("User-Agent", "DiscordBot (https://github.com/bwmarrin/discordgo, v"+VERSION+")")
|
|
|
|
|
|
if s.Debug {
|
|
|
for k, v := range req.Header {
|
|
@@ -129,13 +130,9 @@ func (s *Session) RequestWithLockedBucket(method, urlStr, contentType string, b
|
|
|
}
|
|
|
|
|
|
switch resp.StatusCode {
|
|
|
-
|
|
|
case http.StatusOK:
|
|
|
case http.StatusCreated:
|
|
|
case http.StatusNoContent:
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
case http.StatusBadGateway:
|
|
|
|
|
|
if sequence < s.MaxRestRetries {
|
|
@@ -145,7 +142,6 @@ func (s *Session) RequestWithLockedBucket(method, urlStr, contentType string, b
|
|
|
} else {
|
|
|
err = fmt.Errorf("Exceeded Max retries HTTP %s, %s", resp.Status, response)
|
|
|
}
|
|
|
-
|
|
|
case 429:
|
|
|
rl := TooManyRequests{}
|
|
|
err = json.Unmarshal(response, &rl)
|
|
@@ -161,7 +157,12 @@ func (s *Session) RequestWithLockedBucket(method, urlStr, contentType string, b
|
|
|
|
|
|
|
|
|
response, err = s.RequestWithLockedBucket(method, urlStr, contentType, b, s.Ratelimiter.LockBucketObject(bucket), sequence)
|
|
|
-
|
|
|
+ case http.StatusUnauthorized:
|
|
|
+ if strings.Index(s.Token, "Bot ") != 0 {
|
|
|
+ s.log(LogInformational, ErrUnauthorized.Error())
|
|
|
+ err = ErrUnauthorized
|
|
|
+ }
|
|
|
+ fallthrough
|
|
|
default:
|
|
|
err = newRestError(req, resp, response)
|
|
|
}
|
|
@@ -249,7 +250,7 @@ func (s *Session) Register(username string) (token string, err error) {
|
|
|
|
|
|
func (s *Session) Logout() (err error) {
|
|
|
|
|
|
-
|
|
|
+
|
|
|
|
|
|
if s.Token == "" {
|
|
|
return
|
|
@@ -361,6 +362,21 @@ func (s *Session) UserUpdateStatus(status Status) (st *Settings, err error) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+func (s *Session) UserConnections() (conn []*UserConnection, err error) {
|
|
|
+ response, err := s.RequestWithBucketID("GET", EndpointUserConnections("@me"), nil, EndpointUserConnections("@me"))
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ err = unmarshal(response, &conn)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|
|
|
func (s *Session) UserChannels() (st []*Channel, err error) {
|
|
@@ -412,7 +428,7 @@ func (s *Session) UserGuilds(limit int, beforeID, afterID string) (st []*UserGui
|
|
|
uri := EndpointUserGuilds("@me")
|
|
|
|
|
|
if len(v) > 0 {
|
|
|
- uri = fmt.Sprintf("%s?%s", uri, v.Encode())
|
|
|
+ uri += "?" + v.Encode()
|
|
|
}
|
|
|
|
|
|
body, err := s.RequestWithBucketID("GET", uri, nil, EndpointUserGuilds(""))
|
|
@@ -565,7 +581,7 @@ func (s *Session) Guild(guildID string) (st *Guild, err error) {
|
|
|
if s.StateEnabled {
|
|
|
|
|
|
st, err = s.State.Guild(guildID)
|
|
|
- if err == nil {
|
|
|
+ if err == nil && !st.Unavailable {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
@@ -735,7 +751,7 @@ func (s *Session) GuildMembers(guildID string, after string, limit int) (st []*M
|
|
|
}
|
|
|
|
|
|
if len(v) > 0 {
|
|
|
- uri = fmt.Sprintf("%s?%s", uri, v.Encode())
|
|
|
+ uri += "?" + v.Encode()
|
|
|
}
|
|
|
|
|
|
body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildMembers(guildID))
|
|
@@ -761,6 +777,32 @@ func (s *Session) GuildMember(guildID, userID string) (st *Member, err error) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+func (s *Session) GuildMemberAdd(accessToken, guildID, userID, nick string, roles []string, mute, deaf bool) (err error) {
|
|
|
+
|
|
|
+ data := struct {
|
|
|
+ AccessToken string `json:"access_token"`
|
|
|
+ Nick string `json:"nick,omitempty"`
|
|
|
+ Roles []string `json:"roles,omitempty"`
|
|
|
+ Mute bool `json:"mute,omitempty"`
|
|
|
+ Deaf bool `json:"deaf,omitempty"`
|
|
|
+ }{accessToken, nick, roles, mute, deaf}
|
|
|
+
|
|
|
+ _, err = s.RequestWithBucketID("PUT", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""))
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ return err
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
@@ -877,17 +919,22 @@ func (s *Session) GuildChannels(guildID string) (st []*Channel, err error) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-func (s *Session) GuildChannelCreate(guildID, name, ctype string) (st *Channel, err error) {
|
|
|
-
|
|
|
- data := struct {
|
|
|
- Name string `json:"name"`
|
|
|
- Type string `json:"type"`
|
|
|
- }{name, ctype}
|
|
|
+
|
|
|
+type GuildChannelCreateData struct {
|
|
|
+ Name string `json:"name"`
|
|
|
+ Type ChannelType `json:"type"`
|
|
|
+ Topic string `json:"topic,omitempty"`
|
|
|
+ Bitrate int `json:"bitrate,omitempty"`
|
|
|
+ UserLimit int `json:"user_limit,omitempty"`
|
|
|
+ PermissionOverwrites []*PermissionOverwrite `json:"permission_overwrites,omitempty"`
|
|
|
+ ParentID string `json:"parent_id,omitempty"`
|
|
|
+ NSFW bool `json:"nsfw,omitempty"`
|
|
|
+}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+func (s *Session) GuildChannelCreateComplex(guildID string, data GuildChannelCreateData) (st *Channel, err error) {
|
|
|
body, err := s.RequestWithBucketID("POST", EndpointGuildChannels(guildID), data, EndpointGuildChannels(guildID))
|
|
|
if err != nil {
|
|
|
return
|
|
@@ -897,12 +944,33 @@ func (s *Session) GuildChannelCreate(guildID, name, ctype string) (st *Channel,
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+func (s *Session) GuildChannelCreate(guildID, name string, ctype ChannelType) (st *Channel, err error) {
|
|
|
+ return s.GuildChannelCreateComplex(guildID, GuildChannelCreateData{
|
|
|
+ Name: name,
|
|
|
+ Type: ctype,
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
|
func (s *Session) GuildChannelsReorder(guildID string, channels []*Channel) (err error) {
|
|
|
|
|
|
- _, err = s.RequestWithBucketID("PATCH", EndpointGuildChannels(guildID), channels, EndpointGuildChannels(guildID))
|
|
|
+ data := make([]struct {
|
|
|
+ ID string `json:"id"`
|
|
|
+ Position int `json:"position"`
|
|
|
+ }, len(channels))
|
|
|
+
|
|
|
+ for i, c := range channels {
|
|
|
+ data[i].ID = c.ID
|
|
|
+ data[i].Position = c.Position
|
|
|
+ }
|
|
|
+
|
|
|
+ _, err = s.RequestWithBucketID("PATCH", EndpointGuildChannels(guildID), data, EndpointGuildChannels(guildID))
|
|
|
return
|
|
|
}
|
|
|
|
|
@@ -1021,7 +1089,7 @@ func (s *Session) GuildPruneCount(guildID string, days uint32) (count uint32, er
|
|
|
Pruned uint32 `json:"pruned"`
|
|
|
}{}
|
|
|
|
|
|
- uri := EndpointGuildPrune(guildID) + fmt.Sprintf("?days=%d", days)
|
|
|
+ uri := EndpointGuildPrune(guildID) + "?days=" + strconv.FormatUint(uint64(days), 10)
|
|
|
body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildPrune(guildID))
|
|
|
if err != nil {
|
|
|
return
|
|
@@ -1075,7 +1143,7 @@ func (s *Session) GuildPrune(guildID string, days uint32) (count uint32, err err
|
|
|
|
|
|
|
|
|
|
|
|
-func (s *Session) GuildIntegrations(guildID string) (st []*GuildIntegration, err error) {
|
|
|
+func (s *Session) GuildIntegrations(guildID string) (st []*Integration, err error) {
|
|
|
|
|
|
body, err := s.RequestWithBucketID("GET", EndpointGuildIntegrations(guildID), nil, EndpointGuildIntegrations(guildID))
|
|
|
if err != nil {
|
|
@@ -1206,6 +1274,94 @@ func (s *Session) GuildEmbedEdit(guildID string, enabled bool, channelID string)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+func (s *Session) GuildAuditLog(guildID, userID, beforeID string, actionType, limit int) (st *GuildAuditLog, err error) {
|
|
|
+
|
|
|
+ uri := EndpointGuildAuditLogs(guildID)
|
|
|
+
|
|
|
+ v := url.Values{}
|
|
|
+ if userID != "" {
|
|
|
+ v.Set("user_id", userID)
|
|
|
+ }
|
|
|
+ if beforeID != "" {
|
|
|
+ v.Set("before", beforeID)
|
|
|
+ }
|
|
|
+ if actionType > 0 {
|
|
|
+ v.Set("action_type", strconv.Itoa(actionType))
|
|
|
+ }
|
|
|
+ if limit > 0 {
|
|
|
+ v.Set("limit", strconv.Itoa(limit))
|
|
|
+ }
|
|
|
+ if len(v) > 0 {
|
|
|
+ uri = fmt.Sprintf("%s?%s", uri, v.Encode())
|
|
|
+ }
|
|
|
+
|
|
|
+ body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildAuditLogs(guildID))
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ err = unmarshal(body, &st)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+func (s *Session) GuildEmojiCreate(guildID, name, image string, roles []string) (emoji *Emoji, err error) {
|
|
|
+
|
|
|
+ data := struct {
|
|
|
+ Name string `json:"name"`
|
|
|
+ Image string `json:"image"`
|
|
|
+ Roles []string `json:"roles,omitempty"`
|
|
|
+ }{name, image, roles}
|
|
|
+
|
|
|
+ body, err := s.RequestWithBucketID("POST", EndpointGuildEmojis(guildID), data, EndpointGuildEmojis(guildID))
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ err = unmarshal(body, &emoji)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+func (s *Session) GuildEmojiEdit(guildID, emojiID, name string, roles []string) (emoji *Emoji, err error) {
|
|
|
+
|
|
|
+ data := struct {
|
|
|
+ Name string `json:"name"`
|
|
|
+ Roles []string `json:"roles,omitempty"`
|
|
|
+ }{name, roles}
|
|
|
+
|
|
|
+ body, err := s.RequestWithBucketID("PATCH", EndpointGuildEmoji(guildID, emojiID), data, EndpointGuildEmojis(guildID))
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ err = unmarshal(body, &emoji)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+func (s *Session) GuildEmojiDelete(guildID, emojiID string) (err error) {
|
|
|
+
|
|
|
+ _, err = s.RequestWithBucketID("DELETE", EndpointGuildEmoji(guildID, emojiID), nil, EndpointGuildEmojis(guildID))
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
@@ -1291,7 +1447,7 @@ func (s *Session) ChannelMessages(channelID string, limit int, beforeID, afterID
|
|
|
v.Set("around", aroundID)
|
|
|
}
|
|
|
if len(v) > 0 {
|
|
|
- uri = fmt.Sprintf("%s?%s", uri, v.Encode())
|
|
|
+ uri += "?" + v.Encode()
|
|
|
}
|
|
|
|
|
|
body, err := s.RequestWithBucketID("GET", uri, nil, EndpointChannelMessages(channelID))
|
|
@@ -1586,7 +1742,8 @@ func (s *Session) ChannelInviteCreate(channelID string, i Invite) (st *Invite, e
|
|
|
MaxAge int `json:"max_age"`
|
|
|
MaxUses int `json:"max_uses"`
|
|
|
Temporary bool `json:"temporary"`
|
|
|
- }{i.MaxAge, i.MaxUses, i.Temporary}
|
|
|
+ Unique bool `json:"unique"`
|
|
|
+ }{i.MaxAge, i.MaxUses, i.Temporary, i.Unique}
|
|
|
|
|
|
body, err := s.RequestWithBucketID("POST", EndpointChannelInvites(channelID), data, EndpointChannelInvites(channelID))
|
|
|
if err != nil {
|
|
@@ -1638,6 +1795,19 @@ func (s *Session) Invite(inviteID string) (st *Invite, err error) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+func (s *Session) InviteWithCounts(inviteID string) (st *Invite, err error) {
|
|
|
+
|
|
|
+ body, err := s.RequestWithBucketID("GET", EndpointInvite(inviteID)+"?with_counts=true", nil, EndpointInvite(""))
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ err = unmarshal(body, &st)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|
|
|
func (s *Session) InviteDelete(inviteID string) (st *Invite, err error) {
|
|
@@ -1830,12 +2000,13 @@ func (s *Session) WebhookWithToken(webhookID, token string) (st *Webhook, err er
|
|
|
|
|
|
|
|
|
|
|
|
-func (s *Session) WebhookEdit(webhookID, name, avatar string) (st *Role, err error) {
|
|
|
+func (s *Session) WebhookEdit(webhookID, name, avatar, channelID string) (st *Role, err error) {
|
|
|
|
|
|
data := struct {
|
|
|
- Name string `json:"name,omitempty"`
|
|
|
- Avatar string `json:"avatar,omitempty"`
|
|
|
- }{name, avatar}
|
|
|
+ Name string `json:"name,omitempty"`
|
|
|
+ Avatar string `json:"avatar,omitempty"`
|
|
|
+ ChannelID string `json:"channel_id,omitempty"`
|
|
|
+ }{name, avatar, channelID}
|
|
|
|
|
|
body, err := s.RequestWithBucketID("PATCH", EndpointWebhook(webhookID), data, EndpointWebhooks)
|
|
|
if err != nil {
|
|
@@ -1965,7 +2136,7 @@ func (s *Session) MessageReactions(channelID, messageID, emojiID string, limit i
|
|
|
}
|
|
|
|
|
|
if len(v) > 0 {
|
|
|
- uri = fmt.Sprintf("%s?%s", uri, v.Encode())
|
|
|
+ uri += "?" + v.Encode()
|
|
|
}
|
|
|
|
|
|
body, err := s.RequestWithBucketID("GET", uri, nil, EndpointMessageReaction(channelID, "", "", ""))
|