1use oiseau::cache::Cache;
2use crate::model::auth::AchievementName;
3use crate::model::requests::{ActionRequest, ActionType};
4use crate::model::{Error, Result, auth::User, auth::UserFollow, permissions::FinePermission, id::Id};
5use crate::{auto_method, DataManager};
6
7use oiseau::{PostgresRow, execute, get, query_row, query_rows, params};
8
9impl DataManager {
10 pub(crate) fn get_user_follow_from_row(x: &PostgresRow) -> UserFollow {
12 UserFollow {
13 id: Id::deserialize(&get!(x->0(String))),
14 created: get!(x->1(i64)) as u128,
15 initiator: Id::deserialize(&get!(x->2(String))),
16 receiver: Id::deserialize(&get!(x->3(String))),
17 }
18 }
19
20 auto_method!(get_user_follow_by_id()@get_user_follow_from_row -> "SELECT * FROM user_follows WHERE id = $1" --name="user follow" --returns=UserFollow --cache-key-tmpl="atto.user_follow:{}");
21
22 pub fn user_follows_user_filter(&self, x: &[(UserFollow, User)]) -> Vec<(UserFollow, User)> {
24 let mut out: Vec<(UserFollow, User)> = Vec::new();
25
26 for mut y in x.iter().cloned() {
27 y.1.clean();
28 out.push(y);
29 }
30
31 out
32 }
33
34 pub async fn get_user_follow_by_initiator_receiver(
36 &self,
37 initiator: &Id,
38 receiver: &Id,
39 ) -> Result<UserFollow> {
40 let conn = match self.0.connect().await {
41 Ok(c) => c,
42 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
43 };
44
45 let res = query_row!(
46 &conn,
47 "SELECT * FROM user_follows WHERE initiator = $1 AND receiver = $2",
48 &[&initiator.printable(), &receiver.printable()],
49 |x| { Ok(Self::get_user_follow_from_row(x)) }
50 );
51
52 if res.is_err() {
53 return Err(Error::GeneralNotFound("user follow".to_string()));
54 }
55
56 Ok(res.unwrap())
57 }
58
59 pub async fn get_user_follow_by_receiver_initiator(
61 &self,
62 receiver: &Id,
63 initiator: &Id,
64 ) -> Result<UserFollow> {
65 let conn = match self.0.connect().await {
66 Ok(c) => c,
67 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
68 };
69
70 let res = query_row!(
71 &conn,
72 "SELECT * FROM user_follows WHERE receiver = $1 AND initiator = $2",
73 &[&receiver.printable(), &initiator.printable()],
74 |x| { Ok(Self::get_user_follow_from_row(x)) }
75 );
76
77 if res.is_err() {
78 return Err(Error::GeneralNotFound("user follow".to_string()));
79 }
80
81 Ok(res.unwrap())
82 }
83
84 pub async fn get_user_follows_by_initiator(
91 &self,
92 id: &Id,
93 batch: usize,
94 page: usize,
95 ) -> Result<Vec<UserFollow>> {
96 let conn = match self.0.connect().await {
97 Ok(c) => c,
98 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
99 };
100
101 let res = query_rows!(
102 &conn,
103 "SELECT * FROM user_follows WHERE initiator = $1 ORDER BY created DESC LIMIT $2 OFFSET $3",
104 &[&id.printable(), &(batch as i64), &((page * batch) as i64)],
105 |x| { Self::get_user_follow_from_row(x) }
106 );
107
108 if res.is_err() {
109 return Err(Error::GeneralNotFound("user follow".to_string()));
110 }
111
112 Ok(res.unwrap())
113 }
114
115 pub async fn get_user_follows_by_initiator_all(&self, id: &Id) -> Result<Vec<UserFollow>> {
120 let conn = match self.0.connect().await {
121 Ok(c) => c,
122 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
123 };
124
125 let res = query_rows!(
126 &conn,
127 "SELECT * FROM user_follows WHERE initiator = $1",
128 &[&id.printable()],
129 |x| { Self::get_user_follow_from_row(x) }
130 );
131
132 if res.is_err() {
133 return Err(Error::GeneralNotFound("user follow".to_string()));
134 }
135
136 Ok(res.unwrap())
137 }
138
139 pub async fn get_user_follows_by_receiver(
146 &self,
147 id: &Id,
148 batch: usize,
149 page: usize,
150 ) -> Result<Vec<UserFollow>> {
151 let conn = match self.0.connect().await {
152 Ok(c) => c,
153 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
154 };
155
156 let res = query_rows!(
157 &conn,
158 "SELECT * FROM user_follows WHERE receiver = $1 ORDER BY created DESC LIMIT $2 OFFSET $3",
159 &[&id.printable(), &(batch as i64), &((page * batch) as i64)],
160 |x| { Self::get_user_follow_from_row(x) }
161 );
162
163 if res.is_err() {
164 return Err(Error::GeneralNotFound("user follow".to_string()));
165 }
166
167 Ok(res.unwrap())
168 }
169
170 pub async fn get_user_follows_by_receiver_all(&self, id: &Id) -> Result<Vec<UserFollow>> {
175 let conn = match self.0.connect().await {
176 Ok(c) => c,
177 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
178 };
179
180 let res = query_rows!(
181 &conn,
182 "SELECT * FROM user_follows WHERE receiver = $1",
183 &[&id.printable()],
184 |x| { Self::get_user_follow_from_row(x) }
185 );
186
187 if res.is_err() {
188 return Err(Error::GeneralNotFound("user follow".to_string()));
189 }
190
191 Ok(res.unwrap())
192 }
193
194 pub async fn fill_user_follows_with_receiver(
196 &self,
197 user_follows: Vec<UserFollow>,
198 as_user: &Option<User>,
199 do_check: bool,
200 ) -> Result<Vec<(UserFollow, User)>> {
201 let mut out: Vec<(UserFollow, User)> = Vec::new();
202
203 for userfollow in user_follows {
204 let receiver = userfollow.receiver.clone();
205 let user = match self.get_user_by_id(&receiver).await {
206 Ok(u) => u,
207 Err(_) => continue,
208 };
209
210 if user.settings.hide_from_social_lists && do_check {
211 if let Some(ua) = as_user {
212 if !ua.permissions.check(FinePermission::ManageUsers) {
213 continue;
214 }
215 } else {
216 continue;
217 }
218 }
219
220 out.push((userfollow, user));
221 }
222
223 Ok(out)
224 }
225
226 pub async fn fill_user_follows_with_initiator(
228 &self,
229 user_follows: Vec<UserFollow>,
230 as_user: &Option<User>,
231 do_check: bool,
232 ) -> Result<Vec<(UserFollow, User)>> {
233 let mut out: Vec<(UserFollow, User)> = Vec::new();
234
235 for userfollow in user_follows {
236 let initiator = userfollow.initiator.clone();
237 let user = match self.get_user_by_id(&initiator).await {
238 Ok(u) => u,
239 Err(_) => continue,
240 };
241
242 if user.settings.hide_from_social_lists && do_check {
243 if let Some(ua) = as_user {
244 if !ua.permissions.check(FinePermission::ManageUsers) {
245 continue;
246 }
247 } else {
248 continue;
249 }
250 }
251
252 out.push((userfollow, user));
253 }
254
255 Ok(out)
256 }
257
258 pub async fn create_user_follow(
264 &self,
265 data: UserFollow,
266 initiator: &User,
267 force: bool,
268 ) -> Result<bool> {
269 let mut asked = false;
270 if !force {
271 let mut other_user = self.get_user_by_id(&data.receiver).await?;
272
273 if other_user.settings.private_profile {
274 self.create_request(ActionRequest::with_id(
276 data.initiator.clone(),
277 data.receiver.clone(),
278 ActionType::Follow,
279 data.receiver.clone(),
280 None,
281 ))
282 .await?;
283
284 asked = true;
285 }
286
287 if initiator.permissions.check(FinePermission::StaffBadge) {
289 self.add_achievement(
290 &mut other_user,
291 AchievementName::FollowedByStaff.into(),
292 true,
293 )
294 .await?;
295 }
296
297 self.add_achievement(&mut other_user, AchievementName::Get1Follower.into(), true)
299 .await?;
300
301 if other_user.follower_count >= 9 {
302 self.add_achievement(
303 &mut other_user,
304 AchievementName::Get10Followers.into(),
305 true,
306 )
307 .await?;
308 }
309
310 if other_user.follower_count >= 49 {
311 self.add_achievement(
312 &mut other_user,
313 AchievementName::Get50Followers.into(),
314 true,
315 )
316 .await?;
317 }
318
319 if other_user.follower_count >= 99 {
320 self.add_achievement(
321 &mut other_user,
322 AchievementName::Get100Followers.into(),
323 true,
324 )
325 .await?;
326 }
327
328 if initiator.following_count >= 9 {
329 self.add_achievement(
330 &mut initiator.clone(),
331 AchievementName::Follow10Users.into(),
332 true,
333 )
334 .await?;
335 }
336 }
337
338 let conn = match self.0.connect().await {
340 Ok(c) => c,
341 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
342 };
343
344 let res = execute!(
345 &conn,
346 "INSERT INTO user_follows VALUES ($1, $2, $3, $4)",
347 params![
348 &data.id.printable(),
349 &(data.created as i64),
350 &data.initiator.printable(),
351 &data.receiver.printable()
352 ]
353 );
354
355 if let Err(e) = res {
356 return Err(Error::DatabaseError(e.to_string()));
357 }
358
359 self.incr_user_following_count(&data.initiator)
361 .await
362 .unwrap();
363
364 self.incr_user_follower_count(&data.receiver).await.unwrap();
365
366 Ok(asked)
368 }
369
370 pub async fn delete_user_follow(
371 &self,
372 id: &Id,
373 user: &User,
374 is_deleting_user: bool,
375 ) -> Result<()> {
376 let follow = self.get_user_follow_by_id(id).await?;
377
378 if (user.id != follow.initiator)
379 && (user.id != follow.receiver)
380 && !user.permissions.check(FinePermission::ManageFollows)
381 && !is_deleting_user
382 {
383 return Err(Error::NotAllowed);
384 }
385
386 let conn = match self.0.connect().await {
387 Ok(c) => c,
388 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
389 };
390
391 let res = execute!(
392 &conn,
393 "DELETE FROM user_follows WHERE id = $1",
394 &[&id.printable()]
395 );
396
397 if let Err(e) = res {
398 return Err(Error::DatabaseError(e.to_string()));
399 }
400
401 self.0.1.remove(format!("atto.user_follow:{}", id)).await;
402
403 if !is_deleting_user | (follow.initiator != user.id)
405 && self
406 .decr_user_following_count(&follow.initiator)
407 .await
408 .is_err()
409 {
410 println!("ERR_TETRATTO_DECR_FOLLOWS: could not decr initiator follow count")
411 }
412
413 if !is_deleting_user | (follow.receiver != user.id) {
414 self.decr_user_follower_count(&follow.receiver)
415 .await
416 .unwrap();
417 }
418
419 Ok(())
421 }
422
423 pub async fn delete_user_follow_forced(&self, id: &Id, user_id: &Id) -> Result<()> {
424 let follow = self.get_user_follow_by_id(id).await?;
425
426 let conn = match self.0.connect().await {
427 Ok(c) => c,
428 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
429 };
430
431 let res = execute!(
432 &conn,
433 "DELETE FROM user_follows WHERE id = $1",
434 &[&id.printable()]
435 );
436
437 if let Err(e) = res {
438 return Err(Error::DatabaseError(e.to_string()));
439 }
440
441 self.0.1.remove(format!("atto.user_follow:{}", id)).await;
442
443 if follow.initiator != *user_id {
445 self.decr_user_following_count(&follow.initiator)
446 .await
447 .unwrap();
448 }
449
450 if follow.receiver != *user_id {
451 self.decr_user_follower_count(&follow.receiver)
452 .await
453 .unwrap();
454 }
455
456 Ok(())
458 }
459}