twitch_api/eventsub/channel/chat/
user_message_update.rs1#![doc(alias = "channel.chat.user_message_update")]
2use super::*;
5#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
7#[cfg_attr(feature = "typed-builder", derive(typed_builder::TypedBuilder))]
8#[cfg_attr(feature = "deny_unknown_fields", serde(deny_unknown_fields))]
9#[non_exhaustive]
10pub struct ChannelChatUserMessageUpdateV1 {
11 #[cfg_attr(feature = "typed-builder", builder(setter(into)))]
13 pub broadcaster_user_id: types::UserId,
14 #[cfg_attr(feature = "typed-builder", builder(setter(into)))]
16 pub user_id: types::UserId,
17}
18
19impl ChannelChatUserMessageUpdateV1 {
20 pub fn new(
22 broadcaster_user_id: impl Into<types::UserId>,
23 user_id: impl Into<types::UserId>,
24 ) -> Self {
25 Self {
26 broadcaster_user_id: broadcaster_user_id.into(),
27 user_id: user_id.into(),
28 }
29 }
30}
31
32impl EventSubscription for ChannelChatUserMessageUpdateV1 {
33 type Payload = ChannelChatUserMessageUpdateV1Payload;
34
35 const EVENT_TYPE: EventType = EventType::ChannelChatUserMessageUpdate;
36 #[cfg(feature = "twitch_oauth2")]
37 const SCOPE: twitch_oauth2::Validator =
38 twitch_oauth2::validator![twitch_oauth2::Scope::UserReadChat];
39 const VERSION: &'static str = "1";
40}
41
42#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
44#[cfg_attr(feature = "deny_unknown_fields", serde(deny_unknown_fields))]
45#[non_exhaustive]
46pub struct ChannelChatUserMessageUpdateV1Payload {
47 pub broadcaster_user_id: types::UserId,
49 pub broadcaster_user_login: types::UserName,
51 pub broadcaster_user_name: types::DisplayName,
53 pub user_id: types::UserId,
55 pub user_login: types::UserName,
57 pub user_name: types::DisplayName,
59 pub status: crate::eventsub::automod::message::AutomodMessageStatus,
61 pub message_id: types::MsgId,
63 pub message: crate::eventsub::automod::message::AutomodMessage,
65}
66
67#[cfg(test)]
68#[test]
69fn parse_payload() {
70 use crate::eventsub::{Event, Message};
71
72 let payload = r##"
73 {
74 "subscription": {
75 "id": "f1c2a387-161a-49f9-a165-0f21d7a4e1c4",
76 "type": "channel.chat.user_message_update",
77 "version": "1",
78 "status": "enabled",
79 "cost": 0,
80 "condition": {
81 "broadcaster_user_id": "1337",
82 "user_id": "9001"
83 },
84 "transport": {
85 "method": "webhook",
86 "callback": "https://example.com/webhooks/callback"
87 },
88 "created_at": "2023-04-11T10:11:12.123Z"
89 },
90 "event": {
91 "broadcaster_user_id": "123",
92 "broadcaster_user_login": "bob",
93 "broadcaster_user_name": "Bob",
94 "user_id": "456",
95 "user_login": "tom",
96 "user_name": "Tommy",
97 "status": "approved",
98 "message_id": "789",
99 "message": {
100 "text": "hey world",
101 "fragments": [
102 {
103 "type": "emote",
104 "text": "hey world",
105 "cheermote": null,
106 "emote": {
107 "id": "foo",
108 "emote_set_id": "7"
109 }
110 },
111 {
112 "type": "cheermote",
113 "text": "bye world",
114 "cheermote": {
115 "prefix": "prefix",
116 "bits": 100,
117 "tier": 1
118 },
119 "emote": null
120 },
121 {
122 "type": "text",
123 "text": "surprise",
124 "cheermote": null,
125 "emote": null
126 }
127 ]
128 }
129 }
130 }
131 "##;
132
133 let val = Event::parse(payload).unwrap();
134 crate::tests::roundtrip(&val);
135
136 let Event::ChannelChatUserMessageUpdateV1(val) = val else {
137 panic!("invalid event type");
138 };
139 let Message::Notification(notif) = val.message else {
140 panic!("invalid message type");
141 };
142
143 assert_eq!(notif.broadcaster_user_id.as_str(), "123");
144 assert_eq!(notif.user_id.as_str(), "456");
145 assert_eq!(
146 notif.status,
147 crate::eventsub::automod::message::AutomodMessageStatus::Approved
148 );
149 assert_eq!(notif.message_id.as_str(), "789");
150 assert_eq!(notif.message.text, "hey world");
151}