create a dedicated Message struct and implement reply(&str) on there, since it seems to be a commonly used thing. Begin implementing helpers for command parsing.

This commit is contained in:
Adrian Malacoda 2017-02-19 05:37:56 -06:00
parent b9d5b7916c
commit 0f945ec604
9 changed files with 96 additions and 92 deletions

View File

@ -1,7 +1,7 @@
use {Channel, User};
use {Message, Channel, User};
pub enum Event {
Message { sender: User, channel: Option<Channel>, content: String },
Message { message: Message },
Join { channel: Channel },
Quit { channel: Channel }
}

6
src/helpers/command.rs Normal file
View File

@ -0,0 +1,6 @@
pub fn split_command (input: &str) -> Option<(&str, &str)> {
match input.split_whitespace().into_iter().next() {
Some(command) => { Some((command, input[command.len()..].trim())) },
None => None
}
}

View File

@ -1,13 +1 @@
use event::Event;
pub fn reply_to (event: Event, reply: &str) {
match event {
Event::Message { content: message, channel, sender } => {
match channel {
Some(channel) => channel.send(reply),
None => sender.send(reply)
}
}
_ => ()
}
}
pub mod command;

View File

@ -89,6 +89,21 @@ impl Tenquestionmarks {
}
}
pub struct Message {
content: String,
author: User,
channel: Option<Channel>
}
impl Message {
fn reply (&self, message: &str) {
match self.channel {
Some(ref channel) => channel.send(message),
None => self.author.send(message)
}
}
}
pub struct Channel {
name: String,
description: String,

View File

@ -10,9 +10,7 @@ use event;
use std::sync::Arc;
use std::sync::mpsc::Sender;
use MessageSender;
use User;
use Channel;
use {MessageSender, Message, User, Channel};
pub struct DiscordModule {
token: String,
@ -82,7 +80,13 @@ impl Module for DiscordModule {
})
};
match sender.send(Arc::new(event::Event::Message { sender: author, content: message.content, channel: Option::Some(channel) })) {
let message = Message {
author: author,
content: message.content,
channel: Some(channel)
};
match sender.send(Arc::new(event::Event::Message { message: message })) {
Err(err) => error!("Error sending message event: {:?}", err),
Ok(_) => {}
}

View File

@ -3,6 +3,8 @@ use toml::Table;
use std::sync::Arc;
use std::sync::mpsc::Receiver;
use helpers::command::split_command;
use event::Event;
pub struct EchoModule {
@ -13,7 +15,7 @@ impl EchoModule {
pub fn new (configuration: &Table) -> Box<Module> {
let prefix = configuration.get("prefix")
.and_then(|value| value.as_str())
.unwrap_or("!echo ");
.unwrap_or("!echo");
Box::new(EchoModule {
prefix: String::from(prefix)
@ -27,14 +29,15 @@ impl Module for EchoModule {
match receiver.recv() {
Ok(event) => {
match *event {
Event::Message { content: ref message, ref channel, ref sender } => {
debug!("Received message... {:?}", message);
if message.starts_with(self.prefix.as_str()) {
let substring = &message[self.prefix.chars().count()..];
match *channel {
Some(ref channel) => channel.send(substring),
None => sender.send(substring)
Event::Message { ref message } => {
debug!("Received message... {:?}", message.content);
match split_command(&message.content) {
Some((command, argument)) => {
if command == self.prefix {
message.reply(argument);
}
},
_ => {}
}
}
_ => ()

View File

@ -5,7 +5,8 @@ use std::sync::Arc;
use std::sync::mpsc::Receiver;
use event::Event;
use {Channel, User};
use {Message, Channel, User};
use helpers::command::split_command;
use pvn::Error;
use pvn::Fighter;
@ -32,46 +33,32 @@ fn split_combatants (input: &str) -> Option<(&str, &str)> {
))
}
fn split_command (input: &str) -> Option<(&str, &str)> {
match input.split_whitespace().into_iter().next() {
Some(command) => { Some((command, input[command.len()..].trim())) },
None => None
}
}
fn reply (message: &str, channel: &Option<Channel>, user: &User) {
match *channel {
Some(ref channel) => channel.send(message),
None => user.send(message)
}
}
trait PvnFighter: Fighter {
fn name (&self) -> &str;
fn print (&self, channel: &Option<Channel>, user: &User);
fn print (&self, message: &Message);
fn fight (&self, other: &PvnFighter, channel: &Option<Channel>, user: &User) {
self.print(channel, user);
other.print(channel, user);
fn fight (&self, other: &PvnFighter, message: &Message) {
self.print(message);
other.print(message);
if self.power() == other.power() {
reply("**It's a tie!**", channel, user);
message.reply("**It's a tie!**");
} else if self.power() > other.power() {
reply(&format!("**Winner: {}!**", self.name()), channel, user);
message.reply(&format!("**Winner: {}!**", self.name()));
} else {
reply(&format!("**Winner: {}!**", other.name()), channel, user);
message.reply(&format!("**Winner: {}!**", other.name()));
}
}
}
impl PvnFighter for Pirate {
fn print (&self, channel: &Option<Channel>, user: &User) {
reply(&format!("**{}**", self.name), channel, user);
reply(&format!("Swashbuckling: {}", self.swashbuckling), channel, user);
reply(&format!("Drunkenness: {}", self.drunkenness), channel, user);
reply(&format!("Booty: {}", self.booty), channel, user);
reply(&format!("Weapons: {}", self.weapons.join(", ")), channel, user);
reply(&format!("**TOTAL POWER: {}**", self.power()), channel, user);
fn print (&self, message: &Message) {
message.reply(&format!("**{}**", self.name));
message.reply(&format!("Swashbuckling: {}", self.swashbuckling));
message.reply(&format!("Drunkenness: {}", self.drunkenness));
message.reply(&format!("Booty: {}", self.booty));
message.reply(&format!("Weapons: {}", self.weapons.join(", ")));
message.reply(&format!("**TOTAL POWER: {}**", self.power()));
}
fn name (&self) -> &str {
@ -80,13 +67,13 @@ impl PvnFighter for Pirate {
}
impl PvnFighter for Ninja {
fn print (&self, channel: &Option<Channel>, user: &User) {
reply(&format!("**{}**", self.name), channel, user);
reply(&format!("Sneakiness: {}", self.sneakiness), channel, user);
reply(&format!("Pajamas: {}", self.pajamas), channel, user);
reply(&format!("Pointy Things: {}", self.pointy_things), channel, user);
reply(&format!("Weapons: {}", self.weapons.join(", ")), channel, user);
reply(&format!("**TOTAL POWER: {}**", self.power()), channel, user);
fn print (&self, message: &Message) {
message.reply(&format!("**{}**", self.name));
message.reply(&format!("Sneakiness: {}", self.sneakiness));
message.reply(&format!("Pajamas: {}", self.pajamas));
message.reply(&format!("Pointy Things: {}", self.pointy_things));
message.reply(&format!("Weapons: {}", self.weapons.join(", ")));
message.reply(&format!("**TOTAL POWER: {}**", self.power()));
}
fn name (&self) -> &str {
@ -100,14 +87,14 @@ struct PirateVsNinja {
}
impl PirateVsNinja {
fn pvn_command (&mut self, argument: &str, channel: &Option<Channel>, user: &User) {
fn pvn_command (&mut self, argument: &str, message: &Message) {
match split_combatants(argument) {
Some((pirate_name, ninja_name)) => {
match self.pirates.get(pirate_name) {
Ok(pirate) => {
match self.ninjas.get(ninja_name) {
Ok(ninja) => {
pirate.fight(ninja, channel, user);
pirate.fight(ninja, message);
},
Err(error) => {
error!("Error getting ninja: {:?}", error);
@ -120,15 +107,15 @@ impl PirateVsNinja {
}
},
None => {
reply("Expected two arguments of the form: {pirate} | {ninja}", channel, user);
message.reply("Expected two arguments of the form: {pirate} | {ninja}");
}
}
}
fn pirate_command (&mut self, name: &str, channel: &Option<Channel>, user: &User) {
fn pirate_command (&mut self, name: &str, message: &Message) {
match self.pirates.get(name) {
Ok(pirate) => {
pirate.print(channel, user);
pirate.print(message);
},
Err(error) => {
error!("Error getting pirate: {:?}", error);
@ -136,10 +123,10 @@ impl PirateVsNinja {
}
}
fn ninja_command (&mut self, name: &str, channel: &Option<Channel>, user: &User) {
fn ninja_command (&mut self, name: &str, message: &Message) {
match self.ninjas.get(name) {
Ok(ninja) => {
ninja.print(channel, user);
ninja.print(message);
},
Err(error) => {
error!("Error getting ninja: {:?}", error);
@ -167,13 +154,13 @@ impl Module for PvnModule {
match receiver.recv() {
Ok(event) => {
match *event {
Event::Message { content: ref message, ref channel, ref sender } => {
let command = split_command(message);
debug!("Received message... {:?}", message);
Event::Message { ref message } => {
let command = split_command(&message.content);
debug!("Received message... {:?}", &message.content);
match command {
Some(("?pvn", argument)) => { pvn.pvn_command(argument, channel, sender) },
Some(("?pirate", name)) => { pvn.pirate_command(name, channel, sender) },
Some(("?ninja", name)) => { pvn.ninja_command(name, channel, sender) },
Some(("?pvn", argument)) => { pvn.pvn_command(argument, message) },
Some(("?pirate", name)) => { pvn.pirate_command(name, message) },
Some(("?ninja", name)) => { pvn.ninja_command(name, message) },
_ => {}
}
}

View File

@ -3,8 +3,9 @@ use toml::Table;
use std::sync::Arc;
use std::sync::mpsc::Receiver;
use event::Event;
use helpers::command::split_command;
use event::Event;
use rand;
pub struct RandomModule {
@ -41,15 +42,16 @@ impl Module for RandomModule {
match receiver.recv() {
Ok(event) => {
match *event {
Event::Message { content: ref message, ref channel, ref sender } => {
debug!("Received message... {:?}", message);
if message.starts_with(self.prefix.as_str()) {
Event::Message { ref message } => {
debug!("Received message... {:?}", message.content);
match split_command(&message.content) {
Some((command, _)) => {
if command == self.prefix {
let response = &rand::sample(&mut rng, &self.responses, 1)[0][..];
match *channel {
Some(ref channel) => channel.send(response),
None => sender.send(response)
message.reply(response);
}
},
_ => {}
}
}
_ => ()

View File

@ -3,8 +3,7 @@ use std::io;
use modules::Module;
use toml::Table;
use User;
use MessageSender;
use {MessageSender, Message, User};
use std::sync::Arc;
use std::sync::mpsc::Sender;
@ -35,8 +34,8 @@ impl Module for StdinModule {
let mut input = String::new();
match io::stdin().read_line(&mut input) {
Ok(n) => {
let message = Event::Message {
sender: User {
let message = Message {
author: User {
name: String::from("Dave"),
sender: Box::new(StdinMessageSender {
name: String::from("Dave")
@ -46,7 +45,7 @@ impl Module for StdinModule {
channel: None
};
match sender.send(Arc::new(message)) {
match sender.send(Arc::new(Event::Message { message: message })) {
Err(err) => error!("Error sending message event: {:?}", err),
Ok(_) => {}
}