diff options
| author | Jokler <jokler@protonmail.com> | 2020-01-26 06:58:42 +0100 |
|---|---|---|
| committer | Jokler <jokler@protonmail.com> | 2020-01-29 20:39:27 +0100 |
| commit | af0a1b81707536caf4e498d86912f65981342072 (patch) | |
| tree | 6a875cd46bc427544804a14278a90e23a119bfc5 /src | |
| parent | 32686ba4a31ecf7c9aedad65c1a6be0be7d96ea2 (diff) | |
| download | pokebot-af0a1b81707536caf4e498d86912f65981342072.tar.gz pokebot-af0a1b81707536caf4e498d86912f65981342072.zip | |
Randomly choose from lists of identities and names
Diffstat (limited to 'src')
| -rw-r--r-- | src/bot/master.rs | 163 | ||||
| -rw-r--r-- | src/bot/music.rs | 19 | ||||
| -rw-r--r-- | src/main.rs | 23 | ||||
| -rw-r--r-- | src/teamspeak.rs | 10 |
4 files changed, 114 insertions, 101 deletions
diff --git a/src/bot/master.rs b/src/bot/master.rs index 007abea..1f1ddfb 100644 --- a/src/bot/master.rs +++ b/src/bot/master.rs @@ -5,6 +5,7 @@ use std::sync::{Arc, Mutex}; use futures::future::{FutureExt, TryFutureExt}; use futures01::future::Future as Future01; use log::info; +use rand::{rngs::SmallRng, seq::SliceRandom, SeedableRng}; use serde::{Deserialize, Serialize}; use tsclientlib::{ClientId, ConnectOptions, Identity, MessageTarget}; @@ -16,8 +17,11 @@ use crate::Args; use crate::bot::{MusicBot, MusicBotArgs, MusicBotMessage}; pub struct MasterBot { - config: MasterConfig, - teamspeak: Option<Arc<TeamSpeakConnection>>, + config: Arc<MasterConfig>, + rng: Arc<Mutex<SmallRng>>, + available_names: Arc<Mutex<Vec<usize>>>, + available_ids: Arc<Mutex<Vec<usize>>>, + teamspeak: Arc<TeamSpeakConnection>, connected_bots: Arc<Mutex<HashMap<String, Arc<MusicBot>>>>, } @@ -25,44 +29,42 @@ impl MasterBot { pub async fn new(args: MasterArgs) -> (Arc<Self>, impl Future) { let (tx, mut rx) = tokio02::sync::mpsc::unbounded_channel(); let tx = Arc::new(Mutex::new(tx)); - let connection = if args.local { - info!("Starting in CLI mode"); - - None - } else { - info!("Starting in TeamSpeak mode"); - - let mut con_config = ConnectOptions::new(args.address.clone()) - .version(tsclientlib::Version::Linux_3_3_2) - .name(args.name.clone()) - .identity(args.id) - .log_commands(args.verbose >= 1) - .log_packets(args.verbose >= 2) - .log_udp_packets(args.verbose >= 3); - - if let Some(channel) = args.channel { - con_config = con_config.channel(channel); - } - - let connection = Arc::new( - TeamSpeakConnection::new(tx.clone(), con_config) - .await - .unwrap(), - ); + info!("Starting in TeamSpeak mode"); + + let mut con_config = ConnectOptions::new(args.address.clone()) + .version(tsclientlib::Version::Linux_3_3_2) + .name(args.master_name.clone()) + .identity(args.id) + .log_commands(args.verbose >= 1) + .log_packets(args.verbose >= 2) + .log_udp_packets(args.verbose >= 3); + + if let Some(channel) = args.channel { + con_config = con_config.channel(channel); + } - Some(connection) - }; + let connection = Arc::new( + TeamSpeakConnection::new(tx.clone(), con_config) + .await + .unwrap(), + ); - let config = MasterConfig { - name: args.name, + let config = Arc::new(MasterConfig { + master_name: args.master_name, address: args.address, - bots: args.bots, + names: args.names, + ids: args.ids, local: args.local, verbose: args.verbose, - }; + }); + let name_count = config.names.len(); + let id_count = config.ids.len(); let bot = Arc::new(Self { config, + rng: Arc::new(Mutex::new(SmallRng::from_entropy())), + available_names: Arc::new(Mutex::new((0..name_count).collect())), + available_ids: Arc::new(Mutex::new((0..id_count).collect())), teamspeak: connection, connected_bots: Arc::new(Mutex::new(HashMap::new())), }); @@ -80,28 +82,62 @@ impl MasterBot { } async fn spawn_bot(&self, id: ClientId) { - let channel = if let Some(ts) = &self.teamspeak { - ts.channel_path_of_user(id) - } else { - String::from("local") + let channel = self.teamspeak.channel_path_of_user(id); + + let (name, name_index) = { + let mut available_names = self.available_names.lock().expect("Mutex was not poisoned"); + let mut rng = self.rng.lock().expect("Mutex was not poisoned"); + available_names.shuffle(&mut *rng); + let name_index = match available_names.pop() { + Some(v) => v, + None => { + self.teamspeak.send_message_to_user( + id, + "Out of names. Too many bots are already connected!", + ); + return; + } + }; + + (self.config.names[name_index].clone(), name_index) }; - let preset = self.config.bots[0].clone(); - let name = format!("{}({})", preset.name, self.config.name); + let (id, id_index) = { + let mut available_ids = self.available_ids.lock().expect("Mutex was not poisoned"); + let mut rng = self.rng.lock().expect("Mutex was not poisoned"); + available_ids.shuffle(&mut *rng); + let id_index = match available_ids.pop() { + Some(v) => v, + None => { + self.teamspeak.send_message_to_user( + id, + "Out of identities. Too many bots are already connected!", + ); + return; + } + }; + + (self.config.ids[id_index].clone(), id_index) + }; let cconnected_bots = self.connected_bots.clone(); - let disconnect_cb = Box::new(move |n| { + let cavailable_names = self.available_names.clone(); + let cavailable_ids = self.available_ids.clone(); + let disconnect_cb = Box::new(move |n, name_index, id_index| { let mut bots = cconnected_bots.lock().expect("Mutex was not poisoned"); bots.remove(&n); + cavailable_names.lock().expect("Mutex was not poisoned").push(name_index); + cavailable_ids.lock().expect("Mutex was not poisoned").push(id_index); }); info!("Connecting to {} on {}", channel, self.config.address); let bot_args = MusicBotArgs { name: name.clone(), - owner: preset.owner, + name_index, + id_index, local: self.config.local, address: self.config.address.clone(), - id: preset.id, + id, channel, verbose: self.config.verbose, disconnect_cb, @@ -128,15 +164,16 @@ impl MasterBot { #[derive(Debug, Serialize, Deserialize)] pub struct MasterArgs { #[serde(default = "default_name")] - pub name: String, + pub master_name: String, #[serde(default = "default_local")] pub local: bool, pub address: String, pub channel: Option<String>, #[serde(default = "default_verbose")] pub verbose: u8, + pub names: Vec<String>, pub id: Identity, - pub bots: Vec<BotConfig>, + pub ids: Vec<Identity>, } fn default_name() -> String { @@ -163,8 +200,9 @@ impl MasterArgs { }; Self { - name: self.name, - bots: self.bots, + master_name: self.master_name, + names: self.names, + ids: self.ids, local, address, id: self.id, @@ -175,39 +213,10 @@ impl MasterArgs { } pub struct MasterConfig { - pub name: String, + pub master_name: String, pub address: String, - pub bots: Vec<BotConfig>, + pub names: Vec<String>, + pub ids: Vec<Identity>, pub local: bool, pub verbose: u8, } - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct BotConfig { - pub name: String, - #[serde( - deserialize_with = "client_id_deserialize", - serialize_with = "client_id_serialize" - )] - pub owner: Option<ClientId>, - pub id: Identity, -} - -fn client_id_serialize<S>(c: &Option<ClientId>, s: S) -> Result<S::Ok, S::Error> -where - S: serde::Serializer, -{ - match c { - Some(c) => s.serialize_some(&c.0), - None => s.serialize_none(), - } -} - -fn client_id_deserialize<'de, D>(deserializer: D) -> Result<Option<ClientId>, D::Error> -where - D: serde::Deserializer<'de>, -{ - let id: Option<u16> = Deserialize::deserialize(deserializer)?; - - Ok(id.map(|id| ClientId(id))) -} diff --git a/src/bot/music.rs b/src/bot/music.rs index 94e7350..fd1a7da 100644 --- a/src/bot/music.rs +++ b/src/bot/music.rs @@ -54,13 +54,14 @@ pub struct MusicBot { pub struct MusicBotArgs { pub name: String, - pub owner: Option<ClientId>, + pub name_index: usize, + pub id_index: usize, pub local: bool, pub address: String, pub id: Identity, pub channel: String, pub verbose: u8, - pub disconnect_cb: Box<dyn FnMut(String) + Send + Sync>, + pub disconnect_cb: Box<dyn FnMut(String, usize, usize) + Send + Sync>, } impl MusicBot { @@ -77,7 +78,7 @@ impl MusicBot { let con_config = ConnectOptions::new(args.address) .version(tsclientlib::Version::Linux_3_3_2) - .name(args.name.clone()) + .name(format!("🎵 {}", args.name)) .identity(args.id) .log_commands(args.verbose >= 1) .log_packets(args.verbose >= 2) @@ -122,12 +123,14 @@ impl MusicBot { let cbot = bot.clone(); let mut disconnect_cb = args.disconnect_cb; let name = args.name; + let name_index = args.name_index; + let id_index = args.id_index; let msg_loop = async move { 'outer: loop { while let Some(msg) = rx.recv().await { if let MusicBotMessage::Quit(reason) = msg { cbot.with_teamspeak(|ts| ts.disconnect(&reason)); - disconnect_cb(name); + disconnect_cb(name, name_index, id_index); break 'outer; } cbot.on_message(msg).await.unwrap(); @@ -294,13 +297,13 @@ impl MusicBot { if *current_state != state { match state { State::Playing => { - self.set_nickname(&format!("{} - Playing", self.name)); + self.set_nickname(&format!("🎵 {} - Playing", self.name)); } State::Paused => { - self.set_nickname(&format!("{} - Paused", self.name)); + self.set_nickname(&format!("🎵 {} - Paused", self.name)); } State::Stopped => { - self.set_nickname(&self.name); + self.set_nickname(&format!("🎵 {}", self.name)); self.set_description(""); } State::EndOfStream => { @@ -310,7 +313,7 @@ impl MusicBot { self.start_playing_audio(request); } else { - self.set_nickname(&self.name); + self.set_nickname(&format!("🎵 {}", self.name)); self.set_description(""); } } diff --git a/src/main.rs b/src/main.rs index bff40f8..ae1bed7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ mod playlist; mod teamspeak; mod youtube_dl; -use bot::{BotConfig, MasterArgs, MasterBot}; +use bot::{MasterArgs, MasterBot}; #[derive(StructOpt, Debug)] #[structopt(raw(global_settings = "&[AppSettings::ColoredHelp]"))] @@ -61,22 +61,18 @@ pub struct Args { } fn main() { - //let example = BotConfig { - //name: String::from("asd"), - //id: Identity::create().unwrap(), - //owner: Some(ClientId(12)), - //}; - //let bots = vec![example]; + //let ids = vec![Identity::create().unwrap()]; //println!( //"{}", //toml::to_string(&MasterArgs { - //name: String::from("PokeBot"), + //master_name: String::from("PokeBot"), //id: Identity::create().unwrap(), + //names: vec![String::from("test")], //address: String::from("localhost"), //channel: Some(String::from("Poke If Needed")), //local: false, //verbose: 0, - //bots, + //ids, //}) //.map_err(|e| panic!(e.to_string())) //.unwrap() @@ -102,14 +98,9 @@ fn run() -> Result<(), Box<dyn std::error::Error>> { let mut config: MasterArgs = toml::from_str(&toml)?; if let Some(count) = args.gen_id_count { - for i in 0..count { + for _ in 0..count { let id = Identity::create().expect("Failed to create id"); - let bot = BotConfig { - name: format!("{}", i), - owner: None, - id, - }; - config.bots.push(bot); + config.ids.push(id); } let toml = toml::to_string(&config)?; diff --git a/src/teamspeak.rs b/src/teamspeak.rs index f49f7a6..5dd80ba 100644 --- a/src/teamspeak.rs +++ b/src/teamspeak.rs @@ -197,6 +197,16 @@ impl TeamSpeakConnection { ); } + 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) |
