diff --git a/Cargo.lock b/Cargo.lock index aec3fda..8d79847 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -210,9 +210,9 @@ dependencies = [ [[package]] name = "cloudabi" -version = "0.0.3" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467" dependencies = [ "bitflags", ] @@ -487,6 +487,15 @@ dependencies = [ "bytes", ] +[[package]] +name = "instant" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66" +dependencies = [ + "cfg-if", +] + [[package]] name = "iovec" version = "0.1.4" @@ -542,9 +551,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" dependencies = [ "scopeguard", ] @@ -784,22 +793,24 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" +checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733" dependencies = [ + "instant", "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" +checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b" dependencies = [ "cfg-if", "cloudabi", + "instant", "libc", "redox_syscall", "smallvec", @@ -1003,6 +1014,7 @@ name = "rocketchat" version = "0.1.0" dependencies = [ "anyhow", + "parking_lot", "serde", "tokio-tungstenite", ] @@ -1538,9 +1550,9 @@ name = "weechat-rocketchat" version = "0.1.0" dependencies = [ "anyhow", + "clap", "futures", "libc", - "parking_lot", "rocketchat", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index ff0454b..be97a23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,18 +17,18 @@ name = "rocketchat" crate-type = ["cdylib"] [dependencies] -libc = "0.2.70" anyhow = "1.0.31" -serde_json = "1.0.53" -serde = { version = "1.0.110", features = ["derive"] } futures = "0.3.5" +libc = "0.2.70" +serde = { version = "1.0.110", features = ["derive"] } +serde_json = "1.0.53" tokio = { version = "0.2.21", features = ["full"] } tokio-tls = "0.3.1" -parking_lot = "0.10.2" rocketchat = { path = "rocketchat" } tracing = "0.1.21" tracing-subscriber = "0.2.14" +clap = "2.33.3" [dependencies.weechat] git = "https://github.com/poljar/rust-weechat" diff --git a/rocketchat/Cargo.toml b/rocketchat/Cargo.toml index a0674ae..302e37c 100644 --- a/rocketchat/Cargo.toml +++ b/rocketchat/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Michael Zhang "] edition = "2018" [dependencies] -tokio-tungstenite = { version = "0.10.1", features = ["tls"] } -serde = { version = "1.0.110", features = ["derive"] } anyhow = "1.0.33" +parking_lot = "0.11.0" +serde = { version = "1.0.110", features = ["derive"] } +tokio-tungstenite = { version = "0.10.1", features = ["tls"] } diff --git a/rocketchat/src/client.rs b/rocketchat/src/client.rs index 24bf8ea..abca909 100644 --- a/rocketchat/src/client.rs +++ b/rocketchat/src/client.rs @@ -1,10 +1,34 @@ +use std::sync::Arc; + use anyhow::Result; +use parking_lot::Mutex; + +use crate::config::Config; #[derive(Clone)] -pub struct Client {} +pub struct Client { + config: Config, + inner: Arc>, +} impl Client { - pub fn new() -> Result { - Ok(Client {}) + pub fn new(config: Config) -> Result { + let inner = InnerClient { + login_state: LoginState::NotLoggedIn, + }; + let inner = Arc::new(Mutex::new(inner)); + + Ok(Client { config, inner }) } + + pub async fn connect() {} +} + +pub struct InnerClient { + login_state: LoginState, +} + +#[derive(Clone)] +pub enum LoginState { + NotLoggedIn, } diff --git a/rocketchat/src/config.rs b/rocketchat/src/config.rs new file mode 100644 index 0000000..e54a307 --- /dev/null +++ b/rocketchat/src/config.rs @@ -0,0 +1,4 @@ +#[derive(Clone)] +pub struct Config { + pub hostname: String, +} diff --git a/rocketchat/src/lib.rs b/rocketchat/src/lib.rs index 3468eb0..31aee78 100644 --- a/rocketchat/src/lib.rs +++ b/rocketchat/src/lib.rs @@ -2,6 +2,8 @@ extern crate serde; mod client; +mod config; pub mod message; pub use crate::client::Client; +pub use crate::config::Config; diff --git a/src/commands/rocketchat.rs b/src/commands/rocketchat.rs index 5548b90..ab8ba47 100644 --- a/src/commands/rocketchat.rs +++ b/src/commands/rocketchat.rs @@ -1,3 +1,7 @@ +use clap::{ + App as Argparse, AppSettings as ArgParseSettings, Arg, ArgMatches, + SubCommand, +}; use weechat::{ buffer::Buffer, hooks::{Command, CommandCallback, CommandSettings}, @@ -5,6 +9,7 @@ use weechat::{ }; use crate::config::ConfigHandle; +use crate::server::RocketchatServer; use crate::servers::Servers; pub struct RocketchatCommand { @@ -30,8 +35,82 @@ impl RocketchatCommand { }, ) } + + fn server_command(&self, args: &ArgMatches) { + match args.subcommand() { + ("add", Some(subargs)) => self.add_server(subargs), + _ => unreachable!(), + } + } + + fn add_server(&self, args: &ArgMatches) { + let server_name = args.value_of("name").unwrap(); + let hostname = args.value_of("hostname").unwrap(); + + let mut config_borrow = self.config.borrow_mut(); + let mut section = config_borrow + .search_section_mut("server") + .expect("can't get server section"); + + let server = + RocketchatServer::new(server_name, &self.config, &mut section); + + let mut servers = self.servers.borrow_mut(); + servers.insert(server_name.to_owned(), server); + + let hostname_option = section + .search_option(&format!("{}.hostname", server_name)) + .expect("hostname option wasn't created"); + hostname_option.set(hostname, true); + + Weechat::print(&format!( + "rocketchat server {} at {} has been added.", + server_name, hostname, + )); + } } impl CommandCallback for RocketchatCommand { - fn callback(&mut self, _: &Weechat, buffer: &Buffer, args: Args) {} + fn callback(&mut self, _: &Weechat, buffer: &Buffer, args: Args) { + let server_command = SubCommand::with_name("server") + .about("manipulate rocketchat servers") + .subcommand( + SubCommand::with_name("add") + .about("add a rocketchat server") + .arg( + Arg::with_name("name") + .value_name("server-name") + .required(true), + ) + .arg(Arg::with_name("hostname").required(true)), + ); + + let argparse = Argparse::new("rocketchat") + .about("rocketchat protocol commands") + .global_setting(ArgParseSettings::DisableHelpFlags) + .global_setting(ArgParseSettings::DisableVersion) + .global_setting(ArgParseSettings::VersionlessSubcommands) + .setting(ArgParseSettings::SubcommandRequiredElseHelp) + .subcommand(server_command); + + let matches = match argparse.get_matches_from_safe(args) { + Ok(m) => m, + Err(e) => { + Weechat::print( + &Weechat::execute_modifier( + "color_decode_ansi", + "1", + &e.to_string(), + ) + .unwrap(), + ); + return; + } + }; + + match matches.subcommand() { + ("server", Some(subargs)) => self.server_command(subargs), + _ => unreachable!(), + } + } } diff --git a/src/server.rs b/src/server.rs index b7e2665..c3ad83d 100644 --- a/src/server.rs +++ b/src/server.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use anyhow::Result; use rocketchat::Client; -use weechat::config::ConfigSection; +use weechat::config::{ConfigSection, StringOptionSettings}; use crate::config::ConfigHandle; use crate::connection::Connection; @@ -24,8 +24,14 @@ impl RocketchatServer { client: None, login_state: None, connection: Rc::new(RefCell::new(None)), + settings: ServerSettings::default(), }; let inner = Rc::new(RefCell::new(inner)); + RocketchatServer::create_server_conf( + &server_name, + server_section, + &inner, + ); RocketchatServer { server_name, inner } } @@ -53,12 +59,34 @@ impl RocketchatServer { self.inner.borrow().connection.borrow_mut().take(); } + + fn create_server_conf( + server_name: &str, + server_section: &mut ConfigSection, + server_ref: &Rc>, + ) { + let server = Rc::downgrade(server_ref); + let hostname = + StringOptionSettings::new(format!("{}.hostname", server_name)) + .set_change_callback(move |_, option| { + let server = server.clone(); + let server_ref = server.upgrade().expect( + "server got deleted while config is still alive", + ); + let mut server = server_ref.borrow_mut(); + server.settings.hostname = option.value().to_string(); + }); + server_section + .new_string_option(hostname) + .expect("can't create hostname option"); + } } pub struct InnerServer { client: Option, login_state: Option, connection: Rc>>, + settings: ServerSettings, } impl InnerServer { @@ -67,7 +95,12 @@ impl InnerServer { } fn create_client(&mut self) -> Result { - let client = Client::new()?; + let hostname = self.settings.hostname.clone(); + + use rocketchat::Config; + let config = Config { hostname }; + + let client = Client::new(config)?; Ok(client) } @@ -83,3 +116,8 @@ impl InnerServer { } pub struct LoginInfo {} + +#[derive(Default)] +pub struct ServerSettings { + hostname: String, +}