]> Untitled Git - lemmy.git/blob - server/lemmy_db/src/lib.rs
Translated using Weblate (Italian)
[lemmy.git] / server / lemmy_db / src / lib.rs
1 #[macro_use]
2 pub extern crate diesel;
3 #[macro_use]
4 pub extern crate strum_macros;
5 #[macro_use]
6 pub extern crate lazy_static;
7 pub extern crate bcrypt;
8 pub extern crate chrono;
9 pub extern crate log;
10 pub extern crate regex;
11 pub extern crate serde;
12 pub extern crate serde_json;
13 pub extern crate sha2;
14 pub extern crate strum;
15
16 use chrono::NaiveDateTime;
17 use diesel::{dsl::*, result::Error, *};
18 use regex::Regex;
19 use serde::{Deserialize, Serialize};
20 use std::{env, env::VarError};
21
22 pub mod activity;
23 pub mod category;
24 pub mod comment;
25 pub mod comment_view;
26 pub mod community;
27 pub mod community_view;
28 pub mod moderator;
29 pub mod moderator_views;
30 pub mod password_reset_request;
31 pub mod post;
32 pub mod post_view;
33 pub mod private_message;
34 pub mod private_message_view;
35 pub mod schema;
36 pub mod site;
37 pub mod site_view;
38 pub mod user;
39 pub mod user_mention;
40 pub mod user_mention_view;
41 pub mod user_view;
42
43 pub trait Crud<T> {
44   fn create(conn: &PgConnection, form: &T) -> Result<Self, Error>
45   where
46     Self: Sized;
47   fn read(conn: &PgConnection, id: i32) -> Result<Self, Error>
48   where
49     Self: Sized;
50   fn update(conn: &PgConnection, id: i32, form: &T) -> Result<Self, Error>
51   where
52     Self: Sized;
53   fn delete(conn: &PgConnection, id: i32) -> Result<usize, Error>
54   where
55     Self: Sized;
56 }
57
58 pub trait Followable<T> {
59   fn follow(conn: &PgConnection, form: &T) -> Result<Self, Error>
60   where
61     Self: Sized;
62   fn unfollow(conn: &PgConnection, form: &T) -> Result<usize, Error>
63   where
64     Self: Sized;
65 }
66
67 pub trait Joinable<T> {
68   fn join(conn: &PgConnection, form: &T) -> Result<Self, Error>
69   where
70     Self: Sized;
71   fn leave(conn: &PgConnection, form: &T) -> Result<usize, Error>
72   where
73     Self: Sized;
74 }
75
76 pub trait Likeable<T> {
77   fn read(conn: &PgConnection, id: i32) -> Result<Vec<Self>, Error>
78   where
79     Self: Sized;
80   fn like(conn: &PgConnection, form: &T) -> Result<Self, Error>
81   where
82     Self: Sized;
83   fn remove(conn: &PgConnection, form: &T) -> Result<usize, Error>
84   where
85     Self: Sized;
86 }
87
88 pub trait Bannable<T> {
89   fn ban(conn: &PgConnection, form: &T) -> Result<Self, Error>
90   where
91     Self: Sized;
92   fn unban(conn: &PgConnection, form: &T) -> Result<usize, Error>
93   where
94     Self: Sized;
95 }
96
97 pub trait Saveable<T> {
98   fn save(conn: &PgConnection, form: &T) -> Result<Self, Error>
99   where
100     Self: Sized;
101   fn unsave(conn: &PgConnection, form: &T) -> Result<usize, Error>
102   where
103     Self: Sized;
104 }
105
106 pub trait Readable<T> {
107   fn mark_as_read(conn: &PgConnection, form: &T) -> Result<Self, Error>
108   where
109     Self: Sized;
110   fn mark_as_unread(conn: &PgConnection, form: &T) -> Result<usize, Error>
111   where
112     Self: Sized;
113 }
114
115 pub trait MaybeOptional<T> {
116   fn get_optional(self) -> Option<T>;
117 }
118
119 impl<T> MaybeOptional<T> for T {
120   fn get_optional(self) -> Option<T> {
121     Some(self)
122   }
123 }
124
125 impl<T> MaybeOptional<T> for Option<T> {
126   fn get_optional(self) -> Option<T> {
127     self
128   }
129 }
130
131 pub fn get_database_url_from_env() -> Result<String, VarError> {
132   env::var("LEMMY_DATABASE_URL")
133 }
134
135 #[derive(EnumString, ToString, Debug, Serialize, Deserialize)]
136 pub enum SortType {
137   Hot,
138   New,
139   TopDay,
140   TopWeek,
141   TopMonth,
142   TopYear,
143   TopAll,
144 }
145
146 #[derive(EnumString, ToString, Debug, Serialize, Deserialize)]
147 pub enum ListingType {
148   All,
149   Subscribed,
150   Community,
151 }
152
153 #[derive(EnumString, ToString, Debug, Serialize, Deserialize)]
154 pub enum SearchType {
155   All,
156   Comments,
157   Posts,
158   Communities,
159   Users,
160   Url,
161 }
162
163 pub fn fuzzy_search(q: &str) -> String {
164   let replaced = q.replace(" ", "%");
165   format!("%{}%", replaced)
166 }
167
168 pub fn limit_and_offset(page: Option<i64>, limit: Option<i64>) -> (i64, i64) {
169   let page = page.unwrap_or(1);
170   let limit = limit.unwrap_or(10);
171   let offset = limit * (page - 1);
172   (limit, offset)
173 }
174
175 pub fn naive_now() -> NaiveDateTime {
176   chrono::prelude::Utc::now().naive_utc()
177 }
178
179 pub fn is_email_regex(test: &str) -> bool {
180   EMAIL_REGEX.is_match(test)
181 }
182
183 lazy_static! {
184   static ref EMAIL_REGEX: Regex =
185     Regex::new(r"^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$").unwrap();
186 }
187
188 #[cfg(test)]
189 mod tests {
190   use super::fuzzy_search;
191   use crate::{get_database_url_from_env, is_email_regex};
192   use diesel::{Connection, PgConnection};
193
194   pub fn establish_unpooled_connection() -> PgConnection {
195     let db_url = match get_database_url_from_env() {
196       Ok(url) => url,
197       Err(e) => panic!(
198         "Failed to read database URL from env var LEMMY_DATABASE_URL: {}",
199         e
200       ),
201     };
202     PgConnection::establish(&db_url).unwrap_or_else(|_| panic!("Error connecting to {}", db_url))
203   }
204
205   #[test]
206   fn test_fuzzy_search() {
207     let test = "This is a fuzzy search";
208     assert_eq!(fuzzy_search(test), "%This%is%a%fuzzy%search%".to_string());
209   }
210
211   #[test]
212   fn test_email() {
213     assert!(is_email_regex("gush@gmail.com"));
214     assert!(!is_email_regex("nada_neutho"));
215   }
216 }