Skip to content

Commit a8e86ec

Browse files
committed
Added support for eventsub triggeopics chann channel.shoutout.create and channel.shoutout.receive
1 parent 05945ee commit a8e86ec

File tree

4 files changed

+217
-0
lines changed

4 files changed

+217
-0
lines changed

internal/events/models.go

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ var triggerSupported = map[string]bool{
3535
"revoke": true,
3636
"shield-mode-begin": true,
3737
"shield-mode-end": true,
38+
"shoutout-create": true,
39+
"shoutout-received": true,
3840
"stream-change": true,
3941
"streamdown": true,
4042
"streamup": true,
+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package shoutout
4+
5+
import (
6+
"encoding/json"
7+
"strings"
8+
"time"
9+
10+
"github.com/twitchdev/twitch-cli/internal/events"
11+
"github.com/twitchdev/twitch-cli/internal/models"
12+
"github.com/twitchdev/twitch-cli/internal/util"
13+
)
14+
15+
var transportsSupported = map[string]bool{
16+
models.TransportEventSub: true,
17+
}
18+
var triggers = []string{"shoutout-create", "shoutout-received"}
19+
20+
var triggerMapping = map[string]map[string]string{
21+
models.TransportEventSub: {
22+
"shoutout-create": "channel.shoutout.create",
23+
"shoutout-received": "channel.shoutout.receive",
24+
},
25+
}
26+
27+
type Event struct{}
28+
29+
func (e Event) GenerateEvent(params events.MockEventParameters) (events.MockEventResponse, error) {
30+
var event []byte
31+
var err error
32+
33+
switch params.Transport {
34+
case models.TransportEventSub:
35+
viewerCount := util.RandomInt(2000)
36+
startedAt := util.GetTimestamp()
37+
38+
moderatorUserID := "3502151007"
39+
40+
if params.Trigger == "shoutout-create" {
41+
body := models.ShoutoutCreateEventSubResponse{
42+
Subscription: models.EventsubSubscription{
43+
ID: params.ID,
44+
Status: params.SubscriptionStatus,
45+
Type: triggerMapping[params.Transport][params.Trigger],
46+
Version: e.SubscriptionVersion(),
47+
Condition: models.EventsubCondition{
48+
BroadcasterUserID: params.FromUserID,
49+
ModeratorUserID: moderatorUserID,
50+
},
51+
Transport: models.EventsubTransport{
52+
Method: "webhook",
53+
Callback: "null",
54+
},
55+
Cost: 0,
56+
CreatedAt: params.Timestamp,
57+
},
58+
Event: models.ShoutoutCreateEventSubEvent{
59+
BroadcasterUserID: params.FromUserID,
60+
BroadcasterUserName: params.FromUserName,
61+
BroadcasterUserLogin: params.FromUserName,
62+
ToBroadcasterUserID: params.ToUserID,
63+
ToBroadcasterUserName: params.ToUserName,
64+
ToBroadcasterUserLogin: params.ToUserName,
65+
ModeratorUserID: moderatorUserID,
66+
ModeratorUserName: "TrustedUser123",
67+
ModeratorUserLogin: "trusteduser123",
68+
ViewerCount: int(viewerCount),
69+
StartedAt: startedAt.Format(time.RFC3339Nano),
70+
CooldownEndsAt: startedAt.Add(2 * time.Minute).Format(time.RFC3339Nano),
71+
TargetCooldownEndsAt: startedAt.Add(1 * time.Hour).Format(time.RFC3339Nano),
72+
},
73+
}
74+
75+
event, err = json.Marshal(body)
76+
if err != nil {
77+
return events.MockEventResponse{}, err
78+
}
79+
} else if params.Trigger == "shoutout-received" {
80+
body := models.ShoutoutReceivedEventSubResponse{
81+
Subscription: models.EventsubSubscription{
82+
ID: params.ID,
83+
Status: params.SubscriptionStatus,
84+
Type: triggerMapping[params.Transport][params.Trigger],
85+
Version: e.SubscriptionVersion(),
86+
Condition: models.EventsubCondition{
87+
BroadcasterUserID: params.ToUserID,
88+
ModeratorUserID: moderatorUserID,
89+
},
90+
Transport: models.EventsubTransport{
91+
Method: "webhook",
92+
Callback: "null",
93+
},
94+
Cost: 0,
95+
CreatedAt: params.Timestamp,
96+
},
97+
Event: models.ShoutoutReceivedEventSubEvent{
98+
BroadcasterUserID: params.ToUserID,
99+
BroadcasterUserName: params.ToUserName,
100+
BroadcasterUserLogin: params.ToUserName,
101+
FromBroadcasterUserID: params.FromUserID,
102+
FromBroadcasterUserName: params.FromUserName,
103+
FromBroadcasterUserLogin: params.FromUserName,
104+
ViewerCount: int(viewerCount),
105+
StartedAt: startedAt.Format(time.RFC3339Nano),
106+
},
107+
}
108+
109+
event, err = json.Marshal(body)
110+
if err != nil {
111+
return events.MockEventResponse{}, err
112+
}
113+
}
114+
115+
// Delete event info if Subscription.Status is not set to "enabled"
116+
if !strings.EqualFold(params.SubscriptionStatus, "enabled") {
117+
var i interface{}
118+
if err := json.Unmarshal([]byte(event), &i); err != nil {
119+
return events.MockEventResponse{}, err
120+
}
121+
if m, ok := i.(map[string]interface{}); ok {
122+
delete(m, "event") // Matches JSON key defined in body variable above
123+
}
124+
125+
event, err = json.Marshal(i)
126+
if err != nil {
127+
return events.MockEventResponse{}, err
128+
}
129+
}
130+
default:
131+
return events.MockEventResponse{}, nil
132+
}
133+
134+
return events.MockEventResponse{
135+
ID: params.ID,
136+
JSON: event,
137+
ToUser: params.ToUserID,
138+
FromUser: params.FromUserID,
139+
}, nil
140+
}
141+
142+
func (e Event) ValidTransport(transport string) bool {
143+
return transportsSupported[transport]
144+
}
145+
146+
func (e Event) ValidTrigger(trigger string) bool {
147+
for _, t := range triggers {
148+
if t == trigger {
149+
return true
150+
}
151+
}
152+
return false
153+
}
154+
func (e Event) GetTopic(transport string, trigger string) string {
155+
return triggerMapping[transport][trigger]
156+
}
157+
func (e Event) GetEventSubAlias(t string) string {
158+
// check for aliases
159+
for trigger, topic := range triggerMapping[models.TransportEventSub] {
160+
if topic == t {
161+
return trigger
162+
}
163+
}
164+
return ""
165+
}
166+
167+
func (e Event) SubscriptionVersion() string {
168+
return "beta"
169+
}

internal/events/types/types.go

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/twitchdev/twitch-cli/internal/events/types/prediction"
2424
"github.com/twitchdev/twitch-cli/internal/events/types/raid"
2525
"github.com/twitchdev/twitch-cli/internal/events/types/shield_mode"
26+
"github.com/twitchdev/twitch-cli/internal/events/types/shoutout"
2627
"github.com/twitchdev/twitch-cli/internal/events/types/stream_change"
2728
"github.com/twitchdev/twitch-cli/internal/events/types/streamdown"
2829
"github.com/twitchdev/twitch-cli/internal/events/types/streamup"
@@ -51,6 +52,7 @@ func All() []events.MockEvent {
5152
prediction.Event{},
5253
raid.Event{},
5354
shield_mode.Event{},
55+
shoutout.Event{},
5456
stream_change.Event{},
5557
streamup.Event{},
5658
streamdown.Event{},

internal/models/shoutout.go

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package models
4+
5+
// channel.shoutout.create
6+
7+
type ShoutoutCreateEventSubResponse struct {
8+
Subscription EventsubSubscription `json:"subscription"`
9+
Event ShoutoutCreateEventSubEvent `json:"event"`
10+
}
11+
12+
type ShoutoutCreateEventSubEvent struct {
13+
BroadcasterUserID string `json:"broadcaster_user_id"`
14+
BroadcasterUserName string `json:"broadcaster_user_name"`
15+
BroadcasterUserLogin string `json:"broadcaster_user_login"`
16+
ToBroadcasterUserID string `json:"to_broadcaster_user_id"`
17+
ToBroadcasterUserName string `json:"to_broadcaster_user_name"`
18+
ToBroadcasterUserLogin string `json:"to_broadcaster_user_login"`
19+
ModeratorUserID string `json:"moderator_user_id"`
20+
ModeratorUserName string `json:"moderator_user_name"`
21+
ModeratorUserLogin string `json:"moderator_user_login"`
22+
ViewerCount int `json:"viewer_count"`
23+
StartedAt string `json:"started_at"`
24+
CooldownEndsAt string `json:"cooldown_ends_at"`
25+
TargetCooldownEndsAt string `json:"target_cooldown_ends_at"`
26+
}
27+
28+
// channel.shoutout.receive
29+
30+
type ShoutoutReceivedEventSubResponse struct {
31+
Subscription EventsubSubscription `json:"subscription"`
32+
Event ShoutoutReceivedEventSubEvent `json:"event"`
33+
}
34+
35+
type ShoutoutReceivedEventSubEvent struct {
36+
BroadcasterUserID string `json:"broadcaster_user_id"`
37+
BroadcasterUserName string `json:"broadcaster_user_name"`
38+
BroadcasterUserLogin string `json:"broadcaster_user_login"`
39+
FromBroadcasterUserID string `json:"from_broadcaster_user_id"`
40+
FromBroadcasterUserName string `json:"from_broadcaster_user_name"`
41+
FromBroadcasterUserLogin string `json:"from_broadcaster_user_login"`
42+
ViewerCount int `json:"viewer_count"`
43+
StartedAt string `json:"started_at"`
44+
}

0 commit comments

Comments
 (0)