tetratto_core/database/
message_reactions.rs1use oiseau::{cache::Cache, query_rows};
2use crate::model::{
3 Error, Result,
4 auth::{Notification, User},
5 permissions::FinePermission,
6 channels::MessageReaction,
7};
8use crate::{auto_method, DataManager};
9
10use oiseau::{PostgresRow, execute, get, query_row, params};
11
12impl DataManager {
13 pub(crate) fn get_message_reaction_from_row(x: &PostgresRow) -> MessageReaction {
15 MessageReaction {
16 id: get!(x->0(i64)) as usize,
17 created: get!(x->1(i64)) as usize,
18 owner: get!(x->2(i64)) as usize,
19 message: get!(x->3(i64)) as usize,
20 emoji: get!(x->4(String)),
21 }
22 }
23
24 auto_method!(get_message_reaction_by_id()@get_message_reaction_from_row -> "SELECT * FROM message_reactions WHERE id = $1" --name="message_reaction" --returns=MessageReaction --cache-key-tmpl="atto.message_reaction:{}");
25
26 pub async fn get_message_reactions_by_owner_message(
28 &self,
29 owner: usize,
30 message: usize,
31 ) -> Result<Vec<MessageReaction>> {
32 let conn = match self.0.connect().await {
33 Ok(c) => c,
34 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
35 };
36
37 let res = query_rows!(
38 &conn,
39 "SELECT * FROM message_reactions WHERE owner = $1 AND message = $2",
40 &[&(owner as i64), &(message as i64)],
41 |x| { Self::get_message_reaction_from_row(x) }
42 );
43
44 if res.is_err() {
45 return Err(Error::GeneralNotFound("message_reaction".to_string()));
46 }
47
48 Ok(res.unwrap())
49 }
50
51 pub async fn get_message_reaction_by_owner_message_emoji(
53 &self,
54 owner: usize,
55 message: usize,
56 emoji: &str,
57 ) -> Result<MessageReaction> {
58 let conn = match self.0.connect().await {
59 Ok(c) => c,
60 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
61 };
62
63 let res = query_row!(
64 &conn,
65 "SELECT * FROM message_reactions WHERE owner = $1 AND message = $2 AND emoji = $3",
66 params![&(owner as i64), &(message as i64), &emoji],
67 |x| { Ok(Self::get_message_reaction_from_row(x)) }
68 );
69
70 if res.is_err() {
71 return Err(Error::GeneralNotFound("message_reaction".to_string()));
72 }
73
74 Ok(res.unwrap())
75 }
76
77 pub async fn create_message_reaction(&self, data: MessageReaction, user: &User) -> Result<()> {
82 let conn = match self.0.connect().await {
83 Ok(c) => c,
84 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
85 };
86
87 let mut message = self.get_message_by_id(data.message).await?;
88 let channel = self.get_channel_by_id(message.channel).await?;
89
90 let res = execute!(
92 &conn,
93 "INSERT INTO message_reactions VALUES ($1, $2, $3, $4, $5)",
94 params![
95 &(data.id as i64),
96 &(data.created as i64),
97 &(data.owner as i64),
98 &(data.message as i64),
99 &data.emoji
100 ]
101 );
102
103 if let Err(e) = res {
104 return Err(Error::DatabaseError(e.to_string()));
105 }
106
107 if let Some(x) = message.reactions.get(&data.emoji) {
109 message.reactions.insert(data.emoji.clone(), x + 1);
110 } else {
111 message.reactions.insert(data.emoji.clone(), 1);
112 }
113
114 self.update_message_reactions(message.id, message.reactions)
115 .await?;
116
117 if message.owner != user.id {
119 self
120 .create_notification(Notification::new(
121 "Your message has received a reaction!".to_string(),
122 format!(
123 "[@{}](/api/v1/auth/user/find/{}) has reacted \"{}\" to your [message](/chats/{}/{}?message={})!",
124 user.username, user.id, data.emoji, channel.community, channel.id, message.id
125 ),
126 message.owner,
127 ))
128 .await?;
129 }
130
131 Ok(())
133 }
134
135 pub async fn delete_message_reaction(&self, id: usize, user: &User) -> Result<()> {
136 let message_reaction = self.get_message_reaction_by_id(id).await?;
137
138 if user.id != message_reaction.owner
139 && !user.permissions.check(FinePermission::MANAGE_REACTIONS)
140 {
141 return Err(Error::NotAllowed);
142 }
143
144 let mut message = self.get_message_by_id(message_reaction.message).await?;
145
146 let conn = match self.0.connect().await {
147 Ok(c) => c,
148 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
149 };
150
151 let res = execute!(
152 &conn,
153 "DELETE FROM message_reactions WHERE id = $1",
154 &[&(id as i64)]
155 );
156
157 if let Err(e) = res {
158 return Err(Error::DatabaseError(e.to_string()));
159 }
160
161 self.0
162 .1
163 .remove(format!("atto.message_reaction:{}", id))
164 .await;
165
166 if let Some(x) = message.reactions.get(&message_reaction.emoji) {
168 if *x == 1 {
169 message.reactions.remove(&message_reaction.emoji);
171 } else {
172 message.reactions.insert(message_reaction.emoji, x - 1);
174 }
175 }
176
177 self.update_message_reactions(message.id, message.reactions)
178 .await?;
179
180 Ok(())
182 }
183}