2014-11-06 15:23:02 -05:00
|
|
|
//! JSON configuration files using libserialize.
|
2014-11-03 00:52:15 -05:00
|
|
|
#![stable]
|
2014-12-23 12:53:30 -05:00
|
|
|
use std::borrow::ToOwned;
|
2014-11-02 18:16:49 -05:00
|
|
|
use std::collections::HashMap;
|
2015-01-09 17:38:46 -05:00
|
|
|
use std::error::Error;
|
2015-01-28 12:19:02 -05:00
|
|
|
use std::old_io::fs::File;
|
|
|
|
use std::old_io::{InvalidInput, IoError, IoResult};
|
2014-12-23 12:53:30 -05:00
|
|
|
use rustc_serialize::json::decode;
|
2014-11-02 18:16:49 -05:00
|
|
|
|
2014-11-06 15:23:02 -05:00
|
|
|
/// Configuration data.
|
2015-01-04 01:18:26 -05:00
|
|
|
#[derive(Clone, RustcDecodable, Default, PartialEq, Show)]
|
2015-01-09 18:36:22 -05:00
|
|
|
#[stable]
|
2014-11-02 18:16:49 -05:00
|
|
|
pub struct Config {
|
2014-11-06 15:23:02 -05:00
|
|
|
/// A list of the owners of the bot by nickname.
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub owners: Option<Vec<String>>,
|
2014-11-06 15:23:02 -05:00
|
|
|
/// The bot's nickname.
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub nickname: Option<String>,
|
2014-12-09 17:01:47 -05:00
|
|
|
/// The bot's NICKSERV password.
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-12-09 17:01:47 -05:00
|
|
|
pub nick_password: Option<String>,
|
2014-12-06 18:49:07 -05:00
|
|
|
/// Alternative nicknames for the bots, if the default is taken.
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-12-06 18:49:07 -05:00
|
|
|
pub alt_nicks: Option<Vec<String>>,
|
2014-11-06 15:23:02 -05:00
|
|
|
/// The bot's username.
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub username: Option<String>,
|
2014-11-06 15:23:02 -05:00
|
|
|
/// The bot's real name.
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub realname: Option<String>,
|
2014-11-06 15:23:02 -05:00
|
|
|
/// The server to connect to.
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub server: Option<String>,
|
2014-11-06 15:23:02 -05:00
|
|
|
/// The port to connect on.
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub port: Option<u16>,
|
2014-12-09 16:17:05 -05:00
|
|
|
/// The password to connect to the server.
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-12-09 16:17:05 -05:00
|
|
|
pub password: Option<String>,
|
2014-11-08 17:35:19 -05:00
|
|
|
/// Whether or not to use SSL.
|
2014-11-08 23:21:55 -05:00
|
|
|
/// Bots will automatically panic if this is enabled without SSL support.
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub use_ssl: Option<bool>,
|
2014-11-30 01:29:38 -05:00
|
|
|
/// The encoding type used for this connection.
|
|
|
|
/// This is typically UTF-8, but could be something else.
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub encoding: Option<String>,
|
2014-11-06 15:23:02 -05:00
|
|
|
/// A list of channels to join on connection.
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub channels: Option<Vec<String>>,
|
2014-12-22 16:35:56 -05:00
|
|
|
/// The text that'll be sent in response to CTCP USERINFO requests.
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-12-22 16:35:56 -05:00
|
|
|
pub user_info: Option<String>,
|
2014-11-06 15:23:02 -05:00
|
|
|
/// A map of additional options to be stored in config.
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub options: Option<HashMap<String, String>>,
|
2014-11-02 18:16:49 -05:00
|
|
|
}
|
|
|
|
|
2015-01-13 03:51:18 -05:00
|
|
|
#[stable]
|
2014-11-02 18:16:49 -05:00
|
|
|
impl Config {
|
2014-11-06 15:23:02 -05:00
|
|
|
/// Loads a JSON configuration from the desired path.
|
2014-11-03 00:52:15 -05:00
|
|
|
#[stable]
|
2014-11-02 18:16:49 -05:00
|
|
|
pub fn load(path: Path) -> IoResult<Config> {
|
|
|
|
let mut file = try!(File::open(&path));
|
|
|
|
let data = try!(file.read_to_string());
|
2015-01-09 17:38:46 -05:00
|
|
|
decode(&data[]).map_err(|e| IoError {
|
2014-11-02 18:16:49 -05:00
|
|
|
kind: InvalidInput,
|
|
|
|
desc: "Failed to decode configuration file.",
|
2015-01-24 16:18:32 -05:00
|
|
|
detail: Some(e.description().to_owned()),
|
2014-11-02 18:16:49 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2014-11-06 15:23:02 -05:00
|
|
|
/// Loads a JSON configuration using the string as a UTF-8 path.
|
2014-11-03 00:52:15 -05:00
|
|
|
#[stable]
|
2014-11-02 18:16:49 -05:00
|
|
|
pub fn load_utf8(path: &str) -> IoResult<Config> {
|
|
|
|
Config::load(Path::new(path))
|
|
|
|
}
|
|
|
|
|
2014-11-06 15:23:02 -05:00
|
|
|
/// Determines whether or not the nickname provided is the owner of the bot.
|
2014-11-03 00:52:15 -05:00
|
|
|
#[stable]
|
2014-11-02 18:16:49 -05:00
|
|
|
pub fn is_owner(&self, nickname: &str) -> bool {
|
2014-12-04 21:04:22 -05:00
|
|
|
self.owners.as_ref().map(|o| o.contains(&String::from_str(nickname))).unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the nickname specified in the configuration.
|
2014-12-06 18:49:07 -05:00
|
|
|
/// This will panic if not specified.
|
2015-01-09 18:36:22 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub fn nickname(&self) -> &str {
|
2015-01-09 17:38:46 -05:00
|
|
|
self.nickname.as_ref().map(|s| &s[]).unwrap()
|
2014-12-04 21:04:22 -05:00
|
|
|
}
|
|
|
|
|
2014-12-09 17:01:47 -05:00
|
|
|
/// Gets the bot's nickserv password specified in the configuration.
|
|
|
|
/// This defaults to an empty string when not specified.
|
2015-01-09 18:36:22 -05:00
|
|
|
#[stable]
|
2014-12-09 17:01:47 -05:00
|
|
|
pub fn nick_password(&self) -> &str {
|
2015-01-09 17:38:46 -05:00
|
|
|
self.nick_password.as_ref().map(|s| &s[]).unwrap_or("")
|
2014-12-09 17:01:47 -05:00
|
|
|
}
|
|
|
|
|
2014-12-06 18:49:07 -05:00
|
|
|
/// Gets the alternate nicknames specified in the configuration.
|
|
|
|
/// This defaults to an empty vector when not specified.
|
2015-01-09 18:36:22 -05:00
|
|
|
#[stable]
|
2014-12-06 18:49:07 -05:00
|
|
|
pub fn get_alternate_nicknames(&self) -> Vec<&str> {
|
2015-01-09 17:38:46 -05:00
|
|
|
self.alt_nicks.as_ref().map(|v| v.iter().map(|s| &s[]).collect()).unwrap_or(vec![])
|
2014-12-06 18:49:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-12-04 21:04:22 -05:00
|
|
|
/// Gets the username specified in the configuration.
|
|
|
|
/// This defaults to the user's nickname when not specified.
|
2015-01-09 18:36:22 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub fn username(&self) -> &str {
|
2015-01-09 17:38:46 -05:00
|
|
|
self.username.as_ref().map(|s| &s[]).unwrap_or(self.nickname())
|
2014-12-04 21:04:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the real name specified in the configuration.
|
|
|
|
/// This defaults to the user's nickname when not specified.
|
2015-01-09 18:36:22 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub fn real_name(&self) -> &str {
|
2015-01-09 17:38:46 -05:00
|
|
|
self.realname.as_ref().map(|s| &s[]).unwrap_or(self.nickname())
|
2014-12-04 21:04:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the address of the server specified in the configuration.
|
|
|
|
/// This panics when not specified.
|
2015-01-09 18:36:22 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub fn server(&self) -> &str {
|
2015-01-09 17:38:46 -05:00
|
|
|
self.server.as_ref().map(|s| &s[]).unwrap()
|
2014-12-04 21:04:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the port of the server specified in the configuration.
|
|
|
|
/// This defaults to 6667 (or 6697 if use_ssl is specified as true) when not specified.
|
2015-01-09 18:36:22 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub fn port(&self) -> u16 {
|
|
|
|
self.port.as_ref().map(|p| *p).unwrap_or(if self.use_ssl() {
|
|
|
|
6697
|
|
|
|
} else {
|
|
|
|
6667
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2014-12-09 16:17:05 -05:00
|
|
|
/// Gets the server password specified in the configuration.
|
|
|
|
/// This defaults to a blank string when not specified.
|
2015-01-09 18:36:22 -05:00
|
|
|
#[stable]
|
2014-12-09 16:17:05 -05:00
|
|
|
pub fn password(&self) -> &str {
|
2015-01-09 17:38:46 -05:00
|
|
|
self.password.as_ref().map(|s| &s[]).unwrap_or("")
|
2014-12-09 16:17:05 -05:00
|
|
|
}
|
|
|
|
|
2014-12-04 21:04:22 -05:00
|
|
|
/// Gets whether or not to use SSL with this connection.
|
|
|
|
/// This defaults to false when not specified.
|
2015-01-09 18:36:22 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub fn use_ssl(&self) -> bool {
|
|
|
|
self.use_ssl.as_ref().map(|u| *u).unwrap_or(false)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the encoding to use for this connection. This requires the encode feature to work.
|
|
|
|
/// This defaults to UTF-8 when not specified.
|
2015-01-09 18:36:22 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub fn encoding(&self) -> &str {
|
2015-01-09 17:38:46 -05:00
|
|
|
self.encoding.as_ref().map(|s| &s[]).unwrap_or("UTF-8")
|
2014-12-04 21:04:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the channels to join upon connection.
|
|
|
|
/// This defaults to an empty vector if it's not specified.
|
2015-01-09 18:36:22 -05:00
|
|
|
#[stable]
|
2014-12-04 21:04:22 -05:00
|
|
|
pub fn channels(&self) -> Vec<&str> {
|
2015-01-09 17:38:46 -05:00
|
|
|
self.channels.as_ref().map(|v| v.iter().map(|s| &s[]).collect()).unwrap_or(vec![])
|
2014-11-02 18:16:49 -05:00
|
|
|
}
|
2014-11-29 05:49:20 -05:00
|
|
|
|
2014-12-22 16:35:56 -05:00
|
|
|
/// Gets the string to be sent in response to CTCP USERINFO requests.
|
|
|
|
/// This defaults to an empty string when not specified.
|
2015-01-09 18:36:22 -05:00
|
|
|
#[unstable = "Feature is still relatively new."]
|
2014-12-22 16:35:56 -05:00
|
|
|
pub fn user_info(&self) -> &str {
|
2015-01-09 17:38:46 -05:00
|
|
|
self.user_info.as_ref().map(|s| &s[]).unwrap_or("")
|
2014-12-22 16:35:56 -05:00
|
|
|
}
|
|
|
|
|
2014-11-29 05:49:20 -05:00
|
|
|
/// Looks up the specified string in the options map.
|
|
|
|
/// This uses indexing, and thus panics when the string is not present.
|
2014-12-04 21:04:22 -05:00
|
|
|
/// This will also panic if used and there are no options.
|
2015-01-09 18:36:22 -05:00
|
|
|
#[stable]
|
2014-11-29 05:49:20 -05:00
|
|
|
pub fn get_option(&self, option: &str) -> &str {
|
2015-01-09 17:38:46 -05:00
|
|
|
self.options.as_ref().map(|o| &o[option.to_owned()][]).unwrap()
|
2014-11-29 05:49:20 -05:00
|
|
|
}
|
2014-11-02 18:16:49 -05:00
|
|
|
}
|
2014-11-05 01:45:17 -05:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::Config;
|
|
|
|
use std::collections::HashMap;
|
2014-12-05 10:27:58 -05:00
|
|
|
use std::default::Default;
|
2014-11-05 01:45:17 -05:00
|
|
|
|
|
|
|
#[test]
|
2014-11-30 03:30:10 -05:00
|
|
|
fn load() {
|
|
|
|
let cfg = Config {
|
2014-12-04 21:04:22 -05:00
|
|
|
owners: Some(vec![format!("test")]),
|
|
|
|
nickname: Some(format!("test")),
|
2014-12-09 17:01:47 -05:00
|
|
|
nick_password: None,
|
2014-12-06 18:49:07 -05:00
|
|
|
alt_nicks: None,
|
2014-12-04 21:04:22 -05:00
|
|
|
username: Some(format!("test")),
|
|
|
|
realname: Some(format!("test")),
|
|
|
|
password: Some(String::new()),
|
|
|
|
server: Some(format!("irc.test.net")),
|
|
|
|
port: Some(6667),
|
|
|
|
use_ssl: Some(false),
|
|
|
|
encoding: Some(format!("UTF-8")),
|
|
|
|
channels: Some(vec![format!("#test"), format!("#test2")]),
|
2014-12-23 12:15:41 -05:00
|
|
|
user_info: None,
|
2014-12-04 21:04:22 -05:00
|
|
|
options: Some(HashMap::new()),
|
2014-11-30 03:30:10 -05:00
|
|
|
};
|
2015-01-13 03:01:18 -05:00
|
|
|
assert_eq!(Config::load(Path::new("client_config.json")), Ok(cfg));
|
2014-11-30 03:30:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn load_utf8() {
|
|
|
|
let cfg = Config {
|
2014-12-04 21:04:22 -05:00
|
|
|
owners: Some(vec![format!("test")]),
|
|
|
|
nickname: Some(format!("test")),
|
2014-12-09 17:01:47 -05:00
|
|
|
nick_password: None,
|
2014-12-06 18:49:07 -05:00
|
|
|
alt_nicks: None,
|
2014-12-04 21:04:22 -05:00
|
|
|
username: Some(format!("test")),
|
|
|
|
realname: Some(format!("test")),
|
|
|
|
password: Some(String::new()),
|
|
|
|
server: Some(format!("irc.test.net")),
|
|
|
|
port: Some(6667),
|
|
|
|
use_ssl: Some(false),
|
|
|
|
encoding: Some(format!("UTF-8")),
|
|
|
|
channels: Some(vec![format!("#test"), format!("#test2")]),
|
2014-12-23 12:15:41 -05:00
|
|
|
user_info: None,
|
2014-12-04 21:04:22 -05:00
|
|
|
options: Some(HashMap::new()),
|
2014-11-30 03:30:10 -05:00
|
|
|
};
|
2015-01-13 03:01:18 -05:00
|
|
|
assert_eq!(Config::load_utf8("client_config.json"), Ok(cfg));
|
2014-11-30 03:30:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
2014-11-05 01:45:17 -05:00
|
|
|
fn is_owner() {
|
|
|
|
let cfg = Config {
|
2014-12-04 21:04:22 -05:00
|
|
|
owners: Some(vec![format!("test"), format!("test2")]),
|
2014-12-05 10:27:58 -05:00
|
|
|
.. Default::default()
|
2014-11-05 01:45:17 -05:00
|
|
|
};
|
|
|
|
assert!(cfg.is_owner("test"));
|
|
|
|
assert!(cfg.is_owner("test2"));
|
|
|
|
assert!(!cfg.is_owner("test3"));
|
|
|
|
}
|
2014-11-29 05:49:20 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn get_option() {
|
2014-12-04 21:04:22 -05:00
|
|
|
let cfg = Config {
|
2014-11-30 03:30:10 -05:00
|
|
|
options: {
|
|
|
|
let mut map = HashMap::new();
|
|
|
|
map.insert(format!("testing"), format!("test"));
|
2014-12-04 21:04:22 -05:00
|
|
|
Some(map)
|
2014-11-30 03:30:10 -05:00
|
|
|
},
|
2014-12-05 10:27:58 -05:00
|
|
|
.. Default::default()
|
2014-11-30 03:30:10 -05:00
|
|
|
};
|
|
|
|
assert_eq!(cfg.get_option("testing"), "test");
|
|
|
|
}
|
2014-11-05 01:45:17 -05:00
|
|
|
}
|