use crate::{CalckeyDbError, CalckeyModel}; use ck::emoji; use sea_orm::prelude::Expr; use sea_orm::{ColumnTrait, EntityTrait, IntoSimpleExpr, QueryFilter, QueryOrder}; #[derive(Debug, Copy, Clone)] pub struct EmojiTag<'a> { pub name: &'a str, pub host: Option<&'a str>, } pub struct EmojiResolver(CalckeyModel); impl EmojiResolver { pub fn new(db: CalckeyModel) -> Self { EmojiResolver(db) } pub async fn get_local_emoji(&self) -> Result, CalckeyDbError> { Ok(emoji::Entity::find() .filter(emoji::Column::Host.is_null()) .order_by_asc(emoji::Column::Category) .order_by_asc(emoji::Column::Name) .all(self.0.inner()) .await?) } pub async fn fetch_emoji( &self, shortcode: &str, host: Option<&str>, ) -> Result, CalckeyDbError> { let host_filter = if let Some(host) = host { emoji::Column::Host.eq(host) } else { emoji::Column::Host.is_null() }; let name_filter = emoji::Column::Name.eq(shortcode); let filter = host_filter.and(name_filter); Ok(emoji::Entity::find() .filter(filter) .one(self.0.inner()) .await?) } pub async fn fetch_many_emojis( &self, shortcodes: &[String], host: Option<&str>, ) -> Result, CalckeyDbError> { let host_filter = if let Some(host) = host { emoji::Column::Host.eq(host) } else { emoji::Column::Host.is_null() }; let name_filter = emoji::Column::Name.is_in(shortcodes); let filter = host_filter.and(name_filter); Ok(emoji::Entity::find() .filter(filter) .all(self.0.inner()) .await?) } pub async fn fetch_many_tagged_emojis( &self, shortcodes: &[EmojiTag<'_>], ) -> Result, CalckeyDbError> { let remote_shortcode_host_pairs = shortcodes .iter() .filter_map(|s| { s.host.map(|host| { Expr::tuple([ Expr::value(s.name.to_string()), Expr::value(host.to_string()), ]) }) }) .collect::>(); let local_shortcodes = shortcodes .iter() .filter_map(|s| s.host.is_none().then_some(s.name.to_string())) .collect::>(); let remote_filter = Expr::tuple([ emoji::Column::Name.into_simple_expr(), emoji::Column::Host.into_simple_expr(), ]) .is_in(remote_shortcode_host_pairs); let local_filter = emoji::Column::Name .is_in(local_shortcodes) .and(emoji::Column::Host.is_null()); let filter = remote_filter.or(local_filter); Ok(emoji::Entity::find() .filter(filter) .all(self.0.inner()) .await?) } }