serenity/utils/argument_convert/
role.rs1use std::fmt;
2
3use super::ArgumentConvert;
4use crate::model::prelude::*;
5use crate::prelude::*;
6
7#[non_exhaustive]
9#[derive(Debug)]
10pub enum RoleParseError {
11 NotInGuild,
13 NotInCache,
15 Http(SerenityError),
17 NotFoundOrMalformed,
20}
21
22impl std::error::Error for RoleParseError {
23 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
24 match self {
25 Self::Http(e) => Some(e),
26 Self::NotFoundOrMalformed | Self::NotInGuild | Self::NotInCache => None,
27 }
28 }
29}
30
31impl fmt::Display for RoleParseError {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 match self {
34 Self::NotInGuild => f.write_str("Must invoke this operation in a guild"),
35 Self::NotInCache => f.write_str("Guild's roles were not found in cache"),
36 Self::Http(_) => f.write_str("Failed to retrieve roles via HTTP"),
37 Self::NotFoundOrMalformed => f.write_str("Role not found or unknown format"),
38 }
39 }
40}
41
42#[async_trait::async_trait]
51impl ArgumentConvert for Role {
52 type Err = RoleParseError;
53
54 async fn convert(
55 ctx: impl CacheHttp,
56 guild_id: Option<GuildId>,
57 _channel_id: Option<ChannelId>,
58 s: &str,
59 ) -> Result<Self, Self::Err> {
60 let guild_id = guild_id.ok_or(RoleParseError::NotInGuild)?;
61
62 #[cfg(feature = "cache")]
63 let guild;
64
65 #[cfg(feature = "cache")]
66 let roles = {
67 let cache = ctx.cache().ok_or(RoleParseError::NotInCache)?;
68 guild = cache.guild(guild_id).ok_or(RoleParseError::NotInCache)?;
69 &guild.roles
70 };
71
72 #[cfg(not(feature = "cache"))]
73 let roles = ctx.http().get_guild_roles(guild_id).await.map_err(RoleParseError::Http)?;
74
75 if let Some(role_id) = s.parse().ok().or_else(|| crate::utils::parse_role_mention(s)) {
76 #[cfg(feature = "cache")]
77 if let Some(role) = roles.get(&role_id) {
78 return Ok(role.clone());
79 }
80 #[cfg(not(feature = "cache"))]
81 if let Some(role) = roles.iter().find(|role| role.id == role_id) {
82 return Ok(role.clone());
83 }
84 }
85
86 #[cfg(feature = "cache")]
87 if let Some(role) = roles.values().find(|role| role.name.eq_ignore_ascii_case(s)) {
88 return Ok(role.clone());
89 }
90 #[cfg(not(feature = "cache"))]
91 if let Some(role) = roles.into_iter().find(|role| role.name.eq_ignore_ascii_case(s)) {
92 return Ok(role);
93 }
94
95 Err(RoleParseError::NotFoundOrMalformed)
96 }
97}