Permalink
Cannot retrieve contributors at this time
Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
| package disgord | |
| import ( | |
| "context" | |
| "errors" | |
| "fmt" | |
| "net/http" | |
| "os" | |
| "os/signal" | |
| "strconv" | |
| "sync" | |
| "syscall" | |
| "time" | |
| "github.com/andersfylling/disgord/event" | |
| "github.com/andersfylling/disgord/httd" | |
| "github.com/sirupsen/logrus" | |
| ) | |
| // Config Configuration for the Disgord client | |
| type Config struct { | |
| Token string | |
| HTTPClient *http.Client | |
| CancelRequestWhenRateLimited bool | |
| CacheConfig *CacheConfig | |
| ShardID uint | |
| TotalShards uint | |
| WebsocketURL string | |
| //ImmutableCache bool | |
| //LoadAllMembers bool | |
| //LoadAllChannels bool | |
| //LoadAllRoles bool | |
| //LoadAllPresences bool | |
| Debug bool | |
| // your project name, name of bot, or whatever | |
| ProjectName string | |
| //Logger logger.Logrus | |
| } | |
| // Client is the main disgord client to hold your state and data | |
| type Client struct { | |
| sync.RWMutex | |
| config *Config | |
| token string | |
| connected sync.Mutex | |
| ws DiscordWebsocket | |
| socketEvtChan <-chan DiscordWSEvent | |
| myID Snowflake | |
| // register listeners for events | |
| evtDispatch *Dispatch | |
| // cancelRequestWhenRateLimited by default the client waits until either the HTTPClient.timeout or | |
| // the rate limit ends before closing a request channel. If activated, in stead, requests will | |
| // instantly be denied, and the channel closed. | |
| cancelRequestWhenRateLimited bool | |
| // discord http api | |
| req *httd.Client | |
| httpClient *http.Client | |
| // cache | |
| cache *Cache | |
| } | |
| // HeartbeatLatency checks the duration of waiting before receiving a response from Discord when a | |
| // heartbeat packet was sent. Note that heartbeats are usually sent around once a minute and is not a accurate | |
| // way to measure delay between the client and Discord server | |
| func (c *Client) HeartbeatLatency() (duration time.Duration, err error) { | |
| return c.ws.HeartbeatLatency() | |
| } | |
| // ShardID ... | |
| func (c *Client) ShardID() uint { | |
| return c.config.ShardID | |
| } | |
| // ShardIDString convert the shard ID to a string | |
| func (c *Client) ShardIDString() string { | |
| return strconv.Itoa(int(c.ShardID())) | |
| } | |
| // Myself get the current user / connected user | |
| func (c *Client) Myself() (user *User, err error) { | |
| if c.myID.Empty() { | |
| user, err = c.GetCurrentUser() | |
| if err == nil { | |
| c.myID = user.ID | |
| } | |
| return | |
| } | |
| var usr interface{} | |
| usr, err = c.cache.Get(UserCache, c.myID) | |
| if err == nil { | |
| user = usr.(*User) | |
| } | |
| return | |
| } | |
| func (c *Client) logInfo(msg string) { | |
| logrus.WithFields(logrus.Fields{ | |
| "lib": LibraryInfo(), | |
| }).Info(msg) | |
| } | |
| func (c *Client) logErr(msg string) { | |
| logrus.WithFields(logrus.Fields{ | |
| "lib": LibraryInfo(), | |
| }).Error(msg) | |
| } | |
| func (c *Client) String() string { | |
| return LibraryInfo() | |
| } | |
| // RateLimiter return the rate limiter object | |
| func (c *Client) RateLimiter() httd.RateLimiter { | |
| return c.req.RateLimiter() | |
| } | |
| // Connect establishes a websocket connection to the discord API | |
| func (c *Client) Connect() (err error) { | |
| // set the user ID upon connection | |
| // only works for socketing | |
| c.Once(event.Ready, func(session Session, rdy *Ready) { | |
| c.myID = rdy.User.ID | |
| }) | |
| c.On(event.UserUpdate, func(session Session, update *UserUpdate) { | |
| session.Cache().Update(UserCache, update.User) | |
| }) | |
| c.logInfo("Connecting to discord Gateway") | |
| c.evtDispatch.start() | |
| err = c.ws.Connect() | |
| if err != nil { | |
| c.logErr(err.Error()) | |
| return | |
| } | |
| c.logInfo("Connected") | |
| // setup event observer | |
| go c.eventHandler() | |
| return nil | |
| } | |
| // Disconnect closes the discord websocket connection | |
| func (c *Client) Disconnect() (err error) { | |
| fmt.Println() // to keep ^C on it's own line | |
| c.logInfo("Closing Discord gateway connection") | |
| c.evtDispatch.stop() | |
| err = c.ws.Disconnect() | |
| if err != nil { | |
| c.logErr(err.Error()) | |
| return | |
| } | |
| c.logInfo("Disconnected") | |
| return nil | |
| } | |
| // DisconnectOnInterrupt wait until a termination signal is detected | |
| func (c *Client) DisconnectOnInterrupt() (err error) { | |
| // create a channel to listen for termination signals (graceful shutdown) | |
| termSignal := make(chan os.Signal, 1) | |
| signal.Notify(termSignal, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill) | |
| <-termSignal | |
| return c.Disconnect() | |
| } | |
| // Req return the request object. Used in REST requests to handle rate limits, | |
| // wrong http responses, etc. | |
| func (c *Client) Req() httd.Requester { | |
| return c.req | |
| } | |
| // Cache returns the cache manager for the session | |
| func (c *Client) Cache() Cacher { | |
| return c.cache | |
| } | |
| // On adds a event handler on the given event. | |
| // On => event => handle the content like this | |
| func (c *Client) On(event string, handlers ...interface{}) { | |
| c.evtDispatch.On(event, handlers...) | |
| } | |
| // Once same as `On`, however, once the handler is triggered, it is removed. In other words, it is only triggered once. | |
| func (c *Client) Once(event string, handlers ...interface{}) { | |
| c.evtDispatch.Once(event, handlers...) | |
| } | |
| // Emit sends a socket command directly to Discord. | |
| func (c *Client) Emit(command SocketCommand, data interface{}) { | |
| switch command { | |
| case CommandUpdateStatus, CommandUpdateVoiceState, CommandRequestGuildMembers: | |
| default: | |
| return | |
| } | |
| c.ws.Emit(command, data) | |
| } | |
| // EventChan get a event channel using the event name | |
| func (c *Client) EventChan(event string) (channel interface{}, err error) { | |
| return c.evtDispatch.EventChan(event) | |
| } | |
| // EventChannels get access to all the event channels | |
| func (c *Client) EventChannels() (channels EventChannels) { | |
| return c.evtDispatch | |
| } | |
| // AcceptEvent only events registered using this method is accepted from the Discord socket API. The rest is discarded | |
| // to improve performance. | |
| func (c *Client) AcceptEvent(events ...string) { | |
| for _, evt := range events { | |
| c.ws.RegisterEvent(evt) | |
| } | |
| } | |
| // Generic CRUDS | |
| // DeleteFromDiscord if the given object has implemented the private interface discordDeleter this method can | |
| // be used to delete said object. | |
| func (c *Client) DeleteFromDiscord(obj discordDeleter) (err error) { | |
| err = obj.deleteFromDiscord(c) | |
| return | |
| } | |
| // SaveToDiscord saves an object to the Discord servers. This supports creation of new objects or udpating/modifying | |
| // existing objects. It really depends on how the object has implemented the private interface discordSaver. | |
| func (c *Client) SaveToDiscord(obj discordSaver) (err error) { | |
| err = obj.saveToDiscord(c) | |
| return | |
| } | |
| // REST | |
| // Audit-log | |
| // GetGuildAuditLogs ... | |
| func (c *Client) GetGuildAuditLogs(guildID Snowflake, params *GuildAuditLogsParams) (log *AuditLog, err error) { | |
| log, err = GuildAuditLogs(c.req, guildID, params) | |
| return | |
| } | |
| // Channel | |
| // GetChannel ... | |
| func (c *Client) GetChannel(id Snowflake) (ret *Channel, err error) { | |
| if ret, err = c.cache.GetChannel(id); err != nil { | |
| ret, err = GetChannel(c.req, id) | |
| if err != nil { | |
| return | |
| } | |
| _ = c.cache.Update(ChannelCache, ret) | |
| } | |
| return | |
| } | |
| // ModifyChannel ... | |
| func (c *Client) ModifyChannel(id Snowflake, changes *ModifyChannelParams) (ret *Channel, err error) { | |
| ret, err = ModifyChannel(c.req, id, changes) // should trigger a socket event, no need to update cache | |
| return | |
| } | |
| // DeleteChannel ... | |
| func (c *Client) DeleteChannel(id Snowflake) (channel *Channel, err error) { | |
| channel, err = DeleteChannel(c.req, id) // should trigger a socket event, no need to update cache | |
| return | |
| } | |
| // EditChannelPermissions ... | |
| func (c *Client) EditChannelPermissions(chanID, overwriteID Snowflake, params *EditChannelPermissionsParams) (err error) { | |
| err = EditChannelPermissions(c.req, chanID, overwriteID, params) | |
| return | |
| } | |
| // GetChannelInvites ... | |
| func (c *Client) GetChannelInvites(id Snowflake) (ret []*Invite, err error) { | |
| ret, err = GetChannelInvites(c.req, id) | |
| return | |
| } | |
| // CreateChannelInvites ... | |
| func (c *Client) CreateChannelInvites(id Snowflake, params *CreateChannelInvitesParams) (ret *Invite, err error) { | |
| ret, err = CreateChannelInvites(c.req, id, params) | |
| return | |
| } | |
| // DeleteChannelPermission . | |
| func (c *Client) DeleteChannelPermission(channelID, overwriteID Snowflake) (err error) { | |
| err = DeleteChannelPermission(c.req, channelID, overwriteID) | |
| return | |
| } | |
| // TriggerTypingIndicator . | |
| func (c *Client) TriggerTypingIndicator(channelID Snowflake) (err error) { | |
| err = TriggerTypingIndicator(c.req, channelID) | |
| return | |
| } | |
| // GetPinnedMessages . | |
| func (c *Client) GetPinnedMessages(channelID Snowflake) (ret []*Message, err error) { | |
| ret, err = GetPinnedMessages(c.req, channelID) | |
| return | |
| } | |
| // AddPinnedChannelMessage . | |
| func (c *Client) AddPinnedChannelMessage(channelID, msgID Snowflake) (err error) { | |
| err = AddPinnedChannelMessage(c.req, channelID, msgID) | |
| return | |
| } | |
| // DeletePinnedChannelMessage . | |
| func (c *Client) DeletePinnedChannelMessage(channelID, msgID Snowflake) (err error) { | |
| err = DeletePinnedChannelMessage(c.req, channelID, msgID) | |
| return | |
| } | |
| // GroupDMAddRecipient . | |
| func (c *Client) GroupDMAddRecipient(channelID, userID Snowflake, params *GroupDMAddRecipientParams) (err error) { | |
| err = GroupDMAddRecipient(c.req, channelID, userID, params) | |
| return | |
| } | |
| // GroupDMRemoveRecipient . | |
| func (c *Client) GroupDMRemoveRecipient(channelID, userID Snowflake) (err error) { | |
| err = GroupDMRemoveRecipient(c.req, channelID, userID) | |
| return | |
| } | |
| // GetChannelMessages . | |
| func (c *Client) GetChannelMessages(channelID Snowflake, params URLParameters) (ret []*Message, err error) { | |
| ret, err = GetChannelMessages(c.req, channelID, params) | |
| return | |
| } | |
| // GetChannelMessage . | |
| func (c *Client) GetChannelMessage(channelID, messageID Snowflake) (ret *Message, err error) { | |
| ret, err = GetChannelMessage(c.req, channelID, messageID) | |
| return | |
| } | |
| // CreateChannelMessage . | |
| func (c *Client) CreateChannelMessage(channelID Snowflake, params *CreateChannelMessageParams) (ret *Message, err error) { | |
| ret, err = CreateChannelMessage(c.req, channelID, params) | |
| return | |
| } | |
| // EditMessage . | |
| func (c *Client) EditMessage(chanID, msgID Snowflake, params *EditMessageParams) (ret *Message, err error) { | |
| ret, err = EditMessage(c.req, chanID, msgID, params) | |
| return | |
| } | |
| // DeleteMessage . | |
| func (c *Client) DeleteMessage(channelID, msgID Snowflake) (err error) { | |
| err = DeleteMessage(c.req, channelID, msgID) | |
| return | |
| } | |
| // BulkDeleteMessages . | |
| func (c *Client) BulkDeleteMessages(chanID Snowflake, params *BulkDeleteMessagesParams) (err error) { | |
| err = BulkDeleteMessages(c.req, chanID, params) | |
| return | |
| } | |
| // CreateReaction . | |
| func (c *Client) CreateReaction(channelID, messageID Snowflake, emoji interface{}) (ret *Reaction, err error) { | |
| ret, err = CreateReaction(c.req, channelID, messageID, emoji) | |
| return | |
| } | |
| // DeleteOwnReaction . | |
| func (c *Client) DeleteOwnReaction(channelID, messageID Snowflake, emoji interface{}) (err error) { | |
| err = DeleteOwnReaction(c.req, channelID, messageID, emoji) | |
| return | |
| } | |
| // DeleteUserReaction . | |
| func (c *Client) DeleteUserReaction(channelID, messageID, userID Snowflake, emoji interface{}) (err error) { | |
| err = DeleteUserReaction(c.req, channelID, messageID, userID, emoji) | |
| return | |
| } | |
| // GetReaction . | |
| func (c *Client) GetReaction(channelID, messageID Snowflake, emoji interface{}, params URLParameters) (ret []*User, err error) { | |
| ret, err = GetReaction(c.req, channelID, messageID, emoji, params) | |
| return | |
| } | |
| // DeleteAllReactions . | |
| func (c *Client) DeleteAllReactions(channelID, messageID Snowflake) (err error) { | |
| err = DeleteAllReactions(c.req, channelID, messageID) | |
| return | |
| } | |
| // Emoji | |
| // GetGuildEmojis . | |
| func (c *Client) GetGuildEmojis(id Snowflake) (ret []*Emoji, err error) { | |
| var guild *Guild | |
| guild, err = c.cache.GetGuild(id) | |
| if err != nil { | |
| ret, err = ListGuildEmojis(c.req, id) | |
| if err == nil { | |
| c.cache.SetGuildEmojis(id, ret) | |
| } | |
| return | |
| } | |
| ret = guild.Emojis | |
| return | |
| } | |
| // GetGuildEmoji . | |
| func (c *Client) GetGuildEmoji(guildID, emojiID Snowflake) (ret *Emoji, err error) { | |
| var guild *Guild | |
| guild, err = c.cache.GetGuild(guildID) | |
| if err != nil { | |
| ret, err = GetGuildEmoji(c.req, guildID, emojiID) | |
| // TODO: cache | |
| return | |
| } | |
| ret, err = guild.Emoji(emojiID) | |
| if err != nil { | |
| ret, err = GetGuildEmoji(c.req, guildID, emojiID) | |
| // TODO: cache | |
| return | |
| } | |
| return | |
| } | |
| // CreateGuildEmoji . | |
| func (c *Client) CreateGuildEmoji(guildID Snowflake, params *CreateGuildEmojiParams) (ret *Emoji, err error) { | |
| ret, err = CreateGuildEmoji(c.req, guildID, params) | |
| return | |
| } | |
| // ModifyGuildEmoji . | |
| func (c *Client) ModifyGuildEmoji(guildID, emojiID Snowflake, params *ModifyGuildEmojiParams) (ret *Emoji, err error) { | |
| ret, err = ModifyGuildEmoji(c.req, guildID, emojiID, params) | |
| return | |
| } | |
| // DeleteGuildEmoji . | |
| func (c *Client) DeleteGuildEmoji(guildID, emojiID Snowflake) (err error) { | |
| err = DeleteGuildEmoji(c.req, guildID, emojiID) | |
| return | |
| } | |
| // Guild | |
| // CreateGuild . | |
| func (c *Client) CreateGuild(params *CreateGuildParams) (ret *Guild, err error) { | |
| ret, err = CreateGuild(c.req, params) | |
| return | |
| } | |
| // GetGuild . | |
| func (c *Client) GetGuild(id Snowflake) (ret *Guild, err error) { | |
| ret, err = c.cache.GetGuild(id) | |
| if err != nil { | |
| ret, err = GetGuild(c.req, id) | |
| if err != nil { | |
| return | |
| } | |
| c.cache.SetGuild(ret) | |
| } | |
| return | |
| } | |
| // ModifyGuild . | |
| func (c *Client) ModifyGuild(id Snowflake, params *ModifyGuildParams) (ret *Guild, err error) { | |
| ret, err = ModifyGuild(c.req, id, params) | |
| return | |
| } | |
| // DeleteGuild . | |
| func (c *Client) DeleteGuild(id Snowflake) (err error) { | |
| err = DeleteGuild(c.req, id) | |
| return | |
| } | |
| // GetGuildChannels . | |
| func (c *Client) GetGuildChannels(id Snowflake) (ret []*Channel, err error) { | |
| var guild *Guild | |
| guild, err = c.cache.GetGuild(id) | |
| if err != nil { | |
| ret, err = GetGuildChannels(c.req, id) | |
| if err != nil { | |
| return | |
| } | |
| c.cache.SetGuild(&Guild{ | |
| ID: id, | |
| Channels: ret, | |
| }) | |
| } else { | |
| ret = guild.Channels | |
| } | |
| return | |
| } | |
| // CreateGuildChannel . | |
| func (c *Client) CreateGuildChannel(id Snowflake, params *CreateGuildChannelParams) (ret *Channel, err error) { | |
| ret, err = CreateGuildChannel(c.req, id, params) | |
| return | |
| } | |
| // GetGuildMember . | |
| func (c *Client) GetGuildMember(guildID, userID Snowflake) (ret *Member, err error) { | |
| ret, err = c.cache.GetGuildMember(guildID, userID) | |
| if err != nil { | |
| ret, err = GetGuildMember(c.req, guildID, userID) | |
| if err != nil { | |
| return | |
| } | |
| c.cache.SetGuildMember(guildID, ret) | |
| c.cache.Update(UserCache, ret.User) | |
| } | |
| return | |
| } | |
| // GetGuildMembers . | |
| func (c *Client) GetGuildMembers(guildID, after Snowflake, limit int) (ret []*Member, err error) { | |
| ret, err = c.cache.GetGuildMembersAfter(guildID, after, limit) | |
| if err != nil { | |
| ret, err = GetGuildMembers(c.req, guildID, after, limit) | |
| if err != nil { | |
| return | |
| } | |
| c.cache.SetGuildMembers(guildID, ret) | |
| //c.cache.Update(UserCache, ret.User) | |
| // TODO: update users | |
| } | |
| return | |
| } | |
| // AddGuildMember . | |
| func (c *Client) AddGuildMember(guildID, userID Snowflake, params *AddGuildMemberParams) (ret *Member, err error) { | |
| ret, err = AddGuildMember(c.req, guildID, userID, params) | |
| return | |
| } | |
| // ModifyGuildMember . | |
| func (c *Client) ModifyGuildMember(guildID, userID Snowflake, params *ModifyGuildMemberParams) (err error) { | |
| err = ModifyGuildMember(c.req, guildID, userID, params) | |
| return | |
| } | |
| // ModifyCurrentUserNick . | |
| func (c *Client) ModifyCurrentUserNick(id Snowflake, params *ModifyCurrentUserNickParams) (nick string, err error) { | |
| nick, err = ModifyCurrentUserNick(c.req, id, params) | |
| return | |
| } | |
| // AddGuildMemberRole . | |
| func (c *Client) AddGuildMemberRole(guildID, userID, roleID Snowflake) (err error) { | |
| err = AddGuildMemberRole(c.req, guildID, userID, roleID) | |
| return | |
| } | |
| // RemoveGuildMemberRole . | |
| func (c *Client) RemoveGuildMemberRole(guildID, userID, roleID Snowflake) (err error) { | |
| err = RemoveGuildMemberRole(c.req, guildID, userID, roleID) | |
| return | |
| } | |
| // RemoveGuildMember . | |
| func (c *Client) RemoveGuildMember(guildID, userID Snowflake) (err error) { | |
| err = RemoveGuildMember(c.req, guildID, userID) | |
| return | |
| } | |
| // GetGuildBans . | |
| func (c *Client) GetGuildBans(id Snowflake) (ret []*Ban, err error) { | |
| ret, err = GetGuildBans(c.req, id) | |
| return | |
| } | |
| // GetGuildBan . | |
| func (c *Client) GetGuildBan(guildID, userID Snowflake) (ret *Ban, err error) { | |
| ret, err = GetGuildBan(c.req, guildID, userID) | |
| return | |
| } | |
| // CreateGuildBan . | |
| func (c *Client) CreateGuildBan(guildID, userID Snowflake, params *CreateGuildBanParams) (err error) { | |
| err = CreateGuildBan(c.req, guildID, userID, params) | |
| return | |
| } | |
| // RemoveGuildBan . | |
| func (c *Client) RemoveGuildBan(guildID, userID Snowflake) (err error) { | |
| err = RemoveGuildBan(c.req, guildID, userID) | |
| return | |
| } | |
| // GetGuildRoles . | |
| func (c *Client) GetGuildRoles(guildID Snowflake) (ret []*Role, err error) { | |
| ret, err = c.cache.GetGuildRoles(guildID) | |
| if err != nil { | |
| ret, err = GetGuildRoles(c.req, guildID) | |
| if err != nil { | |
| return | |
| } | |
| c.cache.SetGuildRoles(guildID, ret) | |
| } | |
| return | |
| } | |
| // CreateGuildRole . | |
| func (c *Client) CreateGuildRole(id Snowflake, params *CreateGuildRoleParams) (ret *Role, err error) { | |
| ret, err = CreateGuildRole(c.req, id, params) | |
| return | |
| } | |
| // ModifyGuildRolePositions . | |
| func (c *Client) ModifyGuildRolePositions(guildID Snowflake, params *ModifyGuildRolePositionsParams) (ret []*Role, err error) { | |
| ret, err = ModifyGuildRolePositions(c.req, guildID, params) | |
| return | |
| } | |
| // ModifyGuildRole . | |
| func (c *Client) ModifyGuildRole(guildID, roleID Snowflake, params *ModifyGuildRoleParams) (ret *Role, err error) { | |
| ret, err = ModifyGuildRole(c.req, guildID, roleID, params) | |
| return | |
| } | |
| // DeleteGuildRole . | |
| func (c *Client) DeleteGuildRole(guildID, roleID Snowflake) (err error) { | |
| err = DeleteGuildRole(c.req, guildID, roleID) | |
| return | |
| } | |
| // GetGuildPruneCount . | |
| func (c *Client) GetGuildPruneCount(id Snowflake, params *GuildPruneParams) (ret *GuildPruneCount, err error) { | |
| ret, err = GetGuildPruneCount(c.req, id, params) | |
| return | |
| } | |
| // BeginGuildPrune . | |
| func (c *Client) BeginGuildPrune(id Snowflake, params *GuildPruneParams) (ret *GuildPruneCount, err error) { | |
| ret, err = BeginGuildPrune(c.req, id, params) | |
| return | |
| } | |
| // GetGuildVoiceRegions . | |
| func (c *Client) GetGuildVoiceRegions(id Snowflake) (ret []*VoiceRegion, err error) { | |
| ret, err = GetGuildVoiceRegions(c.req, id) | |
| return | |
| } | |
| // GetGuildInvites . | |
| func (c *Client) GetGuildInvites(id Snowflake) (ret []*Invite, err error) { | |
| ret, err = GetGuildInvites(c.req, id) | |
| return | |
| } | |
| // GetGuildIntegrations . | |
| func (c *Client) GetGuildIntegrations(id Snowflake) (ret []*Integration, err error) { | |
| ret, err = GetGuildIntegrations(c.req, id) | |
| return | |
| } | |
| // CreateGuildIntegration . | |
| func (c *Client) CreateGuildIntegration(guildID Snowflake, params *CreateGuildIntegrationParams) (err error) { | |
| err = CreateGuildIntegration(c.req, guildID, params) | |
| return | |
| } | |
| // ModifyGuildIntegration . | |
| func (c *Client) ModifyGuildIntegration(guildID, integrationID Snowflake, params *ModifyGuildIntegrationParams) (err error) { | |
| err = ModifyGuildIntegration(c.req, guildID, integrationID, params) | |
| return | |
| } | |
| // DeleteGuildIntegration . | |
| func (c *Client) DeleteGuildIntegration(guildID, integrationID Snowflake) (err error) { | |
| err = DeleteGuildIntegration(c.req, guildID, integrationID) | |
| return | |
| } | |
| // SyncGuildIntegration . | |
| func (c *Client) SyncGuildIntegration(guildID, integrationID Snowflake) (err error) { | |
| err = SyncGuildIntegration(c.req, guildID, integrationID) | |
| return | |
| } | |
| // GetGuildEmbed . | |
| func (c *Client) GetGuildEmbed(guildID Snowflake) (ret *GuildEmbed, err error) { | |
| ret, err = GetGuildEmbed(c.req, guildID) | |
| return | |
| } | |
| // ModifyGuildEmbed . | |
| func (c *Client) ModifyGuildEmbed(guildID Snowflake, params *GuildEmbed) (ret *GuildEmbed, err error) { | |
| ret, err = ModifyGuildEmbed(c.req, guildID, params) | |
| return | |
| } | |
| // GetGuildVanityURL . | |
| func (c *Client) GetGuildVanityURL(guildID Snowflake) (ret *PartialInvite, err error) { | |
| ret, err = GetGuildVanityURL(c.req, guildID) | |
| return | |
| } | |
| // Invite | |
| // GetInvite . | |
| func (c *Client) GetInvite(inviteCode string, withCounts bool) (invite *Invite, err error) { | |
| invite, err = GetInvite(c.req, inviteCode, withCounts) | |
| return | |
| } | |
| // DeleteInvite . | |
| func (c *Client) DeleteInvite(inviteCode string) (invite *Invite, err error) { | |
| invite, err = DeleteInvite(c.req, inviteCode) | |
| return | |
| } | |
| // User | |
| // GetCurrentUser . | |
| func (c *Client) GetCurrentUser() (ret *User, err error) { | |
| ret, err = GetCurrentUser(c.req) | |
| return | |
| } | |
| // GetUser . | |
| func (c *Client) GetUser(id Snowflake) (ret *User, err error) { | |
| ret, err = c.cache.GetUser(id) | |
| if err != nil { | |
| ret, err = GetUser(c.req, id) | |
| if err != nil { | |
| return | |
| } | |
| c.cache.Update(UserCache, ret) | |
| } | |
| return | |
| } | |
| // ModifyCurrentUser . | |
| func (c *Client) ModifyCurrentUser(params *ModifyCurrentUserParams) (ret *User, err error) { | |
| ret, err = ModifyCurrentUser(c.req, params) | |
| return | |
| } | |
| // GetCurrentUserGuilds . | |
| func (c *Client) GetCurrentUserGuilds(params *GetCurrentUserGuildsParams) (ret []*Guild, err error) { | |
| ret, err = GetCurrentUserGuilds(c.req, params) | |
| return | |
| } | |
| // LeaveGuild . | |
| func (c *Client) LeaveGuild(id Snowflake) (err error) { | |
| err = LeaveGuild(c.req, id) | |
| return | |
| } | |
| // GetUserDMs . | |
| func (c *Client) GetUserDMs() (ret []*Channel, err error) { | |
| ret, err = GetUserDMs(c.req) | |
| return | |
| } | |
| // CreateDM . | |
| func (c *Client) CreateDM(recipientID Snowflake) (ret *Channel, err error) { | |
| ret, err = CreateDM(c.req, recipientID) | |
| return | |
| } | |
| // CreateGroupDM . | |
| func (c *Client) CreateGroupDM(params *CreateGroupDMParams) (ret *Channel, err error) { | |
| ret, err = CreateGroupDM(c.req, params) | |
| return | |
| } | |
| // GetUserConnections . | |
| func (c *Client) GetUserConnections() (ret []*UserConnection, err error) { | |
| ret, err = GetUserConnections(c.req) | |
| return | |
| } | |
| // Voice | |
| // GetVoiceRegions . | |
| func (c *Client) GetVoiceRegions() (ret []*VoiceRegion, err error) { | |
| ret, err = ListVoiceRegions(c.req) | |
| return | |
| } | |
| // Webhook | |
| // CreateWebhook . | |
| func (c *Client) CreateWebhook(channelID Snowflake, params *CreateWebhookParams) (ret *Webhook, err error) { | |
| ret, err = CreateWebhook(c.req, channelID, params) | |
| return | |
| } | |
| // GetChannelWebhooks . | |
| func (c *Client) GetChannelWebhooks(channelID Snowflake) (ret []*Webhook, err error) { | |
| ret, err = GetChannelWebhooks(c.req, channelID) | |
| return | |
| } | |
| // GetGuildWebhooks . | |
| func (c *Client) GetGuildWebhooks(guildID Snowflake) (ret []*Webhook, err error) { | |
| ret, err = GetGuildWebhooks(c.req, guildID) | |
| return | |
| } | |
| // GetWebhook . | |
| func (c *Client) GetWebhook(id Snowflake) (ret *Webhook, err error) { | |
| ret, err = GetWebhook(c.req, id) | |
| return | |
| } | |
| // GetWebhookWithToken . | |
| func (c *Client) GetWebhookWithToken(id Snowflake, token string) (ret *Webhook, err error) { | |
| ret, err = GetWebhookWithToken(c.req, id, token) | |
| return | |
| } | |
| // ModifyWebhook . | |
| func (c *Client) ModifyWebhook(newWebhook *Webhook) (ret *Webhook, err error) { | |
| ret, err = ModifyWebhook(c.req, newWebhook) | |
| return | |
| } | |
| // ModifyWebhookWithToken . | |
| func (c *Client) ModifyWebhookWithToken(newWebhook *Webhook) (ret *Webhook, err error) { | |
| ret, err = ModifyWebhookWithToken(c.req, newWebhook) | |
| return | |
| } | |
| // DeleteWebhook . | |
| func (c *Client) DeleteWebhook(webhookID Snowflake) (err error) { | |
| err = DeleteWebhook(c.req, webhookID) | |
| return | |
| } | |
| // DeleteWebhookWithToken . | |
| func (c *Client) DeleteWebhookWithToken(id Snowflake, token string) (err error) { | |
| err = DeleteWebhookWithToken(c.req, id, token) | |
| return | |
| } | |
| // ExecuteWebhook . | |
| func (c *Client) ExecuteWebhook(params *ExecuteWebhookParams, wait bool, URLSuffix string) (err error) { | |
| err = ExecuteWebhook(c.req, params, wait, URLSuffix) | |
| return | |
| } | |
| // ExecuteSlackWebhook . | |
| func (c *Client) ExecuteSlackWebhook(params *ExecuteWebhookParams, wait bool) (err error) { | |
| err = ExecuteSlackWebhook(c.req, params, wait) | |
| return | |
| } | |
| // ExecuteGitHubWebhook . | |
| func (c *Client) ExecuteGitHubWebhook(params *ExecuteWebhookParams, wait bool) (err error) { | |
| err = ExecuteGitHubWebhook(c.req, params, wait) | |
| return | |
| } | |
| // Custom methods are usually reused by the resource package for readability | |
| // ----- | |
| // SendMsg . | |
| func (c *Client) SendMsg(channelID Snowflake, message *Message) (msg *Message, err error) { | |
| message.RLock() | |
| params := &CreateChannelMessageParams{ | |
| Content: message.Content, | |
| Tts: message.Tts, | |
| // File: ... | |
| // Embed: ... | |
| } | |
| if !message.Nonce.Empty() { | |
| params.Nonce = message.Nonce | |
| } | |
| if len(message.Embeds) > 0 { | |
| params.Embed = message.Embeds[0] | |
| } | |
| message.RUnlock() | |
| return c.CreateChannelMessage(channelID, params) | |
| } | |
| // SendMsgString . | |
| func (c *Client) SendMsgString(channelID Snowflake, content string) (msg *Message, err error) { | |
| params := &CreateChannelMessageParams{ | |
| Content: content, | |
| } | |
| msg, err = c.CreateChannelMessage(channelID, params) | |
| return | |
| } | |
| // UpdateMessage . | |
| func (c *Client) UpdateMessage(message *Message) (msg *Message, err error) { | |
| message.RLock() | |
| defer message.RUnlock() | |
| params := &EditMessageParams{ | |
| Content: message.Content, | |
| } | |
| if len(message.Embeds) > 0 { | |
| params.Embed = message.Embeds[0] | |
| } | |
| msg, err = c.EditMessage(message.ChannelID, message.ID, params) | |
| return | |
| } | |
| // UpdateChannel Not implemented yet | |
| func (c *Client) UpdateChannel(channel *Channel) (err error) { | |
| // there are several different REST calls that needs to be made in order | |
| // to update the channel. But how exactly do we know what has changed? | |
| return errors.New("not implemented") | |
| } | |
| func waitForEvent(eventEmitter <-chan DiscordWSEvent) (event DiscordWSEvent, err error) { | |
| var alive bool | |
| event, alive = <-eventEmitter | |
| if !alive { | |
| err = errors.New("event emitter (channel) is dead") | |
| } | |
| return | |
| } | |
| // eventHandler Takes a incoming event from the websocket package, parses it, and sends | |
| // trigger requests to the event dispatcher and state cacher. | |
| func (c *Client) eventHandler() { | |
| for { | |
| var err error | |
| var evt DiscordWSEvent | |
| evt, err = waitForEvent(c.socketEvtChan) | |
| if err != nil { | |
| return | |
| } | |
| evtName := evt.Name() | |
| var box eventBox | |
| switch evtName { | |
| case EventReady: | |
| box = &Ready{} | |
| case EventResumed: | |
| box = &Resumed{} | |
| case EventChannelCreate: | |
| box = &ChannelCreate{} | |
| case EventChannelUpdate: | |
| box = &ChannelUpdate{} | |
| case EventChannelDelete: | |
| box = &ChannelDelete{} | |
| case EventChannelPinsUpdate: | |
| box = &ChannelPinsUpdate{} | |
| case EventGuildCreate: | |
| box = &GuildCreate{} | |
| case EventGuildUpdate: | |
| box = &GuildUpdate{} | |
| case EventGuildDelete: | |
| box = &GuildDelete{} | |
| case EventGuildBanAdd: | |
| box = &GuildBanAdd{} | |
| case EventGuildBanRemove: | |
| box = &GuildBanRemove{} | |
| case EventGuildEmojisUpdate: | |
| box = &GuildEmojisUpdate{} | |
| case EventGuildIntegrationsUpdate: | |
| box = &GuildIntegrationsUpdate{} | |
| case EventGuildMemberAdd: | |
| box = &GuildMemberAdd{} | |
| case EventGuildMemberRemove: | |
| box = &GuildMemberRemove{} | |
| case EventGuildMemberUpdate: | |
| box = &GuildMemberUpdate{} | |
| case EventGuildMembersChunk: | |
| box = &GuildMembersChunk{} | |
| case EventGuildRoleCreate: | |
| box = &GuildRoleCreate{} | |
| case EventGuildRoleUpdate: | |
| box = &GuildRoleUpdate{} | |
| case EventGuildRoleDelete: | |
| box = &GuildRoleDelete{} | |
| case EventMessageCreate: | |
| box = &MessageCreate{} | |
| case EventMessageUpdate: | |
| box = &MessageUpdate{} | |
| case EventMessageDelete: | |
| box = &MessageDelete{} | |
| case EventMessageDeleteBulk: | |
| box = &MessageDeleteBulk{} | |
| case EventMessageReactionAdd: | |
| box = &MessageReactionAdd{} | |
| case EventMessageReactionRemove: | |
| box = &MessageReactionRemove{} | |
| case EventMessageReactionRemoveAll: | |
| box = &MessageReactionRemoveAll{} | |
| case EventPresenceUpdate: | |
| box = &PresenceUpdate{} | |
| case EventTypingStart: | |
| box = &TypingStart{} | |
| case EventUserUpdate: | |
| box = &UserUpdate{} | |
| case EventVoiceStateUpdate: | |
| box = &VoiceStateUpdate{} | |
| case EventVoiceServerUpdate: | |
| box = &VoiceServerUpdate{} | |
| case EventWebhooksUpdate: | |
| box = &WebhooksUpdate{} | |
| default: | |
| fmt.Printf("------\nTODO\nImplement event handler for `%s`, data: \n%+v\n------\n\n", evtName, string(evt.Data())) | |
| continue // move on to next event | |
| } | |
| // populate box | |
| ctx := context.Background() | |
| box.registerContext(ctx) | |
| data := evt.Data() | |
| // first unmarshal to get identifiers | |
| //tmp := *box | |
| // unmarshal into cache | |
| //err := c.cacheEvent2(evtName, box) | |
| err = unmarshal(data, box) | |
| if err != nil { | |
| logrus.Error(err) | |
| continue // ignore event | |
| // TODO: if an event is ignored, should it not at least send a signal for listeners with no parameters? | |
| } | |
| // cache | |
| c.cacheEvent(evtName, box) | |
| // trigger listeners | |
| c.evtDispatch.triggerChan(ctx, evtName, c, box) | |
| c.evtDispatch.triggerCallbacks(ctx, evtName, c, box) | |
| } | |
| } | |
| func (c *Client) cacheEvent(event string, v interface{}) (err error) { | |
| // updates holds key and object to be cached | |
| updates := map[int]([]interface{}){} | |
| switch event { | |
| case EventReady: | |
| ready := v.(*Ready) | |
| updates[UserCache] = append(updates[UserCache], ready.User) | |
| for _, guild := range ready.Guilds { | |
| updates[GuildCache] = append(updates[GuildCache], guild) | |
| } | |
| case EventVoiceStateUpdate: | |
| update := v.(*VoiceStateUpdate) | |
| updates[VoiceStateCache] = append(updates[VoiceStateCache], update.VoiceState) | |
| case EventChannelCreate, EventChannelUpdate: | |
| var channel *Channel | |
| if event == EventChannelCreate { | |
| channel = (v.(*ChannelCreate)).Channel | |
| } else if event == EventChannelUpdate { | |
| channel = (v.(*ChannelUpdate)).Channel | |
| } | |
| if len(channel.Recipients) > 0 { | |
| for i := range channel.Recipients { | |
| updates[UserCache] = append(updates[UserCache], channel.Recipients[i]) | |
| } | |
| } | |
| updates[ChannelCache] = append(updates[ChannelCache], channel) | |
| case EventChannelDelete: | |
| channel := (v.(*ChannelDelete)).Channel | |
| c.cache.DeleteChannel(channel.ID) | |
| c.cache.DeleteGuildChannel(channel.GuildID, channel.ID) | |
| case EventChannelPinsUpdate: | |
| evt := v.(*ChannelPinsUpdate) | |
| c.cache.UpdateChannelPin(evt.ChannelID, evt.LastPinTimestamp) | |
| case EventGuildCreate, EventGuildUpdate: | |
| var guild *Guild | |
| if event == EventGuildCreate { | |
| guild = (v.(*GuildCreate)).Guild | |
| } else if event == EventGuildUpdate { | |
| guild = (v.(*GuildUpdate)).Guild | |
| } | |
| updates[GuildCache] = append(updates[GuildCache], guild) | |
| // update all users | |
| if len(guild.Members) > 0 { | |
| updates[UserCache] = make([]interface{}, len(guild.Members)) | |
| for i := range guild.Members { | |
| updates[UserCache][i] = guild.Members[i].User | |
| } | |
| } | |
| case EventGuildDelete: | |
| uguild := (v.(*GuildDelete)).UnavailableGuild | |
| c.cache.DeleteGuild(uguild.ID) | |
| case EventGuildRoleDelete: | |
| evt := v.(*GuildRoleDelete) | |
| c.cache.DeleteGuildRole(evt.GuildID, evt.RoleID) | |
| case EventGuildEmojisUpdate: | |
| evt := v.(*GuildEmojisUpdate) | |
| c.cache.SetGuildEmojis(evt.GuildID, evt.Emojis) | |
| case EventUserUpdate: | |
| usr := v.(*UserUpdate).User | |
| updates[UserCache] = append(updates[UserCache], usr) | |
| case EventMessageCreate: | |
| // TODO: performance issues? | |
| msg := (v.(*MessageCreate)).Message | |
| c.cache.UpdateChannelLastMessageID(msg.ChannelID, msg.ID) | |
| default: | |
| err = errors.New("unsupported event for caching") | |
| //case EventResumed: | |
| //case EventGuildBanAdd: | |
| //case EventGuildBanRemove: | |
| //case EventGuildIntegrationsUpdate: | |
| //case EventGuildMemberAdd: | |
| //case EventGuildMemberRemove: | |
| //case EventGuildMemberUpdate: | |
| //case EventGuildMembersChunk: | |
| //case EventGuildRoleCreate: | |
| //case EventGuildRoleUpdate: | |
| //case EventMessageUpdate: | |
| //case EventMessageDelete: | |
| //case EventMessageDeleteBulk: | |
| //case EventMessageReactionAdd: | |
| //case EventMessageReactionRemove: | |
| //case EventMessageReactionRemoveAll: | |
| //case EventPresenceUpdate: | |
| //case EventTypingStart: | |
| //case EventVoiceServerUpdate: | |
| //case EventWebhooksUpdate: | |
| } | |
| for key, structs := range updates { | |
| err = c.cache.Updates(key, structs) | |
| } | |
| return | |
| } |