1#![doc(alias = "bits")]
2#![doc(alias = "channel-bits-events-v2")]
3use crate::{pubsub, types};
5use serde_derive::{Deserialize, Serialize};
6
7#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)]
9#[serde(into = "String", try_from = "String")]
10pub struct ChannelBitsEventsV2 {
11 pub channel_id: u32,
13}
14
15impl_de_ser!(ChannelBitsEventsV2, "channel-bits-events-v2", channel_id);
16
17impl pubsub::Topic for ChannelBitsEventsV2 {
18 #[cfg(feature = "twitch_oauth2")]
19 const SCOPE: twitch_oauth2::Validator =
20 twitch_oauth2::validator![twitch_oauth2::Scope::BitsRead];
21
22 fn into_topic(self) -> pubsub::Topics { super::Topics::ChannelBitsEventsV2(self) }
23}
24
25#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
27#[cfg_attr(feature = "deny_unknown_fields", serde(deny_unknown_fields))]
28#[serde(tag = "message_type")]
29#[non_exhaustive]
30pub enum ChannelBitsEventsV2Reply {
31 #[serde(rename = "bits_event")]
33 BitsEvent {
34 data: BitsEventData,
36 message_id: String,
38 version: String,
40 #[doc(hidden)]
41 #[serde(default)] is_anonymous: bool,
43 },
44}
45
46#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
48#[cfg_attr(feature = "deny_unknown_fields", serde(deny_unknown_fields))]
49#[non_exhaustive]
50pub struct BitsEventData {
51 pub badge_entitlement: Option<BadgeEntitlement>,
53 pub bits_used: i64,
55 pub channel_id: types::UserId,
57 pub channel_name: types::UserName,
59 pub chat_message: String,
61 pub context: BitsContext,
63 #[serde(default)] pub is_anonymous: bool,
66 pub time: types::Timestamp,
68 pub total_bits_used: i64,
70 pub user_id: types::UserId,
72 pub user_name: types::UserName,
74}
75
76#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
78#[cfg_attr(feature = "deny_unknown_fields", serde(deny_unknown_fields))]
79#[non_exhaustive]
80pub struct BadgeEntitlement {
81 new_version: u64,
83 previous_version: u64,
85}
86
87#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
89#[non_exhaustive]
90pub enum BitsContext {
91 #[serde(rename = "cheer")]
93 Cheer,
94}
95
96#[cfg(test)]
97mod tests {
98 use super::super::{Response, TopicData};
99 use super::*;
100 #[test]
101 fn bits_event() {
102 let source = r#"
103{
104 "type": "MESSAGE",
105 "data": {
106 "topic": "channel-bits-events-v2.1234",
107 "message": "{\"data\":{\"user_name\":\"justintv\",\"channel_name\":\"tmi\",\"user_id\":\"12345\",\"channel_id\":\"1234\",\"time\":\"2020-10-19T17:50:24.807841596Z\",\"chat_message\":\"Corgo1 Corgo1 Corgo1 Corgo1 Corgo1\",\"bits_used\":5,\"total_bits_used\":29,\"is_anonymous\":false,\"context\":\"cheer\",\"badge_entitlement\":null},\"version\":\"1.0\",\"message_type\":\"bits_event\",\"message_id\":\"d1831817-95f2-5dfa-8864-f36f16eeb5d8\"}"
108 }
109}"#;
110 let actual = dbg!(Response::parse(source).unwrap());
111 assert!(matches!(
112 actual,
113 Response::Message {
114 data: TopicData::ChannelBitsEventsV2 { .. },
115 }
116 ));
117 }
118
119 #[test]
120 fn bits_event_documented() {
121 let source = r#"
122{
123 "type": "MESSAGE",
124 "data": {
125 "topic": "channel-bits-events-v2.46024993",
126 "message": "{\"data\":{\"user_name\":\"jwp\",\"channel_name\":\"bontakun\",\"user_id\":\"95546976\",\"channel_id\":\"46024993\",\"time\":\"2017-02-09T13:23:58.168Z\",\"chat_message\":\"cheer10000 New badge hype!\",\"bits_used\":10000,\"total_bits_used\":25000,\"context\":\"cheer\",\"badge_entitlement\":{\"new_version\":25000,\"previous_version\":10000}},\"version\":\"1.0\",\"message_type\":\"bits_event\",\"message_id\":\"8145728a4-35f0-4cf7-9dc0-f2ef24de1eb6\",\"is_anonymous\":true}"
127 }
128}
129"#;
130
131 let actual = dbg!(Response::parse(source).unwrap());
132 assert!(matches!(
133 actual,
134 Response::Message {
135 data: TopicData::ChannelBitsEventsV2 { .. },
136 }
137 ));
138 }
139 #[test]
140 fn check_deser() {
141 use std::convert::TryInto as _;
142 let s = "channel-bits-events-v2.1234";
143 assert_eq!(
144 ChannelBitsEventsV2 { channel_id: 1234 },
145 s.to_string().try_into().unwrap()
146 );
147 }
148
149 #[test]
150 fn check_ser() {
151 let s = "channel-bits-events-v2.1234";
152 let right: String = ChannelBitsEventsV2 { channel_id: 1234 }.into();
153 assert_eq!(s.to_string(), right);
154 }
155}