mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-09 20:20:29 +00:00
Add leaderboard command
This commit is contained in:
parent
5d9fda682e
commit
ba74465ca7
3 changed files with 118 additions and 13 deletions
|
@ -20,7 +20,8 @@ use serenity::all::User;
|
|||
"forcesave",
|
||||
"beatmap",
|
||||
"check",
|
||||
"ranks"
|
||||
"ranks",
|
||||
"leaderboard"
|
||||
)
|
||||
)]
|
||||
pub async fn osu<U: HasOsuEnv>(_ctx: CmdContext<'_, U>) -> Result<()> {
|
||||
|
@ -429,7 +430,7 @@ async fn check<U: HasOsuEnv>(
|
|||
#[description = "Sort scores by"] sort: Option<SortScoreBy>,
|
||||
#[description = "Reverse the sorting order"] reverse: Option<bool>,
|
||||
#[description = "Filter the mods on the scores"] mods: Option<UnparsedMods>,
|
||||
#[description = "Filter the mode of the scores"] mode: Option<Mode>,
|
||||
#[description = "Filter the gamemode of the scores"] mode: Option<Mode>,
|
||||
#[description = "Find all scores in the beatmapset instead"] beatmapset: Option<bool>,
|
||||
#[description = "Score listing style"] style: Option<ScoreListStyle>,
|
||||
) -> Result<()> {
|
||||
|
@ -510,7 +511,14 @@ async fn check<U: HasOsuEnv>(
|
|||
.await?
|
||||
.into_message()
|
||||
.await?;
|
||||
args.style
|
||||
|
||||
let style = style.unwrap_or(if scores.len() <= 5 {
|
||||
ScoreListStyle::Grid
|
||||
} else {
|
||||
ScoreListStyle::Table
|
||||
});
|
||||
|
||||
style
|
||||
.display_scores(
|
||||
scores,
|
||||
beatmaps[0].1,
|
||||
|
@ -550,6 +558,90 @@ async fn ranks<U: HasOsuEnv>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Display the leaderboard on a single map of members in the server.
|
||||
#[poise::command(slash_command, guild_only)]
|
||||
async fn leaderboard<U: HasOsuEnv>(
|
||||
ctx: CmdContext<'_, U>,
|
||||
#[description = "The link or shortlink of the map"] map: Option<String>,
|
||||
#[description = "Sort scores by"] sort: Option<server_rank::OrderBy>,
|
||||
#[description = "Reverse the ordering"] reverse: Option<bool>,
|
||||
#[description = "Include unranked scores"] unranked: Option<bool>,
|
||||
#[description = "Filter the gamemode of the scores"] mode: Option<Mode>,
|
||||
#[description = "Score listing style"] style: Option<ScoreListStyle>,
|
||||
) -> Result<()> {
|
||||
let env = ctx.data().osu_env();
|
||||
let guild = ctx.partial_guild().await.unwrap();
|
||||
let style = style.unwrap_or_default();
|
||||
|
||||
let bm = match parse_map_input(ctx.channel_id(), env, map, mode, None).await? {
|
||||
EmbedType::Beatmap(beatmap, _, _) => {
|
||||
let nmode = beatmap.mode.with_override(mode);
|
||||
BeatmapWithMode(*beatmap, nmode)
|
||||
}
|
||||
EmbedType::Beatmapset(_) => return Err(Error::msg("invalid map link")),
|
||||
};
|
||||
|
||||
ctx.defer().await?;
|
||||
|
||||
let mut scores = server_rank::get_leaderboard(
|
||||
ctx.serenity_context(),
|
||||
env,
|
||||
&bm,
|
||||
unranked.unwrap_or(false),
|
||||
sort.unwrap_or(server_rank::OrderBy::PP),
|
||||
guild.id,
|
||||
)
|
||||
.await?;
|
||||
if reverse == Some(true) {
|
||||
scores.reverse();
|
||||
}
|
||||
|
||||
let beatmap = &bm.0;
|
||||
if scores.is_empty() {
|
||||
ctx.reply(format!(
|
||||
"No scores have been recorded in **{}** on [`{}`]({}).",
|
||||
guild.name,
|
||||
beatmap.short_link(mode, Mods::NOMOD),
|
||||
beatmap.link()
|
||||
))
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let header = format!(
|
||||
"Here are the top scores of **{}** on {}",
|
||||
guild.name,
|
||||
beatmap.mention(mode, Mods::NOMOD),
|
||||
);
|
||||
|
||||
match style {
|
||||
ScoreListStyle::Table => {
|
||||
let reply = ctx.reply(header).await?.into_message().await?;
|
||||
server_rank::display_rankings_table(
|
||||
ctx.serenity_context(),
|
||||
reply,
|
||||
scores,
|
||||
&bm,
|
||||
sort.unwrap_or_default(),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
ScoreListStyle::Grid => {
|
||||
let reply = ctx.reply(header).await?.into_message().await?;
|
||||
style
|
||||
.display_scores(
|
||||
scores.into_iter().map(|s| s.score).collect(),
|
||||
bm.1,
|
||||
ctx.serenity_context(),
|
||||
Some(guild.id),
|
||||
reply,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn arg_from_username_or_discord(
|
||||
username: Option<String>,
|
||||
discord_name: Option<User>,
|
||||
|
|
|
@ -328,7 +328,7 @@ where
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, poise::ChoiceParameter)]
|
||||
pub enum OrderBy {
|
||||
PP,
|
||||
Score,
|
||||
|
@ -376,14 +376,12 @@ pub async fn show_leaderboard(ctx: &Context, msg: &Message, mut args: Args) -> C
|
|||
let style = args.single::<ScoreListStyle>().unwrap_or_default();
|
||||
let guild = msg.guild_id.expect("Guild-only command");
|
||||
let env = ctx.data.read().await.get::<OsuEnv>().unwrap().clone();
|
||||
let bm = match super::load_beatmap(&env, msg.channel_id, msg.referenced_message.as_ref()).await
|
||||
{
|
||||
Some((bm, _)) => bm,
|
||||
None => {
|
||||
msg.reply(&ctx, "No beatmap queried on this channel.")
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
let Some((bm, _)) =
|
||||
super::load_beatmap(&env, msg.channel_id, msg.referenced_message.as_ref()).await
|
||||
else {
|
||||
msg.reply(&ctx, "No beatmap queried on this channel.")
|
||||
.await?;
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let scores = {
|
||||
|
|
|
@ -414,9 +414,16 @@ impl Beatmap {
|
|||
|
||||
/// Gets a link pointing to the beatmap, in the new format.
|
||||
pub fn link(&self) -> String {
|
||||
self.mode_link(None)
|
||||
}
|
||||
|
||||
/// Gets a link pointing to the beatmap, in the new format, with overridable mode.
|
||||
pub fn mode_link(&self, mode: Option<Mode>) -> String {
|
||||
format!(
|
||||
"https://osu.ppy.sh/beatmapsets/{}#{}/{}",
|
||||
self.beatmapset_id, NEW_MODE_NAMES[self.mode as usize], self.beatmap_id
|
||||
self.beatmapset_id,
|
||||
NEW_MODE_NAMES[self.mode.with_override(mode) as usize],
|
||||
self.beatmap_id
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -443,6 +450,14 @@ impl Beatmap {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn mention(&self, override_mode: Option<Mode>, mods: &Mods) -> String {
|
||||
format!(
|
||||
"[`{}`]({})",
|
||||
self.short_link(override_mode, mods),
|
||||
self.mode_link(override_mode),
|
||||
)
|
||||
}
|
||||
|
||||
/// Link to the cover image of the beatmap.
|
||||
pub fn cover_url(&self) -> String {
|
||||
format!(
|
||||
|
|
Loading…
Add table
Reference in a new issue