1use super::id::Id;
2use serde::{Serialize, Deserialize};
3use serde_valid::Validate;
4use tritools::time::unix_epoch_timestamp;
5
6#[derive(Clone, Debug, Serialize, Deserialize, Validate)]
7pub struct PostContext {
8 #[serde(default = "default_comments_enabled")]
9 pub comments_enabled: bool,
10 #[serde(default)]
11 pub is_profile_pinned: bool,
12 #[serde(default)]
13 pub edited: u128,
14 #[serde(default)]
15 pub is_nsfw: bool,
16 #[serde(default)]
17 pub repost: Option<RepostContext>,
18 #[serde(default = "default_reposts_enabled")]
19 pub reposts_enabled: bool,
20 #[serde(default)]
22 pub answering: Option<Id>,
23 #[serde(default = "default_reactions_enabled")]
24 pub reactions_enabled: bool,
25 #[serde(default)]
26 #[validate(max_length = 1024)]
27 pub content_warning: String,
28 #[serde(default)]
29 #[validate(max_items = 12)]
30 pub tags: Vec<String>,
31}
32
33fn default_comments_enabled() -> bool {
34 true
35}
36
37fn default_reposts_enabled() -> bool {
38 true
39}
40
41fn default_reactions_enabled() -> bool {
42 true
43}
44
45impl Default for PostContext {
46 fn default() -> Self {
47 Self {
48 comments_enabled: default_comments_enabled(),
49 reposts_enabled: default_reposts_enabled(),
50 is_profile_pinned: false,
51 edited: 0,
52 is_nsfw: false,
53 repost: None,
54 answering: None,
55 reactions_enabled: default_reactions_enabled(),
56 content_warning: String::new(),
57 tags: Vec::new(),
58 }
59 }
60}
61
62#[derive(Clone, Debug, Serialize, Deserialize)]
63pub struct RepostContext {
64 pub is_repost: bool,
68 pub reposting: Option<Id>,
72}
73
74#[derive(Clone, Debug, Serialize, Deserialize)]
75pub struct Post {
76 pub id: Id,
77 pub created: u128,
78 pub content: String,
79 pub owner: Id,
81 pub context: PostContext,
83 pub replying_to: Option<Id>,
85 pub likes: isize,
86 pub dislikes: isize,
87 pub comment_count: usize,
88 pub uploads: Vec<usize>,
90 pub is_deleted: bool,
92 pub poll_id: Option<Id>,
94 pub views: usize,
95 pub group: Option<Id>,
96 pub limited_reach: bool,
97}
98
99impl Post {
100 pub fn new(
102 content: String,
103 replying_to: Option<Id>,
104 owner: Id,
105 poll_id: Option<Id>,
106 group: Option<Id>,
107 ) -> Self {
108 Self {
109 id: Id::new(),
110 created: unix_epoch_timestamp(),
111 content,
112 owner,
113 context: PostContext::default(),
114 replying_to,
115 likes: 0,
116 dislikes: 0,
117 comment_count: 0,
118 uploads: Vec::new(),
119 is_deleted: false,
120 poll_id,
121 views: 0,
122 group,
123 limited_reach: false,
124 }
125 }
126
127 pub fn repost(content: String, owner: Id, post_id: Id) -> Self {
129 let mut post = Self::new(content, None, owner, None, None);
130
131 post.context.repost = Some(RepostContext {
132 is_repost: false,
133 reposting: Some(post_id),
134 });
135
136 post
137 }
138
139 pub fn mark_as_repost(&mut self) {
141 self.context.repost = Some(RepostContext {
142 is_repost: true,
143 reposting: None,
144 });
145 }
146
147 pub fn can_comment(&self) -> bool {
149 self.context.repost.is_none() || !self.content.is_empty()
150 }
151}
152
153#[derive(Clone, Debug, Serialize, Deserialize)]
154pub struct Question {
155 pub id: Id,
156 pub created: u128,
157 pub owner: Id,
158 pub receiver: Id,
159 pub content: String,
160 pub is_global: bool,
165 pub answer_count: usize,
168 #[serde(default)]
170 pub likes: isize,
171 #[serde(default)]
172 pub dislikes: isize,
173 #[serde(default)]
175 pub context: QuestionContext,
176 #[serde(default)]
178 pub ip: String,
179 #[serde(default)]
181 pub drawings: Vec<usize>,
182}
183
184impl Question {
185 pub fn new(owner: Id, receiver: Id, content: String, is_global: bool, ip: String) -> Self {
187 Self {
188 id: Id::new(),
189 created: unix_epoch_timestamp(),
190 owner,
191 receiver,
192 content,
193 is_global,
194 answer_count: 0,
195 likes: 0,
196 dislikes: 0,
197 context: QuestionContext::default(),
198 ip,
199 drawings: Vec::new(),
200 }
201 }
202}
203
204#[derive(Debug, Clone, Serialize, Deserialize, Default)]
205pub struct QuestionContext {
206 #[serde(default)]
207 pub is_nsfw: bool,
208 #[serde(default)]
210 pub mask_owner: bool,
211 #[serde(default)]
213 pub asking_about: Option<Id>,
214}
215
216#[derive(Clone, Debug, Serialize, Deserialize)]
217pub struct PostDraft {
218 pub id: Id,
219 pub created: u128,
220 pub content: String,
221 pub owner: Id,
222}
223
224impl PostDraft {
225 pub fn new(content: String, owner: Id) -> Self {
227 Self {
228 id: Id::new(),
229 created: unix_epoch_timestamp(),
230 content,
231 owner,
232 }
233 }
234}
235
236#[derive(Clone, Debug, Serialize, Deserialize)]
237pub struct Poll {
238 pub id: Id,
239 pub owner: Id,
240 pub created: u128,
241 pub expires: u128,
243 pub option_a: String,
245 pub option_b: String,
246 pub option_c: String,
247 pub option_d: String,
248 pub votes_a: usize,
250 pub votes_b: usize,
251 pub votes_c: usize,
252 pub votes_d: usize,
253}
254
255impl Poll {
256 pub fn new(
258 owner: Id,
259 expires: u128,
260 option_a: String,
261 option_b: String,
262 option_c: String,
263 option_d: String,
264 ) -> Self {
265 Self {
266 id: Id::new(),
267 owner,
268 created: unix_epoch_timestamp(),
269 expires,
270 option_a,
272 option_b,
273 option_c,
274 option_d,
275 votes_a: 0,
277 votes_b: 0,
278 votes_c: 0,
279 votes_d: 0,
280 }
281 }
282}
283
284#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
288pub enum PollOption {
289 A,
290 B,
291 C,
292 D,
293}
294
295impl From<u8> for PollOption {
296 fn from(value: u8) -> Self {
297 match value {
298 0 => Self::A,
299 1 => Self::B,
300 2 => Self::C,
301 3 => Self::D,
302 _ => Self::A,
303 }
304 }
305}
306
307impl From<PollOption> for u8 {
308 fn from(val: PollOption) -> Self {
309 match val {
310 PollOption::A => 0,
311 PollOption::B => 1,
312 PollOption::C => 2,
313 PollOption::D => 3,
314 }
315 }
316}
317
318#[derive(Clone, Debug, Serialize, Deserialize)]
319pub struct PollVote {
320 pub id: Id,
321 pub owner: Id,
322 pub created: u128,
323 pub poll_id: Id,
324 pub vote: PollOption,
325}
326
327impl PollVote {
328 pub fn new(owner: Id, poll_id: Id, vote: PollOption) -> Self {
330 Self {
331 id: Id::new(),
332 owner,
333 created: unix_epoch_timestamp(),
334 poll_id,
335 vote,
336 }
337 }
338}