821537186e
- 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
96 lines
3.0 KiB
Rust
96 lines
3.0 KiB
Rust
//! Interactive message components — maps to `message_component` table.
|
|
//!
|
|
//! Discord-style interactive elements attached to messages: buttons, select
|
|
//! menus, etc. Each component belongs to a message and has its own layout row.
|
|
//! Clicking a component emits an interaction event back to the bot/webhook.
|
|
|
|
use chrono::{DateTime, Utc};
|
|
use serde::{Deserialize, Serialize};
|
|
use uuid::Uuid;
|
|
|
|
/// An interactive component attached to a message (button, select menu, etc.).
|
|
///
|
|
/// Maps to the `message_component` table. Each component belongs to a message
|
|
/// and has a layout row/position. User interactions emit callbacks.
|
|
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
|
|
pub struct MessageComponent {
|
|
pub id: Uuid,
|
|
pub message_id: Uuid,
|
|
/// Layout row within the message (0-based).
|
|
pub row: i32,
|
|
/// Position within the row (0-based).
|
|
pub position: i32,
|
|
/// "button" | "select_menu" | "text_input"
|
|
pub component_type: String,
|
|
/// Unique identifier sent back in interaction callbacks.
|
|
pub custom_id: String,
|
|
/// Display label.
|
|
pub label: Option<String>,
|
|
/// Emoji shown on the button (unicode or `:name:id`).
|
|
pub emoji: Option<String>,
|
|
/// Button style: "primary" | "secondary" | "success" | "danger" | "link"
|
|
pub style: Option<String>,
|
|
/// URL for link-style buttons.
|
|
pub url: Option<String>,
|
|
/// Whether the component is disabled.
|
|
pub disabled: bool,
|
|
/// Placeholder text for select menus.
|
|
pub placeholder: Option<String>,
|
|
/// Min/max selections for select menus.
|
|
pub min_values: Option<i32>,
|
|
pub max_values: Option<i32>,
|
|
/// Options for select menus, stored as JSON array.
|
|
pub options: Option<serde_json::Value>,
|
|
pub created_at: DateTime<Utc>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum ComponentType {
|
|
#[default]
|
|
Button,
|
|
SelectMenu,
|
|
TextInput,
|
|
}
|
|
|
|
impl ComponentType {
|
|
pub fn as_str(&self) -> &'static str {
|
|
match self {
|
|
Self::Button => "button",
|
|
Self::SelectMenu => "select_menu",
|
|
Self::TextInput => "text_input",
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_component_serialize() {
|
|
let c = MessageComponent {
|
|
id: Uuid::now_v7(),
|
|
message_id: Uuid::now_v7(),
|
|
row: 0,
|
|
position: 0,
|
|
component_type: ComponentType::Button.as_str().into(),
|
|
custom_id: "btn_approve".into(),
|
|
label: Some("Approve".into()),
|
|
emoji: Some("✅".into()),
|
|
style: Some("success".into()),
|
|
url: None,
|
|
disabled: false,
|
|
placeholder: None,
|
|
min_values: None,
|
|
max_values: None,
|
|
options: None,
|
|
created_at: Utc::now(),
|
|
};
|
|
|
|
let json = serde_json::to_value(&c).unwrap();
|
|
assert_eq!(json["component_type"], "button");
|
|
assert_eq!(json["style"], "success");
|
|
}
|
|
}
|