aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJokler <jokler@protonmail.com>2020-01-26 06:58:42 +0100
committerJokler <jokler@protonmail.com>2020-01-29 20:39:27 +0100
commitaf0a1b81707536caf4e498d86912f65981342072 (patch)
tree6a875cd46bc427544804a14278a90e23a119bfc5
parent32686ba4a31ecf7c9aedad65c1a6be0be7d96ea2 (diff)
downloadpokebot-af0a1b81707536caf4e498d86912f65981342072.tar.gz
pokebot-af0a1b81707536caf4e498d86912f65981342072.zip
Randomly choose from lists of identities and names
-rw-r--r--Cargo.lock19
-rw-r--r--Cargo.toml1
-rw-r--r--src/bot/master.rs163
-rw-r--r--src/bot/music.rs19
-rw-r--r--src/main.rs23
-rw-r--r--src/teamspeak.rs10
6 files changed, 130 insertions, 105 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 90cca45..8d57a14 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1786,6 +1786,7 @@ dependencies = [
"gstreamer-audio",
"log",
"log4rs",
+ "rand 0.7.3",
"serde",
"serde_json",
"structopt",
@@ -1914,22 +1915,23 @@ dependencies = [
"rand_isaac",
"rand_jitter",
"rand_os",
- "rand_pcg",
+ "rand_pcg 0.1.2",
"rand_xorshift",
"winapi 0.3.8",
]
[[package]]
name = "rand"
-version = "0.7.2"
+version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom",
"libc",
"rand_chacha 0.2.1",
"rand_core 0.5.1",
"rand_hc 0.2.0",
+ "rand_pcg 0.2.1",
]
[[package]]
@@ -2039,6 +2041,15 @@ dependencies = [
]
[[package]]
+name = "rand_pcg"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
+dependencies = [
+ "rand_core 0.5.1",
+]
+
+[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2569,7 +2580,7 @@ checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
dependencies = [
"cfg-if",
"libc",
- "rand 0.7.2",
+ "rand 0.7.3",
"redox_syscall",
"remove_dir_all",
"winapi 0.3.8",
diff --git a/Cargo.toml b/Cargo.toml
index 6622793..34726ff 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,3 +33,4 @@ gstreamer-audio = "0.15.0"
byte-slice-cast = "0.3.5"
serde_json = "1.0.44"
serde = "1.0.104"
+rand = { version = "0.7.3", features = ["small_rng"] }
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)