From 9b54fba5e5db1032ac1f215c48689120bc6d5210 Mon Sep 17 00:00:00 2001 From: jellywx Date: Tue, 26 Oct 2021 20:11:19 +0100 Subject: [PATCH] Revert "turned pager into a single type" This reverts commit 4490f19c --- src/commands/reminder_cmds.rs | 17 +- src/commands/todo_cmds.rs | 4 +- src/component_models/mod.rs | 82 +++------ src/component_models/pager.rs | 321 ++++++++++++++++++++++++++++------ 4 files changed, 300 insertions(+), 124 deletions(-) diff --git a/src/commands/reminder_cmds.rs b/src/commands/reminder_cmds.rs index f06367a..b046011 100644 --- a/src/commands/reminder_cmds.rs +++ b/src/commands/reminder_cmds.rs @@ -8,16 +8,12 @@ use chrono::NaiveDateTime; use chrono_tz::Tz; use num_integer::Integer; use regex_command_attr::command; -use serenity::{ - builder::CreateEmbed, - client::Context, - model::{channel::Channel, id::UserId}, -}; +use serenity::{builder::CreateEmbed, client::Context, model::channel::Channel}; use crate::{ check_subscription_on_message, component_models::{ - pager::{DelData, LookData, Pager}, + pager::{DelPager, LookPager, Pager}, ComponentDataModel, DelSelector, }, consts::{ @@ -333,7 +329,7 @@ async fn look(ctx: &Context, invoke: &mut CommandInvoke, args: CommandOptions) { .fold(0, |t, r| t + r.len()) .div_ceil(EMBED_DESCRIPTION_MAX_LENGTH); - let pager = Pager::new(0, LookData { flags, timezone }); + let pager = LookPager::new(flags, timezone); invoke .respond( @@ -367,7 +363,7 @@ async fn delete(ctx: &Context, invoke: &mut CommandInvoke, _args: CommandOptions let reminders = Reminder::from_guild(ctx, invoke.guild_id(), invoke.author_id()).await; - let resp = show_delete_page(&reminders, 0, timezone, invoke.author_id()); + let resp = show_delete_page(&reminders, 0, timezone); let _ = invoke.respond(&ctx, resp).await; } @@ -398,9 +394,8 @@ pub fn show_delete_page( reminders: &[Reminder], page: usize, timezone: Tz, - author_id: UserId, ) -> CreateGenericResponse { - let pager = Pager::new(page, DelData { author_id, timezone }); + let pager = DelPager::new(page, timezone); if reminders.is_empty() { return CreateGenericResponse::new() @@ -455,7 +450,7 @@ pub fn show_delete_page( let display = display_vec.join("\n"); - let del_selector = ComponentDataModel::DelSelector(DelSelector { page, timezone, author_id }); + let del_selector = ComponentDataModel::DelSelector(DelSelector { page, timezone }); CreateGenericResponse::new() .embed(|e| { diff --git a/src/commands/todo_cmds.rs b/src/commands/todo_cmds.rs index abde1c4..789ee69 100644 --- a/src/commands/todo_cmds.rs +++ b/src/commands/todo_cmds.rs @@ -3,7 +3,7 @@ use serenity::client::Context; use crate::{ component_models::{ - pager::{Pager, TodoData}, + pager::{Pager, TodoPager}, ComponentDataModel, TodoSelector, }, consts::{EMBED_DESCRIPTION_MAX_LENGTH, SELECT_MAX_ENTRIES, THEME_COLOR}, @@ -136,7 +136,7 @@ pub fn show_todo_page( channel_id: Option, guild_id: Option, ) -> CreateGenericResponse { - let pager = Pager::new(page, TodoData { user_id, channel_id, guild_id }); + let pager = TodoPager::new(page, user_id, channel_id, guild_id); let pages = max_todo_page(todo_values); let mut page = page; diff --git a/src/component_models/mod.rs b/src/component_models/mod.rs index b13d95e..d0ba9d9 100644 --- a/src/component_models/mod.rs +++ b/src/component_models/mod.rs @@ -1,4 +1,4 @@ -pub mod pager; +pub(crate) mod pager; use std::io::Cursor; @@ -21,7 +21,7 @@ use crate::{ reminder_cmds::{max_delete_page, show_delete_page}, todo_cmds::{max_todo_page, show_todo_page}, }, - component_models::pager::{DelData, LookData, Pager, TodoData}, + component_models::pager::{DelPager, LookPager, Pager, TodoPager}, consts::{EMBED_DESCRIPTION_MAX_LENGTH, THEME_COLOR}, framework::CommandInvoke, models::reminder::Reminder, @@ -29,15 +29,15 @@ use crate::{ }; #[derive(Deserialize, Serialize)] -#[serde(untagged)] +#[serde(tag = "type")] +#[repr(u8)] pub enum ComponentDataModel { Restrict(Restrict), + LookPager(LookPager), + DelPager(DelPager), + TodoPager(TodoPager), DelSelector(DelSelector), TodoSelector(TodoSelector), - LookPager(Pager), - DelPager(Pager), - TodoPager(Pager), - MacroPager(Pager), } impl ComponentDataModel { @@ -90,20 +90,11 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id .await .unwrap(); } else { - component - .create_interaction_response(&ctx, |r| { - r.kind(InteractionResponseType::ChannelMessageWithSource) - .interaction_response_data(|response| response - .flags(InteractionApplicationCommandCallbackDataFlags::EPHEMERAL) - .content("Only the original command user can interact with this message") - ) - }) - .await - .unwrap(); + // tell them they cant do this } } ComponentDataModel::LookPager(pager) => { - let flags = pager.data.flags; + let flags = pager.flags; let channel_opt = component.channel_id.to_channel_cached(&ctx); @@ -121,7 +112,7 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id let pages = reminders .iter() - .map(|reminder| reminder.display(&flags, &pager.data.timezone)) + .map(|reminder| reminder.display(&flags, &pager.timezone)) .fold(0, |t, r| t + r.len()) .div_ceil(EMBED_DESCRIPTION_MAX_LENGTH); @@ -139,7 +130,7 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id let display = reminders .iter() - .map(|reminder| reminder.display(&flags, &pager.data.timezone)) + .map(|reminder| reminder.display(&flags, &pager.timezone)) .skip_while(|p| { skip_char_count += p.len(); @@ -178,33 +169,15 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id .await; } ComponentDataModel::DelPager(pager) => { - if component.user.id == pager.data.author_id { - let reminders = - Reminder::from_guild(ctx, component.guild_id, component.user.id).await; + let reminders = + Reminder::from_guild(ctx, component.guild_id, component.user.id).await; - let max_pages = max_delete_page(&reminders, &pager.data.timezone); + let max_pages = max_delete_page(&reminders, &pager.timezone); - let resp = show_delete_page( - &reminders, - pager.next_page(max_pages), - pager.data.timezone, - pager.data.author_id, - ); + let resp = show_delete_page(&reminders, pager.next_page(max_pages), pager.timezone); - let mut invoke = CommandInvoke::component(component); - let _ = invoke.respond(&ctx, resp).await; - } else { - component - .create_interaction_response(&ctx, |r| { - r.kind(InteractionResponseType::ChannelMessageWithSource) - .interaction_response_data(|response| response - .flags(InteractionApplicationCommandCallbackDataFlags::EPHEMERAL) - .content("Only the original command user can interact with this message") - ) - }) - .await - .unwrap(); - } + let mut invoke = CommandInvoke::component(component); + let _ = invoke.respond(&ctx, resp).await; } ComponentDataModel::DelSelector(selector) => { let pool = ctx.data.read().await.get::().cloned().unwrap(); @@ -218,12 +191,7 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id let reminders = Reminder::from_guild(ctx, component.guild_id, component.user.id).await; - let resp = show_delete_page( - &reminders, - selector.page, - selector.timezone, - selector.author_id, - ); + let resp = show_delete_page(&reminders, selector.page, selector.timezone); let mut invoke = CommandInvoke::component(component); let _ = invoke.respond(&ctx, resp).await; @@ -234,9 +202,9 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id let values = sqlx::query!( // fucking braindead mysql use <=> instead of = for null comparison "SELECT id, value FROM todos WHERE user_id <=> ? AND channel_id <=> ? AND guild_id <=> ?", - pager.data.user_id, - pager.data.channel_id, - pager.data.guild_id, + pager.user_id, + pager.channel_id, + pager.guild_id, ) .fetch_all(&pool) .await @@ -250,9 +218,9 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id let resp = show_todo_page( &values, pager.next_page(max_pages), - pager.data.user_id, - pager.data.channel_id, - pager.data.guild_id, + pager.user_id, + pager.channel_id, + pager.guild_id, ); let mut invoke = CommandInvoke::component(component); @@ -292,7 +260,6 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id let mut invoke = CommandInvoke::component(component); let _ = invoke.respond(&ctx, resp).await; } - ComponentDataModel::MacroPager(pager) => {} } } } @@ -308,7 +275,6 @@ pub struct Restrict { pub struct DelSelector { pub page: usize, pub timezone: Tz, - pub author_id: UserId, } #[derive(Serialize, Deserialize)] diff --git a/src/component_models/pager.rs b/src/component_models/pager.rs index af46854..0d41ab0 100644 --- a/src/component_models/pager.rs +++ b/src/component_models/pager.rs @@ -1,30 +1,37 @@ +// todo split pager out into a single struct use chrono_tz::Tz; -use rmp_serde::Serializer; use serde::{Deserialize, Serialize}; use serde_repr::*; -use serenity::{ - builder::CreateComponents, - model::{id::UserId, interactions::message_component::ButtonStyle}, -}; +use serenity::{builder::CreateComponents, model::interactions::message_component::ButtonStyle}; use crate::{component_models::ComponentDataModel, models::reminder::look_flags::LookFlags}; -#[derive(Serialize, Deserialize)] -pub struct Pager { - pub page: usize, - action: PageAction, - pub data: D, +pub trait Pager { + fn next_page(&self, max_pages: usize) -> usize; + + fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents); } -impl Pager -where - D: Serialize + Clone, -{ - pub fn new(page: usize, data: D) -> Self { - Self { page, action: PageAction::Refresh, data } - } +#[derive(Serialize_repr, Deserialize_repr)] +#[repr(u8)] +enum PageAction { + First = 0, + Previous = 1, + Refresh = 2, + Next = 3, + Last = 4, +} - pub fn next_page(&self, max_pages: usize) -> usize { +#[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), @@ -34,26 +41,11 @@ where } } - pub fn to_custom_id(&self) -> String { - let mut buf = Vec::new(); - self.serialize(&mut Serializer::new(&mut buf)).unwrap(); - base64::encode(buf) - } - - fn buttons(&self, page: usize) -> (Pager, Pager, Pager, Pager, Pager) { - ( - Pager { page, action: PageAction::First, data: self.data.clone() }, - Pager { page, action: PageAction::Previous, data: self.data.clone() }, - Pager { page, action: PageAction::Refresh, data: self.data.clone() }, - Pager { page, action: PageAction::Next, data: self.data.clone() }, - Pager { page, action: PageAction::Last, data: self.data.clone() }, - ) - } - - pub fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents) { + 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_refresh, page_next, page_last) = self.buttons(next_page); + let (page_first, page_prev, page_refresh, page_next, page_last) = + LookPager::buttons(self.flags, next_page, self.timezone); comp.create_action_row(|row| { row.create_button(|b| { @@ -87,31 +79,254 @@ where } } -#[derive(Serialize_repr, Deserialize_repr)] -#[repr(u8)] -enum PageAction { - First = 0, - Previous = 1, - Refresh = 2, - Next = 3, - Last = 4, +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, + ) { + ( + 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::Refresh, + timezone, + }), + ComponentDataModel::LookPager(LookPager { + flags, + page, + action: PageAction::Next, + timezone, + }), + ComponentDataModel::LookPager(LookPager { + flags, + page, + action: PageAction::Last, + timezone, + }), + ) + } } -#[derive(Deserialize, Serialize, Clone)] -pub struct LookData { - pub flags: LookFlags, +#[derive(Serialize, Deserialize)] +pub struct DelPager { + pub page: usize, + action: PageAction, pub timezone: Tz, } -#[derive(Deserialize, Serialize, Clone)] -pub struct DelData { - pub author_id: UserId, - 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::Refresh => self.page, + 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_refresh, 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_refresh.to_custom_id()) + }) + .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) + }) + }); + } } -#[derive(Deserialize, Serialize, Clone)] -pub struct TodoData { +impl DelPager { + pub fn new(page: usize, timezone: Tz) -> Self { + Self { page, action: PageAction::Refresh, timezone } + } + + pub fn buttons( + page: usize, + timezone: Tz, + ) -> ( + ComponentDataModel, + 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::Refresh, timezone }), + ComponentDataModel::DelPager(DelPager { page, action: PageAction::Next, timezone }), + ComponentDataModel::DelPager(DelPager { page, action: PageAction::Last, timezone }), + ) + } +} + +#[derive(Deserialize, Serialize)] +pub struct TodoPager { + pub page: usize, + action: PageAction, pub user_id: Option, pub channel_id: Option, pub guild_id: Option, } + +impl Pager for TodoPager { + fn next_page(&self, max_pages: usize) -> usize { + match self.action { + PageAction::First => 0, + PageAction::Previous => 0.max(self.page - 1), + PageAction::Refresh => self.page, + 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_refresh, page_next, page_last) = + TodoPager::buttons(next_page, self.user_id, self.channel_id, self.guild_id); + + 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_refresh.to_custom_id()) + }) + .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 TodoPager { + pub fn new( + page: usize, + user_id: Option, + channel_id: Option, + guild_id: Option, + ) -> Self { + Self { page, action: PageAction::Refresh, user_id, channel_id, guild_id } + } + + pub fn buttons( + page: usize, + user_id: Option, + channel_id: Option, + guild_id: Option, + ) -> ( + ComponentDataModel, + ComponentDataModel, + ComponentDataModel, + ComponentDataModel, + ComponentDataModel, + ) { + ( + ComponentDataModel::TodoPager(TodoPager { + page, + action: PageAction::First, + user_id, + channel_id, + guild_id, + }), + ComponentDataModel::TodoPager(TodoPager { + page, + action: PageAction::Previous, + user_id, + channel_id, + guild_id, + }), + ComponentDataModel::TodoPager(TodoPager { + page, + action: PageAction::Refresh, + user_id, + channel_id, + guild_id, + }), + ComponentDataModel::TodoPager(TodoPager { + page, + action: PageAction::Next, + user_id, + channel_id, + guild_id, + }), + ComponentDataModel::TodoPager(TodoPager { + page, + action: PageAction::Last, + user_id, + channel_id, + guild_id, + }), + ) + } +}