diff options
| -rw-r--r-- | .travis.yml | 8 | ||||
| -rw-r--r-- | Cargo.toml | 28 | ||||
| -rw-r--r-- | bin/main.rs | 5 | ||||
| -rw-r--r-- | config.toml | 14 | ||||
| -rw-r--r-- | src/lib.rs | 65 | ||||
| -rw-r--r-- | src/plugin.rs | 35 | ||||
| -rw-r--r-- | src/plugins/emoji.rs | 98 | ||||
| -rw-r--r-- | src/plugins/mod.rs | 1 |
8 files changed, 254 insertions, 0 deletions
diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..8c91a74 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: rust +rust: + - stable + - beta + - nightly +matrix: + allow_failures: + - rust: nightly diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a126b60 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "frippy" +version = "0.1.0" +authors = ["Jokler <jokler.contact@gmail.com>"] +repository = "https://github.com/Mavulp/frippy" +readme = "README.md" +license = "MIT" +keywords = ["irc", "bot"] +categories = ["network-programming"] +description = "An IRC Bot" + +[lib] +name = "frippy" +path = "src/lib.rs" + +[[bin]] +name = "frippy" +path = "bin/main.rs" + +[dependencies] +irc = "0.12.5" +lazy_static = "0.2.9" +reqwest = "0.8.0" +regex = "0.2.2" +serde = "1.0.15" +serde_json = "1.0.3" + +unicode_names = { git = 'https://github.com/antifuchs/unicode_names', branch = 'fix-for-rust-1-10' } diff --git a/bin/main.rs b/bin/main.rs new file mode 100644 index 0000000..b974405 --- /dev/null +++ b/bin/main.rs @@ -0,0 +1,5 @@ +extern crate frippy; + +fn main() { + frippy::run(); +} diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..e0f4d57 --- /dev/null +++ b/config.toml @@ -0,0 +1,14 @@ +owners = [""] +nickname = "frippy" +realname = "frippy" +server = "" +port = 6697 +encoding = "UTF-8" +channels = [""] +user_info = "IRC Bot" +version = "irc:git:Rust" +source = "https://github.com/Mavulp/frippy" +ping_time = 180 +ping_timeout = 10 +burst_window_length = 8 +max_messages_in_burst = 15 diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..37ae19c --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,65 @@ +#![feature(proc_macro)] +extern crate irc; +#[macro_use] +extern crate lazy_static; + +#[macro_use] +mod plugin; +mod plugins; + +use std::thread::spawn; +use std::sync::{Arc, Mutex}; +use irc::client::prelude::*; + +use plugin::Plugin; + +pub fn run() { + let server = IrcServer::new("config.toml").unwrap(); + server.identify().unwrap(); + + let plugins: Vec<Arc<Mutex<Plugin>>> = + vec![Arc::new(Mutex::new(plugins::emoji::Emoji::new()))]; + + server + .for_each_incoming(|message| { + let message = Arc::new(message); + + for plugin in plugins.clone().into_iter() { + let server = server.clone(); + let message = message.clone(); + + spawn(move || { + let mut plugin = match plugin.lock() { + Ok(plugin) => plugin, + Err(poisoned) => poisoned.into_inner(), + }; + + if plugin.is_allowed(&server, &message) { + plugin.execute(&server, &message).unwrap(); + } + }); + } + }) + .unwrap(); +} + +#[cfg(test)] +mod tests { + use irc::client::prelude::*; + + pub fn make_server(cmd: &str) -> IrcServer { + let config = Config { + nickname: Some(format!("test")), + server: Some(format!("irc.test.net")), + channels: Some(vec![format!("#test")]), + use_mock_connection: Some(true), + ..Default::default() + }; + + IrcServer::from_config(config).unwrap() + } + + pub fn get_server_value(server: &IrcServer) -> String { + unimplemented!(); + } +} diff --git a/src/plugin.rs b/src/plugin.rs new file mode 100644 index 0000000..473cab1 --- /dev/null +++ b/src/plugin.rs @@ -0,0 +1,35 @@ +use std::fmt; +use irc::client::prelude::*; +use irc::error::Error as IrcError; + +pub trait Plugin: Send + Sync + fmt::Debug { + fn is_allowed(&self, server: &IrcServer, message: &Message) -> bool; + fn execute(&mut self, server: &IrcServer, message: &Message) -> Result<(), IrcError>; +} + +#[macro_export] +macro_rules! register_plugin { + ($t:ident) => { + #[derive(Debug)] + pub struct $t; + + impl $t { + pub fn new() -> $t { + $t { } + } + } + }; + + ($t:ident, $element: ident: $ty: ty) => { + #[derive(Debug)] + pub struct $t { + $element: $ty + } + + impl $t { + pub fn new() -> $t { + $t { $element: <$ty>::new() } + } + } + }; +} diff --git a/src/plugins/emoji.rs b/src/plugins/emoji.rs new file mode 100644 index 0000000..8b56a14 --- /dev/null +++ b/src/plugins/emoji.rs @@ -0,0 +1,98 @@ +use irc::client::prelude::*; +use irc::error::Error as IrcError; +use plugin::Plugin; + +extern crate unicode_names; + +register_plugin!(Emoji); + +impl Emoji { + fn emoji(&self, server: &IrcServer, content: &str, target: &str) -> Result<(), IrcError> { + + let mut names: Vec<String> = Vec::new(); + for emoji in self.return_emojis(&content) { + + names.push(match unicode_names::name(emoji) { + Some(v) => format!("{}", v).to_lowercase(), + None => format!("UNKNOWN"), + }); + } + + server.send_privmsg(target, &names.join(", ")) + } + + fn return_emojis(&self, string: &str) -> Vec<char> { + + let mut emojis: Vec<char> = Vec::new(); + + for c in string.chars() { + if self.is_emoji(&c) { + emojis.push(c); + } + } + + emojis + } + + fn is_emoji(&self, c: &char) -> bool { + match *c { '\u{1F600}'...'\u{1F64F}' // Emoticons + | '\u{1F300}'...'\u{1F5FF}' // Misc Symbols and Pictographs + | '\u{1F680}'...'\u{1F6FF}' // Transport and Map + | '\u{2600}' ...'\u{26FF}' // Misc symbols + | '\u{2700}' ...'\u{27BF}' // Dingbats + | '\u{FE00}' ...'\u{FE0F}' // Variation Selectors + | '\u{1F900}'...'\u{1F9FF}' // Supplemental Symbols and Pictographs + | '\u{20D0}' ...'\u{20FF}' => true, // Combining Diacritical Marks for Symbols + _ => false, + } + } +} + +impl Plugin for Emoji { + fn is_allowed(&self, _: &IrcServer, message: &Message) -> bool { + match message.command { + Command::PRIVMSG(_, _) => true, + _ => false, + } + } + + fn execute(&mut self, server: &IrcServer, message: &Message) -> Result<(), IrcError> { + match message.command { + Command::PRIVMSG(ref target, ref content) => self.emoji(server, content, target), + _ => Ok(()) + } + } +} + +#[cfg(test)] +mod tests { +// use ::tests::{make_server, get_server_value}; +// +// use irc::client::prelude::*; +// +// use plugin::Plugin; +// use super::Emoji; +// +// #[test] +// fn emoji_message() { +// let server = make_server("PRIVMSG test :😃\r\n"); +// let mut plugin = Emoji::new(); +// +// server.for_each_incoming(|message| { +// assert!(plugin.execute(&server, &message).is_ok()); +// }).unwrap(); +// +// assert_eq!("PRIVMSG test :smiling fce with open mouth\r\n", &*get_server_value(&server)); +// } +// +// #[test] +// fn no_emoji_message() { +// let server = make_server("PRIVMSG test :test\r\n"); +// let mut plugin = Emoji::new(); +// +// server.for_each_incoming(|message| { +// assert!(plugin.execute(&server, &message).is_ok()); +// }).unwrap(); +// assert_eq!("", &*get_server_value(&server)); +// } +} diff --git a/src/plugins/mod.rs b/src/plugins/mod.rs new file mode 100644 index 0000000..35cdb27 --- /dev/null +++ b/src/plugins/mod.rs @@ -0,0 +1 @@ +pub mod emoji; |
