look command pager
This commit is contained in:
@ -14,12 +14,14 @@ use serenity::{
|
||||
model::{
|
||||
channel::{Channel, Message},
|
||||
id::ChannelId,
|
||||
interactions::message_component::ButtonStyle,
|
||||
misc::Mentionable,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
check_subscription_on_message,
|
||||
component_models::{ComponentDataModel, LookPager, PageAction},
|
||||
consts::{
|
||||
EMBED_DESCRIPTION_MAX_LENGTH, REGEX_CHANNEL_USER, REGEX_NATURAL_COMMAND_1,
|
||||
REGEX_NATURAL_COMMAND_2, REGEX_REMIND_COMMAND, THEME_COLOR,
|
||||
@ -296,6 +298,12 @@ async fn look(ctx: &Context, invoke: &(dyn CommandInvoke + Send + Sync), args: C
|
||||
invoke.channel_id()
|
||||
};
|
||||
|
||||
let channel_name = if let Some(Channel::Guild(channel)) = channel_id.to_channel_cached(&ctx) {
|
||||
Some(channel.name)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let reminders = Reminder::from_channel(ctx, channel_id, &flags).await;
|
||||
|
||||
if reminders.is_empty() {
|
||||
@ -325,35 +333,84 @@ 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 _ = invoke
|
||||
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,
|
||||
});
|
||||
|
||||
invoke
|
||||
.respond(
|
||||
ctx.http.clone(),
|
||||
CreateGenericResponse::new()
|
||||
.embed(|e| {
|
||||
e.title(format!("Reminders on {}", channel_id.mention()))
|
||||
.description(display)
|
||||
.footer(|f| f.text(format!("Page {} of {}", 1, pages)))
|
||||
e.title(format!(
|
||||
"Reminders{}",
|
||||
channel_name.map_or(String::new(), |n| format!(" on #{}", n))
|
||||
))
|
||||
.description(display)
|
||||
.footer(|f| f.text(format!("Page {} of {}", 1, pages)))
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
.components(|comp| {
|
||||
comp.create_action_row(|row| {
|
||||
row.create_button(|b| b.label("⏮️").custom_id(".1"))
|
||||
.create_button(|b| b.label("◀️").custom_id(".2"))
|
||||
.create_button(|b| b.label("▶️").custom_id(".3"))
|
||||
.create_button(|b| b.label("⏭️").custom_id(".4"))
|
||||
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)
|
||||
})
|
||||
})
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[command("del")]
|
||||
#[description("Delete reminders")]
|
||||
#[permission_level(Managed)]
|
||||
async fn delete(ctx: &Context, msg: &Message, _args: String) {
|
||||
let (pool, lm) = get_ctx_data(&ctx).await;
|
||||
|
||||
let user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap();
|
||||
async fn delete(ctx: &Context, invoke: &(dyn CommandInvoke + Send + Sync)) {
|
||||
let pool = ctx.data.read().await.get::<SQLPool>().cloned().unwrap();
|
||||
|
||||
let _ = msg.channel_id.say(&ctx, lm.get(&user_data.language, "del/listing")).await;
|
||||
|
||||
@ -417,19 +474,6 @@ DELETE FROM reminders WHERE FIND_IN_SET(id, ?)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
if let Some(guild_id) = msg.guild_id {
|
||||
let _ = sqlx::query!(
|
||||
"
|
||||
INSERT INTO events (event_name, bulk_count, guild_id, user_id) VALUES ('delete', ?, ?, ?)
|
||||
",
|
||||
count_row.count,
|
||||
guild_id.as_u64(),
|
||||
user_data.id
|
||||
)
|
||||
.execute(&pool)
|
||||
.await;
|
||||
}
|
||||
|
||||
let content = lm.get(&user_data.language, "del/count").replacen(
|
||||
"{}",
|
||||
&count_row.count.to_string(),
|
||||
|
@ -1,13 +1,28 @@
|
||||
use std::io::Cursor;
|
||||
|
||||
use chrono_tz::Tz;
|
||||
use rmp_serde::Serializer;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serenity::model::{
|
||||
id::{ChannelId, RoleId},
|
||||
interactions::message_component::MessageComponentInteraction,
|
||||
use serenity::{
|
||||
builder::CreateEmbed,
|
||||
client::Context,
|
||||
model::{
|
||||
channel::Channel,
|
||||
id::{ChannelId, RoleId},
|
||||
interactions::{
|
||||
message_component::{ButtonStyle, MessageComponentInteraction},
|
||||
InteractionResponseType,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::models::reminder::look_flags::LookFlags;
|
||||
use crate::{
|
||||
consts::{EMBED_DESCRIPTION_MAX_LENGTH, THEME_COLOR},
|
||||
models::{
|
||||
reminder::{look_flags::LookFlags, Reminder},
|
||||
user_data::UserData,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(tag = "type")]
|
||||
@ -29,23 +44,160 @@ impl ComponentDataModel {
|
||||
rmp_serde::from_read(cur).unwrap()
|
||||
}
|
||||
|
||||
pub async fn act(&self, component: MessageComponentInteraction) {
|
||||
pub async fn act(&self, ctx: &Context, component: MessageComponentInteraction) {
|
||||
match self {
|
||||
ComponentDataModel::Restrict(restrict) => {
|
||||
println!("{:?}", component.data.values);
|
||||
}
|
||||
ComponentDataModel::LookPager(pager) => {}
|
||||
ComponentDataModel::LookPager(pager) => {
|
||||
let flags = pager.flags;
|
||||
|
||||
let channel_opt = component.channel_id.to_channel_cached(&ctx);
|
||||
|
||||
let channel_id = if let Some(Channel::Guild(channel)) = channel_opt {
|
||||
if Some(channel.guild_id) == component.guild_id {
|
||||
flags.channel_id.unwrap_or(component.channel_id)
|
||||
} else {
|
||||
component.channel_id
|
||||
}
|
||||
} else {
|
||||
component.channel_id
|
||||
};
|
||||
|
||||
let reminders = Reminder::from_channel(ctx, channel_id, &flags).await;
|
||||
|
||||
let pages = reminders
|
||||
.iter()
|
||||
.map(|reminder| reminder.display(&flags, &pager.timezone))
|
||||
.fold(0, |t, r| t + r.len())
|
||||
.div_ceil(EMBED_DESCRIPTION_MAX_LENGTH) as u16;
|
||||
|
||||
let channel_name =
|
||||
if let Some(Channel::Guild(channel)) = channel_id.to_channel_cached(&ctx) {
|
||||
Some(channel.name)
|
||||
} else {
|
||||
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 mut char_count = 0;
|
||||
let mut skip_char_count = 0;
|
||||
|
||||
let display = reminders
|
||||
.iter()
|
||||
.map(|reminder| reminder.display(&flags, &pager.timezone))
|
||||
.skip_while(|p| {
|
||||
skip_char_count += p.len();
|
||||
|
||||
skip_char_count < EMBED_DESCRIPTION_MAX_LENGTH * next_page as usize
|
||||
})
|
||||
.take_while(|p| {
|
||||
char_count += p.len();
|
||||
|
||||
char_count < EMBED_DESCRIPTION_MAX_LENGTH
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.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!(
|
||||
"Reminders{}",
|
||||
channel_name.map_or(String::new(), |n| format!(" on #{}", n))
|
||||
))
|
||||
.description(display)
|
||||
.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)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Restrict {
|
||||
pub role_id: RoleId,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub enum PageAction {
|
||||
First = 0,
|
||||
Previous = 1,
|
||||
Next = 2,
|
||||
Last = 3,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct LookPager {
|
||||
pub flags: LookFlags,
|
||||
pub page_request: u16,
|
||||
pub page: u16,
|
||||
pub action: PageAction,
|
||||
pub timezone: Tz,
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
// todo move framework to its own module, split out permission checks
|
||||
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
hash::{Hash, Hasher},
|
||||
|
@ -258,7 +258,7 @@ DELETE FROM guilds WHERE guild = ?
|
||||
}
|
||||
Interaction::MessageComponent(component) => {
|
||||
let component_model = ComponentDataModel::from_custom_id(&component.data.custom_id);
|
||||
component_model.act(component).await;
|
||||
component_model.act(&ctx, component).await;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -3,13 +3,13 @@ use serenity::model::id::ChannelId;
|
||||
|
||||
use crate::consts::REGEX_CHANNEL;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
|
||||
pub enum TimeDisplayType {
|
||||
Absolute = 0,
|
||||
Relative = 1,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
|
||||
pub struct LookFlags {
|
||||
pub show_disabled: bool,
|
||||
pub channel_id: Option<ChannelId>,
|
||||
|
Reference in New Issue
Block a user