mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-19 08:48:54 +00:00
osu: Make c/last/lb sensitive to replied-to messages
This commit is contained in:
parent
00f8c8329e
commit
556ada2b9d
4 changed files with 79 additions and 14 deletions
|
@ -12,13 +12,13 @@ use youmubot_prelude::*;
|
||||||
use super::embeds::beatmap_embed;
|
use super::embeds::beatmap_embed;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref OLD_LINK_REGEX: Regex = Regex::new(
|
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]+))?"
|
r"(?:https?://)?osu\.ppy\.sh/(?P<link_type>s|b)/(?P<id>\d+)(?:[\&\?]m=(?P<mode>\d))?(?:\+(?P<mods>[A-Z]+))?"
|
||||||
).unwrap();
|
).unwrap();
|
||||||
static ref NEW_LINK_REGEX: Regex = Regex::new(
|
pub(crate) static ref NEW_LINK_REGEX: Regex = Regex::new(
|
||||||
r"(?:https?://)?osu\.ppy\.sh/beatmapsets/(?P<set_id>\d+)/?(?:\#(?P<mode>osu|taiko|fruits|mania)(?:/(?P<beatmap_id>\d+)|/?))?(?:\+(?P<mods>[A-Z]+))?"
|
r"(?:https?://)?osu\.ppy\.sh/beatmapsets/(?P<set_id>\d+)/?(?:\#(?P<mode>osu|taiko|fruits|mania)(?:/(?P<beatmap_id>\d+)|/?))?(?:\+(?P<mods>[A-Z]+))?"
|
||||||
).unwrap();
|
).unwrap();
|
||||||
static ref SHORT_LINK_REGEX: Regex = Regex::new(
|
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]+))?)"
|
r"(?:^|\s|\W)(?P<main>/b/(?P<id>\d+)(?:/(?P<mode>osu|taiko|fruits|mania))?(?:\+(?P<mods>[A-Z]+))?)"
|
||||||
).unwrap();
|
).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
||||||
discord::display::ScoreListStyle,
|
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::{BeatmapRequestKind, UserID},
|
||||||
Client as OsuHttpClient,
|
Client as OsuHttpClient,
|
||||||
};
|
};
|
||||||
use serenity::{
|
use serenity::{
|
||||||
|
@ -31,6 +31,7 @@ mod server_rank;
|
||||||
use db::OsuUser;
|
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};
|
||||||
|
use hook::SHORT_LINK_REGEX;
|
||||||
pub use hook::{dot_osu_hook, hook};
|
pub use hook::{dot_osu_hook, hook};
|
||||||
use server_rank::{SERVER_RANK_COMMAND, UPDATE_LEADERBOARD_COMMAND};
|
use server_rank::{SERVER_RANK_COMMAND, UPDATE_LEADERBOARD_COMMAND};
|
||||||
|
|
||||||
|
@ -389,6 +390,61 @@ impl FromStr for OptBeatmapset {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Load the mentioned beatmap from the given message.
|
||||||
|
pub(crate) async fn load_beatmap(
|
||||||
|
ctx: &Context,
|
||||||
|
msg: &Message,
|
||||||
|
) -> Option<(BeatmapWithMode, Option<Mods>)> {
|
||||||
|
let data = ctx.data.read().await;
|
||||||
|
|
||||||
|
if let Some(replied) = &msg.referenced_message {
|
||||||
|
// Try to look for a mention of the replied message.
|
||||||
|
let beatmap_id = SHORT_LINK_REGEX.captures(&replied.content).or_else(|| {
|
||||||
|
msg.embeds.iter().find_map(|e| {
|
||||||
|
e.description
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|v| SHORT_LINK_REGEX.captures(&v))
|
||||||
|
.or_else(|| {
|
||||||
|
e.fields
|
||||||
|
.iter()
|
||||||
|
.find_map(|f| SHORT_LINK_REGEX.captures(&f.value))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
if let Some(caps) = beatmap_id {
|
||||||
|
let id: u64 = caps.name("id").unwrap().as_str().parse().unwrap();
|
||||||
|
let mode = caps
|
||||||
|
.name("mode")
|
||||||
|
.and_then(|m| Mode::parse_from_new_site(m.as_str()));
|
||||||
|
let mods = caps
|
||||||
|
.name("mods")
|
||||||
|
.and_then(|m| m.as_str().parse::<Mods>().ok());
|
||||||
|
let osu = data.get::<OsuClient>().unwrap();
|
||||||
|
let bms = osu
|
||||||
|
.beatmaps(BeatmapRequestKind::Beatmap(id), |f| f.maybe_mode(mode))
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
|
.and_then(|v| v.into_iter().next());
|
||||||
|
if let Some(beatmap) = bms {
|
||||||
|
let bm_mode = beatmap.mode.clone();
|
||||||
|
let bm = BeatmapWithMode(beatmap, mode.unwrap_or(bm_mode));
|
||||||
|
// Store the beatmap in history
|
||||||
|
cache::save_beatmap(&*data, msg.channel_id, &bm)
|
||||||
|
.await
|
||||||
|
.pls_ok();
|
||||||
|
|
||||||
|
return Some((bm, mods));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let b = cache::get_beatmap(&*data, msg.channel_id)
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
|
.flatten();
|
||||||
|
b.map(|b| (b, None))
|
||||||
|
}
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
#[description = "Show information from the last queried beatmap."]
|
#[description = "Show information from the last queried beatmap."]
|
||||||
#[usage = "[--set/-s/--beatmapset] / [mods = no mod]"]
|
#[usage = "[--set/-s/--beatmapset] / [mods = no mod]"]
|
||||||
|
@ -396,12 +452,12 @@ impl FromStr for OptBeatmapset {
|
||||||
#[max_args(2)]
|
#[max_args(2)]
|
||||||
pub async fn last(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
pub async fn last(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||||
let data = ctx.data.read().await;
|
let data = ctx.data.read().await;
|
||||||
let b = cache::get_beatmap(&*data, msg.channel_id).await?;
|
let b = load_beatmap(ctx, msg).await;
|
||||||
let beatmapset = args.find::<OptBeatmapset>().is_ok();
|
let beatmapset = args.find::<OptBeatmapset>().is_ok();
|
||||||
|
|
||||||
match b {
|
match b {
|
||||||
Some(BeatmapWithMode(b, m)) => {
|
Some((BeatmapWithMode(b, m), mods_def)) => {
|
||||||
let mods = args.find::<Mods>().unwrap_or(Mods::NOMOD);
|
let mods = args.find::<Mods>().ok().or(mods_def).unwrap_or(Mods::NOMOD);
|
||||||
if beatmapset {
|
if beatmapset {
|
||||||
let beatmap_cache = data.get::<BeatmapMetaCache>().unwrap();
|
let beatmap_cache = data.get::<BeatmapMetaCache>().unwrap();
|
||||||
let beatmapset = beatmap_cache.get_beatmapset(b.beatmapset_id).await?;
|
let beatmapset = beatmap_cache.get_beatmapset(b.beatmapset_id).await?;
|
||||||
|
@ -447,15 +503,15 @@ pub async fn last(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult
|
||||||
#[max_args(3)]
|
#[max_args(3)]
|
||||||
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 mods = args.find::<Mods>().unwrap_or(Mods::NOMOD);
|
let bm = load_beatmap(ctx, msg).await;
|
||||||
let bm = cache::get_beatmap(&*data, msg.channel_id).await?;
|
|
||||||
|
|
||||||
match bm {
|
match bm {
|
||||||
None => {
|
None => {
|
||||||
msg.reply(&ctx, "No beatmap queried on this channel.")
|
msg.reply(&ctx, "No beatmap queried on this channel.")
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
Some(bm) => {
|
Some((bm, mods_def)) => {
|
||||||
|
let mods = args.find::<Mods>().ok().or(mods_def).unwrap_or(Mods::NOMOD);
|
||||||
let b = &bm.0;
|
let b = &bm.0;
|
||||||
let m = bm.1;
|
let m = bm.1;
|
||||||
let style = args
|
let style = args
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use super::{
|
use super::{
|
||||||
cache::get_beatmap,
|
|
||||||
db::{OsuSavedUsers, OsuUserBests},
|
db::{OsuSavedUsers, OsuUserBests},
|
||||||
ModeArg, OsuClient,
|
ModeArg, OsuClient,
|
||||||
};
|
};
|
||||||
|
@ -179,7 +178,6 @@ impl std::str::FromStr for OrderBy {
|
||||||
pub async fn update_leaderboard(ctx: &Context, m: &Message, mut args: Args) -> CommandResult {
|
pub async fn update_leaderboard(ctx: &Context, m: &Message, mut args: Args) -> CommandResult {
|
||||||
let sort_order = args.single::<OrderBy>().unwrap_or_default();
|
let sort_order = args.single::<OrderBy>().unwrap_or_default();
|
||||||
let style = args.single::<ScoreListStyle>().unwrap_or_default();
|
let style = args.single::<ScoreListStyle>().unwrap_or_default();
|
||||||
let mods = args.find::<Mods>().unwrap_or(Mods::NOMOD);
|
|
||||||
|
|
||||||
let guild = m.guild_id.unwrap();
|
let guild = m.guild_id.unwrap();
|
||||||
let data = ctx.data.read().await;
|
let data = ctx.data.read().await;
|
||||||
|
@ -191,8 +189,11 @@ pub async fn update_leaderboard(ctx: &Context, m: &Message, mut args: Args) -> C
|
||||||
}
|
}
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
};
|
};
|
||||||
let bm = match get_beatmap(&*data, m.channel_id).await? {
|
let (bm, mods) = match super::load_beatmap(ctx, m).await {
|
||||||
Some(bm) => bm,
|
Some((bm, mods_def)) => {
|
||||||
|
let mods = args.find::<Mods>().ok().or(mods_def).unwrap_or(Mods::NOMOD);
|
||||||
|
(bm, mods)
|
||||||
|
}
|
||||||
None => {
|
None => {
|
||||||
m.reply(&ctx, "No beatmap queried on this channel.").await?;
|
m.reply(&ctx, "No beatmap queried on this channel.").await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
|
@ -108,6 +108,14 @@ pub mod builders {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn maybe_mode(&mut self, mode: Option<Mode>) -> &mut Self {
|
||||||
|
if let Some(m) = mode {
|
||||||
|
self.mode(m, true)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mode(&mut self, mode: Mode, converted: bool) -> &mut Self {
|
pub fn mode(&mut self, mode: Mode, converted: bool) -> &mut Self {
|
||||||
self.mode = Some((mode, converted));
|
self.mode = Some((mode, converted));
|
||||||
self
|
self
|
||||||
|
|
Loading…
Add table
Reference in a new issue