Add ephemeral message table and delete them on startup

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

2
Cargo.lock generated

@ -193,7 +193,7 @@ dependencies = [
[[package]] [[package]]
name = "bot-database" name = "bot-database"
version = "0.4.0" version = "0.5.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"diesel", "diesel",

@ -1,6 +1,6 @@
[package] [package]
name = "bot-database" name = "bot-database"
version = "0.4.0" version = "0.5.0"
authors = ["trivernis <trivernis@protonmail.com>"] authors = ["trivernis <trivernis@protonmail.com>"]
edition = "2018" edition = "2018"

@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
DROP TABLE ephemeral_messages;

@ -0,0 +1,7 @@
-- Your SQL goes here
CREATE TABLE ephemeral_messages (
channel_id BIGINT NOT NULL,
message_id BIGINT NOT NULL,
timeout TIMESTAMP NOT NULL,
PRIMARY KEY (channel_id, message_id)
)

@ -0,0 +1,58 @@
use std::time::SystemTime;
use diesel::prelude::*;
use diesel::{delete, insert_into};
use tokio_diesel::*;
use crate::error::DatabaseResult;
use crate::models::*;
use crate::schema::*;
use crate::Database;
impl Database {
/// Adds a command statistic to the database
pub async fn add_ephemeral_message(
&self,
channel_id: u64,
message_id: u64,
timeout: SystemTime,
) -> DatabaseResult<()> {
use ephemeral_messages::dsl;
insert_into(dsl::ephemeral_messages)
.values(EphemeralMessageInsert {
channel_id: channel_id as i64,
message_id: message_id as i64,
timeout,
})
.execute_async(&self.pool)
.await?;
Ok(())
}
/// Returns a vec of all ephemeral messages
pub async fn get_ephemeral_messages(&self) -> DatabaseResult<Vec<EphemeralMessage>> {
use ephemeral_messages::dsl;
let messages: Vec<EphemeralMessage> = dsl::ephemeral_messages
.load_async::<EphemeralMessage>(&self.pool)
.await?;
Ok(messages)
}
/// Deletes a single ephemeral message
pub async fn delete_ephemeral_message(
&self,
channel_id: i64,
message_id: i64,
) -> DatabaseResult<()> {
use ephemeral_messages::dsl;
delete(dsl::ephemeral_messages)
.filter(dsl::channel_id.eq(channel_id))
.filter(dsl::message_id.eq(message_id))
.execute_async(&self.pool)
.await?;
Ok(())
}
}

@ -1,3 +1,4 @@
pub use ephemeral_messages::*;
pub use gifs::*; pub use gifs::*;
pub use guild_playlists::*; pub use guild_playlists::*;
pub use guild_playlists::*; pub use guild_playlists::*;
@ -6,6 +7,7 @@ pub use youtube_songs::*;
use crate::PoolConnection; use crate::PoolConnection;
mod ephemeral_messages;
mod gifs; mod gifs;
mod guild_playlists; mod guild_playlists;
mod guild_settings; mod guild_settings;

@ -77,3 +77,18 @@ pub struct YoutubeSongInsert {
pub album: String, pub album: String,
pub url: String, pub url: String,
} }
#[derive(Queryable, Debug, Clone)]
pub struct EphemeralMessage {
pub channel_id: i64,
pub message_id: i64,
pub timeout: SystemTime,
}
#[derive(Insertable, Debug)]
#[table_name = "ephemeral_messages"]
pub struct EphemeralMessageInsert {
pub channel_id: i64,
pub message_id: i64,
pub timeout: SystemTime,
}

@ -1,3 +1,11 @@
table! {
ephemeral_messages (channel_id, message_id) {
channel_id -> Int8,
message_id -> Int8,
timeout -> Timestamp,
}
}
table! { table! {
gifs (id) { gifs (id) {
id -> Int8, id -> Int8,
@ -47,6 +55,7 @@ table! {
} }
allow_tables_to_appear_in_same_query!( allow_tables_to_appear_in_same_query!(
ephemeral_messages,
gifs, gifs,
guild_playlists, guild_playlists,
guild_settings, guild_settings,

@ -9,6 +9,7 @@ use serenity::model::voice::VoiceState;
use serenity::prelude::*; use serenity::prelude::*;
use crate::commands::music::get_queue_for_guild; use crate::commands::music::get_queue_for_guild;
use crate::utils::delete_messages_from_database;
use bot_serenityutils::menu::{ use bot_serenityutils::menu::{
handle_message_delete, handle_message_delete_bulk, handle_reaction_add, handle_reaction_remove, handle_message_delete, handle_message_delete_bulk, handle_reaction_add, handle_reaction_remove,
start_update_loop, start_update_loop,
@ -21,6 +22,9 @@ impl EventHandler for Handler {
async fn cache_ready(&self, ctx: Context, _: Vec<GuildId>) { async fn cache_ready(&self, ctx: Context, _: Vec<GuildId>) {
log::info!("Cache Ready"); log::info!("Cache Ready");
start_update_loop(&ctx).await; start_update_loop(&ctx).await;
if let Err(e) = delete_messages_from_database(&ctx).await {
log::error!("Failed to delete expired messages {:?}", e);
}
} }
/// Fired when a message was deleted /// Fired when a message was deleted

@ -1,3 +1,24 @@
use crate::utils::context_data::get_database_from_context;
use crate::utils::error::BotResult;
use bot_serenityutils::core::MessageHandle;
use serenity::client::Context;
use std::time::{Duration, SystemTime};
pub mod gifs; pub mod gifs;
pub mod music; pub mod music;
pub mod sauce; pub mod sauce;
/// Adds an ephemeral message to the database
pub async fn add_ephemeral_handle_to_database(
ctx: &Context,
handle: MessageHandle,
timeout: Duration,
) -> BotResult<()> {
let timeout = SystemTime::now() + timeout;
let database = get_database_from_context(ctx).await;
database
.add_ephemeral_message(handle.channel_id, handle.message_id, timeout)
.await?;
Ok(())
}

@ -6,6 +6,7 @@ use serenity::model::prelude::ChannelId;
use songbird::input::Metadata; use songbird::input::Metadata;
use crate::commands::music::{get_queue_for_guild, get_voice_manager, is_dj}; use crate::commands::music::{get_queue_for_guild, get_voice_manager, is_dj};
use crate::messages::add_ephemeral_handle_to_database;
use crate::providers::music::add_youtube_song_to_database; use crate::providers::music::add_youtube_song_to_database;
use crate::providers::music::queue::MusicQueue; use crate::providers::music::queue::MusicQueue;
use crate::utils::context_data::{DatabaseContainer, Store}; use crate::utils::context_data::{DatabaseContainer, Store};
@ -68,6 +69,8 @@ pub async fn create_now_playing_msg(
.build(ctx, channel_id) .build(ctx, channel_id)
.await?; .await?;
add_ephemeral_handle_to_database(ctx, *handle.read().await, Duration::from_secs(0)).await?;
Ok(handle) Ok(handle)
} }

@ -40,7 +40,7 @@ pub async fn show_sauce_menu(
.add_pages(pages) .add_pages(pages)
.build(ctx, msg.channel_id) .build(ctx, msg.channel_id)
.await?; .await?;
}; }
Ok(()) Ok(())
} }

@ -1,7 +1,12 @@
use serenity::client::Context; use serenity::client::Context;
use serenity::model::channel::Message; use serenity::model::channel::Message;
use crate::utils::context_data::get_database_from_context;
use crate::utils::error::BotResult; use crate::utils::error::BotResult;
use std::ops::Add;
use std::sync::Arc;
use std::time::SystemTime;
use tokio::time::Instant;
pub(crate) mod context_data; pub(crate) mod context_data;
pub(crate) mod error; pub(crate) mod error;
@ -24,3 +29,45 @@ pub async fn get_previous_message_or_reply(
Ok(referenced) Ok(referenced)
} }
/// Deletes all expired ephemeral messages that are stored in the database
pub async fn delete_messages_from_database(ctx: &Context) -> BotResult<()> {
let database = get_database_from_context(ctx).await;
let messages = database.get_ephemeral_messages().await?;
for message in messages {
if message.timeout <= SystemTime::now() {
log::debug!("Deleting message {:?}", message);
let _ = ctx
.http
.delete_message(message.channel_id as u64, message.message_id as u64)
.await;
database
.delete_ephemeral_message(message.channel_id, message.message_id)
.await?;
} else {
let http = Arc::clone(&ctx.http);
let database = database.clone();
log::debug!(
"Creating future to delete ephemeral message {:?} later",
message
);
tokio::spawn(async move {
tokio::time::sleep_until(
Instant::now().add(message.timeout.duration_since(SystemTime::now()).unwrap()),
)
.await;
log::debug!("Deleting message {:?}", message);
let _ = http
.delete_message(message.channel_id as u64, message.message_id as u64)
.await;
let _ = database
.delete_ephemeral_message(message.channel_id, message.message_id)
.await;
});
}
}
Ok(())
}

Loading…
Cancel
Save