Add autodelete setting and sticky np embed

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/2/head
trivernis 3 years ago
parent f36cf5a477
commit 69e7a2a18f
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -8,11 +8,13 @@ use songbird::SerenityInit;
use crate::commands::*;
use crate::handler::Handler;
use crate::utils::context_data::{DatabaseContainer, Store, StoreData};
use crate::utils::context_data::{
DatabaseContainer, EventDrivenMessageContainer, Store, StoreData,
};
use crate::utils::error::{BotError, BotResult};
use database::get_database;
use serenity::model::id::UserId;
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
pub async fn get_client() -> BotResult<Client> {
let token = dotenv::var("BOT_TOKEN").map_err(|_| BotError::MissingToken)?;
@ -27,6 +29,7 @@ pub async fn get_client() -> BotResult<Client> {
let mut data = client.data.write().await;
data.insert::<Store>(StoreData::new());
data.insert::<DatabaseContainer>(database);
data.insert::<EventDrivenMessageContainer>(HashMap::new());
}
Ok(client)

@ -0,0 +1,19 @@
use crate::providers::settings::{get_setting, Setting};
use crate::utils::error::BotResult;
use serenity::model::channel::Message;
use serenity::prelude::*;
/// Deletes a message automatically if configured that way
pub async fn handle_autodelete(ctx: &Context, msg: &Message) -> BotResult<()> {
if let Some(guild_id) = msg.guild_id {
let autodelete = get_setting(ctx, guild_id, Setting::BotAutoDelete)
.await?
.unwrap_or(true);
if autodelete {
let _ = msg.delete(ctx).await;
}
}
Ok(())
}

@ -2,6 +2,7 @@ use serenity::client::Context;
use serenity::framework::standard::{macros::command, Args, CommandError, CommandResult};
use serenity::model::channel::Message;
use crate::commands::common::handle_autodelete;
use crate::utils::context_data::Store;
#[command]
@ -64,6 +65,7 @@ pub(crate) async fn enchantment(ctx: &Context, msg: &Message, args: Args) -> Com
})
})
.await?;
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -2,6 +2,7 @@ use serenity::client::Context;
use serenity::framework::standard::{macros::command, Args, CommandError, CommandResult};
use serenity::model::channel::Message;
use crate::commands::common::handle_autodelete;
use crate::utils::context_data::Store;
#[command]
@ -60,6 +61,7 @@ pub(crate) async fn item(ctx: &Context, msg: &Message, args: Args) -> CommandRes
})
})
.await?;
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -1,5 +1,6 @@
use std::collections::HashSet;
use crate::commands::common::handle_autodelete;
use serenity::client::Context;
use serenity::framework::standard::macros::help;
use serenity::framework::standard::{help_commands, Args};
@ -18,6 +19,6 @@ pub async fn help(
owners: HashSet<UserId>,
) -> CommandResult {
let _ = help_commands::with_embeds(ctx, msg, args, help_options, groups, owners).await;
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -1,3 +1,4 @@
use crate::commands::common::handle_autodelete;
use serenity::framework::standard::macros::command;
use serenity::framework::standard::CommandResult;
use serenity::model::channel::Message;
@ -13,5 +14,6 @@ async fn shutdown(ctx: &Context, msg: &Message) -> CommandResult {
msg.channel_id
.say(ctx, ":night_with_stars: Good night ....")
.await?;
handle_autodelete(ctx, msg).await?;
process::exit(0);
}

@ -1,3 +1,4 @@
use crate::commands::common::handle_autodelete;
use chrono::Duration as ChronoDuration;
use serenity::framework::standard::macros::command;
use serenity::framework::standard::CommandResult;
@ -64,6 +65,7 @@ async fn stats(ctx: &Context, msg: &Message) -> CommandResult {
})
})
.await?;
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -8,3 +8,4 @@ pub(crate) mod minecraft;
pub(crate) mod misc;
pub(crate) mod music;
pub(crate) mod settings;
mod common;

@ -3,6 +3,7 @@ use serenity::framework::standard::macros::command;
use serenity::framework::standard::CommandResult;
use serenity::model::channel::Message;
use crate::commands::common::handle_autodelete;
use crate::commands::music::get_queue_for_guild;
#[command]
@ -24,6 +25,7 @@ async fn clear_queue(ctx: &Context, msg: &Message) -> CommandResult {
msg.channel_id
.say(ctx, "The queue has been cleared")
.await?;
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -3,6 +3,7 @@ use serenity::framework::standard::macros::command;
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::messages::music::NowPlayingMessage;
use std::mem;
@ -29,6 +30,7 @@ async fn current(ctx: &Context, msg: &Message) -> CommandResult {
let _ = old_np.inner().delete().await;
}
}
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -3,6 +3,7 @@ use serenity::framework::standard::macros::command;
use serenity::framework::standard::CommandResult;
use serenity::model::channel::Message;
use crate::commands::common::handle_autodelete;
use crate::commands::music::{get_channel_for_author, join_channel};
#[command]
@ -14,6 +15,7 @@ async fn join(ctx: &Context, msg: &Message) -> CommandResult {
let channel_id = get_channel_for_author(&msg.author.id, &guild)?;
log::debug!("Joining channel {} for guild {}", channel_id, guild.id);
join_channel(ctx, channel_id, guild.id).await;
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -3,6 +3,7 @@ use serenity::framework::standard::macros::command;
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};
#[command]
@ -35,6 +36,7 @@ async fn leave(ctx: &Context, msg: &Message) -> CommandResult {
msg.channel_id.say(ctx, "Not in a voice channel").await?;
log::debug!("Not in a voice channel");
}
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -3,6 +3,7 @@ use serenity::framework::standard::macros::command;
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::providers::music::lyrics::get_lyrics;
@ -44,6 +45,7 @@ async fn lyrics(ctx: &Context, msg: &Message) -> CommandResult {
.say(ctx, "I'm not playing music right now")
.await?;
}
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -249,7 +249,7 @@ async fn play_next_in_queue(
let track = handler_lock.play_only_source(source);
log::trace!("Track is {:?}", track);
if let Some(np) = &queue_lock.now_playing_msg {
if let Some(np) = &mut queue_lock.now_playing_msg {
let _ = np.refresh(track.metadata()).await;
}
queue_lock.set_current(track);

@ -3,6 +3,7 @@ use serenity::framework::standard::CommandResult;
use serenity::model::channel::Message;
use serenity::prelude::*;
use crate::commands::common::handle_autodelete;
use crate::commands::music::get_queue_for_guild;
#[command]
@ -28,6 +29,7 @@ async fn pause(ctx: &Context, msg: &Message) -> CommandResult {
} else {
msg.channel_id.say(ctx, "Nothing to pause").await?;
}
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -8,8 +8,8 @@ use crate::commands::music::{
join_channel, play_next_in_queue,
};
use crate::commands::settings::SETTING_AUTOSHUFFLE;
use crate::utils::context_data::get_database_from_context;
use crate::commands::common::handle_autodelete;
use crate::providers::settings::{get_setting, Setting};
#[command]
#[only_in(guilds)]
@ -45,10 +45,10 @@ async fn play(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
for song in songs {
queue_lock.add(song);
}
let database = get_database_from_context(ctx).await;
let autoshuffle = database
.get_guild_setting(guild.id.0, SETTING_AUTOSHUFFLE)?
let autoshuffle = get_setting(ctx, guild.id, Setting::MusicAutoShuffle)
.await?
.unwrap_or(false);
if autoshuffle {
log::debug!("Autoshuffeling");
queue_lock.shuffle();
@ -60,6 +60,7 @@ async fn play(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
log::debug!("Playing first song in queue");
while !play_next_in_queue(&ctx.http, &msg.channel_id, &queue, &handler_lock).await {}
}
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -3,6 +3,7 @@ use serenity::framework::standard::macros::command;
use serenity::framework::standard::{Args, CommandError, CommandResult};
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,
join_channel, play_next_in_queue,
@ -50,6 +51,7 @@ async fn play_next(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
if play_first {
while !play_next_in_queue(&ctx.http, &msg.channel_id, &queue, &handler).await {}
}
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -1,3 +1,4 @@
use crate::commands::common::handle_autodelete;
use crate::utils::context_data::get_database_from_context;
use serenity::client::Context;
use serenity::framework::standard::macros::command;
@ -27,6 +28,7 @@ async fn playlists(ctx: &Context, msg: &Message) -> CommandResult {
})
})
.await?;
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -5,6 +5,7 @@ use serenity::framework::standard::macros::command;
use serenity::framework::standard::CommandResult;
use serenity::model::channel::Message;
use crate::commands::common::handle_autodelete;
use crate::commands::music::get_queue_for_guild;
#[command]
@ -55,6 +56,7 @@ async fn queue(ctx: &Context, msg: &Message) -> CommandResult {
})
})
.await?;
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -3,6 +3,7 @@ use serenity::framework::standard::macros::command;
use serenity::framework::standard::CommandResult;
use serenity::model::channel::Message;
use crate::commands::common::handle_autodelete;
use crate::commands::music::get_queue_for_guild;
#[command]
@ -24,6 +25,7 @@ async fn shuffle(ctx: &Context, msg: &Message) -> CommandResult {
msg.channel_id
.say(ctx, "The queue has been shuffled")
.await?;
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -3,6 +3,7 @@ use serenity::framework::standard::macros::command;
use serenity::framework::standard::CommandResult;
use serenity::model::channel::Message;
use crate::commands::common::handle_autodelete;
use crate::commands::music::get_queue_for_guild;
#[command]
@ -23,6 +24,7 @@ async fn skip(ctx: &Context, msg: &Message) -> CommandResult {
}
msg.channel_id.say(ctx, "Skipped to the next song").await?;
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -3,7 +3,7 @@ use serenity::framework::standard::macros::command;
use serenity::framework::standard::{Args, CommandResult};
use serenity::model::channel::Message;
use crate::commands::settings::GUILD_SETTINGS;
use crate::providers::settings::ALL_SETTINGS;
use crate::utils::context_data::get_database_from_context;
#[command]
@ -37,7 +37,8 @@ async fn get(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
}
} else {
log::debug!("Displaying all guild settings");
for key in GUILD_SETTINGS {
for key in ALL_SETTINGS {
let key = key.to_string();
let mut kv_pairs = Vec::new();
{
match database.get_guild_setting::<String>(guild.id.0, &key)? {

@ -10,6 +10,3 @@ mod set;
#[commands(set, get)]
#[prefix("settings")]
pub struct Settings;
pub const SETTING_AUTOSHUFFLE: &str = "music.autoshuffle";
pub const GUILD_SETTINGS: &[&str] = &[SETTING_AUTOSHUFFLE];

@ -3,7 +3,7 @@ use serenity::framework::standard::macros::command;
use serenity::framework::standard::{Args, CommandResult};
use serenity::model::channel::Message;
use crate::commands::settings::GUILD_SETTINGS;
use crate::providers::settings::ALL_SETTINGS;
use crate::utils::context_data::get_database_from_context;
#[command]
@ -16,7 +16,9 @@ use crate::utils::context_data::get_database_from_context;
#[required_permissions("MANAGE_GUILD")]
async fn set(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
let key = args.single::<String>().unwrap().to_lowercase();
if !GUILD_SETTINGS.contains(&&*key) {
let all_settings: Vec<String> = ALL_SETTINGS.iter().map(|s| s.to_string()).collect();
if !all_settings.contains(&key) {
msg.channel_id
.say(ctx, format!("Invalid setting `{}`", key))
.await?;

@ -32,11 +32,34 @@ impl NowPlayingMessage {
}
/// Refreshes the now playing message
pub async fn refresh(&self, meta: &Metadata) -> BotResult<()> {
self.inner
.edit(|m| m.embed(|e| Self::create_embed(meta, e)))
pub async fn refresh(&mut self, meta: &Metadata) -> BotResult<()> {
let channel_id = self.inner.channel_id();
let messages = channel_id
.messages(self.inner.http(), |p| p.limit(1))
.await?;
let needs_recreate = messages
.first()
.map(|m| m.id != self.inner.message_id())
.unwrap_or(true);
// recreates the message if needed
if needs_recreate {
log::debug!("Song info message will be recreated");
let http = self.inner.http().clone();
let _ = self.inner.delete().await;
self.inner = ShareableMessage::create(http, &channel_id, |f| {
f.embed(|e| Self::create_embed(meta, e))
})
.await?;
} else {
log::debug!("Reusing old song info");
self.inner
.edit(|m| m.embed(|e| Self::create_embed(meta, e)))
.await?;
}
Ok(())
}

@ -1 +1,2 @@
pub(crate) mod music;
pub(crate) mod settings;

@ -0,0 +1,35 @@
use crate::utils::context_data::DatabaseContainer;
use crate::utils::error::{BotError, BotResult};
use serenity::client::Context;
use serenity::model::prelude::GuildId;
use std::str::FromStr;
pub static ALL_SETTINGS: &[Setting] = &[Setting::MusicAutoShuffle, Setting::BotAutoDelete];
#[derive(Clone, Debug)]
pub enum Setting {
MusicAutoShuffle,
BotAutoDelete,
}
impl ToString for Setting {
fn to_string(&self) -> String {
match self {
Self::MusicAutoShuffle => "music.autoshuffle".to_string(),
Self::BotAutoDelete => "bot.autodelete".to_string(),
}
}
}
/// Returns a specific guild setting
pub async fn get_setting<T: 'static + FromStr>(
ctx: &Context,
guild_id: GuildId,
setting: Setting,
) -> BotResult<Option<T>> {
let data = ctx.data.read().await;
let database = data.get::<DatabaseContainer>().unwrap();
database
.get_guild_setting::<T>(guild_id.0, &setting.to_string())
.map_err(BotError::from)
}

@ -42,7 +42,7 @@ impl ShareableMessage {
/// Deletes the underlying message
pub async fn delete(&self) -> BotResult<()> {
let msg = self.get_message().await?;
let msg = self.get_discord_message().await?;
msg.delete(&self.http).await?;
Ok(())
@ -53,20 +53,34 @@ impl ShareableMessage {
where
F: FnOnce(&mut EditMessage) -> &mut EditMessage,
{
let mut message = self.get_message().await?;
let mut message = self.get_discord_message().await?;
message.edit(&self.http, f).await?;
Ok(())
}
/// Returns the underlying message
async fn get_message(&self) -> BotResult<Message> {
pub async fn get_discord_message(&self) -> BotResult<Message> {
let message = self
.http
.http()
.get_message(self.channel_id, self.message_id)
.await?;
Ok(message)
}
/// Returns the channel of the message
pub fn channel_id(&self) -> ChannelId {
ChannelId(self.channel_id)
}
/// Returns the message id of the message
pub fn message_id(&self) -> MessageId {
MessageId(self.message_id)
}
/// Returns the reference to the http object
pub fn http(&self) -> &Arc<Http> {
&self.http
}
}

Loading…
Cancel
Save