mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-19 00:38:54 +00:00
Use the user's own top scores for saving checks
This commit is contained in:
parent
d20dbad1b8
commit
30f186c604
4 changed files with 93 additions and 91 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2992,6 +2992,7 @@ dependencies = [
|
||||||
"dashmap",
|
"dashmap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"osuparse",
|
"osuparse",
|
||||||
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rosu-pp",
|
"rosu-pp",
|
||||||
|
|
|
@ -19,6 +19,7 @@ rosu-pp = "0.9.1"
|
||||||
serde = { version = "1.0.137", features = ["derive"] }
|
serde = { version = "1.0.137", features = ["derive"] }
|
||||||
serenity = "0.11.2"
|
serenity = "0.11.2"
|
||||||
zip = "0.6.2"
|
zip = "0.6.2"
|
||||||
|
rand = "0.8"
|
||||||
|
|
||||||
youmubot-db = { path = "../youmubot-db" }
|
youmubot-db = { path = "../youmubot-db" }
|
||||||
youmubot-db-sql = { path = "../youmubot-db-sql" }
|
youmubot-db-sql = { path = "../youmubot-db-sql" }
|
||||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
||||||
request::{BeatmapRequestKind, UserID},
|
request::{BeatmapRequestKind, UserID},
|
||||||
Client as OsuHttpClient,
|
Client as OsuHttpClient,
|
||||||
};
|
};
|
||||||
|
use rand::seq::IteratorRandom;
|
||||||
use serenity::{
|
use serenity::{
|
||||||
collector::{CollectReaction, ReactionAction},
|
collector::{CollectReaction, ReactionAction},
|
||||||
framework::standard::{
|
framework::standard::{
|
||||||
|
@ -26,11 +27,9 @@ pub(crate) mod display;
|
||||||
pub(crate) mod embeds;
|
pub(crate) mod embeds;
|
||||||
mod hook;
|
mod hook;
|
||||||
pub(crate) mod oppai_cache;
|
pub(crate) mod oppai_cache;
|
||||||
mod register_user;
|
|
||||||
mod server_rank;
|
mod server_rank;
|
||||||
|
|
||||||
use db::OsuUser;
|
use db::{OsuLastBeatmap, OsuSavedUsers, OsuUser, OsuUserBests};
|
||||||
use db::{OsuLastBeatmap, OsuSavedUsers, OsuUserBests};
|
|
||||||
use embeds::{beatmap_embed, score_embed, user_embed};
|
use embeds::{beatmap_embed, score_embed, user_embed};
|
||||||
use hook::SHORT_LINK_REGEX;
|
use hook::SHORT_LINK_REGEX;
|
||||||
pub use hook::{dot_osu_hook, hook};
|
pub use hook::{dot_osu_hook, hook};
|
||||||
|
@ -176,85 +175,105 @@ pub async fn save(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult
|
||||||
let data = ctx.data.read().await;
|
let data = ctx.data.read().await;
|
||||||
let osu = data.get::<OsuClient>().unwrap();
|
let osu = data.get::<OsuClient>().unwrap();
|
||||||
|
|
||||||
async fn check(client: &OsuHttpClient, u: &User) -> Result<bool> {
|
let user = args.single::<String>()?;
|
||||||
let check_beatmap_id = register_user::user_register_beatmap_id(&u);
|
let u = match osu.user(UserID::Auto(user), |f| f).await? {
|
||||||
|
Some(u) => u,
|
||||||
|
None => {
|
||||||
|
msg.reply(&ctx, "user not found...").await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
async fn find_score(client: &OsuHttpClient, u: &User) -> Result<Option<(models::Score, Mode)>> {
|
||||||
|
for mode in &[Mode::Std, Mode::Taiko, Mode::Catch, Mode::Mania] {
|
||||||
|
let scores = client
|
||||||
|
.user_best(UserID::ID(u.id), |f| f.mode(*mode))
|
||||||
|
.await?;
|
||||||
|
match scores.into_iter().choose(&mut rand::thread_rng()) {
|
||||||
|
Some(v) => return Ok(Some((v, *mode))),
|
||||||
|
None => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
let (score, mode) = match find_score(&osu, &u).await? {
|
||||||
|
Some(v) => v,
|
||||||
|
None => {
|
||||||
|
msg.reply(
|
||||||
|
&ctx,
|
||||||
|
"No plays found in this account! Play something first...!",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async fn check(client: &OsuHttpClient, u: &User, map_id: u64) -> Result<bool> {
|
||||||
Ok(client
|
Ok(client
|
||||||
.user_recent(UserID::ID(u.id), |f| f.mode(Mode::Std).limit(1))
|
.user_recent(UserID::ID(u.id), |f| f.mode(Mode::Std).limit(1))
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.take(1)
|
.take(1)
|
||||||
.any(|s| s.beatmap_id == check_beatmap_id))
|
.any(|s| s.beatmap_id == map_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
let user = args.single::<String>()?;
|
let reply = msg.reply(&ctx, format!("To set your osu username, please make your most recent play be the following map: `/b/{}` in **{}** mode! It does **not** have to be a pass, and **NF** can be used! React to this message with 👌 within 5 minutes when you're done!", score.beatmap_id, mode.as_str_new_site()));
|
||||||
let user: Option<User> = osu.user(UserID::Auto(user), |f| f).await?;
|
let beatmap = osu
|
||||||
match user {
|
.beatmaps(
|
||||||
Some(u) => {
|
crate::request::BeatmapRequestKind::Beatmap(score.beatmap_id),
|
||||||
if !check(&osu, &u).await? {
|
|f| f.mode(mode, true),
|
||||||
let check_beatmap_id = register_user::user_register_beatmap_id(&u);
|
)
|
||||||
let reply = msg.reply(&ctx, format!("To set your osu username, please make your most recent play be the following map: `/b/{}` in **osu! standard** mode! It does **not** have to be a pass, and **NF** can be used! React to this message with 👌 within 5 minutes when you're done!", check_beatmap_id));
|
.await?
|
||||||
let beatmap = osu
|
.into_iter()
|
||||||
.beatmaps(
|
.next()
|
||||||
crate::request::BeatmapRequestKind::Beatmap(check_beatmap_id),
|
.unwrap();
|
||||||
|f| f,
|
let info = data
|
||||||
)
|
.get::<BeatmapCache>()
|
||||||
.await?
|
.unwrap()
|
||||||
.into_iter()
|
.get_beatmap(beatmap.beatmap_id)
|
||||||
.next()
|
.await?
|
||||||
.unwrap();
|
.get_possible_pp_with(mode, Mods::NOMOD)?;
|
||||||
let info = data
|
let mut reply = reply.await?;
|
||||||
.get::<BeatmapCache>()
|
reply
|
||||||
.unwrap()
|
.edit(&ctx, |f| {
|
||||||
.get_beatmap(beatmap.beatmap_id)
|
f.embed(|e| beatmap_embed(&beatmap, mode, Mods::NOMOD, info, e))
|
||||||
.await?
|
})
|
||||||
.get_possible_pp_with(Mode::Std, Mods::NOMOD)?;
|
.await?;
|
||||||
let mut reply = reply.await?;
|
let reaction = reply.react(&ctx, '👌').await?;
|
||||||
reply
|
let completed = loop {
|
||||||
.edit(&ctx, |f| {
|
let emoji = reaction.emoji.clone();
|
||||||
f.embed(|e| beatmap_embed(&beatmap, Mode::Std, Mods::NOMOD, info, e))
|
let user_reaction = CollectReaction::new(&ctx)
|
||||||
})
|
.message_id(reply.id.0)
|
||||||
.await?;
|
.author_id(msg.author.id.0)
|
||||||
let reaction = reply.react(&ctx, '👌').await?;
|
.filter(move |r| r.emoji == emoji)
|
||||||
let completed = loop {
|
.timeout(std::time::Duration::from_secs(300))
|
||||||
let emoji = reaction.emoji.clone();
|
.collect_limit(1)
|
||||||
let user_reaction = CollectReaction::new(&ctx)
|
.await;
|
||||||
.message_id(reply.id.0)
|
if let Some(ur) = user_reaction {
|
||||||
.author_id(msg.author.id.0)
|
if check(&osu, &u, score.beatmap_id).await? {
|
||||||
.filter(move |r| r.emoji == emoji)
|
break true;
|
||||||
.timeout(std::time::Duration::from_secs(300))
|
|
||||||
.collect_limit(1)
|
|
||||||
.await;
|
|
||||||
if let Some(ur) = user_reaction {
|
|
||||||
if check(&osu, &u).await? {
|
|
||||||
break true;
|
|
||||||
}
|
|
||||||
if let ReactionAction::Added(ur) = &*ur {
|
|
||||||
ur.delete(&ctx).await?;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if !completed {
|
|
||||||
reaction.delete(&ctx).await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let username = u.username.clone();
|
if let ReactionAction::Added(ur) = &*ur {
|
||||||
add_user(msg.author.id, u, &data).await?;
|
ur.delete(&ctx).await?;
|
||||||
msg.reply(
|
}
|
||||||
&ctx,
|
} else {
|
||||||
MessageBuilder::new()
|
break false;
|
||||||
.push("user has been set to ")
|
|
||||||
.push_mono_safe(username)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
msg.reply(&ctx, "user not found...").await?;
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
if !completed {
|
||||||
|
reaction.delete(&ctx).await?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let username = u.username.clone();
|
||||||
|
add_user(msg.author.id, u, &data).await?;
|
||||||
|
msg.reply(
|
||||||
|
&ctx,
|
||||||
|
MessageBuilder::new()
|
||||||
|
.push("user has been set to ")
|
||||||
|
.push_mono_safe(username)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
use crate::models::User;
|
|
||||||
|
|
||||||
const BEATMAP_IDS: [u64; 100] = [
|
|
||||||
2469345, 2084862, 2486881, 2330357, 2546607, 1655981, 1626537, 888015, 1062394, 1319547,
|
|
||||||
1852572, 1944926, 2129143, 1057509, 2022718, 1097543, 1736329, 1056207, 930249, 1936782,
|
|
||||||
1919312, 1570203, 2201460, 1495498, 965549, 2428358, 2118444, 1849433, 820619, 999944, 1571309,
|
|
||||||
1055147, 1619555, 338682, 1438917, 954692, 824891, 2026320, 764014, 2237466, 2058788, 1969946,
|
|
||||||
1892257, 1473301, 2336704, 774965, 657509, 1031604, 898576, 714001, 1872396, 831705, 1917082,
|
|
||||||
978326, 795232, 1814494, 713867, 2077126, 1612329, 1314214, 1849273, 1829925, 1640362, 801158,
|
|
||||||
431957, 1054501, 1627148, 816600, 1857519, 1080094, 1642274, 1232440, 1843653, 953586, 2044362,
|
|
||||||
1489536, 951053, 1069111, 2154507, 1007699, 1099936, 1077323, 1874119, 909032, 760466, 1911308,
|
|
||||||
1820921, 1231520, 954254, 425779, 1586059, 2198684, 1040044, 799913, 994933, 969681, 888016,
|
|
||||||
1100327, 1063410, 2078961,
|
|
||||||
];
|
|
||||||
|
|
||||||
pub fn user_register_beatmap_id(u: &User) -> u64 {
|
|
||||||
let now = chrono::Utc::now();
|
|
||||||
BEATMAP_IDS[(u.id + (now.timestamp() / 3600) as u64) as usize % BEATMAP_IDS.len()]
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue