Skip to main content

max / makenotwork

5.9 KB · 238 lines History Blame Raw
1 //! People and the standing they hold: waitlist and selection, project roles,
2 //! creator tiers, and the reporting and moderation vocabulary.
3
4 use super::str_enum::impl_str_enum;
5 use serde::{Deserialize, Serialize};
6
7 // --- Waitlist ---
8
9 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
10 #[serde(rename_all = "lowercase")]
11 pub enum WaitlistStatus {
12 Pending,
13 Approved,
14 Spam,
15 }
16
17 impl_str_enum!(WaitlistStatus {
18 Pending => "pending",
19 Approved => "approved",
20 Spam => "spam",
21 });
22
23 impl WaitlistStatus {
24 /// Badge vocabulary (charter: `docs/design-system.md`).
25 pub fn badge_status(self) -> crate::types::BadgeStatus {
26 use crate::types::BadgeStatus;
27 match self {
28 Self::Approved => BadgeStatus::Live,
29 Self::Pending => BadgeStatus::Pending,
30 Self::Spam => BadgeStatus::Failed,
31 }
32 }
33 }
34
35 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
36 pub enum SelectionMethod {
37 #[serde(rename = "hand_picked")]
38 HandPicked,
39 #[serde(rename = "lottery")]
40 Lottery,
41 #[serde(rename = "invited")]
42 Invited,
43 }
44
45 impl_str_enum!(SelectionMethod {
46 HandPicked => "hand_picked",
47 Lottery => "lottery",
48 Invited => "invited",
49 });
50
51 // --- Follows ---
52
53 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
54 #[serde(rename_all = "lowercase")]
55 pub enum FollowTargetType {
56 User,
57 Project,
58 Tag,
59 }
60
61 impl_str_enum!(FollowTargetType {
62 User => "user",
63 Project => "project",
64 Tag => "tag",
65 });
66
67 // --- Project member roles ---
68
69 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
70 #[serde(rename_all = "lowercase")]
71 pub enum ProjectRole {
72 Owner,
73 Member,
74 }
75
76 impl_str_enum!(ProjectRole {
77 Owner => "owner",
78 Member => "member",
79 });
80
81 // --- Appeals ---
82
83 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
84 #[serde(rename_all = "lowercase")]
85 pub enum AppealDecision {
86 Approved,
87 Denied,
88 }
89
90 impl_str_enum!(AppealDecision {
91 Approved => "approved",
92 Denied => "denied",
93 });
94
95 // --- Reports ---
96
97 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
98 #[serde(rename_all = "lowercase")]
99 pub enum ReportTargetType {
100 Project,
101 Item,
102 }
103
104 impl_str_enum!(ReportTargetType {
105 Project => "project",
106 Item => "item",
107 });
108
109 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
110 #[serde(rename_all = "lowercase")]
111 pub enum ReportType {
112 Mislabeled,
113 Spam,
114 Abuse,
115 Infringement,
116 Other,
117 }
118
119 impl_str_enum!(ReportType {
120 Mislabeled => "mislabeled",
121 Spam => "spam",
122 Abuse => "abuse",
123 Infringement => "infringement",
124 Other => "other",
125 });
126
127 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
128 #[serde(rename_all = "lowercase")]
129 pub enum ReportStatus {
130 Open,
131 Resolved,
132 Dismissed,
133 }
134
135 impl_str_enum!(ReportStatus {
136 Open => "open",
137 Resolved => "resolved",
138 Dismissed => "dismissed",
139 });
140
141 // --- Creator Tiers ---
142
143 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
144 #[serde(rename_all = "snake_case")]
145 pub enum CreatorTier {
146 Basic,
147 SmallFiles,
148 BigFiles,
149 Everything,
150 }
151
152 impl_str_enum!(CreatorTier {
153 Basic => "basic",
154 SmallFiles => "small_files",
155 BigFiles => "big_files",
156 Everything => "everything",
157 });
158
159 impl CreatorTier {
160 /// Human-readable label for display.
161 pub fn label(&self) -> &'static str {
162 match self {
163 Self::Basic => "Basic",
164 Self::SmallFiles => "Small Files",
165 Self::BigFiles => "Big Files",
166 Self::Everything => "Everything",
167 }
168 }
169
170 /// Monthly standard price in cents. Reads from the process-global
171 /// `TierPrices` installed at startup from `assumptions.toml`. See
172 /// `crate::tier_prices` for the OnceLock and test-setup helper.
173 pub fn price_cents(&self) -> i32 {
174 crate::tier_prices::TierPrices::global().price_cents_for(*self)
175 }
176
177 /// Maximum per-file upload size in bytes. Reads from the global
178 /// `TierPrices` (see `price_cents`).
179 pub fn max_file_bytes(&self) -> i64 {
180 crate::tier_prices::TierPrices::global().max_file_bytes_for(*self)
181 }
182
183 /// Maximum total storage in bytes. Reads from the global `TierPrices`
184 /// (see `price_cents`).
185 pub fn max_storage_bytes(&self) -> i64 {
186 crate::tier_prices::TierPrices::global().max_storage_bytes_for(*self)
187 }
188
189 /// Whether this tier allows non-cover file uploads (audio, downloads, insertions).
190 /// Basic is text-only; covers are always allowed regardless of tier.
191 pub fn allows_file_uploads(&self) -> bool {
192 !matches!(self, Self::Basic)
193 }
194
195 /// Capability strings exposed to external OAuth implementers via `/oauth/userinfo`.
196 ///
197 /// Implementers gate features on these strings rather than tier names so the
198 /// tier lineup can change without breaking callers. Only ship strings backed by
199 /// live behavior; new capabilities are added when they actually launch.
200 pub fn features(&self) -> &'static [&'static str] {
201 match self {
202 Self::Basic => &[],
203 Self::SmallFiles => &["file_uploads"],
204 Self::BigFiles => &["file_uploads", "large_files"],
205 Self::Everything => &["file_uploads", "large_files"],
206 }
207 }
208 }
209
210 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
211 #[serde(rename_all = "snake_case")]
212 pub enum ModerationActionType {
213 Warning,
214 Suspension,
215 Termination,
216 ContentRemoval,
217 }
218
219 impl_str_enum!(ModerationActionType {
220 Warning => "warning",
221 Suspension => "suspension",
222 Termination => "termination",
223 ContentRemoval => "content_removal",
224 });
225
226 // Checkout types (Stripe metadata)
227
228 impl ModerationActionType {
229 pub fn label(&self) -> &'static str {
230 match self {
231 Self::Warning => "Warning",
232 Self::Suspension => "Suspension",
233 Self::Termination => "Termination",
234 Self::ContentRemoval => "Content Removal",
235 }
236 }
237 }
238