Add expire ban button to incidents command

This commit is contained in:
2025-08-23 02:11:23 -03:00
parent 9b70714fe3
commit 679096a685
9 changed files with 138 additions and 15 deletions
Generated
+1 -1
View File
@@ -1437,7 +1437,7 @@ checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
[[package]]
name = "payphone"
version = "4.2.6"
version = "4.2.8"
dependencies = [
"async-trait",
"axum",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "payphone"
version = "4.2.6"
version = "4.2.8"
edition = "2024"
default-run = "payphone"
+53
View File
@@ -1570,6 +1570,43 @@ impl UserIncident {
&& self.r#type == UserIncidentType::Ban
}
pub async fn get_by_user_and_incident_id(
user_id: u64,
incident_id: u64,
session: &Session,
) -> Result<Option<Self>, DatabaseError> {
let user_id = u64_to_i64(user_id);
let incident_id = u64_to_i64(incident_id);
let result = session
.query_unpaged(
r#"
SELECT
user_id,
incident_id,
report_id,
type,
message,
reason,
created_by_id,
created_at,
expires_at,
duration
FROM
payphone.user_incidents
WHERE
user_id = ? AND incident_id = ?;
"#,
(user_id, incident_id),
)
.await
.map_err(DatabaseError::QueryError)?
.into_rows_result()
.map_err(|_| DatabaseError::ResultNotRows)?;
get_single_row_from_result(&result).await
}
pub async fn get_for_user(user_id: u64, session: &Session) -> Result<Vec<Self>, DatabaseError> {
let user_id = u64_to_i64(user_id);
@@ -1655,4 +1692,20 @@ impl UserIncident {
Ok(())
}
pub async fn expire_by_user_and_incident_id(
user_id: u64,
incident_id: u64,
session: &Session,
) -> Result<(), DatabaseError> {
let Some(mut incident) =
Self::get_by_user_and_incident_id(user_id, incident_id, session).await?
else {
return Ok(());
};
incident.expires_at = Some(UtcDateTime::now());
incident.insert(session).await
}
}
+1 -1
View File
@@ -63,7 +63,7 @@ pub trait Command<T, E>: Send + Sync + Debug {
vec![]
}
fn show_in_help(&self, rt: &Runtime<T, E>, extras: &E) -> bool {
fn show_in_help(&self, _rt: &Runtime<T, E>, _extras: &E) -> bool {
true
}
+1 -1
View File
@@ -90,7 +90,7 @@ impl OnMessageHandler<State, Extras> for CallMessageHandler {
&self,
event: &MessageCreate,
rt: Arc<Runtime<State, Extras>>,
extras: Arc<dyn ExtrasGetter<State, Extras = Extras>>,
_extras: Arc<dyn ExtrasGetter<State, Extras = Extras>>,
) -> EventResult {
if event.author.bot || event.author.system.unwrap_or(false) {
return Ok(());
+1 -1
View File
@@ -46,7 +46,7 @@ impl OnMessageHandler<State, Extras> for MessageLevelingHandler {
&self,
event: &MessageCreate,
rt: Arc<Runtime<State, Extras>>,
extras: Arc<dyn ExtrasGetter<State, Extras = Extras>>,
_extras: Arc<dyn ExtrasGetter<State, Extras = Extras>>,
) -> EventResult {
if event.author.bot || event.author.system.unwrap_or(false) {
return Ok(());
+54
View File
@@ -78,6 +78,60 @@ impl Button<State, Extras> for CounterButton {
}
}
#[derive(Debug)]
pub struct ExpireIncidentButton {
pub user_id: u64,
pub incident_id: u64,
pub incident_index: usize,
}
#[async_trait]
impl Button<State, Extras> for ExpireIncidentButton {
fn id(&self) -> Option<String> {
Some(format!("incidents:expire:{}", get_random_u64()))
}
fn label(&self) -> Option<String> {
Some("Expire Incident".into())
}
fn style(&self) -> ButtonStyle {
ButtonStyle::Danger
}
fn disabled(&self) -> bool {
false
}
async fn on_press(
&self,
ctx: InteractionContext<State, Extras>,
) -> Result<(), InteractionError> {
if !ctx.extras.user.is_moderator {
ctx.defer().await?;
return Ok(());
}
UserIncident::expire_by_user_and_incident_id(
self.user_id,
self.incident_id,
&ctx.rt.state.db,
)
.await?;
ctx.edit_original_message(
get_incident_page(self.user_id, &ctx.rt.state.db, self.incident_index)
.await
.inspect_err(|e| log::error!("Failed to get incident page: {e:?}"))?
.into(),
)
.await
.inspect_err(|e| log::error!("Failed to edit original message: {e:?}"))?;
Ok(())
}
}
#[derive(Debug)]
pub struct DeleteIncidentButton {
pub user_id: u64,
+2 -2
View File
@@ -48,7 +48,7 @@ pub fn incident_embed(incident: &UserIncident) -> Embed {
incident
.created_by_id
.map(|id| format!("<@{id}>"))
.unwrap_or("Automod".into()),
.unwrap_or("Automatic Moderator".into()),
));
if incident.r#type == UserIncidentType::Ban {
@@ -81,7 +81,7 @@ pub fn incident_embed(incident: &UserIncident) -> Embed {
incident
.created_by_id
.map(|id| format!("<@{id}>"))
.unwrap_or("Automod".into()),
.unwrap_or("Automatic Moderator".into()),
));
if incident.r#type == UserIncidentType::Ban {
+23 -7
View File
@@ -1,11 +1,13 @@
use scylla::client::session::Session;
use crate::{
database::models::{DatabaseError, UserIncident},
database::models::{DatabaseError, UserIncident, UserIncidentType},
extras::Extras,
framework::messages::MessageBuilder,
groups::moderation::{
components::{ArrowIncidentButton, CounterButton, DeleteIncidentButton},
components::{
ArrowIncidentButton, CounterButton, DeleteIncidentButton, ExpireIncidentButton,
},
embeds::incident_embed,
},
state::State,
@@ -27,7 +29,7 @@ pub(super) async fn get_incident_page(
incidents.sort_by(|a, b| b.created_at.cmp(&a.created_at));
if let Some(incident) = incidents.get(page_index) {
Ok(MessageBuilder::new()
let mut builder = MessageBuilder::new()
.embed(incident_embed(incident))
.component(
ArrowIncidentButton {
@@ -55,15 +57,29 @@ pub(super) async fn get_incident_page(
go_to: incidents.get(page_index + 1).map(|_| page_index + 1),
},
1,
)
.component(
);
if incident.r#type == UserIncidentType::Ban {
builder = builder.component(
ExpireIncidentButton {
incident_id: incident.incident_id,
incident_index: page_index,
user_id,
},
2,
);
}
builder = builder.component(
DeleteIncidentButton {
incident_id: incident.incident_id,
incident_index: page_index,
user_id,
},
1,
))
2,
);
Ok(builder)
} else {
Ok(MessageBuilder::new().content("No incidents found for this user."))
}