use crate::request::prelude::*;
use std::{
error::Error,
fmt::{Display, Formatter, Result as FmtResult},
};
use twilight_model::id::{ChannelId, GuildId, RoleId, UserId};
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum UpdateGuildMemberError {
NicknameInvalid { nickname: String },
}
impl Display for UpdateGuildMemberError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
Self::NicknameInvalid { .. } => f.write_str("the nickname length is invalid"),
}
}
}
impl Error for UpdateGuildMemberError {}
#[derive(Default, Serialize)]
struct UpdateGuildMemberFields {
#[allow(clippy::option_option)]
#[serde(skip_serializing_if = "Option::is_none")]
channel_id: Option<Option<ChannelId>>,
#[serde(skip_serializing_if = "Option::is_none")]
deaf: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
mute: Option<bool>,
#[allow(clippy::option_option)]
#[serde(skip_serializing_if = "Option::is_none")]
nick: Option<Option<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
roles: Option<Vec<RoleId>>,
}
pub struct UpdateGuildMember<'a> {
fields: UpdateGuildMemberFields,
fut: Option<Pending<'a, ()>>,
guild_id: GuildId,
http: &'a Client,
user_id: UserId,
reason: Option<String>,
}
impl<'a> UpdateGuildMember<'a> {
pub(crate) fn new(http: &'a Client, guild_id: GuildId, user_id: UserId) -> Self {
Self {
fields: UpdateGuildMemberFields::default(),
fut: None,
guild_id,
http,
user_id,
reason: None,
}
}
pub fn channel_id(mut self, channel_id: impl Into<Option<ChannelId>>) -> Self {
self.fields.channel_id.replace(channel_id.into());
self
}
pub fn deaf(mut self, deaf: bool) -> Self {
self.fields.deaf.replace(deaf);
self
}
pub fn mute(mut self, mute: bool) -> Self {
self.fields.mute.replace(mute);
self
}
pub fn nick(self, nick: impl Into<Option<String>>) -> Result<Self, UpdateGuildMemberError> {
self._nick(nick.into())
}
fn _nick(mut self, nick: Option<String>) -> Result<Self, UpdateGuildMemberError> {
if let Some(nick) = nick.as_ref() {
if !validate::nickname(&nick) {
return Err(UpdateGuildMemberError::NicknameInvalid {
nickname: nick.to_owned(),
});
}
}
self.fields.nick.replace(nick);
Ok(self)
}
pub fn roles(mut self, roles: Vec<RoleId>) -> Self {
self.fields.roles.replace(roles);
self
}
fn start(&mut self) -> Result<()> {
let request = if let Some(reason) = &self.reason {
let headers = audit_header(&reason)?;
Request::from((
crate::json_to_vec(&self.fields)?,
headers,
Route::UpdateMember {
guild_id: self.guild_id.0,
user_id: self.user_id.0,
},
))
} else {
Request::from((
crate::json_to_vec(&self.fields)?,
Route::UpdateMember {
guild_id: self.guild_id.0,
user_id: self.user_id.0,
},
))
};
self.fut.replace(Box::pin(self.http.verify(request)));
Ok(())
}
}
impl<'a> AuditLogReason for UpdateGuildMember<'a> {
fn reason(mut self, reason: impl Into<String>) -> Result<Self, AuditLogReasonError> {
self.reason
.replace(AuditLogReasonError::validate(reason.into())?);
Ok(self)
}
}
poll_req!(UpdateGuildMember<'_>, ());