diff --git a/youmubot-osu/src/discord/mod.rs b/youmubot-osu/src/discord/mod.rs index 1fd19c6..70dadea 100644 --- a/youmubot-osu/src/discord/mod.rs +++ b/youmubot-osu/src/discord/mod.rs @@ -19,12 +19,14 @@ mod cache; mod db; pub(crate) mod embeds; mod hook; +mod server_rank; pub use announcer::OsuAnnouncer; use db::OsuUser; use db::{OsuLastBeatmap, OsuSavedUsers}; use embeds::{beatmap_embed, score_embed, user_embed}; pub use hook::hook; +use server_rank::SERVER_RANK_COMMAND; /// The osu! client. pub(crate) struct OsuClient; @@ -68,7 +70,7 @@ pub fn setup( #[group] #[prefix = "osu"] #[description = "osu! related commands."] -#[commands(std, taiko, catch, mania, save, recent, last, check, top)] +#[commands(std, taiko, catch, mania, save, recent, last, check, top, server_rank)] struct Osu; #[command] diff --git a/youmubot-osu/src/discord/server_rank.rs b/youmubot-osu/src/discord/server_rank.rs new file mode 100644 index 0000000..3365b88 --- /dev/null +++ b/youmubot-osu/src/discord/server_rank.rs @@ -0,0 +1,71 @@ +use super::{db::OsuSavedUsers, ModeArg}; +use crate::models::Mode; +use serenity::{ + builder::EditMessage, + framework::standard::{macros::command, Args, CommandError as Error, CommandResult}, + model::channel::Message, + utils::MessageBuilder, +}; +use std::collections::HashMap; +use youmubot_prelude::*; + +#[command("ranks")] +#[description = "See the server's ranks"] +#[usage = "[mode (Std, Taiko, Catch, Mania) = Std]"] +#[max_args(1)] +#[only_in(guilds)] +pub fn server_rank(ctx: &mut Context, m: &Message, mut args: Args) -> CommandResult { + let mode = args.single::().map(|v| v.0).unwrap_or(Mode::Std); + let guild = m.guild_id.expect("Guild-only command"); + let mut users = OsuSavedUsers::open(&*ctx.data.read()) + .borrow() + .expect("DB initialized") + .iter() + .filter_map(|(user_id, osu_user)| { + guild.member(&ctx, user_id).ok().and_then(|member| { + osu_user + .pp + .get(mode as usize) + .cloned() + .and_then(|pp| pp) + .map(|pp| (pp, member.distinct())) + }) + }) + .collect::>(); + users.sort_by(|(a, _), (b, _)| (*b).partial_cmp(a).unwrap_or(std::cmp::Ordering::Equal)); + + if users.is_empty() { + m.reply(&ctx, "No saved users in the current server...")?; + return Ok(()); + } + ctx.data.get_cloned::().paginate_fn( + ctx.clone(), + m.channel_id, + move |page: u8, e: &mut EditMessage| { + let start = (page as usize) * 5; + if start >= users.len() { + return (e, Err(Error("No more items".to_owned()))); + } + let users = users.iter().skip(start).take(5); + let mut content = MessageBuilder::new(); + content + .push_line("```") + .push_line("Rank | pp | Username") + .push_line("-------------------------"); + for (id, (pp, member)) in users.enumerate() { + content + .push(format!( + "{:>4} | {:>7.2} | ", + format!("#{}", id + start), + pp + )) + .push_line_safe(member); + } + content.push("```"); + (e.content(content.build()), Ok(())) + }, + std::time::Duration::from_secs(60), + )?; + + Ok(()) +}