1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4use tetratto_shared::{snow::Snowflake, unix_epoch_timestamp};
5use super::communities_permissions::CommunityPermission;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct Community {
9 pub id: usize,
10 pub created: usize,
11 pub title: String,
12 pub context: CommunityContext,
13 pub owner: usize,
15 pub read_access: CommunityReadAccess,
17 pub write_access: CommunityWriteAccess,
22 pub join_access: CommunityJoinAccess,
24 pub likes: isize,
25 pub dislikes: isize,
26 pub member_count: usize,
27 pub is_forge: bool,
28 pub post_count: usize,
29 pub is_forum: bool,
30 pub topics: HashMap<usize, ForumTopic>,
38}
39
40impl Community {
41 pub fn new(title: String, owner: usize) -> Self {
43 Self {
44 id: Snowflake::new().to_string().parse::<usize>().unwrap(),
45 created: unix_epoch_timestamp(),
46 title: title.clone(),
47 context: CommunityContext {
48 display_name: title,
49 ..Default::default()
50 },
51 owner,
52 read_access: CommunityReadAccess::default(),
53 write_access: CommunityWriteAccess::default(),
54 join_access: CommunityJoinAccess::default(),
55 likes: 0,
56 dislikes: 0,
57 member_count: 0,
58 is_forge: false,
59 post_count: 0,
60 is_forum: false,
61 topics: HashMap::new(),
62 }
63 }
64
65 pub fn void() -> Self {
68 Self {
69 id: 0,
70 created: 0,
71 title: "void".to_string(),
72 context: CommunityContext::default(),
73 owner: 0,
74 read_access: CommunityReadAccess::Joined,
75 write_access: CommunityWriteAccess::Owner,
76 join_access: CommunityJoinAccess::Nobody,
77 likes: 0,
78 dislikes: 0,
79 member_count: 0,
80 is_forge: false,
81 post_count: 0,
82 is_forum: false,
83 topics: HashMap::new(),
84 }
85 }
86}
87
88#[derive(Clone, Debug, Serialize, Deserialize, Default)]
89pub struct CommunityContext {
90 #[serde(default)]
91 pub display_name: String,
92 #[serde(default)]
93 pub description: String,
94 #[serde(default)]
95 pub is_nsfw: bool,
96 #[serde(default)]
97 pub enable_questions: bool,
98 #[serde(default)]
100 pub enable_titles: bool,
101 #[serde(default)]
105 pub require_titles: bool,
106}
107
108#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
110pub enum CommunityReadAccess {
111 Everybody,
113 Joined,
115}
116
117impl Default for CommunityReadAccess {
118 fn default() -> Self {
119 Self::Everybody
120 }
121}
122
123#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
125pub enum CommunityWriteAccess {
126 Everybody,
128 Joined,
132 Owner,
134}
135
136impl Default for CommunityWriteAccess {
137 fn default() -> Self {
138 Self::Joined
139 }
140}
141
142#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
144pub enum CommunityJoinAccess {
145 Nobody,
147 Everybody,
149 Request,
151}
152
153impl Default for CommunityJoinAccess {
154 fn default() -> Self {
155 Self::Everybody
156 }
157}
158
159#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct CommunityMembership {
161 pub id: usize,
162 pub created: usize,
163 pub owner: usize,
164 pub community: usize,
165 pub role: CommunityPermission,
166}
167
168impl CommunityMembership {
169 pub fn new(owner: usize, community: usize, role: CommunityPermission) -> Self {
171 Self {
172 id: Snowflake::new().to_string().parse::<usize>().unwrap(),
173 created: unix_epoch_timestamp(),
174 owner,
175 community,
176 role,
177 }
178 }
179}
180
181#[derive(Clone, Debug, Serialize, Deserialize)]
182pub struct PostContext {
183 #[serde(default = "default_comments_enabled")]
184 pub comments_enabled: bool,
185 #[serde(default)]
186 pub is_pinned: bool,
187 #[serde(default)]
188 pub is_profile_pinned: bool,
189 #[serde(default)]
190 pub edited: usize,
191 #[serde(default)]
192 pub is_nsfw: bool,
193 #[serde(default)]
194 pub repost: Option<RepostContext>,
195 #[serde(default = "default_reposts_enabled")]
196 pub reposts_enabled: bool,
197 #[serde(default)]
199 pub answering: usize,
200 #[serde(default = "default_reactions_enabled")]
201 pub reactions_enabled: bool,
202 #[serde(default)]
203 pub content_warning: String,
204 #[serde(default)]
205 pub tags: Vec<String>,
206 #[serde(default)]
207 pub full_unlist: bool,
208}
209
210fn default_comments_enabled() -> bool {
211 true
212}
213
214fn default_reposts_enabled() -> bool {
215 true
216}
217
218fn default_reactions_enabled() -> bool {
219 true
220}
221
222impl Default for PostContext {
223 fn default() -> Self {
224 Self {
225 comments_enabled: default_comments_enabled(),
226 reposts_enabled: default_reposts_enabled(),
227 is_pinned: false,
228 is_profile_pinned: false,
229 edited: 0,
230 is_nsfw: false,
231 repost: None,
232 answering: 0,
233 reactions_enabled: default_reactions_enabled(),
234 content_warning: String::new(),
235 tags: Vec::new(),
236 full_unlist: false,
237 }
238 }
239}
240
241#[derive(Clone, Debug, Serialize, Deserialize)]
242pub struct RepostContext {
243 pub is_repost: bool,
247 pub reposting: Option<usize>,
251}
252
253#[derive(Clone, Debug, Serialize, Deserialize)]
254pub struct Post {
255 pub id: usize,
256 pub created: usize,
257 pub content: String,
258 pub owner: usize,
260 pub community: usize,
262 pub context: PostContext,
264 pub replying_to: Option<usize>,
266 pub likes: isize,
267 pub dislikes: isize,
268 pub comment_count: usize,
269 pub uploads: Vec<usize>,
271 pub is_deleted: bool,
273 pub poll_id: usize,
275 pub title: String,
277 pub is_open: bool,
279 pub stack: usize,
283 pub topic: usize,
288}
289
290impl Post {
291 pub fn new(
293 content: String,
294 community: usize,
295 replying_to: Option<usize>,
296 owner: usize,
297 poll_id: usize,
298 ) -> Self {
299 Self {
300 id: Snowflake::new().to_string().parse::<usize>().unwrap(),
301 created: unix_epoch_timestamp(),
302 content,
303 owner,
304 community,
305 context: PostContext::default(),
306 replying_to,
307 likes: 0,
308 dislikes: 0,
309 comment_count: 0,
310 uploads: Vec::new(),
311 is_deleted: false,
312 poll_id,
313 title: String::new(),
314 is_open: true,
315 stack: 0,
316 topic: 0,
317 }
318 }
319
320 pub fn repost(content: String, community: usize, owner: usize, post_id: usize) -> Self {
322 let mut post = Self::new(content, community, None, owner, 0);
323
324 post.context.repost = Some(RepostContext {
325 is_repost: false,
326 reposting: Some(post_id),
327 });
328
329 post
330 }
331
332 pub fn mark_as_repost(&mut self) {
334 self.context.repost = Some(RepostContext {
335 is_repost: true,
336 reposting: None,
337 });
338 }
339}
340
341#[derive(Clone, Debug, Serialize, Deserialize)]
342pub struct Question {
343 pub id: usize,
344 pub created: usize,
345 pub owner: usize,
346 pub receiver: usize,
347 pub content: String,
348 pub is_global: bool,
353 pub answer_count: usize,
356 pub community: usize,
359 #[serde(default)]
361 pub likes: isize,
362 #[serde(default)]
363 pub dislikes: isize,
364 #[serde(default)]
366 pub context: QuestionContext,
367 #[serde(default)]
369 pub ip: String,
370 #[serde(default)]
372 pub drawings: Vec<usize>,
373}
374
375impl Question {
376 pub fn new(
378 owner: usize,
379 receiver: usize,
380 content: String,
381 is_global: bool,
382 ip: String,
383 ) -> Self {
384 Self {
385 id: Snowflake::new().to_string().parse::<usize>().unwrap(),
386 created: unix_epoch_timestamp(),
387 owner,
388 receiver,
389 content,
390 is_global,
391 answer_count: 0,
392 community: 0,
393 likes: 0,
394 dislikes: 0,
395 context: QuestionContext::default(),
396 ip,
397 drawings: Vec::new(),
398 }
399 }
400}
401
402#[derive(Debug, Clone, Serialize, Deserialize, Default)]
403pub struct QuestionContext {
404 #[serde(default)]
405 pub is_nsfw: bool,
406 #[serde(default)]
408 pub mask_owner: bool,
409 #[serde(default)]
411 pub asking_about: Option<usize>,
412}
413
414#[derive(Clone, Debug, Serialize, Deserialize)]
415pub struct PostDraft {
416 pub id: usize,
417 pub created: usize,
418 pub content: String,
419 pub owner: usize,
420}
421
422impl PostDraft {
423 pub fn new(content: String, owner: usize) -> Self {
425 Self {
426 id: Snowflake::new().to_string().parse::<usize>().unwrap(),
427 created: unix_epoch_timestamp(),
428 content,
429 owner,
430 }
431 }
432}
433
434#[derive(Clone, Debug, Serialize, Deserialize)]
435pub struct Poll {
436 pub id: usize,
437 pub owner: usize,
438 pub created: usize,
439 pub expires: usize,
441 pub option_a: String,
443 pub option_b: String,
444 pub option_c: String,
445 pub option_d: String,
446 pub votes_a: usize,
448 pub votes_b: usize,
449 pub votes_c: usize,
450 pub votes_d: usize,
451}
452
453impl Poll {
454 pub fn new(
456 owner: usize,
457 expires: usize,
458 option_a: String,
459 option_b: String,
460 option_c: String,
461 option_d: String,
462 ) -> Self {
463 Self {
464 id: Snowflake::new().to_string().parse::<usize>().unwrap(),
465 owner,
466 created: unix_epoch_timestamp(),
467 expires,
468 option_a,
470 option_b,
471 option_c,
472 option_d,
473 votes_a: 0,
475 votes_b: 0,
476 votes_c: 0,
477 votes_d: 0,
478 }
479 }
480}
481
482#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
486pub enum PollOption {
487 A,
488 B,
489 C,
490 D,
491}
492
493impl From<u8> for PollOption {
494 fn from(value: u8) -> Self {
495 match value {
496 0 => Self::A,
497 1 => Self::B,
498 2 => Self::C,
499 3 => Self::D,
500 _ => Self::A,
501 }
502 }
503}
504
505impl Into<u8> for PollOption {
506 fn into(self) -> u8 {
507 match self {
508 Self::A => 0,
509 Self::B => 1,
510 Self::C => 2,
511 Self::D => 3,
512 }
513 }
514}
515
516#[derive(Clone, Debug, Serialize, Deserialize)]
517pub struct PollVote {
518 pub id: usize,
519 pub owner: usize,
520 pub created: usize,
521 pub poll_id: usize,
522 pub vote: PollOption,
523}
524
525impl PollVote {
526 pub fn new(owner: usize, poll_id: usize, vote: PollOption) -> Self {
528 Self {
529 id: Snowflake::new().to_string().parse::<usize>().unwrap(),
530 owner,
531 created: unix_epoch_timestamp(),
532 poll_id,
533 vote,
534 }
535 }
536}
537
538#[derive(Clone, Debug, Serialize, Deserialize)]
539pub struct ForumTopic {
540 pub title: String,
541 pub description: String,
542 pub color: String,
543 pub position: i32,
544 #[serde(default)]
545 pub write_access: CommunityWriteAccess,
546}
547
548impl ForumTopic {
549 pub fn new(
555 title: String,
556 description: String,
557 color: String,
558 position: i32,
559 write_access: CommunityWriteAccess,
560 ) -> (usize, Self) {
561 (
562 Snowflake::new().to_string().parse::<usize>().unwrap(),
563 Self {
564 title,
565 description,
566 color,
567 position,
568 write_access,
569 },
570 )
571 }
572}