Files
reminder-bot/src/commands/look.rs

135 lines
4.2 KiB
Rust

use poise::{
serenity_prelude::{model::id::ChannelId, CreateEmbed, CreateEmbedFooter, PartialChannel},
CreateReply,
};
use serde::{Deserialize, Serialize};
use serde_repr::*;
use crate::{
component_models::pager::{LookPager, Pager},
consts::{EMBED_DESCRIPTION_MAX_LENGTH, THEME_COLOR},
models::{reminder::Reminder, CtxData},
utils::{Extract, Recordable},
Context, Error,
};
#[derive(Serialize_repr, Deserialize_repr, Copy, Clone)]
#[repr(u8)]
pub enum TimeDisplayType {
Absolute = 0,
Relative = 1,
}
#[derive(Serialize, Deserialize, Copy, Clone)]
pub struct LookFlags {
pub show_disabled: bool,
pub channel_id: Option<ChannelId>,
pub time_display: TimeDisplayType,
}
impl Default for LookFlags {
fn default() -> Self {
Self { show_disabled: true, channel_id: None, time_display: TimeDisplayType::Relative }
}
}
#[derive(Serialize, Deserialize, Extract)]
pub struct Options {
channel: Option<PartialChannel>,
disabled: Option<bool>,
relative: Option<bool>,
}
impl Recordable for Options {
async fn run(self, ctx: Context<'_>) -> Result<(), Error> {
let timezone = ctx.timezone().await;
let flags = LookFlags {
show_disabled: self.disabled.unwrap_or(true),
channel_id: self.channel.map(|c| c.id),
time_display: self.relative.map_or(TimeDisplayType::Relative, |b| {
if b {
TimeDisplayType::Relative
} else {
TimeDisplayType::Absolute
}
}),
};
let channel_id = if let Some(channel) = ctx.channel_id().to_channel_cached(&ctx.cache()) {
if Some(channel.guild_id) == ctx.guild_id() {
flags.channel_id.unwrap_or_else(|| ctx.channel_id())
} else {
ctx.channel_id()
}
} else {
ctx.channel_id()
};
let channel_name =
channel_id.to_channel_cached(&ctx.cache()).map(|channel| channel.name.clone());
let reminders = Reminder::from_channel(&ctx.data().database, channel_id, &flags).await;
if reminders.is_empty() {
let _ = ctx.say("No reminders on specified channel").await;
} else {
let mut char_count = 0;
let display = reminders
.iter()
.map(|reminder| reminder.display(&flags, &timezone))
.take_while(|p| {
char_count += p.len();
char_count < EMBED_DESCRIPTION_MAX_LENGTH
})
.collect::<Vec<String>>()
.join("");
let pages = reminders
.iter()
.map(|reminder| reminder.display(&flags, &timezone))
.fold(0, |t, r| t + r.len())
.div_ceil(EMBED_DESCRIPTION_MAX_LENGTH);
let pager = LookPager::new(flags, timezone);
ctx.send(
CreateReply::default()
.ephemeral(true)
.embed(
CreateEmbed::new()
.title(format!(
"Reminders{}",
channel_name.map_or(String::new(), |n| format!(" on #{}", n))
))
.description(display)
.footer(CreateEmbedFooter::new(format!("Page {} of {}", 1, pages)))
.color(*THEME_COLOR),
)
.components(vec![pager.create_button_row(pages)]),
)
.await?;
}
Ok(())
}
}
/// View reminders on a specific channel
#[poise::command(
slash_command,
rename = "look",
identifying_name = "look",
default_member_permissions = "MANAGE_GUILD"
)]
pub async fn command(
ctx: Context<'_>,
#[description = "Channel to view reminders on"] channel: Option<PartialChannel>,
#[description = "Whether to show disabled reminders or not"] disabled: Option<bool>,
#[description = "Whether to display times as relative or exact times"] relative: Option<bool>,
) -> Result<(), Error> {
(Options { channel, disabled, relative }).run(ctx).await
}