diff --git a/tui/src/cache.rs b/tui/src/cache.rs index 6a1d86d..2632eee 100644 --- a/tui/src/cache.rs +++ b/tui/src/cache.rs @@ -30,7 +30,7 @@ struct ServerCache { // container for the relevant user/serer meta data // We use both parts in order to to maintain jwt's within the cache meta: ServerConfig, - channels: Vec + channels: HashMap // channel_id -> cache } pub struct Cache { @@ -41,7 +41,7 @@ pub struct Cache { } impl ServerCache { - pub fn from(meta: ServerConfig, channels: Vec) -> Self { + pub fn from(meta: ServerConfig, channels: HashMap) -> Self { ServerCache { meta, channels } } } @@ -50,7 +50,7 @@ impl Cache { pub fn from(config: &ConfigFile) -> Cache { let mut servers = HashMap::new(); for servercfg in &config.servers { - let i_server_cache = ServerCache::from(servercfg.clone(), Vec::new()); + let i_server_cache = ServerCache::from(servercfg.clone(), HashMap::new()); let url = i_server_cache.meta.server.url.clone(); servers.insert(url, i_server_cache); } @@ -83,14 +83,18 @@ impl Cache { let secret = &meta.meta.user.secret; found = match net::login(url, id, secret).await { Ok(jwt) => { + let twt = jwt.clone(); meta.meta.user.jwt = Some(jwt); self.active_server = Some(meta.meta.clone()); - // Setup websocket to server or something idk + // TODO: Setup websocket to server or something idk self.active_text = None; true }, - Err(e) => { // TODO: some kind of logging here - err_msg = format!("{}", e); + Err(e) => { + err_msg = match e.is_status() { + true => format!("{:?}", e.status().unwrap()), + false => format!("Issue connecting to server") + }; meta.meta.user.jwt = None; false } @@ -123,25 +127,30 @@ impl Cache { Command::Text(hosts) } - pub fn list_channels(&self) -> Command { - use crate::api_types; - if let Some(serv) = &self.active_server { - // Find the server we're whose channels we want - let (_, cache) = self.servers.iter() - .find(|(url, _)| url == &&serv.server.url).unwrap(); - - let mut buffer = String::from("! Channels "); - for (i, chan) in cache.channels.iter().enumerate() { - // NOTE only list out text channels for now - // another command will be provided for voice channels later - if chan.meta.r#type == api_types::TEXT_CHANNEL { - buffer.push_str(&format!("[{}] {}, ", i, chan.meta.r#type)); + pub async fn list_channels(&mut self) -> Command { + if let None = self.active_server { + return Command::Failure("No active server".into()) + } + // we have to own our own reference here to avoid mutating after immutable borrows + let config = self.active_server.clone().unwrap(); + let id = config.user.id; + let jwt = config.user.jwt.unwrap(); + let url = config.server.url.as_str(); + let mut buf = String::new(); + match net::list_channels(url, id, jwt.as_str()).await { + Ok(mut channels) => { + for chan in channels.iter_mut() { + let id = chan.id; + let chan_cache = ChannelCache { meta: chan.clone(), messages: Vec::new() }; + self.servers.get_mut(url).unwrap().channels.insert(id, chan_cache); + let chan = format!("{}: {},", id, chan.name); + buf.push_str(chan.as_str()); } + Command::Text(buf) + }, + Err(e) => { + Command::Failure(format!("Couldn't fetch channels: {:?}", e.status())) } - - Command::Text(buffer) - } else { - Command::Failure(format!("No active server")) } } } diff --git a/tui/src/main.rs b/tui/src/main.rs index 5231523..a542e42 100644 --- a/tui/src/main.rs +++ b/tui/src/main.rs @@ -226,7 +226,7 @@ async fn main() -> Result<(), Box> { Command::Server(host) => app.cache.switch_server(&host).await, Command::Message(msg) => app.cache.send_message(&msg).await, Command::ListHost => app.cache.list_hosts(), - Command::ListChannel => app.cache.list_channels(), + Command::ListChannel => app.cache.list_channels().await, _ => cmd }); } diff --git a/tui/src/net.rs b/tui/src/net.rs index fd275e2..0981b20 100644 --- a/tui/src/net.rs +++ b/tui/src/net.rs @@ -1,19 +1,38 @@ -use crate::api_types::Channel; -use crate::api_types::Jwt; +use serde::Deserialize; +use crate::api_types::{Jwt, Channel, TEXT_CHANNEL}; use reqwest::{Client, Url}; use reqwest::Result as HttpResult; +// TODO: Url generation is kinda gross looking but i'm not 100% +// convinced it needs to be pretty if its just going to add overhead + pub async fn login(url: &str, id: u64, secret: &str) -> HttpResult { let client = Client::new(); - let mut url = Url::parse(&format!("{}/login", url)).unwrap(); - url.query_pairs_mut().append_pair("id", &format!("{}", id)); - url.query_pairs_mut().append_pair("secret", secret); + let url = Url::parse_with_params( + &format!("{}/login", url), + &[("id", format!("{}", id).as_str()), ("secret", secret)] + ).unwrap(); let response: Jwt = client.get(url).send().await?.json().await?; Ok(response.jwt) } -fn list_channels(url: &str, id: u64, secret: &str) -> Vec { - todo!() +pub async fn list_channels(url: &str, id: u64, jwt: &str) -> HttpResult> { + let client = Client::new(); + let url = Url::parse_with_params( + &format!("{}/channels/list", url), + &[ + ("id", format!("{}", id).as_str()), + ("jwt", jwt), + ("kind", format!("{}", TEXT_CHANNEL).as_str()) + ] + ).unwrap(); + + #[derive(Deserialize)] + struct ChannelResponse { + pub channels: Vec + } + let response: ChannelResponse = client.get(url).send().await?.json().await?; + Ok(response.channels) }