use crate::model::prelude::*;
use std::cmp::Ordering;
#[cfg(feature = "model")]
use crate::builder::EditRole;
#[cfg(all(feature = "cache", feature = "model"))]
use crate::internal::prelude::*;
#[cfg(all(feature = "cache", feature = "model"))]
use crate::cache::Cache;
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
use crate::cache::FromStrAndCache;
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
use crate::model::misc::RoleParseError;
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
use crate::utils::parse_role;
#[cfg(feature = "model")]
use crate::http::Http;
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
use async_trait::async_trait;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Role {
pub id: RoleId,
pub guild_id: GuildId,
#[cfg(feature = "utils")]
#[serde(rename = "color")]
pub colour: Colour,
#[cfg(not(feature = "utils"))]
#[serde(rename = "color")]
pub colour: u32,
pub hoist: bool,
pub managed: bool,
#[serde(default)]
pub mentionable: bool,
pub name: String,
pub permissions: Permissions,
pub position: i64,
#[serde(skip)]
pub(crate) _nonexhaustive: (),
}
#[cfg(feature = "model")]
impl Role {
#[inline]
pub async fn delete(&mut self, http: impl AsRef<Http>) -> Result<()> {
http.as_ref().delete_role(self.guild_id.0, self.id.0).await
}
#[inline]
pub async fn edit(&self, http: impl AsRef<Http>, f: impl FnOnce(&mut EditRole) -> &mut EditRole) -> Result<Role> {
self.guild_id.edit_role(http, self.id, f).await
}
#[cfg(feature = "cache")]
#[deprecated(note = "replaced with the `guild_id` field", since = "0.9.0")]
pub async fn find_guild(&self, cache: impl AsRef<Cache>) -> Result<GuildId> {
for guild in cache.as_ref().guilds.read().await.values() {
if guild.roles.contains_key(&RoleId(self.id.0)) {
return Ok(guild.id);
}
}
Err(Error::Model(ModelError::GuildNotFound))
}
#[inline]
pub fn has_permission(&self, permission: Permissions) -> bool {
self.permissions.contains(permission)
}
#[inline]
pub fn has_permissions(&self, permissions: Permissions, precise: bool) -> bool {
if precise {
self.permissions == permissions
} else {
self.permissions.contains(permissions)
}
}
}
impl Display for Role {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
Display::fmt(&self.mention(), f)
}
}
impl Eq for Role {}
impl Ord for Role {
fn cmp(&self, other: &Role) -> Ordering {
if self.position == other.position {
self.id.cmp(&other.id)
} else {
self.position.cmp(&other.position)
}
}
}
impl PartialEq for Role {
fn eq(&self, other: &Role) -> bool { self.id == other.id }
}
impl PartialOrd for Role {
fn partial_cmp(&self, other: &Role) -> Option<Ordering> { Some(self.cmp(other)) }
}
#[cfg(feature = "model")]
impl RoleId {
#[cfg(feature = "cache")]
pub async fn to_role_cached(self, cache: impl AsRef<Cache>) -> Option<Role> {
for guild in cache.as_ref().guilds.read().await.values() {
if !guild.roles.contains_key(&self) {
continue;
}
if let Some(role) = guild.roles.get(&self) {
return Some(role.clone());
}
}
None
}
}
impl From<Role> for RoleId {
fn from(role: Role) -> RoleId { role.id }
}
impl<'a> From<&'a Role> for RoleId {
fn from(role: &Role) -> RoleId { role.id }
}
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
#[async_trait]
impl FromStrAndCache for Role {
type Err = RoleParseError;
async fn from_str<CRL>(cache: CRL, s: &str) -> StdResult<Self, Self::Err>
where CRL: AsRef<Cache> + Send + Sync
{
match parse_role(s) {
Some(x) => match RoleId(x).to_role_cached(&cache).await {
Some(role) => Ok(role),
None => Err(RoleParseError::NotPresentInCache),
},
None => Err(RoleParseError::InvalidRole),
}
}
}