Add a command handler
This commit is contained in:
parent
43b6959805
commit
4d2ebd211d
|
@ -8,10 +8,93 @@ if (not isNil(tokenStream)):
|
||||||
|
|
||||||
tokenStream.close()
|
tokenStream.close()
|
||||||
|
|
||||||
var bot = newDiscordClient(tkn)
|
var bot = newDiscordClient(tkn, "?")
|
||||||
|
|
||||||
|
let pingCommand = Command(name: "ping", commandBody: proc(ctx: CommandContext) =
|
||||||
|
discard ctx.channel.sendMessage("PONG")
|
||||||
|
)
|
||||||
|
|
||||||
|
let modifyChannelTopicCommand = Command(name: "modifyChannelTopic", commandBody: proc(ctx: CommandContext) =
|
||||||
|
let modifyTopic = ctx.message.content.substr(20)
|
||||||
|
|
||||||
|
discard ctx.channel.sendMessage("Modifing Channel!")
|
||||||
|
discard ctx.channel.modifyChannel(ChannelFields(topic: some(modifyTopic)))
|
||||||
|
)
|
||||||
|
|
||||||
|
let deleteChannelCommand = Command(name: "deleteChannel", commandBody: proc(ctx: CommandContext) =
|
||||||
|
let channelID = getIDFromJson(ctx.arguments[0])
|
||||||
|
var channel: Channel = ctx.client.cache.getChannel(channelID)
|
||||||
|
|
||||||
|
# Check if we could find the channel to delete
|
||||||
|
if (channel != nil):
|
||||||
|
discard channel.sendMessage("Deleting Channel!")
|
||||||
|
discard channel.deleteChannel()
|
||||||
|
discard ctx.channel.sendMessage("Deleted Channel!")
|
||||||
|
)
|
||||||
|
|
||||||
|
let bulkDeleteMessagesCommand = Command(name: "bulkDeleteMessages", commandBody: proc(ctx: CommandContext) =
|
||||||
|
var amount: int = 25
|
||||||
|
if (ctx.message.content.len > 19):
|
||||||
|
amount = parseIntEasy(ctx.arguments[0])
|
||||||
|
|
||||||
|
# Get the message to delete, then delete them.
|
||||||
|
let messages = ctx.channel.getMessages(MessagesGetRequest(limit: some(amount), before: some(ctx.message.id)))
|
||||||
|
discard ctx.channel.bulkDeleteMessages(messages)
|
||||||
|
|
||||||
|
# Delete the message that was used to run this command.
|
||||||
|
discard ctx.message.deleteMessage()
|
||||||
|
)
|
||||||
|
|
||||||
|
let reactToMessageCommand = Command(name: "reactToMessage", commandBody: proc(ctx: CommandContext) =
|
||||||
|
let emojis = @[newEmoji("⏮️"), newEmoji("⬅️"), newEmoji("⏹️"), newEmoji("➡️"), newEmoji("⏭️")]
|
||||||
|
for emoji in emojis:
|
||||||
|
discard ctx.message.addReaction(emoji)
|
||||||
|
)
|
||||||
|
|
||||||
|
let testEmbedCommand = Command(name: "testEmbed", commandBody: proc(ctx: CommandContext) =
|
||||||
|
var embed = Embed()
|
||||||
|
embed.setTitle("This embed is being sent from Nimcord!")
|
||||||
|
embed.setDescription("Nimcord was developed in about a week of actual work so there will likely be issues.")
|
||||||
|
embed.addField("Title", "value")
|
||||||
|
embed.addField("Inline-0", "This is an inline field 0", true)
|
||||||
|
embed.addField("Inline-1", "This is an inline field 1", true)
|
||||||
|
embed.setColor(0xffb900)
|
||||||
|
discard ctx.channel.sendMessage("", false, embed)
|
||||||
|
)
|
||||||
|
|
||||||
|
let sendFileCommand = Command(name: "sendFile", commandBody: proc(ctx: CommandContext) =
|
||||||
|
let filePath = ctx.message.content.substr(10)
|
||||||
|
|
||||||
|
let splitFile = splitFile(filePath)
|
||||||
|
let fileName = splitFile.name & splitFile.ext
|
||||||
|
|
||||||
|
let file = DiscordFile(filePath: filePath, fileName: fileName)
|
||||||
|
discard ctx.channel.sendMessage("", false, nil, @[file])
|
||||||
|
)
|
||||||
|
|
||||||
|
let sendImageCommand = Command(name: "sendImage", commandBody: proc(ctx: CommandContext) =
|
||||||
|
let filePath = ctx.message.content.substr(11)
|
||||||
|
|
||||||
|
let splitFile = splitFile(filePath)
|
||||||
|
let fileName = splitFile.name & splitFile.ext
|
||||||
|
|
||||||
|
let file = DiscordFile(filePath: filePath, fileName: fileName)
|
||||||
|
|
||||||
|
var embed = Embed()
|
||||||
|
embed.setTitle("Image attachment test.")
|
||||||
|
embed.setImage("attachment://" & fileName)
|
||||||
|
discard ctx.channel.sendMessage("", false, embed, @[file])
|
||||||
|
)
|
||||||
|
|
||||||
|
# You can even register commands like this:
|
||||||
|
registerCommand(Command(name: "ping2", commandBody: proc(ctx: CommandContext) =
|
||||||
|
discard ctx.channel.sendMessage("PONG3")
|
||||||
|
))
|
||||||
|
|
||||||
|
# Listen for the ready event.
|
||||||
registerEventListener(EventType.evtReady, proc(bEvt: BaseEvent) =
|
registerEventListener(EventType.evtReady, proc(bEvt: BaseEvent) =
|
||||||
let event = ReadyEvent(bEvt)
|
# Cast the BaseEvent to the ReadyEvent which is what we're listening to.
|
||||||
|
let event = ReadyEvent(bEvt)
|
||||||
|
|
||||||
echo "Ready! (v", 0, ".", 0, ".", 1, ")"
|
echo "Ready! (v", 0, ".", 0, ".", 1, ")"
|
||||||
echo "Logged in as: ", bot.clientUser.username, "#", bot.clientUser.discriminator
|
echo "Logged in as: ", bot.clientUser.username, "#", bot.clientUser.discriminator
|
||||||
|
@ -20,83 +103,16 @@ registerEventListener(EventType.evtReady, proc(bEvt: BaseEvent) =
|
||||||
|
|
||||||
let presence = newPresence("with Nimcord", activityTypeGame, clientStatusIdle, false)
|
let presence = newPresence("with Nimcord", activityTypeGame, clientStatusIdle, false)
|
||||||
asyncCheck event.shard.updateClientPresence(presence)
|
asyncCheck event.shard.updateClientPresence(presence)
|
||||||
)
|
|
||||||
|
|
||||||
registerEventListener(EventType.evtMessageCreate, proc(bEvt: BaseEvent) =
|
# Register commands. You don't need to register them in EventReady.
|
||||||
let event = MessageCreateEvent(bEvt)
|
registerCommand(pingCommand)
|
||||||
|
registerCommand(modifyChannelTopicCommand)
|
||||||
if (event.message.content == "?ping"):
|
registerCommand(deleteChannelCommand)
|
||||||
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
registerCommand(bulkDeleteMessagesCommand)
|
||||||
if (channel != nil):
|
registerCommand(reactToMessageCommand)
|
||||||
discard channel.sendMessage("PONG")
|
registerCommand(testEmbedCommand)
|
||||||
elif (event.message.content.startsWith("?modifyChannelTopic")):
|
registerCommand(sendFileCommand)
|
||||||
let modifyTopic = event.message.content.substr(20)
|
registerCommand(sendImageCommand)
|
||||||
|
|
||||||
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
|
||||||
if (channel != nil):
|
|
||||||
discard channel.sendMessage("Modifing Channel!")
|
|
||||||
discard channel.modifyChannel(ChannelFields(topic: some(modifyTopic)))
|
|
||||||
elif (event.message.content.startsWith("?deleteChannel")):
|
|
||||||
let channelID = getIDFromJson(event.message.content.substr(15))
|
|
||||||
var channel: Channel = event.shard.client.cache.getChannel(channelID)
|
|
||||||
|
|
||||||
if (channel != nil):
|
|
||||||
discard channel.sendMessage("Deleting Channel!")
|
|
||||||
discard channel.deleteChannel()
|
|
||||||
discard channel.sendMessage("Deleted Channel!")
|
|
||||||
elif (event.message.content.startsWith("?getMessages")):
|
|
||||||
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
|
||||||
if (channel != nil):
|
|
||||||
discard channel.getMessages(MessagesGetRequest(limit: some(15), before: some(event.message.id)))
|
|
||||||
elif (event.message.content.startsWith("?bulkDeleteMessages")):
|
|
||||||
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
|
||||||
if (channel != nil):
|
|
||||||
var amount: int = 25
|
|
||||||
if (event.message.content.len > 19):
|
|
||||||
amount = parseIntEasy(event.message.content.substr(20))
|
|
||||||
let messages = channel.getMessages(MessagesGetRequest(limit: some(amount), before: some(event.message.id)))
|
|
||||||
discard channel.bulkDeleteMessages(messages)
|
|
||||||
elif (event.message.content.startsWith("?reactToMessage")):
|
|
||||||
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
|
||||||
if (channel != nil):
|
|
||||||
let emojis = @[newEmoji("⏮️"), newEmoji("⬅️"), newEmoji("⏹️"), newEmoji("➡️"), newEmoji("⏭️")]
|
|
||||||
for emoji in emojis:
|
|
||||||
discard event.message.addReaction(emoji)
|
|
||||||
elif (event.message.content.startsWith("?testEmbed")):
|
|
||||||
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
|
||||||
if (channel != nil):
|
|
||||||
var embed = Embed()
|
|
||||||
embed.setTitle("This embed is being sent from Nimcord!")
|
|
||||||
embed.setDescription("Nimcord was developed in about a week of actual work so there will likely be issues.")
|
|
||||||
embed.addField("Title", "value")
|
|
||||||
embed.addField("Inline-0", "This is an inline field 0", true)
|
|
||||||
embed.addField("Inline-1", "This is an inline field 1", true)
|
|
||||||
embed.setColor(0xffb900)
|
|
||||||
discard channel.sendMessage("", false, embed)
|
|
||||||
elif (event.message.content.startsWith("?sendFile")):
|
|
||||||
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
|
||||||
if (channel != nil):
|
|
||||||
let filePath = event.message.content.substr(10)
|
|
||||||
|
|
||||||
let splitFile = splitFile(filePath)
|
|
||||||
let fileName = splitFile.name & splitFile.ext
|
|
||||||
|
|
||||||
let file = DiscordFile(filePath: filePath, fileName: fileName)
|
|
||||||
discard channel.sendMessage("", false, nil, @[file])
|
|
||||||
elif (event.message.content.startsWith("?sendImage")):
|
|
||||||
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
|
||||||
if (channel != nil):
|
|
||||||
let filePath = event.message.content.substr(11)
|
|
||||||
|
|
||||||
let splitFile = splitFile(filePath)
|
|
||||||
let fileName = splitFile.name & splitFile.ext
|
|
||||||
|
|
||||||
let file = DiscordFile(filePath: filePath, fileName: fileName)
|
|
||||||
|
|
||||||
var embed = Embed()
|
|
||||||
embed.setTitle("Image attachment test.")
|
|
||||||
embed.setImage("attachment://" & fileName)
|
|
||||||
discard channel.sendMessage("", false, embed, @[file])
|
|
||||||
)
|
)
|
||||||
|
|
||||||
waitFor bot.startConnection()
|
waitFor bot.startConnection()
|
|
@ -16,11 +16,11 @@
|
||||||
import nimcord/[cache, channel, client, clientobjects, discordobject]
|
import nimcord/[cache, channel, client, clientobjects, discordobject]
|
||||||
import nimcord/[embed, emoji, eventdispatcher, eventhandler, guild]
|
import nimcord/[embed, emoji, eventdispatcher, eventhandler, guild]
|
||||||
import nimcord/[image, member, message, nimcordutils, permission]
|
import nimcord/[image, member, message, nimcordutils, permission]
|
||||||
import nimcord/[presence, role, user]
|
import nimcord/[presence, role, user, commandsystem]
|
||||||
|
|
||||||
export cache, channel, client, clientobjects, discordobject
|
export cache, channel, client, clientobjects, discordobject
|
||||||
export embed, emoji, eventdispatcher, eventhandler, guild
|
export embed, emoji, eventdispatcher, eventhandler, guild
|
||||||
export image, member, message, nimcordutils, permission
|
export image, member, message, nimcordutils, permission
|
||||||
export presence, role, user
|
export presence, role, user, commandsystem
|
||||||
|
|
||||||
const NimCordVersion = "v0.0.1"
|
const NimCordVersion = "v0.0.1"
|
|
@ -247,7 +247,7 @@ proc updateClientPresence*(shard: Shard, presence: Presence) {.async.} =
|
||||||
|
|
||||||
await shard.sendGatewayRequest(jsonPayload)
|
await shard.sendGatewayRequest(jsonPayload)
|
||||||
|
|
||||||
proc newDiscordClient*(tkn: string): DiscordClient =
|
proc newDiscordClient*(tkn: string, commandPrefix: string): DiscordClient =
|
||||||
## Create a DiscordClient using a token.
|
## Create a DiscordClient using a token.
|
||||||
##
|
##
|
||||||
## Sets globalDiscordClient to the newly created client.
|
## Sets globalDiscordClient to the newly created client.
|
||||||
|
@ -256,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, commandPrefix: commandPrefix)
|
|
@ -9,6 +9,7 @@ type
|
||||||
shards*: seq[Shard]
|
shards*: seq[Shard]
|
||||||
shardCount*: int
|
shardCount*: int
|
||||||
endpoint*: string
|
endpoint*: string
|
||||||
|
commandPrefix*: string
|
||||||
|
|
||||||
Shard* = ref object
|
Shard* = ref object
|
||||||
id*: int
|
id*: int
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
import tables, message, member, user, channel, strutils, clientobjects, cache
|
||||||
|
|
||||||
|
type
|
||||||
|
CommandContext* = ref object of RootObj
|
||||||
|
## Object to make it easier to create commands.
|
||||||
|
message*: Message ## The message that ran the command
|
||||||
|
channel*: Channel ## The channel that this command was ran in.
|
||||||
|
author*: GuildMember ## The GuildMember that ran the command.
|
||||||
|
user*: User ## The user who ran the command.
|
||||||
|
arguments*: seq[string] ## The command arguments.
|
||||||
|
client*: DiscordClient ## The DiscordClient.
|
||||||
|
|
||||||
|
Command* = ref object of RootObj
|
||||||
|
## Command object.
|
||||||
|
name*: string ## The name of the command.
|
||||||
|
commandBody*: proc(ctx: CommandContext) ## The command body of the command.
|
||||||
|
commandRequirements*: proc(ctx: CommandContext): bool ## The requirements of the command,
|
||||||
|
## ran before commandBody to check if
|
||||||
|
## the command can run.
|
||||||
|
|
||||||
|
# Table storing all the commands
|
||||||
|
let registeredCommands = newTable[string, Command]()
|
||||||
|
|
||||||
|
proc registerCommand*(command: Command) =
|
||||||
|
## Register a Command.
|
||||||
|
##
|
||||||
|
## Examples:
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
## registerCommand(Command(name: "ping", commandBody: proc(ctx: CommandContext) =
|
||||||
|
## discard ctx.channel.sendMessage("PONG")
|
||||||
|
## ))
|
||||||
|
registeredCommands.add(command.name, command)
|
||||||
|
|
||||||
|
proc fireCommand*(client: DiscordClient, message: Message) =
|
||||||
|
## Fire a command. This is already called by Nimcord. Not any need to call this.
|
||||||
|
|
||||||
|
# If the message doesn't start with the prefix, then
|
||||||
|
# it probably isn't a commnand.
|
||||||
|
if not message.content.startsWith(client.commandPrefix):
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get the arguments for the command
|
||||||
|
var arguments: seq[string] = message.content.split(" ")
|
||||||
|
|
||||||
|
# Extract the command name from arguments
|
||||||
|
let commandName = arguments[0].substr(1)
|
||||||
|
arguments.del(0)
|
||||||
|
|
||||||
|
## Dispatches an event so something can listen to it.
|
||||||
|
if (registeredCommands.hasKey(commandName)):
|
||||||
|
let commandContext = CommandContext(message: message, channel: message.getMessageChannel(client.cache),
|
||||||
|
author: message.member, user: message.author, arguments: arguments, client: client)
|
||||||
|
|
||||||
|
let command = registeredCommands[commandName]
|
||||||
|
if command.commandRequirements != nil:
|
||||||
|
if command.commandRequirements(commandContext):
|
||||||
|
command.commandBody(commandContext)
|
||||||
|
else:
|
||||||
|
command.commandBody(commandContext)
|
|
@ -1,6 +1,7 @@
|
||||||
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 asyncdispatch, clientobjects, discordobject, presence
|
import sequtils, asyncdispatch, clientobjects, discordobject, presence
|
||||||
|
import commandsystem
|
||||||
|
|
||||||
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)
|
||||||
|
@ -275,6 +276,9 @@ proc messageCreateEvent(shard: Shard, json: JsonNode) =
|
||||||
shard.client.cache.messages[msg.id] = msg
|
shard.client.cache.messages[msg.id] = msg
|
||||||
|
|
||||||
let messageCreateEvnt = MessageCreateEvent(shard: shard, message: msg, name: $EventType.evtMessageCreate)
|
let messageCreateEvnt = MessageCreateEvent(shard: shard, message: msg, name: $EventType.evtMessageCreate)
|
||||||
|
|
||||||
|
|
||||||
|
shard.client.fireCommand(msg) # Fire a command
|
||||||
dispatchEvent(messageCreateEvnt)
|
dispatchEvent(messageCreateEvnt)
|
||||||
|
|
||||||
proc messageUpdateEvent(shard: Shard, json: JsonNode) =
|
proc messageUpdateEvent(shard: Shard, json: JsonNode) =
|
||||||
|
|
Reference in New Issue