Finish all guild related endpoints and add a guildID field to some types
This commit is contained in:
parent
65344ad26c
commit
caa20f2c9c
|
@ -26,8 +26,16 @@ proc getGuild*(cache: Cache, id: snowflake): Guild =
|
||||||
if (guild.id == id):
|
if (guild.id == id):
|
||||||
return guild
|
return guild
|
||||||
|
|
||||||
return newGuild(sendRequest(endpoint("/guild/" & $id), HttpGet, defaultHeaders(),
|
return newGuild(sendRequest(endpoint("/guilds/" & $id), HttpGet, defaultHeaders(),
|
||||||
id, RateLimitBucketType.guild))
|
id, RateLimitBucketType.guild))
|
||||||
|
|
||||||
proc getChannelGuild*(channel: Channel, cache: Cache): Guild =
|
proc getChannelGuild*(channel: Channel, cache: Cache): Guild =
|
||||||
return cache.getGuild(channel.guildID)
|
return cache.getGuild(channel.guildID)
|
||||||
|
|
||||||
|
#[ proc getGuildMember*(guild: Guild, memberID: snowflake, cache: Cache): GuildMember =
|
||||||
|
for index, members in cache.members:
|
||||||
|
if (members.id == id):
|
||||||
|
return guild
|
||||||
|
|
||||||
|
return newGuildMember(sendRequest(endpoint("/guilds/" & $guild.id & "/members/" & $memberID),
|
||||||
|
HttpGet, defaultHeaders(), id, RateLimitBucketType.guild)) ]#
|
|
@ -31,18 +31,18 @@ type
|
||||||
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
|
||||||
|
|
||||||
ChannelModify* = ref object
|
ChannelFields* = ref object
|
||||||
## Use this type to modify a channel by setting each fields.
|
## Use this type to modify or create a channel by setting each fields.
|
||||||
name*: Option[string]
|
name*: Option[string]
|
||||||
`type`*: Option[ChannelType]
|
`type`*: Option[ChannelType]
|
||||||
position*: Option[int]
|
|
||||||
topic*: Option[string]
|
topic*: Option[string]
|
||||||
nsfw*: Option[bool]
|
|
||||||
rateLimitPerUser*: Option[int]
|
|
||||||
bitrate*: Option[int]
|
bitrate*: Option[int]
|
||||||
userLimit*: Option[int]
|
userLimit*: Option[int]
|
||||||
|
rateLimitPerUser*: 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]
|
||||||
|
|
||||||
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.
|
||||||
|
@ -140,14 +140,14 @@ proc sendMessage*(channel: Channel, content: string, tts: bool = false): Message
|
||||||
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})), channel.id,
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})), channel.id,
|
||||||
RateLimitBucketType.channel, messagePayload))
|
RateLimitBucketType.channel, messagePayload))
|
||||||
|
|
||||||
proc modifyChannel*(channel: Channel, modify: ChannelModify): Future[Channel] {.async.} =
|
proc modifyChannel*(channel: Channel, modify: ChannelFields): Future[Channel] {.async.} =
|
||||||
## Modifies the channel.
|
## Modifies the channel.
|
||||||
##
|
##
|
||||||
## Examples:
|
## Examples:
|
||||||
##
|
##
|
||||||
## .. code-block:: nim
|
## .. code-block:: nim
|
||||||
## var chan = getChannel(703084913510973472)
|
## var chan = getChannel(703084913510973472)
|
||||||
## chan = chan.modifyChannel(ChannelModify(topic: some("This is the channel topic")))
|
## chan = chan.modifyChannel(ChannelFields(topic: some("This is the channel topic")))
|
||||||
|
|
||||||
var modifyPayload = %*{}
|
var modifyPayload = %*{}
|
||||||
|
|
||||||
|
|
|
@ -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 eventhandler, streams, nimcordutils, discordobject, user, cache, clientobjects
|
||||||
import strutils, channel, options, message, emoji
|
import strutils, channel, options, message, emoji, guild
|
||||||
|
|
||||||
const
|
const
|
||||||
nimcordMajor = 0
|
nimcordMajor = 0
|
||||||
|
@ -104,12 +104,15 @@ proc startConnection*(client: DiscordClient) {.async.} =
|
||||||
|
|
||||||
proc newDiscordClient(tkn: string): DiscordClient =
|
proc newDiscordClient(tkn: string): DiscordClient =
|
||||||
## Create a DiscordClient using a token.
|
## Create a DiscordClient using a token.
|
||||||
|
##
|
||||||
|
## Sets globalDiscordClient to the newly created client.
|
||||||
globalToken = tkn
|
globalToken = tkn
|
||||||
|
|
||||||
var cac: Cache
|
var cac: Cache
|
||||||
new(cac)
|
new(cac)
|
||||||
|
|
||||||
result = DiscordClient(token: tkn, cache: cac)
|
result = DiscordClient(token: tkn, cache: cac)
|
||||||
|
globalDiscordClient = result
|
||||||
|
|
||||||
var tokenStream = newFileStream("token.txt", fmRead)
|
var tokenStream = newFileStream("token.txt", fmRead)
|
||||||
var tkn: string
|
var tkn: string
|
||||||
|
@ -144,7 +147,7 @@ registerEventListener(EventType.evtMessageCreate, proc(bEvt: BaseEvent) =
|
||||||
var channel: Channel = event.message.getMessageChannel(event.client.cache)
|
var channel: Channel = event.message.getMessageChannel(event.client.cache)
|
||||||
if (channel != nil):
|
if (channel != nil):
|
||||||
discard channel.sendMessage("Modifing Channel!")
|
discard channel.sendMessage("Modifing Channel!")
|
||||||
discard channel.modifyChannel(ChannelModify(topic: some(modifyTopic)))
|
discard channel.modifyChannel(ChannelFields(topic: some(modifyTopic)))
|
||||||
elif (event.message.content.startsWith("?deleteChannel")):
|
elif (event.message.content.startsWith("?deleteChannel")):
|
||||||
let channelID = getIDFromJson(event.message.content.substr(15))
|
let channelID = getIDFromJson(event.message.content.substr(15))
|
||||||
var channel: Channel = event.client.cache.getChannel(channelID)
|
var channel: Channel = event.client.cache.getChannel(channelID)
|
||||||
|
@ -166,6 +169,9 @@ registerEventListener(EventType.evtMessageCreate, proc(bEvt: BaseEvent) =
|
||||||
let messages = channel.getMessages(MessagesGetRequest(limit: some(amount), before: some(event.message.id)))
|
let messages = channel.getMessages(MessagesGetRequest(limit: some(amount), before: some(event.message.id)))
|
||||||
discard channel.bulkDeleteMessages(messages)
|
discard channel.bulkDeleteMessages(messages)
|
||||||
elif (event.message.content.startsWith("?reactToMessage")):
|
elif (event.message.content.startsWith("?reactToMessage")):
|
||||||
|
var guild: Guild
|
||||||
|
discard guild.createGuildRole(name = some("Gamer Role"), color = some(0xff0000))
|
||||||
|
|
||||||
var channel: Channel = event.message.getMessageChannel(event.client.cache)
|
var channel: Channel = event.message.getMessageChannel(event.client.cache)
|
||||||
if (channel != nil):
|
if (channel != nil):
|
||||||
let emojis = @[newEmoji("⏮️"), newEmoji("⬅️"), newEmoji("⏹️"), newEmoji("➡️"), newEmoji("⏭️")]
|
let emojis = @[newEmoji("⏮️"), newEmoji("⬅️"), newEmoji("⏹️"), newEmoji("➡️"), newEmoji("⏭️")]
|
||||||
|
|
|
@ -9,3 +9,5 @@ type DiscordClient* = ref object
|
||||||
heartbeatInterval*: int
|
heartbeatInterval*: int
|
||||||
heartbeatAcked*: bool
|
heartbeatAcked*: bool
|
||||||
lastSequence*: int
|
lastSequence*: int
|
||||||
|
|
||||||
|
var globalDiscordClient*: DiscordClient ## Global instance of the DiscordClient.
|
593
src/guild.nim
593
src/guild.nim
|
@ -1,4 +1,6 @@
|
||||||
import json, discordobject, channel, member, options, nimcordutils, emoji, role, permission, httpcore
|
import json, discordobject, channel, member, options, nimcordutils, emoji
|
||||||
|
import role, permission, httpcore, strformat, image, asyncdispatch, user
|
||||||
|
import permission
|
||||||
|
|
||||||
type
|
type
|
||||||
VerificationLevel* = enum
|
VerificationLevel* = enum
|
||||||
|
@ -78,6 +80,68 @@ type
|
||||||
approximateMemberCount*: int
|
approximateMemberCount*: int
|
||||||
approximatePresenceCount*: int
|
approximatePresenceCount*: int
|
||||||
|
|
||||||
|
GuildPreview* = ref object of DiscordObject
|
||||||
|
## Represents a guild review.
|
||||||
|
name*: string
|
||||||
|
icon*: string
|
||||||
|
splash*: string
|
||||||
|
discoverySplash*: string
|
||||||
|
emojis*: seq[Emoji]
|
||||||
|
features*: seq[string]
|
||||||
|
approximateMemberCount*: int
|
||||||
|
approximatePresenceCount*: int
|
||||||
|
description*: string
|
||||||
|
|
||||||
|
GuildBan* = ref object
|
||||||
|
## A guild ban.
|
||||||
|
reason*: string
|
||||||
|
user*: User
|
||||||
|
|
||||||
|
VoiceRegion* = ref object
|
||||||
|
## Voice region.
|
||||||
|
id*: string
|
||||||
|
name*: string
|
||||||
|
vip*: bool
|
||||||
|
optimal*: bool
|
||||||
|
deprecated*: bool
|
||||||
|
custom*: bool
|
||||||
|
|
||||||
|
IntegrationExpireBehavior* = enum
|
||||||
|
intExpireBehRemoveRole = 0,
|
||||||
|
intExpireBehKick = 1
|
||||||
|
|
||||||
|
IntegrationAccount* = ref object
|
||||||
|
id*: string
|
||||||
|
name*: string
|
||||||
|
|
||||||
|
Integration* = ref object of DiscordObject
|
||||||
|
name*: string
|
||||||
|
`type`*: string ## Integration type (twitch, youtube, etc)
|
||||||
|
enabled*: bool
|
||||||
|
syncing*: bool
|
||||||
|
roleID*: snowflake
|
||||||
|
enableEmoticons*: bool
|
||||||
|
expireBehavior*: IntegrationExpireBehavior
|
||||||
|
expireGracePeriod*: int
|
||||||
|
user*: User
|
||||||
|
account*: IntegrationAccount
|
||||||
|
syncedAt*: string
|
||||||
|
|
||||||
|
GuildWidget* = ref object
|
||||||
|
enabled*: bool
|
||||||
|
channelID*: snowflake
|
||||||
|
|
||||||
|
GuildWidgetStyle* = enum
|
||||||
|
guildWidgetStyleShield = "shield", ## Shield style widget with Discord icon and guild members online count.
|
||||||
|
guildWidgetStyleBanner1 = "banner1", ## Large image with guild icon, name and online count.
|
||||||
|
## "POWERED BY DISCORD" as the footer of the widget.
|
||||||
|
guildWidgetStyleBanner2 = "banner2", ## Smaller widget style with guild icon, name and online count.
|
||||||
|
## Split on the right with Discord logo.
|
||||||
|
guildWidgetStyleBanner3 = "banner3", ## Large image with guild icon, name and online count.
|
||||||
|
## In the footer, Discord logo on the left and "Chat Now" on the right.
|
||||||
|
guildWidgetStyleBanner4 = "banner4"
|
||||||
|
|
||||||
|
|
||||||
proc newGuild*(json: JsonNode): Guild {.inline.} =
|
proc newGuild*(json: JsonNode): Guild {.inline.} =
|
||||||
## Parses a Guild type from json.
|
## Parses a Guild type from json.
|
||||||
var g = Guild(
|
var g = Guild(
|
||||||
|
@ -113,7 +177,7 @@ proc newGuild*(json: JsonNode): Guild {.inline.} =
|
||||||
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.roles.add(newRole(role, g.id))
|
||||||
for emoji in json["emojis"]:
|
for emoji in json["emojis"]:
|
||||||
g.emojis.add(newEmoji(emoji))
|
g.emojis.add(newEmoji(emoji))
|
||||||
#TODO features
|
#TODO features
|
||||||
|
@ -130,7 +194,7 @@ proc newGuild*(json: JsonNode): Guild {.inline.} =
|
||||||
#TODO: voice_states
|
#TODO: voice_states
|
||||||
if (json.contains("members")):
|
if (json.contains("members")):
|
||||||
for member in json["members"]:
|
for member in json["members"]:
|
||||||
g.members.insert(newGuildMember(member))
|
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))
|
||||||
|
@ -157,6 +221,7 @@ proc createGuild*(name: string, region: Option[string], icon: Option[string], ve
|
||||||
## Create a new guild.
|
## Create a new guild.
|
||||||
##
|
##
|
||||||
## Some restraints/notes for this endpoint:
|
## Some restraints/notes for this endpoint:
|
||||||
|
## * This endpoint is only available with bots that are in less than 10 guilds.
|
||||||
## * When using the roles parameter, the first member of the array is used
|
## * When using the roles parameter, the first member of the array is used
|
||||||
## to change properties of the guild's @everyone role. If you are trying to
|
## to change properties of the guild's @everyone role. If you are trying to
|
||||||
## bootstrap a guild with additional roles, keep this in mind.
|
## bootstrap a guild with additional roles, keep this in mind.
|
||||||
|
@ -232,3 +297,525 @@ proc createGuild*(name: string, region: Option[string], icon: Option[string], ve
|
||||||
return newGuild(sendRequest(endpoint("/guilds"), HttpPost,
|
return newGuild(sendRequest(endpoint("/guilds"), HttpPost,
|
||||||
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
0, RateLimitBucketType.global, json))
|
0, RateLimitBucketType.global, json))
|
||||||
|
|
||||||
|
proc getGuildPreview*(guild: Guild): GuildPreview =
|
||||||
|
## Returns the guild preview object for the given id, even if the user is not in the guild.
|
||||||
|
## Only available for public guilds!
|
||||||
|
let json = sendRequest(endpoint(fmt("/guilds/{guild.id}/preview")), HttpPost,
|
||||||
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
|
guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
result = GuildPreview(
|
||||||
|
id: getIDFromJson(json["id"].getStr()),
|
||||||
|
name: json["name"].getStr(),
|
||||||
|
icon: json["icon"].getStr(),
|
||||||
|
splash: json["splash"].getStr(),
|
||||||
|
discoverySplash: json["discovery_splash"].getStr(),
|
||||||
|
approximateMemberCount: json["approximate_member_count"].getInt(),
|
||||||
|
approximatePresenceCount: json["approximate_presence_count"].getInt(),
|
||||||
|
description: json["description"].getStr()
|
||||||
|
)
|
||||||
|
|
||||||
|
for emoji in json["emojis"]:
|
||||||
|
result.emojis.add(newEmoji(emoji))
|
||||||
|
|
||||||
|
for feature in json["features"]:
|
||||||
|
result.features.add(feature.getStr())
|
||||||
|
|
||||||
|
type GuildModify* = ref object
|
||||||
|
## Use this type to modify a guild by setting each fields.
|
||||||
|
name*: Option[string]
|
||||||
|
region*: Option[string]
|
||||||
|
verificationLevel*: Option[VerificationLevel]
|
||||||
|
defaultMessageNotifications*: Option[MessageNotificationsLevel]
|
||||||
|
explicitContentFilter*: Option[ExplicitContentFilterLevel]
|
||||||
|
afkChannelID*: Option[snowflake]
|
||||||
|
afkTimeout*: Option[int]
|
||||||
|
icon*: Option[Image]
|
||||||
|
ownerID*: Option[snowflake]
|
||||||
|
splash*: Option[Image]
|
||||||
|
banner*: Option[Image]
|
||||||
|
systemChannelID*: Option[snowflake]
|
||||||
|
rulesChannelID*: Option[snowflake]
|
||||||
|
publicUpdatesChannelID*: Option[snowflake]
|
||||||
|
preferredLocale*: Option[string]
|
||||||
|
|
||||||
|
proc modifyGuild*(guild: Guild, modify: GuildModify): Future[Guild] {.async.} =
|
||||||
|
## Modifies the Guild.
|
||||||
|
##
|
||||||
|
## Examples:
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
## var guild = getGuild(703084913510973472)
|
||||||
|
## guild = guild.modifyGuild(GuildModify(name: some("Epic Gamer Guild")))
|
||||||
|
|
||||||
|
var modifyPayload = %*{}
|
||||||
|
|
||||||
|
if (modify.name.isSome):
|
||||||
|
modifyPayload.add("name", %modify.name.get())
|
||||||
|
|
||||||
|
if (modify.region.isSome):
|
||||||
|
modifyPayload.add("region", %modify.region.get())
|
||||||
|
|
||||||
|
if (modify.verificationLevel.isSome):
|
||||||
|
modifyPayload.add("verification_level", %modify.verificationLevel.get())
|
||||||
|
|
||||||
|
if (modify.defaultMessageNotifications.isSome):
|
||||||
|
modifyPayload.add("default_message_notifications", %modify.defaultMessageNotifications.get())
|
||||||
|
|
||||||
|
if (modify.explicitContentFilter.isSome):
|
||||||
|
modifyPayload.add("explicit_content_filter", %modify.explicitContentFilter.get())
|
||||||
|
|
||||||
|
if (modify.afkChannelID.isSome):
|
||||||
|
modifyPayload.add("afk_channel_id", %modify.afkChannelID.get())
|
||||||
|
|
||||||
|
if (modify.afkTimeout.isSome):
|
||||||
|
modifyPayload.add("afk_timeout", %modify.afkTimeout.get())
|
||||||
|
|
||||||
|
if (modify.icon.isSome):
|
||||||
|
modifyPayload.add("icon", %modify.icon.get().imageToDataURI())
|
||||||
|
|
||||||
|
if (modify.ownerID.isSome):
|
||||||
|
modifyPayload.add("owner_id", %modify.ownerID.get())
|
||||||
|
|
||||||
|
if (modify.splash.isSome):
|
||||||
|
modifyPayload.add("splash", %modify.splash.get().imageToDataURI())
|
||||||
|
|
||||||
|
if (modify.banner.isSome):
|
||||||
|
modifyPayload.add("banner", %modify.banner.get().imageToDataURI())
|
||||||
|
|
||||||
|
if (modify.systemChannelID.isSome):
|
||||||
|
modifyPayload.add("system_channel_id", %modify.systemChannelID.get())
|
||||||
|
|
||||||
|
if (modify.rulesChannelID.isSome):
|
||||||
|
modifyPayload.add("rules_channel_id", %modify.rulesChannelID.get())
|
||||||
|
|
||||||
|
if (modify.publicUpdatesChannelID.isSome):
|
||||||
|
modifyPayload.add("public_updates_channel_id", %modify.publicUpdatesChannelID.get())
|
||||||
|
|
||||||
|
if (modify.preferredLocale.isSome):
|
||||||
|
modifyPayload.add("preferred_locale", %modify.preferredLocale.get())
|
||||||
|
|
||||||
|
return newGuild(sendRequest(endpoint("/guilds/" & $guild.id), HttpPatch,
|
||||||
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
|
guild.id, RateLimitBucketType.guild, modifyPayload))
|
||||||
|
|
||||||
|
proc deleteGuild*(guild: Guild) {.async.} =
|
||||||
|
## Delete the guild. The bot must be the owner of the guild!
|
||||||
|
discard sendRequest(endpoint("/guilds/" & $guild.id), HttpDelete,
|
||||||
|
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
proc requestGuildChannels*(guild: var Guild): seq[Channel] =
|
||||||
|
## Request all guild channels via Discord's REST API
|
||||||
|
## Only use this if for some reason, guild.channels is inaccurate!
|
||||||
|
##
|
||||||
|
## Also updates the guild's channels when called.
|
||||||
|
let json = sendRequest(endpoint("/guilds/" & $guild.id & "/channels"), HttpGet,
|
||||||
|
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
for channel in json:
|
||||||
|
result.add(newChannel(channel))
|
||||||
|
guild.channels = result
|
||||||
|
|
||||||
|
proc createGuildChannel*(guild: var Guild, create: ChannelFields): Future[Channel] {.async.} =
|
||||||
|
## Creates a new guild channel.
|
||||||
|
## The name field must be set, if you dont a `Defect` exception will be raised.
|
||||||
|
## The created channel will be added to the guild's `channels` field.
|
||||||
|
##
|
||||||
|
## Examples:
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
## let guild = getGuild(703084913510973472)
|
||||||
|
## let channel = waitFor guild.createGuildChannel(ChannelFields(name: some("Epic Gamer Channel")))
|
||||||
|
|
||||||
|
var createPayload = %*{}
|
||||||
|
|
||||||
|
# Make sure that the name is supplied since its required for this endpoint.
|
||||||
|
if (create.name.isSome):
|
||||||
|
createPayload.add("name", %create.name.get())
|
||||||
|
else:
|
||||||
|
raise newException(Defect, "You must have a channel name when creating it!")
|
||||||
|
|
||||||
|
if (create.`type`.isSome):
|
||||||
|
createPayload.add("type", %create.`type`.get())
|
||||||
|
|
||||||
|
if (create.position.isSome):
|
||||||
|
createPayload.add("position", %create.position.get())
|
||||||
|
|
||||||
|
if (create.topic.isSome):
|
||||||
|
createPayload.add("topic", %create.topic.get())
|
||||||
|
|
||||||
|
if (create.nsfw.isSome):
|
||||||
|
createPayload.add("nsfw", %create.nsfw.get())
|
||||||
|
|
||||||
|
if (create.rateLimitPerUser.isSome):
|
||||||
|
createPayload.add("rate_limit_per_user", %create.rateLimitPerUser.get())
|
||||||
|
|
||||||
|
if (create.bitrate.isSome):
|
||||||
|
createPayload.add("bitrate", %create.bitrate.get())
|
||||||
|
|
||||||
|
if (create.userLimit.isSome):
|
||||||
|
createPayload.add("user_limit", %create.userLimit.get())
|
||||||
|
|
||||||
|
if (create.permissionOverwrites.isSome):
|
||||||
|
var permOverwrites = parseJson("[]")
|
||||||
|
for perm in create.permissionOverwrites.get():
|
||||||
|
permOverwrites.add(perm.permissionsToJson())
|
||||||
|
createPayload.add("permission_overwrites", permOverwrites)
|
||||||
|
|
||||||
|
result = newChannel(sendRequest(endpoint("/guilds/" & $guild.id & "/channels"), HttpPost,
|
||||||
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
|
guild.id, RateLimitBucketType.guild, createPayload))
|
||||||
|
|
||||||
|
proc modifyGuildChannelPositions*(guild: var Guild, channels: seq[Channel]) {.async.} =
|
||||||
|
## Modify the positions of a set of channel objects for the guild.
|
||||||
|
## The order is determined by the channel's `position` field
|
||||||
|
|
||||||
|
var jsonBody: JsonNode
|
||||||
|
for channel in channels:
|
||||||
|
jsonBody.add(%*{"id": channel.id, "position": channel.position})
|
||||||
|
|
||||||
|
discard sendRequest(endpoint("/guilds/" & $guild.id & "/channels"), HttpPatch,
|
||||||
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
|
guild.id, RateLimitBucketType.guild, jsonBody)
|
||||||
|
|
||||||
|
proc getGuildMember*(guild: var Guild, memberID: snowflake): GuildMember =
|
||||||
|
## Get a guild member.
|
||||||
|
## This first checks `guild.members`, but if it doesn't exist there,
|
||||||
|
## it will be requested from Discord's REST API.
|
||||||
|
##
|
||||||
|
## If we end up requesting one, it will add it to `guild.members`
|
||||||
|
|
||||||
|
for member in guild.members:
|
||||||
|
if (member.id == memberID):
|
||||||
|
return member
|
||||||
|
|
||||||
|
result = newGuildMember(sendRequest(endpoint(fmt("/guilds/{guild.id}/members/{memberID}")),
|
||||||
|
HttpPatch, defaultHeaders(), guild.id, RateLimitBucketType.guild), guild.id)
|
||||||
|
guild.members.add(result)
|
||||||
|
|
||||||
|
# Would this endpoint be worth adding? https://discord.com/developers/docs/resources/guild#list-guild-members
|
||||||
|
# And what about this one? https://discord.com/developers/docs/resources/guild#list-guild-members
|
||||||
|
|
||||||
|
proc modifyCurrentUserNick*(guild: Guild, nick: string) {.async.} =
|
||||||
|
## Modifies the nickname of the current user in a guild.
|
||||||
|
discard sendRequest(endpoint(fmt("/guilds/{guild.id}/members/@me/nick")), HttpPatch,
|
||||||
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
|
guild.id, RateLimitBucketType.guild, %*{"nick": nick})
|
||||||
|
|
||||||
|
proc kickGuildMember*(guild: Guild, member: GuildMember) {.async.} =
|
||||||
|
## Remove a member from a guild. Requires `KICK_MEMBERS` permission.
|
||||||
|
discard sendRequest(endpoint(fmt("/guilds/{guild.id}/members/{member.id}")), HttpDelete,
|
||||||
|
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
proc getGuildBans*(guild: Guild): seq[GuildBan] =
|
||||||
|
## Get a list of guild bans. Requires the `BAN_MEMBERS` permission.
|
||||||
|
let json = sendRequest(endpoint(fmt("/guilds/{guild.id}/bans")), HttpGet,
|
||||||
|
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
for ban in json:
|
||||||
|
result.add(GuildBan(
|
||||||
|
reason: json{"reason"}.getStr(),
|
||||||
|
user: newUser(json["user"])
|
||||||
|
))
|
||||||
|
|
||||||
|
proc getGuildBan*(guild: Guild, userID: snowflake): GuildBan =
|
||||||
|
## Returns a ban object for the given user or nil if the ban cannot be found.
|
||||||
|
## Requires the BAN_MEMBERS permission.
|
||||||
|
let response = sendRequest(endpoint(fmt("/guilds/{guild.id}/bans{userID}")), HttpGet,
|
||||||
|
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
if not response.isNil():
|
||||||
|
return GuildBan(
|
||||||
|
reason: response{"reason"}.getStr(),
|
||||||
|
user: newUser(response["user"])
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return nil
|
||||||
|
|
||||||
|
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
|
||||||
|
## banned user. Requires the BAN_MEMBERS permission.
|
||||||
|
|
||||||
|
var jsonBody: JsonNode
|
||||||
|
|
||||||
|
if (reason.isSome):
|
||||||
|
jsonBody.add("reason", %reason.get())
|
||||||
|
if (deleteMessageDays.isSome):
|
||||||
|
jsonBody.add("deleteMessageDays", %deleteMessageDays.get())
|
||||||
|
|
||||||
|
discard sendRequest(endpoint(fmt("/guilds/{guild.id}/bans/{userID}")), HttpPut,
|
||||||
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
|
guild.id, RateLimitBucketType.guild, jsonBody)
|
||||||
|
|
||||||
|
proc unbanGuildMember*(guild: Guild, userID: snowflake) {.async.} =
|
||||||
|
## Remove the ban for a user. Requires the BAN_MEMBERS permissions.
|
||||||
|
discard sendRequest(endpoint(fmt("/guilds/{guild.id}/bans/{userID}")), HttpDelete,
|
||||||
|
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
proc requestGuildRoles*(guild: Guild): seq[Role] =
|
||||||
|
## Request all guild roles via Discord's REST API
|
||||||
|
## Only use this if for some reason, guild.roles is inaccurate!
|
||||||
|
##
|
||||||
|
## Also updates the guild's roles when called.
|
||||||
|
|
||||||
|
let jsonBody = sendRequest(endpoint(fmt("/guilds/{guild.id}/roles")), HttpGet,
|
||||||
|
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
for role in jsonBody:
|
||||||
|
result.add(newRole(role, guild.id))
|
||||||
|
guild.roles = result
|
||||||
|
|
||||||
|
proc createGuildRole*(guild: Guild, name: Option[string] = none(string), permissions: Option[Permissions] = none(Permissions),
|
||||||
|
color: Option[int] = none(int), hoist: Option[bool] = none(bool), mentionable: Option[bool] = none(bool)): Future[Role] {.async.} =
|
||||||
|
## Create a new role for the guild. Requires the `MANAGE_ROLES` permission.
|
||||||
|
##
|
||||||
|
## Example:
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
## discard guild.createGuildRole(name = some("Gamer Role"), color = some(0xff0000))
|
||||||
|
|
||||||
|
var jsonBody: JsonNode
|
||||||
|
|
||||||
|
if (name.isSome):
|
||||||
|
jsonBody.add("name", %name)
|
||||||
|
|
||||||
|
if (permissions.isSome):
|
||||||
|
jsonBody.add("permissions", %permissions.get().allowPerms)
|
||||||
|
|
||||||
|
if (color.isSome):
|
||||||
|
jsonBody.add("color", %color)
|
||||||
|
|
||||||
|
if (hoist.isSome):
|
||||||
|
jsonBody.add("hoist", %hoist)
|
||||||
|
|
||||||
|
if (mentionable.isSome):
|
||||||
|
jsonBody.add("mentionable", %mentionable)
|
||||||
|
|
||||||
|
return newRole(sendRequest(endpoint(fmt("/guilds/{guild.id}/roles")), HttpPost,
|
||||||
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
|
guild.id, RateLimitBucketType.guild, jsonBody), guild.id)
|
||||||
|
|
||||||
|
proc modifyGuildRolePositions*(guild: var Guild, roles: seq[Role]) {.async.} =
|
||||||
|
## Modify the positions of a set of role objects for the guild.
|
||||||
|
## The order is determined by the role's `position` field
|
||||||
|
|
||||||
|
var jsonBody: JsonNode
|
||||||
|
for role in roles:
|
||||||
|
jsonBody.add(%*{"id": role.id, "position": role.position})
|
||||||
|
|
||||||
|
discard sendRequest(endpoint("/guilds/" & $guild.id & "/roles"), HttpPatch,
|
||||||
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
|
guild.id, RateLimitBucketType.guild, jsonBody)
|
||||||
|
|
||||||
|
proc getGuildPruneCount*(guild: Guild, days: int = 7, includedRoles: seq[snowflake] = @[]): int =
|
||||||
|
## Returns the number of members that would be removed in a prune operation.
|
||||||
|
## Requires the `KICK_MEMBERS` permission.
|
||||||
|
##
|
||||||
|
## By default, prune will not remove users with roles. You can optionally include
|
||||||
|
## specific roles in your prune by providing the `includedRoles` parameter. Any
|
||||||
|
## inactive user that has a subset of the provided role(s) will be counted in
|
||||||
|
## the prune and users with additional roles will not.
|
||||||
|
var url = endpoint(fmt("/guilds/{guild.id}/prune"))
|
||||||
|
|
||||||
|
if days != 7:
|
||||||
|
url &= "?days=" & $days
|
||||||
|
|
||||||
|
if includedRoles.len != 0:
|
||||||
|
# If the days field was also set, then we need to ad "&" to the url.
|
||||||
|
if days != 7:
|
||||||
|
url &= "&"
|
||||||
|
url &= "include_roles=" & ($includedRoles).substr(1)
|
||||||
|
|
||||||
|
let jsonBody = sendRequest(url, HttpGet, defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
return jsonBody["pruned"].getInt()
|
||||||
|
|
||||||
|
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.
|
||||||
|
## Requires the `KICK_MEMBERS` permission.
|
||||||
|
##
|
||||||
|
## If you specify `computePruneCount` the proc will return the amount of users
|
||||||
|
## that were pruned. Not recommended on large guilds!
|
||||||
|
##
|
||||||
|
## By default, prune will not remove users with roles. You can optionally include
|
||||||
|
## specific roles in your prune by providing the `includedRoles` parameter. Any
|
||||||
|
## inactive user that has a subset of the provided role(s) will be counted in
|
||||||
|
## the prune and users with additional roles will not.
|
||||||
|
var url = endpoint(fmt("/guilds/{guild.id}/prune"))
|
||||||
|
|
||||||
|
if days != 7:
|
||||||
|
url &= "?days=" & $days
|
||||||
|
|
||||||
|
if includedRoles.len != 0:
|
||||||
|
# If the days field was also set, then we need to add "&" to the url.
|
||||||
|
if days != 7:
|
||||||
|
url &= "&"
|
||||||
|
url &= "include_roles=" & ($includedRoles).substr(1)
|
||||||
|
|
||||||
|
if computePruneCount:
|
||||||
|
# If the days or includedRoles field was also set, then we need to add "&" to the url.
|
||||||
|
if days != 7 or includedRoles.len != 0:
|
||||||
|
url &= "&"
|
||||||
|
url &= "compute_prune_count=" & $computePruneCount
|
||||||
|
|
||||||
|
let jsonBody = sendRequest(url, HttpGet, defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
if computePruneCount:
|
||||||
|
return some(jsonBody["pruned"].getInt())
|
||||||
|
|
||||||
|
#TODO: https://discord.com/developers/docs/resources/guild#get-guild-voice-regions
|
||||||
|
|
||||||
|
proc getGuildVoiceRegions*(guild: Guild): seq[VoiceRegion] =
|
||||||
|
## Returns a list of voice region objects for the guild.
|
||||||
|
let jsonBody = sendRequest(endpoint(fmt("/guilds/{guild.id}/regions")), HttpGet,
|
||||||
|
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
for voiceRegion in jsonBody:
|
||||||
|
result.add(VoiceRegion(
|
||||||
|
id: jsonBody["id"].getStr(),
|
||||||
|
name: jsonBody["name"].getStr(),
|
||||||
|
vip: jsonBody["vip"].getBool(),
|
||||||
|
optimal: jsonBody["optimal"].getBool(),
|
||||||
|
deprecated: jsonBody["deprecated"].getBool(),
|
||||||
|
custom: jsonBody["custom"].getBool()
|
||||||
|
))
|
||||||
|
|
||||||
|
proc getGuildInvites*(guild: Guild): seq[Invite] =
|
||||||
|
## Returns a list of invite objects (with invite metadata) for the guild.
|
||||||
|
## Requires the `MANAGE_GUILD` permission.
|
||||||
|
let jsonBody = sendRequest(endpoint(fmt("/guilds/{guild.id}/invites")), HttpGet,
|
||||||
|
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
for invite in jsonBody:
|
||||||
|
result.add(newInvite(invite))
|
||||||
|
|
||||||
|
proc getGuildIntegrations*(guild: Guild): seq[Integration] =
|
||||||
|
## Returns a list of integration objects for the guild. Requires the `MANAGE_GUILD` permission.
|
||||||
|
let jsonBody = sendRequest(endpoint(fmt("/guilds/{guild.id}/integrations")), HttpGet,
|
||||||
|
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
for integration in jsonBody:
|
||||||
|
result.add(Integration(
|
||||||
|
id: getIDFromJson(jsonBody["id"].getStr()),
|
||||||
|
name: jsonBody["name"].getStr(),
|
||||||
|
`type`: jsonBody["type"].getStr(),
|
||||||
|
enabled: jsonBody["enabled"].getBool(),
|
||||||
|
syncing: jsonBody["syncing"].getBool(),
|
||||||
|
roleID: getIDFromJson(jsonBody["role_id"].getStr()),
|
||||||
|
enableEmoticons: jsonBody["enable_emoticons"].getBool(),
|
||||||
|
expireBehavior: IntegrationExpireBehavior(jsonBody["expire_behavior"].getInt()),
|
||||||
|
expireGracePeriod: jsonBody{"expire_grace_period"}.getInt(),
|
||||||
|
user: newUser(jsonBody["user"]),
|
||||||
|
account: IntegrationAccount(
|
||||||
|
id: jsonBody["account"]["id"].getStr(),
|
||||||
|
name: jsonBody["account"]["name"].getStr(),
|
||||||
|
),
|
||||||
|
syncedAt: jsonBody["synced_at"].getStr()
|
||||||
|
))
|
||||||
|
|
||||||
|
proc createGuildIntegration*(guild: Guild, `type`: string, id: string) {.async.} =
|
||||||
|
## Attach an integration object from the current user to the guild. Requires the `MANAGE_GUILD` permission.
|
||||||
|
let jsonBody = %* {
|
||||||
|
"type": `type`,
|
||||||
|
"id": id
|
||||||
|
}
|
||||||
|
|
||||||
|
discard sendRequest(endpoint("/guilds/" & $guild.id & "/integrations"), HttpPost,
|
||||||
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
|
guild.id, RateLimitBucketType.guild, jsonBody)
|
||||||
|
|
||||||
|
proc modifyGuildIntegration*(guild: Guild, integration: var Integration,
|
||||||
|
expireBehavior: Option[IntegrationExpireBehavior] = none(IntegrationExpireBehavior),
|
||||||
|
expireGracePeriod: Option[int] = none(int), enableEmoticons: Option[bool] = none(bool)) {.async.} =
|
||||||
|
## Modify the behavior and settings of an integration object for the guild. Requires the `MANAGE_GUILD` permission.
|
||||||
|
##
|
||||||
|
## The changes are reflected to the given `integration`.
|
||||||
|
##
|
||||||
|
## Example:
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
## discard integration.modifyGuildIntegration(enable_emoticons = true)
|
||||||
|
var modifyPayload = %*{}
|
||||||
|
|
||||||
|
if (expireBehavior.isSome):
|
||||||
|
modifyPayload.add("expire_behavior", %expireBehavior.get())
|
||||||
|
integration.expireBehavior = (expireBehavior.get())
|
||||||
|
|
||||||
|
if (expireGracePeriod.isSome):
|
||||||
|
modifyPayload.add("expire_grace_period", %expireGracePeriod.get())
|
||||||
|
integration.expireGracePeriod = expireGracePeriod.get()
|
||||||
|
|
||||||
|
if (enableEmoticons.isSome):
|
||||||
|
modifyPayload.add("enable_emoticons", %enableEmoticons.get())
|
||||||
|
integration.enableEmoticons = enableEmoticons.get()
|
||||||
|
|
||||||
|
discard sendRequest(endpoint(fmt("/guilds/{guild.id}/integration/{integration.id}")), HttpPatch,
|
||||||
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
|
guild.id, RateLimitBucketType.guild, modifyPayload)
|
||||||
|
|
||||||
|
proc deleteGuildIntegration*(guild: Guild, integration: Integration) {.async.} =
|
||||||
|
## Delete the attached integration object for the guild. Requires the `MANAGE_GUILD` permission.
|
||||||
|
discard sendRequest(endpoint(fmt("/guilds/{guild.id}/integrations/{integration.id}")), HttpDelete,
|
||||||
|
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
proc syncGuildIntegration*(guild: Guild, integration: Integration) {.async.} =
|
||||||
|
## Sync an integration. Requires the `MANAGE_GUILD` permission.
|
||||||
|
discard sendRequest(endpoint(fmt("/guilds/{guild.id}/integrations/{integration.id}")), HttpPost,
|
||||||
|
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
proc getGuildWidget*(guild: Guild): GuildWidget =
|
||||||
|
## Returns the guild widget object. Requires the `MANAGE_GUILD` permission.
|
||||||
|
|
||||||
|
let jsonBody = sendRequest(endpoint(fmt("/guilds/{guild.id}/widget")), HttpGet,
|
||||||
|
defaultHeaders(), guild.id, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
return GuildWidget(enabled: jsonBody["enabled"].getBool(),
|
||||||
|
channelID: getIDFromJson(jsonBody{"channel_id"}.getStr()))
|
||||||
|
|
||||||
|
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.
|
||||||
|
widget.enabled = enabled
|
||||||
|
widget.channelID = channelID
|
||||||
|
|
||||||
|
let jsonBody = %* {
|
||||||
|
"enabled": enabled,
|
||||||
|
"channelID": channelID
|
||||||
|
}
|
||||||
|
|
||||||
|
discard sendRequest(endpoint(fmt("/guilds/{guild.id}/widget")), HttpPost,
|
||||||
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
|
guild.id, RateLimitBucketType.guild, jsonBody)
|
||||||
|
|
||||||
|
proc getGuildVanityURL*(guild: Guild): Invite =
|
||||||
|
## Returns a partial invite object for guilds with that feature enabled. Requires the `MANAGE_GUILD` permission.
|
||||||
|
return newInvite(sendRequest(endpoint(fmt("/guilds/{guild.id}/vanity-url")), HttpGet,
|
||||||
|
defaultHeaders(), guild.id, RateLimitBucketType.guild))
|
||||||
|
|
||||||
|
proc getGuildWidgetImage*(guild: Guild, style: GuildWidgetStyle): string =
|
||||||
|
## Returns a url to this guild's widget image.
|
||||||
|
##
|
||||||
|
## Style types:
|
||||||
|
## * Shield: Shield style widget with Discord icon and guild members
|
||||||
|
## online count. [Example](https://discord.com/api/guilds/81384788765712384/widget.png?style=shield)
|
||||||
|
## * Banner 1: Large image with guild icon, name and online count.
|
||||||
|
## "POWERED BY DISCORD" as the footer of the widget. [Example](https://discord.com/api/guilds/81384788765712384/widget.png?style=banner1)
|
||||||
|
## * Banner 2: Smaller widget style with guild icon, name and online
|
||||||
|
## count. Split on the right with Discord logo. [Example](https://discord.com/api/guilds/81384788765712384/widget.png?style=banner2)
|
||||||
|
## * Banner 3: Large image with guild icon, name and online count.
|
||||||
|
## In the footer, Discord logo on the left and "Chat Now" on the right [Example](https://discord.com/api/guilds/81384788765712384/widget.png?style=banner3)
|
||||||
|
## * Banner 4: Large Discord logo at the top of the widget. Guild
|
||||||
|
## icon, name and online count in the middle portion of the widget
|
||||||
|
## 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")
|
||||||
|
|
||||||
|
case (style)
|
||||||
|
of (GuildWidgetStyle.guildWidgetStyleShield):
|
||||||
|
result &= "?style=shield"
|
||||||
|
of (GuildWidgetStyle.guildWidgetStyleBanner1):
|
||||||
|
result &= "?style=banner1"
|
||||||
|
of (GuildWidgetStyle.guildWidgetStyleBanner2):
|
||||||
|
result &= "?style=banner2"
|
||||||
|
of (GuildWidgetStyle.guildWidgetStyleBanner3):
|
||||||
|
result &= "?style=banner3"
|
||||||
|
of (GuildWidgetStyle.guildWidgetStyleBanner4):
|
||||||
|
result &= "?style=banner4"
|
|
@ -1,4 +1,4 @@
|
||||||
import discordobject, user, json, role
|
import discordobject, user, json, role, options, asyncdispatch, nimcordutils, httpcore, strformat, strutils
|
||||||
|
|
||||||
type GuildMember* = ref object of DiscordObject
|
type GuildMember* = ref object of DiscordObject
|
||||||
## This type is a guild member.
|
## This type is a guild member.
|
||||||
|
@ -9,9 +9,9 @@ type GuildMember* = ref object of DiscordObject
|
||||||
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.
|
||||||
|
|
||||||
|
proc newGuildMember*(json: JsonNode, guild: snowflake): GuildMember {.inline.} =
|
||||||
proc newGuildMember*(json: JsonNode): GuildMember {.inline.} =
|
|
||||||
## Construct a GuildMember using json.
|
## Construct a GuildMember using json.
|
||||||
var member = GuildMember(
|
var member = GuildMember(
|
||||||
nick: json{"nick"}.getStr(),
|
nick: json{"nick"}.getStr(),
|
||||||
|
@ -19,14 +19,60 @@ proc newGuildMember*(json: JsonNode): GuildMember {.inline.} =
|
||||||
joinedAt: json["joined_at"].getStr(),
|
joinedAt: json["joined_at"].getStr(),
|
||||||
premiumSince: json{"premium_since"}.getStr(),
|
premiumSince: json{"premium_since"}.getStr(),
|
||||||
deaf: json["deaf"].getBool(),
|
deaf: json["deaf"].getBool(),
|
||||||
mute: json["mute"].getBool()
|
mute: json["mute"].getBool(),
|
||||||
|
guildID: guild
|
||||||
)
|
)
|
||||||
|
|
||||||
if (json.contains("user")):
|
if (json.contains("user")):
|
||||||
member.user = newUser(json["user"])
|
member.user = newUser(json["user"])
|
||||||
|
|
||||||
for role in json:
|
for role in json:
|
||||||
member.roles.add(newRole(role))
|
member.roles.add(newRole(role, member.guildID))
|
||||||
|
|
||||||
return member
|
return member
|
||||||
|
|
||||||
|
type GuildMemberModify* = ref object
|
||||||
|
nick: Option[string]
|
||||||
|
roles: Option[seq[snowflake]]
|
||||||
|
mute: Option[bool]
|
||||||
|
deaf: Option[bool]
|
||||||
|
channelID: Option[snowflake]
|
||||||
|
|
||||||
|
proc modifyGuildMember*(member: GuildMember, memberID: snowflake, modify: GuildMemberModify) {.async.} =
|
||||||
|
## 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.
|
||||||
|
##
|
||||||
|
## The member's new attributes will be reflected to `guild.members`.
|
||||||
|
var modifyPayload = %*{}
|
||||||
|
|
||||||
|
if (modify.nick.isSome):
|
||||||
|
modifyPayload.add("nick", %modify.nick.get())
|
||||||
|
|
||||||
|
if (modify.roles.isSome):
|
||||||
|
# Convert the roles array to a string representation and remove the `@`
|
||||||
|
# that is at the front of a conversion like this.
|
||||||
|
var rolesStr = ($modify.roles.get()).substr(1)
|
||||||
|
modifyPayload.add(parseJson(rolesStr))
|
||||||
|
|
||||||
|
if (modify.mute.isSome):
|
||||||
|
modifyPayload.add("mute", %modify.mute.get())
|
||||||
|
|
||||||
|
if (modify.deaf.isSome):
|
||||||
|
modifyPayload.add("deaf", %modify.deaf.get())
|
||||||
|
|
||||||
|
if (modify.channelID.isSome):
|
||||||
|
modifyPayload.add("channel_id", %modify.channelID.get())
|
||||||
|
|
||||||
|
discard sendRequest(endpoint(fmt("/guilds/{member.guildID}/members/{member.id}")), HttpPatch,
|
||||||
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
|
member.guildID, RateLimitBucketType.guild, modifyPayload)
|
||||||
|
|
||||||
|
proc addGuildMemberRole*(member: GuildMember, roleID: snowflake) {.async.} =
|
||||||
|
## Adds a role to a guild member. Requires the `MANAGE_ROLES` permission.
|
||||||
|
discard sendRequest(endpoint(fmt("/guilds/{member.guildID}/members/{member.id}/roles/{roleID}")),
|
||||||
|
HttpPut, defaultHeaders(), member.guildID, RateLimitBucketType.guild)
|
||||||
|
|
||||||
|
proc removeGuildMemberRole*(member: GuildMember, roleID: snowflake) {.async.} =
|
||||||
|
## 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}")),
|
||||||
|
HttpDelete, defaultHeaders(), member.guildID, RateLimitBucketType.guild)
|
|
@ -94,7 +94,7 @@ proc newMessage*(messageJson: JsonNode): Message =
|
||||||
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.member = newGuildMember(messageJson["member"], msg.guildID)
|
||||||
|
|
||||||
if (messageJson.contains("mentions")):
|
if (messageJson.contains("mentions")):
|
||||||
let mentionsJson = messageJson["mentions"].getElems()
|
let mentionsJson = messageJson["mentions"].getElems()
|
||||||
|
|
38
src/role.nim
38
src/role.nim
|
@ -1,4 +1,4 @@
|
||||||
import json, nimcordutils, discordobject, permission
|
import json, nimcordutils, discordobject, permission, options, httpcore, asyncdispatch, strformat
|
||||||
|
|
||||||
type Role* = ref object of DiscordObject
|
type Role* = ref object of DiscordObject
|
||||||
name*: string
|
name*: string
|
||||||
|
@ -24,3 +24,39 @@ proc newRole*(json: JsonNode, guild: snowflake): Role =
|
||||||
uint(json["permissions"].getInt()))
|
uint(json["permissions"].getInt()))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
proc modifyGuildRole*(role: var Role, name: Option[string] = none(string), permissions: Option[Permissions] = none(Permissions),
|
||||||
|
color: Option[int] = none(int), hoist: Option[bool] = none(bool), mentionable: Option[bool] = none(bool)): Future[Role] {.async.} =
|
||||||
|
## Modify a guild role. Requires the `MANAGE_ROLES` permission.
|
||||||
|
## The changes will reflect on the `role` object you supplied.
|
||||||
|
##
|
||||||
|
## Example:
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
## discard role.modifyGuildRole(name = some("Gamer Role"), color = some(0xff0000))
|
||||||
|
|
||||||
|
var jsonBody: JsonNode
|
||||||
|
|
||||||
|
if (name.isSome):
|
||||||
|
jsonBody.add("name", %name)
|
||||||
|
|
||||||
|
if (permissions.isSome):
|
||||||
|
jsonBody.add("permissions", %permissions.get().allowPerms)
|
||||||
|
|
||||||
|
if (color.isSome):
|
||||||
|
jsonBody.add("color", %color)
|
||||||
|
|
||||||
|
if (hoist.isSome):
|
||||||
|
jsonBody.add("hoist", %hoist)
|
||||||
|
|
||||||
|
if (mentionable.isSome):
|
||||||
|
jsonBody.add("mentionable", %mentionable)
|
||||||
|
|
||||||
|
result = newRole(sendRequest(endpoint(fmt("/guilds/{role.guildID}/roles/{role.id}")), HttpPatch,
|
||||||
|
defaultHeaders(newHttpHeaders({"Content-Type": "application/json"})),
|
||||||
|
role.guildID, RateLimitBucketType.guild, jsonBody), role.guildID)
|
||||||
|
role = result
|
||||||
|
|
||||||
|
proc deleteGuildRole*(role: Role) {.async.} =
|
||||||
|
## Delete a guild role. Requires the `MANAGE_ROLES` permission.
|
||||||
|
discard sendRequest(endpoint(fmt("/guilds/{role.guildID}/roles/{role.id}")), HttpDelete,
|
||||||
|
defaultHeaders(), role.guildID, RateLimitBucketType.guild)
|
Reference in New Issue