feat(ticket): cooldown 5m after close (DB ticket_cooldowns + check on create)
This commit is contained in:
parent
9c0b2624e2
commit
2a7ace8c09
4 changed files with 75 additions and 2 deletions
|
|
@ -12,8 +12,12 @@ pub async fn run(pool: &SqlitePool) -> anyhow::Result<()> {
|
|||
.execute(pool)
|
||||
.await?;
|
||||
|
||||
let migrations =
|
||||
[("V1__initial", V1_INITIAL), ("V2__tickets", V2_TICKETS), ("V3__reminders", V3_REMINDERS)];
|
||||
let migrations = [
|
||||
("V1__initial", V1_INITIAL),
|
||||
("V2__tickets", V2_TICKETS),
|
||||
("V3__reminders", V3_REMINDERS),
|
||||
("V4__ticket_cooldown", V4_COOLDOWN),
|
||||
];
|
||||
for (name, sql) in migrations {
|
||||
let exists: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM _migrations WHERE name = ?")
|
||||
.bind(name)
|
||||
|
|
@ -76,3 +80,11 @@ CREATE TABLE IF NOT EXISTS reminders (
|
|||
sent INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
";
|
||||
const V4_COOLDOWN: &str = "
|
||||
CREATE TABLE IF NOT EXISTS ticket_cooldowns (
|
||||
user_id TEXT NOT NULL,
|
||||
guild_id TEXT NOT NULL,
|
||||
expires_at INTEGER NOT NULL,
|
||||
PRIMARY KEY (user_id, guild_id)
|
||||
);
|
||||
";
|
||||
|
|
|
|||
|
|
@ -146,8 +146,18 @@ pub async fn handle_close_modal(ctx: Context, interaction: serenity::all::ModalI
|
|||
haste_url.clone(),
|
||||
)
|
||||
.await;
|
||||
let opener_for_cooldown = if let Some(pool) = service::pool() {
|
||||
service::get_opener(pool, channel_id.get()).await
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(pool) = service::pool() {
|
||||
service::cleanup_ticket(pool, channel_id.get()).await;
|
||||
if let Some(opener) = opener_for_cooldown {
|
||||
if let Some(gid) = interaction.guild_id {
|
||||
service::set_cooldown(pool, gid.get(), opener, 300).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
let control_row = serenity::all::CreateActionRow::Buttons(vec![
|
||||
serenity::all::CreateButton::new("ticket_reopen")
|
||||
|
|
|
|||
|
|
@ -136,6 +136,20 @@ pub async fn on_modal(ctx: Context, interaction: ModalInteraction) {
|
|||
.await;
|
||||
return;
|
||||
}
|
||||
if let Some(rem) = service::is_on_cooldown(pool, guild_id.get(), user.id.get()).await {
|
||||
let _ = interaction
|
||||
.create_followup(
|
||||
&ctx.http,
|
||||
serenity::all::CreateInteractionResponseFollowup::new()
|
||||
.content(format!(
|
||||
"Cooldown: wait {}s before new ticket (5m after close).",
|
||||
rem
|
||||
))
|
||||
.ephemeral(true),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if let Ok(channels) = guild_id.channels(&ctx.http).await {
|
||||
let exists = channels.values().any(|c| {
|
||||
|
|
|
|||
|
|
@ -65,6 +65,43 @@ pub async fn cleanup_ticket(p: &SqlitePool, c: u64) {
|
|||
let _ = sqlx::query("DELETE FROM tickets WHERE channel_id=?").bind(c.to_string()).execute(p).await;
|
||||
let _ = sqlx::query("DELETE FROM ticket_claims WHERE channel_id=?").bind(c.to_string()).execute(p).await;
|
||||
}
|
||||
pub async fn is_on_cooldown(p: &SqlitePool, g: u64, u: u64) -> Option<u64> {
|
||||
let _ = sqlx::query("CREATE TABLE IF NOT EXISTS ticket_cooldowns (user_id TEXT NOT NULL, guild_id TEXT NOT NULL, expires_at INTEGER NOT NULL, PRIMARY KEY (user_id, guild_id))").execute(p).await;
|
||||
let row: Option<(i64,)> =
|
||||
sqlx::query_as("SELECT expires_at FROM ticket_cooldowns WHERE user_id=? AND guild_id=?")
|
||||
.bind(u.to_string())
|
||||
.bind(g.to_string())
|
||||
.fetch_optional(p)
|
||||
.await
|
||||
.unwrap_or(None);
|
||||
if let Some((exp,)) = row {
|
||||
let now =
|
||||
std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs()
|
||||
as i64;
|
||||
if exp > now {
|
||||
return Some((exp - now) as u64);
|
||||
}
|
||||
let _ = sqlx::query("DELETE FROM ticket_cooldowns WHERE user_id=? AND guild_id=?")
|
||||
.bind(u.to_string())
|
||||
.bind(g.to_string())
|
||||
.execute(p)
|
||||
.await;
|
||||
}
|
||||
None
|
||||
}
|
||||
pub async fn set_cooldown(p: &SqlitePool, g: u64, u: u64, secs: u64) {
|
||||
let _ = sqlx::query("CREATE TABLE IF NOT EXISTS ticket_cooldowns (user_id TEXT NOT NULL, guild_id TEXT NOT NULL, expires_at INTEGER NOT NULL, PRIMARY KEY (user_id, guild_id))").execute(p).await;
|
||||
let exp = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs()
|
||||
+ secs;
|
||||
let _ = sqlx::query(
|
||||
"INSERT OR REPLACE INTO ticket_cooldowns(user_id, guild_id, expires_at) VALUES(?,?,?)",
|
||||
)
|
||||
.bind(u.to_string())
|
||||
.bind(g.to_string())
|
||||
.bind(exp as i64)
|
||||
.execute(p)
|
||||
.await;
|
||||
}
|
||||
pub async fn add_user_to_ticket(
|
||||
http: &Http,
|
||||
channel_id: ChannelId,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue