<commit_before>#![feature(phase)]
extern crate regex;
#[phase(plugin)] extern crate regex_macros;

use std::io::{BufferedReader, BufferedWriter, InvalidInput, IoError, IoResult, TcpStream};

pub struct Bot {
    pub sock: TcpStream
}

impl Bot {
    pub fn new() -> Bot {
        let sock = TcpStream::connect("irc.fyrechat.net", 6667).unwrap();
        Bot {
            sock: sock,
        }
    }

    pub fn identify(&mut self) {
        let mut writer = BufferedWriter::new(self.sock.clone());
        writer.write_str("NICK :pickles\r\n").unwrap();
        writer.write_str("USER pickles 0 * :pickles\r\n").unwrap();
        writer.flush().unwrap();
    }

    pub fn output(&mut self) {
        let mut reader = BufferedReader::new(self.sock.clone());
        for line in reader.lines() {
            match line {
                Ok(ln) => {
                    let (source, command, args) = process(ln.as_slice()).unwrap();
                    self.handle_command(source, command, args.as_slice());
                    println!("{}", ln)
                },
                Err(e) => println!("Shit, you're fucked! {}", e),
            }
        }
    }

    fn handle_command(&mut self, source: &str, command: &str, args: &[&str]) -> () {
        match (command, args) {
            ("PING", [msg]) => {
                self.send("PONG", msg);
            },
            ("376", _) => {
                self.send("JOIN", "#vana");
            },
            ("PRIVMSG", [channel, msg]) => {
                if msg.contains("pickles") && msg.contains("hi") {
                    self.send("PRIVMSG #vana", "hi");
                }

                if msg.starts_with(". ") {
                    self.send("PRIVMSG #vana", msg.slice_from(2));
                }
            },
            _ => (),
        }
    }

    fn send(&mut self, command: &str, arg: &str) {
        let mut writer = BufferedWriter::new(self.sock.clone());
        write!(writer, "{} :{}\r\n", command, arg);
        writer.flush().unwrap();
    }
}

fn process(msg: &str) -> IoResult<(&str, &str, Vec<&str>)> {
    let reg = regex!(r"^(?::([^ ]+) )?([^ ]+)(.*)");
    let cap = match reg.captures(msg) {
        Some(x) => x,
        None => return Err(IoError {
            kind: InvalidInput,
            desc: "Failed to parse line",
            detail: None,
        }),
    };
    let source = cap.at(1);
    let command = cap.at(2);
    let args = parse_args(cap.at(3));
    Ok((source, command, args))
}

fn parse_args(line: &str) -> Vec<&str> {
    let reg = regex!(r" ([^: ]+)| :(.*)$");
    reg.captures_iter(line).map(|cap| {
        match cap.at(1) {
            "" => cap.at(2),
            x => x,
        }
    }).collect()
}<commit_msg>Refactored basic library significantly, but sending isn't working properly.<commit_after>#![feature(phase)]
extern crate regex;
#[phase(plugin)] extern crate regex_macros;

use std::io::{BufferedReader, BufferedWriter, InvalidInput, IoError, IoResult, TcpStream};

pub struct Connection(TcpStream);

pub fn connect(host: &str, port: u16) -> IoResult<Connection> {
    let socket = try!(TcpStream::connect(host, port));
    Ok(Connection(socket))
}

fn send_internal(conn: &Connection, msg: &str) -> IoResult<()> {
    match conn {
        &Connection(ref tcp) => {
            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()).as_slice())
}

pub struct Bot {
    pub conn: Connection,
}

impl Bot {
    pub fn new() -> IoResult<Bot> {
        let conn = try!(connect("irc.fyrechat.net", 6667));
        Ok(Bot {
            conn: conn,
        })
    }

    pub fn send_nick(&mut self, nick: &str) -> IoResult<()> {
        send(&self.conn, Message::new(None, "NICK", [nick]))
    }

    pub fn send_user(&mut 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 output(&mut self) {
        let mut reader = { let Connection(ref tcp) = self.conn; BufferedReader::new(tcp.clone()) };
        for line in reader.lines() {
            match line {
                Ok(ln) => {
                    let (source, command, args) = process(ln.as_slice()).unwrap();
                    self.handle_command(source, command, args.as_slice());
                    println!("{}", ln)
                },
                Err(e) => println!("Shit, you're fucked! {}", e),
            }
        }
    }

    fn handle_command(&mut self, source: &str, command: &str, args: &[&str]) -> IoResult<()> {
        match (command, args) {
            ("PING", [msg]) => {
                try!(send(&self.conn, Message::new(None, "PONG", [msg])));
            },
            ("376", _) => {
                try!(send(&self.conn, Message::new(None, "JOIN", ["#vana"])));
            },
            ("PRIVMSG", [_, msg]) => {
                if msg.contains("pickles") && msg.contains("hi") {
                    try!(send(&self.conn, Message::new(None, "PRIVMSG", ["#vana", "hi"])));
                } else if msg.starts_with(". ") {
                    try!(send(&self.conn, Message::new(None, "PRIVMSG", ["#vana", msg.slice_from(2)])));
                };
            },
            _ => (),
        };
        Ok(())
    }
}

fn process(msg: &str) -> IoResult<(&str, &str, Vec<&str>)> {
    let reg = regex!(r"^(?::([^ ]+) )?([^ ]+)(.*)");
    let cap = match reg.captures(msg) {
        Some(x) => x,
        None => return Err(IoError {
            kind: InvalidInput,
            desc: "Failed to parse line",
            detail: None,
        }),
    };
    let source = cap.at(1);
    let command = cap.at(2);
    let args = parse_args(cap.at(3));
    Ok((source, command, args))
}

fn parse_args(line: &str) -> Vec<&str> {
    let reg = regex!(r" ([^: ]+)| :(.*)$");
    reg.captures_iter(line).map(|cap| {
        match cap.at(1) {
            "" => cap.at(2),
            x => x,
        }
    }).collect()
}
{'fraction_non_alphanumeric': 0.19205101586830786, 'fraction_numerical': 0.0044490582826635025, 'mean_word_length': 1.9709251101321585, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5764028', 'n_tokens_mistral': 2221, 'n_tokens_neox': 2168, 'n_words': 468}