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}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct Post {
41 pub id: Uuid,
42 pub author_id: Uuid,
43 pub author_username: String,
44 pub content: String,
45 #[serde(with = "datetime_format")]
46 pub created_at: DateTime<Utc>,
47 pub upvotes: i32,
48 pub downvotes: i32,
49 pub hashtags: Vec<String>,
50 #[serde(default)]
52 pub user_vote: Option<String>,
53 #[serde(default)]
55 pub parent_post_id: Option<Uuid>,
56 #[serde(default)]
58 pub reply_count: i32,
59 #[serde(default)]
61 pub reply_to_user_id: Option<Uuid>,
62 #[serde(default)]
64 pub reply_to_username: Option<String>,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct Vote {
69 pub user_id: Uuid,
70 pub post_id: Uuid,
71 pub direction: VoteDirection,
72 #[serde(with = "datetime_format")]
73 pub created_at: DateTime<Utc>,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct DirectMessage {
78 pub id: Uuid,
79 pub from_user_id: Uuid,
80 pub to_user_id: Uuid,
81 #[serde(default)]
82 pub from_username: String,
83 #[serde(default)]
84 pub to_username: String,
85 pub content: String,
86 #[serde(with = "datetime_format")]
87 pub created_at: DateTime<Utc>,
88 pub is_read: bool,
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize)]
92pub struct UserProfile {
93 pub user_id: Uuid,
94 pub username: String,
95 pub bio: Option<String>,
96 pub karma: i32,
97 pub post_count: i32,
98 #[serde(with = "datetime_format")]
99 pub join_date: DateTime<Utc>,
100 pub recent_hashtags: Vec<String>,
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct UserProfileView {
105 pub id: String,
106 pub username: String,
107 pub bio: Option<String>,
108 pub join_date: String,
109 pub follower_count: usize,
110 pub following_count: usize,
111 pub post_count: usize,
112 pub relationship: RelationshipStatus,
113}
114
115#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
116#[serde(tag = "type", rename_all = "snake_case")]
117pub enum RelationshipStatus {
118 #[serde(rename = "self")]
119 Self_,
120 MutualFriends,
121 Following,
122 FollowsYou,
123 None,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct UserConfig {
128 pub user_id: Uuid,
129 pub color_scheme: ColorScheme,
130 pub sort_order: SortOrder,
131 pub max_posts_display: i32,
132 pub emoji_enabled: bool,
133}
134
135impl Default for UserConfig {
136 fn default() -> Self {
137 Self {
138 user_id: Uuid::nil(),
139 color_scheme: ColorScheme::default(),
140 sort_order: SortOrder::default(),
141 max_posts_display: 25,
142 emoji_enabled: true,
143 }
144 }
145}
146
147#[derive(Debug, Serialize, Deserialize)]
149pub struct CreatePostRequest {
150 pub content: String,
151}
152
153#[derive(Debug, Serialize, Deserialize)]
154pub struct CreateReplyRequest {
155 pub content: String,
156}
157
158#[derive(Debug, Serialize, Deserialize)]
159pub struct UpdatePostRequest {
160 pub content: String,
161}
162
163#[derive(Debug, Serialize, Deserialize)]
164pub struct VoteRequest {
165 pub direction: String,
166}
167
168#[derive(Debug, Serialize, Deserialize)]
169pub struct SendMessageRequest {
170 pub to_username: String,
171 pub content: String,
172}
173
174#[derive(Debug, Serialize, Deserialize)]
175pub struct UpdateBioRequest {
176 pub bio: String,
177}
178
179#[derive(Debug, Serialize, Deserialize)]
180pub struct UpdateConfigRequest {
181 pub color_scheme: Option<String>,
182 pub sort_order: Option<String>,
183 pub max_posts_display: Option<i32>,
184 pub emoji_enabled: Option<bool>,
185}
186
187#[derive(Debug, Serialize, Deserialize)]
188pub struct LoginRequest {
189 pub username: String,
190}
191
192#[derive(Debug, Serialize, Deserialize)]
193pub struct LoginResponse {
194 pub user: User,
195 pub session_token: String,
196}
197
198#[derive(Debug, Serialize, Deserialize)]
199pub struct ErrorResponse {
200 pub error: String,
201 pub details: Option<String>,
202}