|
|
@@ -5,7 +5,9 @@ use serenity::{ |
|
|
|
utils::MessageBuilder, |
|
|
|
}; |
|
|
|
|
|
|
|
extern crate json; |
|
|
|
extern crate serde_json; |
|
|
|
//use serde::{Deserialize, Serialize}; |
|
|
|
use serde_json::Result; |
|
|
|
|
|
|
|
extern crate regex; |
|
|
|
use regex::{Regex, Match}; |
|
|
@@ -13,33 +15,44 @@ use regex::{Regex, Match}; |
|
|
|
use core::option::Option; |
|
|
|
use std::collections::HashMap; |
|
|
|
use std::string::String; |
|
|
|
use std::fs::{File, OpenOptions}; |
|
|
|
use std::io::BufReader; |
|
|
|
|
|
|
|
use crate::traits::Command; |
|
|
|
|
|
|
|
const MACRO_PATH: &str = "macros.json"; |
|
|
|
|
|
|
|
pub struct CmdMacro { |
|
|
|
format: Regex, |
|
|
|
macros: HashMap<String, String> |
|
|
|
macros: HashMap<u64,HashMap<String, String>> |
|
|
|
} |
|
|
|
|
|
|
|
impl Command for CmdMacro { |
|
|
|
fn execute(& mut self, ctx: &Context, msg: &Message) { |
|
|
|
let id: u64; |
|
|
|
match msg.guild_id { |
|
|
|
Some(g) => id = *g.as_u64(), |
|
|
|
None => id = *msg.channel_id.as_u64(), |
|
|
|
} |
|
|
|
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)) { |
|
|
|
if self.add(&id, parsed.get(2), parsed.get(3)) { |
|
|
|
response.push("Successfully added macro."); |
|
|
|
self.save_json(); |
|
|
|
} 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)) { |
|
|
|
if self.remove(&id, parsed.get(2)) { |
|
|
|
response.push("Successfully removed macro."); |
|
|
|
self.save_json(); |
|
|
|
} else { |
|
|
|
response.push("Macro does not exist."); |
|
|
|
} |
|
|
|
} else { |
|
|
|
response.push(self.get(&op.as_str().to_string())); |
|
|
|
response.push(self.get(&id, &op.as_str().to_string())); |
|
|
|
} |
|
|
|
if let Err(why) = msg.channel_id.say(&ctx.http, &response.build()) { |
|
|
|
println!("Failed to send macro message {:?}", why); |
|
|
@@ -62,40 +75,87 @@ impl Command for CmdMacro { |
|
|
|
|
|
|
|
impl CmdMacro { |
|
|
|
pub fn new() -> CmdMacro{ |
|
|
|
// load macro map from JSON |
|
|
|
let mut file = File::open(MACRO_PATH); |
|
|
|
match file { |
|
|
|
Err(why) => { |
|
|
|
file = File::create(MACRO_PATH); |
|
|
|
println!("Creating file (error {:?})", why); |
|
|
|
}, |
|
|
|
_ => (), |
|
|
|
} |
|
|
|
let reader = BufReader::new(file.unwrap()); |
|
|
|
let macros: HashMap<u64, HashMap<String, String>> = serde_json::from_reader(reader).unwrap_or(HashMap::<u64, HashMap<String, String>>::new()); |
|
|
|
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 |
|
|
|
macros: macros, |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
fn add<'t>(&mut self, key: Option<Match<'t>>, value: Option<Match<'t>>) -> bool { |
|
|
|
fn add<'t>(&mut self, id: &u64, key: Option<Match<'t>>, value: Option<Match<'t>>) -> bool { |
|
|
|
let map: &mut HashMap<String, String>; |
|
|
|
match self.macros.get_mut(id) { |
|
|
|
Some(m) => map = m, |
|
|
|
None => { |
|
|
|
self.macros.insert(*id, HashMap::new()); |
|
|
|
map = self.macros.get_mut(id).unwrap(); |
|
|
|
}, |
|
|
|
} |
|
|
|
let rk; let rv; |
|
|
|
if let Some(k) = key { |
|
|
|
rk = k; |
|
|
|
if self.macros.get(&key.to_owned()).is_some() { |
|
|
|
rk = k.as_str().trim_matches('\"').trim_matches('\'').to_string(); |
|
|
|
if map.get(&rk).is_some() { |
|
|
|
return false; |
|
|
|
} |
|
|
|
} else {return false;} |
|
|
|
if let Some(v) = value { |
|
|
|
rv = v; |
|
|
|
rv = v.as_str().to_string(); |
|
|
|
} else {return false;} |
|
|
|
self.macros.insert(rk.as_str().to_string(), rv.as_str().to_string()); |
|
|
|
map.insert(rk, rv); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
fn remove<'t>(&mut self, key: Option<Match<'t>>) -> bool { |
|
|
|
fn remove<'t>(&mut self, id: &u64, key: Option<Match<'t>>) -> bool { |
|
|
|
let map: &mut HashMap<String, String>; |
|
|
|
match self.macros.get_mut(id) { |
|
|
|
Some(m) => map = m, |
|
|
|
None => { |
|
|
|
self.macros.insert(*id, HashMap::new()); |
|
|
|
map = self.macros.get_mut(id).unwrap(); |
|
|
|
}, |
|
|
|
} |
|
|
|
match key { |
|
|
|
Some(k) => return self.macros.remove(&k.as_str().to_string()).is_some(), |
|
|
|
Some(k) => return map.remove(&k.as_str().trim_matches('\"').trim_matches('\'').to_string()).is_some(), |
|
|
|
None => return false, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fn get(&self, key: &String) -> String { |
|
|
|
if let Some(s) = self.macros.get(&key.to_owned()) { |
|
|
|
fn get(&mut self, id: &u64, key: &String) -> String { |
|
|
|
let map: &HashMap<String, String>; |
|
|
|
match self.macros.get_mut(id) { |
|
|
|
Some(m) => map = m, |
|
|
|
None => { |
|
|
|
self.macros.insert(*id, HashMap::new()); |
|
|
|
map = self.macros.get(id).unwrap(); |
|
|
|
}, |
|
|
|
} |
|
|
|
if let Some(s) = map.get(&key.to_owned()) { |
|
|
|
return s.to_string(); |
|
|
|
} |
|
|
|
return "Invalid macro".to_string(); |
|
|
|
} |
|
|
|
|
|
|
|
fn save_json(&self) { |
|
|
|
let mut file = OpenOptions::new() |
|
|
|
.write(true) |
|
|
|
.open(MACRO_PATH) |
|
|
|
.unwrap(); |
|
|
|
//let writer = BufWriter::new(file.unwrap()); |
|
|
|
match serde_json::to_writer_pretty(file, &self.macros) { |
|
|
|
Err(why) => println!("Macro saving failed ({:?})", why), |
|
|
|
Ok(_) => (), |
|
|
|
} |
|
|
|
} |
|
|
|
} |