use std::fmt;
use super::ArgumentConvert;
use crate::model::prelude::*;
use crate::prelude::*;
#[non_exhaustive]
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum MemberParseError {
OutsideGuild,
GuildNotInCache,
NotFoundOrMalformed,
}
impl std::error::Error for MemberParseError {}
impl fmt::Display for MemberParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::OutsideGuild => f.write_str("Tried to find member outside a guild"),
Self::GuildNotInCache => f.write_str("Guild is not in cache"),
Self::NotFoundOrMalformed => f.write_str("Member not found or unknown format"),
}
}
}
#[async_trait::async_trait]
impl ArgumentConvert for Member {
type Err = MemberParseError;
async fn convert(
ctx: &Context,
guild_id: Option<GuildId>,
_channel_id: Option<ChannelId>,
s: &str,
) -> Result<Self, Self::Err> {
let guild_id = guild_id.ok_or(MemberParseError::OutsideGuild)?;
if let Some(user_id) = s.parse().ok().or_else(|| crate::utils::parse_username(s)) {
if let Ok(member) = guild_id.member(ctx, UserId(user_id)).await {
return Ok(member);
}
}
if let Some((name, discrim)) = crate::utils::parse_user_tag(s) {
if let Ok(member_results) = guild_id.search_members(ctx, name, Some(100)).await {
if let Some(member) = member_results.into_iter().find(|m| {
m.user.name.eq_ignore_ascii_case(name) && m.user.discriminator == discrim
}) {
return Ok(member);
}
}
}
if let Ok(member_results) = guild_id.search_members(ctx, s, Some(100)).await {
if let Some(member) = member_results.into_iter().find(|m| {
m.user.name.eq_ignore_ascii_case(s)
|| m.nick.as_ref().map_or(false, |nick| nick.eq_ignore_ascii_case(s))
}) {
return Ok(member);
}
}
Err(MemberParseError::NotFoundOrMalformed)
}
}