twitch_api/eventsub/channel/shoutout/
create.rs

1#![doc(alias = "channel.shoutout.create")]
2//! A specified broadcaster sends a Shoutout.
3
4use super::*;
5/// [`channel.shoutout.create`](https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types/#channelshoutoutcreate): a Prediction begins on the specified channel
6#[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 ChannelShoutoutCreateV1 {
11    /// The ID of the broadcaster that you want to receive notifications about when they send a Shoutout.
12    #[cfg_attr(feature = "typed-builder", builder(setter(into)))]
13    pub broadcaster_user_id: types::UserId,
14    /// The ID of the broadcaster that gave the Shoutout or one of the broadcaster’s moderators.
15    #[cfg_attr(feature = "typed-builder", builder(setter(into)))]
16    pub moderator_user_id: types::UserId,
17}
18
19impl ChannelShoutoutCreateV1 {
20    /// Create a new [`ChannelShoutoutCreateV1`]
21    pub fn new(
22        broadcaster_user_id: impl Into<types::UserId>,
23        moderator_user_id: impl Into<types::UserId>,
24    ) -> Self {
25        Self {
26            broadcaster_user_id: broadcaster_user_id.into(),
27            moderator_user_id: moderator_user_id.into(),
28        }
29    }
30}
31
32impl EventSubscription for ChannelShoutoutCreateV1 {
33    type Payload = ChannelShoutoutCreateV1Payload;
34
35    const EVENT_TYPE: EventType = EventType::ChannelShoutoutCreate;
36    #[cfg(feature = "twitch_oauth2")]
37    const SCOPE: twitch_oauth2::Validator = twitch_oauth2::validator![any(
38        twitch_oauth2::Scope::ModeratorReadShoutouts,
39        twitch_oauth2::Scope::ModeratorManageShoutouts
40    )];
41    const VERSION: &'static str = "1";
42}
43
44/// [`channel.shoutout.create`](ChannelShoutoutCreateV1) response payload.
45#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
46#[cfg_attr(feature = "deny_unknown_fields", serde(deny_unknown_fields))]
47#[non_exhaustive]
48pub struct ChannelShoutoutCreateV1Payload {
49    /// An ID that identifies the broadcaster that sent the Shoutout.
50    pub broadcaster_user_id: types::UserId,
51    /// The broadcaster’s login name.
52    pub broadcaster_user_login: types::UserName,
53    /// The broadcaster’s display name.
54    pub broadcaster_user_name: types::DisplayName,
55    /// An ID that identifies the broadcaster that received the Shoutout.
56    pub to_broadcaster_user_id: types::UserId,
57    /// The broadcaster’s login name.
58    pub to_broadcaster_user_login: types::UserName,
59    /// The broadcaster’s display name.
60    pub to_broadcaster_user_name: types::DisplayName,
61    /// An ID that identifies the moderator that sent the Shoutout. If the broadcaster sent the Shoutout, this ID is the same as the ID in [`broadcaster_user_id`](Self::broadcaster_user_id).
62    pub moderator_user_id: types::UserId,
63    /// The moderator’s login name.
64    pub moderator_user_login: types::UserName,
65    /// The moderator’s display name.
66    pub moderator_user_name: types::DisplayName,
67    /// The number of users that were watching the broadcaster’s stream at the time of the Shoutout.
68    pub viewer_count: i64,
69    /// The UTC timestamp (in RFC3339 format) of when the moderator sent the Shoutout.
70    pub started_at: types::Timestamp,
71    /// The UTC timestamp (in RFC3339 format) of when the broadcaster may send a Shoutout to a different broadcaster.
72    pub cooldown_ends_at: types::Timestamp,
73    /// The UTC timestamp (in RFC3339 format) of when the broadcaster may send another Shoutout to the broadcaster in [`to_broadcaster_user_id`](Self::to_broadcaster_user_id).
74    pub target_cooldown_ends_at: types::Timestamp,
75}
76
77#[cfg(test)]
78#[test]
79fn parse_payload() {
80    let payload = r##"
81    {
82        "subscription": {
83          "id": "f1c2a387-161a-49f9-a165-0f21d7a4e1c4",
84          "type": "channel.shoutout.create",
85          "version": "1",
86          "status": "enabled",
87          "cost": 0,
88          "condition": {
89            "broadcaster_user_id": "12345",
90            "moderator_user_id": "98765"
91          },
92          "transport": {
93            "method": "webhook",
94            "callback": "https://example.com/webhooks/callback"
95          },
96          "created_at": "2022-07-25T10:11:12.1236739Z"
97        },
98        "event": {
99          "broadcaster_user_id": "12345",
100          "broadcaster_user_name": "SimplySimple",
101          "broadcaster_user_login": "simplysimple",
102          "moderator_user_id": "98765",
103          "moderator_user_name": "ParticularlyParticular123",
104          "moderator_user_login": "particularlyparticular123",
105          "to_broadcaster_user_id": "626262",
106          "to_broadcaster_user_name": "SandySanderman",
107          "to_broadcaster_user_login": "sandysanderman",
108          "started_at": "2022-07-26T17:00:03.17106713Z",
109          "viewer_count": 860,
110          "cooldown_ends_at": "2022-07-26T17:02:03.17106713Z",
111          "target_cooldown_ends_at":"2022-07-26T18:00:03.17106713Z"
112        }
113      }
114    "##;
115
116    let val = dbg!(crate::eventsub::Event::parse(payload).unwrap());
117    crate::tests::roundtrip(&val)
118}