summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJokler <jokler@protonmail.com>2020-01-25 19:51:15 +0100
committerJokler <jokler@protonmail.com>2020-01-29 20:39:27 +0100
commit32686ba4a31ecf7c9aedad65c1a6be0be7d96ea2 (patch)
treed07de19e207e732cf297c9ba4bcbbbcbdd54eff2
parent7be0a2f10f0cfeb89b2f498cfae316b35dcb0814 (diff)
downloadpokebot-32686ba4a31ecf7c9aedad65c1a6be0be7d96ea2.tar.gz
pokebot-32686ba4a31ecf7c9aedad65c1a6be0be7d96ea2.zip
Let the music bot leave once its channel is empty
-rw-r--r--src/bot/master.rs6
-rw-r--r--src/bot/music.rs42
-rw-r--r--src/teamspeak.rs69
3 files changed, 106 insertions, 11 deletions
diff --git a/src/bot/master.rs b/src/bot/master.rs
index 641938a..007abea 100644
--- a/src/bot/master.rs
+++ b/src/bot/master.rs
@@ -1,10 +1,10 @@
+use std::collections::HashMap;
use std::future::Future;
use std::sync::{Arc, Mutex};
-use std::collections::HashMap;
use futures::future::{FutureExt, TryFutureExt};
use futures01::future::Future as Future01;
-use log::{info};
+use log::info;
use serde::{Deserialize, Serialize};
use tsclientlib::{ClientId, ConnectOptions, Identity, MessageTarget};
@@ -13,7 +13,7 @@ use crate::teamspeak::TeamSpeakConnection;
use crate::Args;
-use crate::bot::{MusicBot, MusicBotMessage, MusicBotArgs};
+use crate::bot::{MusicBot, MusicBotArgs, MusicBotMessage};
pub struct MasterBot {
config: MasterConfig,
diff --git a/src/bot/music.rs b/src/bot/music.rs
index 4d67f88..94e7350 100644
--- a/src/bot/music.rs
+++ b/src/bot/music.rs
@@ -6,9 +6,9 @@ use std::thread;
use log::{debug, info};
use structopt::StructOpt;
use tokio02::sync::mpsc::UnboundedSender;
-use tsclientlib::{ClientId, ConnectOptions, Identity, Invoker, MessageTarget};
+use tsclientlib::{data, ChannelId, ClientId, ConnectOptions, Identity, Invoker, MessageTarget};
-use crate::audio_player::{AudioPlayerError, AudioPlayer, PollResult};
+use crate::audio_player::{AudioPlayer, AudioPlayerError, PollResult};
use crate::command::Command;
use crate::playlist::Playlist;
use crate::teamspeak::TeamSpeakConnection;
@@ -32,6 +32,14 @@ pub enum State {
#[derive(Debug)]
pub enum MusicBotMessage {
TextMessage(Message),
+ ClientChannel {
+ client: ClientId,
+ old_channel: ChannelId,
+ },
+ ClientDisconnected {
+ id: ClientId,
+ client: data::Client,
+ },
StateChange(State),
Quit(String),
}
@@ -179,6 +187,20 @@ impl MusicBot {
}
}
+ fn my_channel(&self) -> ChannelId {
+ self.teamspeak
+ .as_ref()
+ .map(|ts| ts.my_channel())
+ .expect("my_channel needs ts")
+ }
+
+ fn user_count(&self, channel: ChannelId) -> u32 {
+ self.teamspeak
+ .as_ref()
+ .map(|ts| ts.user_count(channel))
+ .expect("user_count needs ts")
+ }
+
fn send_message(&self, text: &str) {
debug!("Sending message to TeamSpeak: {}", text);
@@ -307,6 +329,22 @@ impl MusicBot {
self.on_text(message).await?;
}
}
+ MusicBotMessage::ClientChannel {
+ client: _,
+ old_channel,
+ } => {
+ let my_channel = self.my_channel();
+ if old_channel == my_channel && self.user_count(my_channel) <= 1 {
+ self.quit(String::from("Channel is empty"));
+ }
+ }
+ MusicBotMessage::ClientDisconnected { id: _, client } => {
+ let old_channel = client.channel;
+ let my_channel = self.my_channel();
+ if old_channel == my_channel && self.user_count(my_channel) <= 1 {
+ self.quit(String::from("Channel is empty"));
+ }
+ }
MusicBotMessage::StateChange(state) => {
self.on_state(state)?;
}
diff --git a/src/teamspeak.rs b/src/teamspeak.rs
index f1abaec..f49f7a6 100644
--- a/src/teamspeak.rs
+++ b/src/teamspeak.rs
@@ -19,17 +19,53 @@ 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,
}
}
@@ -49,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(MusicBotMessage::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);
}
}
}
@@ -108,6 +145,26 @@ impl TeamSpeakConnection {
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) {
tokio::spawn(
self.conn