use std::fmt;
use serde::{Deserialize, Serialize};
#[cfg(feature = "utoipa")]
use utoipa::ToSchema;
#[cfg(feature = "validator")]
use validator::Validate;
use crate::v1::types::util::Time;
use crate::v1::types::{ChannelId, PaginationKey, RoomId, UserId};
use super::{Channel, Room, User};
#[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
#[cfg_attr(feature = "utoipa", derive(ToSchema), schema(examples("a1b2c3")))]
pub struct InviteCode(pub String);
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct Invite {
pub code: InviteCode,
pub target: InviteTarget,
pub creator: User,
pub creator_id: UserId,
pub created_at: Time,
pub expires_at: Option<Time>,
pub description: Option<String>,
pub is_vanity: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct InviteWithMetadata {
pub max_uses: Option<u16>,
pub uses: u64,
#[serde(flatten)]
pub invite: Invite,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[serde(tag = "type")]
pub enum InviteTarget {
Room {
room: Room,
channel: Option<Box<Channel>>,
},
Gdm { channel: Box<Channel> },
Server,
User { user: Box<User> },
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[serde(tag = "type")]
pub enum InviteTargetId {
Room {
room_id: RoomId,
channel_id: Option<ChannelId>,
},
Gdm {
channel_id: ChannelId,
},
Server,
User {
user_id: UserId,
},
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct InvitePatch {
pub description: Option<Option<String>>,
pub expires_at: Option<Option<Time>>,
pub max_uses: Option<Option<u16>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
#[cfg_attr(feature = "validator", derive(Validate))]
pub struct InviteCreate {
#[cfg_attr(feature = "utoipa", schema(required = false))]
pub description: Option<String>,
#[cfg_attr(feature = "utoipa", schema(required = false))]
pub expires_at: Option<Time>,
#[cfg_attr(feature = "utoipa", schema(required = false))]
pub max_uses: Option<u16>,
}
impl fmt::Display for InviteCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl PaginationKey for InviteCode {
fn min() -> Self {
InviteCode("".to_string())
}
fn max() -> Self {
InviteCode("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ".to_string())
}
}
impl From<InviteWithMetadata> for Invite {
fn from(value: InviteWithMetadata) -> Self {
value.invite
}
}
impl InviteWithMetadata {
pub fn strip_metadata(self) -> Invite {
self.into()
}
pub fn is_dead(&self) -> bool {
if let Some(max_uses) = self.max_uses {
if self.uses >= max_uses as u64 {
return true;
}
}
if let Some(ref expires_at) = self.invite.expires_at {
if *expires_at < Time::now_utc() {
return true;
}
}
false
}
}
impl Invite {
pub fn new(
code: InviteCode,
target: InviteTarget,
creator: User,
creator_id: UserId,
created_at: Time,
expires_at: Option<Time>,
description: Option<String>,
is_vanity: bool,
) -> Self {
Self {
code,
target,
creator,
creator_id,
created_at,
expires_at,
description,
is_vanity,
}
}
}
impl PartialEq for Invite {
fn eq(&self, other: &Self) -> bool {
self.code == other.code
}
}
impl Eq for Invite {}