use std::time::Duration; use telnet::Event::TimedOut; use telnet::Telnet; use crate::{commands, parameter}; use crate::parameter::{parameter_list_find_all, ParameterList}; use crate::models::Channel; use crate::models::Client; use crate::response::Response; use crate::utils::SendTextMessageTarget; pub fn skip_welcome(connection: &mut Telnet) -> Result<(), String> { loop { let event_result = connection.read_timeout(Duration::from_millis(100)); match event_result { Ok(event) => { if let TimedOut = event { return Ok(()); } } Err(_) => return Err(String::from("Failed to read from Teamspeak.")), } } } pub fn login(connection: &mut Telnet) -> Result<(), String> { // read api key from environment variable let apikey = std::env::var("TS3_CLIENT_API_KEY") .map_err(|_| String::from("No API key found in environment variable TS3_CLIENT_API_KEY."))?; commands::login(connection, &apikey) .map(|_| ()) .map_err(|err| format!("Failed to authenticate with Teamspeak: {}", err)) } pub fn get_channels(connection: &mut Telnet, spacers: bool) -> Result<Vec<Channel>, String> { match commands::channellist(connection)? { Response::DataList(parameter_lists) => { let channels: Vec<Channel> = parameter_lists.iter() .map(|params| Channel::from(params.clone())) .collect(); let mut channels = Channel::sort_list(channels); if !spacers { channels.retain(|c| !c.is_spacer()); } Ok(channels) } _ => Err(String::from("Received unexpected models from Teamspeak.")) } } pub fn find_channel(connection: &mut Telnet, key: &str, value: &str, strict: bool) -> Result<Option<Channel>, String> { match commands::channellist(connection)? { Response::DataList(parameter_lists) => { match parameter::parameter_list_find(¶meter_lists, key, value, strict) { Some(params) => { Ok(Some(Channel::from(params))) } None => { Ok(None) } } } _ => Err(String::from("Received unexpected models from Teamspeak.")) } } pub fn get_clients(connection: &mut Telnet) -> Result<Vec<Client>, String> { match commands::clientlist(connection)? { Response::DataList(parameter_lists) => { let mut clients: Vec<Client> = parameter_lists.iter() .map(|params| Client::from(params.clone())) .collect(); clients.sort_by(|a, b| a.client_nickname.cmp(&b.client_nickname)); Ok(clients) } _ => Err(String::from("Received unexpected models from Teamspeak.")) } } pub fn find_client(connection: &mut Telnet, key: &str, value: &str, strict: bool) -> Result<Option<Client>, String> { match commands::clientlist(connection)? { Response::DataList(parameter_lists) => { match parameter::parameter_list_find(¶meter_lists, key, value, strict) { Some(params) => { Ok(Some(Client::from(params))) } None => { Ok(None) } } } _ => Err(String::from("Received unexpected models from Teamspeak.")) } } pub fn get_channel_clients(connection: &mut Telnet, channel: &Channel) -> Result<Vec<Client>, String> { match commands::clientlist(connection)? { Response::DataList(parameter_lists) => { let mut clients: Vec<Client> = Vec::new(); for client_params in parameter_list_find_all(¶meter_lists, "cid", &channel.cid.to_string(), true) { clients.push(Client::from(client_params)); } Ok(clients) } _ => Err(String::from("Received unexpected models from Teamspeak.")) } } pub fn get_self_clid(connection: &mut Telnet) -> Result<String, String> { match commands::whoami(connection)? { Response::Data(params) => { match parameter::parameter_find(¶ms, "clid") { None => Err(String::from("Could not find clid in models from Teamspeak.")), Some(param) => Ok(param) } } _ => Err(String::from("Received unexpected models from Teamspeak for whoami.")) } } pub fn find_self(connection: &mut Telnet) -> Result<Client, String> { let clid = get_self_clid(connection)?; match commands::clientlist(connection)? { Response::DataList(parameter_lists) => { match parameter::parameter_list_find(¶meter_lists, "clid", &clid, false) { Some(params) => { Ok(Client::from(params)) } None => { Err(String::from("Could not find self in models from Teamspeak.")) } } } _ => Err(String::from("Received unexpected models from Teamspeak for clientlist.")) } } pub fn fetch_client(connection: &mut Telnet, clients: &[Client]) -> Result<Response, String> { let cid = find_self(connection)?.cid; let clid_list: Vec<&i32> = clients.iter().map(|c| &c.clid).collect(); commands::clientmove(connection, &cid, clid_list) } pub fn fetch_channel(connection: &mut Telnet, channel: Channel) -> Result<Response, String> { let cid = find_self(connection)?.cid; let clients = get_channel_clients(connection, &channel)?; let clid_list: Vec<&i32> = clients.iter().map(|c| &c.clid).collect(); commands::clientmove(connection, &cid, clid_list) } pub fn move_client(connection: &mut Telnet, channel: &Channel, clients: &[Client]) -> Result<Response, String> { let clid_list: Vec<&i32> = clients.iter().map(|c| &c.clid).collect(); commands::clientmove(connection, &channel.cid, clid_list) } pub fn update_client(connection: &mut Telnet, parameters: ParameterList) -> Result<Response, String> { commands::clientupdate(connection, parameters) } pub fn send_text_message(connection: &mut Telnet, target: SendTextMessageTarget, msg: String) -> Result<Response, String> { commands::sendtextmessage(connection, target, msg) }