use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Intents {
pub bits: u32,
}
impl Intents {
pub const fn new() -> Self {
Self { bits: 0 }
}
pub const fn none() -> Self {
Self::new()
}
pub const fn all() -> Self {
Self {
bits: Self::GUILDS
| Self::GUILD_MEMBERS
| Self::GUILD_MESSAGES
| Self::GUILD_MESSAGE_REACTIONS
| Self::DIRECT_MESSAGE
| Self::INTERACTION
| Self::MESSAGE_AUDIT
| Self::FORUMS
| Self::AUDIO_ACTION
| Self::PUBLIC_GUILD_MESSAGES
| Self::AUDIO_OR_LIVE_CHANNEL_MEMBER
| Self::OPEN_FORUM_EVENT
| Self::PUBLIC_MESSAGES,
}
}
pub const fn default() -> Self {
Self::all()
.without_intent(Self::GUILD_MESSAGES)
.without_intent(Self::FORUMS)
}
pub const GUILDS: u32 = 1 << 0;
pub const GUILD_MEMBERS: u32 = 1 << 1;
pub const GUILD_MESSAGES: u32 = 1 << 9;
pub const GUILD_MESSAGE_REACTIONS: u32 = 1 << 10;
pub const DIRECT_MESSAGE: u32 = 1 << 12;
pub const INTERACTION: u32 = 1 << 26;
pub const MESSAGE_AUDIT: u32 = 1 << 27;
pub const FORUMS: u32 = 1 << 28;
pub const AUDIO_ACTION: u32 = 1 << 29;
pub const PUBLIC_GUILD_MESSAGES: u32 = 1 << 30;
pub const AUDIO_OR_LIVE_CHANNEL_MEMBER: u32 = 1 << 19;
pub const OPEN_FORUM_EVENT: u32 = 1 << 18;
pub const PUBLIC_MESSAGES: u32 = 1 << 25;
pub const fn contains(self, intent: u32) -> bool {
(self.bits & intent) == intent
}
pub const fn with_intent(mut self, intent: u32) -> Self {
self.bits |= intent;
self
}
pub const fn without_intent(mut self, intent: u32) -> Self {
self.bits &= !intent;
self
}
pub const fn with_guilds(self) -> Self {
self.with_intent(Self::GUILDS)
}
pub const fn with_guild_members(self) -> Self {
self.with_intent(Self::GUILD_MEMBERS)
}
pub const fn with_guild_messages(self) -> Self {
self.with_intent(Self::GUILD_MESSAGES)
}
pub const fn with_guild_message_reactions(self) -> Self {
self.with_intent(Self::GUILD_MESSAGE_REACTIONS)
}
pub const fn with_direct_message(self) -> Self {
self.with_intent(Self::DIRECT_MESSAGE)
}
pub const fn with_interaction(self) -> Self {
self.with_intent(Self::INTERACTION)
}
pub const fn with_message_audit(self) -> Self {
self.with_intent(Self::MESSAGE_AUDIT)
}
pub const fn with_forums(self) -> Self {
self.with_intent(Self::FORUMS)
}
pub const fn with_audio_action(self) -> Self {
self.with_intent(Self::AUDIO_ACTION)
}
pub const fn with_public_guild_messages(self) -> Self {
self.with_intent(Self::PUBLIC_GUILD_MESSAGES)
}
pub const fn with_audio_or_live_channel_member(self) -> Self {
self.with_intent(Self::AUDIO_OR_LIVE_CHANNEL_MEMBER)
}
pub const fn with_open_forum_event(self) -> Self {
self.with_intent(Self::OPEN_FORUM_EVENT)
}
pub const fn with_public_messages(self) -> Self {
self.with_intent(Self::PUBLIC_MESSAGES)
}
pub const fn guilds(self) -> bool {
self.contains(Self::GUILDS)
}
pub const fn guild_members(self) -> bool {
self.contains(Self::GUILD_MEMBERS)
}
pub const fn guild_messages(self) -> bool {
self.contains(Self::GUILD_MESSAGES)
}
pub const fn guild_message_reactions(self) -> bool {
self.contains(Self::GUILD_MESSAGE_REACTIONS)
}
pub const fn direct_message(self) -> bool {
self.contains(Self::DIRECT_MESSAGE)
}
pub const fn interaction(self) -> bool {
self.contains(Self::INTERACTION)
}
pub const fn message_audit(self) -> bool {
self.contains(Self::MESSAGE_AUDIT)
}
pub const fn forums(self) -> bool {
self.contains(Self::FORUMS)
}
pub const fn audio_action(self) -> bool {
self.contains(Self::AUDIO_ACTION)
}
pub const fn public_guild_messages(self) -> bool {
self.contains(Self::PUBLIC_GUILD_MESSAGES)
}
pub const fn audio_or_live_channel_member(self) -> bool {
self.contains(Self::AUDIO_OR_LIVE_CHANNEL_MEMBER)
}
pub const fn open_forum_event(self) -> bool {
self.contains(Self::OPEN_FORUM_EVENT)
}
pub const fn public_messages(self) -> bool {
self.contains(Self::PUBLIC_MESSAGES)
}
pub const fn has_privileged(self) -> bool {
self.contains(Self::GUILD_MESSAGES) || self.contains(Self::FORUMS)
}
pub const fn bits(self) -> u32 {
self.bits
}
pub const fn from_bits(bits: u32) -> Self {
Self { bits }
}
}
impl Default for Intents {
fn default() -> Self {
Self::default()
}
}
impl fmt::Display for Intents {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut parts = Vec::new();
if self.guilds() {
parts.push("GUILDS");
}
if self.guild_members() {
parts.push("GUILD_MEMBERS");
}
if self.guild_messages() {
parts.push("GUILD_MESSAGES");
}
if self.guild_message_reactions() {
parts.push("GUILD_MESSAGE_REACTIONS");
}
if self.direct_message() {
parts.push("DIRECT_MESSAGE");
}
if self.interaction() {
parts.push("INTERACTION");
}
if self.message_audit() {
parts.push("MESSAGE_AUDIT");
}
if self.forums() {
parts.push("FORUMS");
}
if self.audio_action() {
parts.push("AUDIO_ACTION");
}
if self.public_guild_messages() {
parts.push("PUBLIC_GUILD_MESSAGES");
}
if self.audio_or_live_channel_member() {
parts.push("AUDIO_OR_LIVE_CHANNEL_MEMBER");
}
if self.open_forum_event() {
parts.push("OPEN_FORUM_EVENT");
}
if self.public_messages() {
parts.push("PUBLIC_MESSAGES");
}
if parts.is_empty() {
write!(f, "Intents(NONE)")
} else {
write!(f, "Intents({})", parts.join(" | "))
}
}
}
impl std::ops::BitOr for Intents {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
Self {
bits: self.bits | rhs.bits,
}
}
}
impl std::ops::BitOrAssign for Intents {
fn bitor_assign(&mut self, rhs: Self) {
self.bits |= rhs.bits;
}
}
impl std::ops::BitAnd for Intents {
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
Self {
bits: self.bits & rhs.bits,
}
}
}
impl std::ops::BitAndAssign for Intents {
fn bitand_assign(&mut self, rhs: Self) {
self.bits &= rhs.bits;
}
}
impl std::ops::BitXor for Intents {
type Output = Self;
fn bitxor(self, rhs: Self) -> Self::Output {
Self {
bits: self.bits ^ rhs.bits,
}
}
}
impl std::ops::BitXorAssign for Intents {
fn bitxor_assign(&mut self, rhs: Self) {
self.bits ^= rhs.bits;
}
}
impl std::ops::Not for Intents {
type Output = Self;
fn not(self) -> Self::Output {
Self { bits: !self.bits }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_intent_creation() {
let intents = Intents::new();
assert_eq!(intents.bits(), 0);
let intents = Intents::all();
assert!(intents.guilds());
assert!(intents.public_guild_messages());
}
#[test]
fn test_intent_operations() {
let mut intents = Intents::none();
assert!(!intents.guilds());
intents = intents.with_guilds();
assert!(intents.guilds());
let other = Intents::none().with_public_guild_messages();
let combined = intents | other;
assert!(combined.guilds());
assert!(combined.public_guild_messages());
}
#[test]
fn test_privileged_intents() {
let intents = Intents::none().with_guild_messages();
assert!(intents.has_privileged());
let intents = Intents::none().with_forums();
assert!(intents.has_privileged());
let intents = Intents::none().with_public_guild_messages();
assert!(!intents.has_privileged());
}
#[test]
fn test_display() {
let intents = Intents::none();
assert_eq!(format!("{}", intents), "Intents(NONE)");
let intents = Intents::none().with_guilds().with_public_guild_messages();
let display = format!("{}", intents);
assert!(display.contains("GUILDS"));
assert!(display.contains("PUBLIC_GUILD_MESSAGES"));
}
}