1use crate::prelude::*;
2
3use serde::{Deserialize, Serialize};
4use strum::Display;
5use strum_macros::EnumString;
6
7#[tsify_next::declare]
8pub type ChatId = uuid::Uuid;
9
10#[tsify_next::declare]
11pub type ChatMessageId = uuid::Uuid;
12
13#[derive(
14 Clone, Debug, Display, Deserialize, Serialize, EnumString, JsonSchema, Tsify, PartialEq, Eq,
15)]
16#[tsify(from_wasm_abi, into_wasm_abi)]
17pub enum ChatType {
18 Global,
19 Private,
20 GlobalSystem,
21 PersonalSystem,
22 #[serde(other)]
30 Unknown,
31}
32
33#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, Tsify)]
34#[tsify(from_wasm_abi, into_wasm_abi)]
35pub struct ChatSettings {
36 #[schemars(title = "Тип чата")]
37 pub chat_type: ChatType,
38
39 #[schemars(title = "Может ли пользователь писать в чат")]
40 pub user_allowed_to_write: bool,
41
42 #[schemars(title = "Получает ли пользователь уведомление при любом сообщении")]
43 pub get_notification_on_messages: bool,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Tsify)]
47#[tsify(from_wasm_abi, into_wasm_abi)]
48pub struct ChatMessage {
49 pub id: Option<ChatMessageId>,
50 pub sender_character_id: uuid::Uuid,
51 pub recipient_character_id: Option<uuid::Uuid>,
52 pub chat_id: Option<ChatId>,
53 pub chat_type: ChatType,
54 pub text: String,
55 pub created_at: chrono::DateTime<chrono::Utc>,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Tsify)]
59#[tsify(from_wasm_abi, into_wasm_abi)]
60pub struct Chat {
61 pub id: ChatId,
62 pub chat_type: ChatType,
63 pub messages: Vec<ChatMessage>,
64 pub last_read_message_id: Option<ChatMessageId>,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Tsify)]
68#[tsify(from_wasm_abi, into_wasm_abi)]
69pub struct ReadMessage {
70 pub chat_id: ChatId,
71 pub message_id: ChatMessageId,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Tsify)]
75#[tsify(from_wasm_abi, into_wasm_abi)]
76pub struct ReportChatMessage {
77 pub message_id: ChatMessageId,
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn known_chat_types_round_trip_unchanged() {
86 for (chat_type, json) in [
87 (ChatType::Global, r#""Global""#),
88 (ChatType::Private, r#""Private""#),
89 (ChatType::GlobalSystem, r#""GlobalSystem""#),
90 (ChatType::PersonalSystem, r#""PersonalSystem""#),
91 ] {
92 assert_eq!(serde_json::to_string(&chat_type).unwrap(), json);
93 assert_eq!(serde_json::from_str::<ChatType>(json).unwrap(), chat_type);
94 }
95 }
96
97 #[test]
100 fn unknown_chat_type_string_deserializes_to_unknown() {
101 let chat_type: ChatType = serde_json::from_str(r#""GuildChat""#).unwrap();
102 assert_eq!(chat_type, ChatType::Unknown);
103 }
104
105 #[test]
108 fn schema_includes_unknown_variant() {
109 let schema = serde_json::to_value(schemars::schema_for!(ChatType)).unwrap();
110 let values: Vec<&str> = schema["enum"]
111 .as_array()
112 .expect("ChatType schema must be a plain enum")
113 .iter()
114 .map(|v| v.as_str().unwrap())
115 .collect();
116 assert_eq!(
117 values,
118 [
119 "Global",
120 "Private",
121 "GlobalSystem",
122 "PersonalSystem",
123 "Unknown"
124 ]
125 );
126 }
127}