Sharding
This commit is contained in:
parent
1fe136186d
commit
8a9436f831
|
@ -45,6 +45,6 @@ You can view examples in the [examples](examples) directory.
|
||||||
- [ ] Channel
|
- [ ] Channel
|
||||||
- [ ] Guild
|
- [ ] Guild
|
||||||
- [ ] Misc.
|
- [ ] Misc.
|
||||||
- [ ] Sharding.
|
- [x] Sharding.
|
||||||
- [ ] Audit log.
|
- [ ] Audit log.
|
||||||
- [ ] Voice.
|
- [ ] Voice.
|
|
@ -1,4 +1,4 @@
|
||||||
import nimcord, asyncdispatch, streams, os, strutils, options
|
import ../src/nimcord, asyncdispatch, streams, os, strutils, options, websocket
|
||||||
|
|
||||||
var tokenStream = newFileStream("token.txt", fmRead)
|
var tokenStream = newFileStream("token.txt", fmRead)
|
||||||
var tkn: string
|
var tkn: string
|
||||||
|
@ -19,37 +19,37 @@ registerEventListener(EventType.evtReady, proc(bEvt: BaseEvent) =
|
||||||
echo "--------------------"
|
echo "--------------------"
|
||||||
|
|
||||||
let presence = newPresence("with Nimcord", activityTypeGame, clientStatusIdle, false)
|
let presence = newPresence("with Nimcord", activityTypeGame, clientStatusIdle, false)
|
||||||
asyncCheck event.client.updateClientPresence(presence)
|
asyncCheck event.shard.updateClientPresence(presence)
|
||||||
)
|
)
|
||||||
|
|
||||||
registerEventListener(EventType.evtMessageCreate, proc(bEvt: BaseEvent) =
|
registerEventListener(EventType.evtMessageCreate, proc(bEvt: BaseEvent) =
|
||||||
let event = MessageCreateEvent(bEvt)
|
let event = MessageCreateEvent(bEvt)
|
||||||
|
|
||||||
if (event.message.content == "?ping"):
|
if (event.message.content == "?ping"):
|
||||||
var channel: Channel = event.message.getMessageChannel(event.client.cache)
|
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
||||||
if (channel != nil):
|
if (channel != nil):
|
||||||
discard channel.sendMessage("PONG")
|
discard channel.sendMessage("PONG")
|
||||||
elif (event.message.content.startsWith("?modifyChannelTopic")):
|
elif (event.message.content.startsWith("?modifyChannelTopic")):
|
||||||
let modifyTopic = event.message.content.substr(20)
|
let modifyTopic = event.message.content.substr(20)
|
||||||
|
|
||||||
var channel: Channel = event.message.getMessageChannel(event.client.cache)
|
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
||||||
if (channel != nil):
|
if (channel != nil):
|
||||||
discard channel.sendMessage("Modifing Channel!")
|
discard channel.sendMessage("Modifing Channel!")
|
||||||
discard channel.modifyChannel(ChannelFields(topic: some(modifyTopic)))
|
discard channel.modifyChannel(ChannelFields(topic: some(modifyTopic)))
|
||||||
elif (event.message.content.startsWith("?deleteChannel")):
|
elif (event.message.content.startsWith("?deleteChannel")):
|
||||||
let channelID = getIDFromJson(event.message.content.substr(15))
|
let channelID = getIDFromJson(event.message.content.substr(15))
|
||||||
var channel: Channel = event.client.cache.getChannel(channelID)
|
var channel: Channel = event.shard.client.cache.getChannel(channelID)
|
||||||
|
|
||||||
if (channel != nil):
|
if (channel != nil):
|
||||||
discard channel.sendMessage("Deleting Channel!")
|
discard channel.sendMessage("Deleting Channel!")
|
||||||
discard channel.deleteChannel()
|
discard channel.deleteChannel()
|
||||||
discard channel.sendMessage("Deleted Channel!")
|
discard channel.sendMessage("Deleted Channel!")
|
||||||
elif (event.message.content.startsWith("?getMessages")):
|
elif (event.message.content.startsWith("?getMessages")):
|
||||||
var channel: Channel = event.message.getMessageChannel(event.client.cache)
|
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
||||||
if (channel != nil):
|
if (channel != nil):
|
||||||
discard channel.getMessages(MessagesGetRequest(limit: some(15), before: some(event.message.id)))
|
discard channel.getMessages(MessagesGetRequest(limit: some(15), before: some(event.message.id)))
|
||||||
elif (event.message.content.startsWith("?bulkDeleteMessages")):
|
elif (event.message.content.startsWith("?bulkDeleteMessages")):
|
||||||
var channel: Channel = event.message.getMessageChannel(event.client.cache)
|
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
||||||
if (channel != nil):
|
if (channel != nil):
|
||||||
var amount: int = 25
|
var amount: int = 25
|
||||||
if (event.message.content.len > 19):
|
if (event.message.content.len > 19):
|
||||||
|
@ -57,13 +57,13 @@ registerEventListener(EventType.evtMessageCreate, proc(bEvt: BaseEvent) =
|
||||||
let messages = channel.getMessages(MessagesGetRequest(limit: some(amount), before: some(event.message.id)))
|
let messages = channel.getMessages(MessagesGetRequest(limit: some(amount), before: some(event.message.id)))
|
||||||
discard channel.bulkDeleteMessages(messages)
|
discard channel.bulkDeleteMessages(messages)
|
||||||
elif (event.message.content.startsWith("?reactToMessage")):
|
elif (event.message.content.startsWith("?reactToMessage")):
|
||||||
var channel: Channel = event.message.getMessageChannel(event.client.cache)
|
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
||||||
if (channel != nil):
|
if (channel != nil):
|
||||||
let emojis = @[newEmoji("⏮️"), newEmoji("⬅️"), newEmoji("⏹️"), newEmoji("➡️"), newEmoji("⏭️")]
|
let emojis = @[newEmoji("⏮️"), newEmoji("⬅️"), newEmoji("⏹️"), newEmoji("➡️"), newEmoji("⏭️")]
|
||||||
for emoji in emojis:
|
for emoji in emojis:
|
||||||
discard event.message.addReaction(emoji)
|
discard event.message.addReaction(emoji)
|
||||||
elif (event.message.content.startsWith("?testEmbed")):
|
elif (event.message.content.startsWith("?testEmbed")):
|
||||||
var channel: Channel = event.message.getMessageChannel(event.client.cache)
|
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
||||||
if (channel != nil):
|
if (channel != nil):
|
||||||
var embed = Embed()
|
var embed = Embed()
|
||||||
embed.setTitle("This embed is being sent from Nimcord!")
|
embed.setTitle("This embed is being sent from Nimcord!")
|
||||||
|
@ -74,7 +74,7 @@ registerEventListener(EventType.evtMessageCreate, proc(bEvt: BaseEvent) =
|
||||||
embed.setColor(0xffb900)
|
embed.setColor(0xffb900)
|
||||||
discard channel.sendMessage("", false, embed)
|
discard channel.sendMessage("", false, embed)
|
||||||
elif (event.message.content.startsWith("?sendFile")):
|
elif (event.message.content.startsWith("?sendFile")):
|
||||||
var channel: Channel = event.message.getMessageChannel(event.client.cache)
|
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
||||||
if (channel != nil):
|
if (channel != nil):
|
||||||
let filePath = event.message.content.substr(10)
|
let filePath = event.message.content.substr(10)
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ registerEventListener(EventType.evtMessageCreate, proc(bEvt: BaseEvent) =
|
||||||
let file = DiscordFile(filePath: filePath, fileName: fileName)
|
let file = DiscordFile(filePath: filePath, fileName: fileName)
|
||||||
discard channel.sendMessage("", false, nil, @[file])
|
discard channel.sendMessage("", false, nil, @[file])
|
||||||
elif (event.message.content.startsWith("?sendImage")):
|
elif (event.message.content.startsWith("?sendImage")):
|
||||||
var channel: Channel = event.message.getMessageChannel(event.client.cache)
|
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
||||||
if (channel != nil):
|
if (channel != nil):
|
||||||
let filePath = event.message.content.substr(11)
|
let filePath = event.message.content.substr(11)
|
||||||
|
|
||||||
|
@ -99,4 +99,4 @@ registerEventListener(EventType.evtMessageCreate, proc(bEvt: BaseEvent) =
|
||||||
discard channel.sendMessage("", false, embed, @[file])
|
discard channel.sendMessage("", false, embed, @[file])
|
||||||
)
|
)
|
||||||
|
|
||||||
waitFor bot.startConnection()
|
waitFor bot.startConnection(2)
|
|
@ -16,7 +16,7 @@ type
|
||||||
opHello = 10,
|
opHello = 10,
|
||||||
opHeartbeatAck = 11
|
opHeartbeatAck = 11
|
||||||
|
|
||||||
proc sendGatewayRequest*(client: DiscordClient, request: JsonNode, msg: string = "") {.async.} =
|
proc sendGatewayRequest*(shard: Shard, request: JsonNode, msg: string = "") {.async.} =
|
||||||
## Send a gateway request.
|
## Send a gateway request.
|
||||||
## Don't use this unless you know what you're doing!
|
## Don't use this unless you know what you're doing!
|
||||||
if (msg.len == 0):
|
if (msg.len == 0):
|
||||||
|
@ -24,50 +24,62 @@ proc sendGatewayRequest*(client: DiscordClient, request: JsonNode, msg: string =
|
||||||
else:
|
else:
|
||||||
echo msg
|
echo msg
|
||||||
|
|
||||||
await client.ws.sendText($request)
|
await shard.ws.sendText($request)
|
||||||
|
|
||||||
proc handleHeartbeat(client: DiscordClient) {.async.} =
|
proc handleHeartbeat(shard: Shard) {.async.} =
|
||||||
while true:
|
while true:
|
||||||
var heartbeatPayload: JsonNode
|
var heartbeatPayload: JsonNode
|
||||||
if (client.lastSequence == 0):
|
if (shard.lastSequence == 0):
|
||||||
heartbeatPayload = %* { "d": nil, "op": ord(DiscordOpCode.opHeartbeat) }
|
heartbeatPayload = %* { "d": nil, "op": ord(DiscordOpCode.opHeartbeat) }
|
||||||
else:
|
else:
|
||||||
heartbeatPayload = %* { "d": client.lastSequence, "op": ord(DiscordOpCode.opHeartbeat) }
|
heartbeatPayload = %* { "d": shard.lastSequence, "op": ord(DiscordOpCode.opHeartbeat) }
|
||||||
|
|
||||||
await client.sendGatewayRequest(heartbeatPayload, fmt("Sending heartbeat payload: {$heartbeatPayload}"))
|
await shard.sendGatewayRequest(heartbeatPayload, fmt("Sending heartbeat payload: {$heartbeatPayload}"))
|
||||||
client.heartbeatAcked = true
|
shard.heartbeatAcked = true
|
||||||
|
|
||||||
echo "Waiting ", client.heartbeatInterval, " ms until next heartbeat..."
|
echo "Waiting ", shard.heartbeatInterval, " ms until next heartbeat..."
|
||||||
await sleepAsync(client.heartbeatInterval)
|
await sleepAsync(shard.heartbeatInterval)
|
||||||
|
|
||||||
proc getIdentifyPacket(client: DiscordClient): JsonNode =
|
proc getIdentifyPacket(shard: Shard): JsonNode =
|
||||||
return %* { "op": ord(DiscordOpCode.opIdentify), "d": { "token": client.token, "properties": { "$os": system.hostOS, "$browser": "NimCord", "$device": "NimCord" } } }
|
return %* {
|
||||||
|
"op": ord(DiscordOpCode.opIdentify),
|
||||||
|
"d": {
|
||||||
|
"token": shard.client.token,
|
||||||
|
"shard": [shard.id, shard.client.shardCount],
|
||||||
|
"properties": {
|
||||||
|
"$os": system.hostOS,
|
||||||
|
"$browser": "NimCord",
|
||||||
|
"$device": "NimCord"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
proc startConnection*(client: DiscordClient) {.async.}
|
# For some reason this shows as an error in VSCode, but it compiles fine.
|
||||||
|
#proc startConnection*(client: DiscordClient, shardCount: int = 1) {.async.}
|
||||||
|
|
||||||
proc closeConnection*(client: DiscordClient, code: int = 1000) {.async.} =
|
proc closeConnection*(shard: Shard, code: int = 1000) {.async.} =
|
||||||
echo "Disconnecting with code: ", code
|
echo "Disconnecting with code: ", code
|
||||||
await client.ws.close(code)
|
await shard.ws.close(code)
|
||||||
|
|
||||||
proc reconnectClient(client: DiscordClient) {.async.} =
|
proc reconnectShard(shard: Shard) {.async.} =
|
||||||
echo "Reconnecting..."
|
echo "Reconnecting..."
|
||||||
client.reconnecting = true
|
shard.reconnecting = true
|
||||||
await client.ws.close(1000)
|
await shard.ws.close(1000)
|
||||||
|
|
||||||
client.ws = await newAsyncWebsocketClient(client.endpoint[6..client.endpoint.high], Port 443,
|
shard.ws = await newAsyncWebsocketClient(shard.client.endpoint[6..shard.client.endpoint.high], Port 443,
|
||||||
path = "/v=6&encoding=json", true)
|
path = "/v=6&encoding=json", true)
|
||||||
|
|
||||||
client.reconnecting = false
|
shard.reconnecting = false
|
||||||
client.heartbeatAcked = true
|
shard.heartbeatAcked = true
|
||||||
#waitFor client.startConnection()
|
#waitFor client.startConnection()
|
||||||
|
|
||||||
# Handle discord disconnect. If it detects that we can reconnect, it will.
|
# Handle discord disconnect. If it detects that we can reconnect, it will.
|
||||||
proc handleDiscordDisconnect(client: DiscordClient, error: string) {.async.} =
|
proc handleGatewayDisconnect(shard: Shard, error: string) {.async.} =
|
||||||
let disconnectData = extractCloseData(error)
|
let disconnectData = extractCloseData(error)
|
||||||
|
|
||||||
echo "Discord gateway disconnected! Error code: ", disconnectData.code, ", msg: ", disconnectData.reason
|
echo "Discord gateway disconnected! Error code: ", disconnectData.code, ", msg: ", disconnectData.reason
|
||||||
|
|
||||||
client.heartbeatAcked = false
|
shard.heartbeatAcked = false
|
||||||
|
|
||||||
# Get the disconnect code
|
# Get the disconnect code
|
||||||
let c = disconnectData.code
|
let c = disconnectData.code
|
||||||
|
@ -76,22 +88,22 @@ proc handleDiscordDisconnect(client: DiscordClient, error: string) {.async.} =
|
||||||
if ( (c >= 4003 and c <= 4005) or c == 4007 or (c >= 4010 and c <= 4013) ):
|
if ( (c >= 4003 and c <= 4005) or c == 4007 or (c >= 4010 and c <= 4013) ):
|
||||||
echo "The Discord gateway sent a disconnect code that we cannot reconnect to."
|
echo "The Discord gateway sent a disconnect code that we cannot reconnect to."
|
||||||
else:
|
else:
|
||||||
if (not client.reconnecting):
|
if (not shard.reconnecting):
|
||||||
waitFor client.reconnectClient()
|
waitFor shard.reconnectShard()
|
||||||
else:
|
else:
|
||||||
echo "Gateway is cannot reconnect due to already reconnecting..."
|
echo "Gateway is cannot reconnect due to already reconnecting..."
|
||||||
|
|
||||||
|
|
||||||
#TODO: Reconnecting may be done, just needs testing.
|
#TODO: Reconnecting may be done, just needs testing.
|
||||||
proc handleWebsocketPacket(client: DiscordClient) {.async.} =
|
proc handleWebsocketPacket(shard: Shard) {.async.} =
|
||||||
while true:
|
while true:
|
||||||
var packet: tuple[opcode: Opcode, data: string]
|
var packet: tuple[opcode: Opcode, data: string]
|
||||||
|
|
||||||
packet = await client.ws.readData();
|
packet = await shard.ws.readData();
|
||||||
echo "Received gateway payload: ", packet.data
|
echo "[SHARD ", $shard.id, "] Received gateway payload: ", packet.data
|
||||||
|
|
||||||
if packet.opcode == Opcode.Close:
|
if packet.opcode == Opcode.Close:
|
||||||
await client.handleDiscordDisconnect(packet.data)
|
await shard.handleGatewayDisconnect(packet.data)
|
||||||
|
|
||||||
var json: JsonNode
|
var json: JsonNode
|
||||||
|
|
||||||
|
@ -103,52 +115,55 @@ proc handleWebsocketPacket(client: DiscordClient) {.async.} =
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if (json.contains("s")):
|
if (json.contains("s")):
|
||||||
client.lastSequence = json["s"].getInt()
|
shard.lastSequence = json["s"].getInt()
|
||||||
|
|
||||||
case json["op"].getInt()
|
case json["op"].getInt()
|
||||||
of ord(DiscordOpCode.opHello):
|
of ord(DiscordOpCode.opHello):
|
||||||
if client.reconnecting:
|
if shard.reconnecting:
|
||||||
echo "Reconnected!"
|
echo "Reconnected!"
|
||||||
client.reconnecting = false
|
shard.reconnecting = false
|
||||||
|
|
||||||
let resume = %* {
|
let resume = %* {
|
||||||
"op": ord(opResume),
|
"op": ord(opResume),
|
||||||
"d": {
|
"d": {
|
||||||
"token": client.token,
|
"token": shard.client.token,
|
||||||
"session_id": client.sessionID,
|
"session_id": shard.sessionID,
|
||||||
"seq": client.lastSequence
|
"seq": shard.lastSequence
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await client.sendGatewayRequest(resume)
|
await shard.sendGatewayRequest(resume)
|
||||||
else:
|
else:
|
||||||
client.heartbeatInterval = json["d"]["heartbeat_interval"].getInt()
|
shard.heartbeatInterval = json["d"]["heartbeat_interval"].getInt()
|
||||||
await client.sendGatewayRequest(client.getIdentifyPacket())
|
await shard.sendGatewayRequest(shard.getIdentifyPacket())
|
||||||
|
|
||||||
asyncCheck client.handleHeartbeat()
|
asyncCheck shard.handleHeartbeat()
|
||||||
client.heartbeatAcked = true
|
shard.heartbeatAcked = true
|
||||||
of ord(DiscordOpCode.opHeartbeatAck):
|
of ord(DiscordOpCode.opHeartbeatAck):
|
||||||
client.heartbeatAcked = true
|
shard.heartbeatAcked = true
|
||||||
of ord(DiscordOpCode.opDispatch):
|
of ord(DiscordOpCode.opDispatch):
|
||||||
asyncCheck handleDiscordEvent(client, json["d"], json["t"].getStr())
|
asyncCheck handleDiscordEvent(shard, json["d"], json["t"].getStr())
|
||||||
of ord(DiscordOpCode.opReconnect):
|
of ord(DiscordOpCode.opReconnect):
|
||||||
asyncCheck client.reconnectClient()
|
asyncCheck shard.reconnectShard()
|
||||||
of ord(DiscordOpCode.opInvalidSession):
|
of ord(DiscordOpCode.opInvalidSession):
|
||||||
# If the json field `d` is true then the session may be resumable.
|
# If the json field `d` is true then the session may be resumable.
|
||||||
if json["d"].getBool():
|
if json["d"].getBool():
|
||||||
let resume = %* {
|
let resume = %* {
|
||||||
"op": ord(opResume),
|
"op": ord(opResume),
|
||||||
"session_id": client.sessionID,
|
"session_id": shard.sessionID,
|
||||||
"seq": client.lastSequence
|
"seq": shard.lastSequence
|
||||||
}
|
}
|
||||||
|
|
||||||
await client.sendGatewayRequest(resume)
|
await shard.sendGatewayRequest(resume)
|
||||||
else:
|
else:
|
||||||
asyncCheck client.reconnectClient()
|
asyncCheck shard.reconnectShard()
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc startConnection*(client: DiscordClient) {.async.} =
|
proc newShard(shardID: int, client: DiscordClient): Shard =
|
||||||
|
return Shard(id: shardID, client: client)
|
||||||
|
|
||||||
|
proc startConnection*(client: DiscordClient, shardAmount: int = 1) {.async.} =
|
||||||
## Start a bot connection.
|
## Start a bot connection.
|
||||||
##
|
##
|
||||||
## Examples:
|
## Examples:
|
||||||
|
@ -170,24 +185,55 @@ proc startConnection*(client: DiscordClient) {.async.} =
|
||||||
let url = urlResult["url"].getStr()
|
let url = urlResult["url"].getStr()
|
||||||
client.endpoint = url
|
client.endpoint = url
|
||||||
|
|
||||||
client.ws = await newAsyncWebsocketClient(url[6..url.high], Port 443,
|
var shardCount = shardAmount
|
||||||
|
if (shardCount < urlResult["shards"].getInt()):
|
||||||
|
shardCount = urlResult["shards"].getInt()
|
||||||
|
client.shardCount = shardCount
|
||||||
|
|
||||||
|
if shardCount > 1:
|
||||||
|
for index in 0..shardCount - 2:
|
||||||
|
var shard = newShard(index, client)
|
||||||
|
client.shards.add(shard)
|
||||||
|
|
||||||
|
shard.ws = await newAsyncWebsocketClient(url[6..url.high], Port 443,
|
||||||
|
path = "/v=6&encoding=json", true)
|
||||||
|
|
||||||
|
asyncCheck shard.handleWebsocketPacket()
|
||||||
|
|
||||||
|
# Theres a 5 second delay on identify payloads.
|
||||||
|
await sleepAsync(5500)
|
||||||
|
|
||||||
|
var shard = newShard(shardCount - 1, client)
|
||||||
|
client.shards.add(shard)
|
||||||
|
|
||||||
|
shard.ws = await newAsyncWebsocketClient(url[6..url.high], Port 443,
|
||||||
|
path = "/v=6&encoding=json", true)
|
||||||
|
|
||||||
|
asyncCheck shard.handleWebsocketPacket()
|
||||||
|
|
||||||
|
# Now just wait. Dont poll while we're reconnecting
|
||||||
|
while true:
|
||||||
|
if not shard.reconnecting:
|
||||||
|
poll()
|
||||||
|
|
||||||
|
#[ client.ws = await newAsyncWebsocketClient(url[6..url.high], Port 443,
|
||||||
path = "/v=6&encoding=json", true)
|
path = "/v=6&encoding=json", true)
|
||||||
|
|
||||||
asyncCheck client.handleWebsocketPacket()
|
asyncCheck client.handleWebsocketPacket()
|
||||||
# Now just wait. Dont poll for new events while we're reconnecting
|
# Now just wait. Dont poll for new events while we're reconnecting
|
||||||
while true:
|
while true:
|
||||||
if not client.reconnecting:
|
if not client.reconnecting:
|
||||||
poll()
|
poll() ]#
|
||||||
else:
|
else:
|
||||||
raise newException(IOError, "Failed to get gateway url, token may of been incorrect!")
|
raise newException(IOError, "Failed to get gateway url, token may of been incorrect!")
|
||||||
|
|
||||||
proc updateClientPresence*(client: DiscordClient, presence: Presence) {.async.} =
|
proc updateClientPresence*(shard: Shard, presence: Presence) {.async.} =
|
||||||
let jsonPayload = %* {
|
let jsonPayload = %* {
|
||||||
"op": ord(opPresenceUpdate),
|
"op": ord(opPresenceUpdate),
|
||||||
"d": presence.presenceToJson()
|
"d": presence.presenceToJson()
|
||||||
}
|
}
|
||||||
|
|
||||||
await client.sendGatewayRequest(jsonPayload)
|
await shard.sendGatewayRequest(jsonPayload)
|
||||||
|
|
||||||
proc newDiscordClient*(tkn: string): DiscordClient =
|
proc newDiscordClient*(tkn: string): DiscordClient =
|
||||||
## Create a DiscordClient using a token.
|
## Create a DiscordClient using a token.
|
||||||
|
@ -198,4 +244,4 @@ proc newDiscordClient*(tkn: string): DiscordClient =
|
||||||
var cac: Cache
|
var cac: Cache
|
||||||
new(cac)
|
new(cac)
|
||||||
|
|
||||||
result = DiscordClient(token: tkn, cache: cac, reconnecting: false)
|
result = DiscordClient(token: tkn, cache: cac)
|
|
@ -1,14 +1,21 @@
|
||||||
import websocket, cache, user
|
import websocket, cache, user
|
||||||
|
|
||||||
type DiscordClient* = ref object
|
type
|
||||||
|
DiscordClient* = ref object
|
||||||
## Discord Client
|
## Discord Client
|
||||||
token*: string
|
token*: string
|
||||||
clientUser*: User
|
clientUser*: User
|
||||||
cache*: Cache
|
cache*: Cache
|
||||||
|
shards*: seq[Shard]
|
||||||
|
shardCount*: int
|
||||||
|
endpoint*: string
|
||||||
|
|
||||||
|
Shard* = ref object
|
||||||
|
id*: int
|
||||||
|
client*: DiscordClient
|
||||||
ws*: AsyncWebSocket
|
ws*: AsyncWebSocket
|
||||||
heartbeatInterval*: int
|
heartbeatInterval*: int
|
||||||
heartbeatAcked*: bool
|
heartbeatAcked*: bool
|
||||||
lastSequence*: int
|
lastSequence*: int
|
||||||
endpoint*: string
|
|
||||||
reconnecting*: bool
|
reconnecting*: bool
|
||||||
sessionID*: string
|
sessionID*: string
|
|
@ -2,13 +2,13 @@ import eventhandler, json, tables, message, emoji, user, member, role
|
||||||
import guild, channel, nimcordutils, httpClient, strformat, cache
|
import guild, channel, nimcordutils, httpClient, strformat, cache
|
||||||
import sequtils, asyncdispatch, clientobjects, discordobject, presence
|
import sequtils, asyncdispatch, clientobjects, discordobject, presence
|
||||||
|
|
||||||
proc readyEvent(discordClient: DiscordClient, json: JsonNode) =
|
proc readyEvent(shard: Shard, json: JsonNode) =
|
||||||
var readyEvent = ReadyEvent(client: discordClient, readyPayload: json, name: $EventType.evtReady)
|
var readyEvent = ReadyEvent(shard: shard, readyPayload: json, name: $EventType.evtReady)
|
||||||
|
|
||||||
# Get client user
|
# Get client user
|
||||||
var client = newHttpClient()
|
var client = newHttpClient()
|
||||||
# Add headers
|
# Add headers
|
||||||
client.headers = newHttpHeaders({"Authorization": fmt("Bot {discordClient.token}"),
|
client.headers = newHttpHeaders({"Authorization": fmt("Bot {shard.client.token}"),
|
||||||
"User-Agent": "NimCord (https://github.com/SeanOMik/nimcord, v0.0.0)",
|
"User-Agent": "NimCord (https://github.com/SeanOMik/nimcord, v0.0.0)",
|
||||||
"X-RateLimit-Precision": "millisecond"})
|
"X-RateLimit-Precision": "millisecond"})
|
||||||
echo "Sending GET request, URL: body: {}"
|
echo "Sending GET request, URL: body: {}"
|
||||||
|
@ -16,30 +16,30 @@ proc readyEvent(discordClient: DiscordClient, json: JsonNode) =
|
||||||
waitForRateLimits(0, RateLimitBucketType.global)
|
waitForRateLimits(0, RateLimitBucketType.global)
|
||||||
var userJson = handleResponse(client.request(endpoint("/users/@me"), HttpGet, ""), 0, RateLimitBucketType.global)
|
var userJson = handleResponse(client.request(endpoint("/users/@me"), HttpGet, ""), 0, RateLimitBucketType.global)
|
||||||
|
|
||||||
discordClient.clientUser = newUser(userJson)
|
shard.client.clientUser = newUser(userJson)
|
||||||
discordClient.sessionID = json["session_id"].getStr()
|
shard.sessionID = json["session_id"].getStr()
|
||||||
|
|
||||||
dispatchEvent(readyEvent)
|
dispatchEvent(readyEvent)
|
||||||
|
|
||||||
proc channelCreateEvent(discordClient: DiscordClient, json: JsonNode) =
|
proc channelCreateEvent(shard: Shard, json: JsonNode) =
|
||||||
let chnl = newChannel(json)
|
let chnl = newChannel(json)
|
||||||
let channelCreateEvent = ChannelCreateEvent(client: discordClient, channel: chnl, name: $EventType.evtChannelCreate)
|
let channelCreateEvent = ChannelCreateEvent(shard: shard, channel: chnl, name: $EventType.evtChannelCreate)
|
||||||
|
|
||||||
# Add the channel to its guild's `channels` field
|
# Add the channel to its guild's `channels` field
|
||||||
if (chnl.guildID != 0):
|
if (chnl.guildID != 0):
|
||||||
discordClient.cache.cacheGuildChannel(chnl.guildID, chnl)
|
shard.client.cache.cacheGuildChannel(chnl.guildID, chnl)
|
||||||
discordClient.cache.channels[chnl.id] = chnl
|
shard.client.cache.channels[chnl.id] = chnl
|
||||||
|
|
||||||
dispatchEvent(channelCreateEvent)
|
dispatchEvent(channelCreateEvent)
|
||||||
|
|
||||||
proc channelUpdateEvent(discordClient: DiscordClient, json: JsonNode) =
|
proc channelUpdateEvent(shard: Shard, json: JsonNode) =
|
||||||
let chnl = newChannel(json)
|
let chnl = newChannel(json)
|
||||||
let channelUpdateEvent = ChannelUpdateEvent(client: discordClient, channel: chnl, name: $EventType.evtChannelUpdate)
|
let channelUpdateEvent = ChannelUpdateEvent(shard: shard, channel: chnl, name: $EventType.evtChannelUpdate)
|
||||||
|
|
||||||
discordClient.cache.channels[chnl.id] = chnl
|
shard.client.cache.channels[chnl.id] = chnl
|
||||||
|
|
||||||
if (chnl.guildID != 0):
|
if (chnl.guildID != 0):
|
||||||
let g = discordClient.cache.getGuild(chnl.guildID)
|
let g = shard.client.cache.getGuild(chnl.guildID)
|
||||||
|
|
||||||
var index = -1
|
var index = -1
|
||||||
for i, channel in g.channels:
|
for i, channel in g.channels:
|
||||||
|
@ -55,81 +55,81 @@ proc channelUpdateEvent(discordClient: DiscordClient, json: JsonNode) =
|
||||||
dispatchEvent(channelUpdateEvent)
|
dispatchEvent(channelUpdateEvent)
|
||||||
|
|
||||||
|
|
||||||
proc channelDeleteEvent(discordClient: DiscordClient, json: JsonNode) =
|
proc channelDeleteEvent(shard: Shard, json: JsonNode) =
|
||||||
let chnl = newChannel(json)
|
let chnl = newChannel(json)
|
||||||
let channelDeleteEvent = ChannelDeleteEvent(client: discordClient, channel: chnl, name: $EventType.evtChannelDelete)
|
let channelDeleteEvent = ChannelDeleteEvent(shard: shard, channel: chnl, name: $EventType.evtChannelDelete)
|
||||||
|
|
||||||
var removedChnl: Channel
|
var removedChnl: Channel
|
||||||
discard discordClient.cache.channels.pop(chnl.id, removedChnl)
|
discard shard.client.cache.channels.pop(chnl.id, removedChnl)
|
||||||
|
|
||||||
dispatchEvent(channelDeleteEvent)
|
dispatchEvent(channelDeleteEvent)
|
||||||
|
|
||||||
proc channelPinsUpdate(discordClient: DiscordClient, json: JsonNode) =
|
proc channelPinsUpdate(shard: Shard, json: JsonNode) =
|
||||||
let channelID = getIDFromJson(json["channel_id"].getStr())
|
let channelID = getIDFromJson(json["channel_id"].getStr())
|
||||||
|
|
||||||
var channel: Channel
|
var channel: Channel
|
||||||
if (discordClient.cache.channels.hasKey(channelID)):
|
if (shard.client.cache.channels.hasKey(channelID)):
|
||||||
channel = discordClient.cache.channels[channelID]
|
channel = shard.client.cache.channels[channelID]
|
||||||
channel.lastPinTimestamp = json["last_pin_timestamp"].getStr()
|
channel.lastPinTimestamp = json["last_pin_timestamp"].getStr()
|
||||||
|
|
||||||
let channelPinsUpdateEvent = ChannelPinsUpdateEvent(client: discordClient, channel: channel, name: $EventType.evtChannelPinsUpdate)
|
let channelPinsUpdateEvent = ChannelPinsUpdateEvent(shard: shard, channel: channel, name: $EventType.evtChannelPinsUpdate)
|
||||||
dispatchEvent(channelPinsUpdateEvent)
|
dispatchEvent(channelPinsUpdateEvent)
|
||||||
|
|
||||||
proc guildCreateEvent(discordClient: DiscordClient, json: JsonNode) =
|
proc guildCreateEvent(shard: Shard, json: JsonNode) =
|
||||||
let g = newGuild(json)
|
let g = newGuild(json)
|
||||||
let guildCreateEvnt = GuildCreateEvent(client: discordClient, guild: g, name: $EventType.evtGuildCreate)
|
let guildCreateEvnt = GuildCreateEvent(shard: shard, guild: g, name: $EventType.evtGuildCreate)
|
||||||
|
|
||||||
# Add guild and its channels and members in cache.
|
# Add guild and its channels and members in cache.
|
||||||
discordClient.cache.guilds[g.id] = g
|
shard.client.cache.guilds[g.id] = g
|
||||||
for channel in g.channels:
|
for channel in g.channels:
|
||||||
discordClient.cache.channels[channel.id] = channel
|
shard.client.cache.channels[channel.id] = channel
|
||||||
for member in g.members:
|
for member in g.members:
|
||||||
discordClient.cache.members[member.id] = member
|
shard.client.cache.members[member.id] = member
|
||||||
|
|
||||||
dispatchEvent(guildCreateEvnt)
|
dispatchEvent(guildCreateEvnt)
|
||||||
|
|
||||||
proc guildUpdateEvent(discordClient: DiscordClient, json: JsonNode) =
|
proc guildUpdateEvent(shard: Shard, json: JsonNode) =
|
||||||
let g = newGuild(json)
|
let g = newGuild(json)
|
||||||
let guildUpdateEvent = GuildUpdateEvent(client: discordClient, guild: g, name: $EventType.evtGuildUpdate)
|
let guildUpdateEvent = GuildUpdateEvent(shard: shard, guild: g, name: $EventType.evtGuildUpdate)
|
||||||
|
|
||||||
# Update guild in cache.
|
# Update guild in cache.
|
||||||
discordClient.cache.guilds[g.id] = g
|
shard.client.cache.guilds[g.id] = g
|
||||||
|
|
||||||
dispatchEvent(guildUpdateEvent)
|
dispatchEvent(guildUpdateEvent)
|
||||||
|
|
||||||
proc guildDeleteEvent(discordClient: DiscordClient, json: JsonNode) =
|
proc guildDeleteEvent(shard: Shard, json: JsonNode) =
|
||||||
let g = newGuild(json)
|
let g = newGuild(json)
|
||||||
let guildDeleteEvent = GuildDeleteEvent(client: discordClient, guild: g, name: $EventType.evtGuildDelete)
|
let guildDeleteEvent = GuildDeleteEvent(shard: shard, guild: g, name: $EventType.evtGuildDelete)
|
||||||
|
|
||||||
# Remove guild from cache
|
# Remove guild from cache
|
||||||
var removedGuild: Guild
|
var removedGuild: Guild
|
||||||
discard discordClient.cache.guilds.pop(g.id, removedGuild)
|
discard shard.client.cache.guilds.pop(g.id, removedGuild)
|
||||||
|
|
||||||
dispatchEvent(guildDeleteEvent)
|
dispatchEvent(guildDeleteEvent)
|
||||||
|
|
||||||
proc guildBanAddEvent(discordClient: DiscordClient, json: JsonNode) =
|
proc guildBanAddEvent(shard: Shard, json: JsonNode) =
|
||||||
let g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
let g = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
let user = newUser(json["user"])
|
let user = newUser(json["user"])
|
||||||
|
|
||||||
let guildBanAddEvent = GuildBanAddEvent(client: discordClient, guild: g, bannedUser: user, name: $EventType.evtGuildBanAdd)
|
let guildBanAddEvent = GuildBanAddEvent(shard: shard, guild: g, bannedUser: user, name: $EventType.evtGuildBanAdd)
|
||||||
dispatchEvent(guildBanAddEvent)
|
dispatchEvent(guildBanAddEvent)
|
||||||
|
|
||||||
proc guildBanRemoveEvent(discordClient: DiscordClient, json: JsonNode) =
|
proc guildBanRemoveEvent(shard: Shard, json: JsonNode) =
|
||||||
let g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
let g = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
let user = newUser(json["user"])
|
let user = newUser(json["user"])
|
||||||
|
|
||||||
let guildBanRemoveEvent = GuildBanRemoveEvent(client: discordClient, guild: g, unbannedUser: user, name: $EventType.evtGuildBanRemove)
|
let guildBanRemoveEvent = GuildBanRemoveEvent(shard: shard, guild: g, unbannedUser: user, name: $EventType.evtGuildBanRemove)
|
||||||
dispatchEvent(guildBanRemoveEvent)
|
dispatchEvent(guildBanRemoveEvent)
|
||||||
|
|
||||||
proc guildEmojisUpdateEvent(discordClient: DiscordClient, json: JsonNode) =
|
proc guildEmojisUpdateEvent(shard: Shard, json: JsonNode) =
|
||||||
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
var g = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
|
|
||||||
# Empty g.emojis and fill it with the newly updated emojis
|
# Empty g.emojis and fill it with the newly updated emojis
|
||||||
g.emojis = @[]
|
g.emojis = @[]
|
||||||
for emoji in json["emojis"]:
|
for emoji in json["emojis"]:
|
||||||
g.emojis.add(newEmoji(emoji, g.id))
|
g.emojis.add(newEmoji(emoji, g.id))
|
||||||
|
|
||||||
let guildEmojisUpdateEvent = GuildEmojisUpdateEvent(client: discordClient, guild: g, emojis: g.emojis, name: $EventType.evtGuildEmojisUpdate)
|
let guildEmojisUpdateEvent = GuildEmojisUpdateEvent(shard: shard, guild: g, emojis: g.emojis, name: $EventType.evtGuildEmojisUpdate)
|
||||||
dispatchEvent(guildEmojisUpdateEvent)
|
dispatchEvent(guildEmojisUpdateEvent)
|
||||||
|
|
||||||
#[ var updatedEmojis: Table[snowflake, Emoji] = initTable[snowflake, Emoji]()
|
#[ var updatedEmojis: Table[snowflake, Emoji] = initTable[snowflake, Emoji]()
|
||||||
|
@ -143,28 +143,28 @@ proc guildEmojisUpdateEvent(discordClient: DiscordClient, json: JsonNode) =
|
||||||
|
|
||||||
#g.emojis.apply
|
#g.emojis.apply
|
||||||
|
|
||||||
proc guildIntegrationsUpdate(discordClient: DiscordClient, json: JsonNode) =
|
proc guildIntegrationsUpdate(shard: Shard, json: JsonNode) =
|
||||||
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
var g = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
|
|
||||||
let guildIntegrationsUpdateEvent = GuildIntegrationsUpdateEvent(client: discordClient, guild: g, name: $EventType.evtGuildIntegrationsUpdate)
|
let guildIntegrationsUpdateEvent = GuildIntegrationsUpdateEvent(shard: shard, guild: g, name: $EventType.evtGuildIntegrationsUpdate)
|
||||||
dispatchEvent(guildIntegrationsUpdateEvent)
|
dispatchEvent(guildIntegrationsUpdateEvent)
|
||||||
|
|
||||||
proc guildMemberAdd(discordClient: DiscordClient, json: JsonNode) =
|
proc guildMemberAdd(shard: Shard, json: JsonNode) =
|
||||||
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
var g = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
var newMember = newGuildMember(json, g.id)
|
var newMember = newGuildMember(json, g.id)
|
||||||
|
|
||||||
let guildMemberAddEvent = GuildMemberAddEvent(client: discordClient, guild: g, member: newMember, name: $EventType.evtGuildMemberAdd)
|
let guildMemberAddEvent = GuildMemberAddEvent(shard: shard, guild: g, member: newMember, name: $EventType.evtGuildMemberAdd)
|
||||||
dispatchEvent(guildMemberAddEvent)
|
dispatchEvent(guildMemberAddEvent)
|
||||||
|
|
||||||
proc guildMemberRemove(discordClient: DiscordClient, json: JsonNode) =
|
proc guildMemberRemove(shard: Shard, json: JsonNode) =
|
||||||
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
var g = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
var removedUser = newUser(json["user"])
|
var removedUser = newUser(json["user"])
|
||||||
|
|
||||||
let guildMemberRemoveEvent = GuildMemberRemoveEvent(client: discordClient, guild: g, user: removedUser, name: $EventType.evtGuildMemberRemove)
|
let guildMemberRemoveEvent = GuildMemberRemoveEvent(shard: shard, guild: g, user: removedUser, name: $EventType.evtGuildMemberRemove)
|
||||||
dispatchEvent(guildMemberRemoveEvent)
|
dispatchEvent(guildMemberRemoveEvent)
|
||||||
|
|
||||||
proc guildMemberUpdate(discordClient: DiscordClient, json: JsonNode) =
|
proc guildMemberUpdate(shard: Shard, json: JsonNode) =
|
||||||
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
var g = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
|
|
||||||
var updatedMember = g.getGuildMember(getIDFromJson(json["user"]["id"].getStr()))
|
var updatedMember = g.getGuildMember(getIDFromJson(json["user"]["id"].getStr()))
|
||||||
updatedMember.user = newUser(json["user"])
|
updatedMember.user = newUser(json["user"])
|
||||||
|
@ -179,13 +179,13 @@ proc guildMemberUpdate(discordClient: DiscordClient, json: JsonNode) =
|
||||||
if json.contains("premium_since"):
|
if json.contains("premium_since"):
|
||||||
updatedMember.premiumSince = json["premium_since"].getStr()
|
updatedMember.premiumSince = json["premium_since"].getStr()
|
||||||
|
|
||||||
let guildMemberUpdateEvent = GuildMemberUpdateEvent(client: discordClient, guild: g, member: updatedMember, name: $EventType.evtGuildMemberUpdate)
|
let guildMemberUpdateEvent = GuildMemberUpdateEvent(shard: shard, guild: g, member: updatedMember, name: $EventType.evtGuildMemberUpdate)
|
||||||
dispatchEvent(guildMemberUpdateEvent)
|
dispatchEvent(guildMemberUpdateEvent)
|
||||||
|
|
||||||
proc guildMembersChunk(discordClient: DiscordClient, json: JsonNode) =
|
proc guildMembersChunk(shard: Shard, json: JsonNode) =
|
||||||
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
var g = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
|
|
||||||
var event = GuildMembersChunkEvent(client: discordClient, guild: g, name: $EventType.evtGuildMembersChunk)
|
var event = GuildMembersChunkEvent(shard: shard, guild: g, name: $EventType.evtGuildMembersChunk)
|
||||||
|
|
||||||
#var members: seq[GuildMember]
|
#var members: seq[GuildMember]
|
||||||
for member in json["members"]:
|
for member in json["members"]:
|
||||||
|
@ -207,17 +207,17 @@ proc guildMembersChunk(discordClient: DiscordClient, json: JsonNode) =
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc guildRoleCreate(discordClient: DiscordClient, json: JsonNode) =
|
proc guildRoleCreate(shard: Shard, json: JsonNode) =
|
||||||
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
var g = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
let role = newRole(json["role"], g.id)
|
let role = newRole(json["role"], g.id)
|
||||||
|
|
||||||
g.roles.add(role)
|
g.roles.add(role)
|
||||||
|
|
||||||
var event = GuildRoleUpdateEvent(client: discordClient, guild: g, role: role, name: $EventType.evtGuildRoleUpdate)
|
var event = GuildRoleUpdateEvent(shard: shard, guild: g, role: role, name: $EventType.evtGuildRoleUpdate)
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc guildRoleUpdate(discordClient: DiscordClient, json: JsonNode) =
|
proc guildRoleUpdate(shard: Shard, json: JsonNode) =
|
||||||
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
var g = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
let role = newRole(json["role"], g.id)
|
let role = newRole(json["role"], g.id)
|
||||||
|
|
||||||
var index = -1
|
var index = -1
|
||||||
|
@ -227,11 +227,11 @@ proc guildRoleUpdate(discordClient: DiscordClient, json: JsonNode) =
|
||||||
|
|
||||||
g.roles[index] = role
|
g.roles[index] = role
|
||||||
|
|
||||||
var event = GuildRoleUpdateEvent(client: discordClient, guild: g, role: role, name: $EventType.evtGuildRoleUpdate)
|
var event = GuildRoleUpdateEvent(shard: shard, guild: g, role: role, name: $EventType.evtGuildRoleUpdate)
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc guildRoleDelete(discordClient: DiscordClient, json: JsonNode) =
|
proc guildRoleDelete(shard: Shard, json: JsonNode) =
|
||||||
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
var g = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
let roleID = getIDFromJson(json["role_id"].getStr())
|
let roleID = getIDFromJson(json["role_id"].getStr())
|
||||||
|
|
||||||
var role: Role
|
var role: Role
|
||||||
|
@ -244,53 +244,53 @@ proc guildRoleDelete(discordClient: DiscordClient, json: JsonNode) =
|
||||||
if index != -1:
|
if index != -1:
|
||||||
g.roles.delete(index)
|
g.roles.delete(index)
|
||||||
|
|
||||||
var event = GuildRoleDeleteEvent(client: discordClient, guild: g, role: role, name: $EventType.evtGuildRoleDelete)
|
var event = GuildRoleDeleteEvent(shard: shard, guild: g, role: role, name: $EventType.evtGuildRoleDelete)
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc inviteCreate(discordClient: DiscordClient, json: JsonNode) =
|
proc inviteCreate(shard: Shard, json: JsonNode) =
|
||||||
var invite = newInvite(json)
|
var invite = newInvite(json)
|
||||||
|
|
||||||
invite.channel = discordClient.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
|
invite.channel = shard.client.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
|
||||||
|
|
||||||
if (json.contains("guild_id")):
|
if (json.contains("guild_id")):
|
||||||
invite.guildID =getIDFromJson(json["guild_id"].getStr())
|
invite.guildID =getIDFromJson(json["guild_id"].getStr())
|
||||||
|
|
||||||
var event = InviteCreateEvent(client: discordClient, invite: invite, name: $EventType.evtInviteCreate)
|
var event = InviteCreateEvent(shard: shard, invite: invite, name: $EventType.evtInviteCreate)
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc inviteDelete(discordClient: DiscordClient, json: JsonNode) =
|
proc inviteDelete(shard: Shard, json: JsonNode) =
|
||||||
var event = InviteDeleteEvent(client: discordClient, name: $EventType.evtInviteDelete)
|
var event = InviteDeleteEvent(shard: shard, name: $EventType.evtInviteDelete)
|
||||||
|
|
||||||
event.channel = discordClient.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
|
event.channel = shard.client.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
|
||||||
event.code = json["code"].getStr()
|
event.code = json["code"].getStr()
|
||||||
|
|
||||||
if (json.contains("guild_id")):
|
if (json.contains("guild_id")):
|
||||||
event.guild = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
event.guild = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc messageCreateEvent(discordClient: DiscordClient, json: JsonNode) =
|
proc messageCreateEvent(shard: Shard, json: JsonNode) =
|
||||||
let msg = newMessage(json)
|
let msg = newMessage(json)
|
||||||
|
|
||||||
discordClient.cache.messages[msg.id] = msg
|
shard.client.cache.messages[msg.id] = msg
|
||||||
|
|
||||||
let messageCreateEvnt = MessageCreateEvent(client: discordClient, message: msg, name: $EventType.evtMessageCreate)
|
let messageCreateEvnt = MessageCreateEvent(shard: shard, message: msg, name: $EventType.evtMessageCreate)
|
||||||
dispatchEvent(messageCreateEvnt)
|
dispatchEvent(messageCreateEvnt)
|
||||||
|
|
||||||
proc messageUpdateEvent(discordClient: DiscordClient, json: JsonNode) =
|
proc messageUpdateEvent(shard: Shard, json: JsonNode) =
|
||||||
let msg = newMessage(json)
|
let msg = newMessage(json)
|
||||||
|
|
||||||
discordClient.cache.messages[msg.id] = msg
|
shard.client.cache.messages[msg.id] = msg
|
||||||
|
|
||||||
let event = MessageCreateEvent(client: discordClient, message: msg, name: $EventType.evtMessageUpdate)
|
let event = MessageCreateEvent(shard: shard, message: msg, name: $EventType.evtMessageUpdate)
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc messageDeleteEvent(discordClient: DiscordClient, json: JsonNode) =
|
proc messageDeleteEvent(shard: Shard, json: JsonNode) =
|
||||||
let msgID = getIDFromJson(json["id"].getStr())
|
let msgID = getIDFromJson(json["id"].getStr())
|
||||||
|
|
||||||
var msg: Message
|
var msg: Message
|
||||||
if discordClient.cache.messages.hasKey(msgID):
|
if shard.client.cache.messages.hasKey(msgID):
|
||||||
discard discordClient.cache.messages.pop(msgID, msg)
|
discard shard.client.cache.messages.pop(msgID, msg)
|
||||||
else:
|
else:
|
||||||
msg = Message(id: msgID)
|
msg = Message(id: msgID)
|
||||||
|
|
||||||
|
@ -298,27 +298,27 @@ proc messageDeleteEvent(discordClient: DiscordClient, json: JsonNode) =
|
||||||
if (json.contains("guild_id")):
|
if (json.contains("guild_id")):
|
||||||
msg.guildID = getIDFromJson(json["guild_id"].getStr())
|
msg.guildID = getIDFromJson(json["guild_id"].getStr())
|
||||||
|
|
||||||
let event = MessageDeleteEvent(client: discordClient, message: msg, name: $EventType.evtMessageDelete)
|
let event = MessageDeleteEvent(shard: shard, message: msg, name: $EventType.evtMessageDelete)
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc messageDeleteBulkEvent(discordClient: DiscordClient, json: JsonNode) =
|
proc messageDeleteBulkEvent(shard: Shard, json: JsonNode) =
|
||||||
var event = MessageDeleteBulkEvent(client: discordClient, name: $EventType.evtMessageDeleteBulk)
|
var event = MessageDeleteBulkEvent(shard: shard, name: $EventType.evtMessageDeleteBulk)
|
||||||
|
|
||||||
event.channel = discordClient.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
|
event.channel = shard.client.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
|
||||||
if (json.contains("guild_id")):
|
if (json.contains("guild_id")):
|
||||||
event.guild = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
event.guild = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
|
|
||||||
for msgIDJson in json["ids"]:
|
for msgIDJson in json["ids"]:
|
||||||
let msgID = getIDFromJson(msgIDJson.getStr())
|
let msgID = getIDFromJson(msgIDJson.getStr())
|
||||||
|
|
||||||
var msg: Message
|
var msg: Message
|
||||||
if discordClient.cache.messages.hasKey(msgID):
|
if shard.client.cache.messages.hasKey(msgID):
|
||||||
discard discordClient.cache.messages.pop(msgID, msg)
|
discard shard.client.cache.messages.pop(msgID, msg)
|
||||||
else:
|
else:
|
||||||
let channelID = getIDFromJson(json["channel_id"].getStr())
|
let channelID = getIDFromJson(json["channel_id"].getStr())
|
||||||
msg = Message(id: msgID, channelID: channelID)
|
msg = Message(id: msgID, channelID: channelID)
|
||||||
|
|
||||||
event.channel = discordClient.cache.getChannel(msg.channelID)
|
event.channel = shard.client.cache.getChannel(msg.channelID)
|
||||||
if (json.contains("guild_id")):
|
if (json.contains("guild_id")):
|
||||||
msg.guildID = getIDFromJson(json["guild_id"].getStr())
|
msg.guildID = getIDFromJson(json["guild_id"].getStr())
|
||||||
|
|
||||||
|
@ -326,13 +326,13 @@ proc messageDeleteBulkEvent(discordClient: DiscordClient, json: JsonNode) =
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc messageReactionAdd(discordClient: DiscordClient, json: JsonNode) =
|
proc messageReactionAdd(shard: Shard, json: JsonNode) =
|
||||||
var event = MessageReactionAddEvent(client: discordClient, name: $EventType.evtMessageReactionAdd)
|
var event = MessageReactionAddEvent(shard: shard, name: $EventType.evtMessageReactionAdd)
|
||||||
|
|
||||||
let msgID = getIDFromJson(json["message_id"].getStr())
|
let msgID = getIDFromJson(json["message_id"].getStr())
|
||||||
var msg: Message
|
var msg: Message
|
||||||
if discordClient.cache.messages.hasKey(msgID):
|
if shard.client.cache.messages.hasKey(msgID):
|
||||||
msg = discordClient.cache.messages[msgID]
|
msg = shard.client.cache.messages[msgID]
|
||||||
else:
|
else:
|
||||||
msg = Message(id: msgID)
|
msg = Message(id: msgID)
|
||||||
|
|
||||||
|
@ -340,7 +340,7 @@ proc messageReactionAdd(discordClient: DiscordClient, json: JsonNode) =
|
||||||
if (json.contains("guild_id")):
|
if (json.contains("guild_id")):
|
||||||
msg.guildID = getIDFromJson(json["guild_id"].getStr())
|
msg.guildID = getIDFromJson(json["guild_id"].getStr())
|
||||||
|
|
||||||
event.user = discordClient.cache.getUser(getIDFromJson(json["user_id"].getStr()))
|
event.user = shard.client.cache.getUser(getIDFromJson(json["user_id"].getStr()))
|
||||||
|
|
||||||
if (json.contains("member")):
|
if (json.contains("member")):
|
||||||
event.member = newGuildMember(json["member"], msg.guildID)
|
event.member = newGuildMember(json["member"], msg.guildID)
|
||||||
|
@ -349,13 +349,13 @@ proc messageReactionAdd(discordClient: DiscordClient, json: JsonNode) =
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc messageReactionRemove(discordClient: DiscordClient, json: JsonNode) =
|
proc messageReactionRemove(shard: Shard, json: JsonNode) =
|
||||||
var event = MessageReactionRemoveEvent(client: discordClient, name: $EventType.evtMessageReactionRemove)
|
var event = MessageReactionRemoveEvent(shard: shard, name: $EventType.evtMessageReactionRemove)
|
||||||
|
|
||||||
let msgID = getIDFromJson(json["message_id"].getStr())
|
let msgID = getIDFromJson(json["message_id"].getStr())
|
||||||
var msg: Message
|
var msg: Message
|
||||||
if discordClient.cache.messages.hasKey(msgID):
|
if shard.client.cache.messages.hasKey(msgID):
|
||||||
msg = discordClient.cache.messages[msgID]
|
msg = shard.client.cache.messages[msgID]
|
||||||
else:
|
else:
|
||||||
msg = Message(id: msgID)
|
msg = Message(id: msgID)
|
||||||
|
|
||||||
|
@ -363,19 +363,19 @@ proc messageReactionRemove(discordClient: DiscordClient, json: JsonNode) =
|
||||||
if (json.contains("guild_id")):
|
if (json.contains("guild_id")):
|
||||||
msg.guildID = getIDFromJson(json["guild_id"].getStr())
|
msg.guildID = getIDFromJson(json["guild_id"].getStr())
|
||||||
|
|
||||||
event.user = discordClient.cache.getUser(getIDFromJson(json["user_id"].getStr()))
|
event.user = shard.client.cache.getUser(getIDFromJson(json["user_id"].getStr()))
|
||||||
|
|
||||||
event.emoji = newEmoji(json["emoji"], msg.guildID)
|
event.emoji = newEmoji(json["emoji"], msg.guildID)
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc messageReactionRemoveAll(discordClient: DiscordClient, json: JsonNode) =
|
proc messageReactionRemoveAll(shard: Shard, json: JsonNode) =
|
||||||
var event = MessageReactionRemoveAllEvent(client: discordClient, name: $EventType.evtMessageReactionRemoveAll)
|
var event = MessageReactionRemoveAllEvent(shard: shard, name: $EventType.evtMessageReactionRemoveAll)
|
||||||
|
|
||||||
let msgID = getIDFromJson(json["message_id"].getStr())
|
let msgID = getIDFromJson(json["message_id"].getStr())
|
||||||
var msg: Message
|
var msg: Message
|
||||||
if discordClient.cache.messages.hasKey(msgID):
|
if shard.client.cache.messages.hasKey(msgID):
|
||||||
msg = discordClient.cache.messages[msgID]
|
msg = shard.client.cache.messages[msgID]
|
||||||
else:
|
else:
|
||||||
msg = Message(id: msgID)
|
msg = Message(id: msgID)
|
||||||
|
|
||||||
|
@ -385,13 +385,13 @@ proc messageReactionRemoveAll(discordClient: DiscordClient, json: JsonNode) =
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc messageReactionRemoveEmoji(discordClient: DiscordClient, json: JsonNode) =
|
proc messageReactionRemoveEmoji(shard: Shard, json: JsonNode) =
|
||||||
var event = MessageReactionRemoveEmojiEvent(client: discordClient, name: $EventType.evtMessageReactionRemoveEmoji)
|
var event = MessageReactionRemoveEmojiEvent(shard: shard, name: $EventType.evtMessageReactionRemoveEmoji)
|
||||||
|
|
||||||
let msgID = getIDFromJson(json["message_id"].getStr())
|
let msgID = getIDFromJson(json["message_id"].getStr())
|
||||||
var msg: Message
|
var msg: Message
|
||||||
if discordClient.cache.messages.hasKey(msgID):
|
if shard.client.cache.messages.hasKey(msgID):
|
||||||
msg = discordClient.cache.messages[msgID]
|
msg = shard.client.cache.messages[msgID]
|
||||||
else:
|
else:
|
||||||
msg = Message(id: msgID)
|
msg = Message(id: msgID)
|
||||||
|
|
||||||
|
@ -403,10 +403,10 @@ proc messageReactionRemoveEmoji(discordClient: DiscordClient, json: JsonNode) =
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc presenceUpdate(discordClient: DiscordClient, json: JsonNode) =
|
proc presenceUpdate(shard: Shard, json: JsonNode) =
|
||||||
# This proc doesn't actually dispatch any events,
|
# This proc doesn't actually dispatch any events,
|
||||||
# it just updates member.presence
|
# it just updates member.presence
|
||||||
var g = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
var g = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
var member = g.getGuildMember(getIDFromJson(json["user"]["id"].getStr()))
|
var member = g.getGuildMember(getIDFromJson(json["user"]["id"].getStr()))
|
||||||
|
|
||||||
# Make sure some member fields are upto date.
|
# Make sure some member fields are upto date.
|
||||||
|
@ -421,51 +421,51 @@ proc presenceUpdate(discordClient: DiscordClient, json: JsonNode) =
|
||||||
|
|
||||||
member.presence = newPresence(json)
|
member.presence = newPresence(json)
|
||||||
|
|
||||||
proc typingStart(discordClient: DiscordClient, json: JsonNode) =
|
proc typingStart(shard: Shard, json: JsonNode) =
|
||||||
var event = TypingStartEvent(client: discordClient, name: $EventType.evtTypingStart)
|
var event = TypingStartEvent(shard: shard, name: $EventType.evtTypingStart)
|
||||||
|
|
||||||
event.channel = discordClient.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
|
event.channel = shard.client.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
|
||||||
|
|
||||||
if (json.contains("guild_id")):
|
if (json.contains("guild_id")):
|
||||||
event.channel.guildID = getIDFromJson(json["guild_id"].getStr())
|
event.channel.guildID = getIDFromJson(json["guild_id"].getStr())
|
||||||
|
|
||||||
event.user = discordClient.cache.getUser(getIDFromJson(json["user_id"].getStr()))
|
event.user = shard.client.cache.getUser(getIDFromJson(json["user_id"].getStr()))
|
||||||
|
|
||||||
if (json.contains("member")):
|
if (json.contains("member")):
|
||||||
event.member = newGuildMember(json["member"], event.channel.guildID)
|
event.member = newGuildMember(json["member"], event.channel.guildID)
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc userUpdate(discordClient: DiscordClient, json: JsonNode) =
|
proc userUpdate(shard: Shard, json: JsonNode) =
|
||||||
var event = UserUpdateEvent(client: discordClient, name: $EventType.evtUserUpdate)
|
var event = UserUpdateEvent(shard: shard, name: $EventType.evtUserUpdate)
|
||||||
|
|
||||||
event.user = newUser(json)
|
event.user = newUser(json)
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc voiceStateUpdate(discordClient: DiscordClient, json: JsonNode) =
|
proc voiceStateUpdate(shard: Shard, json: JsonNode) =
|
||||||
var event = VoiceStateUpdateEvent(client: discordClient, name: $EventType.evtVoiceStateUpdate)
|
var event = VoiceStateUpdateEvent(shard: shard, name: $EventType.evtVoiceStateUpdate)
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc voiceServerUpdate(discordClient: DiscordClient, json: JsonNode) =
|
proc voiceServerUpdate(shard: Shard, json: JsonNode) =
|
||||||
var event = VoiceServerUpdateEvent(client: discordClient, name: $EventType.evtVoiceServerUpdate)
|
var event = VoiceServerUpdateEvent(shard: shard, name: $EventType.evtVoiceServerUpdate)
|
||||||
|
|
||||||
event.token = json["token"].getStr()
|
event.token = json["token"].getStr()
|
||||||
event.guild = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
event.guild = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
event.endpoint = json["endpoint"].getStr()
|
event.endpoint = json["endpoint"].getStr()
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
proc webhooksUpdate(discordClient: DiscordClient, json: JsonNode) =
|
proc webhooksUpdate(shard: Shard, json: JsonNode) =
|
||||||
var event = WebhooksUpdateEvent(client: discordClient, name: $EventType.evtWebhooksUpdate)
|
var event = WebhooksUpdateEvent(shard: shard, name: $EventType.evtWebhooksUpdate)
|
||||||
|
|
||||||
event.guild = discordClient.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
event.guild = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
event.channel = discordClient.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
|
event.channel = shard.client.cache.getChannel(getIDFromJson(json["channel_id"].getStr()))
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
|
||||||
let internalEventTable: Table[string, proc(discordClient: DiscordClient, json: JsonNode) {.nimcall.}] = {
|
let internalEventTable: Table[string, proc(shard: Shard, json: JsonNode) {.nimcall.}] = {
|
||||||
"READY": readyEvent,
|
"READY": readyEvent,
|
||||||
"CHANNEL_CREATE": channelCreateEvent,
|
"CHANNEL_CREATE": channelCreateEvent,
|
||||||
"CHANNEL_UPDATE": channelUpdateEvent,
|
"CHANNEL_UPDATE": channelUpdateEvent,
|
||||||
|
@ -502,11 +502,11 @@ let internalEventTable: Table[string, proc(discordClient: DiscordClient, json: J
|
||||||
"WEBHOOKS_UPDATE": webhooksUpdate
|
"WEBHOOKS_UPDATE": webhooksUpdate
|
||||||
}.toTable
|
}.toTable
|
||||||
|
|
||||||
proc handleDiscordEvent*(discordClient: DiscordClient, json: JsonNode, eventName: string) {.async.} =
|
proc handleDiscordEvent*(shard: Shard, json: JsonNode, eventName: string) {.async.} =
|
||||||
## Handles, and dispatches, a gateway event. Only used internally.
|
## Handles, and dispatches, a gateway event. Only used internally.
|
||||||
if (internalEventTable.hasKey(eventName)):
|
if (internalEventTable.hasKey(eventName)):
|
||||||
let eventProc: proc(discordClient: DiscordClient, json: JsonNode) = internalEventTable[eventName]
|
let eventProc: proc(shard: Shard, json: JsonNode) = internalEventTable[eventName]
|
||||||
eventProc(discordClient, json)
|
eventProc(shard, json)
|
||||||
else:
|
else:
|
||||||
echo "Failed to find event: ", eventName
|
echo "Failed to find event: ", eventName
|
||||||
|
|
|
@ -46,7 +46,7 @@ type
|
||||||
BaseEvent* = object of RootObj
|
BaseEvent* = object of RootObj
|
||||||
## Base event that all events inherit from.
|
## Base event that all events inherit from.
|
||||||
## It stores a reference to the DiscordClient and name of the event.
|
## It stores a reference to the DiscordClient and name of the event.
|
||||||
client*: DiscordClient
|
shard*: Shard
|
||||||
name*: string
|
name*: string
|
||||||
|
|
||||||
# Socket Events
|
# Socket Events
|
||||||
|
|
Reference in New Issue