use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::FromRow; use uuid::Uuid; /// Channel type discriminator. /// Text chat channels keep the historical "room" naming for familiarity. #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum ChannelType { /// Text-based chat room Room, /// Voice channel Voice, /// Waterfall / masonry article post channel Article, } impl Default for ChannelType { fn default() -> Self { Self::Room } } impl std::fmt::Display for ChannelType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Room => write!(f, "room"), Self::Voice => write!(f, "voice"), Self::Article => write!(f, "article"), } } } impl From<&str> for ChannelType { fn from(s: &str) -> Self { match s { "voice" => Self::Voice, "article" => Self::Article, _ => Self::Room, } } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, FromRow)] pub struct ChannelModel { pub id: Uuid, pub wk: Uuid, pub parent: Option, pub name: String, pub topic: Option, /// Legacy DB column; mapped to `channel_type` in app logic. #[sqlx(rename = "room_type")] pub channel_type: String, pub position: i32, pub is_private: bool, pub is_archived: bool, pub ai_enabled: bool, pub created_by: Uuid, pub created_at: DateTime, pub updated_at: DateTime, pub deleted_at: Option>, } impl ChannelModel { /// Return the parsed channel type enum. pub fn channel_kind(&self) -> ChannelType { ChannelType::from(self.channel_type.as_str()) } /// Convenience: true when this is a text-chat room. pub fn is_room(&self) -> bool { self.channel_kind() == ChannelType::Room } /// Convenience: true when this is a voice channel. pub fn is_voice(&self) -> bool { self.channel_kind() == ChannelType::Voice } /// Convenience: true when this is an article post channel. pub fn is_article(&self) -> bool { self.channel_kind() == ChannelType::Article } }