Improve events
Add known clients (cache) for leaving clients Add message to returned json object
This commit is contained in:
		
							parent
							
								
									f860fe3689
								
							
						
					
					
						commit
						ae411b6dcc
					
				
					 7 changed files with 117 additions and 24 deletions
				
			
		
							
								
								
									
										2
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -182,7 +182,7 @@ dependencies = [ | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "teamspeak-query-lib" | name = "teamspeak-query-lib" | ||||||
| version = "0.1.2" | version = "0.1.4" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "clap", |  "clap", | ||||||
|  "serde", |  "serde", | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| [package] | [package] | ||||||
| name = "teamspeak-query-lib" | name = "teamspeak-query-lib" | ||||||
| version = "0.1.2" | version = "0.1.4" | ||||||
| edition = "2021" | edition = "2021" | ||||||
| 
 | 
 | ||||||
| [dependencies] | [dependencies] | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| use telnet::Telnet; | use telnet::Telnet; | ||||||
| use crate::commands; | use crate::{commands, wrappers}; | ||||||
| use crate::models::{Event, EventType}; | use crate::models::{Client, Event, EventType}; | ||||||
| use crate::response::Response; | use crate::response::Response; | ||||||
| 
 | 
 | ||||||
| pub fn register_events(connection: &mut Telnet, events: Vec<EventType>) -> Result<(), String> { | pub fn register_events(connection: &mut Telnet, events: Vec<EventType>) -> Result<(), String> { | ||||||
|  | @ -12,10 +12,10 @@ pub fn register_events(connection: &mut Telnet, events: Vec<EventType>) -> Resul | ||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn handle_event_response(connection: &mut Telnet, response: Response) { | pub fn handle_event_response(connection: &mut Telnet, response: Response, known_clients: &mut Vec<Client>) { | ||||||
|     if let Response::Event(event_type, params) = response { |     if let Response::Event(event_type, params) = response { | ||||||
| 
 | 
 | ||||||
|         let event = Event::new(connection, event_type, params); |         let event = Event::new(connection, event_type, params, &known_clients); | ||||||
|         match serde_json::to_string(&event) { |         match serde_json::to_string(&event) { | ||||||
|             Ok(json) => println!("{}", json), |             Ok(json) => println!("{}", json), | ||||||
|             Err(err) => { |             Err(err) => { | ||||||
|  | @ -24,13 +24,17 @@ pub fn handle_event_response(connection: &mut Telnet, response: Response) { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         if let Ok(new_clients) = wrappers::get_clients(connection) { | ||||||
|  |             *known_clients = new_clients; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn loop_response_reader(connection: &mut Telnet) { | pub fn loop_response_reader(connection: &mut Telnet) { | ||||||
|  |     let mut known_clients = wrappers::get_clients(connection).unwrap_or_else(|_| Vec::new()); | ||||||
|     loop { |     loop { | ||||||
|         match commands::read_response(connection, true, String::new()) { |         match commands::read_response(connection, true, String::new()) { | ||||||
|             Ok(response) => handle_event_response(connection, response), |             Ok(response) => handle_event_response(connection, response, &mut known_clients), | ||||||
|             Err(_) => { |             Err(_) => { | ||||||
|                 // print error?
 |                 // print error?
 | ||||||
|                 return; |                 return; | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; | ||||||
| 
 | 
 | ||||||
| use crate::parameter::{parameter_find, ParameterList}; | use crate::parameter::{parameter_find, ParameterList}; | ||||||
| 
 | 
 | ||||||
| #[derive(Serialize, Deserialize, Debug)] | #[derive(Serialize, Deserialize, Clone, Debug)] | ||||||
| pub struct Client { | pub struct Client { | ||||||
|     pub cid: i32, |     pub cid: i32, | ||||||
|     pub clid: i32, |     pub clid: i32, | ||||||
|  |  | ||||||
|  | @ -1,7 +1,8 @@ | ||||||
| use std::fmt::{Display, Formatter}; | use std::fmt::{Display, Formatter}; | ||||||
| use std::str::FromStr; | use std::str::FromStr; | ||||||
| 
 | 
 | ||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize, Serializer}; | ||||||
|  | use serde::ser::SerializeStruct; | ||||||
| use telnet::Telnet; | use telnet::Telnet; | ||||||
| 
 | 
 | ||||||
| use crate::models::{Channel, Client}; | use crate::models::{Channel, Client}; | ||||||
|  | @ -43,7 +44,7 @@ pub enum EventType { | ||||||
|     NotifyConnectStatusChange, |     NotifyConnectStatusChange, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Serialize, Deserialize, Debug)] | #[derive(Debug)] | ||||||
| pub struct Event { | pub struct Event { | ||||||
|     pub event_type: EventType, |     pub event_type: EventType, | ||||||
|     pub params: ParameterList, |     pub params: ParameterList, | ||||||
|  | @ -152,36 +153,58 @@ impl Display for EventType { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl EventType { | impl EventType { | ||||||
|  | 
 | ||||||
|  |     pub fn find_channel(&self, connection: &mut Telnet, params: &ParameterList, param_name: &str) -> Option<Channel> { | ||||||
|  |         let id = parameter_find(params, param_name)? | ||||||
|  |             .parse::<i32>().unwrap_or(0); | ||||||
|  |         wrappers::find_channel(connection, "cid", &id.to_string(), true).unwrap().or(None) | ||||||
|  |     } | ||||||
|     pub fn get_channel(&self, connection: &mut Telnet, params: &ParameterList) -> Option<Channel> { |     pub fn get_channel(&self, connection: &mut Telnet, params: &ParameterList) -> Option<Channel> { | ||||||
|         match self { |         match self { | ||||||
|             EventType::NotifyClientMoved => { |             EventType::NotifyClientMoved => { | ||||||
|                 let id = parameter_find(params, "ctid")? |                 self.find_channel(connection, params, "ctid") | ||||||
|                     .parse::<i32>().unwrap_or(0); |  | ||||||
|                 wrappers::find_channel(connection, "cid", &id.to_string(), true).unwrap().or(None) |  | ||||||
|             } |             } | ||||||
|             _ => None, |             _ => None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn get_client(&self, connection: &mut Telnet, params: &ParameterList) -> Option<Client> { |     pub fn find_client(&self, connection: &mut Telnet, params: &ParameterList, param_name: &str) -> Option<Client> { | ||||||
|         match self { |         let id = parameter_find(params, param_name)? | ||||||
|             EventType::NotifyClientMoved => { |  | ||||||
|                 let id = parameter_find(params, "clid")? |  | ||||||
|             .parse::<i32>().unwrap_or(0); |             .parse::<i32>().unwrap_or(0); | ||||||
|         wrappers::find_client(connection, "clid", &id.to_string(), true).unwrap().or(None) |         wrappers::find_client(connection, "clid", &id.to_string(), true).unwrap().or(None) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_client(&self, connection: &mut Telnet, params: &ParameterList) -> Option<Client> { | ||||||
|  |         match self { | ||||||
|  |             EventType::NotifyClientMoved => { | ||||||
|  |                 self.find_client(connection, params, "clid") | ||||||
|  |             } | ||||||
|             EventType::NotifyClientEnterView => { |             EventType::NotifyClientEnterView => { | ||||||
|                 Some(Client::from(params.clone())) |                 Some(Client::from(params.clone())) | ||||||
|             } |             } | ||||||
|  |             EventType::NotifyTextMessage => { | ||||||
|  |                 self.find_client(connection, params, "invokerid") | ||||||
|  |             } | ||||||
|  |             EventType::NotifyClientPoke => { | ||||||
|  |                 self.find_client(connection, params, "invokerid") | ||||||
|  |             } | ||||||
|             _ => None, |             _ => None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Event { | impl Event { | ||||||
|     pub fn new(connection: &mut Telnet, event_type: EventType, params: ParameterList) -> Event { |     pub fn new(connection: &mut Telnet, event_type: EventType, params: ParameterList, known_clients: &[Client]) -> Event { | ||||||
|         let channel = event_type.get_channel(connection, ¶ms); |         let channel = event_type.get_channel(connection, ¶ms); | ||||||
|         let client = event_type.get_client(connection, ¶ms); |         let mut client = event_type.get_client(connection, ¶ms); | ||||||
|  | 
 | ||||||
|  |         if client.is_none() { | ||||||
|  |             let id = parameter_find(¶ms, "clid") | ||||||
|  |                 .unwrap_or_else(|| String::from("0")) | ||||||
|  |                 .parse::<i32>().unwrap_or(0); | ||||||
|  |             let client_id = id.to_string(); | ||||||
|  |             client = known_clients.iter().find(|c| c.clid.to_string() == client_id).cloned(); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         Event { |         Event { | ||||||
|             event_type, |             event_type, | ||||||
|  | @ -190,4 +213,70 @@ impl Event { | ||||||
|             client, |             client, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_client_name(&self) -> String { | ||||||
|  |         match &self.client { | ||||||
|  |             Some(client) => client.client_nickname.clone(), | ||||||
|  |             None => String::from("UNKNOWN"), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_channel_name(&self) -> String { | ||||||
|  |         match &self.channel { | ||||||
|  |             Some(channel) => channel.channel_name.clone(), | ||||||
|  |             None => String::from("UNKNOWN"), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_event_msg(&self) -> String { | ||||||
|  |         parameter_find(&self.params, "msg").unwrap_or_else(|| String::from("")) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_message(&self) -> String { | ||||||
|  |         match &self.event_type { | ||||||
|  |             EventType::NotifyClientPoke => { | ||||||
|  |                 format!("{}: {}", | ||||||
|  |                         self.get_client_name(), | ||||||
|  |                         self.get_event_msg() | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  |             EventType::NotifyTextMessage => { | ||||||
|  |                 format!("{}: {}", | ||||||
|  |                         self.get_client_name(), | ||||||
|  |                         self.get_event_msg() | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  |             EventType::NotifyClientMoved => { | ||||||
|  |                 format!("{} joined {}", | ||||||
|  |                     self.get_client_name(), | ||||||
|  |                     self.get_channel_name() | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  |             EventType::NotifyClientLeftView => { | ||||||
|  |                 format!("{} left", | ||||||
|  |                     self.get_client_name() | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  |             EventType::NotifyClientEnterView => { | ||||||
|  |                 format!("{} connected", | ||||||
|  |                     self.get_client_name() | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  |             _ => String::from(""), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Serialize for Event { | ||||||
|  |     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||||||
|  |         where | ||||||
|  |             S: Serializer, | ||||||
|  |     { | ||||||
|  |         let mut x = serializer.serialize_struct("Event", 4)?; | ||||||
|  |         x.serialize_field("type", &self.event_type)?; | ||||||
|  |         x.serialize_field("channel", &self.channel)?; | ||||||
|  |         x.serialize_field("client", &self.client)?; | ||||||
|  |         x.serialize_field("message", &self.get_message())?; | ||||||
|  |         x.end() | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | @ -44,7 +44,7 @@ pub fn parameter_parse(params_str: &str) -> ParameterList { | ||||||
| 
 | 
 | ||||||
|     let mut response_params = ParameterList::new(); |     let mut response_params = ParameterList::new(); | ||||||
|     parts.iter().for_each(|part| { |     parts.iter().for_each(|part| { | ||||||
|         let (key, value) = part.split_once('=').unwrap_or((part, "1")); |         let (key, value) = part.split_once('=').unwrap_or((part, "")); | ||||||
|         response_params.insert(key.to_string(), decode_value(value)); |         response_params.insert(key.to_string(), decode_value(value)); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								ts-control
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								ts-control
									
										
									
									
									
								
							|  | @ -9,7 +9,7 @@ not away | ||||||
| back | back | ||||||
| message | message | ||||||
| message-user | message-user | ||||||
| events-move" | events" | ||||||
| 
 | 
 | ||||||
| _ts_control_get_entity() { | _ts_control_get_entity() { | ||||||
| 	entity=$(_ts_control_single_or_dmenu "$(teamspeak-query-lib "$1s")" "$2") | 	entity=$(_ts_control_single_or_dmenu "$(teamspeak-query-lib "$1s")" "$2") | ||||||
|  | @ -98,8 +98,8 @@ case $action in | ||||||
| 		message=$(_ts_control_get_message "$3") | 		message=$(_ts_control_get_message "$3") | ||||||
| 		teamspeak-query-lib message --strict-client --client "$user" "$message" | 		teamspeak-query-lib message --strict-client --client "$user" "$message" | ||||||
| 		;; | 		;; | ||||||
| 	"events-move") | 	"events") | ||||||
| 		teamspeak-query-lib events NotifyClientMoved NotifyClientEnterView \ | 		teamspeak-query-lib events NotifyClientMoved NotifyClientEnterView NotifyClientLeftView NotifyTextMessage NotifyClientPoke \ | ||||||
| 			| jq -r --unbuffered '.client.client_nickname + " joined " + .channel.channel_name // "the server"' \ | 			| jq -r --unbuffered '.message' \ | ||||||
| 			| tee >(xargs -I{} notify-send "TS3 movement" "{}") | 			| tee >(xargs -I{} notify-send "TS3 Event" "{}") | ||||||
| esac | esac | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue