Add paging for list commands
This commit is contained in:
@ -4,7 +4,7 @@ use crate::{consts::THEME_COLOR, Context, Error};
|
||||
#[poise::command(slash_command)]
|
||||
pub async fn help(ctx: Context<'_>) -> Result<(), Error> {
|
||||
ctx.send(|m| {
|
||||
m.embed(|e| {
|
||||
m.ephemeral(true).embed(|e| {
|
||||
e.title("Help")
|
||||
.color(THEME_COLOR)
|
||||
.footer(|f| {
|
||||
@ -59,7 +59,7 @@ __Advanced Commands__
|
||||
pub async fn info(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let current_user = ctx.discord().cache.current_user();
|
||||
|
||||
ctx.send(|m| m
|
||||
ctx.send(|m| m.ephemeral(true)
|
||||
.embed(|e| e
|
||||
.title("Info")
|
||||
.color(THEME_COLOR)
|
||||
|
@ -1,8 +1,19 @@
|
||||
use poise::{serenity::constants::MESSAGE_CODE_LIMIT, CreateReply};
|
||||
use poise::{
|
||||
serenity_prelude,
|
||||
serenity_prelude::{
|
||||
application::component::ButtonStyle,
|
||||
constants::MESSAGE_CODE_LIMIT,
|
||||
interaction::{message_component::MessageComponentInteraction, InteractionResponseType},
|
||||
CreateActionRow, CreateEmbed, GuildId, UserId,
|
||||
},
|
||||
CreateReply,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
consts::THEME_COLOR,
|
||||
models::sound::{Sound, SoundCtx},
|
||||
Context, Error,
|
||||
Context, Data, Error,
|
||||
};
|
||||
|
||||
fn format_search_results<'a>(search_results: Vec<Sound>) -> CreateReply<'a> {
|
||||
@ -32,37 +43,31 @@ pub async fn list_sounds(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Copy)]
|
||||
enum ListContext {
|
||||
User = 0,
|
||||
Guild = 1,
|
||||
}
|
||||
|
||||
impl ListContext {
|
||||
pub fn title(&self) -> &'static str {
|
||||
match self {
|
||||
ListContext::User => "Your sounds",
|
||||
ListContext::Guild => "Server sounds",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Show the sounds uploaded to this server
|
||||
#[poise::command(slash_command, rename = "server", guild_only = true)]
|
||||
pub async fn list_guild_sounds(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let sounds;
|
||||
let mut message_buffer;
|
||||
let pager = SoundPager {
|
||||
nonce: 0,
|
||||
page: 0,
|
||||
context: ListContext::Guild,
|
||||
};
|
||||
|
||||
sounds = ctx.data().guild_sounds(ctx.guild_id().unwrap()).await?;
|
||||
|
||||
message_buffer = "Sounds on this server: ".to_string();
|
||||
|
||||
// todo change this to iterator
|
||||
for sound in sounds {
|
||||
message_buffer.push_str(
|
||||
format!(
|
||||
"**{}** ({}), ",
|
||||
sound.name,
|
||||
if sound.public { "🔓" } else { "🔒" }
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
|
||||
if message_buffer.len() > 2000 {
|
||||
ctx.say(message_buffer).await?;
|
||||
|
||||
message_buffer = "".to_string();
|
||||
}
|
||||
}
|
||||
|
||||
if message_buffer.len() > 0 {
|
||||
ctx.say(message_buffer).await?;
|
||||
}
|
||||
pager.reply(ctx).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -70,36 +75,181 @@ pub async fn list_guild_sounds(ctx: Context<'_>) -> Result<(), Error> {
|
||||
/// Show all sounds you have uploaded
|
||||
#[poise::command(slash_command, rename = "user", guild_only = true)]
|
||||
pub async fn list_user_sounds(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let sounds;
|
||||
let mut message_buffer;
|
||||
let pager = SoundPager {
|
||||
nonce: 0,
|
||||
page: 0,
|
||||
context: ListContext::User,
|
||||
};
|
||||
|
||||
sounds = ctx.data().user_sounds(ctx.author().id).await?;
|
||||
pager.reply(ctx).await?;
|
||||
|
||||
message_buffer = "Sounds on this server: ".to_string();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// todo change this to iterator
|
||||
for sound in sounds {
|
||||
message_buffer.push_str(
|
||||
format!(
|
||||
"**{}** ({}), ",
|
||||
sound.name,
|
||||
if sound.public { "🔓" } else { "🔒" }
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct SoundPager {
|
||||
nonce: u64,
|
||||
page: u64,
|
||||
context: ListContext,
|
||||
}
|
||||
|
||||
if message_buffer.len() > 2000 {
|
||||
ctx.say(message_buffer).await?;
|
||||
|
||||
message_buffer = "".to_string();
|
||||
impl SoundPager {
|
||||
async fn get_page(
|
||||
&self,
|
||||
data: &Data,
|
||||
user_id: UserId,
|
||||
guild_id: GuildId,
|
||||
) -> Result<Vec<Sound>, sqlx::Error> {
|
||||
match self.context {
|
||||
ListContext::User => data.user_sounds(user_id, Some(self.page)).await,
|
||||
ListContext::Guild => data.guild_sounds(guild_id, Some(self.page)).await,
|
||||
}
|
||||
}
|
||||
|
||||
if message_buffer.len() > 0 {
|
||||
ctx.say(message_buffer).await?;
|
||||
fn create_action_row(&self, max_page: u64) -> CreateActionRow {
|
||||
let mut row = CreateActionRow::default();
|
||||
|
||||
row.create_button(|b| {
|
||||
b.custom_id(
|
||||
serde_json::to_string(&SoundPager {
|
||||
nonce: 0,
|
||||
page: 0,
|
||||
context: self.context,
|
||||
})
|
||||
.unwrap(),
|
||||
)
|
||||
.style(ButtonStyle::Primary)
|
||||
.label("⏪")
|
||||
.disabled(self.page == 0)
|
||||
})
|
||||
.create_button(|b| {
|
||||
b.custom_id(
|
||||
serde_json::to_string(&SoundPager {
|
||||
nonce: 1,
|
||||
page: self.page.saturating_sub(1),
|
||||
context: self.context,
|
||||
})
|
||||
.unwrap(),
|
||||
)
|
||||
.style(ButtonStyle::Secondary)
|
||||
.label("◀️")
|
||||
.disabled(self.page == 0)
|
||||
})
|
||||
.create_button(|b| {
|
||||
b.custom_id("pid")
|
||||
.style(ButtonStyle::Success)
|
||||
.label(format!("Page {}", self.page + 1))
|
||||
.disabled(true)
|
||||
})
|
||||
.create_button(|b| {
|
||||
b.custom_id(
|
||||
serde_json::to_string(&SoundPager {
|
||||
nonce: 2,
|
||||
page: self.page.saturating_add(1),
|
||||
context: self.context,
|
||||
})
|
||||
.unwrap(),
|
||||
)
|
||||
.style(ButtonStyle::Secondary)
|
||||
.label("▶️")
|
||||
.disabled(self.page == max_page)
|
||||
})
|
||||
.create_button(|b| {
|
||||
b.custom_id(
|
||||
serde_json::to_string(&SoundPager {
|
||||
nonce: 3,
|
||||
page: max_page,
|
||||
context: self.context,
|
||||
})
|
||||
.unwrap(),
|
||||
)
|
||||
.style(ButtonStyle::Primary)
|
||||
.label("⏩")
|
||||
.disabled(self.page == max_page)
|
||||
});
|
||||
|
||||
row
|
||||
}
|
||||
|
||||
Ok(())
|
||||
fn embed(&self, sounds: &[Sound], count: u64) -> CreateEmbed {
|
||||
let mut embed = CreateEmbed::default();
|
||||
|
||||
embed
|
||||
.color(THEME_COLOR)
|
||||
.title(self.context.title())
|
||||
.description(format!("**{}** sounds:", count))
|
||||
.fields(sounds.iter().map(|s| {
|
||||
(
|
||||
s.name.as_str(),
|
||||
if s.public { "*Public*" } else { "*Private*" },
|
||||
true,
|
||||
)
|
||||
}));
|
||||
|
||||
embed
|
||||
}
|
||||
|
||||
pub async fn handle_interaction(
|
||||
ctx: &serenity_prelude::Context,
|
||||
data: &Data,
|
||||
interaction: &MessageComponentInteraction,
|
||||
) -> Result<(), Error> {
|
||||
let user_id = interaction.user.id;
|
||||
let guild_id = interaction.guild_id.unwrap();
|
||||
|
||||
match serde_json::from_str::<Self>(&interaction.data.custom_id) {
|
||||
Ok(pager) => {
|
||||
let sounds = pager.get_page(data, user_id, guild_id).await?;
|
||||
let count = match pager.context {
|
||||
ListContext::User => data.count_user_sounds(user_id).await?,
|
||||
ListContext::Guild => data.count_guild_sounds(guild_id).await?,
|
||||
};
|
||||
|
||||
interaction
|
||||
.create_interaction_response(&ctx, |r| {
|
||||
r.kind(InteractionResponseType::UpdateMessage)
|
||||
.interaction_response_data(|d| {
|
||||
d.ephemeral(true)
|
||||
.add_embed(pager.embed(&sounds, count))
|
||||
.components(|c| {
|
||||
c.add_action_row(pager.create_action_row(count / 25))
|
||||
})
|
||||
})
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Err(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
async fn reply(&self, ctx: Context<'_>) -> Result<(), Error> {
|
||||
let sounds = self
|
||||
.get_page(ctx.data(), ctx.author().id, ctx.guild_id().unwrap())
|
||||
.await?;
|
||||
let count = match self.context {
|
||||
ListContext::User => ctx.data().count_user_sounds(ctx.author().id).await?,
|
||||
ListContext::Guild => {
|
||||
ctx.data()
|
||||
.count_guild_sounds(ctx.guild_id().unwrap())
|
||||
.await?
|
||||
}
|
||||
};
|
||||
|
||||
ctx.send(|r| {
|
||||
r.ephemeral(true)
|
||||
.embed(|e| {
|
||||
*e = self.embed(&sounds, count);
|
||||
e
|
||||
})
|
||||
.components(|c| c.add_action_row(self.create_action_row(count / 25)))
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Search for sounds
|
||||
|
Reference in New Issue
Block a user