Merge branch 'develop' of https://github.com/bwmarrin/discordgo into develop

This commit is contained in:
Bruce Marriner 2018-08-27 15:36:04 +00:00
commit 10be6053b9
10 changed files with 57 additions and 21 deletions

View file

@ -136,7 +136,8 @@ var (
EndpointIntegrationsJoin = func(iID string) string { return EndpointAPI + "integrations/" + iID + "/join" } EndpointIntegrationsJoin = func(iID string) string { return EndpointAPI + "integrations/" + iID + "/join" }
EndpointEmoji = func(eID string) string { return EndpointAPI + "emojis/" + eID + ".png" } EndpointEmoji = func(eID string) string { return EndpointAPI + "emojis/" + eID + ".png" }
EndpointEmojiAnimated = func(eID string) string { return EndpointAPI + "emojis/" + eID + ".gif" }
EndpointOauth2 = EndpointAPI + "oauth2/" EndpointOauth2 = EndpointAPI + "oauth2/"
EndpointApplications = EndpointOauth2 + "applications" EndpointApplications = EndpointOauth2 + "applications"

View file

@ -50,6 +50,7 @@ const (
userUpdateEventType = "USER_UPDATE" userUpdateEventType = "USER_UPDATE"
voiceServerUpdateEventType = "VOICE_SERVER_UPDATE" voiceServerUpdateEventType = "VOICE_SERVER_UPDATE"
voiceStateUpdateEventType = "VOICE_STATE_UPDATE" voiceStateUpdateEventType = "VOICE_STATE_UPDATE"
webhooksUpdateEventType = "WEBHOOKS_UPDATE"
) )
// channelCreateEventHandler is an event handler for ChannelCreate events. // channelCreateEventHandler is an event handler for ChannelCreate events.
@ -892,6 +893,26 @@ func (eh voiceStateUpdateEventHandler) Handle(s *Session, i interface{}) {
} }
} }
// webhooksUpdateEventHandler is an event handler for WebhooksUpdate events.
type webhooksUpdateEventHandler func(*Session, *WebhooksUpdate)
// Type returns the event type for WebhooksUpdate events.
func (eh webhooksUpdateEventHandler) Type() string {
return webhooksUpdateEventType
}
// New returns a new instance of WebhooksUpdate.
func (eh webhooksUpdateEventHandler) New() interface{} {
return &WebhooksUpdate{}
}
// Handle is the handler for WebhooksUpdate events.
func (eh webhooksUpdateEventHandler) Handle(s *Session, i interface{}) {
if t, ok := i.(*WebhooksUpdate); ok {
eh(s, t)
}
}
func handlerForInterface(handler interface{}) EventHandler { func handlerForInterface(handler interface{}) EventHandler {
switch v := handler.(type) { switch v := handler.(type) {
case func(*Session, interface{}): case func(*Session, interface{}):
@ -982,6 +1003,8 @@ func handlerForInterface(handler interface{}) EventHandler {
return voiceServerUpdateEventHandler(v) return voiceServerUpdateEventHandler(v)
case func(*Session, *VoiceStateUpdate): case func(*Session, *VoiceStateUpdate):
return voiceStateUpdateEventHandler(v) return voiceStateUpdateEventHandler(v)
case func(*Session, *WebhooksUpdate):
return webhooksUpdateEventHandler(v)
} }
return nil return nil
@ -1027,4 +1050,5 @@ func init() {
registerInterfaceProvider(userUpdateEventHandler(nil)) registerInterfaceProvider(userUpdateEventHandler(nil))
registerInterfaceProvider(voiceServerUpdateEventHandler(nil)) registerInterfaceProvider(voiceServerUpdateEventHandler(nil))
registerInterfaceProvider(voiceStateUpdateEventHandler(nil)) registerInterfaceProvider(voiceStateUpdateEventHandler(nil))
registerInterfaceProvider(webhooksUpdateEventHandler(nil))
} }

View file

@ -254,3 +254,9 @@ type MessageDeleteBulk struct {
ChannelID string `json:"channel_id"` ChannelID string `json:"channel_id"`
GuildID string `json:"guild_id"` GuildID string `json:"guild_id"`
} }
// WebhooksUpdate is the data for a WebhooksUpdate event
type WebhooksUpdate struct {
GuildID string `json:"guild_id"`
ChannelID string `json:"channel_id"`
}

View file

@ -12,7 +12,6 @@ func TestContentWithMoreMentionsReplaced(t *testing.T) {
Username: "User Name", Username: "User Name",
} }
s.StateEnabled = true
s.State.GuildAdd(&Guild{ID: "guild"}) s.State.GuildAdd(&Guild{ID: "guild"})
s.State.RoleAdd("guild", &Role{ s.State.RoleAdd("guild", &Role{
ID: "role", ID: "role",

View file

@ -90,7 +90,7 @@ func (s *Session) RequestWithLockedBucket(method, urlStr, contentType string, b
req.Header.Set("Content-Type", contentType) req.Header.Set("Content-Type", contentType)
// TODO: Make a configurable static variable. // TODO: Make a configurable static variable.
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 { if s.Debug {
for k, v := range req.Header { for k, v := range req.Header {
@ -250,7 +250,7 @@ func (s *Session) Register(username string) (token string, err error) {
// even use. // even use.
func (s *Session) Logout() (err error) { func (s *Session) Logout() (err error) {
// _, err = s.Request("POST", LOGOUT, fmt.Sprintf(`{"token": "%s"}`, s.Token)) // _, err = s.Request("POST", LOGOUT, `{"token": "` + s.Token + `"}`)
if s.Token == "" { if s.Token == "" {
return return
@ -428,7 +428,7 @@ func (s *Session) UserGuilds(limit int, beforeID, afterID string) (st []*UserGui
uri := EndpointUserGuilds("@me") uri := EndpointUserGuilds("@me")
if len(v) > 0 { if len(v) > 0 {
uri = fmt.Sprintf("%s?%s", uri, v.Encode()) uri += "?" + v.Encode()
} }
body, err := s.RequestWithBucketID("GET", uri, nil, EndpointUserGuilds("")) body, err := s.RequestWithBucketID("GET", uri, nil, EndpointUserGuilds(""))
@ -743,7 +743,7 @@ func (s *Session) GuildMembers(guildID string, after string, limit int) (st []*M
} }
if len(v) > 0 { if len(v) > 0 {
uri = fmt.Sprintf("%s?%s", uri, v.Encode()) uri += "?" + v.Encode()
} }
body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildMembers(guildID)) body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildMembers(guildID))
@ -1065,7 +1065,7 @@ func (s *Session) GuildPruneCount(guildID string, days uint32) (count uint32, er
Pruned uint32 `json:"pruned"` 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)) body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildPrune(guildID))
if err != nil { if err != nil {
return return
@ -1423,7 +1423,7 @@ func (s *Session) ChannelMessages(channelID string, limit int, beforeID, afterID
v.Set("around", aroundID) v.Set("around", aroundID)
} }
if len(v) > 0 { if len(v) > 0 {
uri = fmt.Sprintf("%s?%s", uri, v.Encode()) uri += "?" + v.Encode()
} }
body, err := s.RequestWithBucketID("GET", uri, nil, EndpointChannelMessages(channelID)) body, err := s.RequestWithBucketID("GET", uri, nil, EndpointChannelMessages(channelID))
@ -2103,7 +2103,7 @@ func (s *Session) MessageReactions(channelID, messageID, emojiID string, limit i
} }
if len(v) > 0 { if len(v) > 0 {
uri = fmt.Sprintf("%s?%s", uri, v.Encode()) uri += "?" + v.Encode()
} }
body, err := s.RequestWithBucketID("GET", uri, nil, EndpointMessageReaction(channelID, "", "", "")) body, err := s.RequestWithBucketID("GET", uri, nil, EndpointMessageReaction(channelID, "", "", ""))

View file

@ -597,7 +597,7 @@ type Member struct {
GuildID string `json:"guild_id"` GuildID string `json:"guild_id"`
// The time at which the member joined the guild, in ISO8601. // The time at which the member joined the guild, in ISO8601.
JoinedAt string `json:"joined_at"` JoinedAt Timestamp `json:"joined_at"`
// The nickname of the member, if they have one. // The nickname of the member, if they have one.
Nick string `json:"nick"` Nick string `json:"nick"`
@ -615,6 +615,11 @@ type Member struct {
Roles []string `json:"roles"` Roles []string `json:"roles"`
} }
// Mention creates a member mention
func (m *Member) Mention() string {
return "<@!" + m.User.ID + ">"
}
// A Settings stores data for a specific users Discord client settings. // A Settings stores data for a specific users Discord client settings.
type Settings struct { type Settings struct {
RenderEmbeds bool `json:"render_embeds"` RenderEmbeds bool `json:"render_embeds"`
@ -929,6 +934,7 @@ const (
ErrCodeUnknownToken = 10012 ErrCodeUnknownToken = 10012
ErrCodeUnknownUser = 10013 ErrCodeUnknownUser = 10013
ErrCodeUnknownEmoji = 10014 ErrCodeUnknownEmoji = 10014
ErrCodeUnknownWebhook = 10015
ErrCodeBotsCannotUseEndpoint = 20001 ErrCodeBotsCannotUseEndpoint = 20001
ErrCodeOnlyBotsCanUseEndpoint = 20002 ErrCodeOnlyBotsCanUseEndpoint = 20002

View file

@ -11,7 +11,6 @@ package discordgo
import ( import (
"encoding/json" "encoding/json"
"fmt"
"net/http" "net/http"
"time" "time"
) )
@ -54,5 +53,5 @@ func newRestError(req *http.Request, resp *http.Response, body []byte) *RESTErro
} }
func (r RESTError) Error() string { func (r RESTError) Error() string {
return fmt.Sprintf("HTTP %s, %s", r.Response.Status, r.ResponseBody) return "HTTP " + r.Response.Status + ", " + string(r.ResponseBody)
} }

View file

@ -1,9 +1,6 @@
package discordgo package discordgo
import ( import "strings"
"fmt"
"strings"
)
// A User stores all data for an individual Discord user. // A User stores all data for an individual Discord user.
type User struct { type User struct {
@ -43,12 +40,12 @@ type User struct {
// String returns a unique identifier of the form username#discriminator // String returns a unique identifier of the form username#discriminator
func (u *User) String() string { func (u *User) String() string {
return fmt.Sprintf("%s#%s", u.Username, u.Discriminator) return u.Username + "#" + u.Discriminator
} }
// Mention return a string which mentions the user // Mention return a string which mentions the user
func (u *User) Mention() string { func (u *User) Mention() string {
return fmt.Sprintf("<@%s>", u.ID) return "<@" + u.ID + ">"
} }
// AvatarURL returns a URL to the user's avatar. // AvatarURL returns a URL to the user's avatar.

View file

@ -14,6 +14,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net" "net"
"strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -135,7 +136,6 @@ func (v *VoiceConnection) ChangeChannel(channelID string, mute, deaf bool) (err
// Disconnect disconnects from this voice channel and closes the websocket // Disconnect disconnects from this voice channel and closes the websocket
// and udp connections to Discord. // and udp connections to Discord.
// !!! NOTE !!! this function may be removed in favour of ChannelVoiceLeave
func (v *VoiceConnection) Disconnect() (err error) { func (v *VoiceConnection) Disconnect() (err error) {
// Send a OP4 with a nil channel to disconnect // Send a OP4 with a nil channel to disconnect
@ -299,7 +299,7 @@ func (v *VoiceConnection) open() (err error) {
} }
// Connect to VoiceConnection Websocket // Connect to VoiceConnection Websocket
vg := fmt.Sprintf("wss://%s", strings.TrimSuffix(v.endpoint, ":80")) vg := "wss://" + strings.TrimSuffix(v.endpoint, ":80")
v.log(LogInformational, "connecting to voice endpoint %s", vg) v.log(LogInformational, "connecting to voice endpoint %s", vg)
v.wsConn, _, err = websocket.DefaultDialer.Dial(vg, nil) v.wsConn, _, err = websocket.DefaultDialer.Dial(vg, nil)
if err != nil { if err != nil {
@ -542,7 +542,7 @@ func (v *VoiceConnection) udpOpen() (err error) {
return fmt.Errorf("empty endpoint") return fmt.Errorf("empty endpoint")
} }
host := fmt.Sprintf("%s:%d", strings.TrimSuffix(v.endpoint, ":80"), v.op2.Port) host := strings.TrimSuffix(v.endpoint, ":80") + ":" + strconv.Itoa(v.op2.Port)
addr, err := net.ResolveUDPAddr("udp", host) addr, err := net.ResolveUDPAddr("udp", host)
if err != nil { if err != nil {
v.log(LogWarning, "error resolving udp host %s, %s", host, err) v.log(LogWarning, "error resolving udp host %s, %s", host, err)

View file

@ -86,6 +86,10 @@ func (s *Session) Open() error {
return err return err
} }
s.wsConn.SetCloseHandler(func(code int, text string) error {
return nil
})
defer func() { defer func() {
// because of this, all code below must set err to the error // because of this, all code below must set err to the error
// when exiting with an error :) Maybe someone has a better // when exiting with an error :) Maybe someone has a better