1use serde::{Deserialize as Deserialise, Serialize as Serialise};
2
3use crate::{prefix_broadcaster, User};
4
5#[derive(Serialise, Deserialise, Debug, Default, Clone)]
6pub struct UpdateCustomReward {
7 #[serde(skip_serializing_if = "Option::is_none")]
8 pub title: Option<String>,
9 #[serde(skip_serializing_if = "Option::is_none")]
10 pub prompt: Option<String>,
11 #[serde(skip_serializing_if = "Option::is_none")]
12 pub cost: Option<i64>,
13 #[serde(skip_serializing_if = "Option::is_none")]
14 pub background_colour: Option<String>,
15 #[serde(skip_serializing_if = "Option::is_none")]
16 pub is_enabled: Option<bool>,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub is_user_input_required: Option<bool>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub is_max_per_stream_enabled: Option<bool>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub max_per_stream: Option<i64>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub is_max_per_user_per_stream_enabled: Option<bool>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub max_per_user_per_stream: Option<i64>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub is_global_cooldown_enabled: Option<bool>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub global_cooldown_seconds: Option<i64>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 pub is_paused: Option<bool>,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 pub should_redeptions_skip_request_queue: Option<bool>,
35}
36
37impl UpdateCustomReward {
38 pub fn new() -> UpdateCustomReward {
39 UpdateCustomReward::default()
40 }
41
42 pub fn enable(mut self) -> UpdateCustomReward {
43 self.is_enabled = Some(true);
44 self
45 }
46
47 pub fn disable(mut self) -> UpdateCustomReward {
48 self.is_enabled = Some(false);
49 self
50 }
51
52 pub fn prompt<S: Into<String>>(mut self, text: S) -> UpdateCustomReward {
53 self.prompt = Some(text.into());
54 self
55 }
56
57 pub fn title<S: Into<String>>(mut self, text: S) -> UpdateCustomReward {
58 self.title = Some(text.into());
59 self
60 }
61}
62
63#[repr(C)]
64#[derive(Serialise, Deserialise, Clone, Debug, Default)]
65pub enum UserType {
66 #[serde(rename = "admin")]
67 Admin,
68 #[serde(rename = "global_mod")]
69 GlobalMod,
70 #[serde(rename = "staff")]
71 Staff,
72 #[serde(rename = "")]
73 #[default]
74 Normal,
75}
76
77#[repr(C)]
78#[derive(Serialise, Deserialise, Clone, Debug, Default)]
79pub enum BroadcasterType {
80 #[serde(rename = "affiliate")]
81 Affiliate,
82 #[serde(rename = "partner")]
83 Partner,
84 #[serde(rename = "")]
85 #[default]
86 Normal,
87}
88
89#[repr(C)]
90#[derive(Serialise, Deserialise, Clone, Debug)]
91pub struct UserData {
92 pub id: String,
93 pub login: String,
94 #[serde(rename = "display_name")]
95 pub name: String,
96 #[serde(rename = "type")]
97 pub user_type: UserType,
98 pub broadcaster_type: BroadcasterType,
99 pub description: String,
100 pub profile_image_url: String,
101 pub offline_image_url: String,
102 pub view_count: u32,
103 pub email: Option<String>,
104 pub created_at: String,
105}
106
107#[derive(Serialise, Deserialise, Debug)]
108pub struct GetCustomRewards {
109 pub data: Vec<GetCustomReward>,
110}
111
112#[derive(Serialise, Deserialise, Debug)]
113pub struct GetCustomReward {
114 pub id: String,
115 pub broadcaster_id: String,
116 pub broadcaster_login: String,
117 pub broadcaster_name: String,
118 pub title: String,
119 pub image: Option<EmoteStaticImages>,
120 pub default_image: EmoteStaticImages,
121 #[serde(rename = "background_color")]
122 pub background_colour: String,
123 pub is_enabled: bool,
124 pub cost: u32,
125 pub prompt: String,
126 pub is_user_input_required: bool,
127 pub is_paused: bool,
128 pub is_in_stock: bool,
129 pub max_per_stream_setting: MaxPerStreamSetting,
130 pub max_per_user_per_stream_setting: MaxPerUserPerStreamSetting,
131 pub global_cooldown_setting: GlobalCooldownSetting,
132 pub should_redemptions_skip_request_queue: bool,
133 pub redemptions_redeemed_current_stream: Option<u32>,
134 pub cooldown_expires_at: Option<String>,
135}
136
137#[derive(Serialise, Deserialise, Debug)]
138pub struct MaxPerUserPerStreamSetting {
139 pub is_enabled: bool,
140 pub max_per_user_per_stream: u32,
141}
142
143#[derive(Serialise, Deserialise, Debug)]
144pub struct AnnouncementMessage {
145 pub message: String,
146 pub colour: Option<String>,
147}
148
149#[derive(Serialise, Deserialise, Debug)]
150pub struct CreateCustomReward {
151 pub title: String,
152 pub cost: i64,
153 pub prompt: String,
154 pub is_enabled: bool,
155 pub is_user_input_required: bool,
156 pub is_max_per_stream_enabled: bool,
157 pub max_per_stream: i32,
158 pub is_max_per_user_per_stream_enabled: bool,
159 pub max_per_user_per_stream: i32,
160 pub is_global_cooldown_enabled: bool,
161 pub global_cooldown_seconds: i32,
162}
163
164impl Default for CreateCustomReward {
165 fn default() -> Self {
166 CreateCustomReward {
167 title: "default".to_owned(),
168 cost: 1,
169 prompt: "Reward Description".to_owned(),
170 max_per_stream: 1,
171 max_per_user_per_stream: 1,
172 global_cooldown_seconds: 1,
173 is_enabled: true,
174 is_user_input_required: false,
175 is_max_per_user_per_stream_enabled: false,
176 is_max_per_stream_enabled: false,
177 is_global_cooldown_enabled: false,
178 }
179 }
180}
181
182#[derive(Serialise, Deserialise, Debug)]
183pub struct MaxPerStreamSetting {
184 pub is_enabled: bool,
185 pub max_per_stream: i64,
186}
187
188#[derive(Serialise, Deserialise, Debug)]
189pub struct GlobalCooldownSetting {
190 pub is_enabled: bool,
191 pub global_cooldown_seconds: i64,
192}
193
194#[derive(Serialise, Deserialise, Debug)]
195pub struct CreatedCustomRewardResponse {
196 pub data: Vec<CreatedCustomReward>,
197}
198
199#[derive(Serialise, Deserialise, Debug)]
200pub struct CreatedCustomReward {
201 #[serde(flatten, with = "prefix_broadcaster")]
202 pub broadcaster: User,
203 pub id: String,
204 pub title: String,
205 pub prompt: String,
206 pub cost: i32,
207 pub image: Option<EmoteStaticImages>,
208 pub default_image: Option<EmoteStaticImages>,
209 pub background_color: String,
210 pub is_enabled: bool,
211 pub is_user_input_required: bool,
212 pub max_per_stream_setting: MaxPerStreamSetting,
213 pub max_per_user_per_stream: Option<i64>,
214 pub global_cooldown_setting: GlobalCooldownSetting,
215 pub is_paused: bool,
216 pub is_in_stock: bool,
217 pub should_redemptions_skip_request_queue: bool,
218 pub redemptions_redeemed_current_stream: Option<i32>,
219 pub cooldown_expires_at: Option<String>,
220}
221
222#[derive(Serialise, Deserialise, Debug)]
223pub struct AdSchedule {
224 pub data: Vec<AdDetails>,
225}
226
227#[derive(Serialise, Deserialise, Debug)]
228pub struct AdDetails {
229 pub next_ad_at: u32,
230 pub last_ad_at: u32,
231 pub duration: u32,
232 pub preroll_free_time: u32,
233 pub snooze_count: u32,
234 pub snooze_refresh_at: u32,
235}
236
237#[derive(Serialise, Deserialise, Debug)]
238pub struct Pagination {
239 pub cursor: Option<String>,
240}
241
242#[derive(Serialise, Deserialise, Debug)]
243pub struct GetChatters {
244 pub data: Vec<User>,
245 pub pagination: Pagination,
246 pub total: i32,
247}
248
249#[derive(Serialise, Deserialise, Debug, Clone)]
250pub struct EmoteStaticImages {
251 pub url_1x: String,
252 pub url_2x: String,
253 pub url_4x: String,
254}
255
256#[derive(Serialise, Deserialise, Debug, Clone)]
257pub enum EmoteType {
258 #[serde(rename = "bitstier")]
259 BitsTier,
260 #[serde(rename = "follower")]
261 Follower,
262 #[serde(rename = "subscriptions")]
263 Subscriptions,
264 #[serde(rename = "globals")]
265 Global,
266 #[serde(rename = "prime")]
267 Prime,
268 #[serde(rename = "turbo")]
269 Turbo,
270 #[serde(rename = "smilies")]
271 Smilies,
272 #[serde(rename = "limitedtime")]
273 LimitedTime,
274 #[serde(rename = "rewards")]
275 Rewards,
276 #[serde(rename = "none")]
277 None,
278 #[serde(rename = "owl2019")]
279 Owl2019,
280 #[serde(rename = "hypetrain")]
281 HypeTrain,
282 #[serde(rename = "PSTgasm")]
283 PSTGasm,
284 #[serde(rename = "twofactor")]
285 TwoFactor,
286}
287
288#[derive(Serialise, Deserialise, Debug, PartialEq, Clone)]
289pub enum EmoteFormat {
290 #[serde(rename = "static")]
291 Static,
292 #[serde(rename = "animated")]
293 Animated,
294}
295
296impl EmoteFormat {
297 pub fn string(&self) -> String {
298 match self {
299 EmoteFormat::Static => "static",
300 EmoteFormat::Animated => "animated",
301 }
302 .to_string()
303 }
304}
305
306#[derive(Serialise, Deserialise, Debug, Clone)]
307pub enum ThemeMode {
308 #[serde(rename = "light")]
309 Light,
310 #[serde(rename = "dark")]
311 Dark,
312}
313
314impl ThemeMode {
315 pub fn string(&self) -> String {
316 match self {
317 ThemeMode::Light => "light",
318 ThemeMode::Dark => "dark",
319 }
320 .to_string()
321 }
322}
323
324#[derive(Debug)]
325pub struct EmoteData {
326 pub id: String,
327 pub name: String,
328 pub images: EmoteStaticImages,
329 pub format: Vec<EmoteFormat>,
330 pub scale: Vec<String>,
331 pub theme_mode: Vec<ThemeMode>,
332
333 pub tier: Option<String>,
334 pub emote_type: Option<EmoteType>,
335 pub emote_set_id: Option<String>,
336}
337
338#[derive(Serialise, Deserialise, Debug, Clone)]
339pub struct ChannelEmoteData {
340 pub id: String,
341 pub name: String,
342 pub images: EmoteStaticImages,
343 pub tier: String,
344 pub emote_type: EmoteType,
345 pub emote_set_id: String,
346 pub format: Vec<EmoteFormat>,
347 pub scale: Vec<String>,
348 pub theme_mode: Vec<ThemeMode>,
349}
350
351#[derive(Serialise, Deserialise, Debug, Clone)]
352pub struct GlobalEmoteData {
353 pub id: String,
354 pub name: String,
355 pub images: EmoteStaticImages,
356 pub format: Vec<EmoteFormat>,
357 pub scale: Vec<String>,
358 pub theme_mode: Vec<ThemeMode>,
359}
360
361#[derive(Serialise, Deserialise, Debug)]
362pub struct ChannelEmotes {
363 pub data: Vec<ChannelEmoteData>,
364 pub template: String,
365}
366
367#[derive(Serialise, Deserialise, Debug)]
368pub struct GlobalEmotes {
369 pub data: Vec<GlobalEmoteData>,
370 pub template: String,
371}
372
373#[derive(Serialise, Deserialise, Debug)]
374pub struct Users {
375 pub data: Vec<UserData>,
376}
377
378#[derive(Serialise, Deserialise, Debug)]
379pub struct Moderators {
380 pub data: Vec<User>,
381 pub pagination: Pagination,
382}
383
384impl Into<EmoteData> for ChannelEmoteData {
385 fn into(self) -> EmoteData {
386 EmoteData {
387 id: self.id,
388 name: self.name,
389 images: self.images,
390 tier: Some(self.tier),
391 emote_type: Some(self.emote_type),
392 emote_set_id: Some(self.emote_set_id),
393 format: self.format,
394 scale: self.scale,
395 theme_mode: self.theme_mode,
396 }
397 }
398}
399
400impl Into<EmoteData> for GlobalEmoteData {
401 fn into(self) -> EmoteData {
402 EmoteData {
403 id: self.id,
404 name: self.name,
405 images: self.images,
406 tier: None,
407 emote_type: None,
408 emote_set_id: None,
409 format: self.format,
410 scale: self.scale,
411 theme_mode: self.theme_mode,
412 }
413 }
414}
415
416#[derive(Serialise, Deserialise, Debug)]
417pub enum EmoteScale {
418 #[serde(rename = "1.0")]
419 Size1,
420 #[serde(rename = "2.0")]
421 Size2,
422 #[serde(rename = "3.0")]
423 Size3,
424}
425
426impl EmoteScale {
427 pub fn idx(&self) -> usize {
428 match self {
429 EmoteScale::Size1 => 0,
430 EmoteScale::Size2 => 1,
431 EmoteScale::Size3 => 2,
432 }
433 }
434
435 pub fn to_string(&self) -> String {
436 match self {
437 EmoteScale::Size1 => "1x",
438 EmoteScale::Size2 => "2x",
439 EmoteScale::Size3 => "3x",
440 }
441 .to_string()
442 }
443}
444
445#[derive(Debug, Clone)]
446pub struct EmoteUrl {
447 pub url: String,
448 pub animated: bool,
449}