autodisconnect. random and popular searches

This commit is contained in:
jude-lafitteIII 2020-05-18 23:44:51 +01:00
parent 62fe4a20a5
commit 8c6be25f02
2 changed files with 120 additions and 20 deletions

View File

@ -8,5 +8,5 @@ edition = "2018"
serenity = {path = "/home/jude/serenity", features = ["voice", "collector"]} serenity = {path = "/home/jude/serenity", features = ["voice", "collector"]}
sqlx = {version = "0.3", default-features = false, features = ["runtime-tokio", "macros", "mysql", "bigdecimal"]} sqlx = {version = "0.3", default-features = false, features = ["runtime-tokio", "macros", "mysql", "bigdecimal"]}
dotenv = "0.15" dotenv = "0.15"
tokio = {version = "0.2.19", features = ["fs", "sync", "process"]} tokio = {version = "0.2.19", features = ["fs", "sync", "process", "io-util"]}
lazy_static = "1.4.0" lazy_static = "1.4.0"

View File

@ -27,7 +27,10 @@ use serenity::{
Mutex as SerenityMutex, Mutex as SerenityMutex,
* *
}, },
voice::ffmpeg, voice::{
ffmpeg,
pcm
},
}; };
use sqlx::{ use sqlx::{
@ -42,10 +45,14 @@ use dotenv::dotenv;
use tokio::{ use tokio::{
fs::File, fs::File,
io::empty,
process::Command, process::Command,
sync::Mutex,
time,
}; };
use std::{ use std::{
collections::HashSet,
env, env,
path::Path, path::Path,
sync::Arc, sync::Arc,
@ -66,6 +73,12 @@ impl TypeMapKey for VoiceManager {
type Value = Arc<SerenityMutex<ClientVoiceManager>>; type Value = Arc<SerenityMutex<ClientVoiceManager>>;
} }
struct VoiceGuilds;
impl TypeMapKey for VoiceGuilds {
type Value = Arc<Mutex<HashSet<GuildId>>>;
}
static THEME_COLOR: u32 = 0x00e0f3; static THEME_COLOR: u32 = 0x00e0f3;
lazy_static! { lazy_static! {
@ -533,17 +546,26 @@ impl EventHandler for Handler {}
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenv()?; dotenv()?;
let voice_guilds = Arc::new(Mutex::new(HashSet::new()));
let framework = StandardFramework::new() let framework = StandardFramework::new()
.configure(|c| c.dynamic_prefix(|ctx, msg| Box::pin(async move { .configure(|c| c
.dynamic_prefix(|ctx, msg| Box::pin(async move {
let pool = ctx.data.read().await let pool = ctx.data.read().await
.get::<SQLPool>().cloned().expect("Could not get SQLPool from data"); .get::<SQLPool>().cloned().expect("Could not get SQLPool from data");
println!("dynamic_prefix: acquired pool and now about to query");
match GuildData::get_from_id(*msg.guild_id.unwrap().as_u64(), pool).await { match GuildData::get_from_id(*msg.guild_id.unwrap().as_u64(), pool).await {
Some(guild) => Some(guild.prefix), Some(guild) => Some(guild.prefix),
None => Some(String::from("?")) None => Some(String::from("?"))
} }
}))) }))
.allow_dm(false)
.ignore_bots(true)
.ignore_webhooks(true)
)
.group(&ALLUSERS_GROUP) .group(&ALLUSERS_GROUP)
.group(&ROLEMANAGEDUSERS_GROUP) .group(&ROLEMANAGEDUSERS_GROUP)
.group(&PERMISSIONMANAGEDUSERS_GROUP); .group(&PERMISSIONMANAGEDUSERS_GROUP);
@ -561,13 +583,49 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
data.insert::<SQLPool>(pool); data.insert::<SQLPool>(pool);
data.insert::<VoiceManager>(Arc::clone(&client.voice_manager)); data.insert::<VoiceManager>(Arc::clone(&client.voice_manager));
data.insert::<VoiceGuilds>(voice_guilds.clone());
} }
client.start().await?; let cvm = Arc::clone(&client.voice_manager);
// select on the client and client auto disconnector (when the client terminates, terminate the disconnector
tokio::select! {
_ = client.start() => {}
_ = disconnect_from_inactive(cvm, voice_guilds) => {}
};
Ok(()) Ok(())
} }
async fn disconnect_from_inactive(voice_manager_mutex: Arc<SerenityMutex<ClientVoiceManager>>, voice_guilds: Arc<Mutex<HashSet<GuildId>>>) {
loop {
let mut voice_guilds_acquired = voice_guilds.lock().await;
let mut voice_manager = voice_manager_mutex.lock().await;
let mut to_remove = HashSet::new();
for guild in voice_guilds_acquired.iter() {
let manager_opt = voice_manager.get_mut(guild);
if let Some(manager) = manager_opt {
let audio = manager.play_returning(pcm(false, empty()));
if !audio.lock().await.playing {
manager.leave();
to_remove.insert(guild.clone());
}
}
}
for val in to_remove.iter() {
voice_guilds_acquired.remove(val);
}
time::delay_for(Duration::from_secs(30)).await;
}
}
#[command("play")] #[command("play")]
#[aliases("p")] #[aliases("p")]
async fn play(ctx: &Context, msg: &Message, args: Args) -> CommandResult { async fn play(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
@ -610,23 +668,32 @@ async fn play(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
let mut voice_manager = voice_manager_lock.lock().await; let mut voice_manager = voice_manager_lock.lock().await;
let voice_guilds_lock = ctx.data.read().await
.get::<VoiceGuilds>().cloned().expect("Could not get VoiceGuilds from data");
let mut voice_guilds = voice_guilds_lock.lock().await;
match voice_manager.get_mut(guild_id) { match voice_manager.get_mut(guild_id) {
Some(handler) => { Some(handler) => {
// play sound // play sound
handler.play(ffmpeg(fp).await?); handler.play_only(ffmpeg(fp).await?);
sound.plays += 1; sound.plays += 1;
sound.commit(pool).await?; sound.commit(pool).await?;
voice_guilds.insert(guild_id);
} }
None => { None => {
// try & join a voice channel // try & join a voice channel
match voice_manager.join(guild_id, user_channel) { match voice_manager.join(guild_id, user_channel) {
Some(handler) => { Some(handler) => {
handler.play(ffmpeg(fp).await?); handler.play_only(ffmpeg(fp).await?);
sound.plays += 1; sound.plays += 1;
sound.commit(pool).await?; sound.commit(pool).await?;
voice_guilds.insert(guild_id);
} }
None => { None => {
@ -1059,6 +1126,46 @@ async fn search_sounds(ctx: &Context, msg: &Message, args: Args) -> CommandResul
Ok(()) Ok(())
} }
#[command("popular")]
async fn show_popular_sounds(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
let pool = ctx.data.read().await
.get::<SQLPool>().cloned().expect("Could not get SQLPool from data");
let search_results = sqlx::query_as_unchecked!(
Sound,
"
SELECT * FROM sounds
ORDER BY plays
"
)
.fetch_all(&pool)
.await?;
format_search_results(search_results, msg, ctx).await?;
Ok(())
}
#[command("random")]
async fn show_random_sounds(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
let pool = ctx.data.read().await
.get::<SQLPool>().cloned().expect("Could not get SQLPool from data");
let search_results = sqlx::query_as_unchecked!(
Sound,
"
SELECT * FROM sounds
ORDER BY rand()
"
)
.fetch_all(&pool)
.await?;
format_search_results(search_results, msg, ctx).await?;
Ok(())
}
#[command("greet")] #[command("greet")]
async fn set_greet_sound(ctx: &Context, msg: &Message, args: Args) -> CommandResult { async fn set_greet_sound(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
let pool = ctx.data.read().await let pool = ctx.data.read().await
@ -1102,10 +1209,3 @@ WHERE
Ok(()) Ok(())
} }
/*
#[command("popular")]
async fn show_popular_sounds(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
}
*/