+ List channels backbone in place

Technically everything is there but I haven't really tested anything yet
Will 100% need fixing + optimizing

+ Switch server Command also working
! Requires a jwt check to avoid expensive+unnecssary network /login hits
! Probably have to hold onto the input to avoid spam somehow

ChannelCache is nearly ready for manipulation
This commit is contained in:
shockrah 2021-04-05 17:36:24 -07:00
parent 5ab2c961f6
commit 0bee002164

View File

@ -12,32 +12,36 @@
*
*/
use crate::config::ServerMeta;
use crate::api_types::{Channel, Message};
use crate::net;
use crate::command::Command;
use crate::config::ConfigFile;
use crate::config::{ConfigFile, ServerConfig};
use std::collections::HashMap;
use hyper::Request;
type ChannelMeta = Channel;
struct ChannelCache {
meta: Channel,
messages: Vec<Message>
pub meta: ChannelMeta,
pub messages: Vec<Message>
}
struct ServerCache {
meta: ServerMeta,
// 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<ChannelCache>
}
pub struct Cache {
// url -> Cache
servers: HashMap<String, ServerCache>,
active_server: Option<ServerMeta>
active_server: Option<ServerConfig>,
active_text: Option<ChannelMeta>
}
impl ServerCache {
pub fn from(meta: ServerMeta, channels: Vec<ChannelCache>) -> Self {
pub fn from(meta: ServerConfig, channels: Vec<ChannelCache>) -> Self {
ServerCache { meta, channels }
}
}
@ -45,15 +49,16 @@ impl ServerCache {
impl Cache {
pub fn from(config: &ConfigFile) -> Cache {
let mut servers = HashMap::new();
for cfg in &config.servers {
let i_server_cache = ServerCache::from(cfg.server.clone(), Vec::new());
let url = i_server_cache.meta.url.clone();
for servercfg in &config.servers {
let i_server_cache = ServerCache::from(servercfg.clone(), Vec::new());
let url = i_server_cache.meta.server.url.clone();
servers.insert(url, i_server_cache);
}
Cache {
servers,
active_server: None
active_server: None,
active_text: None
}
}
}
@ -67,23 +72,43 @@ impl Cache {
}
}
pub async fn switch_server(&mut self, host: &str) -> Command {
if let Some(srv_cache) = self.servers.get(host) {
Command::Failure(format!("Not implemented yet!"))
// TODO: implement some better fuzzy finding for better ergonomics
// Reallt though the ux is still pretty bad here
// Also it greedily matches so if two servers are behind one domain we're kinda fucked
let mut found = false;
let mut err_msg = String::from("Nothing found");
for (url, meta) in self.servers.iter_mut() {
if url.contains(host) {
let id = meta.meta.user.id;
let secret = &meta.meta.user.secret;
found = match net::login(url, id, secret).await {
Ok(jwt) => {
meta.meta.user.jwt = Some(jwt);
self.active_server = Some(meta.meta.clone());
// Setup websocket to server or something idk
self.active_text = None;
true
},
Err(e) => { // TODO: some kind of logging here
err_msg = format!("{}", e);
meta.meta.user.jwt = None;
false
}
};
meta.meta.user.jwt = Some(String::from("asdf"));
break
}
}
if found {
Command::Text(format!("logged in - /lc to list to list channels"))
} else {
Command::Failure(format!("Host {{ {} }} not found", host))
Command::Failure(err_msg)
}
}
pub async fn send_message(&mut self, id: &str) -> Command {
use hyper::body::HttpBody as _;
use hyper::Client;
if let Some(server) = self.active_server.as_ref() {
let url = format!("{}/message/send", server.url);
let request = Request::builder()
.method("POST")
.uri(url).body(()).unwrap();
Command::Failure(format!("Not implemented yet!"))
} else {
Command::Failure(format!("No active server+channel to send message to"))
@ -97,4 +122,26 @@ 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));
}
}
Command::Text(buffer)
} else {
Command::Failure(format!("No active server"))
}
}
}