From 642622752f62e6df3e8ecc85f0f343e890efc7bb Mon Sep 17 00:00:00 2001 From: Aaron Weiss Date: Tue, 23 Sep 2014 20:11:13 -0400 Subject: [PATCH] Refactored for modularization, incorporated config usage. --- src/conn.rs | 21 +++++++++++++++ src/data.rs | 42 ++++++++++++++++++++++++++++++ src/lib.rs | 73 ++++++++++++++++++++--------------------------------- 3 files changed, 91 insertions(+), 45 deletions(-) create mode 100644 src/conn.rs create mode 100644 src/data.rs diff --git a/src/conn.rs b/src/conn.rs new file mode 100644 index 0000000..a4bddf8 --- /dev/null +++ b/src/conn.rs @@ -0,0 +1,21 @@ +use std::io::{BufferedWriter, IoResult, TcpStream}; +use data::Message; + +pub struct Connection(pub TcpStream); + +pub fn connect(host: &str, port: u16) -> IoResult { + let socket = try!(TcpStream::connect(host, port)); + Ok(Connection(socket)) +} + +fn send_internal(conn: &Connection, msg: &str) -> IoResult<()> { + let &Connection(ref tcp) = conn; + let mut writer = BufferedWriter::new(tcp.clone()); + writer.write_str(msg); + writer.flush() +} + +pub fn send(conn: &Connection, msg: Message) -> IoResult<()> { + let arg_string = msg.args.init().connect(" ").append(" :").append(*msg.args.last().unwrap()); + send_internal(conn, msg.command.to_string().append(" ").append(arg_string.as_slice()).append("\r\n").as_slice()) +} diff --git a/src/data.rs b/src/data.rs new file mode 100644 index 0000000..7365bbc --- /dev/null +++ b/src/data.rs @@ -0,0 +1,42 @@ +use serialize::json::{decode}; +use std::io::fs::File; +use std::io::{InvalidInput, IoError, IoResult}; + +pub struct Message<'a> { + pub source: Option<&'a str>, + pub command: &'a str, + pub args: &'a [&'a str], +} + +impl<'a> Message<'a> { + pub fn new(source: Option<&'a str>, command: &'a str, args: &'a [&'a str]) -> Message<'a> { + Message { + source: source, + command: command, + args: args, + } + } +} + +#[deriving(Decodable)] +pub struct Config { + pub nickname: String, + pub username: String, + pub realname: String, + pub password: String, + pub server: String, + pub port: u16, + pub channels: Vec, +} + +impl Config { + pub fn load() -> IoResult { + let mut file = try!(File::open(&Path::new("config.json"))); + let data = try!(file.read_to_string()); + decode(data.as_slice()).map_err(|e| IoError { + kind: InvalidInput, + desc: "Decoder error", + detail: Some(e.to_string()), + }) + } +} diff --git a/src/lib.rs b/src/lib.rs index 4b2e260..e06cea3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,67 +1,46 @@ #![feature(phase)] extern crate regex; #[phase(plugin)] extern crate regex_macros; +extern crate serialize; -use std::io::{BufferedReader, BufferedWriter, InvalidInput, IoError, IoResult, TcpStream}; -pub struct Connection(TcpStream); +use std::io::{BufferedReader, InvalidInput, IoError, IoResult}; +use data::{Message, Config}; +use conn::{Connection, connect, send}; -pub fn connect(host: &str, port: u16) -> IoResult { - let socket = try!(TcpStream::connect(host, port)); - Ok(Connection(socket)) -} - -fn send_internal(conn: &Connection, msg: &str) -> IoResult<()> { - let &Connection(ref tcp) = conn; - let mut writer = BufferedWriter::new(tcp.clone()); - writer.write_str(msg); - writer.flush() -} - -pub struct Message<'a> { - source: Option<&'a str>, - command: &'a str, - args: &'a [&'a str], -} - -impl<'a> Message<'a> { - pub fn new(source: Option<&'a str>, command: &'a str, args: &'a [&'a str]) -> Message<'a> { - Message { - source: source, - command: command, - args: args, - } - } -} - -pub fn send(conn: &Connection, msg: Message) -> IoResult<()> { - let arg_string = msg.args.init().connect(" ").append(" :").append(*msg.args.last().unwrap()); - send_internal(conn, msg.command.to_string().append(" ").append(arg_string.as_slice()).append("\r\n").as_slice()) -} +pub mod conn; +pub mod data; pub struct Bot { pub conn: Connection, + pub config: Config, } impl Bot { pub fn new() -> IoResult { - let conn = try!(connect("irc.fyrechat.net", 6667)); + let config = try!(Config::load()); + let conn = try!(connect(config.server.as_slice(), config.port)); Ok(Bot { conn: conn, + config: config, }) } - pub fn send_nick(&mut self, nick: &str) -> IoResult<()> { + pub fn send_nick(&self, nick: &str) -> IoResult<()> { send(&self.conn, Message::new(None, "NICK", [nick])) } - pub fn send_user(&mut self, username: &str, real_name: &str) -> IoResult<()> { + pub fn send_user(&self, username: &str, real_name: &str) -> IoResult<()> { send(&self.conn, Message::new(None, "USER", [username, "0", "*", real_name])) } - pub fn identify(&mut self) -> IoResult<()> { - self.send_nick("pickles"); - self.send_user("pickles", "pickles") + pub fn send_join(&self, chan: &str) -> IoResult<()> { + send(&self.conn, Message::new(None, "JOIN", [chan.as_slice()])) + } + + pub fn identify(&self) -> IoResult<()> { + self.send_nick(self.config.nickname.as_slice()); + self.send_user(self.config.username.as_slice(), self.config.realname.as_slice()) } pub fn output(&mut self) { @@ -84,16 +63,20 @@ impl Bot { try!(send(&self.conn, Message::new(None, "PONG", [msg]))); }, ("376", _) => { // End of MOTD - try!(send(&self.conn, Message::new(None, "JOIN", ["#vana"]))); + for chan in self.config.channels.iter() { + try!(self.send_join(chan.as_slice())); + } }, ("422", _) => { // Missing MOTD - try!(send(&self.conn, Message::new(None, "JOIN", ["#vana"]))); + for chan in self.config.channels.iter() { + try!(self.send_join(chan.as_slice())); + } } - ("PRIVMSG", [_, msg]) => { + ("PRIVMSG", [chan, msg]) => { if msg.contains("pickles") && msg.contains("hi") { - try!(send(&self.conn, Message::new(None, "PRIVMSG", ["#vana", "hi"]))); + try!(send(&self.conn, Message::new(None, "PRIVMSG", [chan.as_slice(), "hi"]))); } else if msg.starts_with(". ") { - try!(send(&self.conn, Message::new(None, "PRIVMSG", ["#vana", msg.slice_from(2)]))); + try!(send(&self.conn, Message::new(None, "PRIVMSG", [chan.as_slice(), msg.slice_from(2)]))); }; }, _ => (),