//! Emoji reaction on a message — maps to `message_reaction` table. //! //! One row per (user, message, emoji). `content` stores the emoji string //! (Unicode emoji or custom `:name:id` format like Discord). use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use uuid::Uuid; /// A single emoji reaction on a message by a user. /// /// Maps to the `message_reaction` table. One row per (user, message, emoji). #[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)] pub struct MessageReaction { pub id: Uuid, pub message_id: Uuid, pub channel_id: Uuid, pub user_id: Uuid, /// Emoji string: "👍", "🎉", or custom ":appks:01909a..." pub content: String, pub created_at: DateTime, } /// Aggregated reaction count for a single emoji on a message. /// Returned in [`MessageDetail::reactions`] and list APIs. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ReactionCount { pub content: String, pub count: i64, /// Whether the current user reacted with this emoji. pub me: bool, } #[cfg(test)] mod tests { use super::*; #[test] fn test_reaction_serialize() { let reaction = MessageReaction { id: Uuid::now_v7(), message_id: Uuid::now_v7(), channel_id: Uuid::now_v7(), user_id: Uuid::now_v7(), content: "👍".into(), created_at: Utc::now(), }; let json = serde_json::to_value(&reaction).unwrap(); assert_eq!(json["content"], "👍"); } #[test] fn test_reaction_count_serialize() { let count = ReactionCount { content: "🎉".into(), count: 3, me: true, }; let json = serde_json::to_value(&count).unwrap(); assert_eq!(json["content"], "🎉"); assert_eq!(json["count"], 3); assert_eq!(json["me"], true); } }