diff --git a/src/commands/moderation_cmds.rs b/src/commands/moderation_cmds.rs index aeaed4e..2d0ae7f 100644 --- a/src/commands/moderation_cmds.rs +++ b/src/commands/moderation_cmds.rs @@ -1,26 +1,16 @@ -use std::{collections::HashMap, iter}; - use chrono::offset::Utc; use chrono_tz::{Tz, TZ_VARIANTS}; use levenshtein::levenshtein; -use regex::Regex; use regex_command_attr::command; -use serenity::{ - client::Context, - model::{ - channel::Message, - id::{ChannelId, MessageId, RoleId}, - misc::Mentionable, - }, -}; +use serenity::{client::Context, model::misc::Mentionable}; use crate::{ component_models::{ComponentDataModel, Restrict}, - consts::{REGEX_ALIAS, REGEX_COMMANDS, THEME_COLOR}, + consts::THEME_COLOR, framework::{ CommandInvoke, CommandOptions, CreateGenericResponse, OptionValue, PermissionLevel, }, - models::{channel_data::ChannelData, guild_data::GuildData, user_data::UserData, CtxData}, + models::{channel_data::ChannelData, CtxData}, PopularTimezones, RegexFramework, SQLPool, }; diff --git a/src/commands/reminder_cmds.rs b/src/commands/reminder_cmds.rs index 6223d8c..13112e3 100644 --- a/src/commands/reminder_cmds.rs +++ b/src/commands/reminder_cmds.rs @@ -1,5 +1,4 @@ use std::{ - collections::HashMap, default::Default, string::ToString, time::{SystemTime, UNIX_EPOCH}, @@ -8,20 +7,14 @@ use std::{ use chrono::NaiveDateTime; use num_integer::Integer; use regex_command_attr::command; -use serenity::{ - client::Context, - futures::StreamExt, - model::{ - channel::{Channel, Message}, - id::ChannelId, - interactions::message_component::ButtonStyle, - misc::Mentionable, - }, -}; +use serenity::{client::Context, model::channel::Channel}; use crate::{ check_subscription_on_message, - component_models::{ComponentDataModel, LookPager, PageAction}, + component_models::{ + pager::{DelPager, LookPager, Pager}, + ComponentDataModel, DelSelector, + }, consts::{ EMBED_DESCRIPTION_MAX_LENGTH, REGEX_CHANNEL_USER, REGEX_NATURAL_COMMAND_1, REGEX_NATURAL_COMMAND_2, REGEX_REMIND_COMMAND, THEME_COLOR, @@ -160,7 +153,7 @@ async fn offset(ctx: &Context, invoke: &(dyn CommandInvoke + Send + Sync), args: let channels = guild .channels .iter() - .filter(|(channel_id, channel)| match channel { + .filter(|(_, channel)| match channel { Channel::Guild(guild_channel) => guild_channel.is_text_based(), _ => false, }) @@ -333,30 +326,7 @@ async fn look(ctx: &Context, invoke: &(dyn CommandInvoke + Send + Sync), args: C .fold(0, |t, r| t + r.len()) .div_ceil(EMBED_DESCRIPTION_MAX_LENGTH); - let page_first = ComponentDataModel::LookPager(LookPager { - flags: flags.clone(), - page: 0, - action: PageAction::First, - timezone, - }); - let page_prev = ComponentDataModel::LookPager(LookPager { - flags: flags.clone(), - page: 0, - action: PageAction::Previous, - timezone, - }); - let page_next = ComponentDataModel::LookPager(LookPager { - flags: flags.clone(), - page: 0, - action: PageAction::Next, - timezone, - }); - let page_last = ComponentDataModel::LookPager(LookPager { - flags: flags.clone(), - page: 0, - action: PageAction::Last, - timezone, - }); + let pager = LookPager::new(flags, timezone); invoke .respond( @@ -372,32 +342,9 @@ async fn look(ctx: &Context, invoke: &(dyn CommandInvoke + Send + Sync), args: C .color(*THEME_COLOR) }) .components(|comp| { - comp.create_action_row(|row| { - row.create_button(|b| { - b.label("⏮️") - .style(ButtonStyle::Primary) - .custom_id(page_first.to_custom_id()) - .disabled(true) - }) - .create_button(|b| { - b.label("◀️") - .style(ButtonStyle::Secondary) - .custom_id(page_prev.to_custom_id()) - .disabled(true) - }) - .create_button(|b| { - b.label("▶️") - .style(ButtonStyle::Secondary) - .custom_id(page_next.to_custom_id()) - .disabled(pages == 1) - }) - .create_button(|b| { - b.label("⏭️") - .style(ButtonStyle::Primary) - .custom_id(page_last.to_custom_id()) - .disabled(pages == 1) - }) - }) + pager.create_button_row(pages, comp); + + comp }), ) .await @@ -409,19 +356,92 @@ async fn look(ctx: &Context, invoke: &(dyn CommandInvoke + Send + Sync), args: C #[description("Delete reminders")] #[required_permissions(Managed)] async fn delete(ctx: &Context, invoke: &(dyn CommandInvoke + Send + Sync)) { + let pool = ctx.data.read().await.get::().cloned().unwrap(); + + let timezone = UserData::timezone_of(&invoke.author_id(), &pool).await; + let reminders = Reminder::from_guild(ctx, invoke.guild_id(), invoke.author_id()).await; - let enumerated_reminders = reminders.iter().enumerate().map(|(count, reminder)| { - format!( - "**{}**: '{}' *<#{}>* at ", - count + 1, - reminder.display_content(), - reminder.channel, - reminder.utc_time.timestamp() - ) - }); + if reminders.is_empty() { + let _ = invoke + .respond( + ctx.http.clone(), + CreateGenericResponse::new().content("No reminders to delete!"), + ) + .await; + } else { + let mut char_count = 0; - let _ = invoke.respond(ctx.http.clone(), CreateGenericResponse::new().content("test")).await; + let (shown_reminders, display_vec): (Vec<&Reminder>, Vec) = reminders + .iter() + .enumerate() + .map(|(count, reminder)| (reminder, reminder.display_del(count, &timezone))) + .take_while(|(_, p)| { + char_count += p.len(); + + char_count < EMBED_DESCRIPTION_MAX_LENGTH + }) + .unzip(); + + let display = display_vec.join("\n"); + + let pages = reminders + .iter() + .enumerate() + .map(|(count, reminder)| reminder.display_del(count, &timezone)) + .fold(0, |t, r| t + r.len()) + .div_ceil(EMBED_DESCRIPTION_MAX_LENGTH); + + let pager = DelPager::new(timezone); + + let del_selector = ComponentDataModel::DelSelector(DelSelector { page: 0, timezone }); + + invoke + .respond( + ctx.http.clone(), + CreateGenericResponse::new() + .embed(|e| { + e.title("Delete Reminders") + .description(display) + .footer(|f| f.text(format!("Page {} of {}", 1, pages))) + .color(*THEME_COLOR) + }) + .components(|comp| { + pager.create_button_row(pages, comp); + + comp.create_action_row(|row| { + row.create_select_menu(|menu| { + menu.custom_id(del_selector.to_custom_id()).options(|opt| { + for (count, reminder) in shown_reminders.iter().enumerate() { + opt.create_option(|o| { + o.label(count + 1).value(reminder.id).description({ + let c = reminder.display_content(); + + if c.len() > 100 { + format!( + "{}...", + reminder + .display_content() + .chars() + .take(97) + .collect::() + ) + } else { + c.to_string() + } + }) + }); + } + + opt + }) + }) + }) + }), + ) + .await + .unwrap(); + } } #[command("timer")] diff --git a/src/component_models/mod.rs b/src/component_models/mod.rs index ec9b4d1..f589b5d 100644 --- a/src/component_models/mod.rs +++ b/src/component_models/mod.rs @@ -1,29 +1,25 @@ +pub(crate) mod pager; + use std::io::Cursor; use chrono_tz::Tz; use rmp_serde::Serializer; use serde::{Deserialize, Serialize}; -use serde_repr::*; use serenity::{ builder::CreateEmbed, client::Context, model::{ channel::Channel, - id::{ChannelId, GuildId, RoleId, UserId}, - interactions::{ - message_component::{ButtonStyle, MessageComponentInteraction}, - InteractionResponseType, - }, + id::{GuildId, RoleId, UserId}, + interactions::{message_component::MessageComponentInteraction, InteractionResponseType}, prelude::InteractionApplicationCommandCallbackDataFlags, }, }; use crate::{ + component_models::pager::{DelPager, LookPager, Pager}, consts::{EMBED_DESCRIPTION_MAX_LENGTH, THEME_COLOR}, - models::{ - reminder::{look_flags::LookFlags, Reminder}, - user_data::UserData, - }, + models::reminder::Reminder, SQLPool, }; @@ -33,6 +29,8 @@ use crate::{ pub enum ComponentDataModel { Restrict(Restrict), LookPager(LookPager), + DelPager(DelPager), + DelSelector(DelSelector), } impl ComponentDataModel { @@ -109,7 +107,7 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id .iter() .map(|reminder| reminder.display(&flags, &pager.timezone)) .fold(0, |t, r| t + r.len()) - .div_ceil(EMBED_DESCRIPTION_MAX_LENGTH) as u16; + .div_ceil(EMBED_DESCRIPTION_MAX_LENGTH); let channel_name = if let Some(Channel::Guild(channel)) = channel_id.to_channel_cached(&ctx) { @@ -118,12 +116,7 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id None }; - let next_page = match pager.action { - PageAction::First => 0, - PageAction::Previous => 0.max(pager.page - 1), - PageAction::Next => (pages - 1).min(pager.page + 1), - PageAction::Last => pages - 1, - }; + let next_page = pager.next_page(pages); let mut char_count = 0; let mut skip_char_count = 0; @@ -144,31 +137,6 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id .collect::>() .join("\n"); - let page_first = ComponentDataModel::LookPager(LookPager { - flags: flags.clone(), - page: next_page, - action: PageAction::First, - timezone: pager.timezone, - }); - let page_prev = ComponentDataModel::LookPager(LookPager { - flags: flags.clone(), - page: next_page, - action: PageAction::Previous, - timezone: pager.timezone, - }); - let page_next = ComponentDataModel::LookPager(LookPager { - flags: flags.clone(), - page: next_page, - action: PageAction::Next, - timezone: pager.timezone, - }); - let page_last = ComponentDataModel::LookPager(LookPager { - flags: flags.clone(), - page: next_page, - action: PageAction::Last, - timezone: pager.timezone, - }); - let mut embed = CreateEmbed::default(); embed .title(format!( @@ -179,42 +147,225 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id .footer(|f| f.text(format!("Page {} of {}", next_page + 1, pages))) .color(*THEME_COLOR); - let _ = - component - .create_interaction_response(&ctx, |r| { - r.kind(InteractionResponseType::UpdateMessage) - .interaction_response_data(|response| { - response.embeds(vec![embed]).components(|comp| { - comp.create_action_row(|row| { - row.create_button(|b| { - b.label("⏮️") - .style(ButtonStyle::Primary) - .custom_id(page_first.to_custom_id()) - .disabled(next_page == 0) - }) - .create_button(|b| { - b.label("◀️") - .style(ButtonStyle::Secondary) - .custom_id(page_prev.to_custom_id()) - .disabled(next_page == 0) - }) - .create_button(|b| { - b.label("▶️") - .style(ButtonStyle::Secondary) - .custom_id(page_next.to_custom_id()) - .disabled(next_page + 1 == pages) - }) - .create_button(|b| { - b.label("⏭️") - .style(ButtonStyle::Primary) - .custom_id(page_last.to_custom_id()) - .disabled(next_page + 1 == pages) - }) + let _ = component + .create_interaction_response(&ctx, |r| { + r.kind(InteractionResponseType::UpdateMessage).interaction_response_data( + |response| { + response.embeds(vec![embed]).components(|comp| { + pager.create_button_row(pages, comp); + + comp + }) + }, + ) + }) + .await; + } + ComponentDataModel::DelPager(pager) => { + let reminders = + Reminder::from_guild(ctx, component.guild_id, component.user.id).await; + + let pages = reminders + .iter() + .enumerate() + .map(|(count, reminder)| reminder.display_del(count, &pager.timezone)) + .fold(0, |t, r| t + r.len()) + .div_ceil(EMBED_DESCRIPTION_MAX_LENGTH); + + let next_page = pager.next_page(pages); + + let mut char_count = 0; + let mut skip_char_count = 0; + let mut first_num = 0; + + let (shown_reminders, display_vec): (Vec<&Reminder>, Vec) = reminders + .iter() + .enumerate() + .map(|(count, reminder)| { + (reminder, reminder.display_del(count, &pager.timezone)) + }) + .skip_while(|(_, p)| { + first_num += 1; + skip_char_count += p.len(); + + skip_char_count < EMBED_DESCRIPTION_MAX_LENGTH * next_page + }) + .take_while(|(_, p)| { + char_count += p.len(); + + char_count < EMBED_DESCRIPTION_MAX_LENGTH + }) + .unzip(); + + let display = display_vec.join("\n"); + + let del_selector = ComponentDataModel::DelSelector(DelSelector { + page: next_page, + timezone: pager.timezone, + }); + + let mut embed = CreateEmbed::default(); + embed + .title("Delete Reminders") + .description(display) + .footer(|f| f.text(format!("Page {} of {}", next_page + 1, pages))) + .color(*THEME_COLOR); + + component + .create_interaction_response(&ctx, |r| { + r.kind(InteractionResponseType::UpdateMessage).interaction_response_data( + |response| { + response.embeds(vec![embed]).components(|comp| { + pager.create_button_row(pages, comp); + + comp.create_action_row(|row| { + row.create_select_menu(|menu| { + menu.custom_id(del_selector.to_custom_id()).options( + |opt| { + for (count, reminder) in + shown_reminders.iter().enumerate() + { + opt.create_option(|o| { + o.label(count + first_num) + .value(reminder.id) + .description({ + let c = + reminder.display_content(); + + if c.len() > 100 { + format!( + "{}...", + reminder + .display_content() + .chars() + .take(97) + .collect::( + ) + ) + } else { + c.to_string() + } + }) + }); + } + + opt + }, + ) }) }) }) - }) - .await; + }, + ) + }) + .await; + } + ComponentDataModel::DelSelector(selector) => { + let pool = ctx.data.read().await.get::().cloned().unwrap(); + let selected_id = component.data.values.join(","); + + sqlx::query!("DELETE FROM reminders WHERE FIND_IN_SET(id, ?)", selected_id) + .execute(&pool) + .await + .unwrap(); + + let reminders = + Reminder::from_guild(ctx, component.guild_id, component.user.id).await; + + let mut char_count = 0; + let mut skip_char_count = 0; + let mut first_num = 0; + + let (shown_reminders, display_vec): (Vec<&Reminder>, Vec) = reminders + .iter() + .enumerate() + .map(|(count, reminder)| { + (reminder, reminder.display_del(count, &selector.timezone)) + }) + .skip_while(|(_, p)| { + first_num += 1; + skip_char_count += p.len(); + + skip_char_count < EMBED_DESCRIPTION_MAX_LENGTH * selector.page + }) + .take_while(|(_, p)| { + char_count += p.len(); + + char_count < EMBED_DESCRIPTION_MAX_LENGTH + }) + .unzip(); + + let display = display_vec.join("\n"); + + let pages = reminders + .iter() + .enumerate() + .map(|(count, reminder)| reminder.display_del(count, &selector.timezone)) + .fold(0, |t, r| t + r.len()) + .div_ceil(EMBED_DESCRIPTION_MAX_LENGTH); + + let pager = DelPager::new(selector.timezone); + + let del_selector = ComponentDataModel::DelSelector(DelSelector { + page: selector.page, + timezone: selector.timezone, + }); + + let mut embed = CreateEmbed::default(); + embed + .title("Delete Reminders") + .description(display) + .footer(|f| f.text(format!("Page {} of {}", selector.page + 1, pages))) + .color(*THEME_COLOR); + + component + .create_interaction_response(&ctx, |r| { + r.kind(InteractionResponseType::UpdateMessage).interaction_response_data( + |response| { + response.embeds(vec![embed]).components(|comp| { + pager.create_button_row(pages, comp); + + comp.create_action_row(|row| { + row.create_select_menu(|menu| { + menu.custom_id(del_selector.to_custom_id()).options( + |opt| { + for (count, reminder) in + shown_reminders.iter().enumerate() + { + opt.create_option(|o| { + o.label(count + 1) + .value(reminder.id) + .description({ + let c = + reminder.display_content(); + + if c.len() > 100 { + format!( + "{}...", + reminder + .display_content() + .chars() + .take(97) + .collect::( + ) + ) + } else { + c.to_string() + } + }) + }); + } + + opt + }, + ) + }) + }) + }) + }, + ) + }) + .await; } } } @@ -227,19 +378,8 @@ pub struct Restrict { pub guild_id: GuildId, } -#[derive(Serialize_repr, Deserialize_repr, Debug)] -#[repr(u8)] -pub enum PageAction { - First = 0, - Previous = 1, - Next = 2, - Last = 3, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct LookPager { - pub flags: LookFlags, - pub page: u16, - pub action: PageAction, +#[derive(Serialize, Deserialize)] +pub struct DelSelector { + pub page: usize, pub timezone: Tz, } diff --git a/src/component_models/pager.rs b/src/component_models/pager.rs new file mode 100644 index 0000000..a78e72d --- /dev/null +++ b/src/component_models/pager.rs @@ -0,0 +1,183 @@ +use chrono_tz::Tz; +use serde::{Deserialize, Serialize}; +use serde_repr::*; +use serenity::{builder::CreateComponents, model::interactions::message_component::ButtonStyle}; + +use crate::{component_models::ComponentDataModel, models::reminder::look_flags::LookFlags}; + +pub trait Pager { + fn next_page(&self, max_pages: usize) -> usize; + + fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents); +} + +#[derive(Serialize_repr, Deserialize_repr)] +#[repr(u8)] +enum PageAction { + First = 0, + Previous = 1, + Next = 2, + Last = 3, +} + +#[derive(Serialize, Deserialize)] +pub struct LookPager { + pub flags: LookFlags, + pub page: usize, + action: PageAction, + pub timezone: Tz, +} + +impl Pager for LookPager { + fn next_page(&self, max_pages: usize) -> usize { + match self.action { + PageAction::First => 0, + PageAction::Previous => 0.max(self.page - 1), + PageAction::Next => (max_pages - 1).min(self.page + 1), + PageAction::Last => max_pages - 1, + } + } + + fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents) { + let next_page = self.next_page(max_pages); + + let (page_first, page_prev, page_next, page_last) = + LookPager::buttons(self.flags, next_page, self.timezone); + + comp.create_action_row(|row| { + row.create_button(|b| { + b.label("⏮️") + .style(ButtonStyle::Primary) + .custom_id(page_first.to_custom_id()) + .disabled(next_page == 0) + }) + .create_button(|b| { + b.label("◀️") + .style(ButtonStyle::Secondary) + .custom_id(page_prev.to_custom_id()) + .disabled(next_page == 0) + }) + .create_button(|b| { + b.label("▶️") + .style(ButtonStyle::Secondary) + .custom_id(page_next.to_custom_id()) + .disabled(next_page + 1 == max_pages) + }) + .create_button(|b| { + b.label("⏭️") + .style(ButtonStyle::Primary) + .custom_id(page_last.to_custom_id()) + .disabled(next_page + 1 == max_pages) + }) + }); + } +} + +impl LookPager { + pub fn new(flags: LookFlags, timezone: Tz) -> Self { + Self { flags, page: 0, action: PageAction::First, timezone } + } + + pub fn buttons( + flags: LookFlags, + page: usize, + timezone: Tz, + ) -> (ComponentDataModel, ComponentDataModel, ComponentDataModel, ComponentDataModel) { + ( + ComponentDataModel::LookPager(LookPager { + flags, + page, + action: PageAction::First, + timezone, + }), + ComponentDataModel::LookPager(LookPager { + flags, + page, + action: PageAction::Previous, + timezone, + }), + ComponentDataModel::LookPager(LookPager { + flags, + page, + action: PageAction::Next, + timezone, + }), + ComponentDataModel::LookPager(LookPager { + flags, + page, + action: PageAction::Last, + timezone, + }), + ) + } +} + +#[derive(Serialize, Deserialize)] +pub struct DelPager { + pub page: usize, + action: PageAction, + pub timezone: Tz, +} + +impl Pager for DelPager { + fn next_page(&self, max_pages: usize) -> usize { + match self.action { + PageAction::First => 0, + PageAction::Previous => 0.max(self.page - 1), + PageAction::Next => (max_pages - 1).min(self.page + 1), + PageAction::Last => max_pages - 1, + } + } + + fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents) { + let next_page = self.next_page(max_pages); + + let (page_first, page_prev, page_next, page_last) = + DelPager::buttons(next_page, self.timezone); + + comp.create_action_row(|row| { + row.create_button(|b| { + b.label("⏮️") + .style(ButtonStyle::Primary) + .custom_id(page_first.to_custom_id()) + .disabled(next_page == 0) + }) + .create_button(|b| { + b.label("◀️") + .style(ButtonStyle::Secondary) + .custom_id(page_prev.to_custom_id()) + .disabled(next_page == 0) + }) + .create_button(|b| { + b.label("▶️") + .style(ButtonStyle::Secondary) + .custom_id(page_next.to_custom_id()) + .disabled(next_page + 1 == max_pages) + }) + .create_button(|b| { + b.label("⏭️") + .style(ButtonStyle::Primary) + .custom_id(page_last.to_custom_id()) + .disabled(next_page + 1 == max_pages) + }) + }); + } +} + +impl DelPager { + pub fn new(timezone: Tz) -> Self { + Self { page: 0, action: PageAction::First, timezone } + } + + pub fn buttons( + page: usize, + timezone: Tz, + ) -> (ComponentDataModel, ComponentDataModel, ComponentDataModel, ComponentDataModel) { + ( + ComponentDataModel::DelPager(DelPager { page, action: PageAction::First, timezone }), + ComponentDataModel::DelPager(DelPager { page, action: PageAction::Previous, timezone }), + ComponentDataModel::DelPager(DelPager { page, action: PageAction::Next, timezone }), + ComponentDataModel::DelPager(DelPager { page, action: PageAction::Last, timezone }), + ) + } +} diff --git a/src/framework.rs b/src/framework.rs index a714218..60a3e22 100644 --- a/src/framework.rs +++ b/src/framework.rs @@ -16,15 +16,13 @@ use serenity::{ framework::Framework, futures::prelude::future::BoxFuture, http::Http, - json::Value, model::{ channel::{Channel, GuildChannel, Message}, guild::{Guild, Member}, id::{ChannelId, GuildId, MessageId, RoleId, UserId}, interactions::{ application_command::{ - ApplicationCommand, ApplicationCommandInteraction, ApplicationCommandOption, - ApplicationCommandOptionType, + ApplicationCommand, ApplicationCommandInteraction, ApplicationCommandOptionType, }, InteractionResponseType, }, @@ -772,7 +770,8 @@ impl RegexFramework { ApplicationCommand::set_global_application_commands(&http, |c| { self._populate_commands(c) }) - .await; + .await + .unwrap(); } Some(debug_guild) => { debug_guild diff --git a/src/main.rs b/src/main.rs index 1f7ac9a..eb51567 100644 --- a/src/main.rs +++ b/src/main.rs @@ -304,9 +304,9 @@ async fn main() -> Result<(), Box> { .add_command("natural", &reminder_cmds::NATURAL_COMMAND) .add_command("n", &reminder_cmds::NATURAL_COMMAND) .add_command("", &reminder_cmds::NATURAL_COMMAND) - // management commands - .add_command("del", &reminder_cmds::DELETE_COMMAND) */ + // management commands + .add_command(&reminder_cmds::DELETE_COMMAND) .add_command(&reminder_cmds::LOOK_COMMAND) .add_command(&reminder_cmds::PAUSE_COMMAND) .add_command(&reminder_cmds::OFFSET_COMMAND) diff --git a/src/models/reminder/look_flags.rs b/src/models/reminder/look_flags.rs index 04a684f..5568f85 100644 --- a/src/models/reminder/look_flags.rs +++ b/src/models/reminder/look_flags.rs @@ -2,8 +2,6 @@ use serde::{Deserialize, Serialize}; use serde_repr::*; use serenity::model::id::ChannelId; -use crate::consts::REGEX_CHANNEL; - #[derive(Serialize_repr, Deserialize_repr, Copy, Clone, Debug)] #[repr(u8)] pub enum TimeDisplayType { diff --git a/src/models/reminder/mod.rs b/src/models/reminder/mod.rs index 9837486..25fe205 100644 --- a/src/models/reminder/mod.rs +++ b/src/models/reminder/mod.rs @@ -4,11 +4,6 @@ pub mod errors; mod helper; pub mod look_flags; -use std::{ - convert::{TryFrom, TryInto}, - env, -}; - use chrono::{NaiveDateTime, TimeZone}; use chrono_tz::Tz; use serenity::{ @@ -19,14 +14,13 @@ use sqlx::MySqlPool; use crate::{ models::reminder::{ - errors::InteractionError, helper::longhand_displacement, look_flags::{LookFlags, TimeDisplayType}, }, SQLPool, }; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Reminder { pub id: u32, pub uid: String, @@ -284,6 +278,19 @@ WHERE } } + pub fn display_del(&self, count: usize, timezone: &Tz) -> String { + format!( + "**{}**: '{}' *<#{}>* at **{}**", + count + 1, + self.display_content(), + self.channel, + timezone + .timestamp(self.utc_time.timestamp(), 0) + .format("%Y-%m-%d %H:%M:%S") + .to_string() + ) + } + pub fn display(&self, flags: &LookFlags, timezone: &Tz) -> String { let time_display = match flags.time_display { TimeDisplayType::Absolute => timezone