Finish all gateway events. Still needs testing.

This commit is contained in:
SeanOMik 2020-06-22 15:15:13 -05:00
parent 6dc65dfd23
commit e5504a32d8
No known key found for this signature in database
GPG Key ID: FA4D55AC05268A88
2 changed files with 521 additions and 28 deletions

View File

@ -1,6 +1,6 @@
import eventhandler, json, tables, message, emoji, user, member, role
import guild, channel, nimcordutils, httpClient, strformat, cache
import sequtils, asyncdispatch, clientobjects, discordobject
import sequtils, asyncdispatch, clientobjects, discordobject, presence
proc readyEvent(discordClient: DiscordClient, json: JsonNode) =
var readyEvent = ReadyEvent(client: discordClient, readyPayload: json, name: $EventType.evtReady)
@ -28,7 +28,7 @@ proc channelCreateEvent(discordClient: DiscordClient, json: JsonNode) =
# Add the channel to its guild's `channels` field
if (chnl.guildID != 0):
discordClient.cache.cacheGuildChannel(chnl.guildID, chnl)
discordClient.cache.channels.add(chnl.id, chnl)
discordClient.cache.channels[chnl.id] = chnl
dispatchEvent(channelCreateEvent)
@ -36,10 +36,21 @@ proc channelUpdateEvent(discordClient: DiscordClient, json: JsonNode) =
let chnl = newChannel(json)
let channelUpdateEvent = ChannelUpdateEvent(client: discordClient, channel: chnl, name: $EventType.evtChannelUpdate)
if (discordClient.cache.channels.hasKey(chnl.id)):
discordClient.cache.channels[chnl.id] = chnl
if (chnl.guildID != 0):
let g = discordClient.cache.getGuild(chnl.guildID)
var index = -1
for i, channel in g.channels:
if (channel.id == chnl.id):
index = i
if (index != -1):
g.channels[index] = chnl
else:
discordClient.cache.channels.add(chnl.id, chnl)
g.channels.add(chnl)
dispatchEvent(channelUpdateEvent)
@ -53,14 +64,6 @@ proc channelDeleteEvent(discordClient: DiscordClient, json: JsonNode) =
dispatchEvent(channelDeleteEvent)
proc messageCreateEvent(discordClient: DiscordClient, json: JsonNode) =
let msg = newMessage(json)
discordClient.cache.messages.add(msg.id, msg)
let messageCreateEvnt = MessageCreateEvent(client: discordClient, message: msg, name: $EventType.evtMessageCreate)
dispatchEvent(messageCreateEvnt)
proc channelPinsUpdate(discordClient: DiscordClient, json: JsonNode) =
let channelID = getIDFromJson(json["channel_id"].getStr())
@ -77,21 +80,426 @@ proc guildCreateEvent(discordClient: DiscordClient, json: JsonNode) =
let guildCreateEvnt = GuildCreateEvent(client: discordClient, guild: g, name: $EventType.evtGuildCreate)
# Add guild and its channels and members in cache.
discordClient.cache.guilds.add(g.id, g)
discordClient.cache.guilds[g.id] = g
for channel in g.channels:
discordClient.cache.channels.add(channel.id, channel)
discordClient.cache.channels[channel.id] = channel
for member in g.members:
discordClient.cache.members.add(member.id, member)
discordClient.cache.members[member.id] = member
dispatchEvent(guildCreateEvnt)
proc guildUpdateEvent(discordClient: DiscordClient, json: JsonNode) =
let g = newGuild(json)
let guildUpdateEvent = GuildUpdateEvent(client: discordClient, guild: g, name: $EventType.evtGuildUpdate)
# Update guild in cache.
discordClient.cache.guilds[g.id] = g
dispatchEvent(guildUpdateEvent)
proc guildDeleteEvent(discordClient: DiscordClient, json: JsonNode) =
let g = newGuild(json)
let guildDeleteEvent = GuildDeleteEvent(client: discordClient, guild: g, name: $EventType.evtGuildDelete)
# Remove guild from cache
var removedGuild: Guild
discard discordClient.cache.guilds.pop(g.id, removedGuild)
dispatchEvent(guildDeleteEvent)
proc guildBanAddEvent(discordClient: DiscordClient, json: JsonNode) =
let g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
let user = newUser(json["user"])
let guildBanAddEvent = GuildBanAddEvent(client: discordClient, guild: g, bannedUser: user, name: $EventType.evtGuildBanAdd)
dispatchEvent(guildBanAddEvent)
proc guildBanRemoveEvent(discordClient: DiscordClient, json: JsonNode) =
let g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
let user = newUser(json["user"])
let guildBanRemoveEvent = GuildBanRemoveEvent(client: discordClient, guild: g, unbannedUser: user, name: $EventType.evtGuildBanRemove)
dispatchEvent(guildBanRemoveEvent)
proc guildEmojisUpdateEvent(discordClient: DiscordClient, json: JsonNode) =
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
# Empty g.emojis and fill it with the newly updated emojis
g.emojis = @[]
for emoji in json["emojis"]:
g.emojis.add(newEmoji(emoji, g.id))
let guildEmojisUpdateEvent = GuildEmojisUpdateEvent(client: discordClient, guild: g, emojis: g.emojis, name: $EventType.evtGuildEmojisUpdate)
dispatchEvent(guildEmojisUpdateEvent)
#[ var updatedEmojis: Table[snowflake, Emoji] = initTable[snowflake, Emoji]()
for emoji in json["emojis"]:
var currentEmoji: Emoji = newEmoji(emoji, g.id)
updatedEmojis[currentEmoji.id] = currentEmoji
for emoji in g.emojis:
if updatedEmojis.hasKey(emoji.id):
emoji = updatedEmojis[emoji.id] ]#
#g.emojis.apply
proc guildIntegrationsUpdate(discordClient: DiscordClient, json: JsonNode) =
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
let guildIntegrationsUpdateEvent = GuildIntegrationsUpdateEvent(client: discordClient, guild: g, name: $EventType.evtGuildIntegrationsUpdate)
dispatchEvent(guildIntegrationsUpdateEvent)
proc guildMemberAdd(discordClient: DiscordClient, json: JsonNode) =
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
var newMember = newGuildMember(json, g.id)
let guildMemberAddEvent = GuildMemberAddEvent(client: discordClient, guild: g, member: newMember, name: $EventType.evtGuildMemberAdd)
dispatchEvent(guildMemberAddEvent)
proc guildMemberRemove(discordClient: DiscordClient, json: JsonNode) =
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
var removedUser = newUser(json["user"])
let guildMemberRemoveEvent = GuildMemberRemoveEvent(client: discordClient, guild: g, user: removedUser, name: $EventType.evtGuildMemberRemove)
dispatchEvent(guildMemberRemoveEvent)
proc guildMemberUpdate(discordClient: DiscordClient, json: JsonNode) =
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
var updatedMember = g.getGuildMember(getIDFromJson(json["user"]["id"].getStr()))
updatedMember.user = newUser(json["user"])
updatedMember.roles = @[]
for roleID in json["roles"]:
updatedMember.roles.add(getIDFromJson(roleID.getStr()))
if json.contains("nick"):
updatedMember.nick = json["nick"].getStr()
if json.contains("premium_since"):
updatedMember.premiumSince = json["premium_since"].getStr()
let guildMemberUpdateEvent = GuildMemberUpdateEvent(client: discordClient, guild: g, member: updatedMember, name: $EventType.evtGuildMemberUpdate)
dispatchEvent(guildMemberUpdateEvent)
proc guildMembersChunk(discordClient: DiscordClient, json: JsonNode) =
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
var event = GuildMembersChunkEvent(client: discordClient, guild: g, name: $EventType.evtGuildMembersChunk)
#var members: seq[GuildMember]
for member in json["members"]:
event.members.add(newGuildMember(member, g.id))
event.chunkIndex = json["chunk_index"].getInt()
event.chunkCount = json["chunk_count"].getInt()
if (json.contains("not_found")):
for id in json["not_found"]:
event.notFound.add(getIDFromJson(id.getStr()))
if (json.contains("presences")):
for presence in json["presences"]:
event.presences.add(newPresence(presence))
if (json.contains("nonce")):
event.nonce = json["nonce"].getStr()
dispatchEvent(event)
proc guildRoleCreate(discordClient: DiscordClient, json: JsonNode) =
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
let role = newRole(json["role"], g.id)
g.roles.add(role)
var event = GuildRoleUpdateEvent(client: discordClient, guild: g, role: role, name: $EventType.evtGuildRoleUpdate)
dispatchEvent(event)
proc guildRoleUpdate(discordClient: DiscordClient, json: JsonNode) =
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
let role = newRole(json["role"], g.id)
var index = -1
for i, r in g.roles:
if r.id == role.id:
index = i
g.roles[index] = role
var event = GuildRoleUpdateEvent(client: discordClient, guild: g, role: role, name: $EventType.evtGuildRoleUpdate)
dispatchEvent(event)
proc guildRoleDelete(discordClient: DiscordClient, json: JsonNode) =
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
let roleID = getIDFromJson(json["role_id"].getStr())
var role: Role
var index = -1
for i, r in g.roles:
if r.id == roleID:
index = i
role = r
if index != -1:
g.roles.delete(index)
var event = GuildRoleDeleteEvent(client: discordClient, guild: g, role: role, name: $EventType.evtGuildRoleDelete)
dispatchEvent(event)
proc inviteCreate(discordClient: DiscordClient, json: JsonNode) =
var invite = newInvite(json)
invite.channel = discordClient.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
if (json.contains("guild_id")):
invite.guildID =getIDFromJson(json["guild_id"].getStr())
var event = InviteCreateEvent(client: discordClient, invite: invite, name: $EventType.evtInviteCreate)
dispatchEvent(event)
proc inviteDelete(discordClient: DiscordClient, json: JsonNode) =
var event = InviteDeleteEvent(client: discordClient, name: $EventType.evtInviteDelete)
event.channel = discordClient.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
event.code = json["code"].getStr()
if (json.contains("guild_id")):
event.guild = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
dispatchEvent(event)
proc messageCreateEvent(discordClient: DiscordClient, json: JsonNode) =
let msg = newMessage(json)
discordClient.cache.messages[msg.id] = msg
let messageCreateEvnt = MessageCreateEvent(client: discordClient, message: msg, name: $EventType.evtMessageCreate)
dispatchEvent(messageCreateEvnt)
proc messageUpdateEvent(discordClient: DiscordClient, json: JsonNode) =
let msg = newMessage(json)
discordClient.cache.messages[msg.id] = msg
let event = MessageCreateEvent(client: discordClient, message: msg, name: $EventType.evtMessageUpdate)
dispatchEvent(event)
proc messageDeleteEvent(discordClient: DiscordClient, json: JsonNode) =
let msgID = getIDFromJson(json["id"].getStr())
var msg: Message
if discordClient.cache.messages.hasKey(msgID):
discard discordClient.cache.messages.pop(msgID, msg)
else:
msg = Message(id: msgID)
msg.channelID = getIDFromJson(json["channel_id"].getStr())
if (json.contains("guild_id")):
msg.guildID = getIDFromJson(json["guild_id"].getStr())
let event = MessageDeleteEvent(client: discordClient, message: msg, name: $EventType.evtMessageDelete)
dispatchEvent(event)
proc messageDeleteBulkEvent(discordClient: DiscordClient, json: JsonNode) =
var event = MessageDeleteBulkEvent(client: discordClient, name: $EventType.evtMessageDeleteBulk)
event.channel = discordClient.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
if (json.contains("guild_id")):
event.guild = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
for msgIDJson in json["ids"]:
let msgID = getIDFromJson(msgIDJson.getStr())
var msg: Message
if discordClient.cache.messages.hasKey(msgID):
discard discordClient.cache.messages.pop(msgID, msg)
else:
let channelID = getIDFromJson(json["channel_id"].getStr())
msg = Message(id: msgID, channelID: channelID)
event.channel = discordClient.cache.getChannel(msg.channelID)
if (json.contains("guild_id")):
msg.guildID = getIDFromJson(json["guild_id"].getStr())
event.messages.add(msg)
dispatchEvent(event)
proc messageReactionAdd(discordClient: DiscordClient, json: JsonNode) =
var event = MessageReactionAddEvent(client: discordClient, name: $EventType.evtMessageReactionAdd)
let msgID = getIDFromJson(json["message_id"].getStr())
var msg: Message
if discordClient.cache.messages.hasKey(msgID):
msg = discordClient.cache.messages[msgID]
else:
msg = Message(id: msgID)
msg.channelID = getIDFromJson(json["channel_id"].getStr())
if (json.contains("guild_id")):
msg.guildID = getIDFromJson(json["guild_id"].getStr())
event.user = discordClient.cache.getUser(getIDFromJson(json["user_id"].getStr()))
if (json.contains("member")):
event.member = newGuildMember(json["member"], msg.guildID)
event.emoji = newEmoji(json["emoji"], msg.guildID)
dispatchEvent(event)
proc messageReactionRemove(discordClient: DiscordClient, json: JsonNode) =
var event = MessageReactionRemoveEvent(client: discordClient, name: $EventType.evtMessageReactionRemove)
let msgID = getIDFromJson(json["message_id"].getStr())
var msg: Message
if discordClient.cache.messages.hasKey(msgID):
msg = discordClient.cache.messages[msgID]
else:
msg = Message(id: msgID)
msg.channelID = getIDFromJson(json["channel_id"].getStr())
if (json.contains("guild_id")):
msg.guildID = getIDFromJson(json["guild_id"].getStr())
event.user = discordClient.cache.getUser(getIDFromJson(json["user_id"].getStr()))
event.emoji = newEmoji(json["emoji"], msg.guildID)
dispatchEvent(event)
proc messageReactionRemoveAll(discordClient: DiscordClient, json: JsonNode) =
var event = MessageReactionRemoveAllEvent(client: discordClient, name: $EventType.evtMessageReactionRemoveAll)
let msgID = getIDFromJson(json["message_id"].getStr())
var msg: Message
if discordClient.cache.messages.hasKey(msgID):
msg = discordClient.cache.messages[msgID]
else:
msg = Message(id: msgID)
msg.channelID = getIDFromJson(json["channel_id"].getStr())
if (json.contains("guild_id")):
msg.guildID = getIDFromJson(json["guild_id"].getStr())
dispatchEvent(event)
proc messageReactionRemoveEmoji(discordClient: DiscordClient, json: JsonNode) =
var event = MessageReactionRemoveEmojiEvent(client: discordClient, name: $EventType.evtMessageReactionRemoveEmoji)
let msgID = getIDFromJson(json["message_id"].getStr())
var msg: Message
if discordClient.cache.messages.hasKey(msgID):
msg = discordClient.cache.messages[msgID]
else:
msg = Message(id: msgID)
msg.channelID = getIDFromJson(json["channel_id"].getStr())
if (json.contains("guild_id")):
msg.guildID = getIDFromJson(json["guild_id"].getStr())
event.emoji = newEmoji(json["emoji"], msg.guildID)
dispatchEvent(event)
proc presenceUpdate(discordClient: DiscordClient, json: JsonNode) =
# This proc doesn't actually dispatch any events,
# it just updates member.presence
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
var member = g.getGuildMember(getIDFromJson(json["user"]["id"].getStr()))
# Make sure some member fields are upto date.
member.roles = @[]
for role in json["roles"]:
member.roles.add(getIDFromJson(role.getStr()))
if (json.contains("premium_since")):
member.premiumSince = json["premium_since"].getStr()
if (json.contains("nick")):
member.nick = json["nick"].getStr()
member.presence = newPresence(json)
proc typingStart(discordClient: DiscordClient, json: JsonNode) =
var event = TypingStartEvent(client: discordClient, name: $EventType.evtTypingStart)
event.channel = discordClient.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
if (json.contains("guild_id")):
event.channel.guildID = getIDFromJson(json["guild_id"].getStr())
event.user = discordClient.cache.getUser(getIDFromJson(json["user_id"].getStr()))
if (json.contains("member")):
event.member = newGuildMember(json["member"], event.channel.guildID)
dispatchEvent(event)
proc userUpdate(discordClient: DiscordClient, json: JsonNode) =
var event = UserUpdateEvent(client: discordClient, name: $EventType.evtUserUpdate)
event.user = newUser(json)
dispatchEvent(event)
proc voiceStateUpdate(discordClient: DiscordClient, json: JsonNode) =
var event = VoiceStateUpdateEvent(client: discordClient, name: $EventType.evtVoiceStateUpdate)
dispatchEvent(event)
proc voiceServerUpdate(discordClient: DiscordClient, json: JsonNode) =
var event = VoiceServerUpdateEvent(client: discordClient, name: $EventType.evtVoiceServerUpdate)
event.token = json["token"].getStr()
event.guild = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
event.endpoint = json["endpoint"].getStr()
dispatchEvent(event)
proc webhooksUpdate(discordClient: DiscordClient, json: JsonNode) =
var event = WebhooksUpdateEvent(client: discordClient, name: $EventType.evtWebhooksUpdate)
event.guild = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
event.channel = discordClient.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
dispatchEvent(event)
let internalEventTable: Table[string, proc(discordClient: DiscordClient, json: JsonNode) {.nimcall.}] = {
"READY": readyEvent,
"MESSAGE_CREATE": messageCreateEvent,
"GUILD_CREATE": guildCreateEvent,
"CHANNEL_CREATE": channelCreateEvent,
"CHANNEL_UPDATE": channelUpdateEvent,
"CHANNEL_DELETE": channelDeleteEvent
"CHANNEL_DELETE": channelDeleteEvent,
"CHANNEL_PINS_UPDATE": channelPinsUpdate,
"GUILD_CREATE": guildCreateEvent,
"GUILD_UPDATE": guildUpdateEvent,
"GUILD_DELETE": guildDeleteEvent,
"GUILD_BAN_ADD": guildBanAddEvent,
"GUILD_BAN_REMOVE": guildBanRemoveEvent,
"GUILD_EMOJIS_UPDATE": guildEmojisUpdateEvent,
"GUILD_INTEGRATIONS_UPDATE": guildIntegrationsUpdate,
"GUILD_MEMBER_ADD": guildMemberAdd,
"GUILD_MEMBER_REMOVE": guildMemberRemove,
"GUILD_MEMBER_UPDATE": guildMemberUpdate,
"GUILD_MEMBER_CHUNK": guildMembersChunk,
"GUILD_ROLE_CREATE": guildRoleCreate,
"GUILD_ROLE_UPDATE": guildRoleUpdate,
"GUILD_ROLE_DELETE": guildRoleDelete,
"INVITE_CREATE": inviteCreate,
"INVITE_DELETE": inviteDelete,
"MESSAGE_CREATE": messageCreateEvent,
"MESSAGE_DELETE": messageDeleteEvent,
"MESSAGE_DELETE_BULK": messageDeleteBulkEvent,
"MESSAGE_REACTION_ADD": messageReactionAdd,
"MESSAGE_REACTION_REMOVE": messageReactionRemove,
"MESSAGE_REACTION_REMOVE_ALL": messageReactionRemoveAll,
"MESSAGE_REACTION_REMOVE_EMOJI": messageReactionRemoveEmoji,
"PRESENCE_UPDATE": presenceUpdate,
"TYPING_START": typingStart,
"USER_UPDATE": userUpdate,
"VOICE_STATE_UPDATE": voiceStateUpdate,
"VOICE_SERVER_UPDATE": voiceServerUpdate,
"WEBHOOKS_UPDATE": webhooksUpdate
}.toTable
proc handleDiscordEvent*(discordClient: DiscordClient, json: JsonNode, eventName: string) {.async.} =

View File

@ -1,4 +1,5 @@
import tables, hashes, json, message, emoji, user, member, role, guild, channel, clientobjects
import discordobject, presence
type
EventType* = enum
@ -25,6 +26,8 @@ type
evtGuildRoleCreate = "GUILD_ROLE_CREATE"
evtGuildRoleUpdate = "GUILD_ROLE_UPDATE"
evtGuildRoleDelete = "GUILD_ROLE_DELETE"
evtInviteCreate = "INVITE_CREATE"
evtInviteDelete = "INVITE_DELETE"
evtMessageUpdate = "MESSAGE_UPDATE"
evtMessageDelete = "MESSAGE_DELETE"
evtMessageCreate = "MESSAGE_CREATE"
@ -32,6 +35,7 @@ type
evtMessageReactionAdd = "MESSAGE_REACTION_ADD"
evtMessageReactionRemove = "MESSAGE_REACTION_REMOVE"
evtMessageReactionRemoveAll = "MESSAGE_REACTION_REMOVE_ALL"
evtMessageReactionRemoveEmoji = "MESSAGE_REACTION_REMOVE_EMOJI"
evtPresenceUpdate = "PRESENCE_UPDATE"
evtTypingStart = "TYPING_START"
evtUserUpdate = "USER_UPDATE"
@ -88,36 +92,47 @@ type
GuildBanAddEvent* = object of BaseEvent
## The Guild Ban Add Event is triggered when a member is banned from the guild.
guild*: Guild
guild_member*: GuildMember
bannedUser*: User
GuildBanRemoveEvent* = object of BaseEvent
## The Guild Ban Remove Event is triggered when a member is unbanned from a guild.
guild*: Guild
guild_member*: GuildMember
unbannedUser*: User
GuildEmojisUpdateEvent* = object of BaseEvent
## The Guild Emojis Update event is triggered when a guild emote is updated.
guild*: Guild
emoji*: Emoji
emojis*: seq[Emoji]
#GuildIntegrationsUpdateEvent* = object of BaseEvent
GuildIntegrationsUpdateEvent* = object of BaseEvent
## Dispatched when a guild integration is updated.
guild*: Guild
GuildMemberAddEvent* = object of BaseEvent
## The Guild Member Add event is triggered when a user joins a guild.
guild*: Guild
guild_member*: GuildMember
member*: GuildMember
GuildMemberRemoveEvent* = object of BaseEvent
## The Guild Member Remove event is triggered when a user leaves a guild.
guild*: Guild
guild_member*: GuildMember
user*: User
GuildMemberUpdateEvent* = object of BaseEvent
## The Guild Member Update event is triggered when a member is updated.
guild*: Guild
guild_member*: GuildMember
member*: GuildMember
#GuildMembersChunkEvent* = object of BaseEvent
GuildMembersChunkEvent* = object of BaseEvent
## Sent in response to a Guild Request Members request. You can use the chunkIndex
## and chunkCount to calculate how many chunks are left for your request.
guild*: Guild
members*: seq[GuildMember]
chunkIndex*: int
chunkCount*: int
notFound*: seq[snowflake]
presences*: seq[Presence]
nonce*: string
GuildRoleCreateEvent* = object of BaseEvent
## The Guild Role Create event is triggered when a role is created.
@ -134,6 +149,16 @@ type
guild*: Guild
role*: Role
InviteCreateEvent* = object of BaseEvent
## Sent when a new invite to a channel is created.
invite*: Invite
InviteDeleteEvent* = object of BaseEvent
## Sent when a new invite to a channel is created.
channel*: Channel
guild*: Guild
code*: string
# Message events
MessageCreateEvent* = object of BaseEvent
@ -146,8 +171,68 @@ type
MessageDeleteEvent* = object of BaseEvent
## The Message Create event is triggered when a message is deleted.
## Most message fields will be empty if the message was not cached.
## The ID and channelID field will always be valid.
## The guildID may be valid if it was deleted in a guild.
message*: Message
MessageDeleteBulkEvent* = object of BaseEvent
## The Message Create event is triggered when a message is deleted.
## Most message fields will be empty if the message was not cached.
## The ID and channelID field will always be valid.
## The guildID may be valid if it was deleted in a guild.
channel*: Channel
guild*: Guild
messages*: seq[Message]
MessageReactionAddEvent* = object of BaseEvent
## Dispatched when a user adds a reaction to a message.
message*: Message
emoji*: Emoji
user*: User
member*: GuildMember ## Only valid in guilds
MessageReactionRemoveEvent* = object of BaseEvent
## Dispatched when a user removes a reaction to a message.
message*: Message
emoji*: Emoji
user*: User
MessageReactionRemoveAllEvent* = object of BaseEvent
## Dispatched when a user explicitly removes all reactions from a message.
message*: Message
MessageReactionRemoveEmojiEvent* = object of BaseEvent
## Dispatched when a user explicitly removes all reactions from a message.
message*: Message
emoji*: Emoji
TypingStartEvent* = object of BaseEvent
## Dispatched when a user starts typing in a channel.
user*: User
channel*: Channel
member*: GuildMember
UserUpdateEvent* = object of BaseEvent
## Dispatched when properties about the user change.
user*: User
VoiceStateUpdateEvent* = object of BaseEvent
## Dispatched when someone joins/leaves/moves voice channels.
voiceState*: VoiceState
VoiceServerUpdateEvent* = object of BaseEvent
## Dispatched when a guild's voice server is updated. This is sent when
## initially connecting to voice, and when the current voice instance fails
## over to a new server.
token*: string
guild*: Guild
endpoint*: string
WebhooksUpdateEvent* = object of BaseEvent
## Dispatched when a guild channel's webhook is created, updated, or deleted.
guild*: Guild
channel*: Channel
# Table storing all the event listeners
let eventListeners = newTable[string, seq[proc(event: BaseEvent)]]()