Merge pull request #1 from avahe-kellenberger/master
Clean-up and Nim version fix.
This commit is contained in:
commit
3216b4481f
|
@ -4,4 +4,4 @@ description = "Discord API wrapper written in Nim. Inspired by DisC++, my othe
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
srcDir = "src"
|
srcDir = "src"
|
||||||
|
|
||||||
requires "nim >= 1.0.0", "websocket >= 0.4.0 & <= 0.4.1"
|
requires "nim >= 1.2.0", "websocket >= 0.4.0 & <= 0.4.1"
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import message, member, channel, guild, discordobject, nimcordutils, httpcore, user, tables
|
import message, member, channel, guild, discordobject, nimcordutils, httpcore, user, tables
|
||||||
|
|
||||||
type Cache* = ref object
|
type Cache* = ref object
|
||||||
members*: Table[snowflake, GuildMember]
|
members*: Table[Snowflake, GuildMember]
|
||||||
messages*: Table[snowflake, Message]
|
messages*: Table[Snowflake, Message]
|
||||||
channels*: Table[snowflake, Channel]
|
channels*: Table[Snowflake, Channel]
|
||||||
guilds*: Table[snowflake, Guild]
|
guilds*: Table[Snowflake, Guild]
|
||||||
|
|
||||||
proc getChannel*(cache: var Cache, id: snowflake): Channel =
|
proc getChannel*(cache: var Cache, id: Snowflake): Channel =
|
||||||
## Get a channel object from the id.
|
## Get a channel object from the id.
|
||||||
##
|
##
|
||||||
## If for some reason the channel is not in cache, it gets requested via the
|
## If for some reason the channel is not in cache, it gets requested via the
|
||||||
## Discord REST API.
|
## Discord REST API.
|
||||||
if (cache.channels.hasKey(id)):
|
if cache.channels.hasKey(id):
|
||||||
return cache.channels[id]
|
return cache.channels[id]
|
||||||
|
|
||||||
result = newChannel(sendRequest(endpoint("/channels/" & $id), HttpGet, defaultHeaders(),
|
result = newChannel(sendRequest(endpoint("/channels/" & $id), HttpGet, defaultHeaders(),
|
||||||
|
@ -25,12 +25,12 @@ proc getMessageChannel*(msg: Message, cache: var Cache): Channel =
|
||||||
## Discord REST API.
|
## Discord REST API.
|
||||||
return cache.getChannel(msg.channelID)
|
return cache.getChannel(msg.channelID)
|
||||||
|
|
||||||
proc getGuild*(cache: var Cache, id: snowflake): Guild =
|
proc getGuild*(cache: var Cache, id: Snowflake): Guild =
|
||||||
## Get a guild object from it's id.
|
## Get a guild object from it's id.
|
||||||
##
|
##
|
||||||
## If for some reason the guild is not in cache, it gets requested via the
|
## If for some reason the guild is not in cache, it gets requested via the
|
||||||
## Discord REST API.
|
## Discord REST API.
|
||||||
if (cache.guilds.hasKey(id)):
|
if cache.guilds.hasKey(id):
|
||||||
return cache.guilds[id]
|
return cache.guilds[id]
|
||||||
|
|
||||||
result = newGuild(sendRequest(endpoint("/guilds/" & $id), HttpGet, defaultHeaders(),
|
result = newGuild(sendRequest(endpoint("/guilds/" & $id), HttpGet, defaultHeaders(),
|
||||||
|
@ -44,18 +44,18 @@ proc getChannelGuild*(channel: Channel, cache: var Cache): Guild =
|
||||||
## Discord REST API.
|
## Discord REST API.
|
||||||
return cache.getGuild(channel.guildID)
|
return cache.getGuild(channel.guildID)
|
||||||
|
|
||||||
proc getUser*(cache: Cache, id: snowflake): User =
|
proc getUser*(cache: Cache, id: Snowflake): User =
|
||||||
## Get a user object from it's id.
|
## Get a user object from it's id.
|
||||||
##
|
##
|
||||||
## If for some reason the user is not in cache, it gets requested via the
|
## If for some reason the user is not in cache, it gets requested via the
|
||||||
## Discord REST API.
|
## Discord REST API.
|
||||||
if (cache.members.hasKey(id)):
|
if cache.members.hasKey(id):
|
||||||
return cache.members[id].user
|
return cache.members[id].user
|
||||||
|
|
||||||
return newUser(sendRequest(endpoint("/users/" & $id), HttpGet, defaultHeaders()))
|
return newUser(sendRequest(endpoint("/users/" & $id), HttpGet, defaultHeaders()))
|
||||||
|
|
||||||
proc cacheGuildChannel*(cache: var Cache, guildID: snowflake, channel: Channel) =
|
proc cacheGuildChannel*(cache: var Cache, guildID: Snowflake, channel: Channel) =
|
||||||
## Adds a channel in cache.guilds[guildID].channels.
|
## Adds a channel in cache.guilds[guildID].channels.
|
||||||
## Only used for internal library, dont touch!
|
## Only used for internal library, dont touch!
|
||||||
var guild = cache.getGuild(guildID)
|
var guild = cache.getGuild(guildID)
|
||||||
guild.channels.add(channel)
|
guild.channels.add(channel)
|
||||||
|
|
|
@ -14,21 +14,21 @@ type
|
||||||
Channel* = ref object of DiscordObject
|
Channel* = ref object of DiscordObject
|
||||||
## Discord channel object.
|
## Discord channel object.
|
||||||
`type`*: ChannelType ## The type of channel.
|
`type`*: ChannelType ## The type of channel.
|
||||||
guildID*: snowflake ## The id of the guild.
|
guildID*: Snowflake ## The id of the guild.
|
||||||
position*: int ## Sorting position of the channel.
|
position*: int ## Sorting position of the channel.
|
||||||
permissionOverwrites*: seq[Permissions] ## Explicit permission overwrites for members and roles.
|
permissionOverwrites*: seq[Permissions] ## Explicit permission overwrites for members and roles.
|
||||||
name*: string ## The name of the channel (2-100 characters).
|
name*: string ## The name of the channel (2-100 characters).
|
||||||
topic*: string ## The channel topic (0-1024 characters).
|
topic*: string ## The channel topic (0-1024 characters).
|
||||||
nsfw*: bool ## Whether the channel is nsfw.
|
nsfw*: bool ## Whether the channel is nsfw.
|
||||||
lastMessageID*: snowflake ## The id of the last message sent in this channel (may not point to an existing or valid message).
|
lastMessageID*: Snowflake ## The id of the last message sent in this channel (may not point to an existing or valid message).
|
||||||
bitrate*: int ## The bitrate (in bits) of the voice channel.
|
bitrate*: int ## The bitrate (in bits) of the voice channel.
|
||||||
userLimit*: int ## The user limit of the voice channel.
|
userLimit*: int ## The user limit of the voice channel.
|
||||||
rateLimitPerUser*: int ## Amount of seconds a user has to wait before sending another message (0-21600); bots, as well as users with the permission manage_messages or manage_channel, are unaffected.
|
rateLimitPerUser*: int ## Amount of seconds a user has to wait before sending another message (0-21600); bots, as well as users with the permission manage_messages or manage_channel, are unaffected.
|
||||||
recipients*: seq[User] ## The recipients of the DM
|
recipients*: seq[User] ## The recipients of the DM
|
||||||
icon*: string ## Icon hash
|
icon*: string ## Icon hash
|
||||||
ownerID*: snowflake ## ID of the DM creator
|
ownerID*: Snowflake ## ID of the DM creator
|
||||||
applicationID*: snowflake ## Application id of the group DM creator if it is bot-created
|
applicationID*: Snowflake ## Application id of the group DM creator if it is bot-created
|
||||||
parentID*: snowflake ## ID of the parent category for a channel
|
parentID*: Snowflake ## ID of the parent category for a channel
|
||||||
lastPinTimestamp*: string ## When the last pinned message was pinned
|
lastPinTimestamp*: string ## When the last pinned message was pinned
|
||||||
|
|
||||||
ChannelFields* = ref object
|
ChannelFields* = ref object
|
||||||
|
@ -41,13 +41,13 @@ type
|
||||||
rateLimitPerUser*: Option[int]
|
rateLimitPerUser*: Option[int]
|
||||||
position*: Option[int]
|
position*: Option[int]
|
||||||
permissionOverwrites*: Option[seq[Permissions]] ## Explicit permission overwrites for members and roles.
|
permissionOverwrites*: Option[seq[Permissions]] ## Explicit permission overwrites for members and roles.
|
||||||
parentID*: Option[snowflake]
|
parentID*: Option[Snowflake]
|
||||||
nsfw*: Option[bool]
|
nsfw*: Option[bool]
|
||||||
|
|
||||||
Invite* = object
|
Invite* = object
|
||||||
## Represents a code that when used, adds a user to a guild or group DM channel.
|
## Represents a code that when used, adds a user to a guild or group DM channel.
|
||||||
code*: string ## The invite code (unique ID)
|
code*: string ## The invite code (unique ID)
|
||||||
guildID*: snowflake ## The guild this invite is for
|
guildID*: Snowflake ## The guild this invite is for
|
||||||
channel*: Channel ## The channel this invite is for
|
channel*: Channel ## The channel this invite is for
|
||||||
inviter*: User ## The user who created the invite
|
inviter*: User ## The user who created the invite
|
||||||
targetUser*: User ## The target user for this invite
|
targetUser*: User ## The target user for this invite
|
||||||
|
@ -74,39 +74,39 @@ proc newChannel*(channel: JsonNode): Channel {.inline.} =
|
||||||
`type`: ChannelType(channel["type"].getInt())
|
`type`: ChannelType(channel["type"].getInt())
|
||||||
)
|
)
|
||||||
|
|
||||||
if (channel.contains("guild_id")):
|
if channel.contains("guild_id"):
|
||||||
chan.guildID = getIDFromJson(channel["guild_id"].getStr())
|
chan.guildID = getIDFromJson(channel["guild_id"].getStr())
|
||||||
if (channel.contains("position")):
|
if channel.contains("position"):
|
||||||
chan.position = channel["position"].getInt()
|
chan.position = channel["position"].getInt()
|
||||||
if (channel.contains("permission_overwrites")):
|
if channel.contains("permission_overwrites"):
|
||||||
for perm in channel["permission_overwrites"]:
|
for perm in channel["permission_overwrites"]:
|
||||||
chan.permissionOverwrites.add(newPermissions(perm))
|
chan.permissionOverwrites.add(newPermissions(perm))
|
||||||
if (channel.contains("name")):
|
if channel.contains("name"):
|
||||||
chan.name = channel["name"].getStr()
|
chan.name = channel["name"].getStr()
|
||||||
if (channel.contains("topic")):
|
if channel.contains("topic"):
|
||||||
chan.topic = channel["topic"].getStr()
|
chan.topic = channel["topic"].getStr()
|
||||||
if (channel.contains("nsfw")):
|
if channel.contains("nsfw"):
|
||||||
chan.nsfw = channel["nsfw"].getBool()
|
chan.nsfw = channel["nsfw"].getBool()
|
||||||
if (channel.contains("last_message_id")):
|
if channel.contains("last_message_id"):
|
||||||
chan.lastMessageID = getIDFromJson(channel["last_message_id"].getStr())
|
chan.lastMessageID = getIDFromJson(channel["last_message_id"].getStr())
|
||||||
if (channel.contains("bitrate")):
|
if channel.contains("bitrate"):
|
||||||
chan.bitrate = channel["bitrate"].getInt()
|
chan.bitrate = channel["bitrate"].getInt()
|
||||||
if (channel.contains("user_limit")):
|
if channel.contains("user_limit"):
|
||||||
chan.userLimit = channel["user_limit"].getInt()
|
chan.userLimit = channel["user_limit"].getInt()
|
||||||
if (channel.contains("rate_limit_per_user")):
|
if channel.contains("rate_limit_per_user"):
|
||||||
chan.rateLimitPerUser = channel["rate_limit_per_user"].getInt()
|
chan.rateLimitPerUser = channel["rate_limit_per_user"].getInt()
|
||||||
if (channel.contains("recipients")):
|
if channel.contains("recipients"):
|
||||||
for recipient in channel["recipients"]:
|
for recipient in channel["recipients"]:
|
||||||
chan.recipients.insert(newUser(recipient))
|
chan.recipients.insert(newUser(recipient))
|
||||||
if (channel.contains("icon")):
|
if channel.contains("icon"):
|
||||||
chan.icon = channel["icon"].getStr()
|
chan.icon = channel["icon"].getStr()
|
||||||
if (channel.contains("owner_id")):
|
if channel.contains("owner_id"):
|
||||||
chan.ownerID = getIDFromJson(channel["owner_id"].getStr())
|
chan.ownerID = getIDFromJson(channel["owner_id"].getStr())
|
||||||
if (channel.contains("application_id")):
|
if channel.contains("application_id"):
|
||||||
chan.applicationID = getIDFromJson(channel["application_id"].getStr())
|
chan.applicationID = getIDFromJson(channel["application_id"].getStr())
|
||||||
if (channel.contains("parent_id")):
|
if channel.contains("parent_id"):
|
||||||
chan.parentID = getIDFromJson(channel["parent_id"].getStr())
|
chan.parentID = getIDFromJson(channel["parent_id"].getStr())
|
||||||
if (channel.contains("last_pin_timestamp")):
|
if channel.contains("last_pin_timestamp"):
|
||||||
chan.lastPinTimestamp = channel["last_pin_timestamp"].getStr()
|
chan.lastPinTimestamp = channel["last_pin_timestamp"].getStr()
|
||||||
|
|
||||||
return chan
|
return chan
|
||||||
|
@ -117,23 +117,23 @@ proc newInvite*(json: JsonNode): Invite {.inline.} =
|
||||||
code: json["code"].getStr(),
|
code: json["code"].getStr(),
|
||||||
channel: newChannel(json["channel"])
|
channel: newChannel(json["channel"])
|
||||||
)
|
)
|
||||||
if (json.contains("guild")):
|
if json.contains("guild"):
|
||||||
invite.guildID = getIDFromJson(json["guild"]["id"].getStr())
|
invite.guildID = getIDFromJson(json["guild"]["id"].getStr())
|
||||||
if (json.contains("target_user")):
|
if json.contains("target_user"):
|
||||||
invite.targetUser = newUser(json["target_user"])
|
invite.targetUser = newUser(json["target_user"])
|
||||||
if (json.contains("approximate_presence_count")):
|
if json.contains("approximate_presence_count"):
|
||||||
invite.approximatePresenceCount = json["approximate_presence_count"].getInt()
|
invite.approximatePresenceCount = json["approximate_presence_count"].getInt()
|
||||||
if (json.contains("approximate_member_count")):
|
if json.contains("approximate_member_count"):
|
||||||
invite.approximateMemberCount = json["approximate_member_count"].getInt()
|
invite.approximateMemberCount = json["approximate_member_count"].getInt()
|
||||||
if (json.contains("uses")):
|
if json.contains("uses"):
|
||||||
invite.uses = json["uses"].getInt()
|
invite.uses = json["uses"].getInt()
|
||||||
if (json.contains("max_uses")):
|
if json.contains("max_uses"):
|
||||||
invite.maxUsers = json["max_uses"].getInt()
|
invite.maxUsers = json["max_uses"].getInt()
|
||||||
if (json.contains("max_age")):
|
if json.contains("max_age"):
|
||||||
invite.maxAge = json["max_age"].getInt()
|
invite.maxAge = json["max_age"].getInt()
|
||||||
if (json.contains("temporary")):
|
if json.contains("temporary"):
|
||||||
invite.temporary = json["temporary"].getBool()
|
invite.temporary = json["temporary"].getBool()
|
||||||
if (json.contains("created_at")):
|
if json.contains("created_at"):
|
||||||
invite.createdAt = json["created_at"].getStr()
|
invite.createdAt = json["created_at"].getStr()
|
||||||
|
|
||||||
return invite
|
return invite
|
||||||
|
@ -142,10 +142,10 @@ proc sendMessage*(channel: Channel, content: string, tts: bool = false, embed: E
|
||||||
## Send a message through the channel.
|
## Send a message through the channel.
|
||||||
var messagePayload = %*{"content": content, "tts": tts}
|
var messagePayload = %*{"content": content, "tts": tts}
|
||||||
|
|
||||||
if (not embed.isNil()):
|
if not embed.isNil():
|
||||||
messagePayload.add("embed", embed.embedJson)
|
messagePayload.add("embed", embed.embedJson)
|
||||||
|
|
||||||
if (files.len != 0):
|
if files.len != 0:
|
||||||
var client = newHttpClient()
|
var client = newHttpClient()
|
||||||
let endpoint = endpoint("/channels/" & $channel.id & "/messages")
|
let endpoint = endpoint("/channels/" & $channel.id & "/messages")
|
||||||
var multipart = newMultipartData()
|
var multipart = newMultipartData()
|
||||||
|
@ -154,7 +154,7 @@ proc sendMessage*(channel: Channel, content: string, tts: bool = false, embed: E
|
||||||
|
|
||||||
for index, file in files:
|
for index, file in files:
|
||||||
var imageStream = newFileStream(file.filePath, fmRead)
|
var imageStream = newFileStream(file.filePath, fmRead)
|
||||||
if (not isNil(imageStream)):
|
if not isNil(imageStream):
|
||||||
let data = imageStream.readALL()
|
let data = imageStream.readALL()
|
||||||
multipart.add("file" & $index, data, file.fileName, "application/octet-stream", false)
|
multipart.add("file" & $index, data, file.fileName, "application/octet-stream", false)
|
||||||
|
|
||||||
|
@ -184,37 +184,37 @@ proc modifyChannel*(channel: Channel, modify: ChannelFields): Future[Channel] {.
|
||||||
|
|
||||||
var modifyPayload = %*{}
|
var modifyPayload = %*{}
|
||||||
|
|
||||||
if (modify.name.isSome):
|
if modify.name.isSome:
|
||||||
modifyPayload.add("name", %modify.name.get())
|
modifyPayload.add("name", %modify.name.get())
|
||||||
|
|
||||||
if (modify.`type`.isSome):
|
if modify.`type`.isSome:
|
||||||
modifyPayload.add("type", %modify.`type`.get())
|
modifyPayload.add("type", %modify.`type`.get())
|
||||||
|
|
||||||
if (modify.position.isSome):
|
if modify.position.isSome:
|
||||||
modifyPayload.add("position", %modify.position.get())
|
modifyPayload.add("position", %modify.position.get())
|
||||||
|
|
||||||
if (modify.topic.isSome):
|
if modify.topic.isSome:
|
||||||
modifyPayload.add("topic", %modify.topic.get())
|
modifyPayload.add("topic", %modify.topic.get())
|
||||||
|
|
||||||
if (modify.nsfw.isSome):
|
if modify.nsfw.isSome:
|
||||||
modifyPayload.add("nsfw", %modify.nsfw.get())
|
modifyPayload.add("nsfw", %modify.nsfw.get())
|
||||||
|
|
||||||
if (modify.rateLimitPerUser.isSome):
|
if modify.rateLimitPerUser.isSome:
|
||||||
modifyPayload.add("rate_limit_per_user", %modify.rateLimitPerUser.get())
|
modifyPayload.add("rate_limit_per_user", %modify.rateLimitPerUser.get())
|
||||||
|
|
||||||
if (modify.bitrate.isSome):
|
if modify.bitrate.isSome:
|
||||||
modifyPayload.add("bitrate", %modify.bitrate.get())
|
modifyPayload.add("bitrate", %modify.bitrate.get())
|
||||||
|
|
||||||
if (modify.userLimit.isSome):
|
if modify.userLimit.isSome:
|
||||||
modifyPayload.add("user_limit", %modify.userLimit.get())
|
modifyPayload.add("user_limit", %modify.userLimit.get())
|
||||||
|
|
||||||
if (modify.permissionOverwrites.isSome):
|
if modify.permissionOverwrites.isSome:
|
||||||
var permOverwrites = parseJson("[]")
|
var permOverwrites = parseJson("[]")
|
||||||
for perm in modify.permissionOverwrites.get():
|
for perm in modify.permissionOverwrites.get():
|
||||||
permOverwrites.add(perm.permissionsToJson())
|
permOverwrites.add(perm.permissionsToJson())
|
||||||
modifyPayload.add("permission_overwrites", permOverwrites)
|
modifyPayload.add("permission_overwrites", permOverwrites)
|
||||||
|
|
||||||
if (modify.parentID.isSome):
|
if modify.parentID.isSome:
|
||||||
modifyPayload.add("parent_id", %modify.parentID.get())
|
modifyPayload.add("parent_id", %modify.parentID.get())
|
||||||
|
|
||||||
return newChannel(sendRequest(endpoint("/channels/" & $channel.id), HttpPatch,
|
return newChannel(sendRequest(endpoint("/channels/" & $channel.id), HttpPatch,
|
||||||
|
@ -229,9 +229,9 @@ proc deleteChannel*(channel: Channel) {.async.} =
|
||||||
type MessagesGetRequest* = object
|
type MessagesGetRequest* = object
|
||||||
## Use this type to get a channel's messages by setting some of the fields.
|
## Use this type to get a channel's messages by setting some of the fields.
|
||||||
## You can only set one of `around`, `before`, or `after`.
|
## You can only set one of `around`, `before`, or `after`.
|
||||||
around*: Option[snowflake]
|
around*: Option[Snowflake]
|
||||||
before*: Option[snowflake]
|
before*: Option[Snowflake]
|
||||||
after*: Option[snowflake]
|
after*: Option[Snowflake]
|
||||||
limit*: Option[int]
|
limit*: Option[int]
|
||||||
|
|
||||||
proc getMessages*(channel: Channel, request: MessagesGetRequest): seq[Message] =
|
proc getMessages*(channel: Channel, request: MessagesGetRequest): seq[Message] =
|
||||||
|
@ -245,24 +245,24 @@ proc getMessages*(channel: Channel, request: MessagesGetRequest): seq[Message] =
|
||||||
|
|
||||||
var url: string = endpoint("/channels/" & $channel.id & "/messages?")
|
var url: string = endpoint("/channels/" & $channel.id & "/messages?")
|
||||||
|
|
||||||
if (request.around.isSome):
|
if request.around.isSome:
|
||||||
url = url & "around=" & $request.around.get()
|
url = url & "around=" & $request.around.get()
|
||||||
|
|
||||||
# Raise some exceptions to make sure the user doesn't
|
# Raise some exceptions to make sure the user doesn't
|
||||||
# try to set more than one of these fields
|
# try to set more than one of these fields
|
||||||
if (request.before.isSome):
|
if request.before.isSome:
|
||||||
if (request.around.isSome):
|
if request.around.isSome:
|
||||||
raise newException(Defect, "You cannot get around and before a message! Choose one...")
|
raise newException(Defect, "You cannot get around and before a message! Choose one...")
|
||||||
url = url & "before=" & $request.before.get()
|
url = url & "before=" & $request.before.get()
|
||||||
|
|
||||||
if (request.after.isSome):
|
if request.after.isSome:
|
||||||
if (request.around.isSome or request.before.isSome):
|
if request.around.isSome or request.before.isSome:
|
||||||
raise newException(Defect, "You cannot get around/before and after a message! Choose one...")
|
raise newException(Defect, "You cannot get around/before and after a message! Choose one...")
|
||||||
url = url & "after=" & $request.after.get()
|
url = url & "after=" & $request.after.get()
|
||||||
|
|
||||||
if (request.limit.isSome):
|
if request.limit.isSome:
|
||||||
# Add the `&` for the url if something else is set.
|
# Add the `&` for the url if something else is set.
|
||||||
if (request.around.isSome or request.before.isSome or request.after.isSome):
|
if request.around.isSome or request.before.isSome or request.after.isSome:
|
||||||
url = url & "&"
|
url = url & "&"
|
||||||
|
|
||||||
url = url & "limit=" & $request.limit.get()
|
url = url & "limit=" & $request.limit.get()
|
||||||
|
@ -273,15 +273,15 @@ proc getMessages*(channel: Channel, request: MessagesGetRequest): seq[Message] =
|
||||||
for message in response:
|
for message in response:
|
||||||
result.add(newMessage(message))
|
result.add(newMessage(message))
|
||||||
|
|
||||||
proc getMessage*(channel: Channel, messageID: snowflake): Message =
|
proc getMessage*(channel: Channel, messageID: Snowflake): Message =
|
||||||
## Requests a message from the channel via the Discord REST API.
|
## Requests a message from the channel via the Discord REST API.
|
||||||
return newMessage(sendRequest(endpoint("/channels/" & $channel.id & "/messages/" & $messageID), HttpGet,
|
return newMessage(sendRequest(endpoint("/channels/" & $channel.id & "/messages/" & $messageID), HttpGet,
|
||||||
defaultHeaders(), channel.id, RateLimitBucketType.channel))
|
defaultHeaders(), channel.id, RateLimitBucketType.channel))
|
||||||
|
|
||||||
|
|
||||||
proc bulkDeleteMessages*(channel: Channel, messageIDs: seq[snowflake]) {.async.} =
|
proc bulkDeleteMessages*(channel: Channel, messageIDs: seq[Snowflake]) {.async.} =
|
||||||
## Bulk delete channel messages. This endpoint can only delete 2-100 messages.
|
## Bulk delete channel messages. This endpoint can only delete 2-100 messages.
|
||||||
## This proc takes a seq[snowflakes] represtenting the message's IDs.
|
## This proc takes a seq[Snowflakes] represtenting the message's IDs.
|
||||||
## The messages can not be older than 2 weeks!
|
## The messages can not be older than 2 weeks!
|
||||||
##
|
##
|
||||||
## See also:
|
## See also:
|
||||||
|
@ -301,8 +301,8 @@ proc bulkDeleteMessages*(channel: Channel, messages: seq[Message]) {.async.} =
|
||||||
## The messages can not be older than 2 weeks!
|
## The messages can not be older than 2 weeks!
|
||||||
##
|
##
|
||||||
## See also:
|
## See also:
|
||||||
## * `bulkDeleteMessages(channel: Channel, messageIDs: seq[snowflake])`_
|
## * `bulkDeleteMessages(channel: Channel, messageIDs: seq[Snowflake])`_
|
||||||
var messageIDs: seq[snowflake]
|
var messageIDs: seq[Snowflake]
|
||||||
for msg in messages:
|
for msg in messages:
|
||||||
messageIDs.add(msg.id)
|
messageIDs.add(msg.id)
|
||||||
|
|
||||||
|
@ -329,7 +329,7 @@ type CreateInviteFields* = object
|
||||||
maxUses: Option[int] ## Max number of uses or 0 for unlimited
|
maxUses: Option[int] ## Max number of uses or 0 for unlimited
|
||||||
temporary: Option[bool] ## Whether this invite only grants temporary membership
|
temporary: Option[bool] ## Whether this invite only grants temporary membership
|
||||||
unique: Option[bool] ## If true, don't try to reuse a similar invite (useful for creating many unique one time use invites)
|
unique: Option[bool] ## If true, don't try to reuse a similar invite (useful for creating many unique one time use invites)
|
||||||
targetUser: Option[snowflake] ## The target user id for this invite
|
targetUser: Option[Snowflake] ## The target user id for this invite
|
||||||
targetUserType: Option[int] ## The type of target user for this invite
|
targetUserType: Option[int] ## The type of target user for this invite
|
||||||
|
|
||||||
proc createChannelInvite*(channel: Channel, fields: CreateInviteFields): Invite =
|
proc createChannelInvite*(channel: Channel, fields: CreateInviteFields): Invite =
|
||||||
|
@ -344,18 +344,18 @@ proc createChannelInvite*(channel: Channel, fields: CreateInviteFields): Invite
|
||||||
## channel.createChannelInvite(CreateInviteFields(maxAge: 3600, maxUses: 10))
|
## channel.createChannelInvite(CreateInviteFields(maxAge: 3600, maxUses: 10))
|
||||||
var createPayload = %*{}
|
var createPayload = %*{}
|
||||||
|
|
||||||
if (fields.maxAge.isSome):
|
if fields.maxAge.isSome:
|
||||||
createPayload.add("max_age", %fields.maxAge.get())
|
createPayload.add("max_age", %fields.maxAge.get())
|
||||||
if (fields.maxUses.isSome):
|
if fields.maxUses.isSome:
|
||||||
createPayload.add("max_uses", %fields.maxUses.get())
|
createPayload.add("max_uses", %fields.maxUses.get())
|
||||||
if (fields.temporary.isSome):
|
if fields.temporary.isSome:
|
||||||
createPayload.add("temporary", %fields.temporary.get())
|
createPayload.add("temporary", %fields.temporary.get())
|
||||||
if (fields.unique.isSome):
|
if fields.unique.isSome:
|
||||||
createPayload.add("unique", %fields.unique.get())
|
createPayload.add("unique", %fields.unique.get())
|
||||||
if (fields.targetUser.isSome):
|
if fields.targetUser.isSome:
|
||||||
createPayload.add("target_user", %fields.targetUser.get())
|
createPayload.add("target_user", %fields.targetUser.get())
|
||||||
# Not sure if its needed because it can only be `1`
|
# Not sure if its needed because it can only be `1`
|
||||||
#[ if (fields.targetUserType.isSome):
|
#[ if fields.targetUserType.isSome:
|
||||||
createPayload.add("target_user_type", %fields.targetUserType.get()) ]#
|
createPayload.add("target_user_type", %fields.targetUserType.get()) ]#
|
||||||
|
|
||||||
return newInvite(sendRequest(endpoint("/channels/" & $channel.id & "/invites"), HttpPost,
|
return newInvite(sendRequest(endpoint("/channels/" & $channel.id & "/invites"), HttpPost,
|
||||||
|
@ -391,4 +391,4 @@ proc groupDMAddRecipient*(channel: Channel, user: User, accessToken: string, nic
|
||||||
proc groupDMRemoveRecipient*(channel: Channel, user: User) {.async.} =
|
proc groupDMRemoveRecipient*(channel: Channel, user: User) {.async.} =
|
||||||
## Removes a recipient from a Group DM.
|
## Removes a recipient from a Group DM.
|
||||||
discard sendRequest(endpoint("/channels/" & $channel.id & "/recipients/" & $user.id),
|
discard sendRequest(endpoint("/channels/" & $channel.id & "/recipients/" & $user.id),
|
||||||
HttpPut, defaultHeaders(), channel.id, RateLimitBucketType.channel)
|
HttpPut, defaultHeaders(), channel.id, RateLimitBucketType.channel)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import websocket, asyncdispatch, json, httpClient, eventdispatcher, strformat
|
import websocket, asyncdispatch, json, httpClient, eventdispatcher, strformat
|
||||||
import eventhandler, streams, nimcordutils, discordobject, user, cache, clientobjects
|
import nimcordutils, cache, clientobjects
|
||||||
import strutils, channel, options, message, emoji, guild, embed, os, presence
|
import strutils, options, presence
|
||||||
|
|
||||||
type
|
type
|
||||||
DiscordOpCode = enum
|
DiscordOpCode = enum
|
||||||
|
@ -16,10 +16,23 @@ type
|
||||||
opHello = 10,
|
opHello = 10,
|
||||||
opHeartbeatAck = 11
|
opHeartbeatAck = 11
|
||||||
|
|
||||||
|
# Forward declarations
|
||||||
|
proc closeConnection*(shard: Shard, code: int = 1000) {.async.}
|
||||||
|
proc getIdentifyPacket(shard: Shard): JsonNode
|
||||||
|
proc handleGatewayDisconnect(shard: Shard, error: string) {.async.}
|
||||||
|
proc handleHeartbeat(shard: Shard) {.async.}
|
||||||
|
proc handleWebsocketPacket(shard: Shard) {.async.}
|
||||||
|
proc newDiscordClient*(tkn: string): DiscordClient
|
||||||
|
proc newShard(shardID: int, client: DiscordClient): Shard
|
||||||
|
proc reconnectShard(shard: Shard) {.async.}
|
||||||
|
proc sendGatewayRequest*(shard: Shard, request: JsonNode, msg: string = "") {.async.}
|
||||||
|
proc startConnection*(client: DiscordClient, shardAmount: int = 1) {.async.}
|
||||||
|
proc updateClientPresence*(shard: Shard, presence: Presence) {.async.}
|
||||||
|
|
||||||
proc sendGatewayRequest*(shard: Shard, 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:
|
||||||
echo "Sending gateway payload: ", request
|
echo "Sending gateway payload: ", request
|
||||||
else:
|
else:
|
||||||
echo msg
|
echo msg
|
||||||
|
@ -29,7 +42,7 @@ proc sendGatewayRequest*(shard: Shard, request: JsonNode, msg: string = "") {.as
|
||||||
proc handleHeartbeat(shard: Shard) {.async.} =
|
proc handleHeartbeat(shard: Shard) {.async.} =
|
||||||
while true:
|
while true:
|
||||||
var heartbeatPayload: JsonNode
|
var heartbeatPayload: JsonNode
|
||||||
if (shard.lastSequence == 0):
|
if shard.lastSequence == 0:
|
||||||
heartbeatPayload = %* { "d": nil, "op": ord(DiscordOpCode.opHeartbeat) }
|
heartbeatPayload = %* { "d": nil, "op": ord(DiscordOpCode.opHeartbeat) }
|
||||||
else:
|
else:
|
||||||
heartbeatPayload = %* { "d": shard.lastSequence, "op": ord(DiscordOpCode.opHeartbeat) }
|
heartbeatPayload = %* { "d": shard.lastSequence, "op": ord(DiscordOpCode.opHeartbeat) }
|
||||||
|
@ -53,12 +66,9 @@ proc getIdentifyPacket(shard: Shard): JsonNode =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shard.client.shardCount != -1):
|
if shard.client.shardCount != -1:
|
||||||
result.add("shard", %*[shard.id, shard.client.shardCount])
|
result.add("shard", %*[shard.id, shard.client.shardCount])
|
||||||
|
|
||||||
# For some reason this shows as an error in VSCode, but it compiles fine.
|
|
||||||
#proc startConnection*(client: DiscordClient, shardCount: int = 1) {.async.}
|
|
||||||
|
|
||||||
proc closeConnection*(shard: Shard, code: int = 1000) {.async.} =
|
proc closeConnection*(shard: Shard, code: int = 1000) {.async.} =
|
||||||
echo "Disconnecting with code: ", code
|
echo "Disconnecting with code: ", code
|
||||||
await shard.ws.close(code)
|
await shard.ws.close(code)
|
||||||
|
@ -73,7 +83,7 @@ proc reconnectShard(shard: Shard) {.async.} =
|
||||||
|
|
||||||
shard.reconnecting = false
|
shard.reconnecting = false
|
||||||
shard.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 handleGatewayDisconnect(shard: Shard, error: string) {.async.} =
|
proc handleGatewayDisconnect(shard: Shard, error: string) {.async.} =
|
||||||
|
@ -87,21 +97,20 @@ proc handleGatewayDisconnect(shard: Shard, error: string) {.async.} =
|
||||||
let c = disconnectData.code
|
let c = disconnectData.code
|
||||||
|
|
||||||
# 4003, 4004, 4005, 4007, 4010, 4011, 4012, 4013 are not reconnectable.
|
# 4003, 4004, 4005, 4007, 4010, 4011, 4012, 4013 are not reconnectable.
|
||||||
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 shard.reconnecting):
|
if not shard.reconnecting:
|
||||||
waitFor shard.reconnectShard()
|
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(shard: Shard) {.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 shard.ws.readData();
|
packet = await shard.ws.readData()
|
||||||
echo "[SHARD ", $shard.id, "] Received gateway payload: ", packet.data
|
echo "[SHARD ", $shard.id, "] Received gateway payload: ", packet.data
|
||||||
|
|
||||||
if packet.opcode == Opcode.Close:
|
if packet.opcode == Opcode.Close:
|
||||||
|
@ -111,12 +120,12 @@ proc handleWebsocketPacket(shard: Shard) {.async.} =
|
||||||
|
|
||||||
# If we fail to parse the json just stop this loop
|
# If we fail to parse the json just stop this loop
|
||||||
try:
|
try:
|
||||||
json = parseJson(packet.data);
|
json = parseJson(packet.data)
|
||||||
except:
|
except:
|
||||||
echo "Failed to parse websocket payload: ", packet.data
|
echo "Failed to parse websocket payload: ", packet.data
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if (json.contains("s")):
|
if json.contains("s"):
|
||||||
shard.lastSequence = json["s"].getInt()
|
shard.lastSequence = json["s"].getInt()
|
||||||
|
|
||||||
case json["op"].getInt()
|
case json["op"].getInt()
|
||||||
|
@ -173,7 +182,7 @@ proc startConnection*(client: DiscordClient, shardAmount: int = 1) {.async.} =
|
||||||
## .. code-block:: nim
|
## .. code-block:: nim
|
||||||
## var tokenStream = newFileStream("token.txt", fmRead)
|
## var tokenStream = newFileStream("token.txt", fmRead)
|
||||||
## var tkn: string
|
## var tkn: string
|
||||||
## if (not isNil(tokenStream)):
|
## if not isNil(tokenStream):
|
||||||
## discard tokenStream.readLine(tkn)
|
## discard tokenStream.readLine(tkn)
|
||||||
## echo "Read token from the file: ", tkn
|
## echo "Read token from the file: ", tkn
|
||||||
##
|
##
|
||||||
|
@ -182,13 +191,14 @@ proc startConnection*(client: DiscordClient, shardAmount: int = 1) {.async.} =
|
||||||
## var bot = newDiscordClient(tkn)
|
## var bot = newDiscordClient(tkn)
|
||||||
echo "Connecting..."
|
echo "Connecting..."
|
||||||
|
|
||||||
let urlResult = sendRequest(endpoint("/gateway/bot"), HttpMethod.HttpGet, defaultHeaders())
|
# let urlResult = sendRequest(endpoint("/gateway/bot"), HttpMethod.HttpGet, defaultHeaders())
|
||||||
if (urlResult.contains("url")):
|
let urlResult = sendRequest(endpoint("/gateway"), HttpMethod.HttpGet, defaultHeaders())
|
||||||
|
if urlResult.contains("url"):
|
||||||
let url = urlResult["url"].getStr()
|
let url = urlResult["url"].getStr()
|
||||||
client.endpoint = url
|
client.endpoint = url
|
||||||
|
|
||||||
var shardCount = shardAmount
|
var shardCount = shardAmount
|
||||||
if (shardCount < urlResult["shards"].getInt()):
|
if urlResult.hasKey("shards") and shardCount < urlResult["shards"].getInt():
|
||||||
shardCount = urlResult["shards"].getInt()
|
shardCount = urlResult["shards"].getInt()
|
||||||
client.shardCount = shardCount
|
client.shardCount = shardCount
|
||||||
|
|
||||||
|
@ -246,4 +256,4 @@ proc newDiscordClient*(tkn: string): DiscordClient =
|
||||||
var cac: Cache
|
var cac: Cache
|
||||||
new(cac)
|
new(cac)
|
||||||
|
|
||||||
result = DiscordClient(token: tkn, cache: cac)
|
result = DiscordClient(token: tkn, cache: cac)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
type
|
type
|
||||||
snowflake* = uint64
|
Snowflake* = uint64
|
||||||
DiscordObject* = object of RootObj
|
DiscordObject* = object of RootObj
|
||||||
id*: snowflake
|
id*: Snowflake
|
||||||
|
|
||||||
proc `==`*(obj1: DiscordObject, obj2: DiscordObject): bool =
|
proc `==`*(obj1: DiscordObject, obj2: DiscordObject): bool =
|
||||||
return obj1.id == obj2.id
|
return obj1.id == obj2.id
|
||||||
|
|
|
@ -12,10 +12,10 @@ proc setTitle*(embed: var Embed, title: string) =
|
||||||
##
|
##
|
||||||
## Contstraints:
|
## Contstraints:
|
||||||
## * `title` must be set and cannot be larger than 256 characters.
|
## * `title` must be set and cannot be larger than 256 characters.
|
||||||
if (title.len < 0 or title.len > 256):
|
if title.len < 0 or title.len > 256:
|
||||||
raise newException(EmbedFieldException, "Embed title can only be 0-256 characters")
|
raise newException(EmbedFieldException, "Embed title can only be 0-256 characters")
|
||||||
|
|
||||||
if (embed.embedJson.isNil()):
|
if embed.embedJson.isNil():
|
||||||
embed.embedJson = %*{}
|
embed.embedJson = %*{}
|
||||||
|
|
||||||
embed.embedJson.add("title", %title)
|
embed.embedJson.add("title", %title)
|
||||||
|
@ -25,17 +25,17 @@ proc setDescription*(embed: var Embed, description: string) =
|
||||||
##
|
##
|
||||||
## Contstraints:
|
## Contstraints:
|
||||||
## * `description` must be set and cannot be larger than 2048 characters.
|
## * `description` must be set and cannot be larger than 2048 characters.
|
||||||
if (description.len < 0 or description.len > 2048):
|
if description.len < 0 or description.len > 2048:
|
||||||
raise newException(EmbedFieldException, "Embed description can only be 0-2048 characters")
|
raise newException(EmbedFieldException, "Embed description can only be 0-2048 characters")
|
||||||
|
|
||||||
if (embed.embedJson.isNil()):
|
if embed.embedJson.isNil():
|
||||||
embed.embedJson = %*{}
|
embed.embedJson = %*{}
|
||||||
|
|
||||||
embed.embedJson.add("description", %description)
|
embed.embedJson.add("description", %description)
|
||||||
|
|
||||||
proc setURL*(embed: var Embed, url: string) =
|
proc setURL*(embed: var Embed, url: string) =
|
||||||
## Set the url of the embed.
|
## Set the url of the embed.
|
||||||
if (embed.embedJson.isNil()):
|
if embed.embedJson.isNil():
|
||||||
embed.embedJson = %*{}
|
embed.embedJson = %*{}
|
||||||
|
|
||||||
embed.embedJson.add("url", %url)
|
embed.embedJson.add("url", %url)
|
||||||
|
@ -43,14 +43,14 @@ proc setURL*(embed: var Embed, url: string) =
|
||||||
proc setTimestamp*(embed: var Embed, timestamp: string) =
|
proc setTimestamp*(embed: var Embed, timestamp: string) =
|
||||||
## Set the timestamp of the embed.
|
## Set the timestamp of the embed.
|
||||||
## The timestamp is in `ISO8601` format.
|
## The timestamp is in `ISO8601` format.
|
||||||
if (embed.embedJson.isNil()):
|
if embed.embedJson.isNil():
|
||||||
embed.embedJson = %*{}
|
embed.embedJson = %*{}
|
||||||
|
|
||||||
embed.embedJson.add("timestamp", %timestamp)
|
embed.embedJson.add("timestamp", %timestamp)
|
||||||
|
|
||||||
proc setColor*(embed: var Embed, color: uint) =
|
proc setColor*(embed: var Embed, color: uint) =
|
||||||
## Set the color of the embed.
|
## Set the color of the embed.
|
||||||
if (embed.embedJson.isNil()):
|
if embed.embedJson.isNil():
|
||||||
embed.embedJson = %*{}
|
embed.embedJson = %*{}
|
||||||
|
|
||||||
embed.embedJson.add("color", %color)
|
embed.embedJson.add("color", %color)
|
||||||
|
@ -62,7 +62,7 @@ proc setFooter*(embed: var Embed, text: string, iconURL: string = "", proxyIconU
|
||||||
##
|
##
|
||||||
## Contstraints:
|
## Contstraints:
|
||||||
## * `text` must be set and cannot be larger than 2048 characters.
|
## * `text` must be set and cannot be larger than 2048 characters.
|
||||||
if (text.len < 0 or text.len > 2048):
|
if text.len < 0 or text.len > 2048:
|
||||||
raise newException(EmbedFieldException, "Embed's footer text can only be 0-2048 characters")
|
raise newException(EmbedFieldException, "Embed's footer text can only be 0-2048 characters")
|
||||||
|
|
||||||
let footer = %* {
|
let footer = %* {
|
||||||
|
@ -71,7 +71,7 @@ proc setFooter*(embed: var Embed, text: string, iconURL: string = "", proxyIconU
|
||||||
"proxy_icon_url": proxyIconURL
|
"proxy_icon_url": proxyIconURL
|
||||||
}
|
}
|
||||||
|
|
||||||
if (embed.embedJson.isNil()):
|
if embed.embedJson.isNil():
|
||||||
embed.embedJson = %*{}
|
embed.embedJson = %*{}
|
||||||
|
|
||||||
embed.embedJson.add("footer", footer)
|
embed.embedJson.add("footer", footer)
|
||||||
|
@ -84,12 +84,12 @@ proc setImage*(embed: var Embed, url: string, proxyIconURL: string = "", height:
|
||||||
"proxy_icon_url": proxyIconURL
|
"proxy_icon_url": proxyIconURL
|
||||||
}
|
}
|
||||||
|
|
||||||
if (height != -1):
|
if height != -1:
|
||||||
image.add("height", %height)
|
image.add("height", %height)
|
||||||
if (width != -1):
|
if width != -1:
|
||||||
image.add("width", %width)
|
image.add("width", %width)
|
||||||
|
|
||||||
if (embed.embedJson.isNil()):
|
if embed.embedJson.isNil():
|
||||||
embed.embedJson = %*{}
|
embed.embedJson = %*{}
|
||||||
|
|
||||||
embed.embedJson.add("image", image)
|
embed.embedJson.add("image", image)
|
||||||
|
@ -102,12 +102,12 @@ proc setThumbnail*(embed: var Embed, url: string, proxyIconURL: string = "", hei
|
||||||
"proxy_icon_url": proxyIconURL
|
"proxy_icon_url": proxyIconURL
|
||||||
}
|
}
|
||||||
|
|
||||||
if (height != -1):
|
if height != -1:
|
||||||
thumbnail.add("height", %height)
|
thumbnail.add("height", %height)
|
||||||
if (width != -1):
|
if width != -1:
|
||||||
thumbnail.add("width", %width)
|
thumbnail.add("width", %width)
|
||||||
|
|
||||||
if (embed.embedJson.isNil()):
|
if embed.embedJson.isNil():
|
||||||
embed.embedJson = %*{}
|
embed.embedJson = %*{}
|
||||||
|
|
||||||
embed.embedJson.add("thumbnail", thumbnail)
|
embed.embedJson.add("thumbnail", thumbnail)
|
||||||
|
@ -118,12 +118,12 @@ proc setVideo*(embed: var Embed, url: string, height: int = -1, width: int = -1)
|
||||||
"url": url
|
"url": url
|
||||||
}
|
}
|
||||||
|
|
||||||
if (height != -1):
|
if height != -1:
|
||||||
video.add("height", %height)
|
video.add("height", %height)
|
||||||
if (width != -1):
|
if width != -1:
|
||||||
video.add("width", %width)
|
video.add("width", %width)
|
||||||
|
|
||||||
if (embed.embedJson.isNil()):
|
if embed.embedJson.isNil():
|
||||||
embed.embedJson = %*{}
|
embed.embedJson = %*{}
|
||||||
|
|
||||||
embed.embedJson.add("video", video)
|
embed.embedJson.add("video", video)
|
||||||
|
@ -135,7 +135,7 @@ proc setProvider*(embed: var Embed, name: string, url: string = "") =
|
||||||
"url": url
|
"url": url
|
||||||
}
|
}
|
||||||
|
|
||||||
if (embed.embedJson.isNil()):
|
if embed.embedJson.isNil():
|
||||||
embed.embedJson = %*{}
|
embed.embedJson = %*{}
|
||||||
|
|
||||||
embed.embedJson.add("provider", provider)
|
embed.embedJson.add("provider", provider)
|
||||||
|
@ -146,7 +146,7 @@ proc setAuthor*(embed: var Embed, name: string, url: string = "", iconURL: strin
|
||||||
##
|
##
|
||||||
## Contstraints:
|
## Contstraints:
|
||||||
## * `name` cannot be larger than 256 characters
|
## * `name` cannot be larger than 256 characters
|
||||||
if (name.len < 0 or name.len > 256):
|
if name.len < 0 or name.len > 256:
|
||||||
raise newException(EmbedFieldException, "Embed's author name can only be 0-256 characters")
|
raise newException(EmbedFieldException, "Embed's author name can only be 0-256 characters")
|
||||||
|
|
||||||
let author = %* {
|
let author = %* {
|
||||||
|
@ -156,7 +156,7 @@ proc setAuthor*(embed: var Embed, name: string, url: string = "", iconURL: strin
|
||||||
"proxy_icon_url": proxyIconURL
|
"proxy_icon_url": proxyIconURL
|
||||||
}
|
}
|
||||||
|
|
||||||
if (embed.embedJson.isNil()):
|
if embed.embedJson.isNil():
|
||||||
embed.embedJson = %*{}
|
embed.embedJson = %*{}
|
||||||
|
|
||||||
embed.embedJson.add("author", author)
|
embed.embedJson.add("author", author)
|
||||||
|
@ -167,11 +167,11 @@ proc addField*(embed: var Embed, name: string, value: string, inline: bool = fal
|
||||||
## Contstraints:
|
## Contstraints:
|
||||||
## * `name` must be set and cannot be larger than 256 characters
|
## * `name` must be set and cannot be larger than 256 characters
|
||||||
## * `value` must be set and cannot be larger than 1024 characters
|
## * `value` must be set and cannot be larger than 1024 characters
|
||||||
if (name.len == 0 or value.len == 0):
|
if name.len == 0 or value.len == 0:
|
||||||
raise newException(EmbedFieldException, "Embed's field name or values must be set")
|
raise newException(EmbedFieldException, "Embed's field name or values must be set")
|
||||||
elif (name.len > 256):
|
elif name.len > 256:
|
||||||
raise newException(EmbedFieldException, "Embed's field name can only be 0-256 characters")
|
raise newException(EmbedFieldException, "Embed's field name can only be 0-256 characters")
|
||||||
elif (value.len > 1024):
|
elif value.len > 1024:
|
||||||
raise newException(EmbedFieldException, "Embed's field value can only be 0-1024 characters")
|
raise newException(EmbedFieldException, "Embed's field value can only be 0-1024 characters")
|
||||||
|
|
||||||
let field = %* {
|
let field = %* {
|
||||||
|
@ -180,12 +180,12 @@ proc addField*(embed: var Embed, name: string, value: string, inline: bool = fal
|
||||||
"inline": inline
|
"inline": inline
|
||||||
}
|
}
|
||||||
|
|
||||||
if (embed.embedJson.isNil()):
|
if embed.embedJson.isNil():
|
||||||
embed.embedJson = %*{}
|
embed.embedJson = %*{}
|
||||||
|
|
||||||
if embed.embedJson.contains("fields"):
|
if embed.embedJson.contains("fields"):
|
||||||
if (embed.embedJson["fields"].len > 25):
|
if embed.embedJson["fields"].len > 25:
|
||||||
raise newException(EmbedFieldException, "Embeds can only have upto 25 fields")
|
raise newException(EmbedFieldException, "Embeds can only have upto 25 fields")
|
||||||
embed.embedJson["fields"].add(field)
|
embed.embedJson["fields"].add(field)
|
||||||
else:
|
else:
|
||||||
embed.embedJson.add("fields", %*[field])
|
embed.embedJson.add("fields", %*[field])
|
||||||
|
|
|
@ -3,15 +3,15 @@ import json, discordobject, nimcordutils, user, httpcore, strutils, uri, strform
|
||||||
type
|
type
|
||||||
Emoji* = ref object of DiscordObject
|
Emoji* = ref object of DiscordObject
|
||||||
name*: string
|
name*: string
|
||||||
roles*: seq[snowflake]
|
roles*: seq[Snowflake]
|
||||||
user*: User
|
user*: User
|
||||||
requireColons*: bool
|
requireColons*: bool
|
||||||
managed*: bool
|
managed*: bool
|
||||||
animated*: bool
|
animated*: bool
|
||||||
available*: bool
|
available*: bool
|
||||||
guildID*: snowflake
|
guildID*: Snowflake
|
||||||
|
|
||||||
proc newEmoji*(json: JsonNode, guild: snowflake): Emoji =
|
proc newEmoji*(json: JsonNode, guild: Snowflake): Emoji =
|
||||||
## Construct an emoji with json.
|
## Construct an emoji with json.
|
||||||
## This shouldn't really be used by the user, only internal use.
|
## This shouldn't really be used by the user, only internal use.
|
||||||
result = Emoji(
|
result = Emoji(
|
||||||
|
@ -19,23 +19,23 @@ proc newEmoji*(json: JsonNode, guild: snowflake): Emoji =
|
||||||
guildID: guild
|
guildID: guild
|
||||||
)
|
)
|
||||||
|
|
||||||
if (json.contains("id")):
|
if json.contains("id"):
|
||||||
result.id = getIDFromJson(json["id"].getStr())
|
result.id = getIDFromJson(json["id"].getStr())
|
||||||
if (json.contains("roles")):
|
if json.contains("roles"):
|
||||||
for role in json["roles"]:
|
for role in json["roles"]:
|
||||||
result.roles.add(getIDFromJson(role.getStr()))
|
result.roles.add(getIDFromJson(role.getStr()))
|
||||||
if (json.contains("user")):
|
if json.contains("user"):
|
||||||
result.user = newUser(json["user"])
|
result.user = newUser(json["user"])
|
||||||
if (json.contains("require_colons")):
|
if json.contains("require_colons"):
|
||||||
result.requireColons = json["require_colons"].getBool()
|
result.requireColons = json["require_colons"].getBool()
|
||||||
if (json.contains("managed")):
|
if json.contains("managed"):
|
||||||
result.managed = json["managed"].getBool()
|
result.managed = json["managed"].getBool()
|
||||||
if (json.contains("animated")):
|
if json.contains("animated"):
|
||||||
result.requireColons = json["animated"].getBool()
|
result.requireColons = json["animated"].getBool()
|
||||||
if (json.contains("available")):
|
if json.contains("available"):
|
||||||
result.requireColons = json["available"].getBool()
|
result.requireColons = json["available"].getBool()
|
||||||
|
|
||||||
proc newEmoji*(name: string, id: snowflake): Emoji =
|
proc newEmoji*(name: string, id: Snowflake): Emoji =
|
||||||
## Construct an emoji using its name, and id.
|
## Construct an emoji using its name, and id.
|
||||||
return Emoji(name: name, id: id)
|
return Emoji(name: name, id: id)
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ proc `$`*(emoji: Emoji): string =
|
||||||
# Check if the emoji has a name but not id.
|
# Check if the emoji has a name but not id.
|
||||||
# If its true, this means that the emoji is just a unicode
|
# If its true, this means that the emoji is just a unicode
|
||||||
# representation of the emoji.
|
# representation of the emoji.
|
||||||
if (emoji.id == 0 and not emoji.name.isEmptyOrWhitespace()):
|
if emoji.id == 0 and not emoji.name.isEmptyOrWhitespace():
|
||||||
return emoji.name
|
return emoji.name
|
||||||
else:
|
else:
|
||||||
result = $emoji.id & ":" & emoji.name
|
result = $emoji.id & ":" & emoji.name
|
||||||
|
@ -61,13 +61,13 @@ proc `$`*(emoji: Emoji): string =
|
||||||
proc `==`*(a: Emoji, b: Emoji): bool =
|
proc `==`*(a: Emoji, b: Emoji): bool =
|
||||||
## Check if two Emojis are equal.
|
## Check if two Emojis are equal.
|
||||||
# Check if emojis have name but no id
|
# Check if emojis have name but no id
|
||||||
if (a.id == 0 and b.id == 0 and a.name.isEmptyOrWhitespace() and b.name.isEmptyOrWhitespace()):
|
if a.id == 0 and b.id == 0 and a.name.isEmptyOrWhitespace() and b.name.isEmptyOrWhitespace():
|
||||||
return a.name == b.name
|
return a.name == b.name
|
||||||
# Check if emoji has IDs, but no name
|
# Check if emoji has IDs, but no name
|
||||||
elif (a.id != 0 and b.id != 0 and a.name.isEmptyOrWhitespace() and b.name.isEmptyOrWhitespace()):
|
elif a.id != 0 and b.id != 0 and a.name.isEmptyOrWhitespace() and b.name.isEmptyOrWhitespace():
|
||||||
return a.id == b.id
|
return a.id == b.id
|
||||||
# Check if emoji has IDs, and a name
|
# Check if emoji has IDs, and a name
|
||||||
elif (a.id != 0 and b.id != 0 and not a.name.isEmptyOrWhitespace() and not b.name.isEmptyOrWhitespace()):
|
elif a.id != 0 and b.id != 0 and not a.name.isEmptyOrWhitespace() and not b.name.isEmptyOrWhitespace():
|
||||||
return $a == $b
|
return $a == $b
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ proc toUrlEncoding*(emoji: Emoji): string =
|
||||||
## library use.
|
## library use.
|
||||||
return encodeUrl($emoji, true)
|
return encodeUrl($emoji, true)
|
||||||
|
|
||||||
proc modifyEmoji*(emoji: var Emoji, name: string, roles: seq[snowflake] = @[]): Future[Emoji] {.async.} =
|
proc modifyEmoji*(emoji: var Emoji, name: string, roles: seq[Snowflake]): Future[Emoji] {.async.} =
|
||||||
## Modify the given emoji. Requires the `MANAGE_EMOJIS` permission.
|
## Modify the given emoji. Requires the `MANAGE_EMOJIS` permission.
|
||||||
## Changes will be reflected in given `emoji`.
|
## Changes will be reflected in given `emoji`.
|
||||||
var jsonBody = %* {
|
var jsonBody = %* {
|
||||||
|
@ -95,4 +95,4 @@ proc modifyEmoji*(emoji: var Emoji, name: string, roles: seq[snowflake] = @[]):
|
||||||
proc deleteEmoji*(emoji: Emoji) {.async.} =
|
proc deleteEmoji*(emoji: Emoji) {.async.} =
|
||||||
## Delete the given emoji. Requires the `MANAGE_EMOJIS` permission.
|
## Delete the given emoji. Requires the `MANAGE_EMOJIS` permission.
|
||||||
discard sendRequest(endpoint(fmt("/guilds/{emoji.guildID}/emojis/{emoji.id}")), HttpDelete,
|
discard sendRequest(endpoint(fmt("/guilds/{emoji.guildID}/emojis/{emoji.id}")), HttpDelete,
|
||||||
defaultHeaders(), emoji.guildID, RateLimitBucketType.guild)
|
defaultHeaders(), emoji.guildID, RateLimitBucketType.guild)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import eventhandler, json, tables, message, emoji, user, member, role
|
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 asyncdispatch, clientobjects, discordobject, presence
|
||||||
|
|
||||||
proc readyEvent(shard: Shard, json: JsonNode) =
|
proc readyEvent(shard: Shard, json: JsonNode) =
|
||||||
var readyEvent = ReadyEvent(shard: shard, readyPayload: json, name: $EventType.evtReady)
|
var readyEvent = ReadyEvent(shard: shard, readyPayload: json, name: $EventType.evtReady)
|
||||||
|
@ -26,7 +26,7 @@ proc channelCreateEvent(shard: Shard, json: JsonNode) =
|
||||||
let channelCreateEvent = ChannelCreateEvent(shard: shard, 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:
|
||||||
shard.client.cache.cacheGuildChannel(chnl.guildID, chnl)
|
shard.client.cache.cacheGuildChannel(chnl.guildID, chnl)
|
||||||
shard.client.cache.channels[chnl.id] = chnl
|
shard.client.cache.channels[chnl.id] = chnl
|
||||||
|
|
||||||
|
@ -38,15 +38,15 @@ proc channelUpdateEvent(shard: Shard, json: JsonNode) =
|
||||||
|
|
||||||
shard.client.cache.channels[chnl.id] = chnl
|
shard.client.cache.channels[chnl.id] = chnl
|
||||||
|
|
||||||
if (chnl.guildID != 0):
|
if chnl.guildID != 0:
|
||||||
let g = shard.client.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:
|
||||||
if (channel.id == chnl.id):
|
if channel.id == chnl.id:
|
||||||
index = i
|
index = i
|
||||||
|
|
||||||
if (index != -1):
|
if index != -1:
|
||||||
g.channels[index] = chnl
|
g.channels[index] = chnl
|
||||||
else:
|
else:
|
||||||
g.channels.add(chnl)
|
g.channels.add(chnl)
|
||||||
|
@ -68,7 +68,7 @@ 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 (shard.client.cache.channels.hasKey(channelID)):
|
if shard.client.cache.channels.hasKey(channelID):
|
||||||
channel = shard.client.cache.channels[channelID]
|
channel = shard.client.cache.channels[channelID]
|
||||||
channel.lastPinTimestamp = json["last_pin_timestamp"].getStr()
|
channel.lastPinTimestamp = json["last_pin_timestamp"].getStr()
|
||||||
|
|
||||||
|
@ -194,15 +194,15 @@ proc guildMembersChunk(shard: Shard, json: JsonNode) =
|
||||||
event.chunkIndex = json["chunk_index"].getInt()
|
event.chunkIndex = json["chunk_index"].getInt()
|
||||||
event.chunkCount = json["chunk_count"].getInt()
|
event.chunkCount = json["chunk_count"].getInt()
|
||||||
|
|
||||||
if (json.contains("not_found")):
|
if json.contains("not_found"):
|
||||||
for id in json["not_found"]:
|
for id in json["not_found"]:
|
||||||
event.notFound.add(getIDFromJson(id.getStr()))
|
event.notFound.add(getIDFromJson(id.getStr()))
|
||||||
|
|
||||||
if (json.contains("presences")):
|
if json.contains("presences"):
|
||||||
for presence in json["presences"]:
|
for presence in json["presences"]:
|
||||||
event.presences.add(newPresence(presence))
|
event.presences.add(newPresence(presence))
|
||||||
|
|
||||||
if (json.contains("nonce")):
|
if json.contains("nonce"):
|
||||||
event.nonce = json["nonce"].getStr()
|
event.nonce = json["nonce"].getStr()
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
@ -252,7 +252,7 @@ proc inviteCreate(shard: Shard, json: JsonNode) =
|
||||||
|
|
||||||
invite.channel = shard.client.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(shard: shard, invite: invite, name: $EventType.evtInviteCreate)
|
var event = InviteCreateEvent(shard: shard, invite: invite, name: $EventType.evtInviteCreate)
|
||||||
|
@ -264,7 +264,7 @@ proc inviteDelete(shard: Shard, json: JsonNode) =
|
||||||
event.channel = shard.client.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 = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
event.guild = shard.client.cache.getGuild(getIDFromJson(json["guild_id"].getStr()))
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
@ -295,7 +295,7 @@ proc messageDeleteEvent(shard: Shard, json: JsonNode) =
|
||||||
msg = Message(id: msgID)
|
msg = Message(id: msgID)
|
||||||
|
|
||||||
msg.channelID = getIDFromJson(json["channel_id"].getStr())
|
msg.channelID = getIDFromJson(json["channel_id"].getStr())
|
||||||
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(shard: shard, message: msg, name: $EventType.evtMessageDelete)
|
let event = MessageDeleteEvent(shard: shard, message: msg, name: $EventType.evtMessageDelete)
|
||||||
|
@ -305,7 +305,7 @@ proc messageDeleteBulkEvent(shard: Shard, json: JsonNode) =
|
||||||
var event = MessageDeleteBulkEvent(shard: shard, name: $EventType.evtMessageDeleteBulk)
|
var event = MessageDeleteBulkEvent(shard: shard, name: $EventType.evtMessageDeleteBulk)
|
||||||
|
|
||||||
event.channel = shard.client.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 = shard.client.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"]:
|
||||||
|
@ -319,7 +319,7 @@ proc messageDeleteBulkEvent(shard: Shard, json: JsonNode) =
|
||||||
msg = Message(id: msgID, channelID: channelID)
|
msg = Message(id: msgID, channelID: channelID)
|
||||||
|
|
||||||
event.channel = shard.client.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())
|
||||||
|
|
||||||
event.messages.add(msg)
|
event.messages.add(msg)
|
||||||
|
@ -337,12 +337,12 @@ proc messageReactionAdd(shard: Shard, json: JsonNode) =
|
||||||
msg = Message(id: msgID)
|
msg = Message(id: msgID)
|
||||||
|
|
||||||
msg.channelID = getIDFromJson(json["channel_id"].getStr())
|
msg.channelID = getIDFromJson(json["channel_id"].getStr())
|
||||||
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 = shard.client.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)
|
||||||
|
|
||||||
event.emoji = newEmoji(json["emoji"], msg.guildID)
|
event.emoji = newEmoji(json["emoji"], msg.guildID)
|
||||||
|
@ -360,7 +360,7 @@ proc messageReactionRemove(shard: Shard, json: JsonNode) =
|
||||||
msg = Message(id: msgID)
|
msg = Message(id: msgID)
|
||||||
|
|
||||||
msg.channelID = getIDFromJson(json["channel_id"].getStr())
|
msg.channelID = getIDFromJson(json["channel_id"].getStr())
|
||||||
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 = shard.client.cache.getUser(getIDFromJson(json["user_id"].getStr()))
|
event.user = shard.client.cache.getUser(getIDFromJson(json["user_id"].getStr()))
|
||||||
|
@ -380,7 +380,7 @@ proc messageReactionRemoveAll(shard: Shard, json: JsonNode) =
|
||||||
msg = Message(id: msgID)
|
msg = Message(id: msgID)
|
||||||
|
|
||||||
msg.channelID = getIDFromJson(json["channel_id"].getStr())
|
msg.channelID = getIDFromJson(json["channel_id"].getStr())
|
||||||
if (json.contains("guild_id")):
|
if json.contains("guild_id"):
|
||||||
msg.guildID = getIDFromJson(json["guild_id"].getStr())
|
msg.guildID = getIDFromJson(json["guild_id"].getStr())
|
||||||
|
|
||||||
dispatchEvent(event)
|
dispatchEvent(event)
|
||||||
|
@ -396,7 +396,7 @@ proc messageReactionRemoveEmoji(shard: Shard, json: JsonNode) =
|
||||||
msg = Message(id: msgID)
|
msg = Message(id: msgID)
|
||||||
|
|
||||||
msg.channelID = getIDFromJson(json["channel_id"].getStr())
|
msg.channelID = getIDFromJson(json["channel_id"].getStr())
|
||||||
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.emoji = newEmoji(json["emoji"], msg.guildID)
|
event.emoji = newEmoji(json["emoji"], msg.guildID)
|
||||||
|
@ -414,9 +414,9 @@ proc presenceUpdate(shard: Shard, json: JsonNode) =
|
||||||
for role in json["roles"]:
|
for role in json["roles"]:
|
||||||
member.roles.add(getIDFromJson(role.getStr()))
|
member.roles.add(getIDFromJson(role.getStr()))
|
||||||
|
|
||||||
if (json.contains("premium_since")):
|
if json.contains("premium_since"):
|
||||||
member.premiumSince = json["premium_since"].getStr()
|
member.premiumSince = json["premium_since"].getStr()
|
||||||
if (json.contains("nick")):
|
if json.contains("nick"):
|
||||||
member.nick = json["nick"].getStr()
|
member.nick = json["nick"].getStr()
|
||||||
|
|
||||||
member.presence = newPresence(json)
|
member.presence = newPresence(json)
|
||||||
|
@ -426,12 +426,12 @@ proc typingStart(shard: Shard, json: JsonNode) =
|
||||||
|
|
||||||
event.channel = shard.client.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 = shard.client.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)
|
||||||
|
@ -504,9 +504,9 @@ let internalEventTable: Table[string, proc(shard: Shard, json: JsonNode) {.nimca
|
||||||
|
|
||||||
proc handleDiscordEvent*(shard: Shard, 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(shard: Shard, json: JsonNode) = internalEventTable[eventName]
|
let eventProc: proc(shard: Shard, json: JsonNode) = internalEventTable[eventName]
|
||||||
eventProc(shard, json)
|
eventProc(shard, json)
|
||||||
else:
|
else:
|
||||||
echo "Failed to find event: ", eventName
|
echo "Failed to find event: ", eventName
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ type
|
||||||
members*: seq[GuildMember]
|
members*: seq[GuildMember]
|
||||||
chunkIndex*: int
|
chunkIndex*: int
|
||||||
chunkCount*: int
|
chunkCount*: int
|
||||||
notFound*: seq[snowflake]
|
notFound*: seq[Snowflake]
|
||||||
presences*: seq[Presence]
|
presences*: seq[Presence]
|
||||||
nonce*: string
|
nonce*: string
|
||||||
|
|
||||||
|
@ -252,7 +252,7 @@ proc registerEventListener*(event: EventType, listener: proc(event: BaseEvent))
|
||||||
## echo "ID: ", bot.clientUser.id
|
## echo "ID: ", bot.clientUser.id
|
||||||
## echo "--------------------"
|
## echo "--------------------"
|
||||||
## )
|
## )
|
||||||
if (eventListeners.hasKey($event)):
|
if eventListeners.hasKey($event):
|
||||||
eventListeners[$event].add(cast[proc(event: BaseEvent)](listener))
|
eventListeners[$event].add(cast[proc(event: BaseEvent)](listener))
|
||||||
|
|
||||||
echo "Added other event listener: ", $event
|
echo "Added other event listener: ", $event
|
||||||
|
@ -264,10 +264,10 @@ proc registerEventListener*(event: EventType, listener: proc(event: BaseEvent))
|
||||||
|
|
||||||
proc dispatchEvent*[T: BaseEvent](event: T) =
|
proc dispatchEvent*[T: BaseEvent](event: T) =
|
||||||
## Dispatches an event so something can listen to it.
|
## Dispatches an event so something can listen to it.
|
||||||
if (eventListeners.hasKey(event.name)):
|
if eventListeners.hasKey(event.name):
|
||||||
let listeners = eventListeners[event.name]
|
let listeners = eventListeners[event.name]
|
||||||
echo "Dispatching event: ", event.name
|
echo "Dispatching event: ", event.name
|
||||||
for index, eventListener in listeners.pairs:
|
for index, eventListener in listeners.pairs:
|
||||||
eventListener(event)
|
eventListener(event)
|
||||||
else:
|
else:
|
||||||
echo "No event listeners for event: ", event.name
|
echo "No event listeners for event: ", event.name
|
||||||
|
|
|
@ -53,9 +53,9 @@ type
|
||||||
|
|
||||||
VoiceState* = ref object
|
VoiceState* = ref object
|
||||||
## Used to represent a user's voice connection status
|
## Used to represent a user's voice connection status
|
||||||
guildID*: snowflake
|
guildID*: Snowflake
|
||||||
channelID*: snowflake
|
channelID*: Snowflake
|
||||||
userID*: snowflake
|
userID*: Snowflake
|
||||||
member*: GuildMember
|
member*: GuildMember
|
||||||
sessionID*: string
|
sessionID*: string
|
||||||
deaf*: bool
|
deaf*: bool
|
||||||
|
@ -72,10 +72,10 @@ type
|
||||||
splash*: string
|
splash*: string
|
||||||
discoverySplash*: string
|
discoverySplash*: string
|
||||||
owner*: bool
|
owner*: bool
|
||||||
ownerID: snowflake
|
ownerID: Snowflake
|
||||||
permissions*: Permissions
|
permissions*: Permissions
|
||||||
region*: string
|
region*: string
|
||||||
afkChannelID*: snowflake
|
afkChannelID*: Snowflake
|
||||||
afkTimeout*: int
|
afkTimeout*: int
|
||||||
verificationLevel*: VerificationLevel
|
verificationLevel*: VerificationLevel
|
||||||
defaultMessageNotifications*: MessageNotificationsLevel
|
defaultMessageNotifications*: MessageNotificationsLevel
|
||||||
|
@ -84,12 +84,12 @@ type
|
||||||
emojis*: seq[Emoji]
|
emojis*: seq[Emoji]
|
||||||
features*: seq[string]
|
features*: seq[string]
|
||||||
mfaLevel*: MFALevel
|
mfaLevel*: MFALevel
|
||||||
applicationID*: snowflake
|
applicationID*: Snowflake
|
||||||
widgetEnabled*: bool
|
widgetEnabled*: bool
|
||||||
widgetChannelID*: snowflake
|
widgetChannelID*: Snowflake
|
||||||
systemChannelID*: snowflake
|
systemChannelID*: Snowflake
|
||||||
systemChannelFlags*: int
|
systemChannelFlags*: int
|
||||||
rulesChannelID*: snowflake
|
rulesChannelID*: Snowflake
|
||||||
joinedAt*: string
|
joinedAt*: string
|
||||||
large*: bool
|
large*: bool
|
||||||
unavailable*: bool
|
unavailable*: bool
|
||||||
|
@ -106,7 +106,7 @@ type
|
||||||
premiumTier*: PremiumTier
|
premiumTier*: PremiumTier
|
||||||
premiumSubscriptionCount*: int
|
premiumSubscriptionCount*: int
|
||||||
preferredLocale*: string
|
preferredLocale*: string
|
||||||
publicUpdatesChannelID*: snowflake
|
publicUpdatesChannelID*: Snowflake
|
||||||
maxVideoChannelUsers*: int
|
maxVideoChannelUsers*: int
|
||||||
approximateMemberCount*: int
|
approximateMemberCount*: int
|
||||||
approximatePresenceCount*: int
|
approximatePresenceCount*: int
|
||||||
|
@ -150,7 +150,7 @@ type
|
||||||
`type`*: string ## Integration type (twitch, youtube, etc)
|
`type`*: string ## Integration type (twitch, youtube, etc)
|
||||||
enabled*: bool
|
enabled*: bool
|
||||||
syncing*: bool
|
syncing*: bool
|
||||||
roleID*: snowflake
|
roleID*: Snowflake
|
||||||
enableEmoticons*: bool
|
enableEmoticons*: bool
|
||||||
expireBehavior*: IntegrationExpireBehavior
|
expireBehavior*: IntegrationExpireBehavior
|
||||||
expireGracePeriod*: int
|
expireGracePeriod*: int
|
||||||
|
@ -160,7 +160,7 @@ type
|
||||||
|
|
||||||
GuildWidget* = ref object
|
GuildWidget* = ref object
|
||||||
enabled*: bool
|
enabled*: bool
|
||||||
channelID*: snowflake
|
channelID*: Snowflake
|
||||||
|
|
||||||
GuildWidgetStyle* = enum
|
GuildWidgetStyle* = enum
|
||||||
guildWidgetStyleShield = "shield",
|
guildWidgetStyleShield = "shield",
|
||||||
|
@ -199,9 +199,9 @@ proc newGuild*(json: JsonNode): Guild {.inline.} =
|
||||||
)
|
)
|
||||||
|
|
||||||
# Parse all non guaranteed fields
|
# Parse all non guaranteed fields
|
||||||
if (json.contains("owner")):
|
if json.contains("owner"):
|
||||||
g.owner = json["owner"].getBool()
|
g.owner = json["owner"].getBool()
|
||||||
if (json.contains("permissions")):
|
if json.contains("permissions"):
|
||||||
g.permissions = newPermissions(json["permissions"])
|
g.permissions = newPermissions(json["permissions"])
|
||||||
for role in json["roles"]:
|
for role in json["roles"]:
|
||||||
g.roles.add(newRole(role, g.id))
|
g.roles.add(newRole(role, g.id))
|
||||||
|
@ -209,17 +209,17 @@ proc newGuild*(json: JsonNode): Guild {.inline.} =
|
||||||
g.emojis.add(newEmoji(emoji, g.id))
|
g.emojis.add(newEmoji(emoji, g.id))
|
||||||
for feature in json["features"]:
|
for feature in json["features"]:
|
||||||
g.features.add(feature.getStr())
|
g.features.add(feature.getStr())
|
||||||
if (json.contains("widget_enabled")):
|
if json.contains("widget_enabled"):
|
||||||
g.widgetEnabled = json["widget_enabled"].getBool()
|
g.widgetEnabled = json["widget_enabled"].getBool()
|
||||||
if (json.contains("widget_channel_id")):
|
if json.contains("widget_channel_id"):
|
||||||
g.widgetChannelID = getIDFromJson(json["widget_channel_id"].getStr())
|
g.widgetChannelID = getIDFromJson(json["widget_channel_id"].getStr())
|
||||||
if (json.contains("large")):
|
if json.contains("large"):
|
||||||
g.large = json["large"].getBool()
|
g.large = json["large"].getBool()
|
||||||
if (json.contains("unavailable")):
|
if json.contains("unavailable"):
|
||||||
g.unavailable = json["unavailable"].getBool()
|
g.unavailable = json["unavailable"].getBool()
|
||||||
if (json.contains("member_count")):
|
if json.contains("member_count"):
|
||||||
g.memberCount = json["member_count"].getInt()
|
g.memberCount = json["member_count"].getInt()
|
||||||
if (json.contains("voice_states")):
|
if json.contains("voice_states"):
|
||||||
for voicestate in json["voice_states"]:
|
for voicestate in json["voice_states"]:
|
||||||
var state = VoiceState(
|
var state = VoiceState(
|
||||||
guildID: g.id,
|
guildID: g.id,
|
||||||
|
@ -234,47 +234,47 @@ proc newGuild*(json: JsonNode): Guild {.inline.} =
|
||||||
suppress: voicestate["suppress"].getBool()
|
suppress: voicestate["suppress"].getBool()
|
||||||
)
|
)
|
||||||
|
|
||||||
if (voicestate.contains("member")):
|
if voicestate.contains("member"):
|
||||||
state.member = newGuildMember(voicestate["member"], g.id)
|
state.member = newGuildMember(voicestate["member"], g.id)
|
||||||
|
|
||||||
g.voiceStates.add(state)
|
g.voiceStates.add(state)
|
||||||
if (json.contains("members")):
|
if json.contains("members"):
|
||||||
for member in json["members"]:
|
for member in json["members"]:
|
||||||
g.members.insert(newGuildMember(member, g.id))
|
g.members.insert(newGuildMember(member, g.id))
|
||||||
if (json.contains("channels")):
|
if json.contains("channels"):
|
||||||
for channel in json["channels"]:
|
for channel in json["channels"]:
|
||||||
g.channels.insert(newChannel(channel))
|
g.channels.insert(newChannel(channel))
|
||||||
if (json.contains("presences")):
|
if json.contains("presences"):
|
||||||
# Parse all presences
|
# Parse all presences
|
||||||
var tmpPresences = initTable[snowflake, Presence]()
|
var tmpPresences = initTable[Snowflake, Presence]()
|
||||||
for presence in json["presences"]:
|
for presence in json["presences"]:
|
||||||
tmpPresences.add(getIDFromJson(presence["user"]["id"].getStr()), newPresence(presence))
|
tmpPresences.add(getIDFromJson(presence["user"]["id"].getStr()), newPresence(presence))
|
||||||
|
|
||||||
# Check if the `tmpPresences` variable has a presence for the member,
|
# Check if the `tmpPresences` variable has a presence for the member,
|
||||||
# if it does, then update the member to include its presence.
|
# if it does, then update the member to include its presence.
|
||||||
for member in g.members:
|
for member in g.members:
|
||||||
if (tmpPresences.hasKey(member.user.id)):
|
if tmpPresences.hasKey(member.user.id):
|
||||||
member.presence = tmpPresences[member.user.id]
|
member.presence = tmpPresences[member.user.id]
|
||||||
|
|
||||||
if (json.contains("max_presences")):
|
if json.contains("max_presences"):
|
||||||
g.maxPresences = json["max_presences"].getInt()
|
g.maxPresences = json["max_presences"].getInt()
|
||||||
if (json.contains("max_members")):
|
if json.contains("max_members"):
|
||||||
g.maxMembers = json["max_members"].getInt()
|
g.maxMembers = json["max_members"].getInt()
|
||||||
if (json.contains("premium_subscription_count")):
|
if json.contains("premium_subscription_count"):
|
||||||
g.premiumSubscriptionCount = json["premium_subscription_count"].getInt()
|
g.premiumSubscriptionCount = json["premium_subscription_count"].getInt()
|
||||||
if (json.contains("max_video_channel_users")):
|
if json.contains("max_video_channel_users"):
|
||||||
g.maxVideoChannelUsers = json["max_video_channel_users"].getInt()
|
g.maxVideoChannelUsers = json["max_video_channel_users"].getInt()
|
||||||
if (json.contains("approximate_member_count")):
|
if json.contains("approximate_member_count"):
|
||||||
g.approximateMemberCount = json["approximate_member_count"].getInt()
|
g.approximateMemberCount = json["approximate_member_count"].getInt()
|
||||||
if (json.contains("approximate_presence_count")):
|
if json.contains("approximate_presence_count"):
|
||||||
g.approximatePresenceCount = json["approximate_presence_count"].getInt()
|
g.approximatePresenceCount = json["approximate_presence_count"].getInt()
|
||||||
|
|
||||||
return g
|
return g
|
||||||
|
|
||||||
proc createGuild*(name: string, region: Option[string], icon: Option[string], verificationLevel: Option[VerificationLevel],
|
proc createGuild*(name: string, region: Option[string], icon: Option[string], verificationLevel: Option[VerificationLevel],
|
||||||
defaultMessageNotifications: Option[MessageNotificationsLevel], explicitContentFilter: Option[ExplicitContentFilterLevel],
|
defaultMessageNotifications: Option[MessageNotificationsLevel], explicitContentFilter: Option[ExplicitContentFilterLevel],
|
||||||
roles: Option[seq[Role]], channels: Option[seq[Channel]], afkChannelID: Option[snowflake], afkTimeout: Option[int],
|
roles: Option[seq[Role]], channels: Option[seq[Channel]], afkChannelID: Option[Snowflake], afkTimeout: Option[int],
|
||||||
systemChannelID: Option[snowflake]): Guild =
|
systemChannelID: Option[Snowflake]): Guild =
|
||||||
## Create a new guild.
|
## Create a new guild.
|
||||||
##
|
##
|
||||||
## Some restraints/notes for this endpoint:
|
## Some restraints/notes for this endpoint:
|
||||||
|
@ -296,17 +296,17 @@ proc createGuild*(name: string, region: Option[string], icon: Option[string], ve
|
||||||
|
|
||||||
var json = %* {"name": name}
|
var json = %* {"name": name}
|
||||||
|
|
||||||
if (region.isSome):
|
if region.isSome:
|
||||||
json.add("region", %region.get())
|
json.add("region", %region.get())
|
||||||
if (icon.isSome):
|
if icon.isSome:
|
||||||
json.add("icon", %icon.get())
|
json.add("icon", %icon.get())
|
||||||
if (verificationLevel.isSome):
|
if verificationLevel.isSome:
|
||||||
json.add("verification_level", %ord(verificationLevel.get()))
|
json.add("verification_level", %ord(verificationLevel.get()))
|
||||||
if (defaultMessageNotifications.isSome):
|
if defaultMessageNotifications.isSome:
|
||||||
json.add("default_message_notifications", %ord(defaultMessageNotifications.get()))
|
json.add("default_message_notifications", %ord(defaultMessageNotifications.get()))
|
||||||
if (explicitContentFilter.isSome):
|
if explicitContentFilter.isSome:
|
||||||
json.add("explicit_content_filter", %ord(explicitContentFilter.get()))
|
json.add("explicit_content_filter", %ord(explicitContentFilter.get()))
|
||||||
if (roles.isSome):
|
if roles.isSome:
|
||||||
#json.add("verification_level", %ord(verificationLevel.get()))
|
#json.add("verification_level", %ord(verificationLevel.get()))
|
||||||
var rolesJson = parseJson("[]")
|
var rolesJson = parseJson("[]")
|
||||||
for role in roles.get():
|
for role in roles.get():
|
||||||
|
@ -322,7 +322,7 @@ proc createGuild*(name: string, region: Option[string], icon: Option[string], ve
|
||||||
rolesJson.add(roleJson)
|
rolesJson.add(roleJson)
|
||||||
|
|
||||||
json.add("channels", rolesJson)
|
json.add("channels", rolesJson)
|
||||||
if (channels.isSome):
|
if channels.isSome:
|
||||||
var channelsJson = parseJson("[]")
|
var channelsJson = parseJson("[]")
|
||||||
for channel in channels.get():
|
for channel in channels.get():
|
||||||
var channelJson = %*{
|
var channelJson = %*{
|
||||||
|
@ -336,7 +336,7 @@ proc createGuild*(name: string, region: Option[string], icon: Option[string], ve
|
||||||
"parent_id": channel.parentID
|
"parent_id": channel.parentID
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel.permissionOverwrites.len != 0):
|
if channel.permissionOverwrites.len != 0:
|
||||||
channelsJson.add("permission_overwrites", parseJson("[]"))
|
channelsJson.add("permission_overwrites", parseJson("[]"))
|
||||||
for permOverwrite in channel.permissionOverwrites:
|
for permOverwrite in channel.permissionOverwrites:
|
||||||
channelsJson["permission_overwrites"].add(permOverwrite.permissionsToJson())
|
channelsJson["permission_overwrites"].add(permOverwrite.permissionsToJson())
|
||||||
|
@ -344,11 +344,11 @@ proc createGuild*(name: string, region: Option[string], icon: Option[string], ve
|
||||||
channelsJson.add(channelJson)
|
channelsJson.add(channelJson)
|
||||||
|
|
||||||
json.add("channels", channelsJson)
|
json.add("channels", channelsJson)
|
||||||
if (afkChannelID.isSome):
|
if afkChannelID.isSome:
|
||||||
json.add("afk_channel_id", %ord(afkChannelID.get()))
|
json.add("afk_channel_id", %ord(afkChannelID.get()))
|
||||||
if (afkTimeout.isSome):
|
if afkTimeout.isSome:
|
||||||
json.add("afk_timeout", %ord(afkTimeout.get()))
|
json.add("afk_timeout", %ord(afkTimeout.get()))
|
||||||
if (systemChannelID.isSome):
|
if systemChannelID.isSome:
|
||||||
json.add("system_channel_id", %ord(systemChannelID.get()))
|
json.add("system_channel_id", %ord(systemChannelID.get()))
|
||||||
|
|
||||||
return newGuild(sendRequest(endpoint("/guilds"), HttpPost,
|
return newGuild(sendRequest(endpoint("/guilds"), HttpPost,
|
||||||
|
@ -386,15 +386,15 @@ type GuildModify* = ref object
|
||||||
verificationLevel*: Option[VerificationLevel]
|
verificationLevel*: Option[VerificationLevel]
|
||||||
defaultMessageNotifications*: Option[MessageNotificationsLevel]
|
defaultMessageNotifications*: Option[MessageNotificationsLevel]
|
||||||
explicitContentFilter*: Option[ExplicitContentFilterLevel]
|
explicitContentFilter*: Option[ExplicitContentFilterLevel]
|
||||||
afkChannelID*: Option[snowflake]
|
afkChannelID*: Option[Snowflake]
|
||||||
afkTimeout*: Option[int]
|
afkTimeout*: Option[int]
|
||||||
icon*: Option[Image]
|
icon*: Option[Image]
|
||||||
ownerID*: Option[snowflake]
|
ownerID*: Option[Snowflake]
|
||||||
splash*: Option[Image]
|
splash*: Option[Image]
|
||||||
banner*: Option[Image]
|
banner*: Option[Image]
|
||||||
systemChannelID*: Option[snowflake]
|
systemChannelID*: Option[Snowflake]
|
||||||
rulesChannelID*: Option[snowflake]
|
rulesChannelID*: Option[Snowflake]
|
||||||
publicUpdatesChannelID*: Option[snowflake]
|
publicUpdatesChannelID*: Option[Snowflake]
|
||||||
preferredLocale*: Option[string]
|
preferredLocale*: Option[string]
|
||||||
|
|
||||||
proc modifyGuild*(guild: Guild, modify: GuildModify): Future[Guild] {.async.} =
|
proc modifyGuild*(guild: Guild, modify: GuildModify): Future[Guild] {.async.} =
|
||||||
|
@ -408,49 +408,49 @@ proc modifyGuild*(guild: Guild, modify: GuildModify): Future[Guild] {.async.} =
|
||||||
|
|
||||||
var modifyPayload = %*{}
|
var modifyPayload = %*{}
|
||||||
|
|
||||||
if (modify.name.isSome):
|
if modify.name.isSome:
|
||||||
modifyPayload.add("name", %modify.name.get())
|
modifyPayload.add("name", %modify.name.get())
|
||||||
|
|
||||||
if (modify.region.isSome):
|
if modify.region.isSome:
|
||||||
modifyPayload.add("region", %modify.region.get())
|
modifyPayload.add("region", %modify.region.get())
|
||||||
|
|
||||||
if (modify.verificationLevel.isSome):
|
if modify.verificationLevel.isSome:
|
||||||
modifyPayload.add("verification_level", %modify.verificationLevel.get())
|
modifyPayload.add("verification_level", %modify.verificationLevel.get())
|
||||||
|
|
||||||
if (modify.defaultMessageNotifications.isSome):
|
if modify.defaultMessageNotifications.isSome:
|
||||||
modifyPayload.add("default_message_notifications", %modify.defaultMessageNotifications.get())
|
modifyPayload.add("default_message_notifications", %modify.defaultMessageNotifications.get())
|
||||||
|
|
||||||
if (modify.explicitContentFilter.isSome):
|
if modify.explicitContentFilter.isSome:
|
||||||
modifyPayload.add("explicit_content_filter", %modify.explicitContentFilter.get())
|
modifyPayload.add("explicit_content_filter", %modify.explicitContentFilter.get())
|
||||||
|
|
||||||
if (modify.afkChannelID.isSome):
|
if modify.afkChannelID.isSome:
|
||||||
modifyPayload.add("afk_channel_id", %modify.afkChannelID.get())
|
modifyPayload.add("afk_channel_id", %modify.afkChannelID.get())
|
||||||
|
|
||||||
if (modify.afkTimeout.isSome):
|
if modify.afkTimeout.isSome:
|
||||||
modifyPayload.add("afk_timeout", %modify.afkTimeout.get())
|
modifyPayload.add("afk_timeout", %modify.afkTimeout.get())
|
||||||
|
|
||||||
if (modify.icon.isSome):
|
if modify.icon.isSome:
|
||||||
modifyPayload.add("icon", %modify.icon.get().imageToDataURI())
|
modifyPayload.add("icon", %modify.icon.get().imageToDataURI())
|
||||||
|
|
||||||
if (modify.ownerID.isSome):
|
if modify.ownerID.isSome:
|
||||||
modifyPayload.add("owner_id", %modify.ownerID.get())
|
modifyPayload.add("owner_id", %modify.ownerID.get())
|
||||||
|
|
||||||
if (modify.splash.isSome):
|
if modify.splash.isSome:
|
||||||
modifyPayload.add("splash", %modify.splash.get().imageToDataURI())
|
modifyPayload.add("splash", %modify.splash.get().imageToDataURI())
|
||||||
|
|
||||||
if (modify.banner.isSome):
|
if modify.banner.isSome:
|
||||||
modifyPayload.add("banner", %modify.banner.get().imageToDataURI())
|
modifyPayload.add("banner", %modify.banner.get().imageToDataURI())
|
||||||
|
|
||||||
if (modify.systemChannelID.isSome):
|
if modify.systemChannelID.isSome:
|
||||||
modifyPayload.add("system_channel_id", %modify.systemChannelID.get())
|
modifyPayload.add("system_channel_id", %modify.systemChannelID.get())
|
||||||
|
|
||||||
if (modify.rulesChannelID.isSome):
|
if modify.rulesChannelID.isSome:
|
||||||
modifyPayload.add("rules_channel_id", %modify.rulesChannelID.get())
|
modifyPayload.add("rules_channel_id", %modify.rulesChannelID.get())
|
||||||
|
|
||||||
if (modify.publicUpdatesChannelID.isSome):
|
if modify.publicUpdatesChannelID.isSome:
|
||||||
modifyPayload.add("public_updates_channel_id", %modify.publicUpdatesChannelID.get())
|
modifyPayload.add("public_updates_channel_id", %modify.publicUpdatesChannelID.get())
|
||||||
|
|
||||||
if (modify.preferredLocale.isSome):
|
if modify.preferredLocale.isSome:
|
||||||
modifyPayload.add("preferred_locale", %modify.preferredLocale.get())
|
modifyPayload.add("preferred_locale", %modify.preferredLocale.get())
|
||||||
|
|
||||||
return newGuild(sendRequest(endpoint("/guilds/" & $guild.id), HttpPatch,
|
return newGuild(sendRequest(endpoint("/guilds/" & $guild.id), HttpPatch,
|
||||||
|
@ -488,33 +488,33 @@ proc createGuildChannel*(guild: var Guild, create: ChannelFields): Future[Channe
|
||||||
var createPayload = %*{}
|
var createPayload = %*{}
|
||||||
|
|
||||||
# Make sure that the name is supplied since its required for this endpoint.
|
# Make sure that the name is supplied since its required for this endpoint.
|
||||||
if (create.name.isSome):
|
if create.name.isSome:
|
||||||
createPayload.add("name", %create.name.get())
|
createPayload.add("name", %create.name.get())
|
||||||
else:
|
else:
|
||||||
raise newException(Defect, "You must have a channel name when creating it!")
|
raise newException(Defect, "You must have a channel name when creating it!")
|
||||||
|
|
||||||
if (create.`type`.isSome):
|
if create.`type`.isSome:
|
||||||
createPayload.add("type", %create.`type`.get())
|
createPayload.add("type", %create.`type`.get())
|
||||||
|
|
||||||
if (create.position.isSome):
|
if create.position.isSome:
|
||||||
createPayload.add("position", %create.position.get())
|
createPayload.add("position", %create.position.get())
|
||||||
|
|
||||||
if (create.topic.isSome):
|
if create.topic.isSome:
|
||||||
createPayload.add("topic", %create.topic.get())
|
createPayload.add("topic", %create.topic.get())
|
||||||
|
|
||||||
if (create.nsfw.isSome):
|
if create.nsfw.isSome:
|
||||||
createPayload.add("nsfw", %create.nsfw.get())
|
createPayload.add("nsfw", %create.nsfw.get())
|
||||||
|
|
||||||
if (create.rateLimitPerUser.isSome):
|
if create.rateLimitPerUser.isSome:
|
||||||
createPayload.add("rate_limit_per_user", %create.rateLimitPerUser.get())
|
createPayload.add("rate_limit_per_user", %create.rateLimitPerUser.get())
|
||||||
|
|
||||||
if (create.bitrate.isSome):
|
if create.bitrate.isSome:
|
||||||
createPayload.add("bitrate", %create.bitrate.get())
|
createPayload.add("bitrate", %create.bitrate.get())
|
||||||
|
|
||||||
if (create.userLimit.isSome):
|
if create.userLimit.isSome:
|
||||||
createPayload.add("user_limit", %create.userLimit.get())
|
createPayload.add("user_limit", %create.userLimit.get())
|
||||||
|
|
||||||
if (create.permissionOverwrites.isSome):
|
if create.permissionOverwrites.isSome:
|
||||||
var permOverwrites = parseJson("[]")
|
var permOverwrites = parseJson("[]")
|
||||||
for perm in create.permissionOverwrites.get():
|
for perm in create.permissionOverwrites.get():
|
||||||
permOverwrites.add(perm.permissionsToJson())
|
permOverwrites.add(perm.permissionsToJson())
|
||||||
|
@ -536,7 +536,7 @@ proc modifyGuildChannelPositions*(guild: var Guild, channels: seq[Channel]) {.as
|
||||||
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
guild.id, RateLimitBucketType.guild, jsonBody)
|
guild.id, RateLimitBucketType.guild, jsonBody)
|
||||||
|
|
||||||
proc getGuildMember*(guild: var Guild, memberID: snowflake): GuildMember =
|
proc getGuildMember*(guild: var Guild, memberID: Snowflake): GuildMember =
|
||||||
## Get a guild member.
|
## Get a guild member.
|
||||||
## This first checks `guild.members`, but if it doesn't exist there,
|
## This first checks `guild.members`, but if it doesn't exist there,
|
||||||
## it will be requested from Discord's REST API.
|
## it will be requested from Discord's REST API.
|
||||||
|
@ -544,7 +544,7 @@ proc getGuildMember*(guild: var Guild, memberID: snowflake): GuildMember =
|
||||||
## If we end up requesting one, it will add it to `guild.members`
|
## If we end up requesting one, it will add it to `guild.members`
|
||||||
|
|
||||||
for member in guild.members:
|
for member in guild.members:
|
||||||
if (member.id == memberID):
|
if member.id == memberID:
|
||||||
return member
|
return member
|
||||||
|
|
||||||
result = newGuildMember(sendRequest(endpoint(fmt("/guilds/{guild.id}/members/{memberID}")),
|
result = newGuildMember(sendRequest(endpoint(fmt("/guilds/{guild.id}/members/{memberID}")),
|
||||||
|
@ -576,7 +576,7 @@ proc getGuildBans*(guild: Guild): seq[GuildBan] =
|
||||||
user: newUser(json["user"])
|
user: newUser(json["user"])
|
||||||
))
|
))
|
||||||
|
|
||||||
proc getGuildBan*(guild: Guild, userID: snowflake): GuildBan =
|
proc getGuildBan*(guild: Guild, userID: Snowflake): GuildBan =
|
||||||
## Returns a ban object for the given user or nil if the ban cannot be found.
|
## Returns a ban object for the given user or nil if the ban cannot be found.
|
||||||
## Requires the BAN_MEMBERS permission.
|
## Requires the BAN_MEMBERS permission.
|
||||||
let response = sendRequest(endpoint(fmt("/guilds/{guild.id}/bans{userID}")), HttpGet,
|
let response = sendRequest(endpoint(fmt("/guilds/{guild.id}/bans{userID}")), HttpGet,
|
||||||
|
@ -590,22 +590,22 @@ proc getGuildBan*(guild: Guild, userID: snowflake): GuildBan =
|
||||||
else:
|
else:
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
proc banGuildMember*(guild: Guild, userID: snowflake, reason: Option[string] = none(string), deleteMessageDays: Option[int] = none(int)) {.async.} =
|
proc banGuildMember*(guild: Guild, userID: Snowflake, reason: Option[string] = none(string), deleteMessageDays: Option[int] = none(int)) {.async.} =
|
||||||
## Create a guild ban, and optionally delete previous messages sent by the
|
## Create a guild ban, and optionally delete previous messages sent by the
|
||||||
## banned user. Requires the BAN_MEMBERS permission.
|
## banned user. Requires the BAN_MEMBERS permission.
|
||||||
|
|
||||||
var jsonBody: JsonNode
|
var jsonBody: JsonNode
|
||||||
|
|
||||||
if (reason.isSome):
|
if reason.isSome:
|
||||||
jsonBody.add("reason", %reason.get())
|
jsonBody.add("reason", %reason.get())
|
||||||
if (deleteMessageDays.isSome):
|
if deleteMessageDays.isSome:
|
||||||
jsonBody.add("deleteMessageDays", %deleteMessageDays.get())
|
jsonBody.add("deleteMessageDays", %deleteMessageDays.get())
|
||||||
|
|
||||||
discard sendRequest(endpoint(fmt("/guilds/{guild.id}/bans/{userID}")), HttpPut,
|
discard sendRequest(endpoint(fmt("/guilds/{guild.id}/bans/{userID}")), HttpPut,
|
||||||
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
guild.id, RateLimitBucketType.guild, jsonBody)
|
guild.id, RateLimitBucketType.guild, jsonBody)
|
||||||
|
|
||||||
proc unbanGuildMember*(guild: Guild, userID: snowflake) {.async.} =
|
proc unbanGuildMember*(guild: Guild, userID: Snowflake) {.async.} =
|
||||||
## Remove the ban for a user. Requires the BAN_MEMBERS permissions.
|
## Remove the ban for a user. Requires the BAN_MEMBERS permissions.
|
||||||
discard sendRequest(endpoint(fmt("/guilds/{guild.id}/bans/{userID}")), HttpDelete,
|
discard sendRequest(endpoint(fmt("/guilds/{guild.id}/bans/{userID}")), HttpDelete,
|
||||||
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
@ -634,19 +634,19 @@ proc createGuildRole*(guild: Guild, name: Option[string] = none(string), permiss
|
||||||
|
|
||||||
var jsonBody: JsonNode
|
var jsonBody: JsonNode
|
||||||
|
|
||||||
if (name.isSome):
|
if name.isSome:
|
||||||
jsonBody.add("name", %name)
|
jsonBody.add("name", %name)
|
||||||
|
|
||||||
if (permissions.isSome):
|
if permissions.isSome:
|
||||||
jsonBody.add("permissions", %permissions.get().allowPerms)
|
jsonBody.add("permissions", %permissions.get().allowPerms)
|
||||||
|
|
||||||
if (color.isSome):
|
if color.isSome:
|
||||||
jsonBody.add("color", %color)
|
jsonBody.add("color", %color)
|
||||||
|
|
||||||
if (hoist.isSome):
|
if hoist.isSome:
|
||||||
jsonBody.add("hoist", %hoist)
|
jsonBody.add("hoist", %hoist)
|
||||||
|
|
||||||
if (mentionable.isSome):
|
if mentionable.isSome:
|
||||||
jsonBody.add("mentionable", %mentionable)
|
jsonBody.add("mentionable", %mentionable)
|
||||||
|
|
||||||
return newRole(sendRequest(endpoint(fmt("/guilds/{guild.id}/roles")), HttpPost,
|
return newRole(sendRequest(endpoint(fmt("/guilds/{guild.id}/roles")), HttpPost,
|
||||||
|
@ -665,7 +665,7 @@ proc modifyGuildRolePositions*(guild: var Guild, roles: seq[Role]) {.async.} =
|
||||||
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
guild.id, RateLimitBucketType.guild, jsonBody)
|
guild.id, RateLimitBucketType.guild, jsonBody)
|
||||||
|
|
||||||
proc getGuildPruneCount*(guild: Guild, days: int = 7, includedRoles: seq[snowflake] = @[]): int =
|
proc getGuildPruneCount*(guild: Guild, days: int = 7, includedRoles: seq[Snowflake]): int =
|
||||||
## Returns the number of members that would be removed in a prune operation.
|
## Returns the number of members that would be removed in a prune operation.
|
||||||
## Requires the `KICK_MEMBERS` permission.
|
## Requires the `KICK_MEMBERS` permission.
|
||||||
##
|
##
|
||||||
|
@ -687,7 +687,7 @@ proc getGuildPruneCount*(guild: Guild, days: int = 7, includedRoles: seq[snowfla
|
||||||
let jsonBody = sendRequest(url, HttpGet, defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
let jsonBody = sendRequest(url, HttpGet, defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
return jsonBody["pruned"].getInt()
|
return jsonBody["pruned"].getInt()
|
||||||
|
|
||||||
proc beginGuildPrune*(guild: Guild, days: int = 7, computePruneCount: bool = false, includedRoles: seq[snowflake] = @[]): Future[Option[int]] {.async.} =
|
proc beginGuildPrune*(guild: Guild, days: int = 7, computePruneCount: bool = false, includedRoles: seq[Snowflake]): Future[Option[int]] {.async.} =
|
||||||
## Returns the number of members that would be removed in a prune operation.
|
## Returns the number of members that would be removed in a prune operation.
|
||||||
## Requires the `KICK_MEMBERS` permission.
|
## Requires the `KICK_MEMBERS` permission.
|
||||||
##
|
##
|
||||||
|
@ -792,15 +792,15 @@ proc modifyGuildIntegration*(guild: Guild, integration: var Integration,
|
||||||
## discard integration.modifyGuildIntegration(enable_emoticons = true)
|
## discard integration.modifyGuildIntegration(enable_emoticons = true)
|
||||||
var modifyPayload = %*{}
|
var modifyPayload = %*{}
|
||||||
|
|
||||||
if (expireBehavior.isSome):
|
if expireBehavior.isSome:
|
||||||
modifyPayload.add("expire_behavior", %expireBehavior.get())
|
modifyPayload.add("expire_behavior", %expireBehavior.get())
|
||||||
integration.expireBehavior = (expireBehavior.get())
|
integration.expireBehavior = (expireBehavior.get())
|
||||||
|
|
||||||
if (expireGracePeriod.isSome):
|
if expireGracePeriod.isSome:
|
||||||
modifyPayload.add("expire_grace_period", %expireGracePeriod.get())
|
modifyPayload.add("expire_grace_period", %expireGracePeriod.get())
|
||||||
integration.expireGracePeriod = expireGracePeriod.get()
|
integration.expireGracePeriod = expireGracePeriod.get()
|
||||||
|
|
||||||
if (enableEmoticons.isSome):
|
if enableEmoticons.isSome:
|
||||||
modifyPayload.add("enable_emoticons", %enableEmoticons.get())
|
modifyPayload.add("enable_emoticons", %enableEmoticons.get())
|
||||||
integration.enableEmoticons = enableEmoticons.get()
|
integration.enableEmoticons = enableEmoticons.get()
|
||||||
|
|
||||||
|
@ -827,7 +827,7 @@ proc getGuildWidget*(guild: Guild): GuildWidget =
|
||||||
return GuildWidget(enabled: jsonBody["enabled"].getBool(),
|
return GuildWidget(enabled: jsonBody["enabled"].getBool(),
|
||||||
channelID: getIDFromJson(jsonBody{"channel_id"}.getStr()))
|
channelID: getIDFromJson(jsonBody{"channel_id"}.getStr()))
|
||||||
|
|
||||||
proc modifyGuildWidget*(guild: Guild, widget: var GuildWidget, enabled: bool, channelID: snowflake) {.async.} =
|
proc modifyGuildWidget*(guild: Guild, widget: var GuildWidget, enabled: bool, channelID: Snowflake) {.async.} =
|
||||||
## Modify a guild widget object for the guild. Requires the `MANAGE_GUILD` permission.
|
## Modify a guild widget object for the guild. Requires the `MANAGE_GUILD` permission.
|
||||||
widget.enabled = enabled
|
widget.enabled = enabled
|
||||||
widget.channelID = channelID
|
widget.channelID = channelID
|
||||||
|
@ -863,16 +863,16 @@ proc getGuildWidgetImage*(guild: Guild, style: GuildWidgetStyle): string =
|
||||||
## and a "JOIN MY SERVER" button at the bottom. [Example](https://discord.com/api/guilds/81384788765712384/widget.png?style=banner4)
|
## and a "JOIN MY SERVER" button at the bottom. [Example](https://discord.com/api/guilds/81384788765712384/widget.png?style=banner4)
|
||||||
result = fmt("guilds/{guild.id}/widget.png")
|
result = fmt("guilds/{guild.id}/widget.png")
|
||||||
|
|
||||||
case (style)
|
case style
|
||||||
of (GuildWidgetStyle.guildWidgetStyleShield):
|
of GuildWidgetStyle.guildWidgetStyleShield:
|
||||||
result &= "?style=shield"
|
result &= "?style=shield"
|
||||||
of (GuildWidgetStyle.guildWidgetStyleBanner1):
|
of GuildWidgetStyle.guildWidgetStyleBanner1:
|
||||||
result &= "?style=banner1"
|
result &= "?style=banner1"
|
||||||
of (GuildWidgetStyle.guildWidgetStyleBanner2):
|
of GuildWidgetStyle.guildWidgetStyleBanner2:
|
||||||
result &= "?style=banner2"
|
result &= "?style=banner2"
|
||||||
of (GuildWidgetStyle.guildWidgetStyleBanner3):
|
of GuildWidgetStyle.guildWidgetStyleBanner3:
|
||||||
result &= "?style=banner3"
|
result &= "?style=banner3"
|
||||||
of (GuildWidgetStyle.guildWidgetStyleBanner4):
|
of GuildWidgetStyle.guildWidgetStyleBanner4:
|
||||||
result &= "?style=banner4"
|
result &= "?style=banner4"
|
||||||
|
|
||||||
proc requestEmojis*(guild: Guild): seq[Emoji] =
|
proc requestEmojis*(guild: Guild): seq[Emoji] =
|
||||||
|
@ -887,7 +887,7 @@ proc requestEmojis*(guild: Guild): seq[Emoji] =
|
||||||
result.add(newEmoji(emoji, guild.id))
|
result.add(newEmoji(emoji, guild.id))
|
||||||
guild.emojis = result
|
guild.emojis = result
|
||||||
|
|
||||||
proc getEmoji*(guild: Guild, emojiID: snowflake): Emoji =
|
proc getEmoji*(guild: Guild, emojiID: Snowflake): Emoji =
|
||||||
## Returns a guild's emoji with `emojiID`.
|
## Returns a guild's emoji with `emojiID`.
|
||||||
## If the emoji isn't found in `guild.emojis` then it will request on
|
## If the emoji isn't found in `guild.emojis` then it will request on
|
||||||
## from the Discord REST API.
|
## from the Discord REST API.
|
||||||
|
@ -898,7 +898,7 @@ proc getEmoji*(guild: Guild, emojiID: snowflake): Emoji =
|
||||||
return newEmoji(sendRequest(endpoint("/guilds/{guild.id}/emojis/{emojiID}"), HttpGet,
|
return newEmoji(sendRequest(endpoint("/guilds/{guild.id}/emojis/{emojiID}"), HttpGet,
|
||||||
defaultHeaders(), guild.id, RateLimitBucketType.guild), guild.id)
|
defaultHeaders(), guild.id, RateLimitBucketType.guild), guild.id)
|
||||||
|
|
||||||
proc createEmoji*(guild: Guild, name: string, image: Image, roles: seq[snowflake] = @[]): Future[Emoji] {.async.} =
|
proc createEmoji*(guild: Guild, name: string, image: Image, roles: seq[Snowflake]): Future[Emoji] {.async.} =
|
||||||
## Create a new emoji for the guild. Requires the `MANAGE_EMOJIS` permission.
|
## Create a new emoji for the guild. Requires the `MANAGE_EMOJIS` permission.
|
||||||
var jsonBody = %* {
|
var jsonBody = %* {
|
||||||
"name": name,
|
"name": name,
|
||||||
|
@ -914,5 +914,5 @@ proc createEmoji*(guild: Guild, name: string, image: Image, roles: seq[snowflake
|
||||||
proc getGuildMemberRoles*(guild: Guild, member: GuildMember): seq[Role] =
|
proc getGuildMemberRoles*(guild: Guild, member: GuildMember): seq[Role] =
|
||||||
## Get the role objects for a member's roles.
|
## Get the role objects for a member's roles.
|
||||||
for role in guild.roles:
|
for role in guild.roles:
|
||||||
if (member.roles.contains(role.id)):
|
if member.roles.contains(role.id):
|
||||||
result.add(role)
|
result.add(role)
|
||||||
|
|
|
@ -9,7 +9,7 @@ proc newImage*(filepath: string): Image =
|
||||||
## Reads from a file that exists at `filepath`. It reads the image data,
|
## Reads from a file that exists at `filepath`. It reads the image data,
|
||||||
## and image extension for later use.
|
## and image extension for later use.
|
||||||
var imageStream = newFileStream(filepath, fmRead)
|
var imageStream = newFileStream(filepath, fmRead)
|
||||||
if (not isNil(imageStream)):
|
if not isNil(imageStream):
|
||||||
let data = imageStream.readALL()
|
let data = imageStream.readALL()
|
||||||
|
|
||||||
# Get the file's extension and remove the `.` from the start of it
|
# Get the file's extension and remove the `.` from the start of it
|
||||||
|
@ -24,4 +24,4 @@ proc newImage*(filepath: string): Image =
|
||||||
raise newException(IOError, "Failed to open file: " & filepath)
|
raise newException(IOError, "Failed to open file: " & filepath)
|
||||||
|
|
||||||
proc imageToDataURI*(image: Image): string =
|
proc imageToDataURI*(image: Image): string =
|
||||||
return fmt("data:image/{image.extension};base64,{image.base64Encoded}")
|
return fmt("data:image/{image.extension};base64,{image.base64Encoded}")
|
||||||
|
|
|
@ -25,7 +25,7 @@ proc newLog*(flags: int, filePath: string = ""): Log =
|
||||||
var log = Log(flags: flags)
|
var log = Log(flags: flags)
|
||||||
if filePath.len > 0:
|
if filePath.len > 0:
|
||||||
log.logFile = newFileStream(filePath, fmWrite)
|
log.logFile = newFileStream(filePath, fmWrite)
|
||||||
if (isNil(log.logFile)):
|
if isNil(log.logFile):
|
||||||
raise newException(IOError, "Failed to open log file: " & filePath)
|
raise newException(IOError, "Failed to open log file: " & filePath)
|
||||||
|
|
||||||
return log
|
return log
|
||||||
|
@ -38,18 +38,18 @@ proc canLog(log: Log, sev: LogSeverity): bool =
|
||||||
elif (log.flags and int(LoggerFlags.loggerFlagDebugSeverity)) == int(LoggerFlags.loggerFlagDebugSeverity):
|
elif (log.flags and int(LoggerFlags.loggerFlagDebugSeverity)) == int(LoggerFlags.loggerFlagDebugSeverity):
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case (sev)
|
case sev
|
||||||
of LogSeverity.logSevInfo:
|
of LogSeverity.logSevInfo:
|
||||||
return (log.flags and int(LoggerFlags.loggerFlagInfoSeverity)) == int(LoggerFlags.loggerFlagInfoSeverity);
|
return (log.flags and int(LoggerFlags.loggerFlagInfoSeverity)) == int(LoggerFlags.loggerFlagInfoSeverity)
|
||||||
of LogSeverity.logSevWarn:
|
of LogSeverity.logSevWarn:
|
||||||
return (log.flags and int(LoggerFlags.loggerFlagWarnSeverity)) == int(LoggerFlags.loggerFlagWarnSeverity);
|
return (log.flags and int(LoggerFlags.loggerFlagWarnSeverity)) == int(LoggerFlags.loggerFlagWarnSeverity)
|
||||||
of LogSeverity.logSevError:
|
of LogSeverity.logSevError:
|
||||||
return (log.flags and int(LoggerFlags.loggerFlagErrorSeverity)) == int(LoggerFlags.loggerFlagErrorSeverity);
|
return (log.flags and int(LoggerFlags.loggerFlagErrorSeverity)) == int(LoggerFlags.loggerFlagErrorSeverity)
|
||||||
else:
|
else:
|
||||||
return false;
|
return false
|
||||||
|
|
||||||
proc severityToString(sev: LogSeverity): string =
|
proc severityToString(sev: LogSeverity): string =
|
||||||
case (sev)
|
case sev
|
||||||
of LogSeverity.logSevInfo:
|
of LogSeverity.logSevInfo:
|
||||||
return "INFO"
|
return "INFO"
|
||||||
of LogSeverity.logSevWarn:
|
of LogSeverity.logSevWarn:
|
||||||
|
@ -61,7 +61,7 @@ proc severityToString(sev: LogSeverity): string =
|
||||||
|
|
||||||
#TODO: Remove colors from file.
|
#TODO: Remove colors from file.
|
||||||
template autoLog(log: Log, sev: LogSeverity, args: varargs[untyped]) =
|
template autoLog(log: Log, sev: LogSeverity, args: varargs[untyped]) =
|
||||||
if (log.canLog(sev)):
|
if log.canLog(sev):
|
||||||
let timeFormated = getTime().format("[HH:mm:ss]")
|
let timeFormated = getTime().format("[HH:mm:ss]")
|
||||||
let sevStr = "[" & severityToString(sev) & "]"
|
let sevStr = "[" & severityToString(sev) & "]"
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ template autoLog(log: Log, sev: LogSeverity, args: varargs[untyped]) =
|
||||||
|
|
||||||
terminal.styledEcho(logHeader, args)
|
terminal.styledEcho(logHeader, args)
|
||||||
|
|
||||||
if (log.logFile != nil):
|
if log.logFile != nil:
|
||||||
log.logFile.writeLine(logHeader, args)
|
log.logFile.writeLine(logHeader, args)
|
||||||
|
|
||||||
template debug*(log: Log, args: varargs[untyped]) =
|
template debug*(log: Log, args: varargs[untyped]) =
|
||||||
|
@ -90,6 +90,6 @@ template info*(log: Log, args: varargs[untyped]) =
|
||||||
|
|
||||||
proc closeLog*(log: Log) =
|
proc closeLog*(log: Log) =
|
||||||
## Close log file if it was ever open.
|
## Close log file if it was ever open.
|
||||||
if (log.logFile != nil):
|
if log.logFile != nil:
|
||||||
log.info(fgYellow, "Closing log...")
|
log.info(fgYellow, "Closing log...")
|
||||||
log.logFile.close()
|
log.logFile.close()
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import discordobject, user, json, role, options, asyncdispatch, nimcordutils, httpcore, strformat, strutils, presence
|
import discordobject, user, json, options, asyncdispatch, nimcordutils, httpcore, strformat, strutils, presence
|
||||||
|
|
||||||
type GuildMember* = ref object of DiscordObject
|
type GuildMember* = ref object of DiscordObject
|
||||||
## This type is a guild member.
|
## This type is a guild member.
|
||||||
user*: User ## The user this guild member represents.
|
user*: User ## The user this guild member represents.
|
||||||
nick*: string ## This users guild nickname.
|
nick*: string ## This users guild nickname.
|
||||||
roles*: seq[snowflake] ## Array of roles.
|
roles*: seq[Snowflake] ## Array of roles.
|
||||||
joinedAt*: string ## When the user joined the guild.
|
joinedAt*: string ## When the user joined the guild.
|
||||||
premiumSince*: string ## When the user started boosting the guild.
|
premiumSince*: string ## When the user started boosting the guild.
|
||||||
deaf*: bool ## Whether the user is deafened in voice channels.
|
deaf*: bool ## Whether the user is deafened in voice channels.
|
||||||
mute*: bool ## Whether the user is muted in voice channels.
|
mute*: bool ## Whether the user is muted in voice channels.
|
||||||
guildID*: snowflake ## The guild this member is in.
|
guildID*: Snowflake ## The guild this member is in.
|
||||||
presence*: Presence ## The member's presence.
|
presence*: Presence ## The member's presence.
|
||||||
|
|
||||||
proc newGuildMember*(json: JsonNode, guild: snowflake): GuildMember {.inline.} =
|
proc newGuildMember*(json: JsonNode, guild: Snowflake): GuildMember {.inline.} =
|
||||||
## Construct a GuildMember using json.
|
## Construct a GuildMember using json.
|
||||||
result = GuildMember(
|
result = GuildMember(
|
||||||
nick: json{"nick"}.getStr(),
|
nick: json{"nick"}.getStr(),
|
||||||
|
@ -24,7 +24,7 @@ proc newGuildMember*(json: JsonNode, guild: snowflake): GuildMember {.inline.} =
|
||||||
guildID: guild
|
guildID: guild
|
||||||
)
|
)
|
||||||
|
|
||||||
if (json.contains("user")):
|
if json.contains("user"):
|
||||||
result.user = newUser(json["user"])
|
result.user = newUser(json["user"])
|
||||||
|
|
||||||
# Add roles
|
# Add roles
|
||||||
|
@ -33,46 +33,46 @@ proc newGuildMember*(json: JsonNode, guild: snowflake): GuildMember {.inline.} =
|
||||||
|
|
||||||
type GuildMemberModify* = ref object
|
type GuildMemberModify* = ref object
|
||||||
nick: Option[string]
|
nick: Option[string]
|
||||||
roles: Option[seq[snowflake]]
|
roles: Option[seq[Snowflake]]
|
||||||
mute: Option[bool]
|
mute: Option[bool]
|
||||||
deaf: Option[bool]
|
deaf: Option[bool]
|
||||||
channelID: Option[snowflake]
|
channelID: Option[Snowflake]
|
||||||
|
|
||||||
proc modifyGuildMember*(member: GuildMember, memberID: snowflake, modify: GuildMemberModify) {.async.} =
|
proc modifyGuildMember*(member: GuildMember, memberID: Snowflake, modify: GuildMemberModify) {.async.} =
|
||||||
## Modify attributes of a guild member. If the `channel_id` is set to null,
|
## Modify attributes of a guild member. If the `channel_id` is set to null,
|
||||||
## this will force the target user to be disconnected from voice.
|
## this will force the target user to be disconnected from voice.
|
||||||
##
|
##
|
||||||
## The member's new attributes will be reflected to `guild.members`.
|
## The member's new attributes will be reflected to `guild.members`.
|
||||||
var modifyPayload = %*{}
|
var modifyPayload = %*{}
|
||||||
|
|
||||||
if (modify.nick.isSome):
|
if modify.nick.isSome:
|
||||||
modifyPayload.add("nick", %modify.nick.get())
|
modifyPayload.add("nick", %modify.nick.get())
|
||||||
|
|
||||||
if (modify.roles.isSome):
|
if modify.roles.isSome:
|
||||||
# Convert the roles array to a string representation and remove the `@`
|
# Convert the roles array to a string representation and remove the `@`
|
||||||
# that is at the front of a conversion like this.
|
# that is at the front of a conversion like this.
|
||||||
var rolesStr = ($modify.roles.get()).substr(1)
|
var rolesStr = ($modify.roles.get()).substr(1)
|
||||||
modifyPayload.add(parseJson(rolesStr))
|
modifyPayload.add(parseJson(rolesStr))
|
||||||
|
|
||||||
if (modify.mute.isSome):
|
if modify.mute.isSome:
|
||||||
modifyPayload.add("mute", %modify.mute.get())
|
modifyPayload.add("mute", %modify.mute.get())
|
||||||
|
|
||||||
if (modify.deaf.isSome):
|
if modify.deaf.isSome:
|
||||||
modifyPayload.add("deaf", %modify.deaf.get())
|
modifyPayload.add("deaf", %modify.deaf.get())
|
||||||
|
|
||||||
if (modify.channelID.isSome):
|
if modify.channelID.isSome:
|
||||||
modifyPayload.add("channel_id", %modify.channelID.get())
|
modifyPayload.add("channel_id", %modify.channelID.get())
|
||||||
|
|
||||||
discard sendRequest(endpoint(fmt("/guilds/{member.guildID}/members/{member.id}")), HttpPatch,
|
discard sendRequest(endpoint(fmt("/guilds/{member.guildID}/members/{member.id}")), HttpPatch,
|
||||||
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
member.guildID, RateLimitBucketType.guild, modifyPayload)
|
member.guildID, RateLimitBucketType.guild, modifyPayload)
|
||||||
|
|
||||||
proc addGuildMemberRole*(member: GuildMember, roleID: snowflake) {.async.} =
|
proc addGuildMemberRole*(member: GuildMember, roleID: Snowflake) {.async.} =
|
||||||
## Adds a role to a guild member. Requires the `MANAGE_ROLES` permission.
|
## Adds a role to a guild member. Requires the `MANAGE_ROLES` permission.
|
||||||
discard sendRequest(endpoint(fmt("/guilds/{member.guildID}/members/{member.id}/roles/{roleID}")),
|
discard sendRequest(endpoint(fmt("/guilds/{member.guildID}/members/{member.id}/roles/{roleID}")),
|
||||||
HttpPut, defaultHeaders(), member.guildID, RateLimitBucketType.guild)
|
HttpPut, defaultHeaders(), member.guildID, RateLimitBucketType.guild)
|
||||||
|
|
||||||
proc removeGuildMemberRole*(member: GuildMember, roleID: snowflake) {.async.} =
|
proc removeGuildMemberRole*(member: GuildMember, roleID: Snowflake) {.async.} =
|
||||||
## Remove's a role to a guild member. Requires the `MANAGE_ROLES` permission.
|
## Remove's a role to a guild member. Requires the `MANAGE_ROLES` permission.
|
||||||
discard sendRequest(endpoint(fmt("/guilds/{member.guildID}/members/{member.id}/roles/{roleID}")),
|
discard sendRequest(endpoint(fmt("/guilds/{member.guildID}/members/{member.id}/roles/{roleID}")),
|
||||||
HttpDelete, defaultHeaders(), member.guildID, RateLimitBucketType.guild)
|
HttpDelete, defaultHeaders(), member.guildID, RateLimitBucketType.guild)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import json, discordobject, nimcordutils, user, member, httpcore, asyncdispatch, emoji, options, embed, role, emoji
|
import json, discordobject, nimcordutils, user, member, httpcore, asyncdispatch, emoji, options, embed, emoji
|
||||||
|
|
||||||
type
|
type
|
||||||
MessageType* = enum
|
MessageType* = enum
|
||||||
|
@ -35,9 +35,9 @@ type
|
||||||
name*: string
|
name*: string
|
||||||
|
|
||||||
MessageReference* = ref object
|
MessageReference* = ref object
|
||||||
messageID*: snowflake
|
messageID*: Snowflake
|
||||||
channelID*: snowflake
|
channelID*: Snowflake
|
||||||
guildID*: snowflake
|
guildID*: Snowflake
|
||||||
|
|
||||||
MessageFlags* = enum
|
MessageFlags* = enum
|
||||||
msgFlagCrossposted = 0,
|
msgFlagCrossposted = 0,
|
||||||
|
@ -53,8 +53,8 @@ type
|
||||||
|
|
||||||
ChannelMention* = ref object
|
ChannelMention* = ref object
|
||||||
## Represents a channel mention inside of a message.
|
## Represents a channel mention inside of a message.
|
||||||
channelID*: snowflake
|
channelID*: Snowflake
|
||||||
guildID*: snowflake
|
guildID*: Snowflake
|
||||||
channelType*: int
|
channelType*: int
|
||||||
name*: string
|
name*: string
|
||||||
|
|
||||||
|
@ -68,8 +68,8 @@ type
|
||||||
width*: int
|
width*: int
|
||||||
|
|
||||||
Message* = ref object of DiscordObject
|
Message* = ref object of DiscordObject
|
||||||
channelID*: snowflake
|
channelID*: Snowflake
|
||||||
guildID*: snowflake
|
guildID*: Snowflake
|
||||||
author*: User
|
author*: User
|
||||||
member*: GuildMember
|
member*: GuildMember
|
||||||
content*: string
|
content*: string
|
||||||
|
@ -78,13 +78,13 @@ type
|
||||||
tts*: bool
|
tts*: bool
|
||||||
mentionEveryone*: bool
|
mentionEveryone*: bool
|
||||||
mentions*: seq[User]
|
mentions*: seq[User]
|
||||||
mentionRoles*: seq[snowflake]
|
mentionRoles*: seq[Snowflake]
|
||||||
mentionChannels*: seq[ChannelMention]
|
mentionChannels*: seq[ChannelMention]
|
||||||
attachments*: seq[MessageAttachment]
|
attachments*: seq[MessageAttachment]
|
||||||
embeds*: seq[Embed]
|
embeds*: seq[Embed]
|
||||||
reactions*: seq[Reaction]
|
reactions*: seq[Reaction]
|
||||||
pinned*: bool
|
pinned*: bool
|
||||||
webhookID*: snowflake
|
webhookID*: Snowflake
|
||||||
`type`*: MessageType
|
`type`*: MessageType
|
||||||
activity*: MessageActivity
|
activity*: MessageActivity
|
||||||
application*: MessageApplication
|
application*: MessageApplication
|
||||||
|
@ -107,19 +107,19 @@ proc newMessage*(messageJson: JsonNode): Message =
|
||||||
flags: messageJson{"flags"}.getInt()
|
flags: messageJson{"flags"}.getInt()
|
||||||
)
|
)
|
||||||
|
|
||||||
if (messageJson.contains("author")):
|
if messageJson.contains("author"):
|
||||||
msg.author = newUser(messageJson["author"])
|
msg.author = newUser(messageJson["author"])
|
||||||
if (messageJson.contains("member")):
|
if messageJson.contains("member"):
|
||||||
msg.member = newGuildMember(messageJson["member"], msg.guildID)
|
msg.member = newGuildMember(messageJson["member"], msg.guildID)
|
||||||
|
|
||||||
if (messageJson.contains("mentions")):
|
if messageJson.contains("mentions"):
|
||||||
for userJson in messageJson["mentions"]:
|
for userJson in messageJson["mentions"]:
|
||||||
msg.mentions.add(newUser(userJson))
|
msg.mentions.add(newUser(userJson))
|
||||||
|
|
||||||
for role in messageJson["mention_roles"]:
|
for role in messageJson["mention_roles"]:
|
||||||
msg.mentionRoles.add(getIDFromJson(role.getStr()))
|
msg.mentionRoles.add(getIDFromJson(role.getStr()))
|
||||||
|
|
||||||
if (messageJson.contains("mention_channels")):
|
if messageJson.contains("mention_channels"):
|
||||||
for channel in messageJson["mention_channels"]:
|
for channel in messageJson["mention_channels"]:
|
||||||
msg.mentionChannels.add(ChannelMention(
|
msg.mentionChannels.add(ChannelMention(
|
||||||
channelID: getIDFromJson(channel["id"].getStr()),
|
channelID: getIDFromJson(channel["id"].getStr()),
|
||||||
|
@ -142,7 +142,7 @@ proc newMessage*(messageJson: JsonNode): Message =
|
||||||
for embed in messageJson["embeds"]:
|
for embed in messageJson["embeds"]:
|
||||||
msg.embeds.add(Embed(embedJson: embed))
|
msg.embeds.add(Embed(embedJson: embed))
|
||||||
|
|
||||||
if (messageJson.contains("reactions")):
|
if messageJson.contains("reactions"):
|
||||||
for reaction in messageJson["reactions"]:
|
for reaction in messageJson["reactions"]:
|
||||||
msg.reactions.add(Reaction(
|
msg.reactions.add(Reaction(
|
||||||
count: uint(reaction["count"].getInt()),
|
count: uint(reaction["count"].getInt()),
|
||||||
|
@ -150,10 +150,10 @@ proc newMessage*(messageJson: JsonNode): Message =
|
||||||
emoji: newEmoji(reaction["emoji"], msg.guildID)
|
emoji: newEmoji(reaction["emoji"], msg.guildID)
|
||||||
))
|
))
|
||||||
|
|
||||||
if (messageJson.contains("activity")):
|
if messageJson.contains("activity"):
|
||||||
msg.activity = MessageActivity(`type`: MessageActivityType(messageJson["activity"]["type"].getInt()),
|
msg.activity = MessageActivity(`type`: MessageActivityType(messageJson["activity"]["type"].getInt()),
|
||||||
partyID: messageJson["activity"]["party_id"].getStr())
|
partyID: messageJson["activity"]["party_id"].getStr())
|
||||||
if (messageJson.contains("application")):
|
if messageJson.contains("application"):
|
||||||
msg.application = MessageApplication(
|
msg.application = MessageApplication(
|
||||||
id: getIDFromJson(messageJson["application"]["id"].getStr()),
|
id: getIDFromJson(messageJson["application"]["id"].getStr()),
|
||||||
coverImage: messageJson["application"]{"cover_image"}.getStr(),
|
coverImage: messageJson["application"]{"cover_image"}.getStr(),
|
||||||
|
@ -161,7 +161,7 @@ proc newMessage*(messageJson: JsonNode): Message =
|
||||||
icon: messageJson["application"]{"icon"}.getStr(),
|
icon: messageJson["application"]{"icon"}.getStr(),
|
||||||
name: messageJson["application"]["name"].getStr()
|
name: messageJson["application"]["name"].getStr()
|
||||||
)
|
)
|
||||||
if (messageJson.contains("message_reference")):
|
if messageJson.contains("message_reference"):
|
||||||
msg.messageReference = MessageReference(
|
msg.messageReference = MessageReference(
|
||||||
messageID: getIDFromJson(messageJson["message_reference"]{"message_id"}.getStr()),
|
messageID: getIDFromJson(messageJson["message_reference"]{"message_id"}.getStr()),
|
||||||
channelID: getIDFromJson(messageJson["message_reference"]["channel_id"].getStr()),
|
channelID: getIDFromJson(messageJson["message_reference"]["channel_id"].getStr()),
|
||||||
|
@ -212,8 +212,8 @@ type ReactantsGetRequest* = object
|
||||||
## Use this type to get a messages's reactants by setting
|
## Use this type to get a messages's reactants by setting
|
||||||
## some of the fields.
|
## some of the fields.
|
||||||
## You can only set one of `before` and `after`.
|
## You can only set one of `before` and `after`.
|
||||||
before*: Option[snowflake]
|
before*: Option[Snowflake]
|
||||||
after*: Option[snowflake]
|
after*: Option[Snowflake]
|
||||||
limit*: Option[int]
|
limit*: Option[int]
|
||||||
|
|
||||||
proc getReactants*(message: Message, emoji: Emoji, request: ReactantsGetRequest): seq[User] =
|
proc getReactants*(message: Message, emoji: Emoji, request: ReactantsGetRequest): seq[User] =
|
||||||
|
@ -224,17 +224,17 @@ proc getReactants*(message: Message, emoji: Emoji, request: ReactantsGetRequest)
|
||||||
|
|
||||||
# Raise some exceptions to make sure the user doesn't
|
# Raise some exceptions to make sure the user doesn't
|
||||||
# try to set more than one of these fields
|
# try to set more than one of these fields
|
||||||
if (request.before.isSome):
|
if request.before.isSome:
|
||||||
url = url & "before=" & $request.before.get()
|
url = url & "before=" & $request.before.get()
|
||||||
|
|
||||||
if (request.after.isSome):
|
if request.after.isSome:
|
||||||
if (request.before.isSome):
|
if request.before.isSome:
|
||||||
raise newException(Defect, "You cannot get before and after a message! Choose one...")
|
raise newException(Defect, "You cannot get before and after a message! Choose one...")
|
||||||
url = url & "after=" & $request.after.get()
|
url = url & "after=" & $request.after.get()
|
||||||
|
|
||||||
if (request.limit.isSome):
|
if request.limit.isSome:
|
||||||
# Add the `&` for the url if something else is set.
|
# Add the `&` for the url if something else is set.
|
||||||
if (request.before.isSome or request.after.isSome):
|
if request.before.isSome or request.after.isSome:
|
||||||
url = url & "&"
|
url = url & "&"
|
||||||
|
|
||||||
url = url & "limit=" & $request.limit.get()
|
url = url & "limit=" & $request.limit.get()
|
||||||
|
@ -276,7 +276,7 @@ proc editMessage*(message: Message, content: string, embed: Embed = nil): Future
|
||||||
## Edit a previously sent message.
|
## Edit a previously sent message.
|
||||||
var jsonBody = %*{"content": content}
|
var jsonBody = %*{"content": content}
|
||||||
|
|
||||||
if (not embed.isNil()):
|
if embed != nil:
|
||||||
jsonBody.add("embed", embed.embedJson)
|
jsonBody.add("embed", embed.embedJson)
|
||||||
|
|
||||||
return newMessage(sendRequest(endpoint("/channels/" & $message.channelID & "/messages/" & $message.id),
|
return newMessage(sendRequest(endpoint("/channels/" & $message.channelID & "/messages/" & $message.id),
|
||||||
|
@ -291,4 +291,4 @@ proc deleteMessage*(message: Message) {.async.} =
|
||||||
## See also:
|
## See also:
|
||||||
## * `deleteMessage<#deleteMessage,Message>`_
|
## * `deleteMessage<#deleteMessage,Message>`_
|
||||||
discard sendRequest(endpoint("/channels/" & $message.channelID & "/messages/" & $message.id),
|
discard sendRequest(endpoint("/channels/" & $message.channelID & "/messages/" & $message.id),
|
||||||
HttpDelete, defaultHeaders(), message.channelID, RateLimitBucketType.channel)
|
HttpDelete, defaultHeaders(), message.channelID, RateLimitBucketType.channel)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import parseutils, json, httpClient, strformat, tables, times, asyncdispatch
|
import parseutils, json, httpClient, strformat, tables, times, asyncdispatch
|
||||||
from discordobject import snowflake
|
from discordobject import Snowflake
|
||||||
|
|
||||||
proc getIDFromJson*(str: string): uint64 =
|
proc getIDFromJson*(str: string): uint64 =
|
||||||
var num: uint64
|
var num: uint64
|
||||||
|
@ -17,10 +17,11 @@ proc endpoint*(url: string): string =
|
||||||
var globalToken*: string
|
var globalToken*: string
|
||||||
|
|
||||||
proc defaultHeaders*(added: HttpHeaders = newHttpHeaders()): HttpHeaders =
|
proc defaultHeaders*(added: HttpHeaders = newHttpHeaders()): HttpHeaders =
|
||||||
added.add("Authorization", fmt("Bot {globalToken}"))
|
# added.add("Authorization", fmt("Bot {globalToken}"))
|
||||||
|
added.add("Authorization", fmt("{globalToken}"))
|
||||||
added.add("User-Agent", "NimCord (https://github.com/SeanOMik/nimcord, v0.0.0)")
|
added.add("User-Agent", "NimCord (https://github.com/SeanOMik/nimcord, v0.0.0)")
|
||||||
added.add("X-RateLimit-Precision", "millisecond")
|
added.add("X-RateLimit-Precision", "millisecond")
|
||||||
return added;
|
return added
|
||||||
|
|
||||||
type
|
type
|
||||||
RateLimitBucketType* = enum
|
RateLimitBucketType* = enum
|
||||||
|
@ -37,16 +38,16 @@ proc newRateLimit(lmt: int = 500, remLmnt: int = 500, ratelmtReset: float = 0):
|
||||||
return RateLimit(limit: lmt, remainingLimit: remLmnt, ratelimitReset: ratelmtReset)
|
return RateLimit(limit: lmt, remainingLimit: remLmnt, ratelimitReset: ratelmtReset)
|
||||||
|
|
||||||
# Rate limit buckets
|
# Rate limit buckets
|
||||||
let channelRatelimitBucket = newTable[snowflake, RateLimit]()
|
let channelRatelimitBucket = newTable[Snowflake, RateLimit]()
|
||||||
let guildRatelimitBucket = newTable[snowflake, RateLimit]()
|
let guildRatelimitBucket = newTable[Snowflake, RateLimit]()
|
||||||
let webhookRatelimitBucket = newTable[snowflake, RateLimit]()
|
let webhookRatelimitBucket = newTable[Snowflake, RateLimit]()
|
||||||
var globalRateLimit: RateLimit = newRateLimit()
|
var globalRateLimit: RateLimit = newRateLimit()
|
||||||
|
|
||||||
proc handleRateLimits*(headers: HttpHeaders, objectID: snowflake, bucketType: RateLimitBucketType) =
|
proc handleRateLimits*(headers: HttpHeaders, objectID: Snowflake, bucketType: RateLimitBucketType) =
|
||||||
var obj: RateLimit
|
var obj: RateLimit
|
||||||
if (headers.hasKey("x-ratelimit-global")):
|
if headers.hasKey("x-ratelimit-global"):
|
||||||
obj = globalRateLimit
|
obj = globalRateLimit
|
||||||
elif (headers.hasKey("x-ratelimit-limit")):
|
elif headers.hasKey("x-ratelimit-limit"):
|
||||||
case bucketType:
|
case bucketType:
|
||||||
of RateLimitBucketType.channel:
|
of RateLimitBucketType.channel:
|
||||||
obj = channelRatelimitBucket[objectID]
|
obj = channelRatelimitBucket[objectID]
|
||||||
|
@ -68,33 +69,33 @@ proc handleRateLimits*(headers: HttpHeaders, objectID: snowflake, bucketType: Ra
|
||||||
discard parseFloat(headers["x-ratelimit-reset"], obj.ratelimitReset)
|
discard parseFloat(headers["x-ratelimit-reset"], obj.ratelimitReset)
|
||||||
|
|
||||||
|
|
||||||
proc handleResponse*(response: Response, objectID: snowflake, bucketType: RateLimitBucketType): JsonNode =
|
proc handleResponse*(response: Response, objectID: Snowflake, bucketType: RateLimitBucketType): JsonNode =
|
||||||
echo fmt("Received requested payload: {response.body}")
|
echo fmt("Received requested payload: {response.body}")
|
||||||
|
|
||||||
handleRateLimits(response.headers, objectID, bucketType)
|
handleRateLimits(response.headers, objectID, bucketType)
|
||||||
|
|
||||||
return parseJson(response.body())
|
return parseJson(response.body())
|
||||||
|
|
||||||
proc waitForRateLimits*(objectID: snowflake, bucketType: RateLimitBucketType) =
|
proc waitForRateLimits*(objectID: Snowflake, bucketType: RateLimitBucketType) =
|
||||||
var rlmt: RateLimit
|
var rlmt: RateLimit
|
||||||
if (globalRateLimit.remainingLimit == 0):
|
if globalRateLimit.remainingLimit == 0:
|
||||||
rlmt = globalRateLimit
|
rlmt = globalRateLimit
|
||||||
else:
|
else:
|
||||||
case bucketType:
|
case bucketType:
|
||||||
of RateLimitBucketType.channel:
|
of RateLimitBucketType.channel:
|
||||||
if (channelRatelimitBucket.hasKey(objectID)):
|
if channelRatelimitBucket.hasKey(objectID):
|
||||||
rlmt = channelRatelimitBucket[objectID]
|
rlmt = channelRatelimitBucket[objectID]
|
||||||
else:
|
else:
|
||||||
channelRatelimitBucket.add(objectID, newRateLimit())
|
channelRatelimitBucket.add(objectID, newRateLimit())
|
||||||
rlmt = channelRatelimitBucket[objectID]
|
rlmt = channelRatelimitBucket[objectID]
|
||||||
of RateLimitBucketType.guild:
|
of RateLimitBucketType.guild:
|
||||||
if (guildRatelimitBucket.hasKey(objectID)):
|
if guildRatelimitBucket.hasKey(objectID):
|
||||||
rlmt = guildRatelimitBucket[objectID]
|
rlmt = guildRatelimitBucket[objectID]
|
||||||
else:
|
else:
|
||||||
guildRatelimitBucket.add(objectID, newRateLimit())
|
guildRatelimitBucket.add(objectID, newRateLimit())
|
||||||
rlmt = guildRatelimitBucket[objectID]
|
rlmt = guildRatelimitBucket[objectID]
|
||||||
of RateLimitBucketType.webhook:
|
of RateLimitBucketType.webhook:
|
||||||
if (webhookRatelimitBucket.hasKey(objectID)):
|
if webhookRatelimitBucket.hasKey(objectID):
|
||||||
rlmt = webhookRatelimitBucket[objectID]
|
rlmt = webhookRatelimitBucket[objectID]
|
||||||
else:
|
else:
|
||||||
webhookRatelimitBucket.add(objectID, newRateLimit())
|
webhookRatelimitBucket.add(objectID, newRateLimit())
|
||||||
|
@ -102,21 +103,21 @@ proc waitForRateLimits*(objectID: snowflake, bucketType: RateLimitBucketType) =
|
||||||
of RateLimitBucketType.global:
|
of RateLimitBucketType.global:
|
||||||
rlmt = globalRateLimit
|
rlmt = globalRateLimit
|
||||||
|
|
||||||
if (rlmt != nil and rlmt.remainingLimit == 0):
|
if rlmt != nil and rlmt.remainingLimit == 0:
|
||||||
let millisecondTime: float = rlmt.ratelimitReset * 1000 - epochTime() * 1000
|
let millisecondTime: float = rlmt.ratelimitReset * 1000 - epochTime() * 1000
|
||||||
|
|
||||||
if (millisecondTime > 0):
|
if millisecondTime > 0:
|
||||||
echo fmt("Rate limit wait time: {millisecondTime} miliseconds")
|
echo fmt("Rate limit wait time: {millisecondTime} miliseconds")
|
||||||
waitFor sleepAsync(millisecondTime)
|
waitFor sleepAsync(millisecondTime)
|
||||||
|
|
||||||
proc sendRequest*(endpoint: string, httpMethod: HttpMethod, headers: HttpHeaders, objectID: snowflake = 0,
|
proc sendRequest*(endpoint: string, httpMethod: HttpMethod, headers: HttpHeaders, objectID: Snowflake = 0,
|
||||||
bucketType: RateLimitBucketType = global, jsonBody: JsonNode = nil): JsonNode =
|
bucketType: RateLimitBucketType = global, jsonBody: JsonNode = nil): JsonNode =
|
||||||
var client = newHttpClient()
|
var client = newHttpClient()
|
||||||
# Add headers
|
# Add headers
|
||||||
client.headers = headers
|
client.headers = headers
|
||||||
|
|
||||||
var strPayload: string
|
var strPayload: string
|
||||||
if (jsonBody == nil):
|
if jsonBody == nil:
|
||||||
strPayload = ""
|
strPayload = ""
|
||||||
else:
|
else:
|
||||||
strPayload = $jsonBody
|
strPayload = $jsonBody
|
||||||
|
@ -124,4 +125,4 @@ proc sendRequest*(endpoint: string, httpMethod: HttpMethod, headers: HttpHeaders
|
||||||
|
|
||||||
waitForRateLimits(objectID, bucketType)
|
waitForRateLimits(objectID, bucketType)
|
||||||
let response = client.request(endpoint, httpMethod, strPayload)
|
let response = client.request(endpoint, httpMethod, strPayload)
|
||||||
return handleResponse(response, objectId, bucketType)
|
return handleResponse(response, objectId, bucketType)
|
||||||
|
|
|
@ -39,12 +39,12 @@ type
|
||||||
|
|
||||||
Permissions* = ref object
|
Permissions* = ref object
|
||||||
## This type referes to a user's permissions given by the role or per user.
|
## This type referes to a user's permissions given by the role or per user.
|
||||||
roleUserID*: snowflake
|
roleUserID*: Snowflake
|
||||||
allowPerms*: uint
|
allowPerms*: uint
|
||||||
denyPerms*: uint
|
denyPerms*: uint
|
||||||
permissionType*: PermissionType
|
permissionType*: PermissionType
|
||||||
|
|
||||||
proc newPermissions*(id: snowflake, `type`: PermissionType, byteSet: uint): Permissions =
|
proc newPermissions*(id: Snowflake, `type`: PermissionType, byteSet: uint): Permissions =
|
||||||
## Create a new `Permissions` using an id, type, and byte set.
|
## Create a new `Permissions` using an id, type, and byte set.
|
||||||
result = Permissions(roleUserID: id, permissionType: `type`, allowPerms: byteSet)
|
result = Permissions(roleUserID: id, permissionType: `type`, allowPerms: byteSet)
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ proc newPermissions*(json: JsonNode): Permissions =
|
||||||
denyPerms: uint(json["deny"].getInt())
|
denyPerms: uint(json["deny"].getInt())
|
||||||
)
|
)
|
||||||
|
|
||||||
if (json["type"].getStr() == "role"):
|
if json["type"].getStr() == "role":
|
||||||
result.permissionType = PermissionType.permTypeRole
|
result.permissionType = PermissionType.permTypeRole
|
||||||
else:
|
else:
|
||||||
result.permissionType = PermissionType.permTypeMember
|
result.permissionType = PermissionType.permTypeMember
|
||||||
|
@ -71,7 +71,7 @@ proc addAllowPermission*(perms: Permissions, perm: Permission): Future[Permissio
|
||||||
## If it finds the permission in denyPerms, it will remove it from that also.
|
## If it finds the permission in denyPerms, it will remove it from that also.
|
||||||
|
|
||||||
# Check if the permission is in deny, and remove it.
|
# Check if the permission is in deny, and remove it.
|
||||||
if ((perms.denyPerms and uint(perm)) == uint(perm)):
|
if (perms.denyPerms and uint(perm)) == uint(perm):
|
||||||
perms.denyPerms = perms.denyPerms and (not uint(perm))
|
perms.denyPerms = perms.denyPerms and (not uint(perm))
|
||||||
|
|
||||||
perms.allowPerms = perms.allowPerms or uint(perm)
|
perms.allowPerms = perms.allowPerms or uint(perm)
|
||||||
|
@ -81,7 +81,7 @@ proc addDenyPermission*(perms: Permissions, perm: Permission): Future[Permission
|
||||||
## If it finds the permission in allowPerms, it will remove it from that also.
|
## If it finds the permission in allowPerms, it will remove it from that also.
|
||||||
|
|
||||||
# Check if the permission is in allowed, and remove it.
|
# Check if the permission is in allowed, and remove it.
|
||||||
if ((perms.allowPerms and uint(perm)) == uint(perm)):
|
if (perms.allowPerms and uint(perm)) == uint(perm):
|
||||||
perms.allowPerms = perms.allowPerms and (not uint(perm))
|
perms.allowPerms = perms.allowPerms and (not uint(perm))
|
||||||
|
|
||||||
perms.denyPerms = perms.denyPerms or uint(perm)
|
perms.denyPerms = perms.denyPerms or uint(perm)
|
||||||
|
@ -94,7 +94,7 @@ proc permissionsToJson*(perms: Permissions): JsonNode =
|
||||||
"deny": perms.denyPerms
|
"deny": perms.denyPerms
|
||||||
}
|
}
|
||||||
|
|
||||||
if (perms.permissionType == PermissionType.permTypeMember):
|
if perms.permissionType == PermissionType.permTypeMember:
|
||||||
json.add("type", %"member")
|
json.add("type", %"member")
|
||||||
else:
|
else:
|
||||||
json.add("type", %"role")
|
json.add("type", %"role")
|
||||||
|
|
|
@ -48,7 +48,7 @@ type
|
||||||
url*: string
|
url*: string
|
||||||
createdAt*: uint
|
createdAt*: uint
|
||||||
timestamps*: seq[ActivityTimestamp]
|
timestamps*: seq[ActivityTimestamp]
|
||||||
applicationID*: snowflake
|
applicationID*: Snowflake
|
||||||
details*: string
|
details*: string
|
||||||
state*: string
|
state*: string
|
||||||
emoji*: Emoji
|
emoji*: Emoji
|
||||||
|
@ -64,7 +64,7 @@ type
|
||||||
activities*: seq[Activity]
|
activities*: seq[Activity]
|
||||||
afk*: bool
|
afk*: bool
|
||||||
|
|
||||||
proc newActivity*(json: JsonNode, guildID: snowflake): Activity =
|
proc newActivity*(json: JsonNode, guildID: Snowflake): Activity =
|
||||||
## Parse a new activity from json.
|
## Parse a new activity from json.
|
||||||
var act = Activity(
|
var act = Activity(
|
||||||
name: json["name"].getStr(),
|
name: json["name"].getStr(),
|
||||||
|
@ -78,44 +78,44 @@ proc newActivity*(json: JsonNode, guildID: snowflake): Activity =
|
||||||
flags: uint(json{"flags"}.getInt()),
|
flags: uint(json{"flags"}.getInt()),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (json.contains("timestamps")):
|
if json.contains("timestamps"):
|
||||||
var time = ActivityTimestamp()
|
var time = ActivityTimestamp()
|
||||||
if (json["timestamps"].contains("start")):
|
if json["timestamps"].contains("start"):
|
||||||
time.startTime = uint(json["timestamps"]{"start"}.getInt())
|
time.startTime = uint(json["timestamps"]{"start"}.getInt())
|
||||||
if (json["timestamps"].contains("end")):
|
if json["timestamps"].contains("end"):
|
||||||
time.endTime = uint(json["timestamps"]{"end"}.getInt())
|
time.endTime = uint(json["timestamps"]{"end"}.getInt())
|
||||||
|
|
||||||
act.timestamps.add(time)
|
act.timestamps.add(time)
|
||||||
|
|
||||||
if (json.contains("emoji")):
|
if json.contains("emoji"):
|
||||||
act.emoji = newEmoji(json["emoji"], guildID)
|
act.emoji = newEmoji(json["emoji"], guildID)
|
||||||
|
|
||||||
if (json.contains("party")):
|
if json.contains("party"):
|
||||||
var party = ActivityParty()
|
var party = ActivityParty()
|
||||||
if (json["party"].contains("id")):
|
if json["party"].contains("id"):
|
||||||
party.id = json["party"]["id"].getStr()
|
party.id = json["party"]["id"].getStr()
|
||||||
if (json["party"].contains("size")):
|
if json["party"].contains("size"):
|
||||||
party.currentSize = uint(json["party"]["size"].elems[0].getInt())
|
party.currentSize = uint(json["party"]["size"].elems[0].getInt())
|
||||||
party.maxSize = uint(json["party"]["size"].elems[1].getInt())
|
party.maxSize = uint(json["party"]["size"].elems[1].getInt())
|
||||||
|
|
||||||
if (json.contains("assets")):
|
if json.contains("assets"):
|
||||||
var assets = ActivityAssets()
|
var assets = ActivityAssets()
|
||||||
if (json["assets"].contains("large_image")):
|
if json["assets"].contains("large_image"):
|
||||||
assets.largeImg = json["assets"]["large_image"].getStr()
|
assets.largeImg = json["assets"]["large_image"].getStr()
|
||||||
if (json["assets"].contains("large_text")):
|
if json["assets"].contains("large_text"):
|
||||||
assets.largeText = json["assets"]["large_text"].getStr()
|
assets.largeText = json["assets"]["large_text"].getStr()
|
||||||
if (json["assets"].contains("small_image")):
|
if json["assets"].contains("small_image"):
|
||||||
assets.smallImg = json["assets"]["small_image"].getStr()
|
assets.smallImg = json["assets"]["small_image"].getStr()
|
||||||
if (json["assets"].contains("small_text")):
|
if json["assets"].contains("small_text"):
|
||||||
assets.smallText = json["assets"]["small_text"].getStr()
|
assets.smallText = json["assets"]["small_text"].getStr()
|
||||||
|
|
||||||
if (json.contains("secrets")):
|
if json.contains("secrets"):
|
||||||
var secrets = ActivitySecrets()
|
var secrets = ActivitySecrets()
|
||||||
if (json["secrets"].contains("join")):
|
if json["secrets"].contains("join"):
|
||||||
secrets.join = json["secrets"]["join"].getStr()
|
secrets.join = json["secrets"]["join"].getStr()
|
||||||
if (json["secrets"].contains("spectate")):
|
if json["secrets"].contains("spectate"):
|
||||||
secrets.spectate = json["secrets"]["spectate"].getStr()
|
secrets.spectate = json["secrets"]["spectate"].getStr()
|
||||||
if (json["secrets"].contains("match")):
|
if json["secrets"].contains("match"):
|
||||||
secrets.match = json["secrets"]["match"].getStr()
|
secrets.match = json["secrets"]["match"].getStr()
|
||||||
|
|
||||||
proc newPresence*(json: JsonNode): Presence =
|
proc newPresence*(json: JsonNode): Presence =
|
||||||
|
@ -124,7 +124,7 @@ proc newPresence*(json: JsonNode): Presence =
|
||||||
status: json["status"].getStr()
|
status: json["status"].getStr()
|
||||||
)
|
)
|
||||||
|
|
||||||
if (json.contains("game") and json["game"].getFields().len > 0):
|
if json.contains("game") and json["game"].getFields().len > 0:
|
||||||
let guildID = if json.contains("guild_id"): getIDFromJson(json["guild_id"].getStr()) else: 0
|
let guildID = if json.contains("guild_id"): getIDFromJson(json["guild_id"].getStr()) else: 0
|
||||||
result.game = newActivity(json["game"], guildID)
|
result.game = newActivity(json["game"], guildID)
|
||||||
|
|
||||||
|
@ -154,4 +154,4 @@ proc presenceToJson*(presence: Presence): JsonNode =
|
||||||
"name": presence.game.name,
|
"name": presence.game.name,
|
||||||
"type": ord(presence.game.`type`)
|
"type": ord(presence.game.`type`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,9 @@ type Role* = ref object of DiscordObject
|
||||||
permissions*: Permissions
|
permissions*: Permissions
|
||||||
managed*: bool
|
managed*: bool
|
||||||
mentionable*: bool
|
mentionable*: bool
|
||||||
guildID*: snowflake
|
guildID*: Snowflake
|
||||||
|
|
||||||
proc newRole*(json: JsonNode, guild: snowflake): Role =
|
proc newRole*(json: JsonNode, guild: Snowflake): Role =
|
||||||
## Parses role from json.
|
## Parses role from json.
|
||||||
result = Role(
|
result = Role(
|
||||||
id: getIDFromJson(json["id"].getStr()),
|
id: getIDFromJson(json["id"].getStr()),
|
||||||
|
@ -38,19 +38,19 @@ proc modifyGuildRole*(role: var Role, name: Option[string] = none(string), permi
|
||||||
|
|
||||||
var jsonBody: JsonNode
|
var jsonBody: JsonNode
|
||||||
|
|
||||||
if (name.isSome):
|
if name.isSome:
|
||||||
jsonBody.add("name", %name)
|
jsonBody.add("name", %name)
|
||||||
|
|
||||||
if (permissions.isSome):
|
if permissions.isSome:
|
||||||
jsonBody.add("permissions", %permissions.get().allowPerms)
|
jsonBody.add("permissions", %permissions.get().allowPerms)
|
||||||
|
|
||||||
if (color.isSome):
|
if color.isSome:
|
||||||
jsonBody.add("color", %color)
|
jsonBody.add("color", %color)
|
||||||
|
|
||||||
if (hoist.isSome):
|
if hoist.isSome:
|
||||||
jsonBody.add("hoist", %hoist)
|
jsonBody.add("hoist", %hoist)
|
||||||
|
|
||||||
if (mentionable.isSome):
|
if mentionable.isSome:
|
||||||
jsonBody.add("mentionable", %mentionable)
|
jsonBody.add("mentionable", %mentionable)
|
||||||
|
|
||||||
result = newRole(sendRequest(endpoint(fmt("/guilds/{role.guildID}/roles/{role.id}")), HttpPatch,
|
result = newRole(sendRequest(endpoint(fmt("/guilds/{role.guildID}/roles/{role.id}")), HttpPatch,
|
||||||
|
@ -61,4 +61,4 @@ proc modifyGuildRole*(role: var Role, name: Option[string] = none(string), permi
|
||||||
proc deleteGuildRole*(role: Role) {.async.} =
|
proc deleteGuildRole*(role: Role) {.async.} =
|
||||||
## Delete a guild role. Requires the `MANAGE_ROLES` permission.
|
## Delete a guild role. Requires the `MANAGE_ROLES` permission.
|
||||||
discard sendRequest(endpoint(fmt("/guilds/{role.guildID}/roles/{role.id}")), HttpDelete,
|
discard sendRequest(endpoint(fmt("/guilds/{role.guildID}/roles/{role.id}")), HttpDelete,
|
||||||
defaultHeaders(), role.guildID, RateLimitBucketType.guild)
|
defaultHeaders(), role.guildID, RateLimitBucketType.guild)
|
||||||
|
|
Reference in New Issue