1use chrono::{DateTime, Utc};
2use diesel::{ExpressionMethods, QueryDsl, Queryable, Selectable, SelectableHelper};
3use diesel_async::RunQueryDsl;
4use serde::{Deserialize, Serialize};
5use uuid::Uuid;
6
7use crate::{Conn, error::Error, objects::Me, schema::users, utils::CacheFns};
8
9use super::load_or_empty;
10
11#[derive(Deserialize, Serialize, Clone, Queryable, Selectable)]
12#[diesel(table_name = users)]
13#[diesel(check_for_backend(diesel::pg::Pg))]
14pub struct UserBuilder {
15 uuid: Uuid,
16 username: String,
17 display_name: Option<String>,
18 avatar: Option<String>,
19 pronouns: Option<String>,
20 about: Option<String>,
21 online_status: i16,
22}
23
24impl UserBuilder {
25 pub fn build(self) -> User {
26 User {
27 uuid: self.uuid,
28 username: self.username,
29 display_name: self.display_name,
30 avatar: self.avatar,
31 pronouns: self.pronouns,
32 about: self.about,
33 online_status: self.online_status,
34 friends_since: None,
35 }
36 }
37}
38
39#[derive(Deserialize, Serialize, Clone)]
40pub struct User {
41 pub uuid: Uuid,
42 username: String,
43 display_name: Option<String>,
44 avatar: Option<String>,
45 pronouns: Option<String>,
46 about: Option<String>,
47 online_status: i16,
48 pub friends_since: Option<DateTime<Utc>>,
49}
50
51impl User {
52 pub async fn fetch_one(
53 conn: &mut Conn,
54 cache_pool: &redis::Client,
55 user_uuid: Uuid,
56 ) -> Result<Self, Error> {
57 if let Ok(cache_hit) = cache_pool.get_cache_key(user_uuid.to_string()).await {
58 return Ok(cache_hit);
59 }
60
61 use users::dsl;
62 let user_builder: UserBuilder = dsl::users
63 .filter(dsl::uuid.eq(user_uuid))
64 .select(UserBuilder::as_select())
65 .get_result(conn)
66 .await?;
67
68 let user = user_builder.build();
69
70 cache_pool
71 .set_cache_key(user_uuid.to_string(), user.clone(), 1800)
72 .await?;
73
74 Ok(user)
75 }
76
77 pub async fn fetch_one_with_friendship(
78 conn: &mut Conn,
79 cache_pool: &redis::Client,
80 me: &Me,
81 user_uuid: Uuid,
82 ) -> Result<Self, Error> {
83 let mut user = Self::fetch_one(conn, cache_pool, user_uuid).await?;
84
85 if let Some(friend) = me.friends_with(conn, user_uuid).await? {
86 user.friends_since = Some(friend.accepted_at);
87 }
88
89 Ok(user)
90 }
91
92 pub async fn fetch_amount(
93 conn: &mut Conn,
94 offset: i64,
95 amount: i64,
96 ) -> Result<Vec<Self>, Error> {
97 use users::dsl;
98 let user_builders: Vec<UserBuilder> = load_or_empty(
99 dsl::users
100 .limit(amount)
101 .offset(offset)
102 .select(UserBuilder::as_select())
103 .load(conn)
104 .await,
105 )?;
106
107 let users: Vec<User> = user_builders.iter().map(|u| u.clone().build()).collect();
108
109 Ok(users)
110 }
111}