aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJokler <jokler.contact@gmail.com>2018-06-30 19:57:37 +0200
committerJokler <jokler.contact@gmail.com>2018-06-30 19:57:37 +0200
commit3929022952ffbd5be0a9ba4ff074a735dea2aed1 (patch)
tree0f2c3847f358c619059b151ea2c33bd2094063cd
parent82ab100c7e6334dc6fa92e92c8838ecc622118d5 (diff)
downloadfrippy-3929022952ffbd5be0a9ba4ff074a735dea2aed1.tar.gz
frippy-3929022952ffbd5be0a9ba4ff074a735dea2aed1.zip
Plugins: Replace IrcClient with a trait
This is to make it simpler to replace the client in the future.
-rw-r--r--src/lib.rs67
-rw-r--r--src/plugin.rs10
-rw-r--r--src/plugins/emoji.rs25
-rw-r--r--src/plugins/factoids/mod.rs31
-rw-r--r--src/plugins/factoids/utils.rs8
-rw-r--r--src/plugins/help.rs26
-rw-r--r--src/plugins/keepnick.rs28
-rw-r--r--src/plugins/remind/mod.rs33
-rw-r--r--src/plugins/sed.rs27
-rw-r--r--src/plugins/tell/mod.rs34
-rw-r--r--src/plugins/url.rs27
11 files changed, 206 insertions, 110 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 9b49644..b8662e4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -60,23 +60,37 @@ pub mod plugin;
pub mod plugins;
pub mod utils;
+use plugin::*;
+
+use error::*;
+use failure::ResultExt;
+
+pub use irc::client::data::Config;
+use irc::client::ext::ClientExt;
+use irc::client::reactor::IrcReactor;
+use irc::client::{Client, IrcClient};
+use irc::error::IrcError;
+use irc::proto::{command::Command, Message};
+
use std::collections::HashMap;
use std::fmt;
use std::sync::Arc;
use std::thread;
-use error::*;
-use failure::ResultExt;
-pub use irc::client::prelude::*;
-pub use irc::error::IrcError;
+pub trait FrippyClient: Client + Send + Sync + Clone + fmt::Debug {
+ fn current_nickname(&self) -> &str;
+}
-use plugin::*;
+impl FrippyClient for IrcClient {
+ fn current_nickname(&self) -> &str {
+ self.current_nickname()
+ }
+}
/// The bot which contains the main logic.
-#[derive(Default)]
pub struct Bot<'a> {
prefix: &'a str,
- plugins: ThreadedPlugins,
+ plugins: ThreadedPlugins<IrcClient>,
}
impl<'a> Bot<'a> {
@@ -93,7 +107,7 @@ impl<'a> Bot<'a> {
/// use frippy::Bot;
/// let mut bot = Bot::new(".");
/// ```
- pub fn new(cmd_prefix: &'a str) -> Bot<'a> {
+ pub fn new(cmd_prefix: &'a str) -> Self {
Bot {
prefix: cmd_prefix,
plugins: ThreadedPlugins::new(),
@@ -110,7 +124,10 @@ impl<'a> Bot<'a> {
/// let mut bot = frippy::Bot::new(".");
/// bot.add_plugin(plugins::help::Help::new());
/// ```
- pub fn add_plugin<T: Plugin + 'static>(&mut self, plugin: T) {
+ pub fn add_plugin<T>(&mut self, plugin: T)
+ where
+ T: Plugin<Client = IrcClient> + 'static,
+ {
self.plugins.add(plugin);
}
@@ -179,12 +196,15 @@ impl<'a> Bot<'a> {
}
}
-fn process_msg(
- client: &IrcClient,
- mut plugins: ThreadedPlugins,
+fn process_msg<C>(
+ client: &C,
+ mut plugins: ThreadedPlugins<C>,
prefix: &str,
message: Message,
-) -> Result<(), IrcError> {
+) -> Result<(), IrcError>
+where
+ C: FrippyClient + 'static,
+{
// Log any channels we join
if let Command::JOIN(ref channel, _, _) = message.command {
if message.source_nickname().unwrap() == client.current_nickname() {
@@ -207,19 +227,22 @@ fn process_msg(
Ok(())
}
-#[derive(Clone, Default, Debug)]
-struct ThreadedPlugins {
- plugins: HashMap<String, Arc<Plugin>>,
+#[derive(Clone, Debug)]
+struct ThreadedPlugins<C: FrippyClient> {
+ plugins: HashMap<String, Arc<Plugin<Client = C>>>,
}
-impl ThreadedPlugins {
- pub fn new() -> ThreadedPlugins {
+impl<C: FrippyClient + 'static> ThreadedPlugins<C> {
+ pub fn new() -> Self {
ThreadedPlugins {
plugins: HashMap::new(),
}
}
- pub fn add<T: Plugin + 'static>(&mut self, plugin: T) {
+ pub fn add<T>(&mut self, plugin: T)
+ where
+ T: Plugin<Client = C> + 'static,
+ {
let name = plugin.name().to_lowercase();
let safe_plugin = Arc::new(plugin);
@@ -232,7 +255,7 @@ impl ThreadedPlugins {
/// Runs the execute functions on all plugins.
/// Any errors that occur are printed right away.
- pub fn execute_plugins(&mut self, client: &IrcClient, message: Message) {
+ pub fn execute_plugins(&mut self, client: &C, message: Message) {
let message = Arc::new(message);
for (name, plugin) in self.plugins.clone() {
@@ -273,7 +296,7 @@ impl ThreadedPlugins {
pub fn handle_command(
&mut self,
- client: &IrcClient,
+ client: &C,
mut command: PluginCommand,
) -> Result<(), FrippyError> {
// Check if there is a plugin for this command
@@ -300,7 +323,7 @@ impl ThreadedPlugins {
}
}
-impl fmt::Display for ThreadedPlugins {
+impl<C: FrippyClient> fmt::Display for ThreadedPlugins<C> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let plugin_names = self.plugins
.iter()
diff --git a/src/plugin.rs b/src/plugin.rs
index 5538313..65bfe1f 100644
--- a/src/plugin.rs
+++ b/src/plugin.rs
@@ -20,17 +20,19 @@ pub enum ExecutionStatus {
/// `Plugin` has to be implemented for any struct that should be usable
/// as a `Plugin` in frippy.
pub trait Plugin: PluginName + Send + Sync + fmt::Debug {
+ type Client;
/// Handles messages which are not commands or returns
/// [`RequiresThread`](enum.ExecutionStatus.html#variant.RequiresThread)
/// if [`execute_threaded()`](trait.Plugin.html#tymethod.execute_threaded) should be used instead.
- fn execute(&self, client: &IrcClient, message: &Message) -> ExecutionStatus;
+ fn execute(&self, client: &Self::Client, message: &Message) -> ExecutionStatus;
/// Handles messages which are not commands in a new thread.
- fn execute_threaded(&self, client: &IrcClient, message: &Message) -> Result<(), FrippyError>;
+ fn execute_threaded(&self, client: &Self::Client, message: &Message)
+ -> Result<(), FrippyError>;
/// Handles any command directed at this plugin.
- fn command(&self, client: &IrcClient, command: PluginCommand) -> Result<(), FrippyError>;
+ fn command(&self, client: &Self::Client, command: PluginCommand) -> Result<(), FrippyError>;
/// Similar to [`command()`](trait.Plugin.html#tymethod.command) but return a String instead of
/// sending messages directly to IRC.
- fn evaluate(&self, client: &IrcClient, command: PluginCommand) -> Result<String, String>;
+ fn evaluate(&self, client: &Self::Client, command: PluginCommand) -> Result<String, String>;
}
/// `PluginName` is required by [`Plugin`](trait.Plugin.html).
diff --git a/src/plugins/emoji.rs b/src/plugins/emoji.rs
index e4dffdb..01fb39c 100644
--- a/src/plugins/emoji.rs
+++ b/src/plugins/emoji.rs
@@ -1,10 +1,12 @@
extern crate unicode_names;
use std::fmt;
+use std::marker::PhantomData;
use irc::client::prelude::*;
use plugin::*;
+use FrippyClient;
use error::ErrorKind as FrippyErrorKind;
use error::FrippyError;
@@ -33,11 +35,15 @@ impl fmt::Display for EmojiHandle {
}
#[derive(PluginName, Default, Debug)]
-pub struct Emoji;
+pub struct Emoji<C> {
+ phantom: PhantomData<C>,
+}
-impl Emoji {
- pub fn new() -> Emoji {
- Emoji {}
+impl<C: FrippyClient> Emoji<C> {
+ pub fn new() -> Self {
+ Emoji {
+ phantom: PhantomData,
+ }
}
fn emoji(&self, content: &str) -> Option<String> {
@@ -102,8 +108,9 @@ impl Emoji {
}
}
-impl Plugin for Emoji {
- fn execute(&self, client: &IrcClient, message: &Message) -> ExecutionStatus {
+impl<C: FrippyClient> Plugin for Emoji<C> {
+ type Client = C;
+ fn execute(&self, client: &Self::Client, message: &Message) -> ExecutionStatus {
match message.command {
Command::PRIVMSG(_, ref content) => {
if let Some(emojis) = self.emoji(content) {
@@ -121,11 +128,11 @@ impl Plugin for Emoji {
}
}
- fn execute_threaded(&self, _: &IrcClient, _: &Message) -> Result<(), FrippyError> {
+ fn execute_threaded(&self, _: &Self::Client, _: &Message) -> Result<(), FrippyError> {
panic!("Emoji should not use threading")
}
- fn command(&self, client: &IrcClient, command: PluginCommand) -> Result<(), FrippyError> {
+ fn command(&self, client: &Self::Client, command: PluginCommand) -> Result<(), FrippyError> {
client
.send_notice(
&command.source,
@@ -136,7 +143,7 @@ impl Plugin for Emoji {
Ok(())
}
- fn evaluate(&self, _: &IrcClient, command: PluginCommand) -> Result<String, String> {
+ fn evaluate(&self, _: &Self::Client, command: PluginCommand) -> Result<String, String> {
if let Some(emojis) = self.emoji(&command.tokens[0]) {
Ok(emojis)
} else {
diff --git a/src/plugins/factoids/mod.rs b/src/plugins/factoids/mod.rs
index 6ff2132..10f5131 100644
--- a/src/plugins/factoids/mod.rs
+++ b/src/plugins/factoids/mod.rs
@@ -4,12 +4,14 @@ use self::rlua::prelude::*;
use antidote::RwLock;
use irc::client::prelude::*;
use std::fmt;
+use std::marker::PhantomData;
use std::str::FromStr;
use chrono::NaiveDateTime;
use time;
use plugin::*;
+use FrippyClient;
pub mod database;
use self::database::Database;
@@ -30,14 +32,16 @@ enum FactoidResponse {
}
#[derive(PluginName)]
-pub struct Factoids<T: Database> {
+pub struct Factoids<T: Database, C: Client> {
factoids: RwLock<T>,
+ phantom: PhantomData<C>,
}
-impl<T: Database> Factoids<T> {
- pub fn new(db: T) -> Factoids<T> {
+impl<T: Database, C: Client> Factoids<T, C> {
+ pub fn new(db: T) -> Self {
Factoids {
factoids: RwLock::new(db),
+ phantom: PhantomData,
}
}
@@ -228,8 +232,9 @@ impl<T: Database> Factoids<T> {
}
}
-impl<T: Database> Plugin for Factoids<T> {
- fn execute(&self, _: &IrcClient, message: &Message) -> ExecutionStatus {
+impl<T: Database, C: FrippyClient> Plugin for Factoids<T, C> {
+ type Client = C;
+ fn execute(&self, _: &Self::Client, message: &Message) -> ExecutionStatus {
match message.command {
Command::PRIVMSG(_, ref content) => if content.starts_with('!') {
ExecutionStatus::RequiresThread
@@ -240,7 +245,11 @@ impl<T: Database> Plugin for Factoids<T> {
}
}
- fn execute_threaded(&self, client: &IrcClient, message: &Message) -> Result<(), FrippyError> {
+ fn execute_threaded(
+ &self,
+ client: &Self::Client,
+ message: &Message,
+ ) -> Result<(), FrippyError> {
if let Command::PRIVMSG(_, mut content) = message.command.clone() {
content.remove(0);
@@ -262,7 +271,11 @@ impl<T: Database> Plugin for Factoids<T> {
Ok(())
}
- fn command(&self, client: &IrcClient, mut command: PluginCommand) -> Result<(), FrippyError> {
+ fn command(
+ &self,
+ client: &Self::Client,
+ mut command: PluginCommand,
+ ) -> Result<(), FrippyError> {
use self::FactoidResponse::{Private, Public};
if command.tokens.is_empty() {
@@ -310,14 +323,14 @@ impl<T: Database> Plugin for Factoids<T> {
Ok(())
}
- fn evaluate(&self, _: &IrcClient, _: PluginCommand) -> Result<String, String> {
+ fn evaluate(&self, _: &Self::Client, _: PluginCommand) -> Result<String, String> {
Err(String::from(
"Evaluation of commands is not implemented for Factoids at this time",
))
}
}
-impl<T: Database> fmt::Debug for Factoids<T> {
+impl<T: Database, C: FrippyClient> fmt::Debug for Factoids<T, C> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Factoids {{ ... }}")
}
diff --git a/src/plugins/factoids/utils.rs b/src/plugins/factoids/utils.rs
index 9352a43..a7bf04a 100644
--- a/src/plugins/factoids/utils.rs
+++ b/src/plugins/factoids/utils.rs
@@ -38,7 +38,9 @@ pub fn download(_: &Lua, url: String) -> Result<String, LuaError> {
fn convert_value(lua: &Lua, sval: SerdeValue, max_recurs: usize) -> Result<LuaValue, LuaError> {
if max_recurs == 0 {
- return Err(RuntimeError(String::from("Reached max recursion level - json is nested too deep")));
+ return Err(RuntimeError(String::from(
+ "Reached max recursion level - json is nested too deep",
+ )));
}
let lval = match sval {
@@ -46,7 +48,9 @@ fn convert_value(lua: &Lua, sval: SerdeValue, max_recurs: usize) -> Result<LuaVa
SerdeValue::Bool(b) => LuaValue::Boolean(b),
SerdeValue::String(s) => LuaValue::String(lua.create_string(&s)?),
SerdeValue::Number(n) => {
- let f = n.as_f64().ok_or(RuntimeError(String::from("Failed to convert number into double",)))?;
+ let f = n.as_f64().ok_or(RuntimeError(String::from(
+ "Failed to convert number into double",
+ )))?;
LuaValue::Number(f)
}
SerdeValue::Array(arr) => {
diff --git a/src/plugins/help.rs b/src/plugins/help.rs
index f048a8e..9a67c99 100644
--- a/src/plugins/help.rs
+++ b/src/plugins/help.rs
@@ -1,30 +1,38 @@
+use std::marker::PhantomData;
+
use irc::client::prelude::*;
use plugin::*;
+use FrippyClient;
use error::ErrorKind as FrippyErrorKind;
use error::FrippyError;
use failure::ResultExt;
#[derive(PluginName, Default, Debug)]
-pub struct Help;
+pub struct Help<C> {
+ phantom: PhantomData<C>,
+}
-impl Help {
- pub fn new() -> Help {
- Help {}
+impl<C: FrippyClient> Help<C> {
+ pub fn new() -> Self {
+ Help {
+ phantom: PhantomData,
+ }
}
}
-impl Plugin for Help {
- fn execute(&self, _: &IrcClient, _: &Message) -> ExecutionStatus {
+impl<C: FrippyClient> Plugin for Help<C> {
+ type Client = C;
+ fn execute(&self, _: &Self::Client, _: &Message) -> ExecutionStatus {
ExecutionStatus::Done
}
- fn execute_threaded(&self, _: &IrcClient, _: &Message) -> Result<(), FrippyError> {
+ fn execute_threaded(&self, _: &Self::Client, _: &Message) -> Result<(), FrippyError> {
panic!("Help should not use threading")
}
- fn command(&self, client: &IrcClient, command: PluginCommand) -> Result<(), FrippyError> {
+ fn command(&self, client: &Self::Client, command: PluginCommand) -> Result<(), FrippyError> {
client
.send_notice(
&command.source,
@@ -37,7 +45,7 @@ impl Plugin for Help {
Ok(())
}
- fn evaluate(&self, _: &IrcClient, _: PluginCommand) -> Result<String, String> {
+ fn evaluate(&self, _: &Self::Client, _: PluginCommand) -> Result<String, String> {
Err(String::from("Help has not been added yet."))
}
}
diff --git a/src/plugins/keepnick.rs b/src/plugins/keepnick.rs
index a728c63..6ba16c1 100644
--- a/src/plugins/keepnick.rs
+++ b/src/plugins/keepnick.rs
@@ -1,20 +1,27 @@
+use std::marker::PhantomData;
+
use irc::client::prelude::*;
use plugin::*;
+use FrippyClient;
use error::ErrorKind as FrippyErrorKind;
use error::FrippyError;
use failure::ResultExt;
#[derive(PluginName, Default, Debug)]
-pub struct KeepNick;
+pub struct KeepNick<C> {
+ phantom: PhantomData<C>,
+}
-impl KeepNick {
- pub fn new() -> KeepNick {
- KeepNick {}
+impl<C: FrippyClient> KeepNick<C> {
+ pub fn new() -> Self {
+ KeepNick {
+ phantom: PhantomData,
+ }
}
- fn check_nick(&self, client: &IrcClient, leaver: &str) -> ExecutionStatus {
+ fn check_nick(&self, client: &C, leaver: &str) -> ExecutionStatus {
let cfg_nick = match client.config().nickname {
Some(ref nick) => nick.clone(),
None => return ExecutionStatus::Done,
@@ -41,8 +48,9 @@ impl KeepNick {
}
}
-impl Plugin for KeepNick {
- fn execute(&self, client: &IrcClient, message: &Message) -> ExecutionStatus {
+impl<C: FrippyClient> Plugin for KeepNick<C> {
+ type Client = C;
+ fn execute(&self, client: &Self::Client, message: &Message) -> ExecutionStatus {
match message.command {
Command::QUIT(ref nick) => {
self.check_nick(client, &nick.clone().unwrap_or_else(String::new))
@@ -51,11 +59,11 @@ impl Plugin for KeepNick {
}
}
- fn execute_threaded(&self, _: &IrcClient, _: &Message) -> Result<(), FrippyError> {
+ fn execute_threaded(&self, _: &Self::Client, _: &Message) -> Result<(), FrippyError> {
panic!("Tell should not use threading")
}
- fn command(&self, client: &IrcClient, command: PluginCommand) -> Result<(), FrippyError> {
+ fn command(&self, client: &Self::Client, command: PluginCommand) -> Result<(), FrippyError> {
client
.send_notice(
&command.source,
@@ -66,7 +74,7 @@ impl Plugin for KeepNick {
Ok(())
}
- fn evaluate(&self, _: &IrcClient, _: PluginCommand) -> Result<String, String> {
+ fn evaluate(&self, _: &Self::Client, _: PluginCommand) -> Result<String, String> {
Err(String::from("This Plugin does not implement any commands."))
}
}
diff --git a/src/plugins/remind/mod.rs b/src/plugins/remind/mod.rs
index fa7cf70..fa44b0b 100644
--- a/src/plugins/remind/mod.rs
+++ b/src/plugins/remind/mod.rs
@@ -1,12 +1,16 @@
-use antidote::RwLock;
-use irc::client::prelude::*;
+use std::marker::PhantomData;
use std::thread::{sleep, spawn};
use std::{fmt, sync::Arc, time::Duration};
+use antidote::RwLock;
+use irc::client::prelude::*;
+
use chrono::{self, NaiveDateTime};
use time;
use plugin::*;
+use FrippyClient;
+
pub mod database;
mod parser;
use self::database::Database;
@@ -38,7 +42,7 @@ fn get_events<T: Database>(db: &RwLock<T>, in_next: chrono::Duration) -> Vec<dat
}
}
-fn run<T: Database>(client: &IrcClient, db: Arc<RwLock<T>>) {
+fn run<T: Database, C: FrippyClient>(client: &C, db: Arc<RwLock<T>>) {
let look_ahead = chrono::Duration::minutes(2);
let mut events = get_events(&db, look_ahead);
@@ -88,18 +92,20 @@ fn run<T: Database>(client: &IrcClient, db: Arc<RwLock<T>>) {
}
#[derive(PluginName)]
-pub struct Remind<T: 'static + Database> {
+pub struct Remind<T: Database + 'static, C> {
events: Arc<RwLock<T>>,
has_reminder: RwLock<bool>,
+ phantom: PhantomData<C>,
}
-impl<T: 'static + Database> Remind<T> {
+impl<T: Database + 'static, C: FrippyClient> Remind<T, C> {
pub fn new(db: T) -> Self {
let events = Arc::new(RwLock::new(db));
Remind {
events,
has_reminder: RwLock::new(false),
+ phantom: PhantomData,
}
}
@@ -188,8 +194,9 @@ impl<T: 'static + Database> Remind<T> {
}
}
-impl<T: Database> Plugin for Remind<T> {
- fn execute(&self, client: &IrcClient, msg: &Message) -> ExecutionStatus {
+impl<T: Database, C: FrippyClient + 'static> Plugin for Remind<T, C> {
+ type Client = C;
+ fn execute(&self, client: &Self::Client, msg: &Message) -> ExecutionStatus {
if let Command::JOIN(_, _, _) = msg.command {
let mut has_reminder = self.has_reminder.write();
@@ -206,11 +213,15 @@ impl<T: Database> Plugin for Remind<T> {
ExecutionStatus::Done
}
- fn execute_threaded(&self, _: &IrcClient, _: &Message) -> Result<(), FrippyError> {
+ fn execute_threaded(&self, _: &Self::Client, _: &Message) -> Result<(), FrippyError> {
panic!("Remind should not use frippy's threading")
}
- fn command(&self, client: &IrcClient, mut command: PluginCommand) -> Result<(), FrippyError> {
+ fn command(
+ &self,
+ client: &Self::Client,
+ mut command: PluginCommand,
+ ) -> Result<(), FrippyError> {
if command.tokens.is_empty() {
client
.send_notice(&command.source, &ErrorKind::InvalidCommand.to_string())
@@ -248,14 +259,14 @@ impl<T: Database> Plugin for Remind<T> {
Ok(())
}
- fn evaluate(&self, _: &IrcClient, _: PluginCommand) -> Result<String, String> {
+ fn evaluate(&self, _: &Self::Client, _: PluginCommand) -> Result<String, String> {
Err(String::from(
"Evaluation of commands is not implemented for remind at this time",
))
}
}
-impl<T: Database> fmt::Debug for Remind<T> {
+impl<T: Database, C: FrippyClient> fmt::Debug for Remind<T, C> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Remind {{ ... }}")
}
diff --git a/src/plugins/sed.rs b/src/plugins/sed.rs
index 368f5d4..cf7f9d5 100644
--- a/src/plugins/sed.rs
+++ b/src/plugins/sed.rs
@@ -1,11 +1,14 @@
+use std::collections::HashMap;
+use std::marker::PhantomData;
+
use antidote::RwLock;
use circular_queue::CircularQueue;
use regex::{Regex, RegexBuilder};
-use std::collections::HashMap;
use irc::client::prelude::*;
use plugin::*;
+use FrippyClient;
use self::error::*;
use error::ErrorKind as FrippyErrorKind;
@@ -14,20 +17,23 @@ use failure::Fail;
use failure::ResultExt;
lazy_static! {
- static ref RE: Regex = Regex::new(r"^s/((?:\\/|[^/])+)/((?:\\/|[^/])*)/(?:(\w+))?\s*$").unwrap();
+ static ref RE: Regex =
+ Regex::new(r"^s/((?:\\/|[^/])+)/((?:\\/|[^/])*)/(?:(\w+))?\s*$").unwrap();
}
#[derive(PluginName, Debug)]
-pub struct Sed {
+pub struct Sed<C> {
per_channel: usize,
channel_messages: RwLock<HashMap<String, CircularQueue<String>>>,
+ phantom: PhantomData<C>,
}
-impl Sed {
- pub fn new(per_channel: usize) -> Sed {
+impl<C: FrippyClient> Sed<C> {
+ pub fn new(per_channel: usize) -> Self {
Sed {
per_channel,
channel_messages: RwLock::new(HashMap::new()),
+ phantom: PhantomData,
}
}
@@ -108,8 +114,9 @@ impl Sed {
}
}
-impl Plugin for Sed {
- fn execute(&self, client: &IrcClient, message: &Message) -> ExecutionStatus {
+impl<C: FrippyClient> Plugin for Sed<C> {
+ type Client = C;
+ fn execute(&self, client: &Self::Client, message: &Message) -> ExecutionStatus {
match message.command {
Command::PRIVMSG(_, ref content) => {
let channel = message.response_target().unwrap();
@@ -145,11 +152,11 @@ impl Plugin for Sed {
}
}
- fn execute_threaded(&self, _: &IrcClient, _: &Message) -> Result<(), FrippyError> {
+ fn execute_threaded(&self, _: &Self::Client, _: &Message) -> Result<(), FrippyError> {
panic!("Sed should not use threading")
}
- fn command(&self, client: &IrcClient, command: PluginCommand) -> Result<(), FrippyError> {
+ fn command(&self, client: &Self::Client, command: PluginCommand) -> Result<(), FrippyError> {
client
.send_notice(
&command.source,
@@ -160,7 +167,7 @@ impl Plugin for Sed {
Ok(())
}
- fn evaluate(&self, _: &IrcClient, _: PluginCommand) -> Result<String, String> {
+ fn evaluate(&self, _: &Self::Client, _: PluginCommand) -> Result<String, String> {
Err(String::from(
"Evaluation of commands is not implemented for sed at this time",
))
diff --git a/src/plugins/tell/mod.rs b/src/plugins/tell/mod.rs
index 07b2478..eb7a244 100644
--- a/src/plugins/tell/mod.rs
+++ b/src/plugins/tell/mod.rs
@@ -1,3 +1,5 @@
+use std::marker::PhantomData;
+
use antidote::RwLock;
use irc::client::data::User;
use irc::client::prelude::*;
@@ -8,6 +10,7 @@ use std::time::Duration;
use time;
use plugin::*;
+use FrippyClient;
use self::error::*;
use error::ErrorKind as FrippyErrorKind;
@@ -19,22 +22,20 @@ pub mod database;
use self::database::Database;
#[derive(PluginName)]
-pub struct Tell<T: Database> {
+pub struct Tell<T: Database, C> {
tells: RwLock<T>,
+ phantom: PhantomData<C>,
}
-impl<T: Database> Tell<T> {
- pub fn new(db: T) -> Tell<T> {
+impl<T: Database, C: FrippyClient> Tell<T, C> {
+ pub fn new(db: T) -> Self {
Tell {
tells: RwLock::new(db),
+ phantom: PhantomData,
}
}
- fn tell_command(
- &self,
- client: &IrcClient,
- command: PluginCommand,
- ) -> Result<String, TellError> {
+ fn tell_command(&self, client: &C, command: PluginCommand) -> Result<String, TellError> {
if command.tokens.len() < 2 {
return Ok(self.invalid_command().to_owned());
}
@@ -105,7 +106,7 @@ impl<T: Database> Tell<T> {
})
}
- fn on_namelist(&self, client: &IrcClient, channel: &str) -> Result<(), FrippyError> {
+ fn on_namelist(&self, client: &C, channel: &str) -> Result<(), FrippyError> {
let receivers = self.tells
.read()
.get_receivers()
@@ -128,7 +129,7 @@ impl<T: Database> Tell<T> {
}
}
- fn send_tells(&self, client: &IrcClient, receiver: &str) -> Result<(), FrippyError> {
+ fn send_tells(&self, client: &C, receiver: &str) -> Result<(), FrippyError> {
if client.current_nickname() == receiver {
return Ok(());
}
@@ -187,8 +188,9 @@ impl<T: Database> Tell<T> {
}
}
-impl<T: Database> Plugin for Tell<T> {
- fn execute(&self, client: &IrcClient, message: &Message) -> ExecutionStatus {
+impl<T: Database, C: FrippyClient> Plugin for Tell<T, C> {
+ type Client = C;
+ fn execute(&self, client: &Self::Client, message: &Message) -> ExecutionStatus {
let res = match message.command {
Command::JOIN(_, _, _) => self.send_tells(client, message.source_nickname().unwrap()),
Command::NICK(ref nick) => self.send_tells(client, nick),
@@ -211,11 +213,11 @@ impl<T: Database> Plugin for Tell<T> {
}
}
- fn execute_threaded(&self, _: &IrcClient, _: &Message) -> Result<(), FrippyError> {
+ fn execute_threaded(&self, _: &Self::Client, _: &Message) -> Result<(), FrippyError> {
panic!("Tell should not use threading")
}
- fn command(&self, client: &IrcClient, command: PluginCommand) -> Result<(), FrippyError> {
+ fn command(&self, client: &Self::Client, command: PluginCommand) -> Result<(), FrippyError> {
if command.tokens.is_empty() {
client
.send_notice(&command.source, &self.invalid_command())
@@ -242,13 +244,13 @@ impl<T: Database> Plugin for Tell<T> {
Ok(())
}
- fn evaluate(&self, _: &IrcClient, _: PluginCommand) -> Result<String, String> {
+ fn evaluate(&self, _: &Self::Client, _: PluginCommand) -> Result<String, String> {
Err(String::from("This Plugin does not implement any commands."))
}
}
use std::fmt;
-impl<T: Database> fmt::Debug for Tell<T> {
+impl<T: Database, C: FrippyClient> fmt::Debug for Tell<T, C> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Tell {{ ... }}")
}
diff --git a/src/plugins/url.rs b/src/plugins/url.rs
index 971597d..24b2948 100644
--- a/src/plugins/url.rs
+++ b/src/plugins/url.rs
@@ -1,5 +1,6 @@
extern crate htmlescape;
+use std::marker::PhantomData;
use std::time::Duration;
use irc::client::prelude::*;
@@ -8,6 +9,7 @@ use regex::Regex;
use plugin::*;
use utils::Url;
+use FrippyClient;
use self::error::*;
use error::ErrorKind as FrippyErrorKind;
@@ -21,8 +23,9 @@ lazy_static! {
}
#[derive(PluginName, Debug)]
-pub struct UrlTitles {
+pub struct UrlTitles<C> {
max_kib: usize,
+ phantom: PhantomData<C>,
}
#[derive(Clone, Debug)]
@@ -104,10 +107,13 @@ impl Title {
}
}
-impl UrlTitles {
+impl<C: FrippyClient> UrlTitles<C> {
/// If a file is larger than `max_kib` KiB the download is stopped
pub fn new(max_kib: usize) -> Self {
- UrlTitles { max_kib }
+ UrlTitles {
+ max_kib,
+ phantom: PhantomData,
+ }
}
fn grep_url<'a>(&self, msg: &'a str) -> Option<Url<'a>> {
@@ -148,8 +154,9 @@ impl UrlTitles {
}
}
-impl Plugin for UrlTitles {
- fn execute(&self, _: &IrcClient, message: &Message) -> ExecutionStatus {
+impl<C: FrippyClient> Plugin for UrlTitles<C> {
+ type Client = C;
+ fn execute(&self, _: &Self::Client, message: &Message) -> ExecutionStatus {
match message.command {
Command::PRIVMSG(_, ref msg) => if URL_RE.is_match(msg) {
ExecutionStatus::RequiresThread
@@ -160,7 +167,11 @@ impl Plugin for UrlTitles {
}
}
- fn execute_threaded(&self, client: &IrcClient, message: &Message) -> Result<(), FrippyError> {
+ fn execute_threaded(
+ &self,
+ client: &Self::Client,
+ message: &Message,
+ ) -> Result<(), FrippyError> {
if let Command::PRIVMSG(_, ref content) = message.command {
let title = self.url(content).context(FrippyErrorKind::Url)?;
let response = format!("[URL] {}", title);
@@ -173,7 +184,7 @@ impl Plugin for UrlTitles {
Ok(())
}
- fn command(&self, client: &IrcClient, command: PluginCommand) -> Result<(), FrippyError> {
+ fn command(&self, client: &Self::Client, command: PluginCommand) -> Result<(), FrippyError> {
client
.send_notice(
&command.source,
@@ -184,7 +195,7 @@ impl Plugin for UrlTitles {
Ok(())
}
- fn evaluate(&self, _: &IrcClient, command: PluginCommand) -> Result<String, String> {
+ fn evaluate(&self, _: &Self::Client, command: PluginCommand) -> Result<String, String> {
self.url(&command.tokens[0])
.map_err(|e| e.cause().unwrap().to_string())
}