diff --git a/internal/events/models.go b/internal/events/models.go index 5433af16..c43ae867 100644 --- a/internal/events/models.go +++ b/internal/events/models.go @@ -7,6 +7,10 @@ var triggerSupported = map[string]bool{ "add-redemption": true, "add-reward": true, "ban": true, + "charity-donate": true, + "charity-progress": true, + "charity-start": true, + "charity-stop": true, "cheer": true, "drop": true, "follow": true, @@ -29,6 +33,8 @@ var triggerSupported = map[string]bool{ "remove-moderator": true, "remove-reward": true, "revoke": true, + "shield-mode-begin": true, + "shield-mode-end": true, "stream-change": true, "streamdown": true, "streamup": true, diff --git a/internal/events/types/shield_mode/shield_mode.go b/internal/events/types/shield_mode/shield_mode.go new file mode 100644 index 00000000..4b86e438 --- /dev/null +++ b/internal/events/types/shield_mode/shield_mode.go @@ -0,0 +1,129 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package shield_mode + +import ( + "encoding/json" + "strings" + "time" + + "github.com/twitchdev/twitch-cli/internal/events" + "github.com/twitchdev/twitch-cli/internal/models" + "github.com/twitchdev/twitch-cli/internal/util" +) + +var transportsSupported = map[string]bool{ + models.TransportEventSub: true, +} +var triggers = []string{"shield-mode-begin", "shield-mode-end"} + +var triggerMapping = map[string]map[string]string{ + models.TransportEventSub: { + "shield-mode-begin": "channel.shield_mode.begin", + "shield-mode-end": "channel.shield_mode.end", + }, +} + +type Event struct{} + +func (e Event) GenerateEvent(params events.MockEventParameters) (events.MockEventResponse, error) { + var event []byte + var err error + + switch params.Transport { + case models.TransportEventSub: + eventBody := models.ShieldModeEventSubEvent{ + BroadcasterUserID: params.ToUserID, + BroadcasterUserName: params.ToUserName, + BroadcasterUserLogin: params.ToUserName, + ModeratorUserID: params.FromUserID, + ModeratorUserName: params.FromUserName, + ModeratorUserLogin: params.FromUserName, + } + + if params.Trigger == "shield-mode-begin" { + eventBody.StartedAt = util.GetTimestamp().Add(-10 * time.Minute).Format(time.RFC3339Nano) + } else if params.Trigger == "shield-mode-end" { + eventBody.EndedAt = util.GetTimestamp().Format(time.RFC3339Nano) + } + + body := models.ShieldModeEventSubResponse{ + Subscription: models.EventsubSubscription{ + ID: params.ID, + Status: params.SubscriptionStatus, + Type: triggerMapping[params.Transport][params.Trigger], + Version: e.SubscriptionVersion(), + Condition: models.EventsubCondition{ + BroadcasterUserID: params.ToUserID, + ModeratorUserID: params.FromUserID, + }, + Transport: models.EventsubTransport{ + Method: "webhook", + Callback: "null", + }, + Cost: 0, + CreatedAt: params.Timestamp, + }, + Event: eventBody, + } + + event, err = json.Marshal(body) + if err != nil { + return events.MockEventResponse{}, err + } + + // Delete event info if Subscription.Status is not set to "enabled" + if !strings.EqualFold(params.SubscriptionStatus, "enabled") { + var i interface{} + if err := json.Unmarshal([]byte(event), &i); err != nil { + return events.MockEventResponse{}, err + } + if m, ok := i.(map[string]interface{}); ok { + delete(m, "event") // Matches JSON key defined in body variable above + } + + event, err = json.Marshal(i) + if err != nil { + return events.MockEventResponse{}, err + } + } + default: + return events.MockEventResponse{}, nil + } + + return events.MockEventResponse{ + ID: params.ID, + JSON: event, + ToUser: params.ToUserID, + FromUser: params.FromUserID, + }, nil +} + +func (e Event) ValidTransport(transport string) bool { + return transportsSupported[transport] +} + +func (e Event) ValidTrigger(trigger string) bool { + for _, t := range triggers { + if t == trigger { + return true + } + } + return false +} +func (e Event) GetTopic(transport string, trigger string) string { + return triggerMapping[transport][trigger] +} +func (e Event) GetEventSubAlias(t string) string { + // check for aliases + for trigger, topic := range triggerMapping[models.TransportEventSub] { + if topic == t { + return trigger + } + } + return "" +} + +func (e Event) SubscriptionVersion() string { + return "beta" +} diff --git a/internal/events/types/shield_mode/shield_mode_test.go b/internal/events/types/shield_mode/shield_mode_test.go new file mode 100644 index 00000000..1b33435e --- /dev/null +++ b/internal/events/types/shield_mode/shield_mode_test.go @@ -0,0 +1,106 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package shield_mode + +import ( + "encoding/json" + "testing" + + "github.com/twitchdev/twitch-cli/internal/events" + "github.com/twitchdev/twitch-cli/internal/models" + "github.com/twitchdev/twitch-cli/test_setup" +) + +var fromUser = "1234" +var toUser = "4567" + +func TestEventSub(t *testing.T) { + a := test_setup.SetupTestEnv(t) + + beginParams := *&events.MockEventParameters{ + FromUserID: fromUser, + ToUserID: toUser, + Transport: models.TransportEventSub, + Trigger: "shield-mode-begin", + SubscriptionStatus: "enabled", + Cost: 0, + } + endParams := *&events.MockEventParameters{ + FromUserID: fromUser, + ToUserID: toUser, + Transport: models.TransportEventSub, + Trigger: "shield-mode-end", + SubscriptionStatus: "enabled", + Cost: 0, + } + + r1, err := Event{}.GenerateEvent(beginParams) + a.Nil(err) + + r2, err := Event{}.GenerateEvent(endParams) + a.Nil(err) + + var body models.ShieldModeEventSubResponse + err = json.Unmarshal(r1.JSON, &body) + a.Nil(err) + + err = json.Unmarshal(r2.JSON, &body) + a.Nil(err) +} + +func TestFakeTransport(t *testing.T) { + a := test_setup.SetupTestEnv(t) + + beginParams := *&events.MockEventParameters{ + FromUserID: fromUser, + ToUserID: toUser, + Transport: "fake_transport", + Trigger: "shield-mode-begin", + SubscriptionStatus: "enabled", + } + endParams := *&events.MockEventParameters{ + FromUserID: fromUser, + ToUserID: toUser, + Transport: "fake_transport", + Trigger: "shield-mode-end", + SubscriptionStatus: "enabled", + } + + r1, err1 := Event{}.GenerateEvent(beginParams) + r2, err2 := Event{}.GenerateEvent(endParams) + a.Nil(err1) + a.Nil(err2) + a.Empty(r1) + a.Empty(r2) +} +func TestValidTrigger(t *testing.T) { + a := test_setup.SetupTestEnv(t) + + r := Event{}.ValidTrigger("shield-mode-begin") + a.Equal(true, r) + + r = Event{}.ValidTrigger("shield-mode-end") + a.Equal(true, r) + + r = Event{}.ValidTrigger("notshield") + a.Equal(false, r) +} + +func TestValidTransport(t *testing.T) { + a := test_setup.SetupTestEnv(t) + + r := Event{}.ValidTransport(models.TransportEventSub) + a.Equal(true, r) + + r = Event{}.ValidTransport("noteventsub") + a.Equal(false, r) +} +func TestGetTopic(t *testing.T) { + a := test_setup.SetupTestEnv(t) + + r := Event{}.GetTopic(models.TransportEventSub, "shield-mode-begin") + a.NotNil(r) + + r = Event{}.GetTopic(models.TransportEventSub, "shield-mode-end") + a.NotNil(r) +} diff --git a/internal/events/types/types.go b/internal/events/types/types.go index 0446a9a0..0d7642b8 100644 --- a/internal/events/types/types.go +++ b/internal/events/types/types.go @@ -22,6 +22,7 @@ import ( "github.com/twitchdev/twitch-cli/internal/events/types/poll" "github.com/twitchdev/twitch-cli/internal/events/types/prediction" "github.com/twitchdev/twitch-cli/internal/events/types/raid" + "github.com/twitchdev/twitch-cli/internal/events/types/shield_mode" "github.com/twitchdev/twitch-cli/internal/events/types/stream_change" "github.com/twitchdev/twitch-cli/internal/events/types/streamdown" "github.com/twitchdev/twitch-cli/internal/events/types/streamup" @@ -49,6 +50,7 @@ func All() []events.MockEvent { poll.Event{}, prediction.Event{}, raid.Event{}, + shield_mode.Event{}, stream_change.Event{}, streamup.Event{}, streamdown.Event{}, diff --git a/internal/models/eventsub.go b/internal/models/eventsub.go index 9b5bead0..4c3c3f95 100644 --- a/internal/models/eventsub.go +++ b/internal/models/eventsub.go @@ -23,6 +23,7 @@ type EventsubCondition struct { ToBroadcasterUserID string `json:"to_broadcaster_user_id,omitempty"` UserID string `json:"user_id,omitempty"` FromBroadcasterUserID string `json:"from_broadcaster_user_id,omitempty"` + ModeratorUserID string `json:"moderator_user_id,omitempty"` ClientID string `json:"client_id,omitempty"` ExtensionClientID string `json:"extension_client_id,omitempty"` OrganizationID string `json:"organization_id,omitempty"` diff --git a/internal/models/shield_mode.go b/internal/models/shield_mode.go new file mode 100644 index 00000000..76d6fa5d --- /dev/null +++ b/internal/models/shield_mode.go @@ -0,0 +1,19 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package models + +type ShieldModeEventSubResponse struct { + Subscription EventsubSubscription `json:"subscription"` + Event ShieldModeEventSubEvent `json:"event"` +} + +type ShieldModeEventSubEvent struct { + BroadcasterUserID string `json:"broadcaster_user_id"` + BroadcasterUserName string `json:"broadcaster_user_name"` + BroadcasterUserLogin string `json:"broadcaster_user_login"` + ModeratorUserID string `json:"moderator_user_id"` + ModeratorUserName string `json:"moderator_user_name"` + ModeratorUserLogin string `json:"moderator_user_login"` + StartedAt string `json:"started_at,omitempty"` + EndedAt string `json:"ended_at,omitempty"` +}