Update fork and resolve conflicts
This commit is contained in:
commit
10edf15944
13 changed files with 233 additions and 33 deletions
|
@ -1,6 +1,6 @@
|
||||||
# DiscordGo
|
# DiscordGo
|
||||||
|
|
||||||
[](https://godoc.org/github.com/bwmarrin/discordgo) [](http://goreportcard.com/report/bwmarrin/discordgo) [](https://travis-ci.org/bwmarrin/discordgo) [](https://discord.gg/0f1SbxBZjYoCtNPP) [](https://discord.gg/0SBTUU1wZTWT6sqd)
|
[](https://godoc.org/github.com/bwmarrin/discordgo) [](http://goreportcard.com/report/bwmarrin/discordgo) [](https://travis-ci.org/bwmarrin/discordgo) [](https://discord.gg/0f1SbxBZjYoCtNPP) [](https://discordapp.com/invite/discord-api)
|
||||||
|
|
||||||
<img align="right" src="http://bwmarrin.github.io/discordgo/img/discordgo.png">
|
<img align="right" src="http://bwmarrin.github.io/discordgo/img/discordgo.png">
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/)
|
// VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/)
|
||||||
const VERSION = "0.19.0"
|
const VERSION = "0.20.1"
|
||||||
|
|
||||||
// ErrMFA will be risen by New when the user has 2FA.
|
// ErrMFA will be risen by New when the user has 2FA.
|
||||||
var ErrMFA = errors.New("account has 2FA enabled")
|
var ErrMFA = errors.New("account has 2FA enabled")
|
||||||
|
@ -58,6 +58,7 @@ func New(args ...interface{}) (s *Session, err error) {
|
||||||
ShardCount: 1,
|
ShardCount: 1,
|
||||||
MaxRestRetries: 3,
|
MaxRestRetries: 3,
|
||||||
Client: &http.Client{Timeout: (20 * time.Second)},
|
Client: &http.Client{Timeout: (20 * time.Second)},
|
||||||
|
UserAgent: "DiscordBot (https://github.com/bwmarrin/discordgo, v" + VERSION + ")",
|
||||||
sequence: new(int64),
|
sequence: new(int64),
|
||||||
LastHeartbeatAck: time.Now().UTC(),
|
LastHeartbeatAck: time.Now().UTC(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,4 +30,4 @@ information and support for DiscordGo. There's also a chance to make some
|
||||||
friends :)
|
friends :)
|
||||||
|
|
||||||
* Join the [Discord Gophers](https://discord.gg/0f1SbxBZjYoCtNPP) chat server dedicated to Go programming.
|
* Join the [Discord Gophers](https://discord.gg/0f1SbxBZjYoCtNPP) chat server dedicated to Go programming.
|
||||||
* Join the [Discord API](https://discord.gg/0SBTUU1wZTWT6sqd) chat server dedicated to the Discord API.
|
* Join the [Discord API](https://discordapp.com/invite/discord-API) chat server dedicated to the Discord API.
|
||||||
|
|
12
endpoints.go
12
endpoints.go
|
@ -38,6 +38,7 @@ var (
|
||||||
EndpointCDNIcons = EndpointCDN + "icons/"
|
EndpointCDNIcons = EndpointCDN + "icons/"
|
||||||
EndpointCDNSplashes = EndpointCDN + "splashes/"
|
EndpointCDNSplashes = EndpointCDN + "splashes/"
|
||||||
EndpointCDNChannelIcons = EndpointCDN + "channel-icons/"
|
EndpointCDNChannelIcons = EndpointCDN + "channel-icons/"
|
||||||
|
EndpointCDNBanners = EndpointCDN + "banners/"
|
||||||
|
|
||||||
EndpointAuth = EndpointAPI + "auth/"
|
EndpointAuth = EndpointAPI + "auth/"
|
||||||
EndpointLogin = EndpointAuth + "login"
|
EndpointLogin = EndpointAuth + "login"
|
||||||
|
@ -92,11 +93,13 @@ var (
|
||||||
EndpointGuildEmbed = func(gID string) string { return EndpointGuilds + gID + "/embed" }
|
EndpointGuildEmbed = func(gID string) string { return EndpointGuilds + gID + "/embed" }
|
||||||
EndpointGuildPrune = func(gID string) string { return EndpointGuilds + gID + "/prune" }
|
EndpointGuildPrune = func(gID string) string { return EndpointGuilds + gID + "/prune" }
|
||||||
EndpointGuildIcon = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".png" }
|
EndpointGuildIcon = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".png" }
|
||||||
|
EndpointGuildIconAnimated = func(gID, hash string) string { return EndpointCDNIcons + gID + "/" + hash + ".gif" }
|
||||||
EndpointGuildSplash = func(gID, hash string) string { return EndpointCDNSplashes + gID + "/" + hash + ".png" }
|
EndpointGuildSplash = func(gID, hash string) string { return EndpointCDNSplashes + gID + "/" + hash + ".png" }
|
||||||
EndpointGuildWebhooks = func(gID string) string { return EndpointGuilds + gID + "/webhooks" }
|
EndpointGuildWebhooks = func(gID string) string { return EndpointGuilds + gID + "/webhooks" }
|
||||||
EndpointGuildAuditLogs = func(gID string) string { return EndpointGuilds + gID + "/audit-logs" }
|
EndpointGuildAuditLogs = func(gID string) string { return EndpointGuilds + gID + "/audit-logs" }
|
||||||
EndpointGuildEmojis = func(gID string) string { return EndpointGuilds + gID + "/emojis" }
|
EndpointGuildEmojis = func(gID string) string { return EndpointGuilds + gID + "/emojis" }
|
||||||
EndpointGuildEmoji = func(gID, eID string) string { return EndpointGuilds + gID + "/emojis/" + eID }
|
EndpointGuildEmoji = func(gID, eID string) string { return EndpointGuilds + gID + "/emojis/" + eID }
|
||||||
|
EndpointGuildBanner = func(gID, hash string) string { return EndpointCDNBanners + gID + "/" + hash + ".png" }
|
||||||
|
|
||||||
EndpointChannel = func(cID string) string { return EndpointChannels + cID }
|
EndpointChannel = func(cID string) string { return EndpointChannels + cID }
|
||||||
EndpointChannelPermissions = func(cID string) string { return EndpointChannels + cID + "/permissions" }
|
EndpointChannelPermissions = func(cID string) string { return EndpointChannels + cID + "/permissions" }
|
||||||
|
@ -139,8 +142,9 @@ var (
|
||||||
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" }
|
EndpointEmojiAnimated = func(eID string) string { return EndpointAPI + "emojis/" + eID + ".gif" }
|
||||||
|
|
||||||
EndpointOauth2 = EndpointAPI + "oauth2/"
|
EndpointOauth2 = EndpointAPI + "oauth2/"
|
||||||
EndpointApplications = EndpointOauth2 + "applications"
|
EndpointApplications = EndpointOauth2 + "applications"
|
||||||
EndpointApplication = func(aID string) string { return EndpointApplications + "/" + aID }
|
EndpointApplication = func(aID string) string { return EndpointApplications + "/" + aID }
|
||||||
EndpointApplicationsBot = func(aID string) string { return EndpointApplications + "/" + aID + "/bot" }
|
EndpointApplicationsBot = func(aID string) string { return EndpointApplications + "/" + aID + "/bot" }
|
||||||
|
EndpointApplicationAssets = func(aID string) string { return EndpointApplications + "/" + aID + "/assets" }
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,15 +10,15 @@ import (
|
||||||
//go:generate go run tools/cmd/eventhandlers/main.go
|
//go:generate go run tools/cmd/eventhandlers/main.go
|
||||||
|
|
||||||
// Connect is the data for a Connect event.
|
// Connect is the data for a Connect event.
|
||||||
// This is a sythetic event and is not dispatched by Discord.
|
// This is a synthetic event and is not dispatched by Discord.
|
||||||
type Connect struct{}
|
type Connect struct{}
|
||||||
|
|
||||||
// Disconnect is the data for a Disconnect event.
|
// Disconnect is the data for a Disconnect event.
|
||||||
// This is a sythetic event and is not dispatched by Discord.
|
// This is a synthetic event and is not dispatched by Discord.
|
||||||
type Disconnect struct{}
|
type Disconnect struct{}
|
||||||
|
|
||||||
// RateLimit is the data for a RateLimit event.
|
// RateLimit is the data for a RateLimit event.
|
||||||
// This is a sythetic event and is not dispatched by Discord.
|
// This is a synthetic event and is not dispatched by Discord.
|
||||||
type RateLimit struct {
|
type RateLimit struct {
|
||||||
*TooManyRequests
|
*TooManyRequests
|
||||||
URL string
|
URL string
|
||||||
|
@ -162,6 +162,8 @@ type MessageCreate struct {
|
||||||
// MessageUpdate is the data for a MessageUpdate event.
|
// MessageUpdate is the data for a MessageUpdate event.
|
||||||
type MessageUpdate struct {
|
type MessageUpdate struct {
|
||||||
*Message
|
*Message
|
||||||
|
// BeforeUpdate will be nil if the Message was not previously cached in the state cache.
|
||||||
|
BeforeUpdate *Message `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessageDelete is the data for a MessageDelete event.
|
// MessageDelete is the data for a MessageDelete event.
|
||||||
|
|
79
message.go
79
message.go
|
@ -28,6 +28,11 @@ const (
|
||||||
MessageTypeChannelIconChange
|
MessageTypeChannelIconChange
|
||||||
MessageTypeChannelPinnedMessage
|
MessageTypeChannelPinnedMessage
|
||||||
MessageTypeGuildMemberJoin
|
MessageTypeGuildMemberJoin
|
||||||
|
MessageTypeUserPremiumGuildSubscription
|
||||||
|
MessageTypeUserPremiumGuildSubscriptionTierOne
|
||||||
|
MessageTypeUserPremiumGuildSubscriptionTierTwo
|
||||||
|
MessageTypeUserPremiumGuildSubscriptionTierThree
|
||||||
|
MessageTypeChannelFollowAdd
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Message stores all data related to a specific Discord message.
|
// A Message stores all data related to a specific Discord message.
|
||||||
|
@ -80,11 +85,39 @@ type Message struct {
|
||||||
// A list of reactions to the message.
|
// A list of reactions to the message.
|
||||||
Reactions []*MessageReactions `json:"reactions"`
|
Reactions []*MessageReactions `json:"reactions"`
|
||||||
|
|
||||||
|
// Whether the message is pinned or not.
|
||||||
|
Pinned bool `json:"pinned"`
|
||||||
|
|
||||||
// The type of the message.
|
// The type of the message.
|
||||||
Type MessageType `json:"type"`
|
Type MessageType `json:"type"`
|
||||||
|
|
||||||
// The webhook ID of the message, if it was generated by a webhook
|
// The webhook ID of the message, if it was generated by a webhook
|
||||||
WebhookID string `json:"webhook_id"`
|
WebhookID string `json:"webhook_id"`
|
||||||
|
|
||||||
|
// Member properties for this message's author,
|
||||||
|
// contains only partial information
|
||||||
|
Member *Member `json:"member"`
|
||||||
|
|
||||||
|
// Channels specifically mentioned in this message
|
||||||
|
// Not all channel mentions in a message will appear in mention_channels.
|
||||||
|
// Only textual channels that are visible to everyone in a lurkable guild will ever be included.
|
||||||
|
// Only crossposted messages (via Channel Following) currently include mention_channels at all.
|
||||||
|
// If no mentions in the message meet these requirements, this field will not be sent.
|
||||||
|
MentionChannels []*Channel `json:"mention_channels"`
|
||||||
|
|
||||||
|
// Is sent with Rich Presence-related chat embeds
|
||||||
|
Activity *MessageActivity `json:"activity"`
|
||||||
|
|
||||||
|
// Is sent with Rich Presence-related chat embeds
|
||||||
|
Application *MessageApplication `json:"application"`
|
||||||
|
|
||||||
|
// MessageReference contains reference data sent with crossposted messages
|
||||||
|
MessageReference *MessageReference `json:"message_reference"`
|
||||||
|
|
||||||
|
// The flags of the message, which describe extra features of a message.
|
||||||
|
// This is a combination of bit masks; the presence of a certain permission can
|
||||||
|
// be checked by performing a bitwise AND between this int and the flag.
|
||||||
|
Flags int `json:"flags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// File stores info about files you e.g. send in messages.
|
// File stores info about files you e.g. send in messages.
|
||||||
|
@ -225,6 +258,52 @@ type MessageReactions struct {
|
||||||
Emoji *Emoji `json:"emoji"`
|
Emoji *Emoji `json:"emoji"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MessageActivity is sent with Rich Presence-related chat embeds
|
||||||
|
type MessageActivity struct {
|
||||||
|
Type MessageActivityType `json:"type"`
|
||||||
|
PartyID string `json:"party_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageActivityType is the type of message activity
|
||||||
|
type MessageActivityType int
|
||||||
|
|
||||||
|
// Constants for the different types of Message Activity
|
||||||
|
const (
|
||||||
|
MessageActivityTypeJoin = iota + 1
|
||||||
|
MessageActivityTypeSpectate
|
||||||
|
MessageActivityTypeListen
|
||||||
|
MessageActivityTypeJoinRequest
|
||||||
|
)
|
||||||
|
|
||||||
|
// MessageFlag describes an extra feature of the message
|
||||||
|
type MessageFlag int
|
||||||
|
|
||||||
|
// Constants for the different bit offsets of Message Flags
|
||||||
|
const (
|
||||||
|
// This message has been published to subscribed channels (via Channel Following)
|
||||||
|
MessageFlagCrossposted = 1 << iota
|
||||||
|
// This message originated from a message in another channel (via Channel Following)
|
||||||
|
MessageFlagIsCrosspost
|
||||||
|
// Do not include any embeds when serializing this message
|
||||||
|
MessageFlagSuppressEmbeds
|
||||||
|
)
|
||||||
|
|
||||||
|
// MessageApplication is sent with Rich Presence-related chat embeds
|
||||||
|
type MessageApplication struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
CoverImage string `json:"cover_image"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Icon string `json:"icon"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageReference contains reference data sent with crossposted messages
|
||||||
|
type MessageReference struct {
|
||||||
|
MessageID string `json:"message_id"`
|
||||||
|
ChannelID string `json:"channel_id"`
|
||||||
|
GuildID string `json:"guild_id"`
|
||||||
|
}
|
||||||
|
|
||||||
// ContentWithMentionsReplaced will replace all @<id> mentions with the
|
// ContentWithMentionsReplaced will replace all @<id> mentions with the
|
||||||
// username of the mention.
|
// username of the mention.
|
||||||
func (m *Message) ContentWithMentionsReplaced() (content string) {
|
func (m *Message) ContentWithMentionsReplaced() (content string) {
|
||||||
|
|
19
oauth2.go
19
oauth2.go
|
@ -105,6 +105,25 @@ func (s *Session) ApplicationDelete(appID string) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Asset struct stores values for an asset of an application
|
||||||
|
type Asset struct {
|
||||||
|
Type int `json:"type"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplicationAssets returns an application's assets
|
||||||
|
func (s *Session) ApplicationAssets(appID string) (ass []*Asset, err error) {
|
||||||
|
|
||||||
|
body, err := s.RequestWithBucketID("GET", EndpointApplicationAssets(appID), nil, EndpointApplicationAssets(""))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = unmarshal(body, &ass)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Code specific to Discord OAuth2 Application Bots
|
// Code specific to Discord OAuth2 Application Bots
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
24
restapi.go
24
restapi.go
|
@ -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", "DiscordBot (https://github.com/bwmarrin/discordgo, v"+VERSION+")")
|
req.Header.Set("User-Agent", s.UserAgent)
|
||||||
|
|
||||||
if s.Debug {
|
if s.Debug {
|
||||||
for k, v := range req.Header {
|
for k, v := range req.Header {
|
||||||
|
@ -617,10 +617,10 @@ func (s *Session) GuildCreate(name string) (st *Guild, err error) {
|
||||||
// g : A GuildParams struct with the values Name, Region and VerificationLevel defined.
|
// g : A GuildParams struct with the values Name, Region and VerificationLevel defined.
|
||||||
func (s *Session) GuildEdit(guildID string, g GuildParams) (st *Guild, err error) {
|
func (s *Session) GuildEdit(guildID string, g GuildParams) (st *Guild, err error) {
|
||||||
|
|
||||||
// Bounds checking for VerificationLevel, interval: [0, 3]
|
// Bounds checking for VerificationLevel, interval: [0, 4]
|
||||||
if g.VerificationLevel != nil {
|
if g.VerificationLevel != nil {
|
||||||
val := *g.VerificationLevel
|
val := *g.VerificationLevel
|
||||||
if val < 0 || val > 3 {
|
if val < 0 || val > 4 {
|
||||||
err = ErrVerificationLevelBounds
|
err = ErrVerificationLevelBounds
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -675,7 +675,7 @@ func (s *Session) GuildLeave(guildID string) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GuildBans returns an array of User structures for all bans of a
|
// GuildBans returns an array of GuildBan structures for all bans of a
|
||||||
// given guild.
|
// given guild.
|
||||||
// guildID : The ID of a Guild.
|
// guildID : The ID of a Guild.
|
||||||
func (s *Session) GuildBans(guildID string) (st []*GuildBan, err error) {
|
func (s *Session) GuildBans(guildID string) (st []*GuildBan, err error) {
|
||||||
|
@ -2067,14 +2067,20 @@ func (s *Session) WebhookDeleteWithToken(webhookID, token string) (st *Webhook,
|
||||||
// WebhookExecute executes a webhook.
|
// WebhookExecute executes a webhook.
|
||||||
// webhookID: The ID of a webhook.
|
// webhookID: The ID of a webhook.
|
||||||
// token : The auth token for the webhook
|
// token : The auth token for the webhook
|
||||||
func (s *Session) WebhookExecute(webhookID, token string, wait bool, data *WebhookParams) (err error) {
|
// wait : Waits for server confirmation of message send and ensures that the return struct is populated (it is nil otherwise)
|
||||||
|
func (s *Session) WebhookExecute(webhookID, token string, wait bool, data *WebhookParams) (st *Message, err error) {
|
||||||
uri := EndpointWebhookToken(webhookID, token)
|
uri := EndpointWebhookToken(webhookID, token)
|
||||||
|
|
||||||
if wait {
|
if wait {
|
||||||
uri += "?wait=true"
|
uri += "?wait=true"
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = s.RequestWithBucketID("POST", uri, data, EndpointWebhookToken("", ""))
|
response, err := s.RequestWithBucketID("POST", uri, data, EndpointWebhookToken("", ""))
|
||||||
|
if !wait || err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = unmarshal(response, &st)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -2085,6 +2091,8 @@ func (s *Session) WebhookExecute(webhookID, token string, wait bool, data *Webho
|
||||||
// emojiID : Either the unicode emoji for the reaction, or a guild emoji identifier.
|
// emojiID : Either the unicode emoji for the reaction, or a guild emoji identifier.
|
||||||
func (s *Session) MessageReactionAdd(channelID, messageID, emojiID string) error {
|
func (s *Session) MessageReactionAdd(channelID, messageID, emojiID string) error {
|
||||||
|
|
||||||
|
// emoji such as #⃣ need to have # escaped
|
||||||
|
emojiID = strings.Replace(emojiID, "#", "%23", -1)
|
||||||
_, err := s.RequestWithBucketID("PUT", EndpointMessageReaction(channelID, messageID, emojiID, "@me"), nil, EndpointMessageReaction(channelID, "", "", ""))
|
_, err := s.RequestWithBucketID("PUT", EndpointMessageReaction(channelID, messageID, emojiID, "@me"), nil, EndpointMessageReaction(channelID, "", "", ""))
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
@ -2097,6 +2105,8 @@ func (s *Session) MessageReactionAdd(channelID, messageID, emojiID string) error
|
||||||
// userID : @me or ID of the user to delete the reaction for.
|
// userID : @me or ID of the user to delete the reaction for.
|
||||||
func (s *Session) MessageReactionRemove(channelID, messageID, emojiID, userID string) error {
|
func (s *Session) MessageReactionRemove(channelID, messageID, emojiID, userID string) error {
|
||||||
|
|
||||||
|
// emoji such as #⃣ need to have # escaped
|
||||||
|
emojiID = strings.Replace(emojiID, "#", "%23", -1)
|
||||||
_, err := s.RequestWithBucketID("DELETE", EndpointMessageReaction(channelID, messageID, emojiID, userID), nil, EndpointMessageReaction(channelID, "", "", ""))
|
_, err := s.RequestWithBucketID("DELETE", EndpointMessageReaction(channelID, messageID, emojiID, userID), nil, EndpointMessageReaction(channelID, "", "", ""))
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
@ -2120,6 +2130,8 @@ func (s *Session) MessageReactionsRemoveAll(channelID, messageID string) error {
|
||||||
// beforeID : If provided all reactions returned will be before given ID.
|
// beforeID : If provided all reactions returned will be before given ID.
|
||||||
// afterID : If provided all reactions returned will be after given ID.
|
// afterID : If provided all reactions returned will be after given ID.
|
||||||
func (s *Session) MessageReactions(channelID, messageID, emojiID string, limit int, beforeID, afterID string) (st []*User, err error) {
|
func (s *Session) MessageReactions(channelID, messageID, emojiID string, limit int, beforeID, afterID string) (st []*User, err error) {
|
||||||
|
// emoji such as #⃣ need to have # escaped
|
||||||
|
emojiID = strings.Replace(emojiID, "#", "%23", -1)
|
||||||
uri := EndpointMessageReactions(channelID, messageID, emojiID)
|
uri := EndpointMessageReactions(channelID, messageID, emojiID)
|
||||||
|
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
|
|
7
state.go
7
state.go
|
@ -882,6 +882,13 @@ func (s *State) OnInterface(se *Session, i interface{}) (err error) {
|
||||||
}
|
}
|
||||||
case *MessageUpdate:
|
case *MessageUpdate:
|
||||||
if s.MaxMessageCount != 0 {
|
if s.MaxMessageCount != 0 {
|
||||||
|
var old *Message
|
||||||
|
old, err = s.Message(t.ChannelID, t.ID)
|
||||||
|
if err == nil {
|
||||||
|
oldCopy := *old
|
||||||
|
t.BeforeUpdate = &oldCopy
|
||||||
|
}
|
||||||
|
|
||||||
err = s.MessageAdd(t.Message)
|
err = s.MessageAdd(t.Message)
|
||||||
}
|
}
|
||||||
case *MessageDelete:
|
case *MessageDelete:
|
||||||
|
|
66
structs.go
66
structs.go
|
@ -15,6 +15,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -82,6 +83,9 @@ type Session struct {
|
||||||
// The http client used for REST requests
|
// The http client used for REST requests
|
||||||
Client *http.Client
|
Client *http.Client
|
||||||
|
|
||||||
|
// The user agent used for REST APIs
|
||||||
|
UserAgent string
|
||||||
|
|
||||||
// Stores the last HeartbeatAck that was recieved (in UTC)
|
// Stores the last HeartbeatAck that was recieved (in UTC)
|
||||||
LastHeartbeatAck time.Time
|
LastHeartbeatAck time.Time
|
||||||
|
|
||||||
|
@ -196,6 +200,8 @@ const (
|
||||||
ChannelTypeGuildVoice
|
ChannelTypeGuildVoice
|
||||||
ChannelTypeGroupDM
|
ChannelTypeGroupDM
|
||||||
ChannelTypeGuildCategory
|
ChannelTypeGuildCategory
|
||||||
|
ChannelTypeGuildNews
|
||||||
|
ChannelTypeGuildStore
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Channel holds all data related to an individual Discord channel.
|
// A Channel holds all data related to an individual Discord channel.
|
||||||
|
@ -220,6 +226,10 @@ type Channel struct {
|
||||||
// guaranteed to be an ID of a valid message.
|
// guaranteed to be an ID of a valid message.
|
||||||
LastMessageID string `json:"last_message_id"`
|
LastMessageID string `json:"last_message_id"`
|
||||||
|
|
||||||
|
// The timestamp of the last pinned message in the channel.
|
||||||
|
// Empty if the channel has no pinned messages.
|
||||||
|
LastPinTimestamp Timestamp `json:"last_pin_timestamp"`
|
||||||
|
|
||||||
// Whether the channel is marked as NSFW.
|
// Whether the channel is marked as NSFW.
|
||||||
NSFW bool `json:"nsfw"`
|
NSFW bool `json:"nsfw"`
|
||||||
|
|
||||||
|
@ -247,6 +257,10 @@ type Channel struct {
|
||||||
|
|
||||||
// The ID of the parent channel, if the channel is under a category
|
// The ID of the parent channel, if the channel is under a category
|
||||||
ParentID string `json:"parent_id"`
|
ParentID string `json:"parent_id"`
|
||||||
|
|
||||||
|
// Amount of seconds a user has to wait before sending another message (0-21600)
|
||||||
|
// bots, as well as users with the permission manage_messages or manage_channel, are unaffected
|
||||||
|
RateLimitPerUser int `json:"rate_limit_per_user"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mention returns a string which mentions the channel
|
// Mention returns a string which mentions the channel
|
||||||
|
@ -283,6 +297,7 @@ type Emoji struct {
|
||||||
Managed bool `json:"managed"`
|
Managed bool `json:"managed"`
|
||||||
RequireColons bool `json:"require_colons"`
|
RequireColons bool `json:"require_colons"`
|
||||||
Animated bool `json:"animated"`
|
Animated bool `json:"animated"`
|
||||||
|
Available bool `json:"available"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessageFormat returns a correctly formatted Emoji for use in Message content and embeds
|
// MessageFormat returns a correctly formatted Emoji for use in Message content and embeds
|
||||||
|
@ -312,12 +327,13 @@ func (e *Emoji) APIName() string {
|
||||||
// VerificationLevel type definition
|
// VerificationLevel type definition
|
||||||
type VerificationLevel int
|
type VerificationLevel int
|
||||||
|
|
||||||
// Constants for VerificationLevel levels from 0 to 3 inclusive
|
// Constants for VerificationLevel levels from 0 to 4 inclusive
|
||||||
const (
|
const (
|
||||||
VerificationLevelNone VerificationLevel = iota
|
VerificationLevelNone VerificationLevel = iota
|
||||||
VerificationLevelLow
|
VerificationLevelLow
|
||||||
VerificationLevelMedium
|
VerificationLevelMedium
|
||||||
VerificationLevelHigh
|
VerificationLevelHigh
|
||||||
|
VerificationLevelVeryHigh
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExplicitContentFilterLevel type definition
|
// ExplicitContentFilterLevel type definition
|
||||||
|
@ -339,6 +355,17 @@ const (
|
||||||
MfaLevelElevated
|
MfaLevelElevated
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PremiumTier type definition
|
||||||
|
type PremiumTier int
|
||||||
|
|
||||||
|
// Constants for PremiumTier levels from 0 to 3 inclusive
|
||||||
|
const (
|
||||||
|
PremiumTierNone PremiumTier = iota
|
||||||
|
PremiumTier1
|
||||||
|
PremiumTier2
|
||||||
|
PremiumTier3
|
||||||
|
)
|
||||||
|
|
||||||
// A Guild holds all data related to a specific Discord Guild. Guilds are also
|
// A Guild holds all data related to a specific Discord Guild. Guilds are also
|
||||||
// sometimes referred to as Servers in the Discord client.
|
// sometimes referred to as Servers in the Discord client.
|
||||||
type Guild struct {
|
type Guild struct {
|
||||||
|
@ -443,6 +470,34 @@ type Guild struct {
|
||||||
|
|
||||||
// The Channel ID to which system messages are sent (eg join and leave messages)
|
// The Channel ID to which system messages are sent (eg join and leave messages)
|
||||||
SystemChannelID string `json:"system_channel_id"`
|
SystemChannelID string `json:"system_channel_id"`
|
||||||
|
|
||||||
|
// the vanity url code for the guild
|
||||||
|
VanityURLCode string `json:"vanity_url_code"`
|
||||||
|
|
||||||
|
// the description for the guild
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// The hash of the guild's banner
|
||||||
|
Banner string `json:"banner"`
|
||||||
|
|
||||||
|
// The premium tier of the guild
|
||||||
|
PremiumTier PremiumTier `json:"premium_tier"`
|
||||||
|
|
||||||
|
// The total number of users currently boosting this server
|
||||||
|
PremiumSubscriptionCount int `json:"premium_subscription_count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IconURL returns a URL to the guild's icon.
|
||||||
|
func (g *Guild) IconURL() string {
|
||||||
|
if g.Icon == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(g.Icon, "a_") {
|
||||||
|
return EndpointGuildIconAnimated(g.ID, g.Icon)
|
||||||
|
}
|
||||||
|
|
||||||
|
return EndpointGuildIcon(g.ID, g.Icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A UserGuild holds a brief version of a Guild
|
// A UserGuild holds a brief version of a Guild
|
||||||
|
@ -617,6 +672,9 @@ type Member struct {
|
||||||
|
|
||||||
// A list of IDs of the roles which are possessed by the member.
|
// A list of IDs of the roles which are possessed by the member.
|
||||||
Roles []string `json:"roles"`
|
Roles []string `json:"roles"`
|
||||||
|
|
||||||
|
// When the user used their Nitro boost on the server
|
||||||
|
PremiumSince Timestamp `json:"premium_since"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mention creates a member mention
|
// Mention creates a member mention
|
||||||
|
@ -872,6 +930,7 @@ const (
|
||||||
PermissionVoiceDeafenMembers
|
PermissionVoiceDeafenMembers
|
||||||
PermissionVoiceMoveMembers
|
PermissionVoiceMoveMembers
|
||||||
PermissionVoiceUseVAD
|
PermissionVoiceUseVAD
|
||||||
|
PermissionVoicePrioritySpeaker = 1 << (iota + 2)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Constants for general management.
|
// Constants for general management.
|
||||||
|
@ -907,7 +966,8 @@ const (
|
||||||
PermissionVoiceMuteMembers |
|
PermissionVoiceMuteMembers |
|
||||||
PermissionVoiceDeafenMembers |
|
PermissionVoiceDeafenMembers |
|
||||||
PermissionVoiceMoveMembers |
|
PermissionVoiceMoveMembers |
|
||||||
PermissionVoiceUseVAD
|
PermissionVoiceUseVAD |
|
||||||
|
PermissionVoicePrioritySpeaker
|
||||||
PermissionAllChannel = PermissionAllText |
|
PermissionAllChannel = PermissionAllText |
|
||||||
PermissionAllVoice |
|
PermissionAllVoice |
|
||||||
PermissionCreateInstantInvite |
|
PermissionCreateInstantInvite |
|
||||||
|
@ -956,7 +1016,7 @@ const (
|
||||||
ErrCodeMissingAccess = 50001
|
ErrCodeMissingAccess = 50001
|
||||||
ErrCodeInvalidAccountType = 50002
|
ErrCodeInvalidAccountType = 50002
|
||||||
ErrCodeCannotExecuteActionOnDMChannel = 50003
|
ErrCodeCannotExecuteActionOnDMChannel = 50003
|
||||||
ErrCodeEmbedCisabled = 50004
|
ErrCodeEmbedDisabled = 50004
|
||||||
ErrCodeCannotEditFromAnotherUser = 50005
|
ErrCodeCannotEditFromAnotherUser = 50005
|
||||||
ErrCodeCannotSendEmptyMessage = 50006
|
ErrCodeCannotSendEmptyMessage = 50006
|
||||||
ErrCodeCannotSendMessagesToThisUser = 50007
|
ErrCodeCannotSendMessagesToThisUser = 50007
|
||||||
|
|
17
util.go
Normal file
17
util.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package discordgo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SnowflakeTimestamp returns the creation time of a Snowflake ID relative to the creation of Discord.
|
||||||
|
func SnowflakeTimestamp(ID string) (t time.Time, err error) {
|
||||||
|
i, err := strconv.ParseInt(ID, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
timestamp := (i >> 22) + 1420070400000
|
||||||
|
t = time.Unix(timestamp/1000, 0)
|
||||||
|
return
|
||||||
|
}
|
5
voice.go
5
voice.go
|
@ -243,6 +243,7 @@ type voiceOP2 struct {
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
Modes []string `json:"modes"`
|
Modes []string `json:"modes"`
|
||||||
HeartbeatInterval time.Duration `json:"heartbeat_interval"`
|
HeartbeatInterval time.Duration `json:"heartbeat_interval"`
|
||||||
|
IP string `json:"ip"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// WaitUntilConnected waits for the Voice Connection to
|
// WaitUntilConnected waits for the Voice Connection to
|
||||||
|
@ -542,7 +543,7 @@ func (v *VoiceConnection) udpOpen() (err error) {
|
||||||
return fmt.Errorf("empty endpoint")
|
return fmt.Errorf("empty endpoint")
|
||||||
}
|
}
|
||||||
|
|
||||||
host := strings.TrimSuffix(v.endpoint, ":80") + ":" + strconv.Itoa(v.op2.Port)
|
host := v.op2.IP + ":" + 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)
|
||||||
|
@ -593,7 +594,7 @@ func (v *VoiceConnection) udpOpen() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grab port from position 68 and 69
|
// Grab port from position 68 and 69
|
||||||
port := binary.LittleEndian.Uint16(rb[68:70])
|
port := binary.BigEndian.Uint16(rb[68:70])
|
||||||
|
|
||||||
// Take the data from above and send it back to Discord to finalize
|
// Take the data from above and send it back to Discord to finalize
|
||||||
// the UDP connection handshake.
|
// the UDP connection handshake.
|
||||||
|
|
22
wsapi.go
22
wsapi.go
|
@ -261,7 +261,6 @@ type heartbeatOp struct {
|
||||||
|
|
||||||
type helloOp struct {
|
type helloOp struct {
|
||||||
HeartbeatInterval time.Duration `json:"heartbeat_interval"`
|
HeartbeatInterval time.Duration `json:"heartbeat_interval"`
|
||||||
Trace []string `json:"_trace"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailedHeartbeatAcks is the Number of heartbeat intervals to wait until forcing a connection restart.
|
// FailedHeartbeatAcks is the Number of heartbeat intervals to wait until forcing a connection restart.
|
||||||
|
@ -615,11 +614,7 @@ func (s *Session) ChannelVoiceJoin(gID, cID string, mute, deaf bool) (voice *Voi
|
||||||
voice.session = s
|
voice.session = s
|
||||||
voice.Unlock()
|
voice.Unlock()
|
||||||
|
|
||||||
// Send the request to Discord that we want to join the voice channel
|
err = s.ChannelVoiceJoinManual(gID, cID, mute, deaf)
|
||||||
data := voiceChannelJoinOp{4, voiceChannelJoinData{&gID, &cID, mute, deaf}}
|
|
||||||
s.wsMutex.Lock()
|
|
||||||
err = s.wsConn.WriteJSON(data)
|
|
||||||
s.wsMutex.Unlock()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -640,22 +635,25 @@ func (s *Session) ChannelVoiceJoin(gID, cID string, mute, deaf bool) (voice *Voi
|
||||||
// This should only be used when the VoiceServerUpdate will be intercepted and used elsewhere.
|
// This should only be used when the VoiceServerUpdate will be intercepted and used elsewhere.
|
||||||
//
|
//
|
||||||
// gID : Guild ID of the channel to join.
|
// gID : Guild ID of the channel to join.
|
||||||
// cID : Channel ID of the channel to join.
|
// cID : Channel ID of the channel to join, leave empty to disconnect.
|
||||||
// mute : If true, you will be set to muted upon joining.
|
// mute : If true, you will be set to muted upon joining.
|
||||||
// deaf : If true, you will be set to deafened upon joining.
|
// deaf : If true, you will be set to deafened upon joining.
|
||||||
func (s *Session) ChannelVoiceJoinManual(gID, cID string, mute, deaf bool) (err error) {
|
func (s *Session) ChannelVoiceJoinManual(gID, cID string, mute, deaf bool) (err error) {
|
||||||
|
|
||||||
s.log(LogInformational, "called")
|
s.log(LogInformational, "called")
|
||||||
|
|
||||||
|
var channelID *string
|
||||||
|
if cID == "" {
|
||||||
|
channelID = nil
|
||||||
|
} else {
|
||||||
|
channelID = &cID
|
||||||
|
}
|
||||||
|
|
||||||
// Send the request to Discord that we want to join the voice channel
|
// Send the request to Discord that we want to join the voice channel
|
||||||
data := voiceChannelJoinOp{4, voiceChannelJoinData{&gID, &cID, mute, deaf}}
|
data := voiceChannelJoinOp{4, voiceChannelJoinData{&gID, channelID, mute, deaf}}
|
||||||
s.wsMutex.Lock()
|
s.wsMutex.Lock()
|
||||||
err = s.wsConn.WriteJSON(data)
|
err = s.wsConn.WriteJSON(data)
|
||||||
s.wsMutex.Unlock()
|
s.wsMutex.Unlock()
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue