Add event listener with JSON output (WIP) Add notifier on movement events Refactor Parameter and ParameterList (still shit)
This commit is contained in:
		
							parent
							
								
									2c0a8ab616
								
							
						
					
					
						commit
						d8cdc2bb11
					
				
					 14 changed files with 338 additions and 186 deletions
				
			
		
							
								
								
									
										45
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										45
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -102,6 +102,12 @@ version = "0.4.1" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "itoa" | ||||||
|  | version = "1.0.10" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "proc-macro2" | name = "proc-macro2" | ||||||
| version = "1.0.69" | version = "1.0.69" | ||||||
|  | @ -120,6 +126,43 @@ dependencies = [ | ||||||
|  "proc-macro2", |  "proc-macro2", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "ryu" | ||||||
|  | version = "1.0.17" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "serde" | ||||||
|  | version = "1.0.193" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" | ||||||
|  | dependencies = [ | ||||||
|  |  "serde_derive", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "serde_derive" | ||||||
|  | version = "1.0.193" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" | ||||||
|  | dependencies = [ | ||||||
|  |  "proc-macro2", | ||||||
|  |  "quote", | ||||||
|  |  "syn", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "serde_json" | ||||||
|  | version = "1.0.109" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9" | ||||||
|  | dependencies = [ | ||||||
|  |  "itoa", | ||||||
|  |  "ryu", | ||||||
|  |  "serde", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "strsim" | name = "strsim" | ||||||
| version = "0.10.0" | version = "0.10.0" | ||||||
|  | @ -142,6 +185,8 @@ name = "teamspeak-query-lib" | ||||||
| version = "0.1.1" | version = "0.1.1" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "clap", |  "clap", | ||||||
|  |  "serde", | ||||||
|  |  "serde_json", | ||||||
|  "telnet", |  "telnet", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,3 +6,6 @@ edition = "2021" | ||||||
| [dependencies] | [dependencies] | ||||||
| telnet = "0.2" | telnet = "0.2" | ||||||
| clap = { version = "4.4", features = ["derive"] } | clap = { version = "4.4", features = ["derive"] } | ||||||
|  | 
 | ||||||
|  | serde = { version = "1.0", features = ["derive"] } | ||||||
|  | serde_json = "1.0" | ||||||
|  |  | ||||||
							
								
								
									
										34
									
								
								src/cli.rs
									
										
									
									
									
								
							
							
						
						
									
										34
									
								
								src/cli.rs
									
										
									
									
									
								
							|  | @ -1,8 +1,8 @@ | ||||||
| use clap::{Args, Parser, Subcommand}; | use clap::{Args, Parser, Subcommand}; | ||||||
| use telnet::Telnet; | use telnet::Telnet; | ||||||
| 
 | 
 | ||||||
| use crate::parameter::{Parameter, ParameterList}; | use crate::parameter::ParameterList; | ||||||
| use crate::models::Channel; | use crate::models::{Channel, EventType}; | ||||||
| use crate::models::Client; | use crate::models::Client; | ||||||
| use crate::utils::SendTextMessageTarget; | use crate::utils::SendTextMessageTarget; | ||||||
| use crate::wrappers; | use crate::wrappers; | ||||||
|  | @ -23,6 +23,7 @@ pub enum Commands { | ||||||
|     Message(MessageArgs), |     Message(MessageArgs), | ||||||
|     Move(MoveArgs), |     Move(MoveArgs), | ||||||
|     Update(UpdateArgs), |     Update(UpdateArgs), | ||||||
|  |     Events(EventArgs), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Args)] | #[derive(Args)] | ||||||
|  | @ -78,6 +79,11 @@ pub struct UpdateArgs { | ||||||
|     speakers: Option<bool>, |     speakers: Option<bool>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Args)] | ||||||
|  | pub struct EventArgs { | ||||||
|  |     pub event: Vec<EventType>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl FetchArgs { | impl FetchArgs { | ||||||
|     pub fn want_channel(&self) -> bool { |     pub fn want_channel(&self) -> bool { | ||||||
|         self.channel.is_some() |         self.channel.is_some() | ||||||
|  | @ -89,14 +95,14 @@ impl FetchArgs { | ||||||
| 
 | 
 | ||||||
|     pub fn channel(&self, connection: &mut Telnet) -> Result<Option<Channel>, String> { |     pub fn channel(&self, connection: &mut Telnet) -> Result<Option<Channel>, String> { | ||||||
|         if let Some(channel) = &self.channel { |         if let Some(channel) = &self.channel { | ||||||
|             wrappers::find_channel(connection, channel, self.strict_channel) |             wrappers::find_channel(connection, "channel_name", channel, self.strict_channel) | ||||||
|         } else { |         } else { | ||||||
|             Err("No channel specified.".to_string()) |             Err("No channel specified.".to_string()) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     pub fn client(&self, connection: &mut Telnet) -> Result<Option<Client>, String> { |     pub fn client(&self, connection: &mut Telnet) -> Result<Option<Client>, String> { | ||||||
|         if let Some(client) = &self.client { |         if let Some(client) = &self.client { | ||||||
|             wrappers::find_client(connection, client, self.strict_client) |             wrappers::find_client(connection, "client_nickname", client, self.strict_client) | ||||||
|         } else { |         } else { | ||||||
|             Err("No client specified.".to_string()) |             Err("No client specified.".to_string()) | ||||||
|         } |         } | ||||||
|  | @ -108,7 +114,7 @@ impl MessageArgs { | ||||||
|         if self.server { |         if self.server { | ||||||
|             Ok(SendTextMessageTarget::Server) |             Ok(SendTextMessageTarget::Server) | ||||||
|         } else if let Some(client) = &self.client { |         } else if let Some(client) = &self.client { | ||||||
|             if let Some(client) = wrappers::find_client(connection, client, self.strict_client)? { |             if let Some(client) = wrappers::find_client(connection, "client_nickname", client, self.strict_client)? { | ||||||
|                 return Ok(SendTextMessageTarget::Client(client)); |                 return Ok(SendTextMessageTarget::Client(client)); | ||||||
|             } |             } | ||||||
|             return Err("Could not find client.".to_string()); |             return Err("Could not find client.".to_string()); | ||||||
|  | @ -120,12 +126,12 @@ impl MessageArgs { | ||||||
| 
 | 
 | ||||||
| impl MoveArgs { | impl MoveArgs { | ||||||
|     pub fn channel(&self, connection: &mut Telnet) -> Result<Option<Channel>, String> { |     pub fn channel(&self, connection: &mut Telnet) -> Result<Option<Channel>, String> { | ||||||
|         wrappers::find_channel(connection, &self.channel, self.strict_channel) |         wrappers::find_channel(connection, "channel_name", &self.channel, self.strict_channel) | ||||||
|     } |     } | ||||||
|     pub fn client(&self, connection: &mut Telnet) -> Result<Option<Client>, String> { |     pub fn client(&self, connection: &mut Telnet) -> Result<Option<Client>, String> { | ||||||
|         match &self.client { |         match &self.client { | ||||||
|             Some(client) => { |             Some(client) => { | ||||||
|                 wrappers::find_client(connection, client, self.strict_client) |                 wrappers::find_client(connection, "client_nickname", client, self.strict_client) | ||||||
|             } |             } | ||||||
|             None => { |             None => { | ||||||
|                 match wrappers::find_self(connection) { |                 match wrappers::find_self(connection) { | ||||||
|  | @ -139,25 +145,25 @@ impl MoveArgs { | ||||||
| 
 | 
 | ||||||
| impl UpdateArgs { | impl UpdateArgs { | ||||||
|     pub fn to_parameter_list(&self) -> ParameterList { |     pub fn to_parameter_list(&self) -> ParameterList { | ||||||
|         let mut params: ParameterList = Vec::new(); |         let mut params: ParameterList = ParameterList::new(); | ||||||
| 
 | 
 | ||||||
|         if let Some(name) = &self.name { |         if let Some(name) = &self.name { | ||||||
|             params.push(Parameter::new("client_nickname", name)); |             params.insert(String::from("client_nickname"), name.clone()); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if let Some(away) = &self.away { |         if let Some(away) = &self.away { | ||||||
|             params.push(Parameter::new("client_away_message", away)); |             params.insert(String::from("client_away_message"), away.clone()); | ||||||
|             params.push(Parameter::new("client_away", "1")); |             params.insert(String::from("client_away"), String::from("1")); | ||||||
|         } |         } | ||||||
|         if self.back { |         if self.back { | ||||||
|             params.push(Parameter::new("client_away", "0")); |             params.insert(String::from("client_away"), String::from("0")); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if let Some(microphone) = self.microphone { |         if let Some(microphone) = self.microphone { | ||||||
|             params.push(Parameter::new("client_input_muted", &u8::from(!microphone).to_string())); |             params.insert(String::from("client_input_muted"), u8::from(!microphone).to_string()); | ||||||
|         } |         } | ||||||
|         if let Some(speakers) = self.speakers { |         if let Some(speakers) = self.speakers { | ||||||
|             params.push(Parameter::new("client_output_muted", &u8::from(!speakers).to_string())); |             params.insert(String::from("client_output_muted"), u8::from(!speakers).to_string()); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         params |         params | ||||||
|  |  | ||||||
|  | @ -1,8 +1,9 @@ | ||||||
| use crate::utils::SendTextMessageTarget; | use crate::utils::SendTextMessageTarget; | ||||||
| use telnet::Event::Data; | use telnet::Event::Data; | ||||||
| use telnet::Telnet; | use telnet::Telnet; | ||||||
|  | use crate::models::EventType; | ||||||
| 
 | 
 | ||||||
| use crate::parameter::{Parameter, ParameterList}; | use crate::parameter::{Parameter, parameters_to_string, ParameterList, parameter_to_string, parameter_list_to_string}; | ||||||
| use crate::response::Response; | use crate::response::Response; | ||||||
| 
 | 
 | ||||||
| fn to_single_response(resp: Response) -> Response { | fn to_single_response(resp: Response) -> Response { | ||||||
|  | @ -48,7 +49,7 @@ fn send_command(connection: &mut Telnet, command: &str, skip_ok: bool) -> Result | ||||||
|     read_response(connection, skip_ok, String::new()) |     read_response(connection, skip_ok, String::new()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn read_response(connection: &mut Telnet, skip_ok: bool, mut buffer: String) -> Result<Response, String> { | pub fn read_response(connection: &mut Telnet, skip_ok: bool, mut buffer: String) -> Result<Response, String> { | ||||||
|     let (response_str, buffer) = read_response_buffer(connection, &mut buffer)?; |     let (response_str, buffer) = read_response_buffer(connection, &mut buffer)?; | ||||||
| 
 | 
 | ||||||
|     match Response::try_from(response_str) { |     match Response::try_from(response_str) { | ||||||
|  | @ -93,18 +94,22 @@ pub fn whoami(connection: &mut Telnet) -> Result<Response, String> { | ||||||
| pub fn clientmove(connection: &mut Telnet, cid: &i32, clid_list: Vec<&i32>) -> Result<Response, String> { | pub fn clientmove(connection: &mut Telnet, cid: &i32, clid_list: Vec<&i32>) -> Result<Response, String> { | ||||||
|     let clid_param_list = clid_list |     let clid_param_list = clid_list | ||||||
|         .into_iter() |         .into_iter() | ||||||
|         .map(|clid| Parameter::new("clid", &clid.to_string())) |         .map(|clid| (String::from("clid"), clid.to_string())) | ||||||
|         .collect::<Vec<Parameter>>(); |         .collect::<Vec<Parameter>>(); | ||||||
|     let clid_str = Parameter::list_to_string_sep(clid_param_list, "|"); |     let clid_str = parameters_to_string(clid_param_list, "|"); | ||||||
|     send_command(connection, &format!("clientmove cid={} {}", cid, clid_str), false) |     send_command(connection, &format!("clientmove cid={} {}", cid, clid_str), false) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn clientupdate(connection: &mut Telnet, parameters: ParameterList) -> Result<Response, String> { | pub fn clientupdate(connection: &mut Telnet, parameters: ParameterList) -> Result<Response, String> { | ||||||
|     let parameters_str = Parameter::list_to_string(parameters); |     let parameters_str = parameter_list_to_string(parameters, " "); | ||||||
|     send_command(connection, &format!("clientupdate {}", parameters_str), false) |     send_command(connection, &format!("clientupdate {}", parameters_str), false) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn sendtextmessage(connection: &mut Telnet, target: SendTextMessageTarget, msg: String) -> Result<Response, String> { | pub fn sendtextmessage(connection: &mut Telnet, target: SendTextMessageTarget, msg: String) -> Result<Response, String> { | ||||||
|     let msg = String::from(Parameter::new("msg", &msg)); |     let msg = parameter_to_string((String::from("msg"), msg)); | ||||||
|     send_command(connection, &format!("sendtextmessage {} {}", msg, String::from(target)), false) |     send_command(connection, &format!("sendtextmessage {} {}", msg, String::from(target)), false) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | pub fn clientnotifyregister(connection: &mut Telnet, schandlerid: u32, event: EventType) -> Result<Response, String> { | ||||||
|  |     send_command(connection, &format!("clientnotifyregister schandlerid={} event={}", schandlerid, String::from(&event)), false) | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										35
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										35
									
								
								src/main.rs
									
										
									
									
									
								
							|  | @ -3,8 +3,9 @@ use std::process::exit; | ||||||
| use telnet::Telnet; | use telnet::Telnet; | ||||||
| 
 | 
 | ||||||
| use crate::cli::Commands; | use crate::cli::Commands; | ||||||
| use crate::models::Channel; | use crate::models::{Channel, Event}; | ||||||
| use crate::models::Client; | use crate::models::Client; | ||||||
|  | use crate::response::Response; | ||||||
| 
 | 
 | ||||||
| mod wrappers; | mod wrappers; | ||||||
| mod commands; | mod commands; | ||||||
|  | @ -49,8 +50,6 @@ fn main() { | ||||||
|     wrappers::skip_welcome(&mut connection); |     wrappers::skip_welcome(&mut connection); | ||||||
|     wrappers::login(&mut connection); |     wrappers::login(&mut connection); | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     // You can check for the existence of subcommands, and if found use their
 |     // You can check for the existence of subcommands, and if found use their
 | ||||||
|     // matches just as you would the top level cmd
 |     // matches just as you would the top level cmd
 | ||||||
|     match cli { |     match cli { | ||||||
|  | @ -154,5 +153,35 @@ fn main() { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         Commands::Events(args) => { | ||||||
|  |             for event in args.event { | ||||||
|  |                 if commands::clientnotifyregister(&mut connection, 1, event).is_err() { | ||||||
|  |                     println!("Failed to register event listener."); | ||||||
|  |                     exit(1); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             loop { | ||||||
|  |                 match commands::read_response(&mut connection, true, String::new()) { | ||||||
|  |                     Ok(response) => { | ||||||
|  |                         if let Response::Event(event_type, params) = response { | ||||||
|  | 
 | ||||||
|  |                             let event = Event::new(&mut connection, event_type, params); | ||||||
|  |                             match serde_json::to_string(&event) { | ||||||
|  |                                 Ok(json) => println!("{}", json), | ||||||
|  |                                 Err(_) => { | ||||||
|  |                                     // TODO: Handle error
 | ||||||
|  |                                 } | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     Err(_) => { | ||||||
|  |                         // TODO: Handle error
 | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -1,8 +1,9 @@ | ||||||
| use std::fmt::{Display, Formatter}; | use std::fmt::{Display, Formatter}; | ||||||
|  | use serde::{Deserialize, Serialize}; | ||||||
| 
 | 
 | ||||||
| use crate::parameter::{parameter_find, ParameterList}; | use crate::parameter::{parameter_find, ParameterList}; | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Serialize, Deserialize, Debug)] | ||||||
| pub struct Channel { | pub struct Channel { | ||||||
|     pub cid: i32, |     pub cid: i32, | ||||||
|     pub pid: i32, |     pub pid: i32, | ||||||
|  | @ -23,22 +24,20 @@ impl From<ParameterList> for Channel { | ||||||
|         Channel { |         Channel { | ||||||
|             cid: parameter_find(&value, "cid") |             cid: parameter_find(&value, "cid") | ||||||
|                 .unwrap_or_default() |                 .unwrap_or_default() | ||||||
|                 .to_i32(-1), |                 .parse::<i32>().unwrap_or(-1), | ||||||
|             pid: parameter_find(&value, "pid") |             pid: parameter_find(&value, "pid") | ||||||
|                 .unwrap_or_default() |                 .unwrap_or_default() | ||||||
|                 .to_i32(-1), |                 .parse::<i32>().unwrap_or(-1), | ||||||
|             channel_order: parameter_find(&value, "channel_order") |             channel_order: parameter_find(&value, "channel_order") | ||||||
|                 .unwrap_or_default() |                 .unwrap_or_default() | ||||||
|                 .to_i32(-1), |                 .parse::<i32>().unwrap_or(-1), | ||||||
|             channel_name: parameter_find(&value, "channel_name") |             channel_name: parameter_find(&value, "channel_name") | ||||||
|                 .unwrap_or_default() |                 .unwrap_or_default(), | ||||||
|                 .value, |  | ||||||
|             channel_topic: parameter_find(&value, "channel_topic") |             channel_topic: parameter_find(&value, "channel_topic") | ||||||
|                 .unwrap_or_default() |                 .unwrap_or_default(), | ||||||
|                 .value, |  | ||||||
|             channel_flag_are_subscribed: parameter_find(&value, "channel_flag_are_subscribed") |             channel_flag_are_subscribed: parameter_find(&value, "channel_flag_are_subscribed") | ||||||
|                 .unwrap_or_default() |                 .unwrap_or_default() | ||||||
|                 .to_i32(0) == 1, |                 .parse::<i32>().unwrap_or(0) == 1, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,8 +1,9 @@ | ||||||
| use std::fmt::{Display, Formatter}; | use std::fmt::{Display, Formatter}; | ||||||
|  | use serde::{Deserialize, Serialize}; | ||||||
| 
 | 
 | ||||||
| use crate::parameter::{parameter_find, ParameterList}; | use crate::parameter::{parameter_find, ParameterList}; | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Serialize, Deserialize, Debug)] | ||||||
| pub struct Client { | pub struct Client { | ||||||
|     pub cid: i32, |     pub cid: i32, | ||||||
|     pub clid: i32, |     pub clid: i32, | ||||||
|  | @ -22,19 +23,18 @@ impl From<ParameterList> for Client { | ||||||
|         Client { |         Client { | ||||||
|             cid: parameter_find(&value, "cid") |             cid: parameter_find(&value, "cid") | ||||||
|                 .unwrap_or_default() |                 .unwrap_or_default() | ||||||
|                 .to_i32(-1), |                 .parse::<i32>().unwrap_or(-1), | ||||||
|             clid: parameter_find(&value, "clid") |             clid: parameter_find(&value, "clid") | ||||||
|                 .unwrap_or_default() |                 .unwrap_or_default() | ||||||
|                 .to_i32(-1), |                 .parse::<i32>().unwrap_or(-1), | ||||||
|             client_database_id: parameter_find(&value, "client_database_id") |             client_database_id: parameter_find(&value, "client_database_id") | ||||||
|                 .unwrap_or_default() |                 .unwrap_or_default() | ||||||
|                 .to_i32(-1), |                 .parse::<i32>().unwrap_or(-1), | ||||||
|             client_nickname: parameter_find(&value, "client_nickname") |             client_nickname: parameter_find(&value, "client_nickname") | ||||||
|                 .unwrap_or_default() |                 .unwrap_or_default(), | ||||||
|                 .value, |  | ||||||
|             client_type: parameter_find(&value, "channel_topic") |             client_type: parameter_find(&value, "channel_topic") | ||||||
|                 .unwrap_or_default() |                 .unwrap_or_default() | ||||||
|                 .to_i32(0), |                 .parse::<i32>().unwrap_or(0), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -1,7 +1,16 @@ | ||||||
| use std::fmt::{Display, Formatter}; | use std::fmt::{Display, Formatter}; | ||||||
|  | use std::str::FromStr; | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | use serde::{Deserialize, Serialize}; | ||||||
| pub enum Event { | use telnet::Telnet; | ||||||
|  | 
 | ||||||
|  | use crate::models::{Channel, Client}; | ||||||
|  | use crate::parameter::{parameter_find, ParameterList}; | ||||||
|  | use crate::wrappers; | ||||||
|  | 
 | ||||||
|  | #[derive(Serialize, Deserialize, Debug, Clone)] | ||||||
|  | pub enum EventType { | ||||||
|  |     Any, | ||||||
|     ChannelList, |     ChannelList, | ||||||
|     ChannelListFinished, |     ChannelListFinished, | ||||||
|     NotifyTalkStatusChange, |     NotifyTalkStatusChange, | ||||||
|  | @ -16,6 +25,7 @@ pub enum Event { | ||||||
|     NotifyClientChatClosed, |     NotifyClientChatClosed, | ||||||
|     NotifyClientChatComposing, |     NotifyClientChatComposing, | ||||||
|     NotifyClientUpdated, |     NotifyClientUpdated, | ||||||
|  |     NotifyClientChannelGroupChanged, | ||||||
|     NotifyClientIds, |     NotifyClientIds, | ||||||
|     NotifyClientDBIDFromUid, |     NotifyClientDBIDFromUid, | ||||||
|     NotifyClientNameFromUid, |     NotifyClientNameFromUid, | ||||||
|  | @ -33,51 +43,151 @@ pub enum Event { | ||||||
|     NotifyConnectStatusChange, |     NotifyConnectStatusChange, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl TryFrom<&str> for Event { | #[derive(Serialize, Deserialize, Debug)] | ||||||
|  | pub struct Event { | ||||||
|  |     pub event_type: EventType, | ||||||
|  |     pub params: ParameterList, | ||||||
|  |     pub channel: Option<Channel>, | ||||||
|  |     pub client: Option<Client>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl TryFrom<&str> for EventType { | ||||||
|     type Error = String; |     type Error = String; | ||||||
| 
 | 
 | ||||||
|     //noinspection SpellCheckingInspection
 |     //noinspection SpellCheckingInspection
 | ||||||
|     fn try_from(event_type: &str) -> Result<Self, Self::Error> { |     fn try_from(event_type: &str) -> Result<Self, Self::Error> { | ||||||
|         match event_type { |         match event_type.to_lowercase().as_str() { | ||||||
|             "channellist" => Ok(Event::ChannelList), |             "any" => Ok(EventType::Any), | ||||||
|             "channellistfinished" => Ok(Event::ChannelListFinished), |             "channellist" => Ok(EventType::ChannelList), | ||||||
|             "notifytalkstatuschange" => Ok(Event::NotifyTalkStatusChange), |             "channellistfinished" => Ok(EventType::ChannelListFinished), | ||||||
|             "notifymessage" => Ok(Event::NotifyMessage), |             "notifytalkstatuschange" => Ok(EventType::NotifyTalkStatusChange), | ||||||
|             "notifymessagelist" => Ok(Event::NotifyMessageList), |             "notifymessage" => Ok(EventType::NotifyMessage), | ||||||
|             "notifycomplainlist" => Ok(Event::NotifyComplainList), |             "notifymessagelist" => Ok(EventType::NotifyMessageList), | ||||||
|             "notifybanlist" => Ok(Event::NotifyBanList), |             "notifycomplainlist" => Ok(EventType::NotifyComplainList), | ||||||
|             "notifyclientmoved" => Ok(Event::NotifyClientMoved), |             "notifybanlist" => Ok(EventType::NotifyBanList), | ||||||
|             "notifyclientleftview" => Ok(Event::NotifyClientLeftView), |             "notifyclientmoved" => Ok(EventType::NotifyClientMoved), | ||||||
|             "notifycliententerview" => Ok(Event::NotifyClientEnterView), |             "notifyclientleftview" => Ok(EventType::NotifyClientLeftView), | ||||||
|             "notifyclientpoke" => Ok(Event::NotifyClientPoke), |             "notifycliententerview" => Ok(EventType::NotifyClientEnterView), | ||||||
|             "notifyclientchatclosed" => Ok(Event::NotifyClientChatClosed), |             "notifyclientpoke" => Ok(EventType::NotifyClientPoke), | ||||||
|             "notifyclientchatcomposing" => Ok(Event::NotifyClientChatComposing), |             "notifyclientchatclosed" => Ok(EventType::NotifyClientChatClosed), | ||||||
|             "notifyclientupdated" => Ok(Event::NotifyClientUpdated), |             "notifyclientchatcomposing" => Ok(EventType::NotifyClientChatComposing), | ||||||
|             "notifyclientids" => Ok(Event::NotifyClientIds), |             "notifyclientupdated" => Ok(EventType::NotifyClientUpdated), | ||||||
|             "notifyclientdbidfromuid" => Ok(Event::NotifyClientDBIDFromUid), |             "notifyclientchannelgroupchanged" => Ok(EventType::NotifyClientChannelGroupChanged), | ||||||
|             "notifyclientnamefromuid" => Ok(Event::NotifyClientNameFromUid), |             "notifyclientids" => Ok(EventType::NotifyClientIds), | ||||||
|             "notifyclientnamefromdbid" => Ok(Event::NotifyClientNameFromDBID), |             "notifyclientdbidfromuid" => Ok(EventType::NotifyClientDBIDFromUid), | ||||||
|             "notifyclientuidfromclid" => Ok(Event::NotifyClientUidFromClid), |             "notifyclientnamefromuid" => Ok(EventType::NotifyClientNameFromUid), | ||||||
|             "notifyconnectioninfo" => Ok(Event::NotifyConnectionInfo), |             "notifyclientnamefromdbid" => Ok(EventType::NotifyClientNameFromDBID), | ||||||
|             "notifychannelcreated" => Ok(Event::NotifyChannelCreated), |             "notifyclientuidfromclid" => Ok(EventType::NotifyClientUidFromClid), | ||||||
|             "notifychanneledited" => Ok(Event::NotifyChannelEdited), |             "notifyconnectioninfo" => Ok(EventType::NotifyConnectionInfo), | ||||||
|             "notifychanneldeleted" => Ok(Event::NotifyChannelDeleted), |             "notifychannelcreated" => Ok(EventType::NotifyChannelCreated), | ||||||
|             "notifychannelmoved" => Ok(Event::NotifyChannelMoved), |             "notifychanneledited" => Ok(EventType::NotifyChannelEdited), | ||||||
|             "notifyserveredited" => Ok(Event::NotifyServerEdited), |             "notifychanneldeleted" => Ok(EventType::NotifyChannelDeleted), | ||||||
|             "notifyserverupdated" => Ok(Event::NotifyServerUpdated), |             "notifychannelmoved" => Ok(EventType::NotifyChannelMoved), | ||||||
|             "notifytextmessage" => Ok(Event::NotifyTextMessage), |             "notifyserveredited" => Ok(EventType::NotifyServerEdited), | ||||||
|  |             "notifyserverupdated" => Ok(EventType::NotifyServerUpdated), | ||||||
|  |             "notifytextmessage" => Ok(EventType::NotifyTextMessage), | ||||||
|             "notifycurrentserverconnectionchanged" => { |             "notifycurrentserverconnectionchanged" => { | ||||||
|                 Ok(Event::NotifyCurrentServerConnectionChanged) |                 Ok(EventType::NotifyCurrentServerConnectionChanged) | ||||||
|             } |             } | ||||||
|             "notifyconnectstatuschange" => Ok(Event::NotifyConnectStatusChange), |             "notifyconnectstatuschange" => Ok(EventType::NotifyConnectStatusChange), | ||||||
|             _ => Err(String::from("Unknown event type.")), |             _ => Err(format!("Unknown event type: {}", event_type)), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl FromStr for EventType { | ||||||
|  |     type Err = String; | ||||||
| 
 | 
 | ||||||
| impl Display for Event { |     fn from_str(s: &str) -> Result<Self, Self::Err> { | ||||||
|  |         EventType::try_from(s) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl From<&EventType> for String { | ||||||
|  |     //noinspection SpellCheckingInspection
 | ||||||
|  |     fn from(value: &EventType) -> Self { | ||||||
|  |         match value { | ||||||
|  |             EventType::Any => String::from("any"), | ||||||
|  |             EventType::ChannelList => String::from("channellist"), | ||||||
|  |             EventType::ChannelListFinished => String::from("channellistfinished"), | ||||||
|  |             EventType::NotifyTalkStatusChange => String::from("notifytalkstatuschange"), | ||||||
|  |             EventType::NotifyMessage => String::from("notifymessage"), | ||||||
|  |             EventType::NotifyMessageList => String::from("notifymessagelist"), | ||||||
|  |             EventType::NotifyComplainList => String::from("notifycomplainlist"), | ||||||
|  |             EventType::NotifyBanList => String::from("notifybanlist"), | ||||||
|  |             EventType::NotifyClientMoved => String::from("notifyclientmoved"), | ||||||
|  |             EventType::NotifyClientLeftView => String::from("notifyclientleftview"), | ||||||
|  |             EventType::NotifyClientEnterView => String::from("notifycliententerview"), | ||||||
|  |             EventType::NotifyClientPoke => String::from("notifyclientpoke"), | ||||||
|  |             EventType::NotifyClientChatClosed => String::from("notifyclientchatclosed"), | ||||||
|  |             EventType::NotifyClientChatComposing => String::from("notifyclientchatcomposing"), | ||||||
|  |             EventType::NotifyClientChannelGroupChanged => String::from("notifyclientchannelgroupchanged"), | ||||||
|  |             EventType::NotifyClientUpdated => String::from("notifyclientupdated"), | ||||||
|  |             EventType::NotifyClientIds => String::from("notifyclientids"), | ||||||
|  |             EventType::NotifyClientDBIDFromUid => String::from("notifyclientdbidfromuid"), | ||||||
|  |             EventType::NotifyClientNameFromUid => String::from("notifyclientnamefromuid"), | ||||||
|  |             EventType::NotifyClientNameFromDBID => String::from("notifyclientnamefromdbid"), | ||||||
|  |             EventType::NotifyClientUidFromClid => String::from("notifyclientuidfromclid"), | ||||||
|  |             EventType::NotifyConnectionInfo => String::from("notifyconnectioninfo"), | ||||||
|  |             EventType::NotifyChannelCreated => String::from("notifychannelcreated"), | ||||||
|  |             EventType::NotifyChannelEdited => String::from("notifychanneledited"), | ||||||
|  |             EventType::NotifyChannelDeleted => String::from("notifychanneldeleted"), | ||||||
|  |             EventType::NotifyChannelMoved => String::from("notifychannelmoved"), | ||||||
|  |             EventType::NotifyServerEdited => String::from("notifyserveredited"), | ||||||
|  |             EventType::NotifyServerUpdated => String::from("notifyserverupdated"), | ||||||
|  |             EventType::NotifyTextMessage => String::from("notifytextmessage"), | ||||||
|  |             EventType::NotifyCurrentServerConnectionChanged => { | ||||||
|  |                 String::from("notifycurrentserverconnectionchanged") | ||||||
|  |             } | ||||||
|  |             EventType::NotifyConnectStatusChange => String::from("notifyconnectstatuschange"), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Display for EventType { | ||||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||||||
|         write!(f, "{:?}", self) |         let event_str: String = self.into(); | ||||||
|  |         write!(f, "{}", event_str) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl EventType { | ||||||
|  |     pub fn get_channel(&self, connection: &mut Telnet, params: &ParameterList) -> Option<Channel> { | ||||||
|  |         match self { | ||||||
|  |             EventType::NotifyClientMoved => { | ||||||
|  |                 let id = parameter_find(params, "ctid")? | ||||||
|  |                     .parse::<i32>().unwrap_or(0); | ||||||
|  |                 wrappers::find_channel(connection, "cid", &id.to_string(), true).unwrap().or(None) | ||||||
|  |             } | ||||||
|  |             _ => None, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_client(&self, connection: &mut Telnet, params: &ParameterList) -> Option<Client> { | ||||||
|  |         match self { | ||||||
|  |             EventType::NotifyClientMoved => { | ||||||
|  |                 let id = parameter_find(params, "clid")? | ||||||
|  |                     .parse::<i32>().unwrap_or(0); | ||||||
|  |                 wrappers::find_client(connection, "clid", &id.to_string(), true).unwrap().or(None) | ||||||
|  |             } | ||||||
|  |             EventType::NotifyClientEnterView => { | ||||||
|  |                 Some(Client::from(params.clone())) | ||||||
|  |             } | ||||||
|  |             _ => None, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Event { | ||||||
|  |     pub fn new(connection: &mut Telnet, event_type: EventType, params: ParameterList) -> Event { | ||||||
|  |         let channel = event_type.get_channel(connection, ¶ms); | ||||||
|  |         let client = event_type.get_client(connection, ¶ms); | ||||||
|  | 
 | ||||||
|  |         Event { | ||||||
|  |             event_type, | ||||||
|  |             params, | ||||||
|  |             channel, | ||||||
|  |             client, | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -4,4 +4,4 @@ mod event; | ||||||
| 
 | 
 | ||||||
| pub use channel::Channel; | pub use channel::Channel; | ||||||
| pub use client::Client; | pub use client::Client; | ||||||
| pub use event::Event; | pub use event::{EventType, Event}; | ||||||
							
								
								
									
										111
									
								
								src/parameter.rs
									
										
									
									
									
								
							
							
						
						
									
										111
									
								
								src/parameter.rs
									
										
									
									
									
								
							|  | @ -1,36 +1,38 @@ | ||||||
| use std::fmt::{Debug, Display, Formatter}; | use std::collections::HashMap; | ||||||
| use crate::utils::{decode_value, encode_value}; | use crate::utils::{decode_value, encode_value}; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone)] | pub type ParameterList = HashMap<String, String>; | ||||||
| pub struct Parameter { | pub type Parameter = (String, String); | ||||||
|     pub name: String, | 
 | ||||||
|     pub value: String, | pub fn parameter_find(params: &ParameterList, name: &str) -> Option<String> { | ||||||
|  |     params.get(name).map(|value| value.clone()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub type ParameterList = Vec<Parameter>; | pub fn parameter_list_has(params: &ParameterList, key: &str, value: &str, strict: bool) -> bool { | ||||||
| 
 |     if let Some(check_value) = params.get(key) { | ||||||
| pub fn parameter_find(params: &Vec<Parameter>, name: &str) -> Option<Parameter> { |         if check_value == value && strict { | ||||||
|     for param in params { |             return true; | ||||||
|         if param.name == name { |         } | ||||||
|             return Some(param.clone()); |         if check_value.contains(value) && !strict { | ||||||
|  |             return true; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     None |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn parameter_list_find(param_lists: &Vec<ParameterList>, name: &str, value: &str, strict: bool) -> Option<ParameterList> { | pub fn parameter_list_find(param_lists: &Vec<ParameterList>, key: &str, value: &str, strict: bool) -> Option<ParameterList> { | ||||||
|     for params in param_lists { |     for params in param_lists { | ||||||
|         if params.iter().any(|param| param.is(name, value, strict)) { |         if parameter_list_has(params, key, value, strict) { | ||||||
|             return Some(params.clone()); |             return Some(params.clone()); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     None |     None | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn parameter_list_find_all(param_lists: &Vec<ParameterList>, name: &str, value: &str, strict: bool) -> Vec<ParameterList> { | pub fn parameter_list_find_all(param_lists: &Vec<ParameterList>, key: &str, value: &str, strict: bool) -> Vec<ParameterList> { | ||||||
|     let mut found = Vec::new(); |     let mut found = Vec::new(); | ||||||
|     for params in param_lists { |     for params in param_lists { | ||||||
|         if params.iter().any(|param| param.is(name, value, strict)) { |         if parameter_list_has(params, key, value, strict) { | ||||||
|             found.push(params.clone()) |             found.push(params.clone()) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -40,82 +42,31 @@ pub fn parameter_list_find_all(param_lists: &Vec<ParameterList>, name: &str, val | ||||||
| pub fn parameter_parse(params_str: &str) -> ParameterList { | pub fn parameter_parse(params_str: &str) -> ParameterList { | ||||||
|     let parts: Vec<&str> = params_str.split(' ').collect(); |     let parts: Vec<&str> = params_str.split(' ').collect(); | ||||||
| 
 | 
 | ||||||
|     let mut response_params = Vec::new(); |     let mut response_params = ParameterList::new(); | ||||||
|     parts.iter().for_each(|part| { |     parts.iter().for_each(|part| { | ||||||
|         response_params.push(Parameter::from(part.split_once('=').unwrap())); |         let (key, value) = part.split_once('=').unwrap_or((part, "1")); | ||||||
|  |         response_params.insert(key.to_string(), decode_value(value)); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     response_params |     response_params | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl From<(&str, &str)> for Parameter { | pub fn parameter_to_string(param: Parameter) -> String { | ||||||
|     fn from(param: (&str, &str)) -> Parameter { |     format!("{}={}", param.0, encode_value(¶m.1)) | ||||||
|         Parameter::new(param.0, param.1) |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Parameter { | pub fn parameter_list_to_string(parameter_list: ParameterList, sep: &str) -> String { | ||||||
|     pub fn new(name: &str, value: &str) -> Parameter { |  | ||||||
|         Parameter { |  | ||||||
|             name: String::from(name), |  | ||||||
|             value: decode_value(value) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn is(&self, name: &str, value: &str, strict: bool) -> bool { |  | ||||||
|         if self.name != name { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|         if self.value != value && strict { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|         if !self.value.contains(value) && !strict { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|         true |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn to_i32(&self, default: i32) -> i32 { |  | ||||||
|         self.value.parse::<i32>().unwrap_or(default) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn list_to_string(parameter_list: ParameterList) -> String { |  | ||||||
|     parameter_list |     parameter_list | ||||||
|         .into_iter() |         .into_iter() | ||||||
|             .map(String::from) |         .map(|param| parameter_to_string(param)) | ||||||
|             .collect::<Vec<String>>() |  | ||||||
|             .join(" ") |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn list_to_string_sep(parameter_list: ParameterList, sep: &str) -> String { |  | ||||||
|         parameter_list |  | ||||||
|             .into_iter() |  | ||||||
|             .map(String::from) |  | ||||||
|         .collect::<Vec<String>>() |         .collect::<Vec<String>>() | ||||||
|         .join(sep) |         .join(sep) | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Display for Parameter { | pub fn parameters_to_string(parameters: Vec<Parameter>, sep: &str) -> String { | ||||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |     parameters | ||||||
|         write!(f, "{}={}", self.name, self.value) |         .into_iter() | ||||||
|     } |         .map(|param| parameter_to_string(param)) | ||||||
| } |         .collect::<Vec<String>>() | ||||||
| 
 |         .join(sep) | ||||||
| impl Debug for Parameter { |  | ||||||
|     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |  | ||||||
|         write!(f, "{}={}", self.name, self.value) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Default for Parameter { |  | ||||||
|     fn default() -> Self { |  | ||||||
|         Parameter::new("", "") |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl From<Parameter> for String { |  | ||||||
|     fn from(value: Parameter) -> Self { |  | ||||||
|         format!("{}={}", value.name, encode_value(&value.value)) |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| use std::fmt::{Debug, Display, Formatter}; | use std::fmt::{Debug, Display, Formatter}; | ||||||
| use crate::models::Event; | use crate::models::EventType; | ||||||
| 
 | 
 | ||||||
| use crate::parameter::*; | use crate::parameter::*; | ||||||
| 
 | 
 | ||||||
|  | @ -7,12 +7,12 @@ pub enum Response { | ||||||
|     Ok, |     Ok, | ||||||
|     Data(ParameterList), |     Data(ParameterList), | ||||||
|     DataList(Vec<ParameterList>), |     DataList(Vec<ParameterList>), | ||||||
|     Event(Event, ParameterList), |     Event(EventType, ParameterList), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub enum ResponseType { | pub enum ResponseType { | ||||||
|     Error, |     Error, | ||||||
|     Event(Event), |     Event(EventType), | ||||||
|     Data, |     Data, | ||||||
|     Unknown, |     Unknown, | ||||||
| } | } | ||||||
|  | @ -41,7 +41,7 @@ fn get_response_type(type_str: &str) -> Result<ResponseType, String> { | ||||||
|         return Ok(ResponseType::Error); |         return Ok(ResponseType::Error); | ||||||
|     } |     } | ||||||
|     if type_str.starts_with("notify") || type_str == "channellist" || type_str == "channellistfinished" { |     if type_str.starts_with("notify") || type_str == "channellist" || type_str == "channellistfinished" { | ||||||
|         let event_type = Event::try_from(type_str)?; |         let event_type = EventType::try_from(type_str)?; | ||||||
|         return Ok(ResponseType::Event(event_type)); |         return Ok(ResponseType::Event(event_type)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -120,16 +120,16 @@ impl Display for Response { | ||||||
|                 write!(f, "Ok") |                 write!(f, "Ok") | ||||||
|             } |             } | ||||||
|             Response::Data(params) => { |             Response::Data(params) => { | ||||||
|                 for param in params { |                 for param in params.clone() { | ||||||
|                     write!(f, "{};", param)?; |                     write!(f, "{};", parameter_to_string(param))?; | ||||||
|                 } |                 } | ||||||
|                 Ok(()) |                 Ok(()) | ||||||
|             } |             } | ||||||
|             Response::DataList(params_list) => { |             Response::DataList(params_list) => { | ||||||
|                 for params in params_list { |                 for params in params_list { | ||||||
|                     write!(f, "[")?; |                     write!(f, "[")?; | ||||||
|                     for param in params { |                     for param in params.clone() { | ||||||
|                         write!(f, "{};", param)?; |                         write!(f, "{};", parameter_to_string(param))?; | ||||||
|                     } |                     } | ||||||
|                     write!(f, "]")?; |                     write!(f, "]")?; | ||||||
|                 } |                 } | ||||||
|  | @ -137,8 +137,8 @@ impl Display for Response { | ||||||
|             } |             } | ||||||
|             Response::Event(event, params) => { |             Response::Event(event, params) => { | ||||||
|                 write!(f, "Event: {}", event)?; |                 write!(f, "Event: {}", event)?; | ||||||
|                 for param in params { |                 for param in params.clone() { | ||||||
|                     write!(f, "{};", param)?; |                     write!(f, "{};", parameter_to_string(param))?; | ||||||
|                 } |                 } | ||||||
|                 Ok(()) |                 Ok(()) | ||||||
|             } |             } | ||||||
|  | @ -151,14 +151,13 @@ impl ResponseError { | ||||||
|         self.id == 0 |         self.id == 0 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn create_error(params: &Vec<Parameter>) -> ResponseError { |     fn create_error(params: &ParameterList) -> ResponseError { | ||||||
|         ResponseError { |         ResponseError { | ||||||
|             id: parameter_find(params, "id") |             id: parameter_find(params, "id") | ||||||
|                 .unwrap_or_else(|| Parameter::new("id", "-1")) |                 .unwrap_or_else(|| String::from("-1")) | ||||||
|                 .to_i32(-1), |                 .parse::<i32>().unwrap_or(-1), | ||||||
|             msg: parameter_find(params, "msg") |             msg: parameter_find(params, "msg") | ||||||
|                 .unwrap_or_else(|| Parameter::new("msg", "Unknown error.")) |                 .unwrap_or_else(|| String::from("Unknown error.")) | ||||||
|                 .value, |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
							
								
								
									
										10
									
								
								src/utils.rs
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/utils.rs
									
										
									
									
									
								
							|  | @ -1,5 +1,5 @@ | ||||||
| use crate::models::Client; | use crate::models::Client; | ||||||
| use crate::parameter::Parameter; | use crate::parameter::parameters_to_string; | ||||||
| 
 | 
 | ||||||
| pub fn decode_value(value: &str) -> String { | pub fn decode_value(value: &str) -> String { | ||||||
|     value |     value | ||||||
|  | @ -32,9 +32,9 @@ impl From<SendTextMessageTarget> for String { | ||||||
|             _ => String::from("0"), |             _ => String::from("0"), | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         Parameter::list_to_string(vec![ |         parameters_to_string(vec![ | ||||||
|             Parameter::new("targetmode", target_mode), |             (String::from("targetmode"), String::from(target_mode)), | ||||||
|             Parameter::new("target", &target) |             (String::from("target"), target) | ||||||
|         ]) |         ], " ") | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -57,10 +57,10 @@ pub fn get_channels(connection: &mut Telnet, spacers: bool) -> Result<Vec<Channe | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn find_channel(connection: &mut Telnet, name: &str, strict: bool) -> Result<Option<Channel>, String> { | pub fn find_channel(connection: &mut Telnet, key: &str, value: &str, strict: bool) -> Result<Option<Channel>, String> { | ||||||
|     match commands::channellist(connection)? { |     match commands::channellist(connection)? { | ||||||
|         Response::DataList(parameter_lists) => { |         Response::DataList(parameter_lists) => { | ||||||
|             match parameter::parameter_list_find(¶meter_lists, "channel_name", name, strict) { |             match parameter::parameter_list_find(¶meter_lists, key, value, strict) { | ||||||
|                 Some(params) => { |                 Some(params) => { | ||||||
|                     Ok(Some(Channel::from(params))) |                     Ok(Some(Channel::from(params))) | ||||||
|                 } |                 } | ||||||
|  | @ -88,10 +88,10 @@ pub fn get_clients(connection: &mut Telnet) -> Result<Vec<Client>, String> { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn find_client(connection: &mut Telnet, name: &str, strict: bool) -> Result<Option<Client>, String> { | pub fn find_client(connection: &mut Telnet, key: &str, value: &str, strict: bool) -> Result<Option<Client>, String> { | ||||||
|     match commands::clientlist(connection)? { |     match commands::clientlist(connection)? { | ||||||
|         Response::DataList(parameter_lists) => { |         Response::DataList(parameter_lists) => { | ||||||
|             match parameter::parameter_list_find(¶meter_lists, "client_nickname", name, strict) { |             match parameter::parameter_list_find(¶meter_lists, key, value, strict) { | ||||||
|                 Some(params) => { |                 Some(params) => { | ||||||
|                     Ok(Some(Client::from(params))) |                     Ok(Some(Client::from(params))) | ||||||
|                 } |                 } | ||||||
|  | @ -122,7 +122,7 @@ fn get_self_clid(connection: &mut Telnet) -> Result<String, String> { | ||||||
|         Response::Data(params) => { |         Response::Data(params) => { | ||||||
|             match parameter::parameter_find(¶ms, "clid") { |             match parameter::parameter_find(¶ms, "clid") { | ||||||
|                 None => Err(String::from("Could not find clid in models from Teamspeak.")), |                 None => Err(String::from("Could not find clid in models from Teamspeak.")), | ||||||
|                 Some(param) => Ok(param.value) |                 Some(param) => Ok(param) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         _ => Err(String::from("Received unexpected models from Teamspeak for whoami.")) |         _ => Err(String::from("Received unexpected models from Teamspeak for whoami.")) | ||||||
|  |  | ||||||
|  | @ -8,7 +8,8 @@ away | ||||||
| not away | not away | ||||||
| back | back | ||||||
| message | message | ||||||
| message-user" | message-user | ||||||
|  | events-move" | ||||||
| 
 | 
 | ||||||
| _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") | ||||||
|  | @ -97,4 +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") | ||||||
|  | 		teamspeak-query-lib events NotifyClientMoved NotifyClientEnterView \ | ||||||
|  | 			| jq -r --unbuffered '.client.client_nickname + " joined " + .channel.channel_name // "the server"' \ | ||||||
|  | 			| xargs -I{} notify-send "TS3 movement" "{}" | ||||||
| esac | esac | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue