1use serde::{Deserialize, Serialize};
19use std::collections::HashMap;
20
21#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
23pub enum OnlineStatus {
24 Online,
26 Recently,
28 LastWeek,
30 LastMonth,
32 LongTimeAgo,
34 Offline,
36}
37
38impl OnlineStatus {
39 pub fn from_elapsed_seconds(elapsed: i64) -> Self {
41 match elapsed {
42 0..=180 => OnlineStatus::Online, 181..=3600 => OnlineStatus::Recently, 3601..=604800 => OnlineStatus::LastWeek, 604801..=2592000 => OnlineStatus::LastMonth, _ => OnlineStatus::LongTimeAgo,
47 }
48 }
49
50 pub fn as_str(&self) -> &'static str {
52 match self {
53 OnlineStatus::Online => "online",
54 OnlineStatus::Recently => "recently",
55 OnlineStatus::LastWeek => "last_week",
56 OnlineStatus::LastMonth => "last_month",
57 OnlineStatus::LongTimeAgo => "long_time_ago",
58 OnlineStatus::Offline => "offline",
59 }
60 }
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct OnlineStatusInfo {
66 pub user_id: u64,
68 pub status: OnlineStatus,
70 pub last_seen: i64,
72 pub online_devices: Vec<super::DeviceType>,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct SubscribePresenceRequest {
79 pub user_ids: Vec<u64>,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct SubscribePresenceResponse {
87 pub initial_statuses: HashMap<u64, OnlineStatusInfo>,
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize)]
93pub struct UnsubscribePresenceRequest {
94 pub user_ids: Vec<u64>,
96}
97
98pub type UnsubscribePresenceResponse = bool;
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct GetOnlineStatusRequest {
105 pub user_ids: Vec<u64>,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct GetOnlineStatusResponse {
112 pub code: i32,
114 pub message: String,
116 pub statuses: HashMap<u64, OnlineStatusInfo>,
118}
119
120#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct OnlineStatusChangeNotification {
123 pub user_id: u64,
125 pub old_status: OnlineStatus,
127 pub new_status: OnlineStatus,
129 pub last_seen: i64,
131 pub timestamp: i64,
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
137pub enum TypingActionType {
138 Typing,
140 Recording,
142 UploadingPhoto,
144 UploadingVideo,
146 UploadingFile,
148 ChoosingSticker,
150}
151
152impl TypingActionType {
153 pub fn as_str(&self) -> &'static str {
154 match self {
155 TypingActionType::Typing => "typing",
156 TypingActionType::Recording => "recording",
157 TypingActionType::UploadingPhoto => "uploading_photo",
158 TypingActionType::UploadingVideo => "uploading_video",
159 TypingActionType::UploadingFile => "uploading_file",
160 TypingActionType::ChoosingSticker => "choosing_sticker",
161 }
162 }
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct TypingIndicatorRequest {
168 pub channel_id: u64,
170 pub channel_type: u8,
172 pub is_typing: bool,
174 pub action_type: TypingActionType,
176}
177
178#[derive(Debug, Clone, Serialize, Deserialize)]
180pub struct TypingIndicatorResponse {
181 pub code: i32,
183 pub message: String,
185}
186
187#[derive(Debug, Clone, Serialize, Deserialize)]
189pub struct TypingStatusNotification {
190 pub user_id: u64,
192 pub username: Option<String>,
194 pub channel_id: u64,
196 pub channel_type: u8,
198 pub is_typing: bool,
200 pub action_type: TypingActionType,
202 pub timestamp: i64,
204}
205
206#[derive(Debug, Clone, Serialize, Deserialize)]
208pub struct PresencePrivacySettings {
209 pub show_online_to: PrivacyRule,
211 pub show_last_seen_to: PrivacyRule,
213}
214
215#[derive(Debug, Clone, Serialize, Deserialize)]
217pub enum PrivacyRule {
218 Everyone,
220 Contacts,
222 Nobody,
224 Custom {
226 allow_users: Vec<u64>,
228 deny_users: Vec<u64>,
230 },
231}
232
233impl Default for PresencePrivacySettings {
234 fn default() -> Self {
235 Self {
236 show_online_to: PrivacyRule::Everyone,
237 show_last_seen_to: PrivacyRule::Everyone,
238 }
239 }
240}
241
242#[derive(Debug, Clone, Serialize, Deserialize)]
244pub struct GetGroupOnlineStatsRequest {
245 pub group_id: u64,
247 pub include_user_list: bool,
249}
250
251#[derive(Debug, Clone, Serialize, Deserialize)]
253pub struct GetGroupOnlineStatsResponse {
254 pub code: i32,
256 pub message: String,
258 pub group_id: u64,
260 pub total_members: u32,
262 pub online_count: u32,
264 pub online_users: Option<Vec<OnlineStatusInfo>>,
266}
267
268#[cfg(test)]
269mod tests {
270 use super::*;
271
272 #[test]
273 fn test_online_status_calculation() {
274 assert_eq!(OnlineStatus::from_elapsed_seconds(0), OnlineStatus::Online);
275 assert_eq!(
276 OnlineStatus::from_elapsed_seconds(180),
277 OnlineStatus::Online
278 );
279 assert_eq!(
280 OnlineStatus::from_elapsed_seconds(181),
281 OnlineStatus::Recently
282 );
283 assert_eq!(
284 OnlineStatus::from_elapsed_seconds(3600),
285 OnlineStatus::Recently
286 );
287 assert_eq!(
288 OnlineStatus::from_elapsed_seconds(3601),
289 OnlineStatus::LastWeek
290 );
291 }
292
293 #[test]
294 fn test_privacy_rule_default() {
295 let settings = PresencePrivacySettings::default();
296 assert!(matches!(settings.show_online_to, PrivacyRule::Everyone));
297 assert!(matches!(settings.show_last_seen_to, PrivacyRule::Everyone));
298 }
299}