perf(ticket): instant defer on modal, skip channels scan before modal popup
This commit is contained in:
parent
bf52f83a3a
commit
e0d3b44118
1 changed files with 19 additions and 42 deletions
|
|
@ -166,7 +166,7 @@ pub async fn on_select(ctx: Context, interaction: ComponentInteraction) {
|
||||||
.await;
|
.await;
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
// Pre-checks before showing modal (blacklist / existing ticket) to avoid wasted modal.
|
// Fast pre-check: only blacklist (DB, ~5ms). Duplicate check moved to modal submit after defer (guild.channels is 300-500ms and delays modal popup).
|
||||||
if let Some(guild_id) = interaction.guild_id {
|
if let Some(guild_id) = interaction.guild_id {
|
||||||
if let Some(pool) = service::pool() {
|
if let Some(pool) = service::pool() {
|
||||||
if let Some(reason) =
|
if let Some(reason) =
|
||||||
|
|
@ -185,25 +185,6 @@ pub async fn on_select(ctx: Context, interaction: ComponentInteraction) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Ok(channels) = guild_id.channels(&ctx.http).await {
|
|
||||||
let exists = channels.values().any(|c| {
|
|
||||||
c.name.starts_with(&format!("ticket-{}", interaction.user.name.to_lowercase()))
|
|
||||||
|| c.name.starts_with(&format!("ticket-{}", interaction.user.id))
|
|
||||||
});
|
|
||||||
if exists {
|
|
||||||
let _ = interaction
|
|
||||||
.create_response(
|
|
||||||
&ctx.http,
|
|
||||||
CreateInteractionResponse::Message(
|
|
||||||
CreateInteractionResponseMessage::new()
|
|
||||||
.content("You already have an open ticket.")
|
|
||||||
.ephemeral(true),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let modal = CreateModal::new(format!("ticket_modal:{topic}"), format!("New ticket • {label}"))
|
let modal = CreateModal::new(format!("ticket_modal:{topic}"), format!("New ticket • {label}"))
|
||||||
.components(vec![
|
.components(vec![
|
||||||
|
|
@ -268,17 +249,24 @@ pub async fn on_modal(ctx: Context, interaction: ModalInteraction) {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let user = interaction.user.clone();
|
let user = interaction.user.clone();
|
||||||
// Re-check blacklist / duplicate (race between modal open and submit)
|
// Defer immediately — Discord channel creation is slow (1-2s), avoid 3s timeout and UI lag
|
||||||
if let Some(pool) = service::pool() {
|
|
||||||
if let Some(reason) = service::is_blacklisted(pool, guild_id.get(), user.id.get()).await {
|
|
||||||
let _ = interaction
|
let _ = interaction
|
||||||
.create_response(
|
.create_response(
|
||||||
&ctx.http,
|
&ctx.http,
|
||||||
CreateInteractionResponse::Message(
|
CreateInteractionResponse::Defer(
|
||||||
CreateInteractionResponseMessage::new()
|
CreateInteractionResponseMessage::new().ephemeral(true),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
// Re-check blacklist / duplicate after defer (race between modal open and submit)
|
||||||
|
if let Some(pool) = service::pool() {
|
||||||
|
if let Some(reason) = service::is_blacklisted(pool, guild_id.get(), user.id.get()).await {
|
||||||
|
let _ = interaction
|
||||||
|
.create_followup(
|
||||||
|
&ctx.http,
|
||||||
|
serenity::all::CreateInteractionResponseFollowup::new()
|
||||||
.content(format!("You are blacklisted: {reason}"))
|
.content(format!("You are blacklisted: {reason}"))
|
||||||
.ephemeral(true),
|
.ephemeral(true),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
return;
|
return;
|
||||||
|
|
@ -291,27 +279,16 @@ pub async fn on_modal(ctx: Context, interaction: ModalInteraction) {
|
||||||
});
|
});
|
||||||
if exists {
|
if exists {
|
||||||
let _ = interaction
|
let _ = interaction
|
||||||
.create_response(
|
.create_followup(
|
||||||
&ctx.http,
|
&ctx.http,
|
||||||
CreateInteractionResponse::Message(
|
serenity::all::CreateInteractionResponseFollowup::new()
|
||||||
CreateInteractionResponseMessage::new()
|
|
||||||
.content("You already have an open ticket.")
|
.content("You already have an open ticket.")
|
||||||
.ephemeral(true),
|
.ephemeral(true),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Defer ephemeral thinking before heavy channel create (avoid 3s timeout)
|
|
||||||
let _ = interaction
|
|
||||||
.create_response(
|
|
||||||
&ctx.http,
|
|
||||||
CreateInteractionResponse::Defer(
|
|
||||||
CreateInteractionResponseMessage::new().ephemeral(true),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
// Use helper that supports details
|
// Use helper that supports details
|
||||||
match create_ticket_channel(&ctx, guild_id, &user, topic, label, &subject, &description).await {
|
match create_ticket_channel(&ctx, guild_id, &user, topic, label, &subject, &description).await {
|
||||||
Ok(channel_id) => {
|
Ok(channel_id) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue