From 0d43e8294ed6a0f051961e3f7e692cfeec0a50e3 Mon Sep 17 00:00:00 2001 From: trivernis Date: Fri, 9 Apr 2021 19:10:17 +0200 Subject: [PATCH] Change dj role to be optional Signed-off-by: trivernis --- database/src/database.rs | 15 ++++++++++++++- src/commands/music/clear_queue.rs | 8 ++++++-- src/commands/music/leave.rs | 8 ++++++-- src/commands/music/mod.rs | 21 +++++++++++++++++++++ src/commands/music/pause.rs | 8 ++++++-- src/commands/music/play_next.rs | 8 +++++--- src/commands/music/save_playlist.rs | 7 ++++++- src/commands/music/shuffle.rs | 7 +++++-- src/commands/music/skip.rs | 8 +++++--- src/commands/settings/get.rs | 14 ++++++++------ src/commands/settings/set.rs | 24 ++++++++++++++++-------- src/providers/settings.rs | 8 +++++++- 12 files changed, 105 insertions(+), 31 deletions(-) diff --git a/database/src/database.rs b/database/src/database.rs index 16e7a38..850ce63 100644 --- a/database/src/database.rs +++ b/database/src/database.rs @@ -2,8 +2,8 @@ use crate::error::DatabaseResult; use crate::models::*; use crate::schema::*; use crate::PoolConnection; -use diesel::insert_into; use diesel::prelude::*; +use diesel::{delete, insert_into}; use std::any; use std::fmt::Debug; use std::str::FromStr; @@ -79,6 +79,19 @@ impl Database { Ok(()) } + /// Deletes a guild setting + pub fn delete_guild_setting(&self, guild_id: u64, key: &str) -> DatabaseResult<()> { + use guild_settings::dsl; + log::debug!("Deleting '{}' for guild {}", key, guild_id); + let connection = self.pool.get()?; + delete(dsl::guild_settings) + .filter(dsl::guild_id.eq(guild_id as i64)) + .filter(dsl::key.eq(key)) + .execute(&connection)?; + + Ok(()) + } + /// Returns a list of all guild playlists pub fn get_guild_playlists(&self, guild_id: u64) -> DatabaseResult> { use guild_playlists::dsl; diff --git a/src/commands/music/clear_queue.rs b/src/commands/music/clear_queue.rs index b20c10f..3e240a7 100644 --- a/src/commands/music/clear_queue.rs +++ b/src/commands/music/clear_queue.rs @@ -4,16 +4,20 @@ use serenity::framework::standard::CommandResult; use serenity::model::channel::Message; use crate::commands::common::handle_autodelete; -use crate::commands::music::get_queue_for_guild; +use crate::commands::music::{get_queue_for_guild, is_dj}; #[command] #[only_in(guilds)] #[description("Clears the queue")] #[usage("")] #[aliases("cl")] -#[allowed_roles("DJ")] async fn clear_queue(ctx: &Context, msg: &Message) -> CommandResult { let guild = msg.guild(&ctx.cache).await.unwrap(); + + if !is_dj(ctx, guild.id, &msg.author).await? { + msg.channel_id.say(ctx, "Requires DJ permissions").await?; + return Ok(()); + } log::debug!("Clearing queue for guild {}", guild.id); let queue = get_queue_for_guild(ctx, &guild.id).await?; diff --git a/src/commands/music/leave.rs b/src/commands/music/leave.rs index 4471f49..08043d1 100644 --- a/src/commands/music/leave.rs +++ b/src/commands/music/leave.rs @@ -4,17 +4,21 @@ use serenity::framework::standard::CommandResult; use serenity::model::channel::Message; use crate::commands::common::handle_autodelete; -use crate::commands::music::{get_queue_for_guild, get_voice_manager}; +use crate::commands::music::{get_queue_for_guild, get_voice_manager, is_dj}; #[command] #[only_in(guilds)] #[description("Leaves a voice channel")] #[usage("")] #[aliases("stop")] -#[allowed_roles("DJ")] async fn leave(ctx: &Context, msg: &Message) -> CommandResult { let guild = msg.guild(&ctx.cache).await.unwrap(); log::debug!("Leave request received for guild {}", guild.id); + if !is_dj(ctx, guild.id, &msg.author).await? { + msg.channel_id.say(ctx, "Requires DJ permissions").await?; + return Ok(()); + } + let manager = get_voice_manager(ctx).await; let queue = get_queue_for_guild(ctx, &guild.id).await?; let queue_lock = queue.lock().await; diff --git a/src/commands/music/mod.rs b/src/commands/music/mod.rs index f26f94c..b730534 100644 --- a/src/commands/music/mod.rs +++ b/src/commands/music/mod.rs @@ -36,6 +36,7 @@ mod save_playlist; mod shuffle; mod skip; +use crate::providers::settings::{get_setting, Setting}; use clear_queue::CLEAR_QUEUE_COMMAND; use current::CURRENT_COMMAND; use join::JOIN_COMMAND; @@ -47,6 +48,7 @@ use play_next::PLAY_NEXT_COMMAND; use playlists::PLAYLISTS_COMMAND; use queue::QUEUE_COMMAND; use save_playlist::SAVE_PLAYLIST_COMMAND; +use serenity::model::user::User; use shuffle::SHUFFLE_COMMAND; use skip::SKIP_COMMAND; @@ -369,3 +371,22 @@ async fn added_multiple_msg(ctx: &Context, msg: &Message, songs: &mut Vec) .await?; Ok(()) } + +/// Returns if the given user is a dj in the given guild based on the +/// setting for the name of the dj role +async fn is_dj(ctx: &Context, guild: GuildId, user: &User) -> BotResult { + let dj_role = get_setting::(ctx, guild, Setting::MusicDjRole).await?; + + if let Some(role_name) = dj_role { + let roles = ctx.http.get_guild_roles(guild.0).await?; + let role_result = roles.iter().find(|r| r.name == role_name); + + if let Some(role) = role_result { + Ok(user.has_role(ctx, guild, role.id).await?) + } else { + Ok(false) + } + } else { + Ok(true) + } +} diff --git a/src/commands/music/pause.rs b/src/commands/music/pause.rs index 6704f28..97624a8 100644 --- a/src/commands/music/pause.rs +++ b/src/commands/music/pause.rs @@ -4,16 +4,20 @@ use serenity::model::channel::Message; use serenity::prelude::*; use crate::commands::common::handle_autodelete; -use crate::commands::music::get_queue_for_guild; +use crate::commands::music::{get_queue_for_guild, is_dj}; #[command] #[only_in(guilds)] #[description("Pauses playback")] #[usage("")] -#[allowed_roles("DJ")] async fn pause(ctx: &Context, msg: &Message) -> CommandResult { let guild = msg.guild(&ctx.cache).await.unwrap(); log::debug!("Pausing playback for guild {}", guild.id); + if !is_dj(ctx, guild.id, &msg.author).await? { + msg.channel_id.say(ctx, "Requires DJ permissions").await?; + return Ok(()); + } + let queue = get_queue_for_guild(ctx, &guild.id).await?; let mut queue_lock = queue.lock().await; diff --git a/src/commands/music/play_next.rs b/src/commands/music/play_next.rs index ce90f82..be6769a 100644 --- a/src/commands/music/play_next.rs +++ b/src/commands/music/play_next.rs @@ -5,7 +5,7 @@ use serenity::model::channel::Message; use crate::commands::common::handle_autodelete; use crate::commands::music::{ - get_channel_for_author, get_queue_for_guild, get_songs_for_query, get_voice_manager, + get_channel_for_author, get_queue_for_guild, get_songs_for_query, get_voice_manager, is_dj, join_channel, play_next_in_queue, }; @@ -15,13 +15,15 @@ use crate::commands::music::{ #[usage("")] #[min_args(1)] #[aliases("pn", "play-next")] -#[allowed_roles("DJ")] async fn play_next(ctx: &Context, msg: &Message, args: Args) -> CommandResult { let query = args.message(); let guild = msg.guild(&ctx.cache).await.unwrap(); log::debug!("Playing song as next song for guild {}", guild.id); - + if !is_dj(ctx, guild.id, &msg.author).await? { + msg.channel_id.say(ctx, "Requires DJ permissions").await?; + return Ok(()); + } let manager = get_voice_manager(ctx).await; let mut handler = manager.get(guild.id); diff --git a/src/commands/music/save_playlist.rs b/src/commands/music/save_playlist.rs index 5ffa6cb..9da0566 100644 --- a/src/commands/music/save_playlist.rs +++ b/src/commands/music/save_playlist.rs @@ -1,3 +1,4 @@ +use crate::commands::music::is_dj; use crate::utils::context_data::get_database_from_context; use serenity::client::Context; use serenity::framework::standard::macros::command; @@ -11,9 +12,13 @@ use serenity::model::channel::Message; #[example("anime https://www.youtube.com/playlist?list=PLqaM77H_o5hykROCe3uluvZEaPo6bZj-C")] #[min_args(2)] #[aliases("add-playlist", "save-playlist")] -#[allowed_roles("DJ")] async fn save_playlist(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { let guild = msg.guild(&ctx.cache).await.unwrap(); + + if !is_dj(ctx, guild.id, &msg.author).await? { + msg.channel_id.say(ctx, "Requires DJ permissions").await?; + return Ok(()); + } let name: String = args.single().unwrap(); let url: &str = args.remains().unwrap(); log::debug!( diff --git a/src/commands/music/shuffle.rs b/src/commands/music/shuffle.rs index 3475e4a..27c5267 100644 --- a/src/commands/music/shuffle.rs +++ b/src/commands/music/shuffle.rs @@ -4,18 +4,21 @@ use serenity::framework::standard::CommandResult; use serenity::model::channel::Message; use crate::commands::common::handle_autodelete; -use crate::commands::music::get_queue_for_guild; +use crate::commands::music::{get_queue_for_guild, is_dj}; #[command] #[only_in(guilds)] #[description("Shuffles the queue")] #[usage("")] #[aliases("sh")] -#[allowed_roles("DJ")] async fn shuffle(ctx: &Context, msg: &Message) -> CommandResult { let guild = msg.guild(&ctx.cache).await.unwrap(); log::debug!("Shuffling queue for guild {}", guild.id); + if !is_dj(ctx, guild.id, &msg.author).await? { + msg.channel_id.say(ctx, "Requires DJ permissions").await?; + return Ok(()); + } let queue = get_queue_for_guild(ctx, &guild.id).await?; { let mut queue_lock = queue.lock().await; diff --git a/src/commands/music/skip.rs b/src/commands/music/skip.rs index 44118a9..4e2dcd6 100644 --- a/src/commands/music/skip.rs +++ b/src/commands/music/skip.rs @@ -4,17 +4,19 @@ use serenity::framework::standard::CommandResult; use serenity::model::channel::Message; use crate::commands::common::handle_autodelete; -use crate::commands::music::get_queue_for_guild; +use crate::commands::music::{get_queue_for_guild, is_dj}; #[command] #[only_in(guilds)] #[description("Skips to the next song")] #[usage("")] #[aliases("next")] -#[allowed_roles("DJ")] async fn skip(ctx: &Context, msg: &Message) -> CommandResult { let guild = msg.guild(&ctx.cache).await.unwrap(); - + if !is_dj(ctx, guild.id, &msg.author).await? { + msg.channel_id.say(ctx, "Requires DJ permissions").await?; + return Ok(()); + } log::debug!("Skipping song for guild {}", guild.id); let queue = get_queue_for_guild(ctx, &guild.id).await?; let queue_lock = queue.lock().await; diff --git a/src/commands/settings/get.rs b/src/commands/settings/get.rs index f8b3c8d..1143751 100644 --- a/src/commands/settings/get.rs +++ b/src/commands/settings/get.rs @@ -37,21 +37,23 @@ async fn get(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { } } else { log::debug!("Displaying all guild settings"); + let mut kv_pairs = Vec::new(); + for key in ALL_SETTINGS { let key = key.to_string(); - let mut kv_pairs = Vec::new(); + { match database.get_guild_setting::(guild.id.0, &key)? { Some(value) => kv_pairs.push(format!("`{}` = `{}`", key, value)), None => kv_pairs.push(format!("`{}` not set", key)), } } - msg.channel_id - .send_message(ctx, |m| { - m.embed(|e| e.title("Guild Settings").description(kv_pairs.join("\n"))) - }) - .await?; } + msg.channel_id + .send_message(ctx, |m| { + m.embed(|e| e.title("Guild Settings").description(kv_pairs.join("\n"))) + }) + .await?; } Ok(()) diff --git a/src/commands/settings/set.rs b/src/commands/settings/set.rs index 1698cc7..f9fd2e8 100644 --- a/src/commands/settings/set.rs +++ b/src/commands/settings/set.rs @@ -8,10 +8,12 @@ use crate::utils::context_data::get_database_from_context; #[command] #[only_in(guilds)] -#[description("Set a guild setting")] -#[usage(" ")] +#[description( + "Set a guild setting. If no value is given the setting will be reset to the default value." +)] +#[usage(" ()")] #[example("music.autoshuffle true")] -#[min_args(2)] +#[min_args(1)] #[max_args(2)] #[required_permissions("MANAGE_GUILD")] async fn set(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { @@ -24,14 +26,20 @@ async fn set(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { .await?; return Ok(()); } - let value = args.single::().unwrap(); let database = get_database_from_context(ctx).await; let guild = msg.guild(&ctx.cache).await.unwrap(); - database.set_guild_setting(guild.id.0, &key, value.clone())?; - msg.channel_id - .say(ctx, format!("Set `{}` to `{}`", key, value)) - .await?; + if let Ok(value) = args.single::() { + database.set_guild_setting(guild.id.0, &key, value.clone())?; + msg.channel_id + .say(ctx, format!("Set `{}` to `{}`", key, value)) + .await?; + } else { + database.delete_guild_setting(guild.id.0, &key)?; + msg.channel_id + .say(ctx, format!("Setting `{}` reset to default", key)) + .await?; + } Ok(()) } diff --git a/src/providers/settings.rs b/src/providers/settings.rs index 3084aa4..77369b4 100644 --- a/src/providers/settings.rs +++ b/src/providers/settings.rs @@ -4,11 +4,16 @@ use serenity::client::Context; use serenity::model::prelude::GuildId; use std::str::FromStr; -pub static ALL_SETTINGS: &[Setting] = &[Setting::MusicAutoShuffle, Setting::BotAutoDelete]; +pub static ALL_SETTINGS: &[Setting] = &[ + Setting::MusicAutoShuffle, + Setting::BotAutoDelete, + Setting::MusicDjRole, +]; #[derive(Clone, Debug)] pub enum Setting { MusicAutoShuffle, + MusicDjRole, BotAutoDelete, } @@ -17,6 +22,7 @@ impl ToString for Setting { match self { Self::MusicAutoShuffle => "music.autoshuffle".to_string(), Self::BotAutoDelete => "bot.autodelete".to_string(), + Self::MusicDjRole => "music.dj-role".to_string(), } } }