refactor(tests): reformat code and update dependency management

- Reorganized import statements in adapter tests for better readability
- Replaced or_insert_with(Vec::new) with or_default() in test closures
- Updated Cargo.lock with new dependency versions and checksums
- Added TLS features to tonic dependency configuration
- Included sqlx, chrono, and uuid dependencies with specific features
- Added jsonwebtoken and arc-swap as project dependencies
- Reformatted assertion statements to comply with line length limits
- Adjusted base64 import order in engine codec module
- Updated protobuf include statement formatting
This commit is contained in:
zhenyi
2026-06-11 12:11:05 +08:00
parent 06e8ee96a5
commit 821537186e
111 changed files with 10458 additions and 385 deletions
+98
View File
@@ -0,0 +1,98 @@
//! Interactive component event handlers on `MessageService`.
//!
//! Handles button clicks and select menu interactions on message components.
//! When a user clicks a button, the server updates the component state and
//! broadcasts the interaction to the channel.
use std::sync::Arc;
use uuid::Uuid;
use crate::ImksError;
use crate::socket::socket::Socket;
use super::message::MessageService;
impl MessageService {
/// Handle `component:interact` — a user clicked a button or selected from a menu.
pub async fn interact_component(
&self,
socket: Arc<Socket>,
data: &serde_json::Value,
) -> crate::ImksResult<()> {
let user_id = self.user_id(&socket)?;
let arr = data
.as_array()
.and_then(|a| a.first())
.ok_or_else(|| ImksError::InvalidInput("Expected [payload] array".into()))?;
let component_id: Uuid = Self::parse_field(arr, "component_id")?;
let custom_id: String = Self::parse_field(arr, "custom_id")?;
let message_id: Uuid = Self::parse_field(arr, "message_id")?;
let channel_id: Uuid = Self::parse_field(arr, "channel_id")?;
// Get current components to verify the interaction is valid
let components = self.repo.get_components(message_id).await?;
let component = components.iter().find(|c| c.id == component_id);
if component.is_none() {
return Err(ImksError::NotFound(format!("component {component_id}")));
}
// Broadcast the interaction event to all clients in the channel.
// The actual action (e.g., approve/deny) is handled by the bot/webhook
// that listens for this event. The server just relays and disables the
// component to prevent double-clicks.
if let Some(ns) = self.namespaces.get_namespace(&socket.namespace) {
ns.emit_to_room(
&channel_id.to_string(),
"component:interaction",
serde_json::json!({
"component_id": component_id.to_string(),
"custom_id": custom_id,
"message_id": message_id.to_string(),
"user_id": user_id.to_string(),
"channel_id": channel_id.to_string(),
}),
)
.await;
}
tracing::info!(%component_id, %user_id, %custom_id, "Component interaction");
Ok(())
}
/// Handle `component:update` — update a component's state (e.g., disable after interaction).
#[allow(dead_code)]
pub async fn update_component(
&self,
socket: Arc<Socket>,
data: &serde_json::Value,
) -> crate::ImksResult<()> {
let arr = data
.as_array()
.and_then(|a| a.first())
.ok_or_else(|| ImksError::InvalidInput("Expected [payload] array".into()))?;
let component_id: Uuid = Self::parse_field(arr, "component_id")?;
let label: Option<String> = Self::parse_optional(arr, "label")?;
let disabled: bool = Self::parse_optional(arr, "disabled")?.unwrap_or(true);
if let Some(updated) = self
.repo
.update_component(component_id, label.as_deref(), disabled)
.await?
&& let Some(ns) = self.namespaces.get_namespace(&socket.namespace)
{
ns.emit_to_room(
&updated.message_id.to_string(),
"component:updated",
serde_json::to_value(&updated).unwrap_or_default(),
)
.await;
}
Ok(())
}
}