use serde::{Deserialize, Serialize};
macro_rules! string_enum {
(
$(#[$meta:meta])*
pub enum $name:ident { $($(#[$vmeta:meta])* $variant:ident => $wire:literal),+ $(,)? }
) => {
$(#[$meta])*
#[derive(Debug, Clone, PartialEq, Eq, Hash, ::serde::Serialize, ::serde::Deserialize)]
pub enum $name {
$($(#[$vmeta])* #[serde(rename = $wire)] $variant,)+
#[serde(untagged)]
Other(String),
}
impl $name {
pub fn as_str(&self) -> &str {
match self {
$($name::$variant => $wire,)+
$name::Other(value) => value.as_str(),
}
}
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
impl std::str::FromStr for $name {
type Err = std::convert::Infallible;
fn from_str(value: &str) -> Result<Self, Self::Err> {
Ok(match value {
$($wire => $name::$variant,)+
other => $name::Other(other.to_string()),
})
}
}
impl From<&str> for $name {
fn from(value: &str) -> Self {
value.parse().unwrap_or_else(|_| unreachable!())
}
}
impl From<String> for $name {
fn from(value: String) -> Self {
$name::from(value.as_str())
}
}
};
}
pub(crate) use string_enum;
string_enum! {
pub enum Platform {
Twitter => "twitter",
Linkedin => "linkedin",
Facebook => "facebook",
Instagram => "instagram",
InstagramBusiness => "instagram-business",
Telegram => "telegram",
Twitch => "twitch",
Discord => "discord",
Slack => "slack",
Reddit => "reddit",
Pinterest => "pinterest",
Tumblr => "tumblr",
Dribbble => "dribbble",
Mewe => "mewe",
Tiktok => "tiktok",
Youtube => "youtube",
Bluesky => "bluesky",
Threads => "threads",
Mastodon => "mastodon",
Lemmy => "lemmy",
Devto => "devto",
Hashnode => "hashnode",
Medium => "medium",
Substack => "substack",
GoogleBusiness => "google-business",
Kick => "kick",
Listmonk => "listmonk",
Wordpress => "wordpress",
Nostr => "nostr",
Whop => "whop",
Skool => "skool",
}
}
string_enum! {
pub enum PostStatus {
Draft => "draft",
Scheduled => "scheduled",
Publishing => "publishing",
Published => "published",
PartiallyFailed => "partially_failed",
Failed => "failed",
Cancelled => "cancelled",
}
}
string_enum! {
pub enum DeliveryStatus {
Pending => "pending",
Queued => "queued",
Delayed => "delayed",
Publishing => "publishing",
Published => "published",
Failed => "failed",
Cancelled => "cancelled",
}
}
string_enum! {
pub enum ContentType {
Post => "post",
Thread => "thread",
Reel => "reel",
}
}
string_enum! {
pub enum ArtifactType {
TextPost => "text_post",
Thread => "thread",
Article => "article",
Carousel => "carousel",
ShortVideo => "short_video",
LinkShare => "link_share",
}
}
string_enum! {
pub enum MediaType {
Image => "image",
Video => "video",
Gif => "gif",
Document => "document",
}
}
string_enum! {
pub enum HealthStatus {
Healthy => "healthy",
Degraded => "degraded",
Expired => "expired",
Revoked => "revoked",
Unknown => "unknown",
}
}
string_enum! {
pub enum GapUnit {
Hours => "hours",
Days => "days",
Weeks => "weeks",
Months => "months",
}
}
string_enum! {
pub enum WorkspaceType {
Personal => "PERSONAL",
Team => "TEAM",
Organization => "ORGANIZATION",
Client => "CLIENT",
Project => "PROJECT",
Department => "DEPARTMENT",
Event => "EVENT",
Temporary => "TEMPORARY",
Community => "COMMUNITY",
Brand => "BRAND",
Agency => "AGENCY",
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MediaItem {
#[serde(rename = "type")]
pub media_type: MediaType,
#[serde(default)]
pub name: Option<String>,
pub url: String,
#[serde(default)]
pub size: Option<f64>,
#[serde(default)]
pub alt: Option<String>,
#[serde(default)]
pub thumbnail: Option<String>,
}
impl MediaItem {
pub fn new(media_type: MediaType, name: impl Into<String>, url: impl Into<String>) -> Self {
Self {
media_type,
name: Some(name.into()),
url: url.into(),
size: None,
alt: None,
thumbnail: None,
}
}
pub fn alt(mut self, alt: impl Into<String>) -> Self {
self.alt = Some(alt.into());
self
}
}
#[derive(Debug, Clone, Deserialize)]
pub struct PageMeta {
#[serde(default)]
pub current_page: u32,
#[serde(default)]
pub per_page: u32,
#[serde(default)]
pub total: u64,
#[serde(default)]
pub last_page: u32,
#[serde(default)]
pub from: u64,
#[serde(default)]
pub to: u64,
}
#[derive(Debug, Clone, Deserialize)]
pub struct Page<T> {
#[serde(rename = "data", default = "Vec::new")]
pub items: Vec<T>,
pub meta: PageMeta,
}
impl<T> Page<T> {
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
pub fn len(&self) -> usize {
self.items.len()
}
pub fn has_next(&self) -> bool {
self.meta.current_page < self.meta.last_page
}
}
impl<T> IntoIterator for Page<T> {
type Item = T;
type IntoIter = std::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.items.into_iter()
}
}
impl<'a, T> IntoIterator for &'a Page<T> {
type Item = &'a T;
type IntoIter = std::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.items.iter()
}
}
#[derive(Debug, Clone, Deserialize)]
pub struct Message {
pub message: String,
}