mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-19 08:48:54 +00:00
Use grid throughout the commands
This commit is contained in:
parent
ba8b835cc2
commit
f27939546e
4 changed files with 188 additions and 60 deletions
|
@ -1,7 +1,126 @@
|
||||||
pub use beatmapset::display_beatmapset;
|
pub use beatmapset::display_beatmapset;
|
||||||
pub use scores::table::display_scores_table;
|
pub use scores::ScoreListStyle;
|
||||||
|
|
||||||
mod scores {
|
mod scores {
|
||||||
|
use crate::models::{Mode, Score};
|
||||||
|
use serenity::{framework::standard::CommandResult, model::channel::Message};
|
||||||
|
use youmubot_prelude::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
/// The style for the scores list to be displayed.
|
||||||
|
pub enum ScoreListStyle {
|
||||||
|
Table,
|
||||||
|
Grid,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ScoreListStyle {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Table
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::str::FromStr for ScoreListStyle {
|
||||||
|
type Err = Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"--table" => Ok(Self::Table),
|
||||||
|
"--grid" => Ok(Self::Grid),
|
||||||
|
_ => Err(Error::msg("unknown value")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ScoreListStyle {
|
||||||
|
pub async fn display_scores<'a>(
|
||||||
|
self,
|
||||||
|
scores: Vec<Score>,
|
||||||
|
mode: Mode,
|
||||||
|
ctx: &'a Context,
|
||||||
|
m: &'a Message,
|
||||||
|
) -> CommandResult {
|
||||||
|
match self {
|
||||||
|
ScoreListStyle::Table => table::display_scores_table(scores, mode, ctx, m).await,
|
||||||
|
ScoreListStyle::Grid => grid::display_scores_grid(scores, mode, ctx, m).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod grid {
|
||||||
|
use crate::discord::{
|
||||||
|
cache::save_beatmap, BeatmapCache, BeatmapMetaCache, BeatmapWithMode,
|
||||||
|
};
|
||||||
|
use crate::models::{Mode, Score};
|
||||||
|
use serenity::{framework::standard::CommandResult, model::channel::Message};
|
||||||
|
use youmubot_prelude::*;
|
||||||
|
|
||||||
|
pub async fn display_scores_grid<'a>(
|
||||||
|
scores: Vec<Score>,
|
||||||
|
mode: Mode,
|
||||||
|
ctx: &'a Context,
|
||||||
|
m: &'a Message,
|
||||||
|
) -> CommandResult {
|
||||||
|
if scores.is_empty() {
|
||||||
|
m.reply(&ctx, "No plays found").await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
paginate_reply(
|
||||||
|
Paginate { scores, mode },
|
||||||
|
ctx,
|
||||||
|
m,
|
||||||
|
std::time::Duration::from_secs(60),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Paginate {
|
||||||
|
scores: Vec<Score>,
|
||||||
|
mode: Mode,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl pagination::Paginate for Paginate {
|
||||||
|
async fn render(&mut self, page: u8, ctx: &Context, msg: &mut Message) -> Result<bool> {
|
||||||
|
let data = ctx.data.read().await;
|
||||||
|
let client = data.get::<crate::discord::OsuClient>().unwrap();
|
||||||
|
let osu = data.get::<BeatmapMetaCache>().unwrap();
|
||||||
|
let beatmap_cache = data.get::<BeatmapCache>().unwrap();
|
||||||
|
let page = page as usize;
|
||||||
|
let score = &self.scores[page];
|
||||||
|
|
||||||
|
let hourglass = msg.react(ctx, '⌛').await?;
|
||||||
|
let mode = self.mode;
|
||||||
|
let beatmap = osu.get_beatmap(score.beatmap_id, mode).await?;
|
||||||
|
let content = beatmap_cache.get_beatmap(beatmap.beatmap_id).await?;
|
||||||
|
let bm = BeatmapWithMode(beatmap, mode);
|
||||||
|
let user = client
|
||||||
|
.user(crate::request::UserID::ID(score.user_id), |f| f)
|
||||||
|
.await?
|
||||||
|
.ok_or_else(|| Error::msg("user not found"))?;
|
||||||
|
|
||||||
|
msg.edit(ctx, |e| {
|
||||||
|
e.embed(|e| {
|
||||||
|
crate::discord::embeds::score_embed(score, &bm, &content, &user)
|
||||||
|
.footer(format!("Page {}/{}", page + 1, self.scores.len()))
|
||||||
|
.build(e)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
save_beatmap(&*ctx.data.read().await, msg.channel_id, &bm).await?;
|
||||||
|
|
||||||
|
// End
|
||||||
|
hourglass.delete(ctx).await?;
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn len(&self) -> Option<usize> {
|
||||||
|
Some(self.scores.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub mod table {
|
pub mod table {
|
||||||
use crate::discord::{Beatmap, BeatmapCache, BeatmapInfo, BeatmapMetaCache};
|
use crate::discord::{Beatmap, BeatmapCache, BeatmapInfo, BeatmapMetaCache};
|
||||||
use crate::models::{Mode, Score};
|
use crate::models::{Mode, Score};
|
||||||
|
|
|
@ -169,6 +169,7 @@ pub(crate) struct ScoreEmbedBuilder<'a> {
|
||||||
u: &'a User,
|
u: &'a User,
|
||||||
top_record: Option<u8>,
|
top_record: Option<u8>,
|
||||||
world_record: Option<u16>,
|
world_record: Option<u16>,
|
||||||
|
footer: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ScoreEmbedBuilder<'a> {
|
impl<'a> ScoreEmbedBuilder<'a> {
|
||||||
|
@ -180,6 +181,10 @@ impl<'a> ScoreEmbedBuilder<'a> {
|
||||||
self.world_record = Some(rank);
|
self.world_record = Some(rank);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
pub fn footer(&mut self, footer: impl Into<String>) -> &mut Self {
|
||||||
|
self.footer = Some(footer.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn score_embed<'a>(
|
pub(crate) fn score_embed<'a>(
|
||||||
|
@ -195,12 +200,13 @@ pub(crate) fn score_embed<'a>(
|
||||||
u,
|
u,
|
||||||
top_record: None,
|
top_record: None,
|
||||||
world_record: None,
|
world_record: None,
|
||||||
|
footer: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ScoreEmbedBuilder<'a> {
|
impl<'a> ScoreEmbedBuilder<'a> {
|
||||||
#[allow(clippy::many_single_char_names)]
|
#[allow(clippy::many_single_char_names)]
|
||||||
pub fn build<'b>(&self, m: &'b mut CreateEmbed) -> &'b mut CreateEmbed {
|
pub fn build<'b>(&mut self, m: &'b mut CreateEmbed) -> &'b mut CreateEmbed {
|
||||||
let mode = self.bm.mode();
|
let mode = self.bm.mode();
|
||||||
let b = &self.bm.0;
|
let b = &self.bm.0;
|
||||||
let s = self.s;
|
let s = self.s;
|
||||||
|
@ -358,8 +364,12 @@ impl<'a> ScoreEmbedBuilder<'a> {
|
||||||
)
|
)
|
||||||
.field("Map stats", diff.format_info(mode, s.mods, b), false)
|
.field("Map stats", diff.format_info(mode, s.mods, b), false)
|
||||||
.timestamp(&s.date);
|
.timestamp(&s.date);
|
||||||
|
let mut footer = self.footer.take().unwrap_or_else(String::new);
|
||||||
if mode.to_oppai_mode().is_none() && s.mods != Mods::NOMOD {
|
if mode.to_oppai_mode().is_none() && s.mods != Mods::NOMOD {
|
||||||
m.footer(|f| f.text("Star difficulty does not reflect game mods."));
|
footer += " Star difficulty does not reflect game mods.";
|
||||||
|
}
|
||||||
|
if !footer.is_empty() {
|
||||||
|
m.footer(|f| f.text(footer));
|
||||||
}
|
}
|
||||||
m
|
m
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
discord::beatmap_cache::BeatmapMetaCache,
|
discord::beatmap_cache::BeatmapMetaCache,
|
||||||
discord::display::display_scores_table as list_scores,
|
discord::display::ScoreListStyle,
|
||||||
discord::oppai_cache::{BeatmapCache, BeatmapInfo},
|
discord::oppai_cache::{BeatmapCache, BeatmapInfo},
|
||||||
models::{Beatmap, Mode, Mods, User},
|
models::{Beatmap, Mode, Mods, User},
|
||||||
request::UserID,
|
request::UserID,
|
||||||
|
@ -32,7 +32,7 @@ use db::OsuUser;
|
||||||
use db::{OsuLastBeatmap, OsuSavedUsers, OsuUserBests};
|
use db::{OsuLastBeatmap, OsuSavedUsers, OsuUserBests};
|
||||||
use embeds::{beatmap_embed, score_embed, user_embed};
|
use embeds::{beatmap_embed, score_embed, user_embed};
|
||||||
pub use hook::hook;
|
pub use hook::hook;
|
||||||
use server_rank::{LEADERBOARD_COMMAND, SERVER_RANK_COMMAND, UPDATE_LEADERBOARD_COMMAND};
|
use server_rank::{SERVER_RANK_COMMAND, UPDATE_LEADERBOARD_COMMAND};
|
||||||
|
|
||||||
/// The osu! client.
|
/// The osu! client.
|
||||||
pub(crate) struct OsuClient;
|
pub(crate) struct OsuClient;
|
||||||
|
@ -108,7 +108,6 @@ pub fn setup(
|
||||||
check,
|
check,
|
||||||
top,
|
top,
|
||||||
server_rank,
|
server_rank,
|
||||||
leaderboard,
|
|
||||||
update_leaderboard
|
update_leaderboard
|
||||||
)]
|
)]
|
||||||
#[default_command(std)]
|
#[default_command(std)]
|
||||||
|
@ -315,13 +314,15 @@ impl FromStr for Nth {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
|
#[aliases("rs", "rc")]
|
||||||
#[description = "Gets an user's recent play"]
|
#[description = "Gets an user's recent play"]
|
||||||
#[usage = "#[the nth recent play = --all] / [mode (std, taiko, mania, catch) = std] / [username / user id = your saved id]"]
|
#[usage = "#[the nth recent play = --all] / [style (table or grid) = --table] / [mode (std, taiko, mania, catch) = std] / [username / user id = your saved id]"]
|
||||||
#[example = "#1 / taiko / natsukagami"]
|
#[example = "#1 / taiko / natsukagami"]
|
||||||
#[max_args(3)]
|
#[max_args(4)]
|
||||||
pub async fn recent(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
pub async fn recent(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||||
let data = ctx.data.read().await;
|
let data = ctx.data.read().await;
|
||||||
let nth = args.single::<Nth>().unwrap_or(Nth::All);
|
let nth = args.single::<Nth>().unwrap_or(Nth::All);
|
||||||
|
let style = args.single::<ScoreListStyle>().unwrap_or_default();
|
||||||
let mode = args.single::<ModeArg>().unwrap_or(ModeArg(Mode::Std)).0;
|
let mode = args.single::<ModeArg>().unwrap_or(ModeArg(Mode::Std)).0;
|
||||||
let user = to_user_id_query(args.single::<UsernameArg>().ok(), &*data, msg).await?;
|
let user = to_user_id_query(args.single::<UsernameArg>().ok(), &*data, msg).await?;
|
||||||
|
|
||||||
|
@ -361,7 +362,7 @@ pub async fn recent(ctx: &Context, msg: &Message, mut args: Args) -> CommandResu
|
||||||
let plays = osu
|
let plays = osu
|
||||||
.user_recent(UserID::ID(user.id), |f| f.mode(mode).limit(50))
|
.user_recent(UserID::ID(user.id), |f| f.mode(mode).limit(50))
|
||||||
.await?;
|
.await?;
|
||||||
list_scores(plays, mode, ctx, msg).await?;
|
style.display_scores(plays, mode, ctx, msg).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -433,9 +434,9 @@ pub async fn last(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
#[aliases("c", "chk")]
|
#[aliases("c", "chk")]
|
||||||
#[usage = "[username or tag = yourself]"]
|
#[usage = "[style (table or grid) = --table] / [username or tag = yourself]"]
|
||||||
#[description = "Check your own or someone else's best record on the last beatmap. Also stores the result if possible."]
|
#[description = "Check your own or someone else's best record on the last beatmap. Also stores the result if possible."]
|
||||||
#[max_args(1)]
|
#[max_args(2)]
|
||||||
pub async fn check(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
pub async fn check(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||||
let data = ctx.data.read().await;
|
let data = ctx.data.read().await;
|
||||||
let bm = cache::get_beatmap(&*data, msg.channel_id).await?;
|
let bm = cache::get_beatmap(&*data, msg.channel_id).await?;
|
||||||
|
@ -448,6 +449,7 @@ pub async fn check(ctx: &Context, msg: &Message, mut args: Args) -> CommandResul
|
||||||
Some(bm) => {
|
Some(bm) => {
|
||||||
let b = &bm.0;
|
let b = &bm.0;
|
||||||
let m = bm.1;
|
let m = bm.1;
|
||||||
|
let style = args.single::<ScoreListStyle>().unwrap_or_default();
|
||||||
let username_arg = args.single::<UsernameArg>().ok();
|
let username_arg = args.single::<UsernameArg>().ok();
|
||||||
let user_id = match username_arg.as_ref() {
|
let user_id = match username_arg.as_ref() {
|
||||||
Some(UsernameArg::Tagged(v)) => Some(*v),
|
Some(UsernameArg::Tagged(v)) => Some(*v),
|
||||||
|
@ -457,9 +459,6 @@ pub async fn check(ctx: &Context, msg: &Message, mut args: Args) -> CommandResul
|
||||||
let user = to_user_id_query(username_arg, &*data, msg).await?;
|
let user = to_user_id_query(username_arg, &*data, msg).await?;
|
||||||
|
|
||||||
let osu = data.get::<OsuClient>().unwrap();
|
let osu = data.get::<OsuClient>().unwrap();
|
||||||
let oppai = data.get::<BeatmapCache>().unwrap();
|
|
||||||
|
|
||||||
let content = oppai.get_beatmap(b.beatmap_id).await?;
|
|
||||||
|
|
||||||
let user = osu
|
let user = osu
|
||||||
.user(user, |f| f)
|
.user(user, |f| f)
|
||||||
|
@ -473,22 +472,16 @@ pub async fn check(ctx: &Context, msg: &Message, mut args: Args) -> CommandResul
|
||||||
msg.reply(&ctx, "No scores found").await?;
|
msg.reply(&ctx, "No scores found").await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for score in scores.iter() {
|
|
||||||
msg.channel_id
|
|
||||||
.send_message(&ctx, |c| {
|
|
||||||
c.embed(|m| score_embed(&score, &bm, &content, &user).build(m))
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(user_id) = user_id {
|
if let Some(user_id) = user_id {
|
||||||
// Save to database
|
// Save to database
|
||||||
data.get::<OsuUserBests>()
|
data.get::<OsuUserBests>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.save(user_id, m, scores)
|
.save(user_id, m, scores.clone())
|
||||||
.await
|
.await
|
||||||
.pls_ok();
|
.pls_ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
style.display_scores(scores, m, ctx, msg).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,12 +490,13 @@ pub async fn check(ctx: &Context, msg: &Message, mut args: Args) -> CommandResul
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
#[description = "Get the n-th top record of an user."]
|
#[description = "Get the n-th top record of an user."]
|
||||||
#[usage = "[mode (std, taiko, catch, mania)] = std / #[n-th = --all] / [username or user_id = your saved user id]"]
|
#[usage = "#[n-th = --all] / [style (table or grid) = --table] / [mode (std, taiko, catch, mania)] = std / [username or user_id = your saved user id]"]
|
||||||
#[example = "taiko / #2 / natsukagami"]
|
#[example = "#2 / taiko / natsukagami"]
|
||||||
#[max_args(3)]
|
#[max_args(4)]
|
||||||
pub async fn top(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
pub async fn top(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||||
let data = ctx.data.read().await;
|
let data = ctx.data.read().await;
|
||||||
let nth = args.single::<Nth>().unwrap_or(Nth::All);
|
let nth = args.single::<Nth>().unwrap_or(Nth::All);
|
||||||
|
let style = args.single::<ScoreListStyle>().unwrap_or_default();
|
||||||
let mode = args
|
let mode = args
|
||||||
.single::<ModeArg>()
|
.single::<ModeArg>()
|
||||||
.map(|ModeArg(t)| t)
|
.map(|ModeArg(t)| t)
|
||||||
|
@ -555,7 +549,7 @@ pub async fn top(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult
|
||||||
let plays = osu
|
let plays = osu
|
||||||
.user_best(UserID::ID(user.id), |f| f.mode(mode).limit(100))
|
.user_best(UserID::ID(user.id), |f| f.mode(mode).limit(100))
|
||||||
.await?;
|
.await?;
|
||||||
list_scores(plays, mode, ctx, msg).await?;
|
style.display_scores(plays, mode, ctx, msg).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -5,6 +5,7 @@ use super::{
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
discord::{
|
discord::{
|
||||||
|
display::ScoreListStyle,
|
||||||
oppai_cache::{BeatmapCache, OppaiAccuracy},
|
oppai_cache::{BeatmapCache, OppaiAccuracy},
|
||||||
BeatmapWithMode,
|
BeatmapWithMode,
|
||||||
},
|
},
|
||||||
|
@ -151,23 +152,33 @@ enum OrderBy {
|
||||||
Score,
|
Score,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for OrderBy {
|
impl Default for OrderBy {
|
||||||
fn from(s: &str) -> Self {
|
fn default() -> Self {
|
||||||
if s == "--score" {
|
Self::Score
|
||||||
Self::Score
|
}
|
||||||
} else {
|
}
|
||||||
Self::PP
|
|
||||||
|
impl std::str::FromStr for OrderBy {
|
||||||
|
type Err = Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"--score" => Ok(OrderBy::Score),
|
||||||
|
"--pp" => Ok(OrderBy::PP),
|
||||||
|
_ => Err(Error::msg("unknown value")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command("updatelb")]
|
#[command("leaderboard")]
|
||||||
#[description = "Update the leaderboard on the last seen beatmap"]
|
#[aliases("lb", "bmranks", "br", "cc", "updatelb")]
|
||||||
#[usage = "[--score to sort by score, default to sort by pp]"]
|
#[usage = "[--score to sort by score, default to sort by pp] / [--table to show a table, --grid to show score by score]"]
|
||||||
#[max_args(1)]
|
#[description = "See the server's ranks on the last seen beatmap"]
|
||||||
|
#[max_args(2)]
|
||||||
#[only_in(guilds)]
|
#[only_in(guilds)]
|
||||||
pub async fn update_leaderboard(ctx: &Context, m: &Message, args: Args) -> CommandResult {
|
pub async fn update_leaderboard(ctx: &Context, m: &Message, mut args: Args) -> CommandResult {
|
||||||
let sort_order = OrderBy::from(args.rest());
|
let sort_order = args.single::<OrderBy>().unwrap_or_default();
|
||||||
|
let style = args.single::<ScoreListStyle>().unwrap_or_default();
|
||||||
|
|
||||||
let guild = m.guild_id.unwrap();
|
let guild = m.guild_id.unwrap();
|
||||||
let data = ctx.data.read().await;
|
let data = ctx.data.read().await;
|
||||||
|
@ -246,27 +257,7 @@ pub async fn update_leaderboard(ctx: &Context, m: &Message, args: Args) -> Comma
|
||||||
.await
|
.await
|
||||||
.ok();
|
.ok();
|
||||||
drop(update_lock);
|
drop(update_lock);
|
||||||
show_leaderboard(ctx, m, bm, sort_order).await
|
show_leaderboard(ctx, m, bm, sort_order, style).await
|
||||||
}
|
|
||||||
|
|
||||||
#[command("leaderboard")]
|
|
||||||
#[aliases("lb", "bmranks", "br", "cc")]
|
|
||||||
#[usage = "[--score to sort by score, default to sort by pp]"]
|
|
||||||
#[description = "See the server's ranks on the last seen beatmap"]
|
|
||||||
#[max_args(1)]
|
|
||||||
#[only_in(guilds)]
|
|
||||||
pub async fn leaderboard(ctx: &Context, m: &Message, args: Args) -> CommandResult {
|
|
||||||
let sort_order = OrderBy::from(args.rest());
|
|
||||||
|
|
||||||
let data = ctx.data.read().await;
|
|
||||||
let bm = match get_beatmap(&*data, m.channel_id).await? {
|
|
||||||
Some(bm) => bm,
|
|
||||||
None => {
|
|
||||||
m.reply(&ctx, "No beatmap queried on this channel.").await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
show_leaderboard(ctx, m, bm, sort_order).await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn show_leaderboard(
|
async fn show_leaderboard(
|
||||||
|
@ -274,6 +265,7 @@ async fn show_leaderboard(
|
||||||
m: &Message,
|
m: &Message,
|
||||||
bm: BeatmapWithMode,
|
bm: BeatmapWithMode,
|
||||||
order: OrderBy,
|
order: OrderBy,
|
||||||
|
style: ScoreListStyle,
|
||||||
) -> CommandResult {
|
) -> CommandResult {
|
||||||
let data = ctx.data.read().await;
|
let data = ctx.data.read().await;
|
||||||
|
|
||||||
|
@ -381,6 +373,19 @@ async fn show_leaderboard(
|
||||||
.await?;
|
.await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let ScoreListStyle::Grid = style {
|
||||||
|
style
|
||||||
|
.display_scores(
|
||||||
|
scores.into_iter().map(|(_, _, a)| a).collect(),
|
||||||
|
mode,
|
||||||
|
ctx,
|
||||||
|
m,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
paginate_reply_fn(
|
paginate_reply_fn(
|
||||||
move |page: u8, ctx: &Context, m: &mut Message| {
|
move |page: u8, ctx: &Context, m: &mut Message| {
|
||||||
const ITEMS_PER_PAGE: usize = 5;
|
const ITEMS_PER_PAGE: usize = 5;
|
||||||
|
|
Loading…
Add table
Reference in a new issue