168 lines
4.8 KiB
Rust
168 lines
4.8 KiB
Rust
use chrono_tz::Tz;
|
|
use poise::{
|
|
serenity_prelude::{
|
|
CreateActionRow, CreateEmbed, CreateEmbedFooter, CreateSelectMenu, CreateSelectMenuKind,
|
|
CreateSelectMenuOption,
|
|
},
|
|
CreateReply,
|
|
};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::{
|
|
component_models::{
|
|
pager::{DelPager, Pager},
|
|
ComponentDataModel, DelSelector,
|
|
},
|
|
consts::{EMBED_DESCRIPTION_MAX_LENGTH, SELECT_MAX_ENTRIES, THEME_COLOR},
|
|
models::{reminder::Reminder, CtxData},
|
|
utils::{Extract, Recordable},
|
|
Context, Error,
|
|
};
|
|
|
|
pub fn max_delete_page(reminders: &[Reminder], timezone: &Tz) -> usize {
|
|
let mut rows = 0;
|
|
let mut char_count = 0;
|
|
|
|
reminders
|
|
.iter()
|
|
.enumerate()
|
|
.map(|(count, reminder)| reminder.display_del(count, timezone))
|
|
.fold(1, |mut pages, reminder| {
|
|
rows += 1;
|
|
char_count += reminder.len();
|
|
|
|
if char_count > EMBED_DESCRIPTION_MAX_LENGTH || rows > SELECT_MAX_ENTRIES {
|
|
rows = 1;
|
|
char_count = reminder.len();
|
|
pages += 1;
|
|
}
|
|
|
|
pages
|
|
})
|
|
}
|
|
|
|
pub fn show_delete_page(reminders: &[Reminder], page: usize, timezone: Tz) -> CreateReply {
|
|
let pager = DelPager::new(page, timezone);
|
|
|
|
if reminders.is_empty() {
|
|
let embed = CreateEmbed::new()
|
|
.title("Delete Reminders")
|
|
.description("No Reminders")
|
|
.color(*THEME_COLOR);
|
|
|
|
return CreateReply::default().embed(embed).components(vec![pager.create_button_row(0)]);
|
|
}
|
|
|
|
let pages = max_delete_page(reminders, &timezone);
|
|
|
|
let mut page = page;
|
|
if page >= pages {
|
|
page = pages - 1;
|
|
}
|
|
|
|
let mut char_count = 0;
|
|
let mut rows = 0;
|
|
let mut skipped_rows = 0;
|
|
let mut skipped_char_count = 0;
|
|
let mut first_num = 0;
|
|
|
|
let mut skipped_pages = 0;
|
|
|
|
let (shown_reminders, display_vec): (Vec<&Reminder>, Vec<String>) = reminders
|
|
.iter()
|
|
.enumerate()
|
|
.map(|(count, reminder)| (reminder, reminder.display_del(count, &timezone)))
|
|
.skip_while(|(_, p)| {
|
|
first_num += 1;
|
|
skipped_rows += 1;
|
|
skipped_char_count += p.len();
|
|
|
|
if skipped_char_count > EMBED_DESCRIPTION_MAX_LENGTH
|
|
|| skipped_rows > SELECT_MAX_ENTRIES
|
|
{
|
|
skipped_rows = 1;
|
|
skipped_char_count = p.len();
|
|
skipped_pages += 1;
|
|
}
|
|
|
|
skipped_pages < page
|
|
})
|
|
.take_while(|(_, p)| {
|
|
rows += 1;
|
|
char_count += p.len();
|
|
|
|
char_count < EMBED_DESCRIPTION_MAX_LENGTH && rows <= SELECT_MAX_ENTRIES
|
|
})
|
|
.unzip();
|
|
|
|
let display = display_vec.join("\n");
|
|
|
|
let del_selector = ComponentDataModel::DelSelector(DelSelector { page, timezone });
|
|
|
|
let embed = CreateEmbed::new()
|
|
.title("Delete Reminders")
|
|
.description(display)
|
|
.footer(CreateEmbedFooter::new(format!("Page {} of {}", page + 1, pages)))
|
|
.color(*THEME_COLOR);
|
|
|
|
let select_menu = CreateSelectMenu::new(
|
|
del_selector.to_custom_id(),
|
|
CreateSelectMenuKind::String {
|
|
options: shown_reminders
|
|
.iter()
|
|
.enumerate()
|
|
.map(|(count, reminder)| {
|
|
let c = reminder.display_content();
|
|
let description = if c.len() > 100 {
|
|
format!(
|
|
"{}...",
|
|
reminder.display_content().chars().take(97).collect::<String>()
|
|
)
|
|
} else {
|
|
c.to_string()
|
|
};
|
|
|
|
CreateSelectMenuOption::new(
|
|
(count + first_num).to_string(),
|
|
reminder.id.to_string(),
|
|
)
|
|
.description(description)
|
|
})
|
|
.collect(),
|
|
},
|
|
);
|
|
|
|
CreateReply::default()
|
|
.embed(embed)
|
|
.components(vec![pager.create_button_row(pages), CreateActionRow::SelectMenu(select_menu)])
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Extract)]
|
|
pub struct Options;
|
|
|
|
impl Recordable for Options {
|
|
async fn run(self, ctx: Context<'_>) -> Result<(), Error> {
|
|
let timezone = ctx.timezone().await;
|
|
|
|
let reminders =
|
|
Reminder::from_guild(&ctx, &ctx.data().database, ctx.guild_id(), ctx.author().id).await;
|
|
|
|
let resp = show_delete_page(&reminders, 0, timezone);
|
|
|
|
ctx.send(resp).await?;
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// Delete reminders
|
|
#[poise::command(
|
|
slash_command,
|
|
rename = "delete",
|
|
identifying_name = "delete",
|
|
default_member_permissions = "MANAGE_GUILD"
|
|
)]
|
|
pub async fn command(ctx: Context<'_>) -> Result<(), Error> {
|
|
(Options {}).run(ctx).await
|
|
}
|