From fc27f8cee888acf70683badca9edadb45544822c Mon Sep 17 00:00:00 2001 From: Till Hoeppner Date: Tue, 21 Oct 2014 15:33:17 +0200 Subject: Initial commit. --- .gitignore | 31 ++++++++++ Makefile | 33 ---------- src/color.rs | 49 +++++++++++++++ src/events.rs | 22 +++++++ src/ident.rs | 24 ++++++++ src/lib.rs | 13 +++- src/main.rs | 34 +++++++++++ src/server.rs | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/src/.irsc.rs.swp | Bin 12288 -> 0 bytes src/src/irsc.rs | 106 -------------------------------- target/irsc | Bin 1025479 -> 0 bytes target/rwm | Bin 1177853 -> 0 bytes 12 files changed, 338 insertions(+), 142 deletions(-) create mode 100644 .gitignore delete mode 100644 Makefile create mode 100644 src/color.rs create mode 100644 src/events.rs create mode 100644 src/ident.rs create mode 100644 src/main.rs create mode 100644 src/server.rs delete mode 100644 src/src/.irsc.rs.swp delete mode 100644 src/src/irsc.rs delete mode 100755 target/irsc delete mode 100755 target/rwm diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..245f0b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +# Created by https://www.gitignore.io + +### vim ### +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist +*~ + + +### Linux ### +*~ + +# KDE directory preferences +.directory + + +### Rust ### +# Compiled files +*.o +*.so +*.rlib +*.dll + +# Executables +*.exe + +# Generated by Cargo +/target/ + diff --git a/Makefile b/Makefile deleted file mode 100644 index 58dec28..0000000 --- a/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -RUSTC ?= rustc -RUSTC_FLAGS ?= -NAME ?= irsc - -SRC = $(shell find src -name '*.rs') - -all: $(NAME) - -$(NAME): $(SRC) - mkdir -p target - $(RUSTC) --out-dir target $(RUSTC_FLAGS) src/$(NAME).rs - -opt: RUSTC_FLAGS += --opt-level=3 -Z lto -opt: $(NAME) - -small: opt - upx -9 ./target/$(NAME) - -debug: RUSTC_FLAGS += -g -debug: $(NAME) - -run: $(NAME) - ./target/$(NAME) - -test: $(SRC) - mkdir -p target - $(RUSTC) --test --out-dir target src/$(NAME).rs - ./target/$(NAME) - -clean: - @rm -rf target - -.PHONY: clean 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), + RplYourHost(Box), + RplCreated(Box), + 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 { + 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() + }) + } +} diff --git a/src/lib.rs b/src/lib.rs index a93251b..fcb0096 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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, + event_sender: Option>, + event_types: HashMap, 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 { + 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::>(); + 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 deleted file mode 100644 index da65aeb..0000000 Binary files a/src/src/.irsc.rs.swp and /dev/null differ 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 -} - -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) { - 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::>(); - 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)); -} diff --git a/target/irsc b/target/irsc deleted file mode 100755 index 49a26f5..0000000 Binary files a/target/irsc and /dev/null differ diff --git a/target/rwm b/target/rwm deleted file mode 100755 index b3b0a9e..0000000 Binary files a/target/rwm and /dev/null differ -- cgit v1.2.3