fish_lib/game/repositories/
user_repository.rs

1use crate::database::DatabaseInterface;
2use crate::game::errors::repository::GameRepositoryError;
3use crate::models::user::{NewUser, User};
4use crate::models::user_location::{NewUserLocation, UserLocation};
5use crate::schema::{fish_user_locations, fish_users};
6use crate::traits::repository::Repository;
7use chrono::Utc;
8use diesel::prelude::*;
9use std::sync::{Arc, RwLock};
10
11pub trait UserRepositoryInterface: Repository<User> + Send + Sync {
12    fn find_by_external_id(&self, external_id: i64) -> Result<Option<User>, GameRepositoryError>;
13    fn find_unlocked_locations(&self, id: i64) -> Result<Vec<UserLocation>, GameRepositoryError>;
14    fn find_unlocked_location_ids(&self, id: i64) -> Result<Vec<i32>, GameRepositoryError>;
15    fn unlock_location(
16        &self,
17        id: i64,
18        location_id: i32,
19    ) -> Result<UserLocation, GameRepositoryError>;
20}
21
22pub struct UserRepository {
23    db: Arc<RwLock<dyn DatabaseInterface>>,
24}
25
26impl UserRepository {
27    pub fn new(db: Arc<RwLock<dyn DatabaseInterface>>) -> Self {
28        Self { db }
29    }
30}
31
32impl UserRepositoryInterface for UserRepository {
33    fn find_by_external_id(&self, external_id: i64) -> Result<Option<User>, GameRepositoryError> {
34        let mut connection = self.get_connection()?;
35        let user = fish_users::table
36            .filter(fish_users::external_id.eq(external_id))
37            .first::<User>(&mut connection)
38            .optional()?;
39        Ok(user)
40    }
41
42    fn find_unlocked_locations(&self, id: i64) -> Result<Vec<UserLocation>, GameRepositoryError> {
43        let mut connection = self.get_connection()?;
44
45        let locations = fish_user_locations::table
46            .filter(fish_user_locations::user_id.eq(id))
47            .load::<UserLocation>(&mut connection)?;
48
49        Ok(locations)
50    }
51
52    fn find_unlocked_location_ids(&self, id: i64) -> Result<Vec<i32>, GameRepositoryError> {
53        let mut connection = self.get_connection()?;
54
55        let locations = fish_user_locations::table
56            .filter(fish_user_locations::user_id.eq(id))
57            .select(fish_user_locations::location_id)
58            .load::<i32>(&mut connection)?;
59
60        Ok(locations)
61    }
62
63    fn unlock_location(
64        &self,
65        id: i64,
66        location_id: i32,
67    ) -> Result<UserLocation, GameRepositoryError> {
68        let mut connection = self.get_connection()?;
69
70        let user_location = diesel::insert_into(fish_user_locations::table)
71            .values(NewUserLocation {
72                user_id: id,
73                location_id,
74            })
75            .get_result(&mut connection)?;
76        Ok(user_location)
77    }
78}
79
80impl Repository<User> for UserRepository {
81    fn get_db(&self) -> Arc<RwLock<dyn DatabaseInterface>> {
82        self.db.clone()
83    }
84
85    fn create(&self, new_entity: NewUser) -> Result<User, GameRepositoryError> {
86        let mut connection = self.get_connection()?;
87
88        let new_result = diesel::insert_into(fish_users::table)
89            .values(new_entity)
90            .get_result::<User>(&mut connection)?;
91
92        Ok(new_result)
93    }
94
95    fn find(&self, id: i64) -> Result<Option<User>, GameRepositoryError> {
96        let mut connection = self.get_connection()?;
97        let user = fish_users::table
98            .find(id)
99            .first::<User>(&mut connection)
100            .optional()?;
101        Ok(user)
102    }
103
104    fn save(&self, mut entity: User) -> Result<User, GameRepositoryError> {
105        let mut connection = self.get_connection()?;
106        entity.updated_at = Utc::now();
107
108        let updated_user = diesel::update(fish_users::table)
109            .filter(fish_users::id.eq(entity.id))
110            .set(entity)
111            .get_result::<User>(&mut connection)?;
112
113        Ok(updated_user)
114    }
115
116    fn delete(&self, entity: User) -> Result<bool, GameRepositoryError> {
117        let mut connection = self.get_connection()?;
118
119        let deleted_count = diesel::delete(fish_users::table)
120            .filter(fish_users::id.eq(entity.id))
121            .execute(&mut connection)?;
122
123        Ok(deleted_count > 0)
124    }
125}