Browse Source

Add macro command

master
Graham Littlewood 4 years ago
parent
commit
a8b1fbd3b7
3 changed files with 90 additions and 16 deletions
  1. +74
    -8
      src/commands/cmd_macro.rs
  2. +15
    -7
      src/main.rs
  3. +1
    -1
      src/traits/command.rs

+ 74
- 8
src/commands/cmd_macro.rs View File

@@ -8,28 +8,94 @@ use serenity::{
extern crate json;

extern crate regex;
use regex::Regex;
use regex::{Regex, Match};

use core::option::Option;
use std::collections::HashMap;
use std::string::String;

use crate::traits::Command;

pub struct CmdMacro {}
pub struct CmdMacro {
format: Regex,
macros: HashMap<String, String>
}

impl Command for CmdMacro {
fn execute(&self, ctx: &Context, msg: &Message) {

fn execute(& mut self, ctx: &Context, msg: &Message) {
if let Some(parsed) = self.format.captures(&msg.content) {
if let Some(op) = parsed.get(1) {
let mut response = MessageBuilder::new();
if op.as_str().to_string().to_lowercase() == "add" {
if self.add(parsed.get(2), parsed.get(3)) {
response.push("Successfully added macro.");
} else {
response.push("Missing macro argument or macro already exists.");
}
} else if op.as_str().to_string().to_lowercase() == "remove" {
if self.remove(parsed.get(2)) {
response.push("Successfully removed macro.");
} else {
response.push("Macro does not exist.");
}
} else {
response.push(self.get(&op.as_str().to_string()));
}
if let Err(why) = msg.channel_id.say(&ctx.http, &response.build()) {
println!("Failed to send macro message {:?}", why);
}
return;
}
}
let response = MessageBuilder::new()
.push("Hello World")
.push("Unexpected failure.")
.build();
msg.channel_id.say(&ctx.http, &response);
if let Err(why) = msg.channel_id.say(&ctx.http, &response) {
println!("Failed to send macro failure message {:?}", why);
}
}

fn valid(&self, ctx: &Context, msg: &Message) -> bool {
return msg.content == "macro";
return self.format.is_match(&msg.content);
}
}

impl CmdMacro {
pub fn new() -> CmdMacro{
return CmdMacro{};
return CmdMacro {
format:
Regex::new(r#"^!macro\s+([A-Za-z0-9]+|"[^\s]+"|'[^\s]+')(?:\s+([A-Za-z0-9]+|"[^\s]+"|'[^\s]+')\s+(.+))?"#)
.unwrap(),
macros: HashMap::<String, String>::new(), // TODO: load map from JSON
};
}

fn add<'t>(&mut self, key: Option<Match<'t>>, value: Option<Match<'t>>) -> bool {
let rk; let rv;
if let Some(k) = key {
rk = k;
if self.macros.get(&key.to_owned()).is_some() {
return false;
}
} else {return false;}
if let Some(v) = value {
rv = v;
} else {return false;}
self.macros.insert(rk.as_str().to_string(), rv.as_str().to_string());
return true;
}

fn remove<'t>(&mut self, key: Option<Match<'t>>) -> bool {
match key {
Some(k) => return self.macros.remove(&k.as_str().to_string()).is_some(),
None => return false,
}
}

fn get(&self, key: &String) -> String {
if let Some(s) = self.macros.get(&key.to_owned()) {
return s.to_string();
}
return "Invalid macro".to_string();
}
}

+ 15
- 7
src/main.rs View File

@@ -15,16 +15,23 @@ mod traits;
mod commands;

//use crate::traits::Command;
struct CommandsKey;

impl TypeMapKey for CommandsKey {
type Value = std::vec::Vec<Box<dyn traits::Command>>;
}

struct Handler {
pub commands: std::vec::Vec<Box<dyn traits::Command>>,
}

impl EventHandler for Handler {
fn message(&self, ctx: Context, msg: Message) {
fn message(& self, ctx: Context, msg: Message) {
let mut data = ctx.data.write();
let commands = data.get_mut::<CommandsKey>().unwrap();
// handle messages
let mut count = 0;
for cmd in self.commands.iter() {
for cmd in commands.iter_mut() {
if cmd.valid(&ctx, &msg) {
count+=1;
cmd.execute(&ctx, &msg);
@@ -45,10 +52,6 @@ impl Handler {
commands: std::vec::Vec::new(),
};
}

pub fn add_command(&mut self, box_cmd: Box<dyn traits::Command>) {
self.commands.push(box_cmd);
}
}

fn main() {
@@ -57,9 +60,14 @@ fn main() {
.expect("Expected a Discord API token in DISCORD_TOKEN environment variable");
let mut event_handler = Handler::new();
// register commands;
event_handler.add_command(Box::new(commands::CmdMacro::new()));
let mut commands = std::vec::Vec::<Box<dyn traits::Command>>::new();
commands.push(Box::new(commands::CmdMacro::new()));
// start bot
let mut client = Client::new(&token, event_handler).expect("Error creating client");
{
let mut data = client.data.write();
data.insert::<CommandsKey>(commands);
}
if let Err(why) = client.start() {
println!("Client error: {:?}", why);
}


+ 1
- 1
src/traits/command.rs View File

@@ -5,6 +5,6 @@ use serenity::{
};

pub trait Command: std::marker::Sync + std::marker::Send {
fn execute(&self, ctx: &Context, msg: &Message);
fn execute(& mut self, ctx: &Context, msg: &Message);
fn valid(&self, ctx: &Context, msg: &Message) -> bool;
}