Added documentation everywhere.
This commit is contained in:
parent
63f4ca5097
commit
5bbde7e96c
7 changed files with 141 additions and 53 deletions
12
src/conn.rs
12
src/conn.rs
|
@ -1,14 +1,20 @@
|
|||
//! Thread-safe connections on any IrcWriters and IrcReaders
|
||||
#![experimental]
|
||||
use std::sync::Mutex;
|
||||
use std::io::{BufferedReader, BufferedWriter, IoResult, TcpStream};
|
||||
use data::kinds::{IrcWriter, IrcReader};
|
||||
use data::message::Message;
|
||||
|
||||
/// A thread-safe connection
|
||||
#[experimental]
|
||||
pub struct Connection<T, U> where T: IrcWriter, U: IrcReader {
|
||||
writer: Mutex<T>,
|
||||
reader: Mutex<U>,
|
||||
}
|
||||
|
||||
impl Connection<BufferedWriter<TcpStream>, BufferedReader<TcpStream>> {
|
||||
/// Creates a thread-safe TCP connection to the specified server
|
||||
#[experimental]
|
||||
pub fn connect(host: &str, port: u16) -> IoResult<Connection<BufferedWriter<TcpStream>, BufferedReader<TcpStream>>> {
|
||||
let socket = try!(TcpStream::connect(host, port));
|
||||
Ok(Connection::new(BufferedWriter::new(socket.clone()), BufferedReader::new(socket)))
|
||||
|
@ -16,6 +22,8 @@ impl Connection<BufferedWriter<TcpStream>, BufferedReader<TcpStream>> {
|
|||
}
|
||||
|
||||
impl<T, U> Connection<T, U> where T: IrcWriter, U: IrcReader {
|
||||
/// Creates a new connection from any arbitrary IrcWriter and IrcReader
|
||||
#[experimental]
|
||||
pub fn new(writer: T, reader: U) -> Connection<T, U> {
|
||||
Connection {
|
||||
writer: Mutex::new(writer),
|
||||
|
@ -23,12 +31,16 @@ impl<T, U> Connection<T, U> where T: IrcWriter, U: IrcReader {
|
|||
}
|
||||
}
|
||||
|
||||
/// Sends a Message over this connection
|
||||
#[experimental]
|
||||
pub fn send(&self, message: Message) -> IoResult<()> {
|
||||
let mut send = self.writer.lock();
|
||||
try!(send.write_str(message.into_string()[]));
|
||||
send.flush()
|
||||
}
|
||||
|
||||
/// Receives a single line from this connection
|
||||
#[experimental]
|
||||
pub fn recv(&self) -> IoResult<String> {
|
||||
self.reader.lock().read_line()
|
||||
}
|
||||
|
|
|
@ -1,101 +1,104 @@
|
|||
//! Enumeration of all available client commands
|
||||
#![stable]
|
||||
use std::io::{InvalidInput, IoError, IoResult};
|
||||
use data::message::Message;
|
||||
|
||||
/// List of all client commands as defined in RFC 2812.
|
||||
/// List of all client commands as defined in [RFC 2812](http://tools.ietf.org/html/rfc2812)
|
||||
#[stable]
|
||||
#[deriving(Show, PartialEq)]
|
||||
pub enum Command {
|
||||
// 3.1 Connection Registration
|
||||
/// PASS <password>
|
||||
/// PASS password
|
||||
PASS(String),
|
||||
/// NICK <nickname>
|
||||
/// NICK nickname
|
||||
NICK(String),
|
||||
/// USER <user> <mode> * <realname>
|
||||
/// USER user mode * realname
|
||||
USER(String, String, String),
|
||||
/// OPER <name> <password>
|
||||
/// OPER name password
|
||||
OPER(String, String),
|
||||
/// MODE <nickname> <modes>
|
||||
/// MODE <channel> <modes> [<modeparams>]
|
||||
/// MODE nickname modes
|
||||
/// MODE channel modes [modeparams]
|
||||
MODE(String, String, Option<String>),
|
||||
/// SERVICE <nickname> <reserved> <distribution> <type> <reserved> <info>
|
||||
/// SERVICE nickname reserved distribution type reserved info
|
||||
SERVICE(String, String, String, String, String, String),
|
||||
/// QUIT <Quit Message>
|
||||
/// QUIT Quit Message
|
||||
QUIT(Option<String>),
|
||||
/// SQUIT <server> <comment>
|
||||
/// SQUIT server comment
|
||||
SQUIT(String, String),
|
||||
|
||||
// 3.2 Channel operations
|
||||
/// JOIN <chanlist> [<chankeys>]
|
||||
/// JOIN chanlist [chankeys]
|
||||
JOIN(String, Option<String>),
|
||||
/// PART <chanlist> [<Part Message>]
|
||||
/// PART chanlist [Part Message]
|
||||
PART(String, Option<String>),
|
||||
// MODE is already defined.
|
||||
// MODE(String, String, Option<String>),
|
||||
/// TOPIC <channel> [<topic>]
|
||||
/// TOPIC channel [topic]
|
||||
TOPIC(String, Option<String>),
|
||||
/// NAMES [<chanlist> [<target>]]
|
||||
/// NAMES [chanlist [target]]
|
||||
NAMES(Option<String>, Option<String>),
|
||||
/// LIST [<chanlist> [<target>]]
|
||||
/// LIST [chanlist [target]]
|
||||
LIST(Option<String>, Option<String>),
|
||||
/// INVITE <nickname> <channel>
|
||||
/// INVITE nickname channel
|
||||
INVITE(String, String),
|
||||
/// KICK <chanlist> <userlist> [<comment>]
|
||||
/// KICK chanlist userlist [comment]
|
||||
KICK(String, String, Option<String>),
|
||||
|
||||
// 3.3 Sending messages
|
||||
/// PRIVMSG <msgtarget> <text to be sent>
|
||||
/// PRIVMSG msgtarget text to be sent
|
||||
PRIVMSG(String, String),
|
||||
/// NOTICE <msgtarget> <text>
|
||||
/// NOTICE msgtarget text
|
||||
NOTICE(String, String),
|
||||
|
||||
// 3.4 Server queries and commands
|
||||
/// MOTD [<target>]
|
||||
/// MOTD [target]
|
||||
MOTD(Option<String>),
|
||||
/// LUSERS [<mask> [<target>]]
|
||||
/// LUSERS [mask [target]]
|
||||
LUSERS(Option<String>, Option<String>),
|
||||
/// VERSION [<target>]
|
||||
/// VERSION [target]
|
||||
VERSION(Option<String>),
|
||||
/// STATS [<query> [<target>]]
|
||||
/// STATS [query [target]]
|
||||
STATS(Option<String>, Option<String>),
|
||||
/// LINKS [[<remote server>] <server mask>]
|
||||
/// LINKS [[remote server] server mask]
|
||||
LINKS(Option<String>, Option<String>),
|
||||
/// TIME [<target>]
|
||||
/// TIME [target]
|
||||
TIME(Option<String>),
|
||||
/// CONNECT <target server> <port> [<remote server>]
|
||||
/// CONNECT target server port [remote server]
|
||||
CONNECT(String, String, Option<String>),
|
||||
/// TRACE [<target>]
|
||||
/// TRACE [target]
|
||||
TRACE(Option<String>),
|
||||
/// ADMIN [<target>]
|
||||
/// ADMIN [target]
|
||||
ADMIN(Option<String>),
|
||||
/// INFO [<target>]
|
||||
/// INFO [target]
|
||||
INFO(Option<String>),
|
||||
|
||||
// 3.5 Service Query and Commands
|
||||
/// SERVLIST [<mask> [<type>]]
|
||||
/// SERVLIST [mask [type]]
|
||||
SERVLIST(Option<String>, Option<String>),
|
||||
/// SQUERY <servicename> <text>
|
||||
/// SQUERY servicename text
|
||||
SQUERY(String, String),
|
||||
|
||||
// 3.6 User based queries
|
||||
/// WHO [<mask> ["o"]]
|
||||
/// WHO [mask ["o"]]
|
||||
WHO(Option<String>, Option<bool>),
|
||||
/// WHOIS [<target>] <masklist>
|
||||
/// WHOIS [target] masklist
|
||||
WHOIS(Option<String>, String),
|
||||
/// WHOWAS <nicklist> [<count> [<target>]]
|
||||
/// WHOWAS nicklist [count [target]]
|
||||
WHOWAS(String, Option<String>, Option<String>),
|
||||
|
||||
// 3.7 Miscellaneous messages
|
||||
/// KILL <nickname> <comment>
|
||||
/// KILL nickname comment
|
||||
KILL(String, String),
|
||||
/// PING <server1> [<server2>]
|
||||
/// PING server1 [server2]
|
||||
PING(String, Option<String>),
|
||||
/// PONG <server> [<server2>]
|
||||
/// PONG server [server2]
|
||||
PONG(String, Option<String>),
|
||||
/// ERROR <error message>
|
||||
/// ERROR error message
|
||||
ERROR(String),
|
||||
|
||||
|
||||
// 4 Optional Features
|
||||
/// AWAY [<text>]
|
||||
/// AWAY [text]
|
||||
AWAY(Option<String>),
|
||||
/// REHASH
|
||||
REHASH,
|
||||
|
@ -103,31 +106,33 @@ pub enum Command {
|
|||
DIE,
|
||||
/// RESTART
|
||||
RESTART,
|
||||
/// SUMMON <user> [<target> [<channel>]]
|
||||
/// SUMMON user [target [channel]]
|
||||
SUMMON(String, Option<String>, Option<String>),
|
||||
/// USERS [<target>]
|
||||
/// USERS [target]
|
||||
USERS(Option<String>),
|
||||
/// WALLOPS <Text to be sent>
|
||||
/// WALLOPS Text to be sent
|
||||
WALLOPS(String),
|
||||
/// USERHOST <space-separated nicklist>
|
||||
/// USERHOST space-separated nicklist
|
||||
USERHOST(Vec<String>),
|
||||
/// ISON <space-separated nicklist>
|
||||
/// ISON space-separated nicklist
|
||||
ISON(Vec<String>),
|
||||
|
||||
// Non-RFC commands from InspIRCd
|
||||
/// SAJOIN <nickname> <channel>
|
||||
/// SAJOIN nickname channel
|
||||
SAJOIN(String, String),
|
||||
/// SAMODE <target> <modes> [<modeparams>]
|
||||
/// SAMODE target modes [modeparams]
|
||||
SAMODE(String, String, Option<String>),
|
||||
/// SANICK <old nickname> <new nickname>
|
||||
/// SANICK old nickname new nickname
|
||||
SANICK(String, String),
|
||||
/// SAPART <nickname> <reason>
|
||||
/// SAPART nickname reason
|
||||
SAPART(String, String),
|
||||
/// SAQUIT <nickname> <reason>
|
||||
/// SAQUIT nickname reason
|
||||
SAQUIT(String, String),
|
||||
}
|
||||
|
||||
impl Command {
|
||||
/// Converts a Command into a Message
|
||||
#[stable]
|
||||
pub fn to_message(self) -> Message {
|
||||
match self {
|
||||
PASS(p) => Message::new(None, "PASS", None, Some(p[])),
|
||||
|
@ -221,6 +226,8 @@ impl Command {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a Message into a Command
|
||||
#[stable]
|
||||
pub fn from_message(m: Message) -> IoResult<Command> {
|
||||
Ok(if let "PASS" = m.command[] {
|
||||
if m.suffix.is_some() {
|
||||
|
@ -738,6 +745,8 @@ impl Command {
|
|||
}
|
||||
}
|
||||
|
||||
/// Produces an invalid_input IoError
|
||||
#[stable]
|
||||
fn invalid_input() -> IoError {
|
||||
IoError {
|
||||
kind: InvalidInput,
|
||||
|
|
|
@ -1,22 +1,37 @@
|
|||
//! JSON configuration files using libserialize
|
||||
#![stable]
|
||||
use std::collections::HashMap;
|
||||
use std::io::fs::File;
|
||||
use std::io::{InvalidInput, IoError, IoResult};
|
||||
use serialize::json::decode;
|
||||
|
||||
/// Configuration data
|
||||
#[deriving(Clone, Decodable)]
|
||||
#[unstable]
|
||||
pub struct Config {
|
||||
/// A list of the owners of the bot by nickname
|
||||
pub owners: Vec<String>,
|
||||
/// The bot's nickname
|
||||
pub nickname: String,
|
||||
/// The bot's username
|
||||
pub username: String,
|
||||
/// The bot's real name
|
||||
pub realname: String,
|
||||
/// The bot's password
|
||||
pub password: String,
|
||||
/// The server to connect to
|
||||
pub server: String,
|
||||
/// The port to connect on
|
||||
pub port: u16,
|
||||
/// A list of channels to join on connection
|
||||
pub channels: Vec<String>,
|
||||
/// A map of additional options to be stored in config
|
||||
pub options: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Loads a JSON configuration from the desired path.
|
||||
#[stable]
|
||||
pub fn load(path: Path) -> IoResult<Config> {
|
||||
let mut file = try!(File::open(&path));
|
||||
let data = try!(file.read_to_string());
|
||||
|
@ -27,10 +42,14 @@ impl Config {
|
|||
})
|
||||
}
|
||||
|
||||
/// Loads a JSON configuration using the string as a UTF-8 path.
|
||||
#[stable]
|
||||
pub fn load_utf8(path: &str) -> IoResult<Config> {
|
||||
Config::load(Path::new(path))
|
||||
}
|
||||
|
||||
/// Determines whether or not the nickname provided is the owner of the bot.
|
||||
#[stable]
|
||||
pub fn is_owner(&self, nickname: &str) -> bool {
|
||||
self.owners[].contains(&String::from_str(nickname))
|
||||
}
|
||||
|
|
|
@ -1,14 +1,25 @@
|
|||
//! Messages to and from the server
|
||||
#![experimental]
|
||||
use std::from_str::FromStr;
|
||||
|
||||
/// IRC Message data
|
||||
#[experimental]
|
||||
#[deriving(Clone, PartialEq, Show)]
|
||||
pub struct Message {
|
||||
/// The message prefix (or source) as defined by [RFC 2812](http://tools.ietf.org/html/rfc2812)
|
||||
pub prefix: Option<String>,
|
||||
/// The IRC command as defined by [RFC 2812](http://tools.ietf.org/html/rfc2812)
|
||||
pub command: String,
|
||||
/// The command arguments
|
||||
pub args: Vec<String>,
|
||||
/// The message suffix as defined by [RFC 2812](http://tools.ietf.org/html/rfc2812)
|
||||
/// This is the only part of the message that is allowed to contain spaces.
|
||||
pub suffix: Option<String>,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
/// Creates a new Message
|
||||
#[experimental]
|
||||
pub fn new(prefix: Option<&str>, command: &str, args: Option<Vec<&str>>, suffix: Option<&str>)
|
||||
-> Message {
|
||||
Message {
|
||||
|
@ -19,6 +30,8 @@ impl Message {
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts a Message into a String according to the IRC protocol
|
||||
#[experimental]
|
||||
pub fn into_string(&self) -> String {
|
||||
let mut ret = String::new();
|
||||
if let Some(ref prefix) = self.prefix {
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
//! Data related to IRC functionality
|
||||
#![experimental]
|
||||
|
||||
pub mod kinds {
|
||||
//! Trait definitions of appropriate Writers and Buffers for use with this library
|
||||
#![unstable]
|
||||
|
||||
/// Trait describing all possible Writers for this library
|
||||
#[unstable]
|
||||
pub trait IrcWriter: Writer + Sized + Send + 'static {}
|
||||
impl<T> IrcWriter for T where T: Writer + Sized + Send + 'static {}
|
||||
/// Trait describing all possible Readers for this library
|
||||
#[unstable]
|
||||
pub trait IrcReader: Buffer + Sized + Send + 'static {}
|
||||
impl<T> IrcReader for T where T: Buffer + Sized + Send + 'static {}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! A simple, thread-safe IRC client library.
|
||||
#![crate_name = "irc"]
|
||||
#![crate_type = "lib"]
|
||||
#![unstable]
|
||||
|
||||
#![feature(if_let)]
|
||||
#![feature(slicing_syntax)]
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Interface for working with IRC Servers
|
||||
#![experimental]
|
||||
use std::io::{BufferedReader, BufferedWriter, IoResult, TcpStream};
|
||||
use conn::Connection;
|
||||
use data::command::Command;
|
||||
|
@ -5,18 +7,30 @@ use data::config::Config;
|
|||
use data::kinds::{IrcReader, IrcWriter};
|
||||
use data::message::Message;
|
||||
|
||||
/// Trait describing core Server functionality
|
||||
#[experimental]
|
||||
pub trait Server<'a, T, U> {
|
||||
/// Gets the configuration being used with this Server
|
||||
fn config(&self) -> &Config;
|
||||
/// Sends a Command to this Server
|
||||
fn send(&self, _: Command) -> IoResult<()>;
|
||||
/// Gets an Iterator over Messages received by this Server
|
||||
fn iter(&'a self) -> ServerIterator<'a, T, U>;
|
||||
}
|
||||
|
||||
/// A thread-safe implementation of an IRC Server connection
|
||||
#[experimental]
|
||||
pub struct IrcServer<'a, T, U> where T: IrcWriter, U: IrcReader {
|
||||
pub conn: Connection<T, U>,
|
||||
pub config: Config
|
||||
/// The thread-safe IRC connection
|
||||
conn: Connection<T, U>,
|
||||
/// The configuration used with this connection
|
||||
config: Config
|
||||
}
|
||||
|
||||
impl<'a> IrcServer<'a, BufferedWriter<TcpStream>, BufferedReader<TcpStream>> {
|
||||
pub fn new(config: &str) -> IoResult<IrcServer<'a, BufferedWriter<TcpStream>, BufferedReader<TcpStream>>> {
|
||||
/// Creates a new IRC Server connection from the specified configuration, connecting immediately.
|
||||
#[experimental]
|
||||
pub fn new(config: &str) -> IoResult<IrcServer<'a, BufferedWriter<TcpStream>, BufferedReader<TcpStream>>> {
|
||||
let config = try!(Config::load_utf8(config));
|
||||
let conn = try!(Connection::connect(config.server[], config.port));
|
||||
Ok(IrcServer {
|
||||
|
@ -26,7 +40,11 @@ impl<'a> IrcServer<'a, BufferedWriter<TcpStream>, BufferedReader<TcpStream>> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T, U> Server<'a, T, U> for IrcServer<'a, T, U> where T: IrcWriter, U: IrcReader{
|
||||
impl<'a, T, U> Server<'a, T, U> for IrcServer<'a, T, U> where T: IrcWriter, U: IrcReader {
|
||||
fn config(&self) -> &Config {
|
||||
&self.config
|
||||
}
|
||||
|
||||
fn send(&self, command: Command) -> IoResult<()> {
|
||||
self.conn.send(command.to_message())
|
||||
}
|
||||
|
@ -37,6 +55,8 @@ impl<'a, T, U> Server<'a, T, U> for IrcServer<'a, T, U> where T: IrcWriter, U: I
|
|||
}
|
||||
|
||||
impl<'a, T, U> IrcServer<'a, T, U> where T: IrcWriter, U: IrcReader {
|
||||
/// Creates an IRC server from the specified configuration, and any arbitrary Connection
|
||||
#[experimental]
|
||||
pub fn from_connection(config: &str, conn: Connection<T, U>) -> IoResult<IrcServer<'a, T, U>> {
|
||||
Ok(IrcServer {
|
||||
conn: conn,
|
||||
|
@ -45,11 +65,15 @@ impl<'a, T, U> IrcServer<'a, T, U> where T: IrcWriter, U: IrcReader {
|
|||
}
|
||||
}
|
||||
|
||||
/// An Iterator over an IrcServer's incoming Messages
|
||||
#[experimental]
|
||||
pub struct ServerIterator<'a, T, U> where T: IrcWriter, U: IrcReader {
|
||||
pub server: &'a IrcServer<'a, T, U>
|
||||
}
|
||||
|
||||
impl<'a, T, U> ServerIterator<'a, T, U> where T: IrcWriter, U: IrcReader {
|
||||
/// Creates a new ServerIterator for the desired IrcServer
|
||||
#[experimental]
|
||||
pub fn new(server: &'a IrcServer<'a, T, U>) -> ServerIterator<'a, T, U> {
|
||||
ServerIterator {
|
||||
server: server
|
||||
|
|
Loading…
Reference in a new issue