Added Command iterator. Added a test and a use case example.
This commit is contained in:
parent
0ac5737f7f
commit
04dccf5ce2
4 changed files with 83 additions and 1 deletions
43
examples/simple_cmd.rs
Normal file
43
examples/simple_cmd.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
extern crate irc;
|
||||
|
||||
use std::default::Default;
|
||||
use irc::client::prelude::*;
|
||||
use irc::client::data::message::ToMessage;
|
||||
|
||||
// This is the same as simple.rs, except we use an Iterator over Commands
|
||||
// instead of an Iterator over Messages. A Command is basically a parsed Message,
|
||||
// so Commands and Messages are interchangeable. It is up to the library user to
|
||||
// choose one.
|
||||
|
||||
fn main() {
|
||||
let config = Config {
|
||||
nickname: Some(format!("pickles")),
|
||||
alt_nicks: Some(vec![format!("bananas"), format!("apples")]),
|
||||
server: Some(format!("irc.fyrechat.net")),
|
||||
channels: Some(vec![format!("#vana")]),
|
||||
.. Default::default()
|
||||
};
|
||||
let irc_server = IrcServer::from_config(config).unwrap();
|
||||
// The wrapper provides us with methods like send_privmsg(...) and identify(...)
|
||||
let server = Wrapper::new(&irc_server);
|
||||
server.identify().unwrap();
|
||||
for command in server.iter_cmd() {
|
||||
// Ignore errors
|
||||
// Use of unwrap() with iter_cmd() is discouraged because iter_cmd() is still unstable
|
||||
// and has trouble converting some custom Messages into Commands
|
||||
match command {
|
||||
Ok(cmd) => {
|
||||
print!("{}", cmd.to_message().into_string());
|
||||
match cmd {
|
||||
Command::PRIVMSG(target, text) => {
|
||||
if text[..].contains("pickles") {
|
||||
server.send_privmsg(&target[..], "Hi!").unwrap();
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
},
|
||||
Err(_) => ()
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1145,6 +1145,12 @@ impl Command {
|
|||
return Err(invalid_input())
|
||||
})
|
||||
}
|
||||
|
||||
/// Converts an `IoResult<Message>` holding a Message into an `IoResult<Command>`
|
||||
#[unstable = "This feature is still relatively new."]
|
||||
pub fn from_message_io(m: IoResult<Message>) -> IoResult<Command> {
|
||||
m.and_then(|msg| Command::from_message(&msg))
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of all of the subcommands for the capabilities extension.
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::borrow::ToOwned;
|
|||
use std::collections::HashMap;
|
||||
use std::old_io::{BufferedReader, BufferedWriter, IoError, IoErrorKind, IoResult};
|
||||
use std::sync::{Mutex, RwLock};
|
||||
use std::iter::Map;
|
||||
use client::conn::{Connection, NetStream};
|
||||
use client::data::{Command, Config, Message, Response, User};
|
||||
use client::data::Command::{JOIN, NICK, NICKSERV, PONG, MODE};
|
||||
|
@ -24,6 +25,9 @@ pub trait Server<'a, T, U> {
|
|||
/// Gets an Iterator over Messages received by this Server.
|
||||
#[stable]
|
||||
fn iter(&'a self) -> ServerIterator<'a, T, U>;
|
||||
/// Gets an Iterator over Commands received by this Server.
|
||||
#[unstable = "Feature is still relatively new."]
|
||||
fn iter_cmd(&'a self) -> ServerCmdIterator<'a, T, U>;
|
||||
/// Gets a list of Users in the specified channel. This will be none if the channel is not
|
||||
/// being tracked, or if tracking is not supported altogether.
|
||||
#[stable]
|
||||
|
@ -95,6 +99,10 @@ impl<'a, T: IrcReader, U: IrcWriter> Server<'a, T, U> for IrcServer<T, U> {
|
|||
ServerIterator::new(self)
|
||||
}
|
||||
|
||||
fn iter_cmd(&'a self) -> ServerCmdIterator<'a, T, U> {
|
||||
self.iter().map(Command::from_message_io)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "nochanlists"))]
|
||||
fn list_users(&self, chan: &str) -> Option<Vec<User>> {
|
||||
self.chanlists.lock().unwrap().get(&chan.to_owned()).cloned()
|
||||
|
@ -257,6 +265,12 @@ pub struct ServerIterator<'a, T: IrcReader, U: IrcWriter> {
|
|||
server: &'a IrcServer<T, U>
|
||||
}
|
||||
|
||||
/// An Iterator over an IrcServer's incoming Commands.
|
||||
/// Commands and Messages are interchangeable. This is just a convenient way to get
|
||||
/// a sanitized, already-parsed IRC message.
|
||||
pub type ServerCmdIterator<'a, T, U> =
|
||||
Map<ServerIterator<'a, T, U>, fn(IoResult<Message>) -> IoResult<Command>>;
|
||||
|
||||
#[unstable = "Design is liable to change to accomodate new functionality."]
|
||||
impl<'a, T: IrcReader, U: IrcWriter> ServerIterator<'a, T, U> {
|
||||
/// Creates a new ServerIterator for the desired IrcServer.
|
||||
|
@ -312,6 +326,7 @@ mod test {
|
|||
use client::data::{Config, User};
|
||||
use client::data::command::Command::PRIVMSG;
|
||||
use client::data::kinds::IrcReader;
|
||||
use client::data::message::ToMessage;
|
||||
|
||||
pub fn test_config() -> Config {
|
||||
Config {
|
||||
|
@ -344,6 +359,20 @@ mod test {
|
|||
assert_eq!(&messages[..], exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_cmd() {
|
||||
let exp = "PRIVMSG test :Hi!\r\nPRIVMSG test :This is a test!\r\n\
|
||||
JOIN #test\r\n";
|
||||
let server = IrcServer::from_connection(test_config(), Connection::new(
|
||||
MemReader::new(exp.as_bytes().to_vec()), NullWriter
|
||||
));
|
||||
let mut messages = String::new();
|
||||
for command in server.iter_cmd() {
|
||||
messages.push_str(&command.unwrap().to_message().into_string());
|
||||
}
|
||||
assert_eq!(&messages[..], exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handle_message() {
|
||||
let value = "PING :irc.test.net\r\n:irc.test.net 376 test :End of /MOTD command.\r\n";
|
||||
|
|
|
@ -9,7 +9,7 @@ use client::data::Command::{OPER, PASS, PONG, PRIVMSG, QUIT, SAMODE, SANICK, TOP
|
|||
use client::data::command::CapSubCommand::{END, REQ};
|
||||
use client::data::kinds::{IrcReader, IrcWriter};
|
||||
#[cfg(feature = "ctcp")] use time::get_time;
|
||||
use client::server::{Server, ServerIterator};
|
||||
use client::server::{Server, ServerIterator, ServerCmdIterator};
|
||||
|
||||
/// Functionality-providing wrapper for Server.
|
||||
/// Wrappers are currently not thread-safe, and should be created per-thread, as needed.
|
||||
|
@ -31,6 +31,10 @@ impl<'a, T: IrcReader, U: IrcWriter> Server<'a, T, U> for Wrapper<'a, T, U> {
|
|||
self.server.iter()
|
||||
}
|
||||
|
||||
fn iter_cmd(&'a self) -> ServerCmdIterator<'a, T, U> {
|
||||
self.server.iter_cmd()
|
||||
}
|
||||
|
||||
fn list_users(&self, chan: &str) -> Option<Vec<User>> {
|
||||
self.server.list_users(chan)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue