aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mumctl/src/main.rs19
-rw-r--r--mumd/src/state.rs2
-rw-r--r--mumlib/src/state.rs94
3 files changed, 111 insertions, 4 deletions
diff --git a/mumctl/src/main.rs b/mumctl/src/main.rs
index cfd48f8..c73b793 100644
--- a/mumctl/src/main.rs
+++ b/mumctl/src/main.rs
@@ -6,6 +6,8 @@ use std::{fs, io, iter};
use colored::Colorize;
use mumlib::state::Channel;
+const INDENTATION: &str = " ";
+
macro_rules! err_print {
($func:expr) => {
if let Err(e) = $func {
@@ -84,7 +86,18 @@ fn main() {
} else if let Some(_matches) = matches.subcommand_matches("status") {
match send_command(Command::Status) {
Ok(res) => {
- println!("{:#?}", res.unwrap());
+ match res {
+ Some(CommandResponse::Status { server_state }) => {
+ println!("Connected to {} as {}", server_state.host, server_state.username);
+ let own_channel = server_state.channels.iter().find(|e| e.users.iter().any(|e| e.name == server_state.username)).unwrap();
+ println!("Currently in {} with {} other client{}:", own_channel.name, own_channel.users.len() - 1, if own_channel.users.len() == 2 { "" } else { "s" });
+ println!("{}{}", INDENTATION, own_channel.name);
+ for user in &own_channel.users {
+ println!("{}{}{}", INDENTATION, INDENTATION, user);
+ }
+ }
+ _ => unreachable!(),
+ }
}
Err(e) => println!("{} {}", "error:".red(), e),
}
@@ -119,13 +132,13 @@ fn send_command(command: Command) -> mumlib::error::Result<Option<CommandRespons
}
fn print_channel(channel: &Channel, depth: usize) {
- println!("{}{}{}", iter::repeat(" ").take(depth).collect::<String>(), channel.name.bold(), if channel.max_users != 0 {
+ println!("{}{}{}", iter::repeat(INDENTATION).take(depth).collect::<String>(), channel.name.bold(), if channel.max_users != 0 {
format!(" {}/{}", channel.users.len(), channel.max_users)
} else {
"".to_string()
});
for user in &channel.users {
- println!("{}-{}", iter::repeat(" ").take(depth + 1).collect::<String>(), user.name);
+ println!("{}-{}", iter::repeat(INDENTATION).take(depth + 1).collect::<String>(), user);
}
for child in &channel.children {
print_channel(child, depth + 1);
diff --git a/mumd/src/state.rs b/mumd/src/state.rs
index 4182b6c..2ad88ad 100644
--- a/mumd/src/state.rs
+++ b/mumd/src/state.rs
@@ -87,7 +87,7 @@ impl State {
}
let mut server = Server::new();
server.username = Some(username);
- server.host = Some(host.clone());
+ server.host = Some(format!("{}:{}", host, port));
self.server = Some(server);
self.phase_watcher
.0
diff --git a/mumlib/src/state.rs b/mumlib/src/state.rs
index 01a31ab..96598de 100644
--- a/mumlib/src/state.rs
+++ b/mumlib/src/state.rs
@@ -1,4 +1,6 @@
use serde::{Deserialize, Serialize};
+use std::fmt::Display;
+use serde::export::Formatter;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Server {
@@ -18,6 +20,92 @@ pub struct Channel {
pub users: Vec<User>,
}
+impl Channel {
+ pub fn iter(&self) -> Iter<'_> {
+ Iter {
+ me: Some(&self),
+ channel: if self.children.len() > 0 { Some(0) } else { None },
+ channels: self.children.iter().map(|e| e.iter()).collect()
+ }
+ }
+
+ pub fn users_iter(&self) -> UsersIter<'_> {
+ UsersIter {
+ channels: self.children.iter().map(|e| e.users_iter()).collect(),
+ channel: if self.children.len() > 0 { Some(0) } else { None },
+ user: if self.users.len() > 0 { Some(0) } else { None },
+ users: &self.users
+ }
+ }
+}
+
+pub struct Iter<'a> {
+ me: Option<&'a Channel>,
+ channel: Option<usize>,
+ channels: Vec<Iter<'a>>,
+}
+
+impl<'a> Iterator for Iter<'a> {
+ type Item = &'a Channel;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.me.is_some() {
+ self.me.take()
+ } else if let Some(mut c) = self.channel {
+ let mut n = self.channels[c].next();
+ while n.is_none() {
+ c += 1;
+ if c >= self.channels.len() {
+ self.channel = None;
+ return None;
+ }
+ n = self.channels[c].next();
+ }
+ self.channel = Some(c);
+ n
+ } else {
+ None
+ }
+ }
+}
+
+pub struct UsersIter<'a> {
+ channel: Option<usize>,
+ channels: Vec<UsersIter<'a>>,
+ user: Option<usize>,
+ users: &'a [User],
+}
+
+impl<'a> Iterator for UsersIter<'a> {
+ type Item = &'a User;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if let Some(u) = self.user {
+ let ret = Some(&self.users[u]);
+ if u + 1 < self.users.len() {
+ self.user = Some(u + 1);
+ } else {
+ self.user = None;
+ }
+ ret
+ } else if let Some(mut c) = self.channel {
+ let mut n = self.channels[c].next();
+ while n.is_none() {
+ c += 1;
+ if c >= self.channels.len() {
+ self.channel = None;
+ return None;
+ }
+ n = self.channels[c].next();
+ }
+ self.channel = Some(c);
+ n
+ } else {
+ None
+ }
+ }
+}
+
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct User {
pub comment: Option<String>,
@@ -31,4 +119,10 @@ pub struct User {
pub self_deaf: bool, // by self
pub mute: bool, // by admin
pub deaf: bool, // by admin
+}
+
+impl Display for User {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", self.name)
+ }
} \ No newline at end of file