diff options
Diffstat (limited to 'src/plugins')
| -rw-r--r-- | src/plugins/quote/database.rs | 125 | ||||
| -rw-r--r-- | src/plugins/quote/mod.rs | 39 |
2 files changed, 150 insertions, 14 deletions
diff --git a/src/plugins/quote/database.rs b/src/plugins/quote/database.rs index 3c904df..9e6bb66 100644 --- a/src/plugins/quote/database.rs +++ b/src/plugins/quote/database.rs @@ -45,6 +45,20 @@ pub trait Database: Send + Sync { fn get_channel_quote(&self, channel: &str, idx: i32) -> Result<Quote, QuoteError>; fn count_user_quotes(&self, quotee: &str, channel: &str) -> Result<i32, QuoteError>; fn count_channel_quotes(&self, channel: &str) -> Result<i32, QuoteError>; + fn search_user_quote( + &self, + query: &str, + quotee: &str, + channel: &str, + offset: i32, + ) -> Result<Quote, QuoteError>; + + fn search_channel_quote( + &self, + query: &str, + channel: &str, + offset: i32, + ) -> Result<Quote, QuoteError>; } // HashMap @@ -70,34 +84,79 @@ impl<S: ::std::hash::BuildHasher + Send + Sync> Database } fn get_user_quote(&self, quotee: &str, channel: &str, idx: i32) -> Result<Quote, QuoteError> { - Ok(self + let quote = self .get(&(quotee.to_owned(), channel.to_owned(), idx)) .cloned() - .ok_or(ErrorKind::NotFound)?) + .ok_or(ErrorKind::NotFound)?; + + Ok(quote) } fn get_channel_quote(&self, channel: &str, idx: i32) -> Result<Quote, QuoteError> { - Ok(self + let quote = self .iter() .filter(|&(&(_, ref c, _), _)| c == channel) .nth(idx as usize - 1) .ok_or(ErrorKind::NotFound)? .1 - .clone()) + .clone(); + + Ok(quote) } fn count_user_quotes(&self, quotee: &str, channel: &str) -> Result<i32, QuoteError> { - Ok(self + let count = self .iter() - .filter(|&(&(ref n, ref c, _), _)| n == quotee && c == channel) - .count() as i32) + .filter(|&(&(ref q, ref c, _), _)| q == quotee && c == channel) + .count(); + + Ok(count as i32) } fn count_channel_quotes(&self, channel: &str) -> Result<i32, QuoteError> { - Ok(self + let count = self .iter() .filter(|&(&(_, ref c, _), _)| c == channel) - .count() as i32) + .count(); + + Ok(count as i32) + } + + fn search_user_quote( + &self, + query: &str, + quotee: &str, + channel: &str, + offset: i32, + ) -> Result<Quote, QuoteError> { + let quote = self + .iter() + .filter(|&(&(ref q, ref c, _), _)| q == quotee && c == channel) + .filter(|&(&(_, _, _), q)| q.content.to_lowercase().contains(&query.to_lowercase())) + .nth(offset as usize) + .ok_or(ErrorKind::NotFound)? + .1 + .clone(); + + Ok(quote) + } + + fn search_channel_quote( + &self, + query: &str, + channel: &str, + offset: i32, + ) -> Result<Quote, QuoteError> { + let quote = self + .iter() + .filter(|&(&(_, ref c, _), _)| c == channel) + .filter(|&(&(_, _, _), q)| q.content.contains(query)) + .nth(offset as usize) + .ok_or(ErrorKind::NotFound)? + .1 + .clone(); + + Ok(quote) } } @@ -134,19 +193,23 @@ impl Database for Arc<Pool<ConnectionManager<MysqlConnection>>> { fn get_user_quote(&self, quotee: &str, channel: &str, idx: i32) -> Result<Quote, QuoteError> { let conn = &*self.get().context(ErrorKind::NoConnection)?; - Ok(quotes::table + let quote = quotes::table .find((quotee, channel, idx)) .first(conn) - .context(ErrorKind::MysqlError)?) + .context(ErrorKind::MysqlError)?; + + Ok(quote) } fn get_channel_quote(&self, channel: &str, idx: i32) -> Result<Quote, QuoteError> { let conn = &*self.get().context(ErrorKind::NoConnection)?; - Ok(quotes::table + let quote = quotes::table .filter(quotes::columns::channel.eq(channel)) .offset(idx as i64 - 1) .first(conn) - .context(ErrorKind::MysqlError)?) + .context(ErrorKind::MysqlError)?; + + Ok(quote) } fn count_user_quotes(&self, quotee: &str, channel: &str) -> Result<i32, QuoteError> { @@ -177,4 +240,40 @@ impl Database for Arc<Pool<ConnectionManager<MysqlConnection>>> { Err(e) => Err(e).context(ErrorKind::MysqlError)?, } } + + fn search_user_quote( + &self, + query: &str, + quotee: &str, + channel: &str, + offset: i32, + ) -> Result<Quote, QuoteError> { + let conn = &*self.get().context(ErrorKind::NoConnection)?; + let quote = quotes::table + .filter(quotes::columns::channel.eq(channel)) + .filter(quotes::columns::quotee.eq(quotee)) + .filter(quotes::columns::content.like(&format!("%{}%", query))) + .offset(offset as i64) + .first(conn) + .context(ErrorKind::MysqlError)?; + + Ok(quote) + } + + fn search_channel_quote( + &self, + query: &str, + channel: &str, + offset: i32, + ) -> Result<Quote, QuoteError> { + let conn = &*self.get().context(ErrorKind::NoConnection)?; + let quote = quotes::table + .filter(quotes::columns::channel.eq(channel)) + .filter(quotes::columns::content.like(&format!("%{}%", query))) + .offset(offset as i64) + .first(conn) + .context(ErrorKind::MysqlError)?; + + Ok(quote) + } } diff --git a/src/plugins/quote/mod.rs b/src/plugins/quote/mod.rs index e7ec77c..e5117eb 100644 --- a/src/plugins/quote/mod.rs +++ b/src/plugins/quote/mod.rs @@ -1,5 +1,6 @@ use std::fmt; use std::marker::PhantomData; +use std::ops::Deref; use std::str::FromStr; use antidote::RwLock; @@ -132,6 +133,41 @@ impl<T: Database, C: Client> Quote<T, C> { Ok(response) } + fn search(&self, command: &mut PluginCommand) -> Result<String, QuoteError> { + if command.tokens.len() < 2 { + Err(ErrorKind::InvalidCommand)?; + } + + let user = match command.tokens.remove(0).deref() { + "user" => Some(command.tokens.remove(0)), + "channel" => None, + _ => return Err(ErrorKind::InvalidCommand.into()), + }; + let channel = &command.target; + + if command.tokens.is_empty() { + Err(ErrorKind::InvalidCommand)?; + } + + let query = command.tokens.join(" "); + let quote = if let Some(user) = user { + self.quotes + .read() + .search_user_quote(&query, &user, channel, 0) + .context(ErrorKind::NotFound)? + } else { + self.quotes + .read() + .search_channel_quote(&query, channel, 0) + .context(ErrorKind::NotFound)? + }; + + Ok(format!( + "\"{}\" - {}[{}]", + quote.content, quote.quotee, quote.idx + )) + } + fn info(&self, command: &PluginCommand) -> Result<String, QuoteError> { let tokens = command .tokens @@ -187,7 +223,7 @@ impl<T: Database, C: Client> Quote<T, C> { fn help(&self) -> &str { "usage: quotes <subcommand>\r\n\ - subcommands: add, get, info, help" + subcommands: add, get, search info, help" } } @@ -223,6 +259,7 @@ impl<T: Database, C: FrippyClient> Plugin for Quote<T, C> { let result = match sub_command.as_ref() { "add" => self.add(&mut command).map(|s| Private(s.to_owned())), "get" => self.get(&command).map(Public), + "search" => self.search(&mut command).map(Public), "info" => self.info(&command).map(Public), "help" => Ok(Private(self.help().to_owned())), _ => Err(ErrorKind::InvalidCommand.into()), |
