aboutsummaryrefslogtreecommitdiffstats
path: root/src/teamspeak.rs
diff options
context:
space:
mode:
authorJokler <jokler@protonmail.com>2020-01-29 20:45:40 +0100
committerGitHub <noreply@github.com>2020-01-29 20:45:40 +0100
commitcc9e2a50abe88ad30783d6708f565b5e2d885c6e (patch)
tree0ee5b1495fc402829c44fcb56aec5167b0ff7369 /src/teamspeak.rs
parentf8f986f9e17caac8dc246637de1c9063803d2699 (diff)
parent12f5c6dbe1ca2c6be21faa3bc239385aabef68e4 (diff)
downloadpokebot-cc9e2a50abe88ad30783d6708f565b5e2d885c6e.tar.gz
pokebot-cc9e2a50abe88ad30783d6708f565b5e2d885c6e.zip
Merge pull request #19 from Mavulp/multibot
Split the bot into a master bot and music bots
Diffstat (limited to 'src/teamspeak.rs')
-rw-r--r--src/teamspeak.rs157
1 files changed, 130 insertions, 27 deletions
diff --git a/src/teamspeak.rs b/src/teamspeak.rs
index 79dc1bc..b429869 100644
--- a/src/teamspeak.rs
+++ b/src/teamspeak.rs
@@ -1,36 +1,78 @@
+use std::sync::{Arc, Mutex};
+use std::time::{Duration, Instant};
+
use futures::compat::Future01CompatExt;
use futures01::{future::Future, sink::Sink};
use tokio02::sync::mpsc::UnboundedSender;
-use crate::{ApplicationMessage, Message};
-use std::sync::{Arc, Mutex};
use tsclientlib::Event::ConEvents;
-use tsclientlib::{events::Event, ClientId, ConnectOptions, Connection, MessageTarget};
+use tsclientlib::{
+ events::Event, ChannelId, ClientId, ConnectOptions, Connection, DisconnectOptions,
+ MessageTarget, Reason,
+};
use log::error;
+use crate::bot::{Message, MusicBotMessage};
+
pub struct TeamSpeakConnection {
conn: Connection,
}
-fn get_message<'a>(event: &Event) -> Option<Message> {
+fn get_message<'a>(event: &Event) -> Option<MusicBotMessage> {
+ use tsclientlib::events::{PropertyId, PropertyValue};
+
match event {
Event::Message {
from: target,
invoker: sender,
message: msg,
- } => Some(Message {
- target: target.clone(),
+ } => Some(MusicBotMessage::TextMessage(Message {
+ target: *target,
invoker: sender.clone(),
text: msg.clone(),
- }),
+ })),
+ Event::PropertyChanged {
+ id: property,
+ old: from,
+ invoker: _,
+ } => match property {
+ PropertyId::ClientChannel(client) => {
+ if let PropertyValue::ChannelId(from) = from {
+ Some(MusicBotMessage::ClientChannel {
+ client: *client,
+ old_channel: *from,
+ })
+ } else {
+ None
+ }
+ }
+ _ => None,
+ },
+ Event::PropertyRemoved {
+ id: property,
+ old: client,
+ invoker: _,
+ } => match property {
+ PropertyId::Client(id) => {
+ if let PropertyValue::Client(client) = client {
+ Some(MusicBotMessage::ClientDisconnected {
+ id: *id,
+ client: client.clone(),
+ })
+ } else {
+ None
+ }
+ }
+ _ => None,
+ },
_ => None,
}
}
impl TeamSpeakConnection {
pub async fn new(
- tx: Arc<Mutex<UnboundedSender<ApplicationMessage>>>,
+ tx: Arc<Mutex<UnboundedSender<MusicBotMessage>>>,
options: ConnectOptions,
) -> Result<TeamSpeakConnection, tsclientlib::Error> {
let conn = Connection::new(options).compat().await?;
@@ -43,8 +85,9 @@ impl TeamSpeakConnection {
if let ConEvents(_conn, events) = e {
for event in *events {
if let Some(msg) = get_message(event) {
- let tx = tx.lock().unwrap();
- tx.send(ApplicationMessage::TextMessage(msg)).unwrap();
+ let tx = tx.lock().expect("Mutex was not poisoned");
+ // Ignore the result because the receiver might get dropped first.
+ let _ = tx.send(msg);
}
}
}
@@ -72,23 +115,58 @@ impl TeamSpeakConnection {
tokio::run(send_packet);
}
- pub fn join_channel_of_user(&self, id: ClientId) {
- let channel = self
- .conn
- .lock()
- .clients
- .get(&id)
- .expect("can find poke sender")
- .channel;
- tokio::spawn(
- self.conn
- .lock()
- .to_mut()
- .get_client(&self.conn.lock().own_client)
- .expect("can get myself")
- .set_channel(channel)
- .map_err(|e| error!("Failed to switch channel: {}", e)),
- );
+ pub fn channel_of_user(&self, id: ClientId) -> Option<ChannelId> {
+ Some(self.conn.lock().clients.get(&id)?.channel)
+ }
+
+ pub fn channel_path_of_user(&self, id: ClientId) -> Option<String> {
+ let conn = self.conn.lock();
+
+ let channel_id = conn.clients.get(&id)?.channel;
+
+ let mut channel = conn
+ .channels
+ .get(&channel_id)
+ .expect("can find user channel");
+
+ let mut names = vec![&channel.name[..]];
+
+ // Channel 0 is the root channel
+ while channel.parent != ChannelId(0) {
+ names.push("/");
+ channel = conn
+ .channels
+ .get(&channel.parent)
+ .expect("can find user channel");
+ names.push(&channel.name);
+ }
+
+ let mut path = String::new();
+ while let Some(name) = names.pop() {
+ path.push_str(name);
+ }
+
+ Some(path)
+ }
+
+ pub fn my_channel(&self) -> ChannelId {
+ let conn = self.conn.lock();
+ conn.clients
+ .get(&conn.own_client)
+ .expect("can find myself")
+ .channel
+ }
+
+ pub fn user_count(&self, channel: ChannelId) -> u32 {
+ let conn = self.conn.lock();
+ let mut count = 0;
+ for (_, client) in &conn.clients {
+ if client.channel == channel {
+ count += 1;
+ }
+ }
+
+ count
}
pub fn set_nickname(&self, name: &str) {
@@ -122,4 +200,29 @@ impl TeamSpeakConnection {
.map_err(|e| error!("Failed to send message: {}", e)),
);
}
+
+ pub fn send_message_to_user(&self, id: ClientId, text: &str) {
+ tokio::spawn(
+ self.conn
+ .lock()
+ .to_mut()
+ .send_message(MessageTarget::Client(id), text)
+ .map_err(|e| error!("Failed to send message: {}", e)),
+ );
+ }
+
+ pub fn disconnect(&self, reason: &str) {
+ let opt = DisconnectOptions::new()
+ .reason(Reason::Clientdisconnect)
+ .message(reason);
+ tokio::spawn(
+ self.conn
+ .disconnect(opt)
+ .map_err(|e| error!("Failed to send message: {}", e)),
+ );
+ // Might or might not be required to keep tokio running while the bot disconnects
+ tokio::spawn(
+ tokio::timer::Delay::new(Instant::now() + Duration::from_secs(1)).map_err(|_| ()),
+ );
+ }
}