]> Untitled Git - lemmy.git/blob - crates/db_views/src/custom_emoji_view.rs
66d583e32c889cc437e1b71aeca05430a62a9b41
[lemmy.git] / crates / db_views / src / custom_emoji_view.rs
1 use crate::structs::CustomEmojiView;
2 use diesel::{result::Error, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl};
3 use diesel_async::RunQueryDsl;
4 use lemmy_db_schema::{
5   newtypes::{CustomEmojiId, LocalSiteId},
6   schema::{custom_emoji, custom_emoji_keyword},
7   source::{custom_emoji::CustomEmoji, custom_emoji_keyword::CustomEmojiKeyword},
8   utils::{get_conn, DbPool},
9 };
10 use std::collections::HashMap;
11
12 type CustomEmojiTuple = (CustomEmoji, Option<CustomEmojiKeyword>);
13
14 impl CustomEmojiView {
15   pub async fn get(pool: &DbPool, emoji_id: CustomEmojiId) -> Result<Self, Error> {
16     let conn = &mut get_conn(pool).await?;
17     let emojis = custom_emoji::table
18       .find(emoji_id)
19       .left_join(
20         custom_emoji_keyword::table.on(custom_emoji_keyword::custom_emoji_id.eq(custom_emoji::id)),
21       )
22       .select((
23         custom_emoji::all_columns,
24         custom_emoji_keyword::all_columns.nullable(), // (or all the columns if you want)
25       ))
26       .load::<CustomEmojiTuple>(conn)
27       .await?;
28     if let Some(emoji) = CustomEmojiView::from_tuple_to_vec(emojis)
29       .into_iter()
30       .next()
31     {
32       Ok(emoji)
33     } else {
34       Err(diesel::result::Error::NotFound)
35     }
36   }
37
38   pub async fn get_all(pool: &DbPool, for_local_site_id: LocalSiteId) -> Result<Vec<Self>, Error> {
39     let conn = &mut get_conn(pool).await?;
40     let emojis = custom_emoji::table
41       .filter(custom_emoji::local_site_id.eq(for_local_site_id))
42       .left_join(
43         custom_emoji_keyword::table.on(custom_emoji_keyword::custom_emoji_id.eq(custom_emoji::id)),
44       )
45       .order(custom_emoji::category)
46       .then_order_by(custom_emoji::id)
47       .select((
48         custom_emoji::all_columns,
49         custom_emoji_keyword::all_columns.nullable(), // (or all the columns if you want)
50       ))
51       .load::<CustomEmojiTuple>(conn)
52       .await?;
53
54     Ok(CustomEmojiView::from_tuple_to_vec(emojis))
55   }
56
57   fn from_tuple_to_vec(items: Vec<CustomEmojiTuple>) -> Vec<Self> {
58     let mut result = Vec::new();
59     let mut hash: HashMap<CustomEmojiId, Vec<CustomEmojiKeyword>> = HashMap::new();
60     for item in &items {
61       let emoji_id: CustomEmojiId = item.0.id;
62       if let std::collections::hash_map::Entry::Vacant(e) = hash.entry(emoji_id) {
63         e.insert(Vec::new());
64         result.push(CustomEmojiView {
65           custom_emoji: item.0.clone(),
66           keywords: Vec::new(),
67         })
68       }
69       if let Some(item_keyword) = &item.1 {
70         if let Some(keywords) = hash.get_mut(&emoji_id) {
71           keywords.push(item_keyword.clone())
72         }
73       }
74     }
75     for emoji in &mut result {
76       if let Some(keywords) = hash.get_mut(&emoji.custom_emoji.id) {
77         emoji.keywords = keywords.clone();
78       }
79     }
80     result
81   }
82 }