mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-19 08:48:54 +00:00
Add leaderboard command
This commit is contained in:
parent
14efbcf16f
commit
a5d34f4dc7
3 changed files with 118 additions and 13 deletions
|
@ -20,7 +20,8 @@ use serenity::all::User;
|
||||||
"forcesave",
|
"forcesave",
|
||||||
"beatmap",
|
"beatmap",
|
||||||
"check",
|
"check",
|
||||||
"ranks"
|
"ranks",
|
||||||
|
"leaderboard"
|
||||||
)
|
)
|
||||||
)]
|
)]
|
||||||
pub async fn osu<U: HasOsuEnv>(_ctx: CmdContext<'_, U>) -> Result<()> {
|
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 = "Sort scores by"] sort: Option<SortScoreBy>,
|
||||||
#[description = "Reverse the sorting order"] reverse: Option<bool>,
|
#[description = "Reverse the sorting order"] reverse: Option<bool>,
|
||||||
#[description = "Filter the mods on the scores"] mods: Option<UnparsedMods>,
|
#[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 = "Find all scores in the beatmapset instead"] beatmapset: Option<bool>,
|
||||||
#[description = "Score listing style"] style: Option<ScoreListStyle>,
|
#[description = "Score listing style"] style: Option<ScoreListStyle>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
@ -510,7 +511,14 @@ async fn check<U: HasOsuEnv>(
|
||||||
.await?
|
.await?
|
||||||
.into_message()
|
.into_message()
|
||||||
.await?;
|
.await?;
|
||||||
args.style
|
|
||||||
|
let style = style.unwrap_or(if scores.len() <= 5 {
|
||||||
|
ScoreListStyle::Grid
|
||||||
|
} else {
|
||||||
|
ScoreListStyle::Table
|
||||||
|
});
|
||||||
|
|
||||||
|
style
|
||||||
.display_scores(
|
.display_scores(
|
||||||
scores,
|
scores,
|
||||||
beatmaps[0].1,
|
beatmaps[0].1,
|
||||||
|
@ -550,6 +558,90 @@ async fn ranks<U: HasOsuEnv>(
|
||||||
Ok(())
|
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(
|
fn arg_from_username_or_discord(
|
||||||
username: Option<String>,
|
username: Option<String>,
|
||||||
discord_name: Option<User>,
|
discord_name: Option<User>,
|
||||||
|
|
|
@ -328,7 +328,7 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, poise::ChoiceParameter)]
|
||||||
pub enum OrderBy {
|
pub enum OrderBy {
|
||||||
PP,
|
PP,
|
||||||
Score,
|
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 style = args.single::<ScoreListStyle>().unwrap_or_default();
|
||||||
let guild = msg.guild_id.expect("Guild-only command");
|
let guild = msg.guild_id.expect("Guild-only command");
|
||||||
let env = ctx.data.read().await.get::<OsuEnv>().unwrap().clone();
|
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
|
let Some((bm, _)) =
|
||||||
{
|
super::load_beatmap(&env, msg.channel_id, msg.referenced_message.as_ref()).await
|
||||||
Some((bm, _)) => bm,
|
else {
|
||||||
None => {
|
msg.reply(&ctx, "No beatmap queried on this channel.")
|
||||||
msg.reply(&ctx, "No beatmap queried on this channel.")
|
.await?;
|
||||||
.await?;
|
return Ok(());
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let scores = {
|
let scores = {
|
||||||
|
|
|
@ -414,9 +414,16 @@ impl Beatmap {
|
||||||
|
|
||||||
/// Gets a link pointing to the beatmap, in the new format.
|
/// Gets a link pointing to the beatmap, in the new format.
|
||||||
pub fn link(&self) -> String {
|
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!(
|
format!(
|
||||||
"https://osu.ppy.sh/beatmapsets/{}#{}/{}",
|
"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.
|
/// Link to the cover image of the beatmap.
|
||||||
pub fn cover_url(&self) -> String {
|
pub fn cover_url(&self) -> String {
|
||||||
format!(
|
format!(
|
||||||
|
|
Loading…
Add table
Reference in a new issue