Change music NowPlaying embed to be created as a menu

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

@ -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<dyn EventDrivenMessage>;
@ -25,4 +29,10 @@ impl MessageHandle {
channel_id,
}
}
/// Returns the message object of the handle
pub async fn get_message(&self, http: &Arc<Http>) -> SerenityUtilsResult<Message> {
let msg = http.get_message(self.channel_id, self.message_id).await?;
Ok(msg)
}
}

@ -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?;

@ -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();
}

@ -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<MessageHandle> {
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<Http>,
channel_id: &ChannelId,
meta: &Metadata,
) -> BotResult<Self> {
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<Http>,
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
}

@ -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<Song>,
current: Option<TrackHandle>,
paused: bool,
pub now_playing_msg: Option<NowPlayingMessage>,
pub now_playing_msg: Option<MessageHandle>,
pub leave_flag: bool,
}

@ -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<Http>,
channel_id: u64,
message_id: u64,
}
impl ShareableMessage {
/// Creates a new active message
pub async fn create<'a, F>(http: Arc<Http>, channel_id: &ChannelId, f: F) -> BotResult<Self>
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<Http>, 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<F>(&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<Message> {
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<Http> {
&self.http
}
}

@ -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(

Loading…
Cancel
Save