|
1 | 1 | use crate::built_info; |
2 | 2 | use lazy_static::lazy_static; |
| 3 | +use poise::CreateReply; |
| 4 | +use poise::serenity_prelude::CreateActionRow; |
3 | 5 | use reqwest::header::HeaderMap; |
4 | 6 | use serenity::all::RoleId; |
| 7 | +use serenity::builder::{ |
| 8 | + CreateButton, CreateEmbed, CreateInteractionResponse, CreateInteractionResponseMessage, |
| 9 | +}; |
5 | 10 | use std::env; |
6 | 11 | use std::sync::Arc; |
| 12 | +use std::time::Duration; |
7 | 13 |
|
8 | 14 | pub type CommandError = anyhow::Error; |
9 | 15 | pub type CommandContext<'a> = poise::Context<'a, CommandData, CommandError>; |
@@ -89,3 +95,67 @@ pub async fn is_user_trusted_or_above(ctx: CommandContext<'_>) -> CheckResult { |
89 | 95 |
|
90 | 96 | Ok(false) |
91 | 97 | } |
| 98 | + |
| 99 | +pub async fn paginate<U, E>( |
| 100 | + ctx: poise::Context<'_, U, E>, |
| 101 | + pages: &[&str], |
| 102 | +) -> Result<(), serenity::Error> { |
| 103 | + // Define some unique identifiers for the navigation buttons |
| 104 | + let ctx_id = ctx.id(); |
| 105 | + let author_id = ctx.author().id; |
| 106 | + let prev_button_id = format!("{}prev", ctx_id); |
| 107 | + let next_button_id = format!("{}next", ctx_id); |
| 108 | + |
| 109 | + // Send the embed with the first page as content |
| 110 | + let reply = { |
| 111 | + let components = CreateActionRow::Buttons(vec![ |
| 112 | + CreateButton::new(&prev_button_id).emoji('◀'), |
| 113 | + CreateButton::new(&next_button_id).emoji('▶'), |
| 114 | + ]); |
| 115 | + |
| 116 | + CreateReply::default() |
| 117 | + .embed(CreateEmbed::default().description(pages[0])) |
| 118 | + .components(vec![components]) |
| 119 | + }; |
| 120 | + |
| 121 | + ctx.send(reply).await?; |
| 122 | + |
| 123 | + // Loop through incoming interactions with the navigation buttons |
| 124 | + let mut current_page = 0; |
| 125 | + while let Some(press) = serenity::collector::ComponentInteractionCollector::new(ctx) |
| 126 | + // We defined our button IDs to start with `ctx_id`. If they don't, some other command's |
| 127 | + // button was pressed |
| 128 | + .filter(move |press| { |
| 129 | + press.data.custom_id.starts_with(&ctx_id.to_string()) && press.user.id == author_id |
| 130 | + }) |
| 131 | + // Timeout when no navigation button has been pressed for 24 hours |
| 132 | + .timeout(Duration::from_secs(3600 * 24)) |
| 133 | + .await |
| 134 | + { |
| 135 | + // Depending on which button was pressed, go to next or previous page |
| 136 | + if press.data.custom_id == next_button_id { |
| 137 | + current_page += 1; |
| 138 | + if current_page >= pages.len() { |
| 139 | + current_page = 0; |
| 140 | + } |
| 141 | + } else if press.data.custom_id == prev_button_id { |
| 142 | + current_page = current_page.checked_sub(1).unwrap_or(pages.len() - 1); |
| 143 | + } else { |
| 144 | + // This is an unrelated button interaction |
| 145 | + continue; |
| 146 | + } |
| 147 | + |
| 148 | + // Update the message with the new page contents |
| 149 | + press |
| 150 | + .create_response( |
| 151 | + ctx.serenity_context(), |
| 152 | + CreateInteractionResponse::UpdateMessage( |
| 153 | + CreateInteractionResponseMessage::new() |
| 154 | + .embed(CreateEmbed::new().description(pages[current_page])), |
| 155 | + ), |
| 156 | + ) |
| 157 | + .await?; |
| 158 | + } |
| 159 | + |
| 160 | + Ok(()) |
| 161 | +} |
0 commit comments