Add ephemeral message and use it for most music command answers

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/12/head
trivernis 3 years ago
parent eede854ad4
commit bbf9f1ef93
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

2
Cargo.lock generated

@ -205,7 +205,7 @@ dependencies = [
[[package]]
name = "bot-serenityutils"
version = "0.2.0"
version = "0.2.1"
dependencies = [
"futures",
"log 0.4.14",

@ -68,7 +68,7 @@ dependencies = [
[[package]]
name = "bot-serenityutils"
version = "0.2.0"
version = "0.2.1"
dependencies = [
"futures",
"log",

@ -1,6 +1,6 @@
[package]
name = "bot-serenityutils"
version = "0.2.0"
version = "0.2.1"
authors = ["trivernis <trivernis@protonmail.com>"]
edition = "2018"

@ -4,6 +4,12 @@ use serenity::http::Http;
use serenity::model::channel::Message;
use serenity::model::id::{ChannelId, MessageId};
use std::sync::Arc;
use std::time::Duration;
pub static SHORT_TIMEOUT: Duration = Duration::from_secs(5);
pub static MEDIUM_TIMEOUT: Duration = Duration::from_secs(20);
pub static LONG_TIMEOUT: Duration = Duration::from_secs(60);
pub static EXTRA_LONG_TIMEOUT: Duration = Duration::from_secs(600);
pub type BoxedEventDrivenMessage = Box<dyn EventDrivenMessage>;

@ -0,0 +1,56 @@
use crate::core::MessageHandle;
use crate::error::SerenityUtilsResult;
use serenity::builder::CreateMessage;
use serenity::http::Http;
use serenity::model::channel::Message;
use serenity::model::id::ChannelId;
use std::sync::Arc;
use std::time::Duration;
pub struct EphemeralMessage;
impl EphemeralMessage {
/// Ensures that an already existing message is
/// deleted after a certain amount of time
pub async fn create_from_message(
http: &Arc<Http>,
message: &Message,
timeout: Duration,
) -> SerenityUtilsResult<()> {
log::debug!("Creating ephemeral message from existing message");
let handle = MessageHandle::new(message.channel_id, message.id);
let http = Arc::clone(&http);
log::debug!("Starting delete task");
tokio::spawn(async move {
log::debug!("Waiting for timeout to pass");
tokio::time::sleep(timeout).await;
log::debug!("Deleting ephemeral message");
if let Err(e) = http
.delete_message(handle.channel_id, handle.message_id)
.await
{
log::error!("Failed to delete ephemeral message {:?}: {}", handle, e);
}
});
Ok(())
}
/// Creates a new message that is deleted after a certain amount of time
pub async fn create<'a, F>(
http: &Arc<Http>,
channel_id: ChannelId,
timeout: Duration,
f: F,
) -> SerenityUtilsResult<Message>
where
F: for<'b> FnOnce(&'b mut CreateMessage<'a>) -> &'b mut CreateMessage<'a>,
{
log::debug!("Creating new ephemeral message");
let msg = channel_id.send_message(http, f).await?;
Self::create_from_message(http, &msg, timeout).await?;
Ok(msg)
}
}

@ -1,3 +1,4 @@
pub mod core;
pub mod error;
pub mod menu;
pub mod ephemeral_message;

@ -17,6 +17,8 @@ impl TypeMapKey for EventDrivenMessageContainer {
type Value = EventDrivenMessagesRef;
}
static UPDATE_INTERVAL_SECS: u64 = 5;
/// Starts the loop to handle message updates
pub async fn start_update_loop(ctx: &Context) {
let event_messages = get_listeners_from_context(ctx)
@ -56,7 +58,7 @@ pub async fn start_update_loop(ctx: &Context) {
}
}
log::trace!("Listener unlocked");
tokio::time::sleep(Duration::from_secs(10)).await;
tokio::time::sleep(Duration::from_secs(UPDATE_INTERVAL_SECS)).await;
}
});
}

@ -189,10 +189,6 @@ impl<'a> EventDrivenMessage for Menu<'a> {
Ok(())
}
async fn on_deleted(&mut self, _: &Context) -> SerenityUtilsResult<()> {
Ok(())
}
async fn on_reaction_add(
&mut self,
ctx: &Context,
@ -216,10 +212,6 @@ impl<'a> EventDrivenMessage for Menu<'a> {
Ok(())
}
async fn on_reaction_remove(&mut self, _: &Context, _: Reaction) -> SerenityUtilsResult<()> {
Ok(())
}
}
/// A builder for messages

@ -6,25 +6,35 @@ use serenity::{async_trait, model::prelude::*};
#[async_trait]
pub trait EventDrivenMessage: Send + Sync {
/// Returns if a message has been frozen and won't handle any further events
fn is_frozen(&self) -> bool;
fn is_frozen(&self) -> bool {
false
}
/// Fired periodically
async fn update(&mut self, http: &Http) -> SerenityUtilsResult<()>;
async fn update(&mut self, _http: &Http) -> SerenityUtilsResult<()> {
Ok(())
}
/// Fired when the message was deleted
async fn on_deleted(&mut self, ctx: &Context) -> SerenityUtilsResult<()>;
async fn on_deleted(&mut self, _ctx: &Context) -> SerenityUtilsResult<()> {
Ok(())
}
/// Fired when a reaction was added to the message
async fn on_reaction_add(
&mut self,
ctx: &Context,
reaction: Reaction,
) -> SerenityUtilsResult<()>;
_ctx: &Context,
_reaction: Reaction,
) -> SerenityUtilsResult<()> {
Ok(())
}
/// Fired when a reaction was removed from the message
async fn on_reaction_remove(
&mut self,
ctx: &Context,
reaction: Reaction,
) -> SerenityUtilsResult<()>;
_ctx: &Context,
_reaction: Reaction,
) -> SerenityUtilsResult<()> {
Ok(())
}
}

@ -1,5 +1,7 @@
use crate::utils::context_data::get_database_from_context;
use bot_coreutils::url;
use bot_serenityutils::core::SHORT_TIMEOUT;
use bot_serenityutils::ephemeral_message::EphemeralMessage;
use serenity::client::Context;
use serenity::framework::standard::macros::command;
use serenity::framework::standard::{Args, CommandResult};
@ -25,7 +27,11 @@ async fn add_gif(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult
let database = get_database_from_context(&ctx).await;
database.add_gif(&url, category, name).await?;
msg.reply(ctx, "Gif added to database").await?;
EphemeralMessage::create(&ctx.http, msg.channel_id, SHORT_TIMEOUT, |c| {
c.reference_message(msg)
.content("Gif added to the database.")
})
.await?;
Ok(())
}

@ -5,6 +5,8 @@ use serenity::model::channel::Message;
use crate::commands::common::handle_autodelete;
use crate::commands::music::{get_queue_for_guild, is_dj};
use bot_serenityutils::core::SHORT_TIMEOUT;
use bot_serenityutils::ephemeral_message::EphemeralMessage;
#[command]
#[only_in(guilds)]
@ -27,9 +29,10 @@ async fn clear_queue(ctx: &Context, msg: &Message) -> CommandResult {
queue_lock.clear();
}
msg.channel_id
.say(ctx, "The queue has been cleared")
.await?;
EphemeralMessage::create(&ctx.http, msg.channel_id, SHORT_TIMEOUT, |m| {
m.content("🧹 The queue has been cleared")
})
.await?;
handle_autodelete(ctx, msg).await?;
Ok(())

@ -5,6 +5,8 @@ use serenity::model::channel::Message;
use crate::commands::common::handle_autodelete;
use crate::commands::music::{get_channel_for_author, is_dj, join_channel};
use bot_serenityutils::core::SHORT_TIMEOUT;
use bot_serenityutils::ephemeral_message::EphemeralMessage;
use serenity::model::id::ChannelId;
#[command]
@ -25,6 +27,10 @@ async fn join(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
};
log::debug!("Joining channel {} for guild {}", channel_id, guild.id);
join_channel(ctx, channel_id, guild.id).await;
EphemeralMessage::create(&ctx.http, msg.channel_id, SHORT_TIMEOUT, |m| {
m.content("🎤 Joined the Voice Channel")
})
.await?;
handle_autodelete(ctx, msg).await?;
Ok(())

@ -5,6 +5,8 @@ use serenity::model::channel::Message;
use crate::commands::common::handle_autodelete;
use crate::commands::music::{get_queue_for_guild, get_voice_manager, is_dj};
use bot_serenityutils::core::SHORT_TIMEOUT;
use bot_serenityutils::ephemeral_message::EphemeralMessage;
#[command]
#[only_in(guilds)]
@ -35,10 +37,16 @@ async fn leave(ctx: &Context, msg: &Message) -> CommandResult {
if manager.get(guild.id).is_some() {
manager.remove(guild.id).await?;
msg.channel_id.say(ctx, "Left the voice channel").await?;
EphemeralMessage::create(&ctx.http, msg.channel_id, SHORT_TIMEOUT, |m| {
m.content("👋 Left the Voice Channel")
})
.await?;
log::debug!("Left the voice channel");
} else {
msg.channel_id.say(ctx, "Not in a voice channel").await?;
EphemeralMessage::create(&ctx.http, msg.channel_id, SHORT_TIMEOUT, |m| {
m.content("‼️ I'm not in a Voice Channel")
})
.await?;
log::debug!("Not in a voice channel");
}
handle_autodelete(ctx, msg).await?;

@ -1,4 +1,7 @@
use crate::commands::common::handle_autodelete;
use crate::commands::music::{get_queue_for_guild, is_dj};
use bot_serenityutils::core::SHORT_TIMEOUT;
use bot_serenityutils::ephemeral_message::EphemeralMessage;
use serenity::client::Context;
use serenity::framework::standard::macros::command;
use serenity::framework::standard::{Args, CommandResult};
@ -29,12 +32,14 @@ async fn move_song(ctx: &Context, msg: &Message, mut args: Args) -> CommandResul
let mut queue_lock = queue.lock().await;
queue_lock.move_position(pos1, pos2);
}
msg.channel_id
.say(
ctx,
format!("Moved Song `{}` to new position `{}`", pos1, pos2),
)
.await?;
EphemeralMessage::create(&ctx.http, msg.channel_id, SHORT_TIMEOUT, |m| {
m.content(format!(
"↕ Moved Song `{}` to new position `{}`",
pos1, pos2
))
})
.await?;
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -6,6 +6,8 @@ use serenity::prelude::*;
use crate::commands::common::handle_autodelete;
use crate::commands::music::{get_queue_for_guild, is_dj};
use crate::messages::music::now_playing::update_now_playing_msg;
use bot_serenityutils::core::SHORT_TIMEOUT;
use bot_serenityutils::ephemeral_message::EphemeralMessage;
#[command]
#[only_in(guilds)]
@ -27,14 +29,20 @@ async fn pause(ctx: &Context, msg: &Message) -> CommandResult {
queue_lock.pause();
if queue_lock.paused() {
log::debug!("Paused");
msg.channel_id.say(ctx, "Paused playback").await?;
EphemeralMessage::create(&ctx.http, msg.channel_id, SHORT_TIMEOUT, |m| {
m.content("⏸️ Paused playback")
})
.await?;
if let (Some(menu), Some(current)) = (&queue_lock.now_playing_msg, queue_lock.current())
{
update_now_playing_msg(&ctx.http, menu, current.metadata(), true).await?;
}
} else {
log::debug!("Resumed");
msg.channel_id.say(ctx, "Resumed playback").await?;
EphemeralMessage::create(&ctx.http, msg.channel_id, SHORT_TIMEOUT, |m| {
m.content("▶ Resumed playback")
})
.await?;
if let (Some(menu), Some(current)) = (&queue_lock.now_playing_msg, queue_lock.current())
{
update_now_playing_msg(&ctx.http, menu, current.metadata(), true).await?;

@ -1,4 +1,7 @@
use crate::commands::common::handle_autodelete;
use crate::commands::music::{get_queue_for_guild, is_dj};
use bot_serenityutils::core::SHORT_TIMEOUT;
use bot_serenityutils::ephemeral_message::EphemeralMessage;
use serenity::client::Context;
use serenity::framework::standard::macros::command;
use serenity::framework::standard::{Args, CommandResult};
@ -29,9 +32,11 @@ async fn remove_song(ctx: &Context, msg: &Message, mut args: Args) -> CommandRes
queue_lock.remove(pos);
}
msg.channel_id
.say(ctx, format!("Removed Song at `{}`", pos))
.await?;
EphemeralMessage::create(&ctx.http, msg.channel_id, SHORT_TIMEOUT, |m| {
m.content(format!("🗑️ Removed Song at `{}`", pos))
})
.await?;
handle_autodelete(ctx, msg).await?;
Ok(())
}

@ -5,6 +5,8 @@ use serenity::model::channel::Message;
use crate::commands::common::handle_autodelete;
use crate::commands::music::{get_queue_for_guild, is_dj};
use bot_serenityutils::core::SHORT_TIMEOUT;
use bot_serenityutils::ephemeral_message::EphemeralMessage;
#[command]
#[only_in(guilds)]
@ -26,9 +28,10 @@ async fn shuffle(ctx: &Context, msg: &Message) -> CommandResult {
queue_lock.shuffle();
}
msg.channel_id
.say(ctx, "The queue has been shuffled")
.await?;
EphemeralMessage::create(&ctx.http, msg.channel_id, SHORT_TIMEOUT, |m| {
m.content("🔀 The queue has been shuffled")
})
.await?;
handle_autodelete(ctx, msg).await?;
Ok(())

@ -5,6 +5,8 @@ use serenity::model::channel::Message;
use crate::commands::common::handle_autodelete;
use crate::commands::music::{get_queue_for_guild, is_dj};
use bot_serenityutils::core::SHORT_TIMEOUT;
use bot_serenityutils::ephemeral_message::EphemeralMessage;
#[command]
#[only_in(guilds)]
@ -26,7 +28,10 @@ async fn skip(ctx: &Context, msg: &Message) -> CommandResult {
current.stop()?;
}
msg.channel_id.say(ctx, "Skipped to the next song").await?;
EphemeralMessage::create(&ctx.http, msg.channel_id, SHORT_TIMEOUT, |m| {
m.content("⏭ Skipped to the next song")
})
.await?;
handle_autodelete(ctx, msg).await?;
Ok(())

Loading…
Cancel
Save