Handle score_embed

This commit is contained in:
Natsu Kagami 2020-06-14 19:51:26 -04:00
parent 33f19dbaba
commit eba1bb324c
Signed by: nki
GPG key ID: 73376E117CD20735
3 changed files with 55 additions and 26 deletions

View file

@ -2,6 +2,7 @@ use super::db::{OsuSavedUsers, OsuUser};
use super::{embeds::score_embed, BeatmapWithMode, OsuClient}; use super::{embeds::score_embed, BeatmapWithMode, OsuClient};
use crate::{ use crate::{
discord::beatmap_cache::BeatmapMetaCache, discord::beatmap_cache::BeatmapMetaCache,
discord::oppai_cache::BeatmapCache,
models::{Mode, Score}, models::{Mode, Score},
request::UserID, request::UserID,
Client as Osu, Client as Osu,
@ -24,6 +25,7 @@ pub const ANNOUNCER_KEY: &'static str = "osu";
pub fn updates(c: Arc<CacheAndHttp>, d: AppData, channels: MemberToChannels) -> CommandResult { pub fn updates(c: Arc<CacheAndHttp>, d: AppData, channels: MemberToChannels) -> CommandResult {
let osu = d.get_cloned::<OsuClient>(); let osu = d.get_cloned::<OsuClient>();
let cache = d.get_cloned::<BeatmapMetaCache>(); let cache = d.get_cloned::<BeatmapMetaCache>();
let oppai = d.get_cloned::<BeatmapCache>();
// For each user... // For each user...
let mut data = OsuSavedUsers::open(&*d.read()).borrow()?.clone(); let mut data = OsuSavedUsers::open(&*d.read()).borrow()?.clone();
for (user_id, osu_user) in data.iter_mut() { for (user_id, osu_user) in data.iter_mut() {
@ -38,6 +40,7 @@ pub fn updates(c: Arc<CacheAndHttp>, d: AppData, channels: MemberToChannels) ->
c.clone(), c.clone(),
&osu, &osu,
&cache, &cache,
&oppai,
&osu_user, &osu_user,
*user_id, *user_id,
&channels[..], &channels[..],
@ -64,6 +67,7 @@ fn handle_user_mode(
c: Arc<CacheAndHttp>, c: Arc<CacheAndHttp>,
osu: &Osu, osu: &Osu,
cache: &BeatmapMetaCache, cache: &BeatmapMetaCache,
oppai: &BeatmapCache,
osu_user: &OsuUser, osu_user: &OsuUser,
user_id: UserId, user_id: UserId,
channels: &[ChannelId], channels: &[ChannelId],
@ -75,23 +79,17 @@ fn handle_user_mode(
.ok_or(Error::from("user not found"))?; .ok_or(Error::from("user not found"))?;
scores scores
.into_par_iter() .into_par_iter()
.filter_map(|(rank, score)| { .map(|(rank, score)| -> Result<_, Error> {
let beatmap = cache let beatmap = cache.get_beatmap_default(score.beatmap_id)?;
.get_beatmap_default(score.beatmap_id) let content = oppai.get_beatmap(beatmap.beatmap_id)?;
.map(|v| BeatmapWithMode(v, mode)); Ok((rank, score, BeatmapWithMode(beatmap, mode), content))
match beatmap {
Ok(v) => Some((rank, score, v)),
Err(e) => {
dbg!(e);
None
}
}
}) })
.for_each(|(rank, score, beatmap)| { .filter_map(|v| v.ok())
.for_each(|(rank, score, beatmap, content)| {
for channel in (&channels).iter() { for channel in (&channels).iter() {
if let Err(e) = channel.send_message(c.http(), |c| { if let Err(e) = channel.send_message(c.http(), |c| {
c.content(format!("New top record from {}!", user_id.mention())) 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); dbg!(e);
} }

View file

@ -1,6 +1,6 @@
use super::BeatmapWithMode; use super::BeatmapWithMode;
use crate::{ use crate::{
discord::oppai_cache::BeatmapInfo, discord::oppai_cache::{BeatmapContent, BeatmapInfo},
models::{Beatmap, Mode, Mods, Rank, Score, User}, models::{Beatmap, Mode, Mods, Rank, Score, User},
}; };
use chrono::Utc; use chrono::Utc;
@ -233,6 +233,7 @@ pub fn beatmapset_embed<'a>(
pub(crate) fn score_embed<'a>( pub(crate) fn score_embed<'a>(
s: &Score, s: &Score,
bm: &BeatmapWithMode, bm: &BeatmapWithMode,
content: &BeatmapContent,
u: &User, u: &User,
top_record: Option<u8>, top_record: Option<u8>,
m: &'a mut CreateEmbed, m: &'a mut CreateEmbed,
@ -240,6 +241,11 @@ pub(crate) fn score_embed<'a>(
let mode = bm.mode(); let mode = bm.mode();
let b = &bm.0; let b = &bm.0;
let accuracy = s.accuracy(mode); 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 { let score_line = match &s.rank {
Rank::SS | Rank::SSH => format!("SS"), Rank::SS | Rank::SSH => format!("SS"),
_ if s.perfect => format!("{:.2}% FC", accuracy), _ 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 accuracy, s.max_combo, s.count_miss, v
), ),
}; };
let score_line = let pp = s.pp.map(|pp| format!("{:.2}pp", pp)).or_else(|| {
s.pp.map(|pp| format!("{} | {:.2}pp", &score_line, pp)) mode.to_oppai_mode()
.unwrap_or(score_line); .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 let top_record = top_record
.map(|v| format!("| #{} top record!", v)) .map(|v| format!("| #{} top record!", v))
.unwrap_or("".to_owned()); .unwrap_or("".to_owned());
@ -265,7 +285,7 @@ pub(crate) fn score_embed<'a>(
b.title, b.title,
b.difficulty_name, b.difficulty_name,
s.mods, s.mods,
b.difficulty.stars, stars,
b.creator, b.creator,
score_line, score_line,
top_record top_record
@ -286,7 +306,7 @@ pub(crate) fn score_embed<'a>(
MessageBuilder::new() MessageBuilder::new()
.push(format!("[[Link]]({})", b.link())) .push(format!("[[Link]]({})", b.link()))
.push(", ") .push(", ")
.push_bold(format!("{:.2}", b.difficulty.stars)) .push_bold(format!("{:.2}", stars))
.push(", ") .push(", ")
.push_bold_line( .push_bold_line(
b.mode.to_string() b.mode.to_string()
@ -309,7 +329,11 @@ pub(crate) fn score_embed<'a>(
.build(), .build(),
false, 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>( pub(crate) fn user_embed<'a>(

View file

@ -383,6 +383,7 @@ pub fn recent(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult
let osu = ctx.data.get_cloned::<OsuClient>(); let osu = ctx.data.get_cloned::<OsuClient>();
let meta_cache = ctx.data.get_cloned::<BeatmapMetaCache>(); let meta_cache = ctx.data.get_cloned::<BeatmapMetaCache>();
let oppai = ctx.data.get_cloned::<BeatmapCache>();
let user = osu let user = osu
.user(user, |f| f.mode(mode))? .user(user, |f| f.mode(mode))?
.ok_or(Error::from("User not found"))?; .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"))?; .ok_or(Error::from("No such play"))?;
let beatmap = meta_cache let beatmap = meta_cache
.get_beatmap(recent_play.beatmap_id, mode) .get_beatmap(recent_play.beatmap_id, mode)
.map(|v| BeatmapWithMode(v, mode))
.unwrap(); .unwrap();
let content = oppai.get_beatmap(beatmap.beatmap_id)?;
let beatmap_mode = BeatmapWithMode(beatmap, mode);
msg.channel_id.send_message(&ctx, |m| { msg.channel_id.send_message(&ctx, |m| {
m.content(format!( m.content(format!(
"{}: here is the play that you requested", "{}: here is the play that you requested",
msg.author 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... // 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 => { Nth::All => {
let plays = osu.user_recent(UserID::ID(user.id), |f| f.mode(mode).limit(50))?; 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::<UsernameArg>().ok(), &*ctx.data.read(), msg)?; let user = to_user_id_query(args.single::<UsernameArg>().ok(), &*ctx.data.read(), msg)?;
let osu = ctx.data.get_cloned::<OsuClient>(); let osu = ctx.data.get_cloned::<OsuClient>();
let oppai = ctx.data.get_cloned::<BeatmapCache>();
let content = oppai.get_beatmap(b.beatmap_id)?;
let user = osu let user = osu
.user(user, |f| f)? .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() { for score in scores.into_iter() {
msg.channel_id.send_message(&ctx, |c| { 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::<UsernameArg>().ok(), &*ctx.data.read(), msg)?; let user = to_user_id_query(args.single::<UsernameArg>().ok(), &*ctx.data.read(), msg)?;
let osu = ctx.data.get_cloned::<OsuClient>(); let osu = ctx.data.get_cloned::<OsuClient>();
let oppai = ctx.data.get_cloned::<BeatmapCache>();
let user = osu let user = osu
.user(user, |f| f.mode(mode))? .user(user, |f| f.mode(mode))?
.ok_or(Error::from("User not found"))?; .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() .into_iter()
.next() .next()
.map(|v| BeatmapWithMode(v, mode))
.unwrap(); .unwrap();
let content = oppai.get_beatmap(beatmap.beatmap_id)?;
let beatmap = BeatmapWithMode(beatmap, mode);
msg.channel_id.send_message(&ctx, |m| { msg.channel_id.send_message(&ctx, |m| {
m.content(format!( m.content(format!(
"{}: here is the play that you requested", "{}: here is the play that you requested",
msg.author 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... // Save the beatmap...