1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5use crate::enums::{ColorScheme, SortOrder, VoteDirection};
6
7mod datetime_format {
9 use chrono::{DateTime, Utc};
10 use serde::{self, Deserialize, Deserializer, Serializer};
11
12 pub fn serialize<S>(date: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
13 where
14 S: Serializer,
15 {
16 let s = date.to_rfc3339();
17 serializer.serialize_str(&s)
18 }
19
20 pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
21 where
22 D: Deserializer<'de>,
23 {
24 let s = String::deserialize(deserializer)?;
25 s.parse::<DateTime<Utc>>().map_err(serde::de::Error::custom)
26 }
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct User {
31 pub id: Uuid,
32 pub username: String,
33 pub bio: Option<String>,
34 #[serde(with = "datetime_format")]
35 pub join_date: DateTime<Utc>,
36 pub is_test_user: bool,
37 #[serde(default)]
38 pub is_admin: bool,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct Post {
43 pub id: Uuid,
44 pub author_id: Uuid,
45 pub author_username: String,
46 pub content: String,
47 #[serde(with = "datetime_format")]
48 pub created_at: DateTime<Utc>,
49 pub upvotes: i32,
50 pub downvotes: i32,
51 pub hashtags: Vec<String>,
52 #[serde(default)]
54 pub user_vote: Option<String>,
55 #[serde(default)]
57 pub parent_post_id: Option<Uuid>,
58 #[serde(default)]
60 pub reply_count: i32,
61 #[serde(default)]
63 pub reply_to_user_id: Option<Uuid>,
64 #[serde(default)]
66 pub reply_to_username: Option<String>,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct Vote {
71 pub user_id: Uuid,
72 pub post_id: Uuid,
73 pub direction: VoteDirection,
74 #[serde(with = "datetime_format")]
75 pub created_at: DateTime<Utc>,
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct DirectMessage {
80 pub id: Uuid,
81 pub from_user_id: Uuid,
82 pub to_user_id: Uuid,
83 #[serde(default)]
84 pub from_username: String,
85 #[serde(default)]
86 pub to_username: String,
87 pub content: String,
88 #[serde(with = "datetime_format")]
89 pub created_at: DateTime<Utc>,
90 pub is_read: bool,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct UserProfile {
95 pub user_id: Uuid,
96 pub username: String,
97 pub bio: Option<String>,
98 pub karma: i32,
99 pub post_count: i32,
100 #[serde(with = "datetime_format")]
101 pub join_date: DateTime<Utc>,
102 pub recent_hashtags: Vec<String>,
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct UserProfileView {
107 pub id: String,
108 pub username: String,
109 pub bio: Option<String>,
110 pub join_date: String,
111 pub follower_count: usize,
112 pub following_count: usize,
113 pub post_count: usize,
114 pub relationship: RelationshipStatus,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
118#[serde(tag = "type", rename_all = "snake_case")]
119pub enum RelationshipStatus {
120 #[serde(rename = "self")]
121 Self_,
122 MutualFriends,
123 Following,
124 FollowsYou,
125 None,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct UserConfig {
130 pub user_id: Uuid,
131 pub color_scheme: ColorScheme,
132 pub sort_order: SortOrder,
133 pub max_posts_display: i32,
134 pub emoji_enabled: bool,
135}
136
137impl Default for UserConfig {
138 fn default() -> Self {
139 Self {
140 user_id: Uuid::nil(),
141 color_scheme: ColorScheme::default(),
142 sort_order: SortOrder::default(),
143 max_posts_display: 25,
144 emoji_enabled: true,
145 }
146 }
147}
148
149#[derive(Debug, Serialize, Deserialize)]
151pub struct CreatePostRequest {
152 pub content: String,
153}
154
155#[derive(Debug, Serialize, Deserialize)]
156pub struct CreateReplyRequest {
157 pub content: String,
158}
159
160#[derive(Debug, Serialize, Deserialize)]
161pub struct UpdatePostRequest {
162 pub content: String,
163}
164
165#[derive(Debug, Serialize, Deserialize)]
166pub struct VoteRequest {
167 pub direction: String,
168}
169
170#[derive(Debug, Serialize, Deserialize)]
171pub struct SendMessageRequest {
172 pub to_username: String,
173 pub content: String,
174}
175
176#[derive(Debug, Serialize, Deserialize)]
177pub struct UpdateBioRequest {
178 pub bio: String,
179}
180
181#[derive(Debug, Serialize, Deserialize)]
182pub struct UpdateConfigRequest {
183 pub color_scheme: Option<String>,
184 pub sort_order: Option<String>,
185 pub max_posts_display: Option<i32>,
186 pub emoji_enabled: Option<bool>,
187}
188
189#[derive(Debug, Serialize, Deserialize)]
190pub struct LoginRequest {
191 pub username: String,
192}
193
194#[derive(Debug, Serialize, Deserialize)]
195pub struct LoginResponse {
196 pub user: User,
197 pub session_token: String,
198}
199
200#[derive(Debug, Serialize, Deserialize)]
201pub struct ErrorResponse {
202 pub error: String,
203 pub details: Option<String>,
204}