use crate::models::{HasId, HasName, Snowflake};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Channel {
pub id: Option<Snowflake>,
pub guild_id: Option<Snowflake>,
pub name: Option<String>,
#[serde(rename = "type")]
pub channel_type: Option<ChannelType>,
pub sub_type: Option<ChannelSubType>,
pub position: Option<i32>,
pub parent_id: Option<Snowflake>,
pub owner_id: Option<Snowflake>,
pub private_type: Option<PrivateType>,
pub speak_permission: Option<SpeakPermission>,
pub application_id: Option<Snowflake>,
pub permissions: Option<String>,
}
impl Channel {
pub fn new() -> Self {
Self {
id: None,
guild_id: None,
name: None,
channel_type: None,
sub_type: None,
position: None,
parent_id: None,
owner_id: None,
private_type: None,
speak_permission: None,
application_id: None,
permissions: None,
}
}
pub fn from_data(_api: crate::api::BotApi, id: String, data: serde_json::Value) -> Self {
Self {
id: Some(id),
guild_id: data
.get("guild_id")
.and_then(|v| v.as_str())
.map(String::from),
name: data.get("name").and_then(|v| v.as_str()).map(String::from),
channel_type: data
.get("type")
.and_then(|v| v.as_u64())
.and_then(|v| ChannelType::from_u8(v as u8)),
sub_type: data
.get("sub_type")
.and_then(|v| v.as_u64())
.and_then(|v| ChannelSubType::from_u8(v as u8)),
position: data
.get("position")
.and_then(|v| v.as_i64())
.map(|v| v as i32),
parent_id: data
.get("parent_id")
.and_then(|v| v.as_str())
.map(String::from),
owner_id: data
.get("owner_id")
.and_then(|v| v.as_str())
.map(String::from),
private_type: data
.get("private_type")
.and_then(|v| v.as_u64())
.and_then(|v| PrivateType::from_u8(v as u8)),
speak_permission: data
.get("speak_permission")
.and_then(|v| v.as_u64())
.and_then(|v| SpeakPermission::from_u8(v as u8)),
application_id: data
.get("application_id")
.and_then(|v| v.as_str())
.map(String::from),
permissions: data
.get("permissions")
.and_then(|v| v.as_str())
.map(String::from),
}
}
pub fn mention(&self) -> String {
format!("<#{}>", self.id.as_ref().unwrap_or(&String::new()))
}
pub fn is_text(&self) -> bool {
matches!(self.channel_type, Some(ChannelType::Text))
}
pub fn is_voice(&self) -> bool {
matches!(self.channel_type, Some(ChannelType::Voice))
}
pub fn is_group(&self) -> bool {
matches!(self.channel_type, Some(ChannelType::Group))
}
pub fn is_live(&self) -> bool {
matches!(self.channel_type, Some(ChannelType::Live))
}
pub fn is_application(&self) -> bool {
matches!(self.channel_type, Some(ChannelType::Application))
}
pub fn is_discussion(&self) -> bool {
matches!(self.channel_type, Some(ChannelType::Discussion))
}
pub fn is_public(&self) -> bool {
matches!(self.private_type, Some(PrivateType::Public) | None)
}
pub fn is_admin_only(&self) -> bool {
matches!(self.private_type, Some(PrivateType::AdminOnly))
}
pub fn is_specified_users_only(&self) -> bool {
matches!(
self.private_type,
Some(PrivateType::AdminAndSpecifiedMembers)
)
}
pub fn everyone_can_speak(&self) -> bool {
matches!(self.speak_permission, Some(SpeakPermission::Everyone))
}
pub fn admin_only_speak(&self) -> bool {
matches!(
self.speak_permission,
Some(SpeakPermission::AdminAndSpecifiedMembers)
)
}
pub fn display_name(&self) -> Option<&str> {
self.name.as_deref()
}
}
impl Default for Channel {
fn default() -> Self {
Self::new()
}
}
impl HasId for Channel {
fn id(&self) -> Option<&Snowflake> {
self.id.as_ref()
}
}
impl HasName for Channel {
fn name(&self) -> &str {
self.name.as_deref().unwrap_or("")
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(from = "u32", into = "u32")]
#[repr(u32)]
pub enum ChannelType {
Text = 0,
Voice = 2,
Group = 4,
Live = 10005,
Application = 10006,
Discussion = 10007,
Unknown(u32),
}
impl From<u32> for ChannelType {
fn from(value: u32) -> Self {
match value {
0 => Self::Text,
2 => Self::Voice,
4 => Self::Group,
10005 => Self::Live,
10006 => Self::Application,
10007 => Self::Discussion,
other => Self::Unknown(other),
}
}
}
impl ChannelType {
pub fn from_u8(value: u8) -> Option<Self> {
Some(Self::from(value as u32))
}
}
impl From<ChannelType> for u32 {
fn from(channel_type: ChannelType) -> Self {
match channel_type {
ChannelType::Text => 0,
ChannelType::Voice => 2,
ChannelType::Group => 4,
ChannelType::Live => 10005,
ChannelType::Application => 10006,
ChannelType::Discussion => 10007,
ChannelType::Unknown(value) => value,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(from = "u32", into = "u32")]
#[repr(u32)]
pub enum ChannelSubType {
Talk = 0,
Post = 1,
Cheat = 2,
Black = 3,
Unknown(u32),
}
impl From<u32> for ChannelSubType {
fn from(value: u32) -> Self {
match value {
0 => Self::Talk,
1 => Self::Post,
2 => Self::Cheat,
3 => Self::Black,
other => Self::Unknown(other),
}
}
}
impl ChannelSubType {
pub fn from_u8(value: u8) -> Option<Self> {
Some(Self::from(value as u32))
}
}
impl From<ChannelSubType> for u32 {
fn from(subtype: ChannelSubType) -> Self {
match subtype {
ChannelSubType::Talk => 0,
ChannelSubType::Post => 1,
ChannelSubType::Cheat => 2,
ChannelSubType::Black => 3,
ChannelSubType::Unknown(value) => value,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(from = "u8", into = "u8")]
#[repr(u8)]
pub enum PrivateType {
Public = 0,
AdminOnly = 1,
AdminAndSpecifiedMembers = 2,
Unknown(u8),
}
impl From<u8> for PrivateType {
fn from(value: u8) -> Self {
match value {
0 => Self::Public,
1 => Self::AdminOnly,
2 => Self::AdminAndSpecifiedMembers,
other => Self::Unknown(other),
}
}
}
impl From<PrivateType> for u8 {
fn from(private_type: PrivateType) -> Self {
match private_type {
PrivateType::Public => 0,
PrivateType::AdminOnly => 1,
PrivateType::AdminAndSpecifiedMembers => 2,
PrivateType::Unknown(other) => other,
}
}
}
impl PrivateType {
pub fn from_u8(value: u8) -> Option<Self> {
Some(Self::from(value))
}
}
impl From<PrivateType> for u32 {
fn from(private_type: PrivateType) -> Self {
match private_type {
PrivateType::Public => 0,
PrivateType::AdminOnly => 1,
PrivateType::AdminAndSpecifiedMembers => 2,
PrivateType::Unknown(value) => value as u32,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(from = "u8", into = "u8")]
#[repr(u8)]
pub enum SpeakPermission {
Invalid = 0,
Everyone = 1,
AdminAndSpecifiedMembers = 2,
Unknown(u8),
}
impl From<u8> for SpeakPermission {
fn from(value: u8) -> Self {
match value {
0 => Self::Invalid,
1 => Self::Everyone,
2 => Self::AdminAndSpecifiedMembers,
other => Self::Unknown(other),
}
}
}
impl From<SpeakPermission> for u8 {
fn from(speak_permission: SpeakPermission) -> Self {
match speak_permission {
SpeakPermission::Invalid => 0,
SpeakPermission::Everyone => 1,
SpeakPermission::AdminAndSpecifiedMembers => 2,
SpeakPermission::Unknown(other) => other,
}
}
}
impl SpeakPermission {
pub fn from_u8(value: u8) -> Option<Self> {
Some(Self::from(value))
}
}
impl From<SpeakPermission> for u32 {
fn from(speak_permission: SpeakPermission) -> Self {
match speak_permission {
SpeakPermission::Invalid => 0,
SpeakPermission::Everyone => 1,
SpeakPermission::AdminAndSpecifiedMembers => 2,
SpeakPermission::Unknown(value) => value as u32,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ChannelPermissions {
pub channel_id: Option<Snowflake>,
pub user_id: Option<Snowflake>,
pub role_id: Option<Snowflake>,
pub permissions: Option<String>,
}
impl ChannelPermissions {
pub fn new() -> Self {
Self {
channel_id: None,
user_id: None,
role_id: None,
permissions: None,
}
}
pub fn is_user_permission(&self) -> bool {
self.user_id.is_some()
}
pub fn is_role_permission(&self) -> bool {
self.role_id.is_some()
}
}
impl Default for ChannelPermissions {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_channel_creation() {
let channel = Channel::new();
assert!(channel.id.is_none());
assert!(channel.name.is_none());
assert!(channel.is_public()); }
#[test]
fn test_channel_types() {
let mut channel = Channel::new();
channel.channel_type = Some(ChannelType::Text);
assert!(channel.is_text());
assert!(!channel.is_voice());
channel.channel_type = Some(ChannelType::Voice);
assert!(channel.is_voice());
assert!(!channel.is_text());
channel.channel_type = Some(ChannelType::Group);
assert!(channel.is_group());
}
#[test]
fn test_channel_type_conversion() {
assert_eq!(ChannelType::from(0), ChannelType::Text);
assert_eq!(u32::from(ChannelType::Text), 0);
assert_eq!(ChannelType::from(10005), ChannelType::Live);
assert_eq!(u32::from(ChannelType::Live), 10005);
assert_eq!(ChannelType::from(99999), ChannelType::Unknown(99999));
assert_eq!(u32::from(ChannelType::Unknown(99999)), 99999);
}
#[test]
fn test_private_types() {
let mut channel = Channel::new();
channel.private_type = Some(PrivateType::Public);
assert!(channel.is_public());
assert!(!channel.is_admin_only());
channel.private_type = Some(PrivateType::AdminOnly);
assert!(!channel.is_public());
assert!(channel.is_admin_only());
channel.private_type = Some(PrivateType::AdminAndSpecifiedMembers);
assert!(channel.is_specified_users_only());
}
#[test]
fn test_speak_permissions() {
let mut channel = Channel::new();
channel.speak_permission = Some(SpeakPermission::Everyone);
assert!(channel.everyone_can_speak());
assert!(!channel.admin_only_speak());
channel.speak_permission = Some(SpeakPermission::AdminAndSpecifiedMembers);
assert!(!channel.everyone_can_speak());
assert!(channel.admin_only_speak());
}
#[test]
fn test_channel_mention() {
let mut channel = Channel::new();
channel.id = Some("123456789".to_string());
assert_eq!(channel.mention(), "<#123456789>");
}
#[test]
fn test_channel_permissions() {
let mut perms = ChannelPermissions::new();
assert!(!perms.is_user_permission());
assert!(!perms.is_role_permission());
perms.user_id = Some("user123".to_string());
assert!(perms.is_user_permission());
assert!(!perms.is_role_permission());
perms.user_id = None;
perms.role_id = Some("role123".to_string());
assert!(!perms.is_user_permission());
assert!(perms.is_role_permission());
}
}