+use crate::structs::CustomEmojiView;
+use diesel::{result::Error, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
+use lemmy_db_schema::{
+ newtypes::{CustomEmojiId, LocalSiteId},
+ schema::{custom_emoji, custom_emoji_keyword},
+ source::{custom_emoji::CustomEmoji, custom_emoji_keyword::CustomEmojiKeyword},
+ utils::{get_conn, DbPool},
+};
+use std::collections::HashMap;
+
+type CustomEmojiTuple = (CustomEmoji, Option<CustomEmojiKeyword>);
+
+impl CustomEmojiView {
+ pub async fn get(pool: &DbPool, emoji_id: CustomEmojiId) -> Result<Self, Error> {
+ let conn = &mut get_conn(pool).await?;
+ let emojis = custom_emoji::table
+ .find(emoji_id)
+ .left_join(
+ custom_emoji_keyword::table.on(custom_emoji_keyword::custom_emoji_id.eq(custom_emoji::id)),
+ )
+ .select((
+ custom_emoji::all_columns,
+ custom_emoji_keyword::all_columns.nullable(), // (or all the columns if you want)
+ ))
+ .load::<CustomEmojiTuple>(conn)
+ .await?;
+ if let Some(emoji) = CustomEmojiView::from_tuple_to_vec(emojis)
+ .into_iter()
+ .next()
+ {
+ Ok(emoji)
+ } else {
+ Err(diesel::result::Error::NotFound)
+ }
+ }
+
+ pub async fn get_all(pool: &DbPool, for_local_site_id: LocalSiteId) -> Result<Vec<Self>, Error> {
+ let conn = &mut get_conn(pool).await?;
+ let emojis = custom_emoji::table
+ .filter(custom_emoji::local_site_id.eq(for_local_site_id))
+ .left_join(
+ custom_emoji_keyword::table.on(custom_emoji_keyword::custom_emoji_id.eq(custom_emoji::id)),
+ )
+ .order(custom_emoji::category)
+ .then_order_by(custom_emoji::id)
+ .select((
+ custom_emoji::all_columns,
+ custom_emoji_keyword::all_columns.nullable(), // (or all the columns if you want)
+ ))
+ .load::<CustomEmojiTuple>(conn)
+ .await?;
+
+ Ok(CustomEmojiView::from_tuple_to_vec(emojis))
+ }
+
+ fn from_tuple_to_vec(items: Vec<CustomEmojiTuple>) -> Vec<Self> {
+ let mut result = Vec::new();
+ let mut hash: HashMap<CustomEmojiId, Vec<CustomEmojiKeyword>> = HashMap::new();
+ for item in &items {
+ let emoji_id: CustomEmojiId = item.0.id;
+ if let std::collections::hash_map::Entry::Vacant(e) = hash.entry(emoji_id) {
+ e.insert(Vec::new());
+ result.push(CustomEmojiView {
+ custom_emoji: item.0.clone(),
+ keywords: Vec::new(),
+ })
+ }
+ if let Some(item_keyword) = &item.1 {
+ if let Some(keywords) = hash.get_mut(&emoji_id) {
+ keywords.push(item_keyword.clone())
+ }
+ }
+ }
+ for emoji in &mut result {
+ if let Some(keywords) = hash.get_mut(&emoji.custom_emoji.id) {
+ emoji.keywords = keywords.clone();
+ }
+ }
+ result
+ }
+}