backend/objects/
member.rs1use diesel::{
2 ExpressionMethods, Insertable, QueryDsl, Queryable, Selectable, SelectableHelper, insert_into,
3};
4use diesel_async::RunQueryDsl;
5use serde::{Deserialize, Serialize};
6use uuid::Uuid;
7
8use crate::{error::Error, objects::{Permissions, Role}, schema::guild_members, Conn, Data};
9
10use super::{User, load_or_empty};
11
12#[derive(Serialize, Queryable, Selectable, Insertable)]
13#[diesel(table_name = guild_members)]
14#[diesel(check_for_backend(diesel::pg::Pg))]
15pub struct MemberBuilder {
16 pub uuid: Uuid,
17 pub nickname: Option<String>,
18 pub user_uuid: Uuid,
19 pub guild_uuid: Uuid,
20 pub is_owner: bool,
21}
22
23impl MemberBuilder {
24 pub async fn build(&self, data: &Data) -> Result<Member, Error> {
25 let user = User::fetch_one(data, self.user_uuid).await?;
26
27 Ok(Member {
28 uuid: self.uuid,
29 nickname: self.nickname.clone(),
30 user_uuid: self.user_uuid,
31 guild_uuid: self.guild_uuid,
32 is_owner: self.is_owner,
33 user,
34 })
35 }
36
37 pub async fn check_permission(&self, data: &Data, permission: Permissions) -> Result<(), Error> {
38 if !self.is_owner {
39 let roles = Role::fetch_from_member(&data, self.uuid).await?;
40 let allowed = roles.iter().any(|r| r.permissions & permission as i64 != 0);
41 if !allowed {
42 return Err(Error::Forbidden("Not allowed".to_string()))
43 }
44 }
45
46 Ok(())
47 }
48}
49
50#[derive(Serialize, Deserialize)]
51pub struct Member {
52 pub uuid: Uuid,
53 pub nickname: Option<String>,
54 pub user_uuid: Uuid,
55 pub guild_uuid: Uuid,
56 pub is_owner: bool,
57 user: User,
58}
59
60impl Member {
61 pub async fn count(conn: &mut Conn, guild_uuid: Uuid) -> Result<i64, Error> {
62 use guild_members::dsl;
63 let count: i64 = dsl::guild_members
64 .filter(dsl::guild_uuid.eq(guild_uuid))
65 .count()
66 .get_result(conn)
67 .await?;
68
69 Ok(count)
70 }
71
72 pub async fn check_membership(
73 conn: &mut Conn,
74 user_uuid: Uuid,
75 guild_uuid: Uuid,
76 ) -> Result<MemberBuilder, Error> {
77 use guild_members::dsl;
78 let member_builder = dsl::guild_members
79 .filter(dsl::user_uuid.eq(user_uuid))
80 .filter(dsl::guild_uuid.eq(guild_uuid))
81 .select(MemberBuilder::as_select())
82 .get_result(conn)
83 .await?;
84
85 Ok(member_builder)
86 }
87
88 pub async fn fetch_one(data: &Data, user_uuid: Uuid, guild_uuid: Uuid) -> Result<Self, Error> {
89 let mut conn = data.pool.get().await?;
90
91 use guild_members::dsl;
92 let member: MemberBuilder = dsl::guild_members
93 .filter(dsl::user_uuid.eq(user_uuid))
94 .filter(dsl::guild_uuid.eq(guild_uuid))
95 .select(MemberBuilder::as_select())
96 .get_result(&mut conn)
97 .await?;
98
99 member.build(data).await
100 }
101
102 pub async fn fetch_all(data: &Data, guild_uuid: Uuid) -> Result<Vec<Self>, Error> {
103 let mut conn = data.pool.get().await?;
104
105 use guild_members::dsl;
106 let member_builders: Vec<MemberBuilder> = load_or_empty(
107 dsl::guild_members
108 .filter(dsl::guild_uuid.eq(guild_uuid))
109 .select(MemberBuilder::as_select())
110 .load(&mut conn)
111 .await,
112 )?;
113
114 let member_futures = member_builders
115 .iter()
116 .map(async move |m| m.build(data).await);
117
118 futures::future::try_join_all(member_futures).await
119 }
120
121 pub async fn new(data: &Data, user_uuid: Uuid, guild_uuid: Uuid) -> Result<Self, Error> {
122 let mut conn = data.pool.get().await?;
123
124 let member_uuid = Uuid::now_v7();
125
126 let member = MemberBuilder {
127 uuid: member_uuid,
128 guild_uuid,
129 user_uuid,
130 nickname: None,
131 is_owner: false,
132 };
133
134 insert_into(guild_members::table)
135 .values(&member)
136 .execute(&mut conn)
137 .await?;
138
139 member.build(data).await
140 }
141}