use crate::request::prelude::*;
use std::{
error::Error,
fmt::{Display, Formatter, Result as FmtResult},
};
use twilight_model::{
channel::{permission_overwrite::PermissionOverwrite, Channel, ChannelType},
id::ChannelId,
};
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum UpdateChannelError {
NameInvalid {
name: String,
},
RateLimitPerUserInvalid {
rate_limit_per_user: u64,
},
TopicInvalid {
topic: String,
},
}
impl Display for UpdateChannelError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
Self::NameInvalid { .. } => f.write_str("the length of the name is invalid"),
Self::RateLimitPerUserInvalid { .. } => {
f.write_str("the rate limit per user is invalid")
}
Self::TopicInvalid { .. } => f.write_str("the topic is invalid"),
}
}
}
impl Error for UpdateChannelError {}
#[derive(Default, Serialize)]
struct UpdateChannelFields {
#[serde(skip_serializing_if = "Option::is_none")]
bitrate: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
nsfw: Option<bool>,
#[allow(clippy::option_option)]
#[serde(skip_serializing_if = "Option::is_none")]
parent_id: Option<Option<ChannelId>>,
#[serde(skip_serializing_if = "Option::is_none")]
permission_overwrites: Option<Vec<PermissionOverwrite>>,
#[serde(skip_serializing_if = "Option::is_none")]
position: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
rate_limit_per_user: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
topic: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
user_limit: Option<u64>,
#[serde(rename = "type")]
#[serde(skip_serializing_if = "Option::is_none")]
kind: Option<ChannelType>,
}
pub struct UpdateChannel<'a> {
channel_id: ChannelId,
fields: UpdateChannelFields,
fut: Option<Pending<'a, Channel>>,
http: &'a Client,
reason: Option<String>,
}
impl<'a> UpdateChannel<'a> {
pub(crate) fn new(http: &'a Client, channel_id: ChannelId) -> Self {
Self {
channel_id,
fields: UpdateChannelFields::default(),
fut: None,
http,
reason: None,
}
}
pub fn bitrate(mut self, bitrate: u64) -> Self {
self.fields.bitrate.replace(bitrate);
self
}
pub fn name(self, name: impl Into<String>) -> Result<Self, UpdateChannelError> {
self._name(name.into())
}
fn _name(mut self, name: String) -> Result<Self, UpdateChannelError> {
if !validate::channel_name(&name) {
return Err(UpdateChannelError::NameInvalid { name });
}
self.fields.name.replace(name);
Ok(self)
}
pub fn nsfw(mut self, nsfw: bool) -> Self {
self.fields.nsfw.replace(nsfw);
self
}
pub fn parent_id(mut self, parent_id: impl Into<Option<ChannelId>>) -> Self {
self.fields.parent_id.replace(parent_id.into());
self
}
pub fn permission_overwrites(
mut self,
permission_overwrites: Vec<PermissionOverwrite>,
) -> Self {
self.fields
.permission_overwrites
.replace(permission_overwrites);
self
}
pub fn position(mut self, position: u64) -> Self {
self.fields.position.replace(position);
self
}
pub fn rate_limit_per_user(
mut self,
rate_limit_per_user: u64,
) -> Result<Self, UpdateChannelError> {
if rate_limit_per_user > 21600 {
return Err(UpdateChannelError::RateLimitPerUserInvalid {
rate_limit_per_user,
});
}
self.fields.rate_limit_per_user.replace(rate_limit_per_user);
Ok(self)
}
pub fn topic(self, topic: impl Into<String>) -> Result<Self, UpdateChannelError> {
self._topic(topic.into())
}
fn _topic(mut self, topic: String) -> Result<Self, UpdateChannelError> {
if topic.chars().count() > 1024 {
return Err(UpdateChannelError::TopicInvalid { topic });
}
self.fields.topic.replace(topic);
Ok(self)
}
pub fn user_limit(mut self, user_limit: u64) -> Self {
self.fields.user_limit.replace(user_limit);
self
}
pub fn kind(mut self, kind: ChannelType) -> Self {
self.fields.kind.replace(kind);
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::UpdateChannel {
channel_id: self.channel_id.0,
},
))
} else {
Request::from((
crate::json_to_vec(&self.fields)?,
Route::UpdateChannel {
channel_id: self.channel_id.0,
},
))
};
self.fut.replace(Box::pin(self.http.request(request)));
Ok(())
}
}
impl<'a> AuditLogReason for UpdateChannel<'a> {
fn reason(mut self, reason: impl Into<String>) -> Result<Self, AuditLogReasonError> {
self.reason
.replace(AuditLogReasonError::validate(reason.into())?);
Ok(self)
}
}
poll_req!(UpdateChannel<'_>, Channel);