pub mod forum;
pub mod message;
pub mod permission_overwrite;
pub mod stage_instance;
pub mod thread;
pub mod webhook;
mod attachment;
mod attachment_flags;
mod channel_mention;
mod channel_type;
mod flags;
mod followed_channel;
mod video_quality_mode;
pub use self::{
attachment::Attachment,
attachment_flags::AttachmentFlags,
channel_mention::ChannelMention,
channel_type::ChannelType,
flags::ChannelFlags,
followed_channel::FollowedChannel,
message::Message,
stage_instance::StageInstance,
video_quality_mode::VideoQualityMode,
webhook::{Webhook, WebhookType},
};
use crate::{
channel::{
forum::{DefaultReaction, ForumLayout, ForumSortOrder, ForumTag},
permission_overwrite::PermissionOverwrite,
thread::{AutoArchiveDuration, ThreadMember, ThreadMetadata},
},
id::{
marker::{
ApplicationMarker, ChannelMarker, GenericMarker, GuildMarker, TagMarker, UserMarker,
},
Id,
},
user::User,
util::{ImageHash, Timestamp},
};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct Channel {
#[serde(skip_serializing_if = "Option::is_none")]
pub application_id: Option<Id<ApplicationMarker>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub applied_tags: Option<Vec<Id<TagMarker>>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub available_tags: Option<Vec<ForumTag>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bitrate: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub default_auto_archive_duration: Option<AutoArchiveDuration>,
#[serde(skip_serializing_if = "Option::is_none")]
pub default_forum_layout: Option<ForumLayout>,
#[serde(skip_serializing_if = "Option::is_none")]
pub default_reaction_emoji: Option<DefaultReaction>,
#[serde(skip_serializing_if = "Option::is_none")]
pub default_sort_order: Option<ForumSortOrder>,
#[serde(skip_serializing_if = "Option::is_none")]
pub default_thread_rate_limit_per_user: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
pub flags: Option<ChannelFlags>,
#[serde(skip_serializing_if = "Option::is_none")]
pub guild_id: Option<Id<GuildMarker>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub icon: Option<ImageHash>,
pub id: Id<ChannelMarker>,
#[serde(skip_serializing_if = "Option::is_none")]
pub invitable: Option<bool>,
#[serde(rename = "type")]
pub kind: ChannelType,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_message_id: Option<Id<GenericMarker>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_pin_timestamp: Option<Timestamp>,
#[serde(skip_serializing_if = "Option::is_none")]
pub managed: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub member: Option<ThreadMember>,
#[serde(skip_serializing_if = "Option::is_none")]
pub member_count: Option<i8>,
#[serde(skip_serializing_if = "Option::is_none")]
pub message_count: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub newly_created: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub nsfw: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub owner_id: Option<Id<UserMarker>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent_id: Option<Id<ChannelMarker>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub permission_overwrites: Option<Vec<PermissionOverwrite>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub position: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rate_limit_per_user: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
pub recipients: Option<Vec<User>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rtc_region: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub thread_metadata: Option<ThreadMetadata>,
#[serde(skip_serializing_if = "Option::is_none")]
pub topic: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user_limit: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub video_quality_mode: Option<VideoQualityMode>,
}
#[cfg(test)]
mod tests {
use super::{AutoArchiveDuration, Channel, ChannelType, ThreadMember, ThreadMetadata};
use crate::{
channel::permission_overwrite::{PermissionOverwrite, PermissionOverwriteType},
guild::Permissions,
id::Id,
util::Timestamp,
};
#[test]
fn guild_channel_unknown_field_deserialization() {
let input = serde_json::json!({
"type": 0,
"topic": "a",
"rate_limit_per_user": 0,
"position": 0,
"permission_overwrites": [],
"parent_id": null,
"nsfw": false,
"name": "hey",
"last_message_id": "3",
"id": "2",
"guild_id": "1",
"guild_hashes": {
"version": 1,
"roles": {
"hash": "aaaaaaaaaaa"
},
"metadata": {
"hash": "bbbbbbbbbbb"
},
"channels": {
"hash": "ccccccccccc"
}
},
"unknown_field": "the deserializer should skip unknown field names",
});
let value = Channel {
application_id: None,
applied_tags: None,
available_tags: None,
bitrate: None,
default_auto_archive_duration: None,
default_forum_layout: None,
default_reaction_emoji: None,
default_sort_order: None,
default_thread_rate_limit_per_user: None,
flags: None,
guild_id: Some(Id::new(1)),
icon: None,
id: Id::new(2),
invitable: None,
kind: ChannelType::GuildText,
last_message_id: Some(Id::new(3)),
last_pin_timestamp: None,
managed: None,
member: None,
member_count: None,
message_count: None,
name: Some("hey".to_owned()),
newly_created: None,
nsfw: Some(false),
owner_id: None,
parent_id: None,
permission_overwrites: Some(Vec::new()),
position: Some(0),
rate_limit_per_user: Some(0),
recipients: None,
rtc_region: None,
thread_metadata: None,
topic: Some("a".to_owned()),
user_limit: None,
video_quality_mode: None,
};
assert_eq!(value, serde_json::from_value(input).unwrap());
}
#[test]
fn guild_category_channel_deserialization() {
let value = Channel {
application_id: None,
applied_tags: None,
available_tags: None,
bitrate: None,
default_auto_archive_duration: None,
default_forum_layout: None,
default_reaction_emoji: None,
default_sort_order: None,
default_thread_rate_limit_per_user: None,
flags: None,
guild_id: Some(Id::new(2)),
icon: None,
id: Id::new(1),
invitable: None,
kind: ChannelType::GuildCategory,
last_message_id: None,
last_pin_timestamp: None,
managed: None,
member: None,
member_count: None,
message_count: None,
name: Some("foo".to_owned()),
newly_created: None,
nsfw: None,
owner_id: None,
parent_id: None,
permission_overwrites: Some(Vec::new()),
position: Some(3),
rate_limit_per_user: None,
recipients: None,
rtc_region: None,
thread_metadata: None,
topic: None,
user_limit: None,
video_quality_mode: None,
};
let permission_overwrites: Vec<PermissionOverwrite> = Vec::new();
assert_eq!(
value,
serde_json::from_value(serde_json::json!({
"id": "1",
"guild_id": Some("2"),
"name": "foo",
"permission_overwrites": permission_overwrites,
"position": 3,
"type": 4,
}))
.unwrap()
);
}
#[test]
fn guild_announcement_channel_deserialization() {
let value = Channel {
application_id: None,
applied_tags: None,
available_tags: None,
bitrate: None,
default_auto_archive_duration: None,
default_forum_layout: None,
default_reaction_emoji: None,
default_sort_order: None,
default_thread_rate_limit_per_user: None,
flags: None,
guild_id: Some(Id::new(2)),
icon: None,
id: Id::new(1),
invitable: None,
kind: ChannelType::GuildAnnouncement,
last_message_id: Some(Id::new(4)),
last_pin_timestamp: None,
managed: None,
member: None,
member_count: None,
message_count: None,
name: Some("news".to_owned()),
newly_created: None,
nsfw: Some(true),
owner_id: None,
parent_id: Some(Id::new(5)),
permission_overwrites: Some(Vec::new()),
position: Some(3),
rate_limit_per_user: None,
recipients: None,
rtc_region: None,
thread_metadata: None,
topic: Some("a news channel".to_owned()),
user_limit: None,
video_quality_mode: None,
};
let permission_overwrites: Vec<PermissionOverwrite> = Vec::new();
assert_eq!(
value,
serde_json::from_value(serde_json::json!({
"id": "1",
"guild_id": "2",
"name": "news",
"nsfw": true,
"last_message_id": "4",
"parent_id": "5",
"permission_overwrites": permission_overwrites,
"position": 3,
"topic": "a news channel",
"type": ChannelType::GuildAnnouncement,
}))
.unwrap()
);
}
#[test]
fn guild_announcement_thread_deserialization() {
let timestamp = Timestamp::from_secs(1_632_074_792).expect("non zero");
let formatted = timestamp.iso_8601().to_string();
let value = Channel {
application_id: None,
applied_tags: None,
available_tags: None,
bitrate: None,
default_auto_archive_duration: Some(AutoArchiveDuration::Hour),
default_forum_layout: None,
default_reaction_emoji: None,
default_sort_order: None,
default_thread_rate_limit_per_user: None,
flags: None,
guild_id: Some(Id::new(1)),
icon: None,
id: Id::new(6),
invitable: None,
kind: ChannelType::AnnouncementThread,
last_message_id: Some(Id::new(3)),
last_pin_timestamp: None,
managed: Some(true),
member: Some(ThreadMember {
flags: 0_u64,
id: Some(Id::new(4)),
join_timestamp: timestamp,
member: None,
presence: None,
user_id: Some(Id::new(5)),
}),
member_count: Some(50),
message_count: Some(50),
name: Some("newsthread".into()),
newly_created: Some(true),
nsfw: None,
owner_id: Some(Id::new(5)),
parent_id: Some(Id::new(2)),
permission_overwrites: None,
position: None,
rate_limit_per_user: Some(1000),
recipients: None,
rtc_region: None,
thread_metadata: Some(ThreadMetadata {
archived: false,
auto_archive_duration: AutoArchiveDuration::Day,
archive_timestamp: timestamp,
create_timestamp: Some(timestamp),
invitable: None,
locked: false,
}),
topic: None,
user_limit: None,
video_quality_mode: None,
};
assert_eq!(
value,
serde_json::from_value(serde_json::json!({
"id": "6",
"guild_id": "1",
"type": ChannelType::AnnouncementThread,
"last_message_id": "3",
"member": {
"flags": 0,
"id": "4",
"join_timestamp": formatted,
"user_id": "5",
},
"default_auto_archive_duration": 60,
"managed": true,
"member_count": 50,
"message_count": 50,
"name": "newsthread",
"newly_created": true,
"owner_id": "5",
"parent_id": "2",
"rate_limit_per_user": 1000,
"thread_metadata": {
"archive_timestamp": formatted,
"archived": false,
"auto_archive_duration": AutoArchiveDuration::Day,
"create_timestamp": formatted,
"locked": false
}
}))
.unwrap()
)
}
#[test]
fn public_thread_deserialization() {
let timestamp = Timestamp::from_secs(1_632_074_792).expect("non zero");
let value = Channel {
application_id: None,
applied_tags: None,
available_tags: None,
bitrate: None,
default_auto_archive_duration: Some(AutoArchiveDuration::Hour),
default_forum_layout: None,
default_reaction_emoji: None,
default_sort_order: None,
default_thread_rate_limit_per_user: None,
flags: None,
guild_id: Some(Id::new(1)),
icon: None,
id: Id::new(6),
invitable: None,
kind: ChannelType::PublicThread,
last_message_id: Some(Id::new(3)),
last_pin_timestamp: None,
managed: Some(true),
member: Some(ThreadMember {
flags: 0_u64,
id: Some(Id::new(4)),
join_timestamp: timestamp,
member: None,
presence: None,
user_id: Some(Id::new(5)),
}),
member_count: Some(50),
message_count: Some(50),
name: Some("publicthread".into()),
newly_created: Some(true),
nsfw: None,
owner_id: Some(Id::new(5)),
parent_id: Some(Id::new(2)),
permission_overwrites: None,
position: None,
rate_limit_per_user: Some(1000),
recipients: None,
rtc_region: None,
thread_metadata: Some(ThreadMetadata {
archived: false,
auto_archive_duration: AutoArchiveDuration::Day,
archive_timestamp: timestamp,
create_timestamp: Some(timestamp),
invitable: None,
locked: false,
}),
topic: None,
user_limit: None,
video_quality_mode: None,
};
assert_eq!(
value,
serde_json::from_value(serde_json::json!({
"id": "6",
"guild_id": "1",
"type": ChannelType::PublicThread,
"last_message_id": "3",
"member": {
"flags": 0,
"id": "4",
"join_timestamp": timestamp,
"user_id": "5",
},
"default_auto_archive_duration": 60,
"managed": true,
"member_count": 50,
"message_count": 50,
"name": "publicthread",
"newly_created": true,
"owner_id": "5",
"parent_id": "2",
"rate_limit_per_user": 1000,
"thread_metadata": {
"archive_timestamp": timestamp,
"archived": false,
"auto_archive_duration": AutoArchiveDuration::Day,
"create_timestamp": timestamp,
"locked": false
}
}))
.unwrap()
)
}
#[test]
fn private_thread_deserialization() {
let timestamp = Timestamp::from_secs(1_632_074_792).expect("non zero");
let formatted = timestamp.iso_8601().to_string();
let value = Channel {
application_id: None,
applied_tags: None,
available_tags: None,
bitrate: None,
default_auto_archive_duration: Some(AutoArchiveDuration::Hour),
default_forum_layout: None,
default_reaction_emoji: None,
default_sort_order: None,
default_thread_rate_limit_per_user: None,
flags: None,
guild_id: Some(Id::new(1)),
icon: None,
id: Id::new(6),
invitable: Some(true),
kind: ChannelType::PrivateThread,
last_message_id: Some(Id::new(3)),
last_pin_timestamp: None,
managed: Some(true),
member: Some(ThreadMember {
flags: 0_u64,
id: Some(Id::new(4)),
join_timestamp: timestamp,
member: None,
presence: None,
user_id: Some(Id::new(5)),
}),
member_count: Some(-1),
message_count: Some(50),
name: Some("privatethread".into()),
newly_created: Some(true),
nsfw: None,
owner_id: Some(Id::new(5)),
parent_id: Some(Id::new(2)),
permission_overwrites: Some(Vec::from([PermissionOverwrite {
allow: Permissions::empty(),
deny: Permissions::empty(),
id: Id::new(5),
kind: PermissionOverwriteType::Member,
}])),
position: None,
rate_limit_per_user: Some(1000),
recipients: None,
rtc_region: None,
thread_metadata: Some(ThreadMetadata {
archived: false,
auto_archive_duration: AutoArchiveDuration::Day,
archive_timestamp: timestamp,
create_timestamp: Some(timestamp),
invitable: None,
locked: false,
}),
topic: None,
user_limit: None,
video_quality_mode: None,
};
assert_eq!(
value,
serde_json::from_value(serde_json::json!({
"id": "6",
"guild_id": "1",
"type": ChannelType::PrivateThread,
"last_message_id": "3",
"member": {
"flags": 0,
"id": "4",
"join_timestamp": formatted,
"user_id": "5",
},
"default_auto_archive_duration": 60,
"invitable": true,
"managed": true,
"member_count": -1,
"message_count": 50,
"name": "privatethread",
"newly_created": true,
"owner_id": "5",
"parent_id": "2",
"rate_limit_per_user": 1000,
"thread_metadata": {
"archive_timestamp": formatted,
"archived": false,
"auto_archive_duration": AutoArchiveDuration::Day,
"create_timestamp": formatted,
"locked": false
},
"permission_overwrites": [
{
"allow": "0",
"deny": "0",
"type": 1,
"id": "5"
}
]
}))
.unwrap()
)
}
}