mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-19 00:38:54 +00:00
Implement a score hook
This commit is contained in:
parent
7a98dc21a9
commit
7f15a4698a
3 changed files with 92 additions and 10 deletions
|
@ -2,6 +2,7 @@ use super::BeatmapWithMode;
|
|||
use crate::{
|
||||
discord::oppai_cache::{Accuracy, BeatmapContent, BeatmapInfo, BeatmapInfoWithPP},
|
||||
models::{Beatmap, Difficulty, Mode, Mods, Rank, Score, User},
|
||||
UserHeader,
|
||||
};
|
||||
use serenity::{
|
||||
all::CreateAttachment,
|
||||
|
@ -243,7 +244,7 @@ pub(crate) struct ScoreEmbedBuilder<'a> {
|
|||
s: &'a Score,
|
||||
bm: &'a BeatmapWithMode,
|
||||
content: &'a BeatmapContent,
|
||||
u: &'a User,
|
||||
u: UserHeader,
|
||||
top_record: Option<u8>,
|
||||
world_record: Option<u16>,
|
||||
footer: Option<String>,
|
||||
|
@ -268,13 +269,13 @@ pub(crate) fn score_embed<'a>(
|
|||
s: &'a Score,
|
||||
bm: &'a BeatmapWithMode,
|
||||
content: &'a BeatmapContent,
|
||||
u: &'a User,
|
||||
u: impl Into<UserHeader>,
|
||||
) -> ScoreEmbedBuilder<'a> {
|
||||
ScoreEmbedBuilder {
|
||||
s,
|
||||
bm,
|
||||
content,
|
||||
u,
|
||||
u: u.into(),
|
||||
top_record: None,
|
||||
world_record: None,
|
||||
footer: None,
|
||||
|
@ -288,7 +289,7 @@ impl<'a> ScoreEmbedBuilder<'a> {
|
|||
let b = &self.bm.0;
|
||||
let s = self.s;
|
||||
let content = self.content;
|
||||
let u = self.u;
|
||||
let u = &self.u;
|
||||
let accuracy = s.accuracy(mode);
|
||||
let info = content.get_info_with(mode, s.mods).ok();
|
||||
let stars = info
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use futures_util::stream::FuturesOrdered;
|
||||
use itertools::Itertools;
|
||||
use lazy_static::lazy_static;
|
||||
use pagination::paginate_from_fn;
|
||||
use regex::Regex;
|
||||
use serenity::all::EditMessage;
|
||||
use serenity::{builder::CreateMessage, model::channel::Message, utils::MessageBuilder};
|
||||
use serenity::{
|
||||
all::{EditMessage, EMBED_MAX_COUNT},
|
||||
builder::CreateMessage,
|
||||
model::channel::Message,
|
||||
utils::MessageBuilder,
|
||||
};
|
||||
|
||||
use youmubot_prelude::*;
|
||||
|
||||
use crate::discord::OsuEnv;
|
||||
use crate::discord::embeds::score_embed;
|
||||
use crate::discord::{BeatmapWithMode, OsuEnv};
|
||||
use crate::{
|
||||
discord::oppai_cache::BeatmapInfoWithPP,
|
||||
models::{Beatmap, Mode, Mods},
|
||||
|
@ -18,6 +25,7 @@ use crate::{
|
|||
use super::embeds::beatmap_embed;
|
||||
|
||||
lazy_static! {
|
||||
// Beatmap(set) hooks
|
||||
pub(crate) static ref OLD_LINK_REGEX: Regex = Regex::new(
|
||||
r"(?:https?://)?osu\.ppy\.sh/(?P<link_type>s|b)/(?P<id>\d+)(?:[\&\?]m=(?P<mode>\d))?(?:\+(?P<mods>[A-Z]+))?"
|
||||
).unwrap();
|
||||
|
@ -27,8 +35,81 @@ lazy_static! {
|
|||
pub(crate) static ref SHORT_LINK_REGEX: Regex = Regex::new(
|
||||
r"(?:^|\s|\W)(?P<main>/b/(?P<id>\d+)(?:/(?P<mode>osu|taiko|fruits|mania))?(?:\+(?P<mods>[A-Z]+))?)"
|
||||
).unwrap();
|
||||
|
||||
// Score hook
|
||||
pub(crate) static ref SCORE_LINK_REGEX: Regex = Regex::new(
|
||||
r"(?:https?://)?osu\.ppy\.sh/scores/(?P<score_id>\d+)"
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
/// React to /scores/{id} links.
|
||||
pub fn score_hook<'a>(
|
||||
ctx: &'a Context,
|
||||
msg: &'a Message,
|
||||
) -> std::pin::Pin<Box<dyn future::Future<Output = Result<()>> + Send + 'a>> {
|
||||
Box::pin(async move {
|
||||
if msg.author.bot {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let env = {
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<OsuEnv>().unwrap().clone()
|
||||
};
|
||||
|
||||
let scores = SCORE_LINK_REGEX
|
||||
.captures_iter(&msg.content)
|
||||
.filter_map(|caps| caps.name("score_id"))
|
||||
.filter_map(|score_id| score_id.as_str().parse::<u64>().ok())
|
||||
.map(|id| env.client.score(id))
|
||||
.collect::<FuturesOrdered<_>>()
|
||||
.collect::<Vec<_>>()
|
||||
.await
|
||||
.into_iter()
|
||||
.filter_map(|score| score.pls_ok().flatten());
|
||||
|
||||
let embed_chunks = scores
|
||||
.map(|score| async move {
|
||||
let env = {
|
||||
let data = ctx.data.read().await;
|
||||
data.get::<OsuEnv>().unwrap().clone()
|
||||
};
|
||||
let bm = env
|
||||
.beatmaps
|
||||
.get_beatmap(score.beatmap_id, score.mode)
|
||||
.await?;
|
||||
let content = env.oppai.get_beatmap(score.beatmap_id).await?;
|
||||
let header = env.client.user_header(score.user_id).await?.unwrap();
|
||||
Ok(score_embed(&score, &BeatmapWithMode(bm, score.mode), &content, header).build())
|
||||
as Result<_>
|
||||
})
|
||||
.collect::<FuturesOrdered<_>>()
|
||||
.collect::<Vec<_>>()
|
||||
.await
|
||||
.into_iter()
|
||||
.filter_map(|v| v.pls_ok())
|
||||
.chunks(EMBED_MAX_COUNT)
|
||||
.into_iter()
|
||||
.map(|chunk| chunk.collect::<Vec<_>>())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for embeds in embed_chunks {
|
||||
msg.channel_id
|
||||
.send_message(
|
||||
&ctx,
|
||||
CreateMessage::new()
|
||||
.reference_message(msg)
|
||||
.content("Here are the scores mentioned in the message!")
|
||||
.embeds(embeds),
|
||||
)
|
||||
.await
|
||||
.pls_ok();
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// React to .osz and .osu uploads.
|
||||
pub fn dot_osu_hook<'a>(
|
||||
ctx: &'a Context,
|
||||
msg: &'a Message,
|
||||
|
|
|
@ -16,7 +16,7 @@ use serenity::{
|
|||
use db::{OsuLastBeatmap, OsuSavedUsers, OsuUser, OsuUserBests};
|
||||
use embeds::{beatmap_embed, score_embed, user_embed};
|
||||
use hook::SHORT_LINK_REGEX;
|
||||
pub use hook::{dot_osu_hook, hook};
|
||||
pub use hook::{dot_osu_hook, hook, score_hook};
|
||||
use server_rank::{SERVER_RANK_COMMAND, SHOW_LEADERBOARD_COMMAND};
|
||||
use youmubot_prelude::announcer::AnnouncerHandler;
|
||||
use youmubot_prelude::{stream::FuturesUnordered, *};
|
||||
|
@ -44,7 +44,7 @@ mod server_rank;
|
|||
pub(crate) struct OsuClient;
|
||||
|
||||
impl TypeMapKey for OsuClient {
|
||||
type Value = Arc<OsuHttpClient>;
|
||||
type Value = Arc<crate::Client>;
|
||||
}
|
||||
|
||||
/// The environment for osu! app commands.
|
||||
|
@ -56,7 +56,7 @@ pub struct OsuEnv {
|
|||
pub(crate) last_beatmaps: OsuLastBeatmap,
|
||||
pub(crate) user_bests: OsuUserBests,
|
||||
// clients
|
||||
pub(crate) client: Arc<OsuHttpClient>,
|
||||
pub(crate) client: Arc<crate::Client>,
|
||||
pub(crate) oppai: BeatmapCache,
|
||||
pub(crate) beatmaps: BeatmapMetaCache,
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue