mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-19 00:38:54 +00:00
osu: Always load Me
as a follow-up response
This commit is contained in:
parent
76fd6c803d
commit
24e476239c
3 changed files with 73 additions and 75 deletions
|
@ -2,8 +2,9 @@ use std::pin::Pin;
|
||||||
|
|
||||||
use future::Future;
|
use future::Future;
|
||||||
use serenity::all::{
|
use serenity::all::{
|
||||||
ComponentInteractionDataKind, CreateActionRow, CreateButton, CreateInteractionResponse,
|
ComponentInteraction, ComponentInteractionDataKind, CreateActionRow, CreateButton,
|
||||||
CreateInteractionResponseFollowup, CreateInteractionResponseMessage, GuildId, Interaction,
|
CreateInteractionResponse, CreateInteractionResponseFollowup, CreateInteractionResponseMessage,
|
||||||
|
GuildId, Interaction,
|
||||||
};
|
};
|
||||||
use youmubot_prelude::*;
|
use youmubot_prelude::*;
|
||||||
|
|
||||||
|
@ -52,14 +53,9 @@ pub fn handle_check_button<'a>(
|
||||||
interaction: &'a Interaction,
|
interaction: &'a Interaction,
|
||||||
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
|
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let comp = match interaction.as_message_component() {
|
let comp = match expect_and_defer_button(ctx, interaction, BTN_CHECK).await? {
|
||||||
Some(comp)
|
Some(comp) => comp,
|
||||||
if comp.data.custom_id == BTN_CHECK
|
None => return Ok(()),
|
||||||
&& matches!(comp.data.kind, ComponentInteractionDataKind::Button) =>
|
|
||||||
{
|
|
||||||
comp
|
|
||||||
}
|
|
||||||
_ => return Ok(()),
|
|
||||||
};
|
};
|
||||||
let msg = &*comp.message;
|
let msg = &*comp.message;
|
||||||
|
|
||||||
|
@ -70,46 +66,46 @@ pub fn handle_check_button<'a>(
|
||||||
let user = match env.saved_users.by_user_id(comp.user.id).await? {
|
let user = match env.saved_users.by_user_id(comp.user.id).await? {
|
||||||
Some(u) => u,
|
Some(u) => u,
|
||||||
None => {
|
None => {
|
||||||
comp.create_response(&ctx, CreateInteractionResponse::Message(CreateInteractionResponseMessage::new().content("You don't have a saved account yet! Save your osu! account by `y2!osu save <your-osu-username>`.").ephemeral(true))).await?;
|
comp.create_followup(&ctx, CreateInteractionResponseFollowup::new().content("You don't have a saved account yet! Save your osu! account by `y2!osu save <your-osu-username>`.").ephemeral(true)).await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let scores = super::do_check(&env, &bm, Mods::NOMOD, &crate::UserID::ID(user.id)).await?;
|
let scores = super::do_check(&env, &bm, Mods::NOMOD, &crate::UserID::ID(user.id)).await?;
|
||||||
if scores.is_empty() {
|
if scores.is_empty() {
|
||||||
comp.create_response(
|
comp.create_followup(
|
||||||
&ctx,
|
&ctx,
|
||||||
CreateInteractionResponse::Message(
|
CreateInteractionResponseFollowup::new().content(format!(
|
||||||
CreateInteractionResponseMessage::new().content(format!(
|
"No plays found for [`{}`](<https://osu.ppy.sh/users/{}>) on `{}`.",
|
||||||
"No plays found for [`{}`](<https://osu.ppy.sh/users/{}>) on `{}`.",
|
user.username,
|
||||||
user.username,
|
user.id,
|
||||||
user.id,
|
bm.short_link(Mods::NOMOD)
|
||||||
bm.short_link(Mods::NOMOD)
|
)),
|
||||||
)),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let reply = {
|
let reply = comp
|
||||||
comp.create_response(
|
.create_followup(
|
||||||
&ctx,
|
&ctx,
|
||||||
serenity::all::CreateInteractionResponse::Message(
|
CreateInteractionResponseFollowup::new().content(format!(
|
||||||
CreateInteractionResponseMessage::new().content(format!(
|
"Here are the scores by [`{}`](<https://osu.ppy.sh/users/{}>) on `{}`!",
|
||||||
"Here are the scores by [`{}`](<https://osu.ppy.sh/users/{}>) on `{}`!",
|
user.username,
|
||||||
user.username,
|
user.id,
|
||||||
user.id,
|
bm.short_link(Mods::NOMOD)
|
||||||
bm.short_link(Mods::NOMOD)
|
)),
|
||||||
)),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
comp.get_response(&ctx).await?
|
|
||||||
};
|
let ctx = ctx.clone();
|
||||||
ScoreListStyle::Grid
|
let guild_id = comp.guild_id;
|
||||||
.display_scores(scores, bm.1, ctx, comp.guild_id, reply)
|
spawn_future(async move {
|
||||||
.await?;
|
ScoreListStyle::Grid
|
||||||
|
.display_scores(scores, bm.1, &ctx, guild_id, reply)
|
||||||
|
.await
|
||||||
|
.pls_ok();
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
@ -129,14 +125,9 @@ pub fn handle_last_button<'a>(
|
||||||
interaction: &'a Interaction,
|
interaction: &'a Interaction,
|
||||||
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
|
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let comp = match interaction.as_message_component() {
|
let comp = match expect_and_defer_button(ctx, interaction, BTN_LAST).await? {
|
||||||
Some(comp)
|
Some(comp) => comp,
|
||||||
if comp.data.custom_id == BTN_LAST
|
None => return Ok(()),
|
||||||
&& matches!(comp.data.kind, ComponentInteractionDataKind::Button) =>
|
|
||||||
{
|
|
||||||
comp
|
|
||||||
}
|
|
||||||
_ => return Ok(()),
|
|
||||||
};
|
};
|
||||||
let msg = &*comp.message;
|
let msg = &*comp.message;
|
||||||
|
|
||||||
|
@ -153,17 +144,15 @@ pub fn handle_last_button<'a>(
|
||||||
.get_beatmap(b.beatmap_id)
|
.get_beatmap(b.beatmap_id)
|
||||||
.await?
|
.await?
|
||||||
.get_possible_pp_with(*m, &mods)?;
|
.get_possible_pp_with(*m, &mods)?;
|
||||||
comp.create_response(
|
comp.create_followup(
|
||||||
&ctx,
|
&ctx,
|
||||||
serenity::all::CreateInteractionResponse::Message(
|
serenity::all::CreateInteractionResponseFollowup::new()
|
||||||
CreateInteractionResponseMessage::new()
|
.content(format!(
|
||||||
.content(format!(
|
"Information for beatmap `{}`",
|
||||||
"Information for beatmap `{}`",
|
bm.short_link(&mods)
|
||||||
bm.short_link(&mods)
|
))
|
||||||
))
|
.embed(beatmap_embed(b, *m, &mods, info))
|
||||||
.embed(beatmap_embed(b, *m, &mods, info))
|
.components(vec![beatmap_components(comp.guild_id)]),
|
||||||
.components(vec![beatmap_components(comp.guild_id)]),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
// Save the beatmap...
|
// Save the beatmap...
|
||||||
|
@ -187,14 +176,9 @@ pub fn handle_lb_button<'a>(
|
||||||
interaction: &'a Interaction,
|
interaction: &'a Interaction,
|
||||||
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
|
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let comp = match interaction.as_message_component() {
|
let comp = match expect_and_defer_button(ctx, interaction, BTN_LB).await? {
|
||||||
Some(comp)
|
Some(comp) => comp,
|
||||||
if comp.data.custom_id == BTN_LB
|
None => return Ok(()),
|
||||||
&& matches!(comp.data.kind, ComponentInteractionDataKind::Button) =>
|
|
||||||
{
|
|
||||||
comp
|
|
||||||
}
|
|
||||||
_ => return Ok(()),
|
|
||||||
};
|
};
|
||||||
let msg = &*comp.message;
|
let msg = &*comp.message;
|
||||||
|
|
||||||
|
@ -206,11 +190,6 @@ pub fn handle_lb_button<'a>(
|
||||||
let order = OrderBy::default();
|
let order = OrderBy::default();
|
||||||
let guild = comp.guild_id.expect("Guild-only command");
|
let guild = comp.guild_id.expect("Guild-only command");
|
||||||
|
|
||||||
comp.create_response(
|
|
||||||
&ctx,
|
|
||||||
CreateInteractionResponse::Defer(CreateInteractionResponseMessage::new()),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
let scores = get_leaderboard(ctx, &env, &bm, order, guild).await?;
|
let scores = get_leaderboard(ctx, &env, &bm, order, guild).await?;
|
||||||
|
|
||||||
if scores.is_empty() {
|
if scores.is_empty() {
|
||||||
|
@ -237,3 +216,25 @@ pub fn handle_lb_button<'a>(
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn expect_and_defer_button<'a>(
|
||||||
|
ctx: &'_ Context,
|
||||||
|
interaction: &'a Interaction,
|
||||||
|
expect_id: &'static str,
|
||||||
|
) -> Result<Option<&'a ComponentInteraction>> {
|
||||||
|
let comp = match interaction.as_message_component() {
|
||||||
|
Some(comp)
|
||||||
|
if comp.data.custom_id == expect_id
|
||||||
|
&& matches!(comp.data.kind, ComponentInteractionDataKind::Button) =>
|
||||||
|
{
|
||||||
|
comp
|
||||||
|
}
|
||||||
|
_ => return Ok(None),
|
||||||
|
};
|
||||||
|
comp.create_response(
|
||||||
|
&ctx,
|
||||||
|
CreateInteractionResponse::Defer(CreateInteractionResponseMessage::new()),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(Some(comp))
|
||||||
|
}
|
||||||
|
|
|
@ -26,13 +26,13 @@ where
|
||||||
/// InteractionHook represents the asynchronous hook that is run on every interaction.
|
/// InteractionHook represents the asynchronous hook that is run on every interaction.
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait InteractionHook: Send + Sync {
|
pub trait InteractionHook: Send + Sync {
|
||||||
async fn call(&mut self, ctx: &Context, interaction: &Interaction) -> Result<()>;
|
async fn call(&self, ctx: &Context, interaction: &Interaction) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<T> InteractionHook for T
|
impl<T> InteractionHook for T
|
||||||
where
|
where
|
||||||
T: for<'a> FnMut(
|
T: for<'a> Fn(
|
||||||
&'a Context,
|
&'a Context,
|
||||||
&'a Interaction,
|
&'a Interaction,
|
||||||
)
|
)
|
||||||
|
@ -40,7 +40,7 @@ where
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync,
|
+ Sync,
|
||||||
{
|
{
|
||||||
async fn call(&mut self, ctx: &Context, interaction: &Interaction) -> Result<()> {
|
async fn call(&self, ctx: &Context, interaction: &Interaction) -> Result<()> {
|
||||||
self(ctx, interaction).await
|
self(ctx, interaction).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ mod compose_framework;
|
||||||
|
|
||||||
struct Handler {
|
struct Handler {
|
||||||
hooks: Vec<RwLock<Box<dyn Hook>>>,
|
hooks: Vec<RwLock<Box<dyn Hook>>>,
|
||||||
interaction_hooks: Vec<RwLock<Box<dyn InteractionHook>>>,
|
interaction_hooks: Vec<Box<dyn InteractionHook>>,
|
||||||
ready_hooks: Vec<fn(&Context) -> CommandResult>,
|
ready_hooks: Vec<fn(&Context) -> CommandResult>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ impl Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_interaction_hook<T: InteractionHook + 'static>(&mut self, f: T) {
|
fn push_interaction_hook<T: InteractionHook + 'static>(&mut self, f: T) {
|
||||||
self.interaction_hooks.push(RwLock::new(Box::new(f)));
|
self.interaction_hooks.push(Box::new(f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,10 +113,7 @@ impl EventHandler for Handler {
|
||||||
let interaction = &interaction;
|
let interaction = &interaction;
|
||||||
self.interaction_hooks
|
self.interaction_hooks
|
||||||
.iter()
|
.iter()
|
||||||
.map(|hook| {
|
.map(|hook| hook.call(ctx, interaction))
|
||||||
hook.write()
|
|
||||||
.then(|mut h| async move { h.call(ctx, interaction).await })
|
|
||||||
})
|
|
||||||
.collect::<stream::FuturesUnordered<_>>()
|
.collect::<stream::FuturesUnordered<_>>()
|
||||||
.for_each(|v| async move {
|
.for_each(|v| async move {
|
||||||
if let Err(e) = v {
|
if let Err(e) = v {
|
||||||
|
|
Loading…
Add table
Reference in a new issue