tri 0.1.0

A simple task bot for Slack.
use error_chain::ChainedError;
use slack::{Event, EventHandler, Message, RtmClient, Sender};

use commands::{Command, DynamicCommand, Help};
use controller::Tri;
use errors::{ErrorKind, Result, ResultExt};

pub struct Handler<'a>(pub &'a Tri);

impl<'a> Handler<'a> {
    fn handle(&self, sender: &Sender, text: String, user: String, channel: String) -> Result<()> {
        let at_me = format!("<@{}> ", self.0.slack_id);
        if !text.starts_with(&at_me) || user == self.0.slack_id {
            debug!("Ignoring.");
            return Ok(());
        }
        let text = &text[at_me.len()..];

        sender.send_typing(&channel).ok();

        match text.parse::<DynamicCommand>() {
            Ok(cmd) => {
                let res = match cmd.run(self.0, &user) {
                    Ok(res) => res,
                    Err(err) => {
                        error!("{}", err);
                        format!("An error occurred:\n\n```\n{}\n```", err)
                    }
                };
                sender.send_message(&channel, &res).chain_err(|| {
                    ErrorKind::CouldntSendChannelMessage(channel)
                })?;
            }
            Err(()) => {
                let msg = format!("Huh? I didn't understand that.\n{}",
                    Help.run(self.0, &user).unwrap());
                sender.send_message(&channel, &msg)
                    .chain_err(|| ErrorKind::CouldntSendChannelMessage(channel))?;
            }
        }
        Ok(())
    }
}

impl<'a> EventHandler for Handler<'a> {
    fn on_connect(&mut self, _rtm: &RtmClient) {
        info!("Connected to Slack!");
    }

    fn on_close(&mut self, _rtm: &RtmClient) {
        warn!("Slack connection closed.");
    }

    fn on_event(&mut self, rtm: &RtmClient, event: Event) {
        debug!("Got event from Slack: {:?}", event);
        match event {
            Event::Message(msg) => {
                if let Message::Standard(msg) = *msg {
                    if let (Some(channel), Some(text), Some(user)) =
                        (msg.channel, msg.text, msg.user)
                    {
                        info!(
                            "Got message {:?} from {} in channel {}",
                            text,
                            user,
                            channel
                        );
                        if let Err(err) = self.handle(rtm.sender(), text, user, channel) {
                            error!("{}", err.display_chain());
                        }
                    }
                }
            }
            _ => {}
        }
    }
}