Skip to main content

agentlink_sdk/events/
mod.rs

1//! Typed Event System
2//!
3//! Provides type-safe event handling with generic ServerEvent<T>.
4//! Each event type has its own specific data structure.
5
6pub mod event_loop;
7
8use serde::{Deserialize, Serialize};
9
10/// Generic server event with typed data
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct ServerEvent<T> {
13    /// Event type identifier
14    pub event_type: String,
15    /// Event timestamp (Unix seconds)
16    pub timestamp: i64,
17    /// Sequence ID for deduplication and ordering
18    pub seq_id: i64,
19    /// Event-specific data
20    pub data: T,
21}
22
23impl<T> ServerEvent<T> {
24    /// Create a new server event
25    pub fn new(event_type: &str, seq_id: i64, data: T) -> Self {
26        Self {
27            event_type: event_type.to_string(),
28            timestamp: chrono::Utc::now().timestamp(),
29            seq_id,
30            data,
31        }
32    }
33
34    /// Get event type
35    pub fn event_type(&self) -> &str {
36        &self.event_type
37    }
38
39    /// Get reference to data
40    pub fn data(&self) -> &T {
41        &self.data
42    }
43
44    /// Consume event and return data
45    pub fn into_data(self) -> T {
46        self.data
47    }
48}
49
50// ==================== Message Events ====================
51
52/// Message received event data
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct MessageReceivedData {
55    pub id: String,
56    pub conversation_id: String,
57    pub sender_id: String,
58    pub content: Option<String>,
59    pub message_type: String,
60    pub status: String,
61    pub created_at: String,
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub reply_to_id: Option<String>,
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub data: Option<serde_json::Value>,
66}
67
68/// Message delivered event data
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct MessageDeliveredData {
71    pub message_id: String,
72    pub conversation_id: String,
73    pub delivered_at: i64,
74}
75
76/// Message read event data
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct MessageReadData {
79    pub message_id: String,
80    pub conversation_id: String,
81    pub read_at: i64,
82}
83
84/// Message deleted event data
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct MessageDeletedData {
87    pub message_id: String,
88    pub conversation_id: String,
89    pub deleted_at: i64,
90}
91
92/// Unread count updated event data
93#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct UnreadCountUpdatedData {
95    pub conversation_id: String,
96    pub unread_count: i32,
97    pub total_unread: i32,
98}
99
100/// Offline message batch event data
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct OfflineMessage {
103    pub message_id: String,
104    pub conversation_id: String,
105    pub sender_id: String,
106    pub content: Option<String>,
107    pub message_type: String,
108    pub timestamp: i64,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct OfflineMessagesBatchData {
113    pub batch: i32,
114    pub total: i32,
115    pub messages: Vec<OfflineMessage>,
116}
117
118// ==================== Friend Events ====================
119
120/// Friend request received event data
121/// 
122/// Protocol: mqtt-events.md#friend_request_received
123/// Note: This event contains the complete FriendRequest object
124#[derive(Debug, Clone, Serialize, Deserialize)]
125pub struct FriendRequestReceivedData {
126    pub id: String,
127    pub from_user_id: String,
128    pub to_user_id: String,
129    #[serde(skip_serializing_if = "Option::is_none")]
130    pub message: Option<String>,
131    pub status: String,
132    pub req_count: i32,
133    pub last_req_at: String,
134    #[serde(skip_serializing_if = "Option::is_none")]
135    pub responded_at: Option<String>,
136    #[serde(skip_serializing_if = "Option::is_none")]
137    pub responded_message: Option<String>,
138    pub expires_at: String,
139    pub created_at: String,
140    pub updated_at: String,
141}
142
143/// Friend request accepted event data
144/// 
145/// Protocol: mqtt-events.md#friend_request_accepted
146#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct FriendRequestAcceptedData {
148    pub request_id: String,
149    pub friend_id: String,
150    pub friend: crate::protocols::user::User,
151}
152
153/// Friend request rejected event data
154/// 
155/// Protocol: mqtt-events.md#friend_request_rejected
156#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct FriendRequestRejectedData {
158    pub request_id: String,
159    #[serde(skip_serializing_if = "Option::is_none")]
160    pub message: Option<String>,
161}
162
163/// Friend added event data
164/// 
165/// Protocol: mqtt-events.md#friend_added
166#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct FriendAddedData {
168    pub friend_id: String,
169    /// 可选的完整好友关系数据(服务端优化:避免触发全量同步)
170    pub friendship: Option<crate::protocols::friend::Friendship>,
171}
172
173/// Friend removed event data
174/// 
175/// Protocol: mqtt-events.md#friend_removed
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct FriendRemovedData {
178    pub friend_id: String,
179}
180
181// ==================== User Presence Events ====================
182
183/// User presence changed event data
184#[derive(Debug, Clone, Serialize, Deserialize)]
185pub struct UserPresenceChangedData {
186    pub user_id: String,
187    pub online: bool,
188    #[serde(skip_serializing_if = "Option::is_none")]
189    pub device_type: Option<String>,
190    #[serde(skip_serializing_if = "Option::is_none")]
191    pub last_seen_at: Option<String>,
192}
193
194// ==================== Blacklist Events ====================
195
196/// User blocked event data
197#[derive(Debug, Clone, Serialize, Deserialize)]
198pub struct UserBlockedData {
199    pub blocked_user_id: String,
200    pub blocked_user_nickname: String,
201    pub blocked_at: String,
202}
203
204/// User unblocked event data
205#[derive(Debug, Clone, Serialize, Deserialize)]
206pub struct UserUnblockedData {
207    pub unblocked_user_id: String,
208    pub unblocked_at: String,
209}
210
211// ==================== Sync Events ====================
212
213/// Conversation sync data
214///
215/// Protocol: mqtt-events.md#sync_conversation_list
216/// 注意:协议定义的字段有限,created_at 和 updated_at 是可选的
217#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct SyncConversation {
219    pub id: String,
220    #[serde(rename = "type")]
221    pub conversation_type: String,
222    pub name: Option<String>,
223    pub avatar: Option<String>,
224    #[serde(skip_serializing_if = "Option::is_none")]
225    pub last_msg_id: Option<String>,
226    #[serde(skip_serializing_if = "Option::is_none")]
227    pub last_msg_at: Option<String>,
228    /// 可选字段,部分事件可能不包含
229    #[serde(skip_serializing_if = "Option::is_none")]
230    pub created_at: Option<String>,
231    /// 可选字段,部分事件可能不包含
232    #[serde(skip_serializing_if = "Option::is_none")]
233    pub updated_at: Option<String>,
234}
235
236/// Sync conversation list event data
237/// 
238/// Protocol: mqtt-events.md#sync_conversation_list
239#[derive(Debug, Clone, Serialize, Deserialize)]
240pub struct SyncConversationListData {
241    pub conversations: Vec<SyncConversation>,
242    pub total: i32,
243    pub sync_id: i64,
244}
245
246// Note: SyncFriendListData is defined in protocols/friend.rs
247// It uses Friendship struct which includes the nested `friend` User object
248pub use crate::protocols::friend::SyncFriendListData;
249
250/// Message sync data
251#[derive(Debug, Clone, Serialize, Deserialize)]
252pub struct SyncMessage {
253    pub id: String,
254    pub conversation_id: String,
255    pub sender_id: String,
256    pub content: Option<String>,
257    pub message_type: String,
258    pub status: String,
259    pub created_at: String,
260}
261
262/// Sync message history event data
263/// 
264/// Protocol: mqtt-events.md#sync_message_history
265#[derive(Debug, Clone, Serialize, Deserialize)]
266pub struct SyncMessageHistoryData {
267    pub conversation_id: String,
268    pub messages: Vec<SyncMessage>,
269    pub has_more: bool,
270    #[serde(skip_serializing_if = "Option::is_none")]
271    pub next_page: Option<i32>,
272    pub sync_id: i64,
273}
274
275/// Sync conversation update event data
276#[derive(Debug, Clone, Serialize, Deserialize)]
277pub struct SyncConversationUpdateData {
278    pub id: String,
279    pub name: Option<String>,
280    pub avatar: Option<String>,
281    #[serde(skip_serializing_if = "Option::is_none")]
282    pub last_msg_id: Option<String>,
283    #[serde(skip_serializing_if = "Option::is_none")]
284    pub last_msg_at: Option<String>,
285    pub updated_at: String,
286}
287
288/// Sync friend update event data
289/// 
290/// Protocol: mqtt-events.md#sync_friend_update
291#[derive(Debug, Clone, Serialize, Deserialize)]
292pub struct SyncFriendUpdateData {
293    pub friend: crate::protocols::user::User,
294    pub update_type: String,
295}
296
297/// Friend request sync data
298/// 
299/// Protocol: data-dictionary.md#FriendRequest
300/// Reference: mqtt-events.md#sync_friend_request_list
301#[derive(Debug, Clone, Serialize, Deserialize)]
302pub struct SyncFriendRequest {
303    pub id: String,
304    pub from_user_id: String,
305    pub to_user_id: String,
306    #[serde(skip_serializing_if = "Option::is_none")]
307    pub message: Option<String>,
308    pub status: String,
309    pub req_count: i32,
310    pub last_req_at: String,
311    #[serde(skip_serializing_if = "Option::is_none")]
312    pub responded_at: Option<String>,
313    #[serde(skip_serializing_if = "Option::is_none")]
314    pub responded_message: Option<String>,
315    pub expires_at: String,
316    pub created_at: String,
317    pub updated_at: String,
318}
319
320/// Sync friend request list event data
321/// 
322/// Protocol: mqtt-events.md#sync_friend_request_list
323#[derive(Debug, Clone, Serialize, Deserialize)]
324pub struct SyncFriendRequestListData {
325    pub requests: Vec<SyncFriendRequest>,
326    pub total: i32,
327    pub sync_id: i64,
328}
329
330/// Sync complete event data
331#[derive(Debug, Clone, Serialize, Deserialize)]
332pub struct SyncCompleteData {
333    pub sync_type: String,
334    pub item_count: i32,
335    pub timestamp: String,
336}
337
338// ==================== Event Type Constants ====================
339
340pub const EVENT_MESSAGE_RECEIVED: &str = "message_received";
341pub const EVENT_MESSAGE_DELIVERED: &str = "message_delivered";
342pub const EVENT_MESSAGE_READ: &str = "message_read";
343pub const EVENT_MESSAGE_DELETED: &str = "message_deleted";
344pub const EVENT_UNREAD_COUNT_UPDATED: &str = "unread_count_updated";
345pub const EVENT_OFFLINE_MESSAGES_BATCH: &str = "offline_messages_batch";
346
347pub const EVENT_FRIEND_REQUEST_RECEIVED: &str = "friend_request_received";
348pub const EVENT_FRIEND_REQUEST_ACCEPTED: &str = "friend_request_accepted";
349pub const EVENT_FRIEND_REQUEST_REJECTED: &str = "friend_request_rejected";
350pub const EVENT_FRIEND_ADDED: &str = "friend_added";
351pub const EVENT_FRIEND_REMOVED: &str = "friend_removed";
352
353pub const EVENT_USER_PRESENCE_CHANGED: &str = "user_presence_changed";
354
355pub const EVENT_USER_BLOCKED: &str = "user_blocked";
356pub const EVENT_USER_UNBLOCKED: &str = "user_unblocked";
357
358pub const EVENT_SYNC_CONVERSATION_LIST: &str = "sync_conversation_list";
359pub const EVENT_SYNC_FRIEND_LIST: &str = "sync_friend_list";
360pub const EVENT_SYNC_MESSAGE_HISTORY: &str = "sync_message_history";
361pub const EVENT_SYNC_CONVERSATION_UPDATE: &str = "sync_conversation_update";
362pub const EVENT_SYNC_FRIEND_UPDATE: &str = "sync_friend_update";
363pub const EVENT_SYNC_FRIEND_REQUEST_LIST: &str = "sync_friend_request_list";
364pub const EVENT_SYNC_COMPLETE: &str = "sync_complete";