From 074454e5559453969e03423f69949f17c468d9fb Mon Sep 17 00:00:00 2001 From: Xyon Date: Sat, 19 Oct 2024 16:22:11 +0100 Subject: [PATCH 1/2] Add leaderboard, paginate custom responses output --- Cargo.lock | 1 + Cargo.toml | 5 +-- src/badgey/commands/custom_responses.rs | 29 ++++++++++++---- src/badgey/commands/ranks.rs | 46 +++++++++++++++++++++++-- src/badgey/models/xp.rs | 8 ++++- 5 files changed, 76 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8f2005a..243913c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -180,6 +180,7 @@ dependencies = [ "regex 1.11.0", "rust-i18n", "tokio", + "url", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 2861e7a..1f4f198 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,13 +15,14 @@ diesel = { version = "2.1.0", features = ["postgres", "r2d2", "chrono"] } diesel_migrations = "2.1.0" env_logger = "0.10.0" log = "0.4.20" -manifold = { git = "https://code.orbiter-radio.uk/discord/manifold.git" } -# manifold = { path = "/home/xyon/Workspace/manifold/" } +#manifold = { git = "https://code.orbiter-radio.uk/discord/manifold.git" } +manifold = { path = "/home/xyon/Workspace/manifold/" } poise = { version = "0.5.*", features = [ "cache" ] } rand = { version = "0.8.5", features = [ "small_rng" ] } regex = "1.9.5" rust-i18n = "3.1.2" tokio = { version = "1.16.1", features = ["sync", "macros", "rt-multi-thread"] } +url = "2.5.2" [package.metadata.i18n] # The available locales for your application, default: ["en"]. diff --git a/src/badgey/commands/custom_responses.rs b/src/badgey/commands/custom_responses.rs index eac83d2..fdd3fb5 100644 --- a/src/badgey/commands/custom_responses.rs +++ b/src/badgey/commands/custom_responses.rs @@ -2,7 +2,8 @@ use poise::serenity_prelude as serenity; use manifold::error::{ManifoldError, ManifoldResult}; use manifold::{ManifoldContext, ManifoldData}; -use poise::serenity_prelude::Mentionable; +use poise::serenity_prelude::{CreateEmbed, Mentionable}; +use url::Url; use crate::badgey::models::custom_response::{CustomResponse, CustomResponseInserter}; @@ -52,18 +53,32 @@ async fn undelete_custom_response(ctx: ManifoldContext<'_>, id: i32) -> Manifold #[poise::command(slash_command, prefix_command, required_permissions = "MODERATE_MEMBERS")] async fn list_custom_responses_for_user(ctx: ManifoldContext<'_>, target: serenity::User) -> ManifoldResult<()> { let db = &ctx.data().database; + let userinfo = &ctx.data().user_info.lock().await; - let mut answer: String = "".to_string(); + let reply_handle = ctx.reply("Retrieving custom responses, please stand by...".to_string()).await?; + let mut pages = Vec::::new(); + let responses = CustomResponse::find_by_user(db, &target)?; + let total = responses.len(); - CustomResponse::find_by_user(db, &target)?.iter().for_each(|f| { - answer.push_str(format!("{}{}", "\n", f.to_string()).as_str()); + responses.iter().enumerate().for_each(|(i, f)| { + pages.push(CreateEmbed::default() + .title(format!("Custom Response {item} of {total} for user {target}", item=(i + 1), total=&total, target=target.name)) + .description(format!("Added by {added_by} on ()", added_by=userinfo.get(&(f.added_by as u64)).unwrap().username, added_on=f.added_on)) + .field("ID", format!("{id}", id=f.id), true) + .field("Deleted", format!("{deleted}", deleted=(if f.deleted.unwrap_or(false) {"yes"} else {"no"})), true) + .field("Trigger", format!("{trigger}", trigger=f.trigger), true) + .field("Response", format!("{response}", response=f.response), false) + .image(format!("{response}", response=Url::parse(&*f.response).unwrap_or("https://example.com".parse().unwrap()))) + .to_owned() + ) }); - if answer.len() == 0 { - answer.push_str("\nNone found"); + if pages.len() == 0 { + ctx.reply(format!("No custom responses found for {target}", target=target.mention())).await?; + return Ok(()) } - ctx.reply(t!("commands.custom_response.list_user", user = &target.mention(), response_list = answer)).await?; + manifold::helpers::paginate(ctx, reply_handle, pages, 0).await?; Ok(()) } diff --git a/src/badgey/commands/ranks.rs b/src/badgey/commands/ranks.rs index a60349b..da5271d 100644 --- a/src/badgey/commands/ranks.rs +++ b/src/badgey/commands/ranks.rs @@ -1,7 +1,7 @@ use built::chrono; use manifold::error::{ManifoldError, ManifoldResult}; use manifold::{ManifoldContext, ManifoldData}; -use poise::serenity_prelude::{Mentionable, RoleId}; +use poise::serenity_prelude::{CreateEmbed, Mentionable, RoleId}; use crate::badgey::models::xp::{Rank, Track, Xp}; #[poise::command(prefix_command, slash_command, user_cooldown = 86400)] @@ -119,6 +119,46 @@ async fn rank(ctx: ManifoldContext<'_>) -> ManifoldResult<()> { Ok(()) } -pub fn commands() -> [poise::Command; 3] { - [switch_rank_track(), freeze_rank(), rank()] +#[poise::command(prefix_command, slash_command)] +async fn leaderboard(ctx: ManifoldContext<'_>) -> ManifoldResult<()> { + + let reply_handle = ctx.reply("Retrieving leaderboard, please stand by...".to_string()).await?; + let mut pages = Vec::::new(); + let leaderboard = Xp::get_leaderboard(&ctx.data().database)?; + let total = leaderboard.len(); + let pages_needed = (total / 10) + 1; + + for i in 0..pages_needed { + let mut page = CreateEmbed::default() + .title(format!("XP Leaderboard Page {page} of {total_pages}", page=(i + 1), total_pages=&pages_needed)).to_owned(); + + let mut fields = Vec::new(); + + fields.push(("Rank", "".to_string(), true)); + fields.push(("User", "".to_string(), true)); + fields.push(("XP", "".to_string(), true)); + + leaderboard.iter().skip(i*10).enumerate().for_each(|(i, f)| { + fields.push(("", format!("{rank}", rank=(i+1)), true)); + fields.push(("", format!("<@{id}>", id=f.user_id), true)); + fields.push(("", format!("{xp}", xp=f.xp_value), true)); + }); + + page.fields(fields); + + pages.push(page); + } + + if pages.len() == 0 { + ctx.reply("No leaderboard entries yet!".to_string()).await?; + return Ok(()) + } + + manifold::helpers::paginate(ctx, reply_handle, pages, 0).await?; + + Ok(()) +} + +pub fn commands() -> [poise::Command; 4] { + [switch_rank_track(), freeze_rank(), rank(), leaderboard()] } diff --git a/src/badgey/models/xp.rs b/src/badgey/models/xp.rs index 2883c6f..ffd13a6 100644 --- a/src/badgey/models/xp.rs +++ b/src/badgey/models/xp.rs @@ -27,7 +27,7 @@ pub struct Xp { pub rank_track: i64, pub rank_track_last_changed: Option, pub freeze_rank: Option, - pub freeze_rank_last_changed: Option + pub freeze_rank_last_changed: Option, } #[derive(Queryable, Selectable, Identifiable, Debug, Clone)] @@ -119,6 +119,12 @@ impl Xp { Ok(()) } + pub fn get_leaderboard(conn: &Db) -> ManifoldResult> { + Ok(xp_table::dsl::xp + .order_by(xp::xp_value.desc()) + .load::(&mut conn.get()?)?) + } + pub async fn award(ctx: &Context, fctx: &FrameworkContext<'_, ManifoldData, ManifoldError>, msg: &Message, db: &Db) -> ManifoldResult<()>{ if fctx.user_data().await.user_info.lock().await.get_mut(&msg.author.id.as_u64()).is_none() { debug!("Tried to add XP to a user we don't know about, aborting."); -- 2.30.2 From 6c3b4c6ad722f7511a1eed9c2efdcb603f114aa3 Mon Sep 17 00:00:00 2001 From: Xyon Date: Sat, 19 Oct 2024 16:23:30 +0100 Subject: [PATCH 2/2] Don't use development copy of manifold in prod bot --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1f4f198..5194156 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,8 +15,8 @@ diesel = { version = "2.1.0", features = ["postgres", "r2d2", "chrono"] } diesel_migrations = "2.1.0" env_logger = "0.10.0" log = "0.4.20" -#manifold = { git = "https://code.orbiter-radio.uk/discord/manifold.git" } -manifold = { path = "/home/xyon/Workspace/manifold/" } +manifold = { git = "https://code.orbiter-radio.uk/discord/manifold.git" } +# manifold = { path = "/home/xyon/Workspace/manifold/" } poise = { version = "0.5.*", features = [ "cache" ] } rand = { version = "0.8.5", features = [ "small_rng" ] } regex = "1.9.5" -- 2.30.2