use std::collections::HashSet;
use std::str::FromStr;
use once_cell::sync::Lazy;
use revolt_models::v0;
use revolt_result::Result;
use ulid::Ulid;
use crate::events::client::EventV1;
use crate::Database;
static PERMISSIBLE_EMOJIS: Lazy<HashSet<String>> = Lazy::new(|| {
include_str!("unicode_emoji.txt")
.split('\n')
.map(|x| x.replace('\u{FE0F}', ""))
.collect()
});
auto_derived_partial!(
pub struct Emoji {
#[serde(rename = "_id")]
pub id: String,
pub parent: EmojiParent,
pub creator_id: String,
pub name: String,
#[serde(skip_serializing_if = "crate::if_false", default)]
pub animated: bool,
#[serde(skip_serializing_if = "crate::if_false", default)]
pub nsfw: bool,
},
"PartialEmoji"
);
auto_derived!(
#[serde(tag = "type")]
pub enum EmojiParent {
Server { id: String },
Detached,
}
);
#[allow(clippy::disallowed_methods)]
impl Emoji {
fn parent(&self) -> &str {
match &self.parent {
EmojiParent::Server { id } => id,
EmojiParent::Detached => "",
}
}
pub async fn create(&self, db: &Database) -> Result<()> {
db.insert_emoji(self).await?;
EventV1::EmojiCreate(self.clone().into())
.p(self.parent().to_string())
.await;
Ok(())
}
pub async fn delete(&self, db: &Database) -> Result<()> {
EventV1::EmojiDelete {
id: self.id.to_string(),
}
.p(self.parent().to_string())
.await;
db.detach_emoji(self).await
}
pub async fn update(&mut self, db: &Database, partial: PartialEmoji) -> Result<()> {
if let Some(name) = partial.name.clone() {
self.name = name;
}
db.update_emoji(&self.id, &partial).await?;
EventV1::EmojiUpdate {
id: self.id.clone(),
data: v0::PartialEmoji {
name: partial.name.clone(),
},
}
.p(self.parent().to_string())
.await;
Ok(())
}
pub async fn can_use(db: &Database, emoji: &str) -> Result<bool> {
if Ulid::from_str(emoji).is_ok() {
db.fetch_emoji(emoji).await?;
Ok(true)
} else {
let sanitized_emoji = emoji.replace('\u{FE0F}', "");
Ok(PERMISSIBLE_EMOJIS.contains(&sanitized_emoji))
}
}
pub fn generate_diff(&self, partial: &PartialEmoji) -> PartialEmoji {
let mut before = PartialEmoji::default();
generate_diff!(
self, before, partial, remove,
(
name,
)
);
before
}
}