From bf29b51092b706e3b9d3fd033235b6d0d241e7e3 Mon Sep 17 00:00:00 2001 From: trivernis Date: Sun, 11 Apr 2021 21:56:29 +0200 Subject: [PATCH] Change music NowPlaying embed to be created as a menu Signed-off-by: trivernis --- bot-serenityutils/src/core.rs | 10 +++ src/commands/music/current.rs | 9 +-- src/commands/music/mod.rs | 11 +++- src/messages/music.rs | 111 ++++++++++++++-------------------- src/providers/music/queue.rs | 4 +- src/utils/messages.rs | 80 ------------------------ src/utils/mod.rs | 1 - 7 files changed, 70 insertions(+), 156 deletions(-) delete mode 100644 src/utils/messages.rs diff --git a/bot-serenityutils/src/core.rs b/bot-serenityutils/src/core.rs index f940007..7833b2c 100644 --- a/bot-serenityutils/src/core.rs +++ b/bot-serenityutils/src/core.rs @@ -1,5 +1,9 @@ +use crate::error::SerenityUtilsResult; use crate::menu::traits::EventDrivenMessage; +use serenity::http::Http; +use serenity::model::channel::Message; use serenity::model::id::{ChannelId, MessageId}; +use std::sync::Arc; pub type BoxedEventDrivenMessage = Box; @@ -25,4 +29,10 @@ impl MessageHandle { channel_id, } } + + /// Returns the message object of the handle + pub async fn get_message(&self, http: &Arc) -> SerenityUtilsResult { + let msg = http.get_message(self.channel_id, self.message_id).await?; + Ok(msg) + } } diff --git a/src/commands/music/current.rs b/src/commands/music/current.rs index 57ae17d..7e132f1 100644 --- a/src/commands/music/current.rs +++ b/src/commands/music/current.rs @@ -7,7 +7,7 @@ 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 crate::messages::music::create_now_playing_msg; #[command] #[only_in(guilds)] @@ -25,11 +25,12 @@ async fn current(ctx: &Context, msg: &Message) -> CommandResult { if let Some(current) = queue_lock.current() { let metadata = current.metadata().clone(); log::trace!("Metadata is {:?}", metadata); - let np_msg = - NowPlayingMessage::create(ctx.http.clone(), &msg.channel_id, &metadata).await?; + let np_msg = create_now_playing_msg(ctx, msg.channel_id, &metadata).await?; if let Some(old_np) = mem::replace(&mut queue_lock.now_playing_msg, Some(np_msg)) { - let _ = old_np.inner().delete().await; + if let Ok(message) = old_np.get_message(&ctx.http).await { + let _ = message.delete(ctx).await; + } } } handle_autodelete(ctx, msg).await?; diff --git a/src/commands/music/mod.rs b/src/commands/music/mod.rs index da2ebe7..c91c7ba 100644 --- a/src/commands/music/mod.rs +++ b/src/commands/music/mod.rs @@ -31,6 +31,7 @@ use save_playlist::SAVE_PLAYLIST_COMMAND; use shuffle::SHUFFLE_COMMAND; use skip::SKIP_COMMAND; +use crate::messages::music::update_now_playing_msg; use crate::providers::music::queue::{MusicQueue, Song}; use crate::providers::music::youtube_dl; use crate::providers::settings::{get_setting, Setting}; @@ -250,13 +251,17 @@ async fn play_next_in_queue( let track = handler_lock.play_only_source(source); log::trace!("Track is {:?}", track); - if let Some(np) = &mut queue_lock.now_playing_msg { - let _ = np.refresh(track.metadata()).await; + if let Some(np) = queue_lock.now_playing_msg { + if let Err(e) = update_now_playing_msg(http, np, track.metadata()).await { + log::error!("Failed to update now playing message: {:?}", e); + } } queue_lock.set_current(track); } else { if let Some(np) = mem::take(&mut queue_lock.now_playing_msg) { - let _ = np.inner().delete().await; + if let Ok(message) = np.get_message(http).await { + let _ = message.delete(http).await; + } } queue_lock.clear_current(); } diff --git a/src/messages/music.rs b/src/messages/music.rs index 1edcdfe..2dab442 100644 --- a/src/messages/music.rs +++ b/src/messages/music.rs @@ -6,78 +6,57 @@ use serenity::model::prelude::ChannelId; use songbird::input::Metadata; use crate::utils::error::BotResult; -use crate::utils::messages::ShareableMessage; +use bot_serenityutils::core::MessageHandle; +use bot_serenityutils::menu::MenuBuilder; +use serenity::builder::CreateMessage; +use serenity::client::Context; + +/// Creates a new now playing message and returns the embed for that message +pub async fn create_now_playing_msg( + ctx: &Context, + channel_id: ChannelId, + meta: &Metadata, +) -> BotResult { + let mut page = CreateMessage::default(); + page.embed(|e| create_now_playing_embed(meta, e)); + + let handle = MenuBuilder::default() + .add_page(page) + .build(ctx, channel_id) + .await?; -#[derive(Clone)] -pub struct NowPlayingMessage { - inner: ShareableMessage, + Ok(handle) } -impl NowPlayingMessage { - /// Creates a new now playing message - pub async fn create( - ctx: Arc, - channel_id: &ChannelId, - meta: &Metadata, - ) -> BotResult { - let inner = ShareableMessage::create(ctx, channel_id, |f| { - f.embed(|e| Self::create_embed(meta, e)) - }) +/// Updates the now playing message with new content +pub async fn update_now_playing_msg( + http: &Arc, + handle: MessageHandle, + meta: &Metadata, +) -> BotResult<()> { + let mut message = handle.get_message(http).await?; + message + .edit(http, |m| m.embed(|e| create_now_playing_embed(meta, e))) .await?; - Ok(Self { inner }) - } - - /// Returns the inner shareable message - pub fn inner(&self) -> &ShareableMessage { - &self.inner - } - - /// Refreshes the now playing message - 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(()) +} - Ok(()) +/// Creates the embed of the now playing message +fn create_now_playing_embed<'a>( + meta: &Metadata, + mut embed: &'a mut CreateEmbed, +) -> &'a mut CreateEmbed { + embed = embed.description(format!( + "Now Playing [{}]({}) by {}", + meta.title.clone().unwrap(), + meta.source_url.clone().unwrap(), + meta.artist.clone().unwrap() + )); + + if let Some(thumb) = meta.thumbnail.clone() { + embed = embed.thumbnail(thumb); } - /// Creates the embed of the now playing message - fn create_embed<'a>(meta: &Metadata, mut embed: &'a mut CreateEmbed) -> &'a mut CreateEmbed { - embed = embed.description(format!( - "Now Playing [{}]({}) by {}", - meta.title.clone().unwrap(), - meta.source_url.clone().unwrap(), - meta.artist.clone().unwrap() - )); - - if let Some(thumb) = meta.thumbnail.clone() { - embed = embed.thumbnail(thumb); - } - - embed - } + embed } diff --git a/src/providers/music/queue.rs b/src/providers/music/queue.rs index 057349e..3be4f40 100644 --- a/src/providers/music/queue.rs +++ b/src/providers/music/queue.rs @@ -5,16 +5,16 @@ use songbird::tracks::TrackHandle; use bot_coreutils::shuffle::Shuffle; -use crate::messages::music::NowPlayingMessage; use crate::providers::music::responses::{PlaylistEntry, VideoInformation}; use crate::providers::music::youtube_dl; +use bot_serenityutils::core::MessageHandle; #[derive(Clone)] pub struct MusicQueue { inner: VecDeque, current: Option, paused: bool, - pub now_playing_msg: Option, + pub now_playing_msg: Option, pub leave_flag: bool, } diff --git a/src/utils/messages.rs b/src/utils/messages.rs deleted file mode 100644 index f5ea07c..0000000 --- a/src/utils/messages.rs +++ /dev/null @@ -1,80 +0,0 @@ -use std::sync::Arc; - -use serenity::builder::{CreateMessage, EditMessage}; -use serenity::http::{CacheHttp, Http}; -use serenity::model::channel::Message; -use serenity::model::id::{ChannelId, MessageId}; - -use crate::utils::error::BotResult; - -#[derive(Clone)] -pub struct ShareableMessage { - http: Arc, - channel_id: u64, - message_id: u64, -} - -impl ShareableMessage { - /// Creates a new active message - pub async fn create<'a, F>(http: Arc, channel_id: &ChannelId, f: F) -> BotResult - where - for<'b> F: FnOnce(&'b mut CreateMessage<'a>) -> &'b mut CreateMessage<'a>, - { - let msg = channel_id.send_message(http.http(), f).await?; - - Ok(Self::new(http, &msg.channel_id, &msg.id)) - } - - /// Creates a new active message - pub fn new(http: Arc, channel_id: &ChannelId, message_id: &MessageId) -> Self { - Self { - http, - channel_id: channel_id.0, - message_id: message_id.0, - } - } - - /// Deletes the underlying message - pub async fn delete(&self) -> BotResult<()> { - let msg = self.get_discord_message().await?; - msg.delete(&self.http).await?; - - Ok(()) - } - - /// Edits the active message - pub async fn edit(&self, f: F) -> BotResult<()> - where - F: FnOnce(&mut EditMessage) -> &mut EditMessage, - { - let mut message = self.get_discord_message().await?; - message.edit(&self.http, f).await?; - - Ok(()) - } - - /// Returns the underlying message - pub async fn get_discord_message(&self) -> BotResult { - let message = self - .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 { - &self.http - } -} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 165d02c..5cfea0d 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -6,7 +6,6 @@ use crate::utils::error::BotResult; pub(crate) mod context_data; pub(crate) mod error; pub(crate) mod logging; -pub(crate) mod messages; /// Returns the message the given message is a reply to or the message sent before that pub async fn get_previous_message_or_reply(