From bead9324f053957f73042b1e33905aaa73b57649 Mon Sep 17 00:00:00 2001 From: Till Hoeppner Date: Tue, 24 Mar 2015 23:47:03 +0100 Subject: Partial parsing/formatting of weechat3, plus basic CLI interface --- src/format/weechat3.rs | 163 ++++++++++++++++++++++++++++++++----------------- src/log.rs | 13 ++++ src/main.rs | 10 +-- 3 files changed, 127 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/format/weechat3.rs b/src/format/weechat3.rs index f546983..d0dba67 100644 --- a/src/format/weechat3.rs +++ b/src/format/weechat3.rs @@ -1,8 +1,8 @@ -use std::io::BufRead; +use std::io::{ self, BufRead, Write }; use std::borrow::ToOwned; use log::Event; -use format::Decode; +use format::{ Encode, Decode }; use regex::Regex; @@ -12,8 +12,8 @@ pub struct Weechat3; static NORMAL_LINE: Regex = regex!(r"^(\d+-\d+-\d+ \d+:\d+:\d+)\t[@%+~&]?([^ <-]\S+)\t(.*)"); static ACTION_LINE: Regex = regex!(r"^(\d+-\d+-\d+ \d+:\d+:\d+)\t \*\t(\S+) (.*)"); -//static OTHER_LINES: Regex = regex!(r"^(\d+-\d+-\d+ \d+:\d+:\d+)\s(?:--|<--|-->)\s(\S+)\s(\S+)\s(\S+)\s(\S+)\s(\S+)\n$"); -static OTHER_LINES: Regex = regex!(r"(.*)"); +static OTHER_LINES: Regex = regex!(r"^(\d+-\d+-\d+ \d+:\d+:\d+)\s(?:--|<--|-->)\s(\S+)\s(\S+)\s(\S+)\s(\S+)\s(\S+)(.*)\n$"); +//static OTHER_LINES: Regex = regex!(r"(.+)"); static TIME_DATE_FORMAT: &'static str = "%Y-%m-%d %H:%M:%S"; @@ -28,69 +28,122 @@ impl Iterator for Iter where R: BufRead { fn time(s: &str) -> i64 { UTC.datetime_from_str(s, TIME_DATE_FORMAT).unwrap().timestamp() } - - println!("Reading line..."); - self.buffer.clear(); - match self.input.read_line(&mut self.buffer) { - Ok(0) | Err(_) => return None, - Ok(_) => () + fn mask(s: &str) -> String { + s.trim_left_matches('(').trim_right_matches(')').to_owned() } - let line = &self.buffer; - println!("Read line: {}", line); - if let Some(cap) = NORMAL_LINE.captures(line) { - return Some(Ok(Event::Msg { - from: cap.at(1).unwrap().to_owned(), - content: cap.at(2).unwrap().to_owned(), - time: time(cap.at(0).unwrap()) - })) - } else if let Some(cap) = ACTION_LINE.captures(line) { - return Some(Ok(Event::Action { - from: cap.at(1).unwrap().to_owned(), - content: cap.at(2).unwrap().to_owned(), - time: time(cap.at(0).unwrap()) - })) - } else if let Some(cap) = OTHER_LINES.captures(line) { - if cap.at(4) == Some("has") && cap.at(5) == Some("kicked") { - return Some(Ok(Event::Kick { - kicked_nick: cap.at(6).unwrap().to_owned(), - kicking_nick: cap.at(3).unwrap().to_owned(), - kick_message: cap.at(4).unwrap().to_owned(), - time: time(cap.at(0).unwrap()) - })) - } else if cap.at(3) == Some("has") && cap.at(5) == Some("changed") && cap.at(6) == Some("topic") { - return Some(Ok(Event::Topic { - new_topic: cap.at(5).unwrap().to_owned(), - time: time(cap.at(0).unwrap()) - })) - } else if cap.at(3) == Some("Mode") { - return Some(Ok(Event::Mode { - time: time(cap.at(0).unwrap()) + + loop { + self.buffer.clear(); + match self.input.read_line(&mut self.buffer) { + Ok(0) | Err(_) => return None, + Ok(_) => () + } + let line = &self.buffer; + if let Some(cap) = NORMAL_LINE.captures(line) { + return Some(Ok(Event::Msg { + from: cap.at(1).unwrap().to_owned(), + content: cap.at(2).unwrap().to_owned(), + time: time(cap.at(1).unwrap()) })) - } else if cap.at(5) == Some("has") && cap.at(6) == Some("joined") { - return Some(Ok(Event::Join { - nick: cap.at(3).unwrap().to_owned(), - mask: String::new(), - time: time(cap.at(0).unwrap()) + } else if let Some(cap) = ACTION_LINE.captures(line) { + return Some(Ok(Event::Action { + from: cap.at(1).unwrap().to_owned(), + content: cap.at(2).unwrap().to_owned(), + time: time(cap.at(1).unwrap()) })) - } else if cap.at(5) == Some("now") && cap.at(6) == Some("known") { - + } else if let Some(cap) = OTHER_LINES.captures(line) { + println!("{:?}", cap.iter().collect::>()); + if cap.at(4) == Some("has") && cap.at(5) == Some("kicked") { + println!(" Matched Event::Kick"); + return Some(Ok(Event::Kick { + kicked_nick: cap.at(6).unwrap().to_owned(), + kicking_nick: cap.at(3).unwrap().to_owned(), + kick_message: cap.at(4).unwrap().to_owned(), + time: time(cap.at(1).unwrap()) + })) + } else if cap.at(2) == Some("Topic") && cap.at(3) == Some("for") { + return Some(Ok(Event::Topic { + topic: { let mut s = cap.at(6).unwrap().to_string(); s.push_str(cap.at(7).unwrap()); s }, + time: time(cap.at(1).unwrap()) + })) + } else if cap.at(3) == Some("has") && cap.at(5) == Some("changed") && cap.at(6) == Some("topic") { + return Some(Ok(Event::TopicChange { + new_topic: cap.at(5).unwrap().to_owned(), + time: time(cap.at(1).unwrap()) + })) + } else if cap.at(3) == Some("Mode") { + return Some(Ok(Event::Mode { + time: time(cap.at(1).unwrap()) + })) + } else if cap.at(4) == Some("has") && cap.at(5) == Some("joined") { + return Some(Ok(Event::Join { + nick: cap.at(2).unwrap().to_owned(), + channel: cap.at(6).unwrap().to_owned(), + mask: mask(cap.at(3).unwrap()), + time: time(cap.at(1).unwrap()) + })) + } else if cap.at(4) == Some("has") && cap.at(5) == Some("left") { + return Some(Ok(Event::Part { + nick: cap.at(2).unwrap().to_owned(), + channel: cap.at(6).unwrap().to_owned(), + reason: cap.at(7).unwrap().to_owned(), + mask: mask(cap.at(3).unwrap()), + time: time(cap.at(1).unwrap()) + })) + } else if cap.at(5) == Some("now") && cap.at(6) == Some("known") { + return Some(Ok(Event::Nick { + old: String::new(), + new: String::new(), + time: time(cap.at(1).unwrap()) + })) + } } } - Some(Err(::IlcError::Parse(format!("Line `{}` didn't match any rules.", line)))) } } impl Decode> for Weechat3 where R: BufRead { - fn decode(&mut self, input: R) -> Iter {/* - for line in input.lines() { - let line = &*try!(line); - } else { - handler.err(&format!("Malformatted line: {}", line)); - } - }*/ + fn decode(&mut self, input: R) -> Iter { Iter { input: input, buffer: String::new() } } } + +impl Encode for Weechat3 where W: Write { + fn encode(&self, mut output: W, event: &Event) -> io::Result<()> { + fn date(t: i64) -> String { + format!("{}", UTC.timestamp(t, 0).format(TIME_DATE_FORMAT)) + } + match event { + &Event::Msg { ref from, ref content, ref time } => { + try!(write!(&mut output, "{}\t{}\t{}\n", date(*time), from, content)) + }, + &Event::Action { ref from, ref content, ref time } => { + try!(write!(&mut output, "{}\t*\t{} {}\n", date(*time), from, content)) + }, + &Event::Join { ref nick, ref mask, ref channel, ref time } => { + try!(write!(&mut output, "{}\t-->\t{} ({}) has joined {}\n", + date(*time), nick, mask, channel)) + }, + &Event::Part { ref nick, ref mask, ref channel, ref time, ref reason } => { + try!(write!(&mut output, "{}\t<--\t{} ({}) has left {}", + date(*time), nick, mask, channel)); + if reason.len() > 0 { + try!(write!(&mut output, " ({})", reason)); + } + try!(write!(&mut output, "\n")) + }, + &Event::Quit { ref nick, ref mask, ref time, ref reason } => { + try!(write!(&mut output, "{}\t<--\t{} ({}) has quit", date(*time), nick, mask)); + if reason.len() > 0 { + try!(write!(&mut output, " ({})", reason)); + } + try!(write!(&mut output, "\n")) + }, + _ => () + } + Ok(()) + } +} diff --git a/src/log.rs b/src/log.rs index 3079b38..1b6ed45 100644 --- a/src/log.rs +++ b/src/log.rs @@ -23,12 +23,21 @@ pub enum Event { }, Join { nick: String, + channel: String, mask: String, time: i64 }, + Part { + nick: String, + channel: String, + mask: String, + reason: String, + time: i64 + }, Quit { nick: String, mask: String, + reason: String, time: i64 }, Nick { @@ -48,6 +57,10 @@ pub enum Event { time: i64 }, Topic { + topic: String, + time: i64 + }, + TopicChange { new_topic: String, time: i64 }, diff --git a/src/main.rs b/src/main.rs index 1bdf090..b5f65a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,11 +8,11 @@ extern crate libc; extern crate regex; use std::fs::File; -use std::io::BufReader; +use std::io::{ self, BufReader }; use docopt::Docopt; -use ilc::format::{ self, Decode }; +use ilc::format::{ self, Encode, Decode }; static USAGE: &'static str = " A converter and statistics utility for IRC log files. @@ -47,8 +47,10 @@ fn main() { for file in args.arg_file { let f: BufReader = BufReader::new(File::open(file).unwrap()); let iter = parser.decode(f); - println!("Obtained event iterator"); - for e in iter { println!("{:?}", e) } + let events: Vec<_> = iter.collect(); + for e in events { + parser.encode(io::stdout(), &e.unwrap()); + } } } } -- cgit v1.2.3