Add a command handler
This commit is contained in:
parent
43b6959805
commit
4d2ebd211d
|
@ -8,63 +8,50 @@ if (not isNil(tokenStream)):
|
|||
|
||||
tokenStream.close()
|
||||
|
||||
var bot = newDiscordClient(tkn)
|
||||
var bot = newDiscordClient(tkn, "?")
|
||||
|
||||
registerEventListener(EventType.evtReady, proc(bEvt: BaseEvent) =
|
||||
let event = ReadyEvent(bEvt)
|
||||
|
||||
echo "Ready! (v", 0, ".", 0, ".", 1, ")"
|
||||
echo "Logged in as: ", bot.clientUser.username, "#", bot.clientUser.discriminator
|
||||
echo "ID: ", bot.clientUser.id
|
||||
echo "--------------------"
|
||||
|
||||
let presence = newPresence("with Nimcord", activityTypeGame, clientStatusIdle, false)
|
||||
asyncCheck event.shard.updateClientPresence(presence)
|
||||
let pingCommand = Command(name: "ping", commandBody: proc(ctx: CommandContext) =
|
||||
discard ctx.channel.sendMessage("PONG")
|
||||
)
|
||||
|
||||
registerEventListener(EventType.evtMessageCreate, proc(bEvt: BaseEvent) =
|
||||
let event = MessageCreateEvent(bEvt)
|
||||
let modifyChannelTopicCommand = Command(name: "modifyChannelTopic", commandBody: proc(ctx: CommandContext) =
|
||||
let modifyTopic = ctx.message.content.substr(20)
|
||||
|
||||
if (event.message.content == "?ping"):
|
||||
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
||||
if (channel != nil):
|
||||
discard channel.sendMessage("PONG")
|
||||
elif (event.message.content.startsWith("?modifyChannelTopic")):
|
||||
let modifyTopic = event.message.content.substr(20)
|
||||
discard ctx.channel.sendMessage("Modifing Channel!")
|
||||
discard ctx.channel.modifyChannel(ChannelFields(topic: some(modifyTopic)))
|
||||
)
|
||||
|
||||
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)
|
||||
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 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):
|
||||
discard ctx.channel.sendMessage("Deleted Channel!")
|
||||
)
|
||||
|
||||
let bulkDeleteMessagesCommand = Command(name: "bulkDeleteMessages", commandBody: proc(ctx: CommandContext) =
|
||||
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):
|
||||
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 event.message.addReaction(emoji)
|
||||
elif (event.message.content.startsWith("?testEmbed")):
|
||||
var channel: Channel = event.message.getMessageChannel(event.shard.client.cache)
|
||||
if (channel != nil):
|
||||
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.")
|
||||
|
@ -72,21 +59,21 @@ registerEventListener(EventType.evtMessageCreate, proc(bEvt: BaseEvent) =
|
|||
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)
|
||||
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 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)
|
||||
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
|
||||
|
@ -96,7 +83,36 @@ registerEventListener(EventType.evtMessageCreate, proc(bEvt: BaseEvent) =
|
|||
var embed = Embed()
|
||||
embed.setTitle("Image attachment test.")
|
||||
embed.setImage("attachment://" & fileName)
|
||||
discard channel.sendMessage("", false, embed, @[file])
|
||||
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) =
|
||||
# Cast the BaseEvent to the ReadyEvent which is what we're listening to.
|
||||
let event = ReadyEvent(bEvt)
|
||||
|
||||
echo "Ready! (v", 0, ".", 0, ".", 1, ")"
|
||||
echo "Logged in as: ", bot.clientUser.username, "#", bot.clientUser.discriminator
|
||||
echo "ID: ", bot.clientUser.id
|
||||
echo "--------------------"
|
||||
|
||||
let presence = newPresence("with Nimcord", activityTypeGame, clientStatusIdle, false)
|
||||
asyncCheck event.shard.updateClientPresence(presence)
|
||||
|
||||
# Register commands. You don't need to register them in EventReady.
|
||||
registerCommand(pingCommand)
|
||||
registerCommand(modifyChannelTopicCommand)
|
||||
registerCommand(deleteChannelCommand)
|
||||
registerCommand(bulkDeleteMessagesCommand)
|
||||
registerCommand(reactToMessageCommand)
|
||||
registerCommand(testEmbedCommand)
|
||||
registerCommand(sendFileCommand)
|
||||
registerCommand(sendImageCommand)
|
||||
)
|
||||
|
||||
waitFor bot.startConnection()
|
|
@ -16,11 +16,11 @@
|
|||
import nimcord/[cache, channel, client, clientobjects, discordobject]
|
||||
import nimcord/[embed, emoji, eventdispatcher, eventhandler, guild]
|
||||
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 embed, emoji, eventdispatcher, eventhandler, guild
|
||||
export image, member, message, nimcordutils, permission
|
||||
export presence, role, user
|
||||
export presence, role, user, commandsystem
|
||||
|
||||
const NimCordVersion = "v0.0.1"
|
|
@ -247,7 +247,7 @@ proc updateClientPresence*(shard: Shard, presence: Presence) {.async.} =
|
|||
|
||||
await shard.sendGatewayRequest(jsonPayload)
|
||||
|
||||
proc newDiscordClient*(tkn: string): DiscordClient =
|
||||
proc newDiscordClient*(tkn: string, commandPrefix: string): DiscordClient =
|
||||
## Create a DiscordClient using a token.
|
||||
##
|
||||
## Sets globalDiscordClient to the newly created client.
|
||||
|
@ -256,4 +256,4 @@ proc newDiscordClient*(tkn: string): DiscordClient =
|
|||
var cac: Cache
|
||||
new(cac)
|
||||
|
||||
result = DiscordClient(token: tkn, cache: cac)
|
||||
result = DiscordClient(token: tkn, cache: cac, commandPrefix: commandPrefix)
|
|
@ -9,6 +9,7 @@ type
|
|||
shards*: seq[Shard]
|
||||
shardCount*: int
|
||||
endpoint*: string
|
||||
commandPrefix*: string
|
||||
|
||||
Shard* = ref object
|
||||
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 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) =
|
||||
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
|
||||
|
||||
let messageCreateEvnt = MessageCreateEvent(shard: shard, message: msg, name: $EventType.evtMessageCreate)
|
||||
|
||||
|
||||
shard.client.fireCommand(msg) # Fire a command
|
||||
dispatchEvent(messageCreateEvnt)
|
||||
|
||||
proc messageUpdateEvent(shard: Shard, json: JsonNode) =
|
||||
|
|
Reference in New Issue