use std::{
error::Error,
fmt::{Display, Formatter, Result as FmtResult},
};
pub trait AuditLogReason: private::Sealed {
fn reason(self, reason: impl Into<String>) -> Result<Self, AuditLogReasonError>
where
Self: Sized;
}
mod private {
use crate::request::{
channel::{
invite::{CreateInvite, DeleteInvite},
message::{DeleteMessage, DeleteMessages},
webhook::{
CreateWebhook, DeleteWebhook, DeleteWebhookMessage, UpdateWebhook,
UpdateWebhookMessage,
},
CreatePin, DeleteChannel, DeleteChannelPermissionConfigured, DeletePin, UpdateChannel,
UpdateChannelPermissionConfigured,
},
guild::{
ban::{CreateBan, DeleteBan},
emoji::{CreateEmoji, DeleteEmoji, UpdateEmoji},
integration::DeleteGuildIntegration,
member::{AddRoleToMember, RemoveMember, RemoveRoleFromMember, UpdateGuildMember},
role::{CreateRole, DeleteRole, UpdateRole},
CreateGuildChannel, CreateGuildPrune, UpdateGuild,
},
};
pub trait Sealed {}
impl<'a> Sealed for CreateInvite<'a> {}
impl<'a> Sealed for DeleteInvite<'a> {}
impl<'a> Sealed for DeleteMessage<'a> {}
impl<'a> Sealed for DeleteMessages<'a> {}
impl<'a> Sealed for UpdateChannel<'a> {}
impl<'a> Sealed for CreateWebhook<'a> {}
impl Sealed for DeleteWebhookMessage<'_> {}
impl<'a> Sealed for DeleteWebhook<'a> {}
impl<'a> Sealed for UpdateWebhook<'a> {}
impl<'a> Sealed for CreatePin<'a> {}
impl<'a> Sealed for DeleteChannel<'a> {}
impl<'a> Sealed for DeleteChannelPermissionConfigured<'a> {}
impl<'a> Sealed for DeletePin<'a> {}
impl<'a> Sealed for UpdateChannelPermissionConfigured<'a> {}
impl<'a> Sealed for CreateBan<'a> {}
impl<'a> Sealed for DeleteBan<'a> {}
impl<'a> Sealed for CreateGuildChannel<'a> {}
impl<'a> Sealed for CreateGuildPrune<'a> {}
impl<'a> Sealed for CreateEmoji<'a> {}
impl<'a> Sealed for DeleteEmoji<'a> {}
impl<'a> Sealed for UpdateEmoji<'a> {}
impl<'a> Sealed for DeleteGuildIntegration<'a> {}
impl<'a> Sealed for UpdateGuildMember<'a> {}
impl<'a> Sealed for AddRoleToMember<'a> {}
impl<'a> Sealed for RemoveMember<'a> {}
impl<'a> Sealed for RemoveRoleFromMember<'a> {}
impl<'a> Sealed for CreateRole<'a> {}
impl<'a> Sealed for DeleteRole<'a> {}
impl<'a> Sealed for UpdateRole<'a> {}
impl<'a> Sealed for UpdateGuild<'a> {}
impl Sealed for UpdateWebhookMessage<'_> {}
}
impl AuditLogReasonError {
pub const AUDIT_REASON_LENGTH: usize = 512;
pub(crate) fn validate(reason: String) -> Result<String, AuditLogReasonError> {
if reason.chars().count() <= Self::AUDIT_REASON_LENGTH {
Ok(reason)
} else {
Err(AuditLogReasonError {
kind: AuditLogReasonErrorType::TooLarge { reason },
})
}
}
}
#[derive(Debug)]
pub struct AuditLogReasonError {
kind: AuditLogReasonErrorType,
}
impl AuditLogReasonError {
#[must_use = "retrieving the type has no effect if left unused"]
pub const fn kind(&self) -> &AuditLogReasonErrorType {
&self.kind
}
#[allow(clippy::unused_self)]
#[must_use = "consuming the error and retrieving the source has no effect if left unused"]
pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
None
}
#[must_use = "consuming the error into its parts has no effect if left unused"]
pub fn into_parts(
self,
) -> (
AuditLogReasonErrorType,
Option<Box<dyn Error + Send + Sync>>,
) {
(self.kind, None)
}
}
impl Display for AuditLogReasonError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match &self.kind {
AuditLogReasonErrorType::TooLarge { reason } => write!(
f,
"the audit log reason is {} characters long, but the max is {}",
reason.chars().count(),
Self::AUDIT_REASON_LENGTH
),
}
}
}
impl Error for AuditLogReasonError {}
#[derive(Debug)]
#[non_exhaustive]
pub enum AuditLogReasonErrorType {
TooLarge { reason: String },
}
#[cfg(test)]
mod test {
use super::AuditLogReason;
use crate::request::{
channel::{
invite::{CreateInvite, DeleteInvite},
message::{DeleteMessage, DeleteMessages},
webhook::{CreateWebhook, DeleteWebhook, UpdateWebhook},
CreatePin, DeleteChannel, DeleteChannelPermissionConfigured, DeletePin, UpdateChannel,
UpdateChannelPermissionConfigured,
},
guild::{
ban::{CreateBan, DeleteBan},
emoji::{CreateEmoji, DeleteEmoji, UpdateEmoji},
integration::DeleteGuildIntegration,
member::{AddRoleToMember, RemoveMember, RemoveRoleFromMember, UpdateGuildMember},
role::{CreateRole, DeleteRole, UpdateRole},
CreateGuildChannel, CreateGuildPrune, UpdateGuild,
},
};
use static_assertions::{assert_impl_all, assert_obj_safe};
assert_obj_safe!(AuditLogReason);
assert_impl_all!(CreateInvite<'_>: AuditLogReason);
assert_impl_all!(DeleteInvite<'_>: AuditLogReason);
assert_impl_all!(DeleteMessage<'_>: AuditLogReason);
assert_impl_all!(DeleteMessages<'_>: AuditLogReason);
assert_impl_all!(UpdateChannel<'_>: AuditLogReason);
assert_impl_all!(CreateWebhook<'_>: AuditLogReason);
assert_impl_all!(DeleteWebhook<'_>: AuditLogReason);
assert_impl_all!(UpdateWebhook<'_>: AuditLogReason);
assert_impl_all!(CreatePin<'_>: AuditLogReason);
assert_impl_all!(DeleteChannel<'_>: AuditLogReason);
assert_impl_all!(DeleteChannelPermissionConfigured<'_>: AuditLogReason);
assert_impl_all!(DeletePin<'_>: AuditLogReason);
assert_impl_all!(UpdateChannelPermissionConfigured<'_>: AuditLogReason);
assert_impl_all!(CreateBan<'_>: AuditLogReason);
assert_impl_all!(DeleteBan<'_>: AuditLogReason);
assert_impl_all!(CreateGuildChannel<'_>: AuditLogReason);
assert_impl_all!(CreateGuildPrune<'_>: AuditLogReason);
assert_impl_all!(CreateEmoji<'_>: AuditLogReason);
assert_impl_all!(DeleteEmoji<'_>: AuditLogReason);
assert_impl_all!(UpdateEmoji<'_>: AuditLogReason);
assert_impl_all!(DeleteGuildIntegration<'_>: AuditLogReason);
assert_impl_all!(UpdateGuildMember<'_>: AuditLogReason);
assert_impl_all!(AddRoleToMember<'_>: AuditLogReason);
assert_impl_all!(RemoveMember<'_>: AuditLogReason);
assert_impl_all!(RemoveRoleFromMember<'_>: AuditLogReason);
assert_impl_all!(CreateRole<'_>: AuditLogReason);
assert_impl_all!(DeleteRole<'_>: AuditLogReason);
assert_impl_all!(UpdateRole<'_>: AuditLogReason);
assert_impl_all!(UpdateGuild<'_>: AuditLogReason);
}