119 lines
4.3 KiB
Rust
119 lines
4.3 KiB
Rust
use std::time::Duration;
|
|
use crate::utils::SendTextMessageTarget;
|
|
use telnet::Event::{Data, TimedOut};
|
|
use telnet::Telnet;
|
|
use crate::models::EventType;
|
|
|
|
use crate::parameter::{Parameter, parameters_to_string, ParameterList, parameter_to_string, parameter_list_to_string};
|
|
use crate::response::Response;
|
|
|
|
fn to_single_response(resp: Response) -> Response {
|
|
match resp {
|
|
Response::DataList(list) => Response::Data(list[0].clone()),
|
|
_ => resp
|
|
}
|
|
}
|
|
|
|
fn read_part(connection: &mut Telnet) -> Result<String, String> {
|
|
match connection.read_timeout(Duration::new(5, 0)) {
|
|
Ok(event) => {
|
|
match event {
|
|
Data(bytes) => Ok(String::from_utf8(bytes.to_vec())
|
|
.map_err(|_| "Teamspeak returned an invalid response.")?),
|
|
TimedOut => {
|
|
Ok(String::new())
|
|
},
|
|
_ => {
|
|
Err(String::from("Received unknown event from Teamspeak."))
|
|
}
|
|
}
|
|
}
|
|
Err(err) => {
|
|
Err(format!("Failed to read from Teamspeak: {}", err))
|
|
}
|
|
}
|
|
}
|
|
|
|
fn read_response_buffer(connection: &mut Telnet, buffer: &mut String) -> Result<(String, String), String> {
|
|
loop {
|
|
buffer.push_str(&read_part(connection)?);
|
|
match buffer.split_once("\n\r") {
|
|
None => {}
|
|
Some((response, remaining)) => {
|
|
return Ok((String::from(response), String::from(remaining)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn send_command(connection: &mut Telnet, command: &str, skip_ok: bool) -> Result<Response, String> {
|
|
let command = format!("{}\n\r", command);
|
|
connection.write(command.as_bytes()).map_err(|_| "Failed to write to Teamspeak.")?;
|
|
|
|
read_response(connection, skip_ok, String::new())
|
|
}
|
|
|
|
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)?;
|
|
|
|
match Response::try_from(response_str) {
|
|
Ok(resp) => {
|
|
Ok(resp)
|
|
}
|
|
Err(err) => {
|
|
if err.is_error_okay() {
|
|
if skip_ok {
|
|
read_response(connection, skip_ok, buffer)
|
|
} else {
|
|
Ok(Response::Ok)
|
|
}
|
|
} else {
|
|
Err(format!("Received error models from Teamspeak: {} ({})", err.msg, err.id))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn login(connection: &mut Telnet, apikey: &str) -> Result<Response, String> {
|
|
send_command(connection, &format!("auth apikey={}", apikey), false)
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn set_name(connection: &mut Telnet, name: &str) -> Result<Response, String> {
|
|
send_command(connection, &format!("clientupdate client_nickname={}", name), true)
|
|
}
|
|
|
|
pub fn channellist(connection: &mut Telnet) -> Result<Response, String> {
|
|
send_command(connection, "channellist", true)
|
|
}
|
|
|
|
pub fn clientlist(connection: &mut Telnet) -> Result<Response, String> {
|
|
send_command(connection, "clientlist", true)
|
|
}
|
|
|
|
pub fn whoami(connection: &mut Telnet) -> Result<Response, String> {
|
|
send_command(connection, "whoami", true).map(to_single_response)
|
|
}
|
|
|
|
pub fn clientmove(connection: &mut Telnet, cid: &i32, clid_list: Vec<&i32>) -> Result<Response, String> {
|
|
let clid_param_list = clid_list
|
|
.into_iter()
|
|
.map(|clid| (String::from("clid"), clid.to_string()))
|
|
.collect::<Vec<Parameter>>();
|
|
let clid_str = parameters_to_string(clid_param_list, "|");
|
|
send_command(connection, &format!("clientmove cid={} {}", cid, clid_str), false)
|
|
}
|
|
|
|
pub fn clientupdate(connection: &mut Telnet, parameters: ParameterList) -> Result<Response, String> {
|
|
let parameters_str = parameter_list_to_string(parameters, " ");
|
|
send_command(connection, &format!("clientupdate {}", parameters_str), false)
|
|
}
|
|
|
|
pub fn sendtextmessage(connection: &mut Telnet, target: SendTextMessageTarget, msg: String) -> Result<Response, String> {
|
|
let msg = parameter_to_string((String::from("msg"), msg));
|
|
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)
|
|
}
|