use model::prelude::*;
use std::cmp::Ordering;
#[cfg(all(feature = "builder", feature = "cache", feature = "model"))]
use builder::EditRole;
#[cfg(all(feature = "cache", feature = "model"))]
use internal::prelude::*;
#[cfg(all(feature = "cache", feature = "model"))]
use {CACHE, http};
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
use std::str::FromStr;
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
use model::misc::RoleParseError;
#[cfg(all(feature = "cache", feature = "model", feature = "utils"))]
use utils::parse_role;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Role {
pub id: RoleId,
#[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,
}
#[cfg(feature = "model")]
impl Role {
#[cfg(feature = "cache")]
#[inline]
pub fn delete(&self) -> Result<()> { http::delete_role(self.find_guild()?.0, self.id.0) }
#[cfg(all(feature = "builder", feature = "cache"))]
pub fn edit<F: FnOnce(EditRole) -> EditRole>(&self, f: F) -> Result<Role> {
self.find_guild()
.and_then(|guild_id| guild_id.edit_role(self.id, f))
}
#[cfg(feature = "cache")]
pub fn find_guild(&self) -> Result<GuildId> {
for guild in CACHE.read().guilds.values() {
let guild = guild.read();
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)
}
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")]
#[deprecated(since = "0.5.8", note = "Use the `to_role_cached`-method instead.")]
pub fn find(&self) -> Option<Role> {
self.to_role_cached()
}
#[cfg(feature = "cache")]
pub fn to_role_cached(self) -> Option<Role> {
let cache = CACHE.read();
for guild in cache.guilds.values() {
let guild = guild.read();
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"))]
impl FromStr for Role {
type Err = RoleParseError;
fn from_str(s: &str) -> StdResult<Self, Self::Err> {
match parse_role(s) {
Some(x) => match RoleId(x).to_role_cached() {
Some(role) => Ok(role),
_ => Err(RoleParseError::NotPresentInCache),
},
_ => Err(RoleParseError::InvalidRole),
}
}
}