//! People and the standing they hold: waitlist and selection, project roles, //! creator tiers, and the reporting and moderation vocabulary. use super::str_enum::impl_str_enum; use serde::{Deserialize, Serialize}; // --- Waitlist --- #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum WaitlistStatus { Pending, Approved, Spam, } impl_str_enum!(WaitlistStatus { Pending => "pending", Approved => "approved", Spam => "spam", }); impl WaitlistStatus { /// Badge vocabulary (charter: `docs/design-system.md`). pub fn badge_status(self) -> crate::types::BadgeStatus { use crate::types::BadgeStatus; match self { Self::Approved => BadgeStatus::Live, Self::Pending => BadgeStatus::Pending, Self::Spam => BadgeStatus::Failed, } } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub enum SelectionMethod { #[serde(rename = "hand_picked")] HandPicked, #[serde(rename = "lottery")] Lottery, #[serde(rename = "invited")] Invited, } impl_str_enum!(SelectionMethod { HandPicked => "hand_picked", Lottery => "lottery", Invited => "invited", }); // --- Follows --- #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum FollowTargetType { User, Project, Tag, } impl_str_enum!(FollowTargetType { User => "user", Project => "project", Tag => "tag", }); // --- Project member roles --- #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum ProjectRole { Owner, Member, } impl_str_enum!(ProjectRole { Owner => "owner", Member => "member", }); // --- Appeals --- #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum AppealDecision { Approved, Denied, } impl_str_enum!(AppealDecision { Approved => "approved", Denied => "denied", }); // --- Reports --- #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum ReportTargetType { Project, Item, } impl_str_enum!(ReportTargetType { Project => "project", Item => "item", }); #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum ReportType { Mislabeled, Spam, Abuse, Infringement, Other, } impl_str_enum!(ReportType { Mislabeled => "mislabeled", Spam => "spam", Abuse => "abuse", Infringement => "infringement", Other => "other", }); #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum ReportStatus { Open, Resolved, Dismissed, } impl_str_enum!(ReportStatus { Open => "open", Resolved => "resolved", Dismissed => "dismissed", }); // --- Creator Tiers --- #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum CreatorTier { Basic, SmallFiles, BigFiles, Everything, } impl_str_enum!(CreatorTier { Basic => "basic", SmallFiles => "small_files", BigFiles => "big_files", Everything => "everything", }); impl CreatorTier { /// Human-readable label for display. pub fn label(&self) -> &'static str { match self { Self::Basic => "Basic", Self::SmallFiles => "Small Files", Self::BigFiles => "Big Files", Self::Everything => "Everything", } } /// Monthly standard price in cents. Reads from the process-global /// `TierPrices` installed at startup from `assumptions.toml`. See /// `crate::tier_prices` for the OnceLock and test-setup helper. pub fn price_cents(&self) -> i32 { crate::tier_prices::TierPrices::global().price_cents_for(*self) } /// Maximum per-file upload size in bytes. Reads from the global /// `TierPrices` (see `price_cents`). pub fn max_file_bytes(&self) -> i64 { crate::tier_prices::TierPrices::global().max_file_bytes_for(*self) } /// Maximum total storage in bytes. Reads from the global `TierPrices` /// (see `price_cents`). pub fn max_storage_bytes(&self) -> i64 { crate::tier_prices::TierPrices::global().max_storage_bytes_for(*self) } /// Whether this tier allows non-cover file uploads (audio, downloads, insertions). /// Basic is text-only; covers are always allowed regardless of tier. pub fn allows_file_uploads(&self) -> bool { !matches!(self, Self::Basic) } /// Capability strings exposed to external OAuth implementers via `/oauth/userinfo`. /// /// Implementers gate features on these strings rather than tier names so the /// tier lineup can change without breaking callers. Only ship strings backed by /// live behavior; new capabilities are added when they actually launch. pub fn features(&self) -> &'static [&'static str] { match self { Self::Basic => &[], Self::SmallFiles => &["file_uploads"], Self::BigFiles => &["file_uploads", "large_files"], Self::Everything => &["file_uploads", "large_files"], } } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum ModerationActionType { Warning, Suspension, Termination, ContentRemoval, } impl_str_enum!(ModerationActionType { Warning => "warning", Suspension => "suspension", Termination => "termination", ContentRemoval => "content_removal", }); // Checkout types (Stripe metadata) impl ModerationActionType { pub fn label(&self) -> &'static str { match self { Self::Warning => "Warning", Self::Suspension => "Suspension", Self::Termination => "Termination", Self::ContentRemoval => "Content Removal", } } }