diff options
author | Till Hoeppner | 2014-10-21 15:33:17 +0200 |
---|---|---|
committer | Till Hoeppner | 2014-10-21 16:15:10 +0200 |
commit | fc27f8cee888acf70683badca9edadb45544822c (patch) | |
tree | f39314f857e92a1e5a19f9675205750adf8919f0 /src | |
parent | ce640c2c25b0e16c567553c5774d633c13cbf0ee (diff) | |
download | irsc-fc27f8cee888acf70683badca9edadb45544822c.tar.gz irsc-fc27f8cee888acf70683badca9edadb45544822c.tar.xz irsc-fc27f8cee888acf70683badca9edadb45544822c.zip |
Initial commit.
Diffstat (limited to 'src')
-rw-r--r-- | src/color.rs | 49 | ||||
-rw-r--r-- | src/events.rs | 22 | ||||
-rw-r--r-- | src/ident.rs | 24 | ||||
-rw-r--r-- | src/lib.rs | 13 | ||||
-rw-r--r-- | src/main.rs | 34 | ||||
-rw-r--r-- | src/server.rs | 168 | ||||
-rw-r--r-- | src/src/.irsc.rs.swp | bin | 12288 -> 0 bytes | |||
-rw-r--r-- | src/src/irsc.rs | 106 |
8 files changed, 307 insertions, 109 deletions
diff --git a/src/color.rs b/src/color.rs new file mode 100644 index 0000000..45a5eeb --- /dev/null +++ b/src/color.rs @@ -0,0 +1,49 @@ +pub const WHITE: &'static str = "00"; +pub const BLACK: &'static str = "01"; +pub const BLUE: &'static str = "02"; +pub const GREEN: &'static str = "03"; +pub const RED: &'static str = "04"; +pub const BROWN: &'static str = "05"; +pub const PURPLE: &'static str = "06"; +pub const ORANGE: &'static str = "07"; +pub const YELLOW: &'static str = "08"; +pub const LIME: &'static str = "09"; +pub const TEAL: &'static str = "10"; +pub const LIGHT_CYAN: &'static str = "11"; +pub const LIGHT_BLUE: &'static str = "12"; +pub const PINK: &'static str = "13"; +pub const GREY: &'static str = "14"; +pub const LIGHT_GREY: &'static str = "15"; + +pub const TRANSPARENT: &'static str = "99"; + + + + +pub fn normal(s: &str) -> String { + format!("\x0F{}\x0F", s) +} + +pub fn bold(s: &str) -> String { + format!("\x02{}\x02", s) +} + +pub fn italic(s: &str) -> String { + format!("\x1D{}\x1D", s) +} + +pub fn underline(s: &str) -> String { + format!("\x1F{}\x1F", s) +} + +pub fn foreground(s: &str, foreground: &str) -> String { + format!("\x03{}{}\x03", foreground, s) +} + +pub fn background(s: &str, background: &str) -> String { + format!("\x03,{}{}\x03", background, s) +} + +pub fn color(s: &str, foreground: &str, background: &str) -> String { + format!("\x03{},{}{}\x03", foreground, background, s) +} diff --git a/src/events.rs b/src/events.rs new file mode 100644 index 0000000..8c474d7 --- /dev/null +++ b/src/events.rs @@ -0,0 +1,22 @@ +use ident::Ident; + +macro_rules! string_record( + ($name: ident, $( $fields: ident ),*) => ( + #[deriving(Show, Clone)] + pub struct $name { + $(pub $fields: String),* + } + ) +) + +string_record!(Welcome, source, target, msg) +string_record!(YourHost, source, target, msg) +string_record!(Created, source, target, msg) + +#[deriving(Show, Clone)] +pub enum Event { + RplWelcome(Box<Welcome>), + RplYourHost(Box<YourHost>), + RplCreated(Box<Created>), + PrivMsg(Ident, String, String) +} diff --git a/src/ident.rs b/src/ident.rs new file mode 100644 index 0000000..069e186 --- /dev/null +++ b/src/ident.rs @@ -0,0 +1,24 @@ +use regex::Regex; + +static PATTERN: Regex = regex!(":(.*)!(.*)@(.*)"); + +#[deriving(Show, Clone)] +pub struct Ident { + pub nickname: String, + pub user: String, + pub host: String +} + +impl Ident { + pub fn parse(s: &str) -> Option<Ident> { + let c = match PATTERN.captures(s) { + Some(c) => c, + None => return None + }; + Some(Ident { + nickname: c.at(1).into_string(), + user: c.at(2).into_string(), + host: c.at(3).into_string() + }) + } +} @@ -1,3 +1,10 @@ -#[test] -fn it_works() { -} +#![feature(globs, phase, slicing_syntax, macro_rules)] + +#[phase(plugin)] +extern crate regex_macros; +extern crate regex; + +pub mod server; +pub mod events; +pub mod color; +pub mod ident; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e9965d8 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,34 @@ +#![feature(globs, slicing_syntax)] + +extern crate irsc; + +use irsc::server::Server; +use irsc::events::*; +use irsc::color::bold; + +static NAME: &'static str = "rusticbot"; +static DESC: &'static str = "A bot, written in Rust."; + +fn main() { + let mut s = Server::new("irc.freenode.org".into_string(), 6667); + let events = s.events(); + s.connect().unwrap(); + s.nick(NAME).unwrap(); + s.user(NAME, "*", "*", DESC).unwrap(); + s.join("#botzoo").unwrap(); + + s.msg("flan3002", "Hey!").unwrap(); + + for e in events.iter() { + match e { + RplWelcome(welcome) => { + println!("{}", welcome) + }, + PrivMsg(from, _to, msg) => { + let response = format!("You wrote: {}", bold(msg[])); + s.msg(from.nickname[], response[]).unwrap(); + } + _ => () + } + } +} diff --git a/src/server.rs b/src/server.rs new file mode 100644 index 0000000..71012ba --- /dev/null +++ b/src/server.rs @@ -0,0 +1,168 @@ +use std::io::{ + BufferedReader, + TcpStream, + IoError +}; +use std::ascii::StrAsciiExt; +use std::comm; +use std::comm::{ Sender, Receiver }; +use std::collections::HashMap; + +use std::str::UnicodeStrSlice; + +use events::*; + +use ident::Ident; + +fn parse_msg(v: Vec<&str>, from: uint) -> String { + let mut msg = if v[from].chars().next().unwrap() == ':' { + v[from][1..].into_string() + } else { v[from].into_string() }; + for m in v.iter().skip(from + 1) { + msg.push_str(" "); + msg.push_str(m.trim_right()); + } + msg +} + +#[deriving(Show, PartialEq, Eq, Clone)] +pub enum Failure { + NotConnected, + Io(IoError) +} + +pub struct Context<'a> { + prefix: &'a str, + command: &'a str, + parts: [&'a str] +} + +pub struct Server<'a> { + host: String, + port: u16, + stream: Option<TcpStream>, + event_sender: Option<Sender<Event>>, + event_types: HashMap<String, &'a Fn<Context<'a>, Event> + 'a> +} + +impl<'a> Server<'a> { + pub fn new(host: String, port: u16) -> Server<'a> { + Server { + host: host, + port: port, + stream: None, + event_sender: None, + event_types: HashMap::new() + } + } + + pub fn events(&mut self) -> Receiver<Event> { + let (tx, rx) = comm::channel(); + self.events = Some(tx); + rx + } + + fn fire_event(&mut self, event: Event) { + self.events.as_ref().map(|s| s.send(event.clone())); + } + + pub fn connect(&mut self) -> Result<(), Failure> { + self.stream = match TcpStream::connect(self.host.as_slice(), self.port) { + Ok(tcp) => Some(tcp), + Err(e) => return Err(Io(e)) + }; + + let mut s = self.clone(); + spawn(proc() { + s.listen(); + }); + Ok(()) + } + + #[inline] + fn sendraw(&mut self, s: &str, newline: bool) -> Result<(), Failure> { + println!("{}", s); + if self.stream.is_some() { + let mut st = self.stream.clone().unwrap(); + match st.write_str(s) { + Ok(_) => match st.flush() { + Ok(_) if newline => match st.write_str("\r\n") { + Ok(_) => Ok(()), + Err(e) => return Err(Io(e)) + }, + Ok(_) => Ok(()), + Err(e) => return Err(Io(e)) + }, + Err(e) => return Err(Io(e)) + } + } else { + Err(NotConnected) + } + } + + pub fn join(&mut self, channel: &str) -> Result<(), Failure> { + self.sendraw(format!("JOIN {}", channel).as_slice(), true) + } + + pub fn nick(&mut self, nick: &str) -> Result<(), Failure> { + self.sendraw(format!("NICK {}", nick).as_slice(), true) + } + + pub fn user(&mut self, username: &str, hostname: &str, servername: &str, realname: &str) -> Result<(), Failure> { + self.sendraw(format!("USER {} {} {} :{}", username, hostname, servername, realname).as_slice(), true) + } + + pub fn password(&mut self, password: &str) -> Result<(), Failure> { + self.sendraw(format!("PASS {}", password).as_slice(), true) + } + + pub fn msg(&mut self, target: &str, message: &str) -> Result<(), Failure> { + self.sendraw(format!("PRIVMSG {} :{}", target, message).as_slice(), true) + } + + fn listen(&mut self) { + let stream = match self.stream { + Some(ref s) => s.clone(), + None => return + }; + let mut reader = BufferedReader::new(stream); + loop { + let line = reader.read_line().unwrap(); + let mut parts = line.as_slice().split(' ').collect::<Vec<&str>>(); + println!("{}", parts); + if parts.len() == 0 { + continue; + } + + // if message has a prefix + let prefix = if parts[0].chars().next().unwrap() == ':' { + parts.remove(0).unwrap() + } else { "" }; + + let cmd = parts.remove(0).unwrap(); + let context = Context { prefix: prefix, cmd: cmd, parts: parts }; + self.events.entry(cmd).call(&context); + + /*match parts[0].to_ascii_upper().as_slice() { + "001" => { + self.fire_event(RplWelcome(box Welcome { + source: prefix.into_string(), + target: parts[1].into_string(), + msg: parse_msg(parts, 2) + })) + }, + "PING" => { + let _ = self.sendraw(format!("PONG {}", parts.get(1)).as_slice(), true); + continue; + } + "PRIVMSG" => { + let from = Ident::parse(prefix).unwrap(); + let to = parts[1]; + let msg = parse_msg(parts, 2); + self.fire_event(PrivMsg(from, to.into_string(), msg)) + }, + _ => () + }*/ + } + } +} diff --git a/src/src/.irsc.rs.swp b/src/src/.irsc.rs.swp Binary files differdeleted file mode 100644 index da65aeb..0000000 --- a/src/src/.irsc.rs.swp +++ /dev/null diff --git a/src/src/irsc.rs b/src/src/irsc.rs deleted file mode 100644 index 704a0f7..0000000 --- a/src/src/irsc.rs +++ /dev/null @@ -1,106 +0,0 @@ -use std::io::{ - BufferedReader, - TcpStream, - IoResult -}; -use std::str; -use std::ascii::StrAsciiExt; -use std::simd::f32x4; - -struct Server { - host: String, - port: u16, - stream: Option<TcpStream> -} - -impl Server { - - fn new(host: &str, port: u16) -> Server { - Server { - host: String::from_str(host), - port: port, - stream: None - } - } - - fn connect(&mut self) { - self.stream = Some(TcpStream::connect(self.host.as_slice(), self.port).unwrap()); - - let cs = self.stream.clone(); - spawn(proc() { - Server::listen(cs); - }); - } - - #[inline] - fn sendraw(stream: &mut TcpStream, s: &str) { - stream.write_str(s); - stream.flush(); - } - - #[inline] - fn sendrawln(stream: &mut TcpStream, s: &str) { - Server::sendraw(stream, String::with_capacity(s.len() + 2).append(s).append("\r\n").as_slice()); - } - - fn join(self, channel: &str) { - self.stream.map(|mut st| Server::sendrawln(&mut st, format!("JOIN {}", channel).as_slice())); - } - - fn listen(stream: Option<TcpStream>) { - let mut abort = false; - let mut stream = match stream { - Some(s) => s, - None => return - }; - if abort {return;} - let mut reader = BufferedReader::new(stream.clone()); - loop { - let line = reader.read_line().unwrap(); - //println!("{}", line); - let mut parts = line.as_slice().split(' ').collect::<Vec<&str>>(); - println!("{}", parts); - - if parts.len() == 0 { - continue; - } - - // if message has a prefix - let prefix = if parts.get(0).chars().next().unwrap() == ':' { - parts.shift().unwrap() - } else { "" }; - - match (*parts.get(0)).to_ascii_upper().as_slice() { - "PING" => { - Server::sendrawln(&mut stream, format!("PONG {}", parts.get(1)).as_slice()); - continue; - } - _ => {} - } - - } - } - - -} - -fn main() { - let mut furnet = Server::new("irc.furnet.org", 6667); - furnet.connect(); - - std::io::timer::sleep(5000u64); - - furnet.join("#teenagefurs"); - - // create simd vectors - let x = f32x4(1.0, 2.0, 3.0, 4.0); - let y = f32x4(4.0, 3.0, 2.0, 1.0); - - // simd product - let z = x * y; - - // like any struct, the simd vector can be destructured using `let` - let f32x4(a, b, c, d) = z; - - println!("{}", (a, b, c, d)); -} |