osu: add /s/{id} links to the link parser, support beatmapsets with mode override

This commit is contained in:
Natsu Kagami 2025-02-20 14:16:56 +01:00 committed by Natsu Kagami
parent c28cad0718
commit 84b152adf6
5 changed files with 40 additions and 15 deletions

View file

@ -100,7 +100,7 @@ impl BeatmapMetaCache {
}
/// Get a beatmapset from its ID.
pub async fn get_beatmapset(&self, id: u64) -> Result<Vec<Beatmap>> {
pub async fn get_beatmapset(&self, id: u64, mode: Option<Mode>) -> Result<Vec<Beatmap>> {
let bms = models::CachedBeatmap::by_beatmapset(id as i64, &self.pool).await?;
if !bms.is_empty() {
return Ok(bms
@ -110,7 +110,9 @@ impl BeatmapMetaCache {
}
let mut beatmaps = self
.client
.beatmaps(crate::BeatmapRequestKind::Beatmapset(id), |f| f)
.beatmaps(crate::BeatmapRequestKind::Beatmapset(id), |f| {
f.maybe_mode(mode)
})
.await?;
if beatmaps.is_empty() {
return Err(Error::msg("beatmapset not found"));

View file

@ -709,7 +709,10 @@ async fn parse_map_input(
let output = if beatmapset == Some(true) {
match output {
EmbedType::Beatmap(beatmap, _, _) => {
let beatmaps = env.beatmaps.get_beatmapset(beatmap.beatmapset_id).await?;
let beatmaps = env
.beatmaps
.get_beatmapset(beatmap.beatmapset_id, mode)
.await?;
EmbedType::Beatmapset(beatmaps)
}
bm @ EmbedType::Beatmapset(_) => bm,

View file

@ -313,12 +313,15 @@ async fn handle_last_req(
let mods = mods_def.unwrap_or_default();
if is_beatmapset_req {
let beatmapset = env.beatmaps.get_beatmapset(bm.0.beatmapset_id).await?;
let beatmapset = env
.beatmaps
.get_beatmapset(bm.0.beatmapset_id, None)
.await?;
let reply = comp
.create_followup(
&ctx,
CreateInteractionResponseFollowup::new()
.content(format!("Beatmapset of `{}`", bm.short_link(&mods))),
.content(format!("Beatmapset `{}`", bm.0.beatmapset_mention())),
)
.await?;
super::display::display_beatmapset(

View file

@ -29,7 +29,7 @@ lazy_static! {
r"(?:https?://)?osu\.ppy\.sh/beatmapsets/(?P<set_id>\d+)/?(?:\#(?P<mode>osu|taiko|fruits|mania)(?:/(?P<beatmap_id>\d+)|/?))?(?:(?P<mods>v2|[[:^alpha:]]\S+\b))?"
).unwrap();
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>v2|[[:^alpha:]]\S+\b))?)"
r"(?:^|\s|\W)(?P<main>/(?P<link_type>b|s)/(?P<id>\d+)(?:/(?P<mode>osu|taiko|fruits|mania))?(?:(?P<mods>v2|[[:^alpha:]]\S+\b))?)"
).unwrap();
// Score hook
@ -60,7 +60,7 @@ pub fn parse_old_links<'a>(
.unwrap_or_default();
EmbedType::from_beatmap_id(env, capture["id"].parse()?, mode, mods).await
}
"s" => EmbedType::from_beatmapset_id(env, capture["id"].parse()?).await,
"s" => EmbedType::from_beatmapset_id(env, capture["id"].parse()?, mode).await,
_ => unreachable!(),
}?;
Ok(ToPrint {
@ -99,6 +99,7 @@ pub fn parse_new_links<'a>(
EmbedType::from_beatmapset_id(
env,
capture.name("set_id").unwrap().as_str().parse()?,
mode,
)
.await
}
@ -121,11 +122,17 @@ pub fn parse_short_links<'a>(
.and_then(|v| Mode::parse_from_new_site(v.as_str()));
let link = capture.name("main").unwrap().as_str();
let id: u64 = capture.name("id").unwrap().as_str().parse()?;
let mods = capture
.name("mods")
.and_then(|v| UnparsedMods::from_str(v.as_str()).pls_ok())
.unwrap_or_default();
let embed = EmbedType::from_beatmap_id(env, id, mode, mods).await?;
let embed = match capture.name("link_type").unwrap().as_str() {
"b" => {
let mods = capture
.name("mods")
.and_then(|v| UnparsedMods::from_str(v.as_str()).pls_ok())
.unwrap_or_default();
EmbedType::from_beatmap_id(env, id, mode, mods).await?
}
"s" => EmbedType::from_beatmapset_id(env, id, mode).await?,
_ => unreachable!(),
};
Ok(ToPrint { embed, link, mode })
})
.collect::<stream::FuturesUnordered<_>>()
@ -154,9 +161,13 @@ impl EmbedType {
Ok(Self::Beatmap(Box::new(bm), info, mods))
}
async fn from_beatmapset_id(env: &OsuEnv, beatmapset_id: u64) -> Result<Self> {
async fn from_beatmapset_id(
env: &OsuEnv,
beatmapset_id: u64,
mode: Option<Mode>,
) -> Result<Self> {
Ok(Self::Beatmapset(
env.beatmaps.get_beatmapset(beatmapset_id).await?,
env.beatmaps.get_beatmapset(beatmapset_id, mode).await?,
))
}
}

View file

@ -865,7 +865,13 @@ pub async fn last(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult
Some((bm, mods_def)) => {
let mods = args.find::<UnparsedMods>().ok();
if beatmapset {
let beatmapset = env.beatmaps.get_beatmapset(bm.0.beatmapset_id).await?;
let beatmapset = env
.beatmaps
.get_beatmapset(
bm.0.beatmapset_id,
None, /* Note that we cannot know, so don't force that */
)
.await?;
let reply = msg
.reply(&ctx, "Here is the beatmapset you requested!")
.await?;