Skip to content

Commit 05945ee

Browse files
authored
Merge pull request #205 from twitchdev/eventsub-shield-mode
Added support for eventsub triggers channel.shield_mode.begin and channel.shield_mode.end
2 parents d800dd6 + f9a652d commit 05945ee

File tree

7 files changed

+265
-0
lines changed

7 files changed

+265
-0
lines changed

internal/events/models.go

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ var triggerSupported = map[string]bool{
77
"add-redemption": true,
88
"add-reward": true,
99
"ban": true,
10+
"charity-donate": true,
11+
"charity-progress": true,
12+
"charity-start": true,
13+
"charity-stop": true,
1014
"cheer": true,
1115
"drop": true,
1216
"follow": true,
@@ -29,6 +33,8 @@ var triggerSupported = map[string]bool{
2933
"remove-moderator": true,
3034
"remove-reward": true,
3135
"revoke": true,
36+
"shield-mode-begin": true,
37+
"shield-mode-end": true,
3238
"stream-change": true,
3339
"streamdown": true,
3440
"streamup": true,

internal/events/types/charity/charity_event.go

+2
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,15 @@ func (e Event) GenerateEvent(params events.MockEventParameters) (events.MockEven
4343
var stopped_at *string
4444

4545
randomID := util.RandomGUID()
46+
randomID2 := util.RandomGUID()
4647
charityName := "Example Charity"
4748
charityLogo := "https://abc.cloudfront.net/ppgf/1000/100.png"
4849
charityDescription := "Example Description"
4950
charityWebsite := "https://www.example.com"
5051

5152
if params.Trigger == "charity-donate" {
5253
campaign_id = &randomID
54+
id = &randomID2
5355
user_id = &params.FromUserID
5456
user_login_name = &params.FromUserName
5557

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package shield_mode
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{"shield-mode-begin", "shield-mode-end"}
19+
20+
var triggerMapping = map[string]map[string]string{
21+
models.TransportEventSub: {
22+
"shield-mode-begin": "channel.shield_mode.begin",
23+
"shield-mode-end": "channel.shield_mode.end",
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+
eventBody := models.ShieldModeEventSubEvent{
36+
BroadcasterUserID: params.ToUserID,
37+
BroadcasterUserName: params.ToUserName,
38+
BroadcasterUserLogin: params.ToUserName,
39+
ModeratorUserID: params.FromUserID,
40+
ModeratorUserName: params.FromUserName,
41+
ModeratorUserLogin: params.FromUserName,
42+
}
43+
44+
if params.Trigger == "shield-mode-begin" {
45+
eventBody.StartedAt = util.GetTimestamp().Add(-10 * time.Minute).Format(time.RFC3339Nano)
46+
} else if params.Trigger == "shield-mode-end" {
47+
eventBody.EndedAt = util.GetTimestamp().Format(time.RFC3339Nano)
48+
}
49+
50+
body := models.ShieldModeEventSubResponse{
51+
Subscription: models.EventsubSubscription{
52+
ID: params.ID,
53+
Status: params.SubscriptionStatus,
54+
Type: triggerMapping[params.Transport][params.Trigger],
55+
Version: e.SubscriptionVersion(),
56+
Condition: models.EventsubCondition{
57+
BroadcasterUserID: params.ToUserID,
58+
ModeratorUserID: params.FromUserID,
59+
},
60+
Transport: models.EventsubTransport{
61+
Method: "webhook",
62+
Callback: "null",
63+
},
64+
Cost: 0,
65+
CreatedAt: params.Timestamp,
66+
},
67+
Event: eventBody,
68+
}
69+
70+
event, err = json.Marshal(body)
71+
if err != nil {
72+
return events.MockEventResponse{}, err
73+
}
74+
75+
// Delete event info if Subscription.Status is not set to "enabled"
76+
if !strings.EqualFold(params.SubscriptionStatus, "enabled") {
77+
var i interface{}
78+
if err := json.Unmarshal([]byte(event), &i); err != nil {
79+
return events.MockEventResponse{}, err
80+
}
81+
if m, ok := i.(map[string]interface{}); ok {
82+
delete(m, "event") // Matches JSON key defined in body variable above
83+
}
84+
85+
event, err = json.Marshal(i)
86+
if err != nil {
87+
return events.MockEventResponse{}, err
88+
}
89+
}
90+
default:
91+
return events.MockEventResponse{}, nil
92+
}
93+
94+
return events.MockEventResponse{
95+
ID: params.ID,
96+
JSON: event,
97+
ToUser: params.ToUserID,
98+
FromUser: params.FromUserID,
99+
}, nil
100+
}
101+
102+
func (e Event) ValidTransport(transport string) bool {
103+
return transportsSupported[transport]
104+
}
105+
106+
func (e Event) ValidTrigger(trigger string) bool {
107+
for _, t := range triggers {
108+
if t == trigger {
109+
return true
110+
}
111+
}
112+
return false
113+
}
114+
func (e Event) GetTopic(transport string, trigger string) string {
115+
return triggerMapping[transport][trigger]
116+
}
117+
func (e Event) GetEventSubAlias(t string) string {
118+
// check for aliases
119+
for trigger, topic := range triggerMapping[models.TransportEventSub] {
120+
if topic == t {
121+
return trigger
122+
}
123+
}
124+
return ""
125+
}
126+
127+
func (e Event) SubscriptionVersion() string {
128+
return "1"
129+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package shield_mode
4+
5+
import (
6+
"encoding/json"
7+
"testing"
8+
9+
"github.com/twitchdev/twitch-cli/internal/events"
10+
"github.com/twitchdev/twitch-cli/internal/models"
11+
"github.com/twitchdev/twitch-cli/test_setup"
12+
)
13+
14+
var fromUser = "1234"
15+
var toUser = "4567"
16+
17+
func TestEventSub(t *testing.T) {
18+
a := test_setup.SetupTestEnv(t)
19+
20+
beginParams := *&events.MockEventParameters{
21+
FromUserID: fromUser,
22+
ToUserID: toUser,
23+
Transport: models.TransportEventSub,
24+
Trigger: "shield-mode-begin",
25+
SubscriptionStatus: "enabled",
26+
Cost: 0,
27+
}
28+
endParams := *&events.MockEventParameters{
29+
FromUserID: fromUser,
30+
ToUserID: toUser,
31+
Transport: models.TransportEventSub,
32+
Trigger: "shield-mode-end",
33+
SubscriptionStatus: "enabled",
34+
Cost: 0,
35+
}
36+
37+
r1, err := Event{}.GenerateEvent(beginParams)
38+
a.Nil(err)
39+
40+
r2, err := Event{}.GenerateEvent(endParams)
41+
a.Nil(err)
42+
43+
var body models.ShieldModeEventSubResponse
44+
err = json.Unmarshal(r1.JSON, &body)
45+
a.Nil(err)
46+
47+
err = json.Unmarshal(r2.JSON, &body)
48+
a.Nil(err)
49+
}
50+
51+
func TestFakeTransport(t *testing.T) {
52+
a := test_setup.SetupTestEnv(t)
53+
54+
beginParams := *&events.MockEventParameters{
55+
FromUserID: fromUser,
56+
ToUserID: toUser,
57+
Transport: "fake_transport",
58+
Trigger: "shield-mode-begin",
59+
SubscriptionStatus: "enabled",
60+
}
61+
endParams := *&events.MockEventParameters{
62+
FromUserID: fromUser,
63+
ToUserID: toUser,
64+
Transport: "fake_transport",
65+
Trigger: "shield-mode-end",
66+
SubscriptionStatus: "enabled",
67+
}
68+
69+
r1, err1 := Event{}.GenerateEvent(beginParams)
70+
r2, err2 := Event{}.GenerateEvent(endParams)
71+
a.Nil(err1)
72+
a.Nil(err2)
73+
a.Empty(r1)
74+
a.Empty(r2)
75+
}
76+
func TestValidTrigger(t *testing.T) {
77+
a := test_setup.SetupTestEnv(t)
78+
79+
r := Event{}.ValidTrigger("shield-mode-begin")
80+
a.Equal(true, r)
81+
82+
r = Event{}.ValidTrigger("shield-mode-end")
83+
a.Equal(true, r)
84+
85+
r = Event{}.ValidTrigger("notshield")
86+
a.Equal(false, r)
87+
}
88+
89+
func TestValidTransport(t *testing.T) {
90+
a := test_setup.SetupTestEnv(t)
91+
92+
r := Event{}.ValidTransport(models.TransportEventSub)
93+
a.Equal(true, r)
94+
95+
r = Event{}.ValidTransport("noteventsub")
96+
a.Equal(false, r)
97+
}
98+
func TestGetTopic(t *testing.T) {
99+
a := test_setup.SetupTestEnv(t)
100+
101+
r := Event{}.GetTopic(models.TransportEventSub, "shield-mode-begin")
102+
a.NotNil(r)
103+
104+
r = Event{}.GetTopic(models.TransportEventSub, "shield-mode-end")
105+
a.NotNil(r)
106+
}

internal/events/types/types.go

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/twitchdev/twitch-cli/internal/events/types/poll"
2323
"github.com/twitchdev/twitch-cli/internal/events/types/prediction"
2424
"github.com/twitchdev/twitch-cli/internal/events/types/raid"
25+
"github.com/twitchdev/twitch-cli/internal/events/types/shield_mode"
2526
"github.com/twitchdev/twitch-cli/internal/events/types/stream_change"
2627
"github.com/twitchdev/twitch-cli/internal/events/types/streamdown"
2728
"github.com/twitchdev/twitch-cli/internal/events/types/streamup"
@@ -49,6 +50,7 @@ func All() []events.MockEvent {
4950
poll.Event{},
5051
prediction.Event{},
5152
raid.Event{},
53+
shield_mode.Event{},
5254
stream_change.Event{},
5355
streamup.Event{},
5456
streamdown.Event{},

internal/models/eventsub.go

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type EventsubCondition struct {
2323
ToBroadcasterUserID string `json:"to_broadcaster_user_id,omitempty"`
2424
UserID string `json:"user_id,omitempty"`
2525
FromBroadcasterUserID string `json:"from_broadcaster_user_id,omitempty"`
26+
ModeratorUserID string `json:"moderator_user_id,omitempty"`
2627
ClientID string `json:"client_id,omitempty"`
2728
ExtensionClientID string `json:"extension_client_id,omitempty"`
2829
OrganizationID string `json:"organization_id,omitempty"`

internal/models/shield_mode.go

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package models
4+
5+
type ShieldModeEventSubResponse struct {
6+
Subscription EventsubSubscription `json:"subscription"`
7+
Event ShieldModeEventSubEvent `json:"event"`
8+
}
9+
10+
type ShieldModeEventSubEvent struct {
11+
BroadcasterUserID string `json:"broadcaster_user_id"`
12+
BroadcasterUserName string `json:"broadcaster_user_name"`
13+
BroadcasterUserLogin string `json:"broadcaster_user_login"`
14+
ModeratorUserID string `json:"moderator_user_id"`
15+
ModeratorUserName string `json:"moderator_user_name"`
16+
ModeratorUserLogin string `json:"moderator_user_login"`
17+
StartedAt string `json:"started_at,omitempty"`
18+
EndedAt string `json:"ended_at,omitempty"`
19+
}

0 commit comments

Comments
 (0)