From eba1bb324c3beca3d573939542ec14de6a031424 Mon Sep 17 00:00:00 2001 From: Natsu Kagami Date: Sun, 14 Jun 2020 19:51:26 -0400 Subject: [PATCH] Handle score_embed --- youmubot-osu/src/discord/announcer.rs | 24 ++++++++--------- youmubot-osu/src/discord/embeds.rs | 38 ++++++++++++++++++++++----- youmubot-osu/src/discord/mod.rs | 19 +++++++++----- 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/youmubot-osu/src/discord/announcer.rs b/youmubot-osu/src/discord/announcer.rs index b69a5f2..2949e02 100644 --- a/youmubot-osu/src/discord/announcer.rs +++ b/youmubot-osu/src/discord/announcer.rs @@ -2,6 +2,7 @@ use super::db::{OsuSavedUsers, OsuUser}; use super::{embeds::score_embed, BeatmapWithMode, OsuClient}; use crate::{ discord::beatmap_cache::BeatmapMetaCache, + discord::oppai_cache::BeatmapCache, models::{Mode, Score}, request::UserID, Client as Osu, @@ -24,6 +25,7 @@ pub const ANNOUNCER_KEY: &'static str = "osu"; pub fn updates(c: Arc, d: AppData, channels: MemberToChannels) -> CommandResult { let osu = d.get_cloned::(); let cache = d.get_cloned::(); + let oppai = d.get_cloned::(); // For each user... let mut data = OsuSavedUsers::open(&*d.read()).borrow()?.clone(); for (user_id, osu_user) in data.iter_mut() { @@ -38,6 +40,7 @@ pub fn updates(c: Arc, d: AppData, channels: MemberToChannels) -> c.clone(), &osu, &cache, + &oppai, &osu_user, *user_id, &channels[..], @@ -64,6 +67,7 @@ fn handle_user_mode( c: Arc, osu: &Osu, cache: &BeatmapMetaCache, + oppai: &BeatmapCache, osu_user: &OsuUser, user_id: UserId, channels: &[ChannelId], @@ -75,23 +79,17 @@ fn handle_user_mode( .ok_or(Error::from("user not found"))?; scores .into_par_iter() - .filter_map(|(rank, score)| { - let beatmap = cache - .get_beatmap_default(score.beatmap_id) - .map(|v| BeatmapWithMode(v, mode)); - match beatmap { - Ok(v) => Some((rank, score, v)), - Err(e) => { - dbg!(e); - None - } - } + .map(|(rank, score)| -> Result<_, Error> { + let beatmap = cache.get_beatmap_default(score.beatmap_id)?; + let content = oppai.get_beatmap(beatmap.beatmap_id)?; + Ok((rank, score, BeatmapWithMode(beatmap, mode), content)) }) - .for_each(|(rank, score, beatmap)| { + .filter_map(|v| v.ok()) + .for_each(|(rank, score, beatmap, content)| { for channel in (&channels).iter() { if let Err(e) = channel.send_message(c.http(), |c| { c.content(format!("New top record from {}!", user_id.mention())) - .embed(|e| score_embed(&score, &beatmap, &user, Some(rank), e)) + .embed(|e| score_embed(&score, &beatmap, &content, &user, Some(rank), e)) }) { dbg!(e); } diff --git a/youmubot-osu/src/discord/embeds.rs b/youmubot-osu/src/discord/embeds.rs index 9498f48..5596fcc 100644 --- a/youmubot-osu/src/discord/embeds.rs +++ b/youmubot-osu/src/discord/embeds.rs @@ -1,6 +1,6 @@ use super::BeatmapWithMode; use crate::{ - discord::oppai_cache::BeatmapInfo, + discord::oppai_cache::{BeatmapContent, BeatmapInfo}, models::{Beatmap, Mode, Mods, Rank, Score, User}, }; use chrono::Utc; @@ -233,6 +233,7 @@ pub fn beatmapset_embed<'a>( pub(crate) fn score_embed<'a>( s: &Score, bm: &BeatmapWithMode, + content: &BeatmapContent, u: &User, top_record: Option, m: &'a mut CreateEmbed, @@ -240,6 +241,11 @@ pub(crate) fn score_embed<'a>( let mode = bm.mode(); let b = &bm.0; let accuracy = s.accuracy(mode); + let stars = mode + .to_oppai_mode() + .and_then(|mode| content.get_info_with(Some(mode), s.mods).ok()) + .map(|info| info.stars as f64) + .unwrap_or(b.difficulty.stars); let score_line = match &s.rank { Rank::SS | Rank::SSH => format!("SS"), _ if s.perfect => format!("{:.2}% FC", accuracy), @@ -249,9 +255,23 @@ pub(crate) fn score_embed<'a>( accuracy, s.max_combo, s.count_miss, v ), }; - let score_line = - s.pp.map(|pp| format!("{} | {:.2}pp", &score_line, pp)) - .unwrap_or(score_line); + let pp = s.pp.map(|pp| format!("{:.2}pp", pp)).or_else(|| { + mode.to_oppai_mode() + .and_then(|op| { + content + .get_pp_from( + oppai_rs::Combo::non_fc(s.max_combo as u32, s.count_miss as u32), + accuracy as f32, + Some(op), + s.mods, + ) + .ok() + }) + .map(|pp| format!("{:.2}pp [?]", pp)) + }); + let score_line = pp + .map(|pp| format!("{} | {}", &score_line, pp)) + .unwrap_or(score_line); let top_record = top_record .map(|v| format!("| #{} top record!", v)) .unwrap_or("".to_owned()); @@ -265,7 +285,7 @@ pub(crate) fn score_embed<'a>( b.title, b.difficulty_name, s.mods, - b.difficulty.stars, + stars, b.creator, score_line, top_record @@ -286,7 +306,7 @@ pub(crate) fn score_embed<'a>( MessageBuilder::new() .push(format!("[[Link]]({})", b.link())) .push(", ") - .push_bold(format!("{:.2}⭐", b.difficulty.stars)) + .push_bold(format!("{:.2}⭐", stars)) .push(", ") .push_bold_line( b.mode.to_string() @@ -309,7 +329,11 @@ pub(crate) fn score_embed<'a>( .build(), false, ) - .field("Played on", s.date.format("%F %T"), false) + .field("Played on", s.date.format("%F %T"), false); + if mode.to_oppai_mode().is_none() && s.mods != Mods::NOMOD { + m.footer(|f| f.text("Star difficulty does not reflect game mods.")); + } + m } pub(crate) fn user_embed<'a>( diff --git a/youmubot-osu/src/discord/mod.rs b/youmubot-osu/src/discord/mod.rs index 1977e0e..131a338 100644 --- a/youmubot-osu/src/discord/mod.rs +++ b/youmubot-osu/src/discord/mod.rs @@ -383,6 +383,7 @@ pub fn recent(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult let osu = ctx.data.get_cloned::(); let meta_cache = ctx.data.get_cloned::(); + let oppai = ctx.data.get_cloned::(); let user = osu .user(user, |f| f.mode(mode))? .ok_or(Error::from("User not found"))?; @@ -395,19 +396,20 @@ pub fn recent(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult .ok_or(Error::from("No such play"))?; let beatmap = meta_cache .get_beatmap(recent_play.beatmap_id, mode) - .map(|v| BeatmapWithMode(v, mode)) .unwrap(); + let content = oppai.get_beatmap(beatmap.beatmap_id)?; + let beatmap_mode = BeatmapWithMode(beatmap, mode); msg.channel_id.send_message(&ctx, |m| { m.content(format!( "{}: here is the play that you requested", msg.author )) - .embed(|m| score_embed(&recent_play, &beatmap, &user, None, m)) + .embed(|m| score_embed(&recent_play, &beatmap_mode, &content, &user, None, m)) })?; // Save the beatmap... - cache::save_beatmap(&*ctx.data.read(), msg.channel_id, &beatmap)?; + cache::save_beatmap(&*ctx.data.read(), msg.channel_id, &beatmap_mode)?; } Nth::All => { let plays = osu.user_recent(UserID::ID(user.id), |f| f.mode(mode).limit(50))?; @@ -466,6 +468,9 @@ pub fn check(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult let user = to_user_id_query(args.single::().ok(), &*ctx.data.read(), msg)?; let osu = ctx.data.get_cloned::(); + let oppai = ctx.data.get_cloned::(); + + let content = oppai.get_beatmap(b.beatmap_id)?; let user = osu .user(user, |f| f)? @@ -478,7 +483,7 @@ pub fn check(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult for score in scores.into_iter() { msg.channel_id.send_message(&ctx, |c| { - c.embed(|m| score_embed(&score, &bm, &user, None, m)) + c.embed(|m| score_embed(&score, &bm, &content, &user, None, m)) })?; } } @@ -502,6 +507,7 @@ pub fn top(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult { let user = to_user_id_query(args.single::().ok(), &*ctx.data.read(), msg)?; let osu = ctx.data.get_cloned::(); + let oppai = ctx.data.get_cloned::(); let user = osu .user(user, |f| f.mode(mode))? .ok_or(Error::from("User not found"))?; @@ -522,15 +528,16 @@ pub fn top(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult { })? .into_iter() .next() - .map(|v| BeatmapWithMode(v, mode)) .unwrap(); + let content = oppai.get_beatmap(beatmap.beatmap_id)?; + let beatmap = BeatmapWithMode(beatmap, mode); msg.channel_id.send_message(&ctx, |m| { m.content(format!( "{}: here is the play that you requested", msg.author )) - .embed(|m| score_embed(&top_play, &beatmap, &user, Some(rank), m)) + .embed(|m| score_embed(&top_play, &beatmap, &content, &user, Some(rank), m)) })?; // Save the beatmap...