1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#![doc(alias = "channel.channel_points_custom_reward.update")]
use super::*;
#[derive(Clone, Debug, typed_builder::TypedBuilder, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "deny_unknown_fields", serde(deny_unknown_fields))]
#[non_exhaustive]
pub struct ChannelPointsCustomRewardUpdateV1 {
#[builder(setter(into))]
pub broadcaster_user_id: types::UserId,
#[builder(default, setter(into))]
pub reward_id: Option<types::RewardId>,
}
impl EventSubscription for ChannelPointsCustomRewardUpdateV1 {
type Payload = ChannelPointsCustomRewardUpdateV1Payload;
const EVENT_TYPE: EventType = EventType::ChannelPointsCustomRewardUpdate;
#[cfg(feature = "twitch_oauth2")]
const SCOPE: &'static [twitch_oauth2::Scope] = &[twitch_oauth2::Scope::ChannelReadRedemptions];
const VERSION: &'static str = "1";
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "deny_unknown_fields", serde(deny_unknown_fields))]
#[non_exhaustive]
pub struct ChannelPointsCustomRewardUpdateV1Payload {
pub background_color: String,
pub broadcaster_user_id: types::UserId,
pub broadcaster_user_login: types::UserName,
pub broadcaster_user_name: types::DisplayName,
pub cooldown_expires_at: Option<types::Timestamp>,
pub cost: i64,
pub default_image: Option<types::Image>,
pub global_cooldown: types::GlobalCooldown,
pub id: types::RewardId,
pub image: Option<types::Image>,
pub is_enabled: bool,
pub is_in_stock: bool,
pub is_paused: bool,
pub is_user_input_required: bool,
pub max_per_stream: types::Max,
pub max_per_user_per_stream: types::Max,
pub prompt: String,
pub redemptions_redeemed_current_stream: Option<u32>,
pub should_redemptions_skip_request_queue: bool,
pub title: String,
}
#[cfg(test)]
#[test]
fn parse_payload() {
let payload = r##"
{
"subscription": {
"id": "f1c2a387-161a-49f9-a165-0f21d7a4e1c4",
"type": "channel.channel_points_custom_reward.update",
"version": "1",
"status": "enabled",
"cost": 0,
"condition": {
"broadcaster_user_id": "1337"
},
"transport": {
"method": "webhook",
"callback": "https://example.com/webhooks/callback"
},
"created_at": "2019-11-16T10:11:12.123Z"
},
"event": {
"id": "9001",
"broadcaster_user_id": "1337",
"broadcaster_user_login": "cool_user",
"broadcaster_user_name": "Cool_User",
"is_enabled": true,
"is_paused": false,
"is_in_stock": true,
"title": "Cool Reward",
"cost": 100,
"prompt": "reward prompt",
"is_user_input_required": true,
"should_redemptions_skip_request_queue": false,
"cooldown_expires_at": "2019-11-16T10:11:12.123Z",
"redemptions_redeemed_current_stream": 123,
"max_per_stream": {
"is_enabled": true,
"value": 1000
},
"max_per_user_per_stream": {
"is_enabled": true,
"value": 1000
},
"global_cooldown": {
"is_enabled": true,
"seconds": 1000
},
"background_color": "#FA1ED2",
"image": {
"url_1x": "https://static-cdn.jtvnw.net/image-1.png",
"url_2x": "https://static-cdn.jtvnw.net/image-2.png",
"url_4x": "https://static-cdn.jtvnw.net/image-4.png"
},
"default_image": {
"url_1x": "https://static-cdn.jtvnw.net/default-1.png",
"url_2x": "https://static-cdn.jtvnw.net/default-2.png",
"url_4x": "https://static-cdn.jtvnw.net/default-4.png"
}
}
}
"##;
let val = dbg!(crate::eventsub::Event::parse(payload).unwrap());
crate::tests::roundtrip(&val)
}