use serde::{Deserialize, Serialize};
#[cfg(feature = "utoipa")]
use utoipa::ToSchema;
#[cfg(feature = "validator")]
use validator::Validate;
use crate::v1::types::tag::Tag;
use crate::v1::types::user_config::UserConfigChannel;
use crate::v1::types::util::{some_option, Time};
use crate::v1::types::{util::Diff, ChannelVerId, PermissionOverwrite};
use crate::v1::types::{MediaId, MessageVerId, TagId, ThreadMember, User};
use super::{ChannelId, RoomId, UserId};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[cfg_attr(feature = "validator", derive(Validate))]
pub struct Channel {
pub id: ChannelId,
pub room_id: Option<RoomId>,
pub creator_id: UserId,
pub owner_id: Option<UserId>,
pub version_id: ChannelVerId,
#[cfg_attr(feature = "utoipa", schema(min_length = 1, max_length = 64))]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 64)))]
pub name: String,
#[cfg_attr(
feature = "utoipa",
schema(required = false, min_length = 1, max_length = 2048)
)]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 2048)))]
pub description: Option<String>,
#[serde(rename = "type")]
pub ty: ChannelType,
pub member_count: u64,
pub online_count: u64,
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 256)))]
pub tags: Option<Vec<TagId>>,
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 256)))]
pub tags_available: Option<Vec<Tag>>,
pub deleted_at: Option<Time>,
pub archived_at: Option<Time>,
pub locked: bool,
pub parent_id: Option<ChannelId>,
pub position: Option<u16>,
pub permission_overwrites: Vec<PermissionOverwrite>,
pub nsfw: bool,
pub last_version_id: Option<MessageVerId>,
pub message_count: Option<u64>,
pub root_message_count: Option<u64>,
#[cfg_attr(feature = "validator", validate(range(min = 8192)))]
pub bitrate: Option<u64>,
#[cfg_attr(feature = "validator", validate(range(min = 1, max = 100)))]
pub user_limit: Option<u64>,
pub is_unread: Option<bool>,
pub last_read_id: Option<MessageVerId>,
pub mention_count: Option<u64>,
pub user_config: Option<UserConfigChannel>,
pub recipients: Vec<User>,
pub icon: Option<MediaId>,
#[serde(default)]
pub invitable: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub thread_member: Option<Box<ThreadMember>>,
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub enum ChannelType {
#[default]
Text,
ThreadPublic,
ThreadPrivate,
Dm,
Gdm,
#[cfg(feature = "feat_thread_type_forums")]
Forum,
Voice,
Category,
Calendar,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "validator", derive(Validate))]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct ChannelCreate {
#[cfg_attr(feature = "utoipa", schema(max_length = 1, min_length = 64))]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 64)))]
pub name: String,
#[cfg_attr(
feature = "utoipa",
schema(required = false, max_length = 1, min_length = 2048)
)]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 2048)))]
pub description: Option<String>,
pub icon: Option<MediaId>,
#[serde(default, rename = "type")]
pub ty: ChannelType,
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 4096)))]
pub tags: Option<Vec<TagId>>,
#[serde(default)]
pub nsfw: bool,
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 10)))]
pub recipients: Option<Vec<UserId>>,
#[cfg_attr(feature = "validator", validate(range(min = 8192)))]
pub bitrate: Option<u64>,
#[cfg_attr(feature = "validator", validate(range(min = 1, max = 100)))]
pub user_limit: Option<u64>,
pub parent_id: Option<ChannelId>,
#[serde(default)]
pub permission_overwrites: Vec<PermissionOverwrite>,
#[serde(default)]
pub invitable: bool,
}
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[cfg_attr(feature = "validator", derive(Validate))]
pub struct ChannelPatch {
#[cfg_attr(
feature = "utoipa",
schema(required = false, min_length = 1, max_length = 64)
)]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 64)))]
pub name: Option<String>,
#[cfg_attr(feature = "utoipa", schema(min_length = 1, max_length = 2048))]
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 2048)))]
#[serde(default, deserialize_with = "some_option")]
pub description: Option<Option<String>>,
#[serde(default, deserialize_with = "some_option")]
pub icon: Option<Option<MediaId>>,
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 4096)))]
pub tags: Option<Vec<TagId>>,
pub nsfw: Option<bool>,
#[cfg_attr(feature = "validator", validate(range(min = 8192)))]
#[serde(default, deserialize_with = "some_option")]
pub bitrate: Option<Option<u64>>,
#[cfg_attr(feature = "validator", validate(range(min = 1, max = 100)))]
#[serde(default, deserialize_with = "some_option")]
pub user_limit: Option<Option<u64>>,
#[serde(default, deserialize_with = "some_option")]
pub owner_id: Option<Option<UserId>>,
pub ty: Option<ChannelType>,
#[serde(default, deserialize_with = "some_option")]
pub parent_id: Option<Option<ChannelId>>,
pub archived: Option<bool>,
pub locked: Option<bool>,
pub invitable: Option<bool>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[cfg_attr(feature = "validator", derive(Validate))]
pub struct ChannelReorder {
#[serde(default)]
#[validate(length(min = 1, max = 1024))]
pub channels: Vec<ChannelReorderItem>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[cfg_attr(feature = "validator", derive(Validate))]
pub struct ChannelReorderItem {
pub id: ChannelId,
#[serde(default, deserialize_with = "some_option")]
pub position: Option<Option<u16>>,
#[serde(default, deserialize_with = "some_option")]
pub parent_id: Option<Option<ChannelId>>,
}
impl Diff<Channel> for ChannelPatch {
fn changes(&self, other: &Channel) -> bool {
self.name.changes(&other.name)
|| self.description.changes(&other.description)
|| self.icon.changes(&other.icon)
|| self.tags.changes(&other.tags)
|| self.nsfw.changes(&other.nsfw)
|| self.bitrate.changes(&other.bitrate)
|| self.user_limit.changes(&other.user_limit)
|| self.owner_id.changes(&other.owner_id)
|| self.ty.changes(&other.ty)
|| self.parent_id.changes(&other.parent_id)
|| self.locked.changes(&other.locked)
|| self.invitable.changes(&other.invitable)
|| self
.archived
.is_some_and(|a| a != other.archived_at.is_some())
}
}
impl Channel {
pub fn strip(self) -> Channel {
Channel {
is_unread: None,
last_read_id: None,
mention_count: None,
user_config: None,
..self
}
}
}
impl ChannelType {
pub fn is_thread(&self) -> bool {
matches!(self, ChannelType::ThreadPublic | ChannelType::ThreadPrivate)
}
pub fn has_members(&self) -> bool {
matches!(
self,
ChannelType::ThreadPublic | ChannelType::ThreadPrivate | ChannelType::Gdm
)
}
pub fn has_text(&self) -> bool {
matches!(
self,
ChannelType::ThreadPublic
| ChannelType::ThreadPrivate
| ChannelType::Text
| ChannelType::Dm
| ChannelType::Gdm
| ChannelType::Voice
)
}
pub fn has_public_threads(&self) -> bool {
matches!(
self,
ChannelType::Text | ChannelType::Dm | ChannelType::Gdm | ChannelType::Forum
)
}
pub fn has_private_threads(&self) -> bool {
matches!(self, ChannelType::Text | ChannelType::Dm | ChannelType::Gdm)
}
pub fn has_voice(&self) -> bool {
matches!(self, ChannelType::Voice)
}
pub fn is_taggable(&self) -> bool {
matches!(self, ChannelType::ThreadPublic | ChannelType::ThreadPrivate)
}
pub fn has_tags(&self) -> bool {
matches!(self, ChannelType::Forum)
}
pub fn has_icon(&self) -> bool {
matches!(self, ChannelType::Gdm)
}
pub fn can_change_to(self, other: ChannelType) -> bool {
match (self, other) {
(ChannelType::ThreadPublic, ChannelType::ThreadPrivate) => true,
(ChannelType::ThreadPrivate, ChannelType::ThreadPublic) => true,
_ => false,
}
}
}