use std::fmt;
use super::ArgumentConvert;
use crate::model::prelude::*;
use crate::prelude::*;
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum EmojiParseError {
OutsideGuild,
FailedToRetrieveGuild,
NotFoundOrMalformed,
}
impl std::error::Error for EmojiParseError {}
impl fmt::Display for EmojiParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::OutsideGuild => f.write_str("Tried to find emoji outside a guild"),
Self::FailedToRetrieveGuild => f.write_str("Could not retrieve guild data"),
Self::NotFoundOrMalformed => f.write_str("Emoji not found or unknown format"),
}
}
}
#[async_trait::async_trait]
impl ArgumentConvert for Emoji {
type Err = EmojiParseError;
async fn convert(
ctx: impl CacheHttp,
guild_id: Option<GuildId>,
_channel_id: Option<ChannelId>,
s: &str,
) -> Result<Self, Self::Err> {
let guild_id = guild_id.ok_or(EmojiParseError::OutsideGuild)?;
let guild = guild_id
.to_partial_guild(&ctx)
.await
.map_err(|_| EmojiParseError::FailedToRetrieveGuild)?;
let direct_id = s.parse().ok();
let id_from_mention = crate::utils::parse_emoji(s).map(|e| e.id);
if let Some(emoji_id) = direct_id.or(id_from_mention) {
if let Some(emoji) = guild.emojis.get(&emoji_id).cloned() {
return Ok(emoji);
}
}
if let Some(emoji) =
guild.emojis.values().find(|emoji| emoji.name.eq_ignore_ascii_case(s)).cloned()
{
return Ok(emoji);
}
Err(EmojiParseError::NotFoundOrMalformed)
}
}