From 73ead8d50ad49cfba0c5497e7cd003dfe84e7acc Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Tue, 31 Dec 2024 02:48:36 +0100 Subject: [PATCH] Add recent command --- youmubot-osu/src/discord/commands.rs | 85 +++++++++++++++++++++++++++- youmubot-osu/src/discord/mod.rs | 10 +++- 2 files changed, 89 insertions(+), 6 deletions(-) diff --git a/youmubot-osu/src/discord/commands.rs b/youmubot-osu/src/discord/commands.rs index 9e6e8c0..77dff2a 100644 --- a/youmubot-osu/src/discord/commands.rs +++ b/youmubot-osu/src/discord/commands.rs @@ -1,10 +1,9 @@ use super::*; use poise::CreateReply; use serenity::all::User; -use youmubot_prelude::*; /// osu!-related command group. -#[poise::command(slash_command, subcommands("profile", "top"))] +#[poise::command(slash_command, subcommands("profile", "top", "recent"))] pub async fn osu(_ctx: CmdContext<'_, U>) -> Result<()> { Ok(()) } @@ -64,7 +63,7 @@ async fn top( ctx.send({ CreateReply::default() .content(format!( - "Here is the #{} top play by {}", + "Here is the #{} top play by {}!", nth + 1, user.mention() )) @@ -134,6 +133,86 @@ async fn profile( Ok(()) } +/// Returns recent plays from a given player. +/// +/// If no osu! username is given, defaults to the currently registered user. +#[poise::command(slash_command)] +async fn recent( + ctx: CmdContext<'_, U>, + #[description = "Index of the score"] + #[min = 1] + #[max = 50] + index: Option, + #[description = "Score listing style"] style: Option, + #[description = "Game mode"] mode: Option, + #[description = "osu! username"] username: Option, + #[description = "Discord username"] discord_name: Option, +) -> Result<()> { + let env = ctx.data().osu_env(); + let args = arg_from_username_or_discord(username, discord_name); + let style = style.unwrap_or(ScoreListStyle::Table); + + let ListingArgs { + nth, + style, + mode, + user, + } = ListingArgs::from_params(env, index, style, mode, args, ctx.author().id).await?; + + ctx.defer().await?; + + let osu_client = &env.client; + let plays = osu_client + .user_recent(UserID::ID(user.id), |f| f.mode(mode).limit(50)) + .await?; + match nth { + Nth::All => { + let reply = ctx + .clone() + .reply(format!("Here are the recent plays by {}!", user.mention())) + .await? + .into_message() + .await?; + style + .display_scores(plays, mode, ctx.serenity_context(), reply.guild_id, reply) + .await?; + } + Nth::Nth(nth) => { + let Some(play) = plays.get(nth as usize) else { + Err(Error::msg("No such play"))? + }; + let attempts = plays + .iter() + .skip(nth as usize) + .take_while(|p| p.beatmap_id == play.beatmap_id && p.mods == play.mods) + .count(); + let beatmap = env.beatmaps.get_beatmap(play.beatmap_id, mode).await?; + let content = env.oppai.get_beatmap(beatmap.beatmap_id).await?; + let beatmap_mode = BeatmapWithMode(beatmap, mode); + + ctx.send( + CreateReply::default() + .content(format!( + "Here is the #{} recent play by {}!", + nth + 1, + user.mention() + )) + .embed( + score_embed(play, &beatmap_mode, &content, user) + .footer(format!("Attempt #{}", attempts)) + .build(), + ) + .components(vec![score_components(ctx.guild_id())]), + ) + .await?; + + // Save the beatmap... + cache::save_beatmap(&env, ctx.channel_id(), &beatmap_mode).await?; + } + } + Ok(()) +} + fn arg_from_username_or_discord( username: Option, discord_name: Option, diff --git a/youmubot-osu/src/discord/mod.rs b/youmubot-osu/src/discord/mod.rs index cba91b7..fb62325 100644 --- a/youmubot-osu/src/discord/mod.rs +++ b/youmubot-osu/src/discord/mod.rs @@ -675,7 +675,7 @@ pub async fn recent(ctx: &Context, msg: &Message, mut args: Args) -> CommandResu let reply = msg .reply( ctx, - format!("Here are the recent plays by `{}`!", user.username), + format!("Here are the recent plays by {}!", user.mention()), ) .await?; style @@ -699,7 +699,11 @@ pub async fn recent(ctx: &Context, msg: &Message, mut args: Args) -> CommandResu .send_message( &ctx, CreateMessage::new() - .content("Here is the play that you requested".to_string()) + .content(format!( + "Here is the #{} recent play by {}!", + nth + 1, + user.mention() + )) .embed( score_embed(play, &beatmap_mode, &content, user) .footer(format!("Attempt #{}", attempts)) @@ -1007,7 +1011,7 @@ pub async fn top(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult .send_message(&ctx, { CreateMessage::new() .content(format!( - "Here is the #{} top play by {}", + "Here is the #{} top play by {}!", nth + 1, user.mention() ))