From 4446aca4055da69daa398ed3103b069e65a7f2c1 Mon Sep 17 00:00:00 2001 From: Jokler Date: Wed, 4 Oct 2017 04:35:27 +0200 Subject: Initial bot source --- src/lib.rs | 65 ++++++++++++++++++++++++++++++++++ src/plugin.rs | 35 +++++++++++++++++++ src/plugins/emoji.rs | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/plugins/mod.rs | 1 + 4 files changed, 199 insertions(+) create mode 100644 src/lib.rs create mode 100644 src/plugin.rs create mode 100644 src/plugins/emoji.rs create mode 100644 src/plugins/mod.rs (limited to 'src') 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>> = + 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 = 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 { + + let mut emojis: Vec = 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; -- cgit v1.2.3-70-g09d2