Skip to content

Commit

Permalink
stream_change support addition
Browse files Browse the repository at this point in the history
Adding support for "stream_change" websub and eventsub.
  • Loading branch information
Braxton Lancial committed Mar 9, 2021
1 parent 89cc2bd commit e460762
Show file tree
Hide file tree
Showing 7 changed files with 287 additions and 0 deletions.
3 changes: 3 additions & 0 deletions cmd/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var (
itemID string
cost int64
count int
streamTitle string
)

var eventCmd = &cobra.Command{
Expand Down Expand Up @@ -83,6 +84,7 @@ func init() {
triggerCmd.Flags().StringVarP(&status, "status", "S", "", "Status of the event object, currently applies to channel points redemptions.")
triggerCmd.Flags().StringVarP(&itemID, "item-id", "i", "", "Manually set the ID of the event payload item (for example the reward ID in redemption events).")
triggerCmd.Flags().Int64VarP(&cost, "cost", "C", 0, "Amount of bits or channel points redeemed/used in the event.")
triggerCmd.Flags().StringVarP(&streamTitle, "description", "d", "", "Title the stream should be updated with.")

// retrigger flags
retriggerCmd.Flags().StringVarP(&forwardAddress, "forward-address", "F", "", "Forward address for mock event.")
Expand Down Expand Up @@ -125,6 +127,7 @@ func triggerCmdRun(cmd *cobra.Command, args []string) {
Status: status,
ItemID: itemID,
Cost: cost,
StreamTitle: streamTitle,
})

if err != nil {
Expand Down
1 change: 1 addition & 0 deletions internal/events/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type MockEventParameters struct {
Status string
ItemID string
Cost int64
StreamTitle string
}

type MockEventResponse struct {
Expand Down
2 changes: 2 additions & 0 deletions internal/events/trigger/trigger_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type TriggerParameters struct {
Secret string
Verbose bool
Count int
StreamTitle string
}

type TriggerResponse struct {
Expand Down Expand Up @@ -60,6 +61,7 @@ func Fire(p TriggerParameters) (string, error) {
IsAnonymous: p.IsAnonymous,
Cost: p.Cost,
Status: p.Status,
StreamTitle: p.StreamTitle,
}

e, err := types.GetByTriggerAndTransport(p.Event, p.Transport)
Expand Down
123 changes: 123 additions & 0 deletions internal/events/types/stream_change/stream_change_event.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package stream_change

import (
"encoding/json"

"github.com/twitchdev/twitch-cli/internal/events"
"github.com/twitchdev/twitch-cli/internal/models"
"github.com/twitchdev/twitch-cli/internal/util"
"time"
)

var transportsSupported = map[string]bool{
models.TransportWebSub: true,
models.TransportEventSub: true,
}

var triggerSupported = []string{"stream_change"}

var triggerMapping = map[string]map[string]string{
models.TransportWebSub: {
"stream_change": "streams",
},
models.TransportEventSub: {
"stream_change": "channel.update",
},
}

type Event struct{}

func (e Event) GenerateEvent(params events.MockEventParameters) (events.MockEventResponse, error) {
var event []byte
var err error

if params.StreamTitle == "" {
params.StreamTitle = "Default Title!"
}

switch params.Transport{
case models.TransportEventSub:
body := &models.EventsubResponse{
// make the eventsub response (if supported)
Subscription: models.EventsubSubscription{
ID: params.ID,
Status: "enabled",
Type: "channel.update",
Version: "1",
Condition: models.EventsubCondition{
BroadcasterUserID: params.ToUserID,
},
Transport: models.EventsubTransport{
Method: "webhook",
Callback: "null",
},
CreatedAt: util.GetTimestamp().Format(time.RFC3339Nano),
},
Event: models.ChannelUpdateEventSubEvent{
BroadcasterUserID: params.ToUserID,
BroadcasterUserLogin: params.ToUserID,
BroadcasterUserName: params.ToUserName,
StreamTitle: params.StreamTitle,
StreamLanguage: "en",
StreamCategoryID: "509658",
StreamCategoryName: "Just Chatting",
IsMature: "true",
},
}
event, err = json.Marshal(body)
if err != nil {
return events.MockEventResponse{}, err
}
case models.TransportWebSub:
body := models.StreamChangeWebSubResponse{
Data: []models.StreamChangeWebSubResponseData{
{
WebsubID: params.FromUserID,
BroadcasterUserID: params.ToUserID,
BroadcasterUserLogin: params.ToUserID,
BroadcasterUserName: params.ToUserName,
StreamCategoryID: "509658",
StreamCategoryName: "Just Chatting",
StreamType: "live",
StreamTitle: params.StreamTitle,
StreamViewerCount: 9848,
StreamStartedAt: util.GetTimestamp().Format(time.RFC3339),
StreamLanguage: "en",
StreamThumbnailURL: "https://static-cdn.jtvnw.net/previews-ttv/live_user_lirik-{width}x{height}.jpg",
},
},
}
event, err = json.Marshal(body)
if err != nil {
return events.MockEventResponse{}, err
}
default:
return events.MockEventResponse{}, nil
}

return events.MockEventResponse{
ID: params.ID,
JSON: event,
FromUser: params.FromUserID,
ToUser: params.ToUserID,
}, nil
}

func (e Event) ValidTransport(t string) bool {
return transportsSupported[t]
}

func (e Event) ValidTrigger(t string) bool {
for _, ts := range triggerSupported {
if ts == t {
return true
}
}
return false
}

func (e Event) GetTopic(transport string, trigger string) string {
return triggerMapping[transport][trigger]
}
117 changes: 117 additions & 0 deletions internal/events/types/stream_change/stream_change_event_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package stream_change

import (
"encoding/json"
"testing"

"github.com/twitchdev/twitch-cli/internal/events"
"github.com/twitchdev/twitch-cli/internal/models"
"github.com/twitchdev/twitch-cli/internal/util"
)

var fromUser = "1234"
var toUser = "4567"

func TestEventSub(t *testing.T) {
a := util.SetupTestEnv(t)

params := *&events.MockEventParameters{
FromUserID: fromUser,
ToUserID: toUser,
Transport: models.TransportEventSub,
Trigger: "stream_change",
}

r, err := Event{}.GenerateEvent(params)
a.Nil(err)

var body models.ChannelUpdateEventSubResponse
err = json.Unmarshal(r.JSON, &body)
a.Nil(err, "Error unmarshalling JSON")

// write actual tests here (making sure you set appropriate values and the like) for eventsub
a.Equal(toUser, body.Event.BroadcasterUserID, "Expected Stream Channel %v, got %v", toUser, body.Event.BroadcasterUserID)

// test for changing a title
params = events.MockEventParameters{
FromUserID: fromUser,
ToUserID: toUser,
Transport: models.TransportEventSub,
Trigger: "stream_change",
}

r, err = Event{}.GenerateEvent(params)
a.Nil(err)

err = json.Unmarshal(r.JSON, &body)
a.Nil(err)

a.Equal(toUser, body.Event.BroadcasterUserID, "Expected Stream Channel %v, got %v", toUser, body.Event.BroadcasterUserID)
a.Equal("Default Title!", body.Event.StreamTitle, "Expected new stream title, got %v", body.Event.StreamTitle)
}

func TestWebSubStreamChange(t *testing.T) {
a := util.SetupTestEnv(t)

newStreamTitle := "Awesome new title!"

params := *&events.MockEventParameters{
FromUserID: fromUser,
ToUserID: toUser,
Transport: models.TransportWebSub,
Trigger: "stream_change",
StreamTitle: newStreamTitle,
}

r, err := Event{}.GenerateEvent(params)
a.Nil(err)

var body models.StreamChangeWebSubResponse
err = json.Unmarshal(r.JSON, &body)
a.Nil(err)

// write tests here for websub
a.Equal(toUser, body.Data[0].BroadcasterUserID, "Expected Stream Channel %v, got %v", toUser, body.Data[0].BroadcasterUserID)
a.Equal(newStreamTitle, body.Data[0].StreamTitle, "Expected new stream title, got %v", body.Data[0].StreamTitle)
}
func TestFakeTransport(t *testing.T) {
a := util.SetupTestEnv(t)

params := *&events.MockEventParameters{
FromUserID: fromUser,
ToUserID: toUser,
Transport: "fake_transport",
Trigger: "stream_change",
}

r, err := Event{}.GenerateEvent(params)
a.Nil(err)
a.Empty(r)
}
func TestValidTrigger(t *testing.T) {
a := util.SetupTestEnv(t)

r := Event{}.ValidTrigger("stream_change")
a.Equal(true, r)

r = Event{}.ValidTrigger("not_trigger_keyword")
a.Equal(false, r)
}

func TestValidTransport(t *testing.T) {
a := util.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 := util.SetupTestEnv(t)

r := Event{}.GetTopic(models.TransportEventSub, "stream_change")
a.NotNil(r)
}
2 changes: 2 additions & 0 deletions internal/events/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/twitchdev/twitch-cli/internal/events/types/follow"
"github.com/twitchdev/twitch-cli/internal/events/types/moderator_change"
"github.com/twitchdev/twitch-cli/internal/events/types/raid"
"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"
"github.com/twitchdev/twitch-cli/internal/events/types/subscribe"
Expand All @@ -29,6 +30,7 @@ func All() []events.MockEvent {
follow.Event{},
raid.Event{},
subscribe.Event{},
stream_change.Event{},
streamup.Event{},
streamdown.Event{},
moderator_change.Event{},
Expand Down
39 changes: 39 additions & 0 deletions internal/models/stream_change.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package models

type ChannelUpdateEventSubEvent struct {
BroadcasterUserID string `json:"broadcaster_user_id"`
BroadcasterUserLogin string `json:"broadcaster_user_login"`
BroadcasterUserName string `json:"broadcaster_user_name"`
StreamTitle string `json:"title"`
StreamLanguage string `json:"language"`
StreamCategoryID string `json:"category_id"`
StreamCategoryName string `json:"category_name"`
IsMature string `json:"is_mature"`
}

type StreamChangeWebSubResponse struct {
Data []StreamChangeWebSubResponseData `json:"data"`
}

type StreamChangeWebSubResponseData struct {
WebsubID string `json:"id"`
BroadcasterUserID string `json:"user_id"`
BroadcasterUserLogin string `json:"user_login"`
BroadcasterUserName string `json:"user_name"`
StreamCategoryID string `json:"game_id"`
StreamCategoryName string `json:"game_name"`
StreamType string `json:"type"`
StreamTitle string `json:"title"`
StreamViewerCount int `json:"viewer_count"`
StreamStartedAt string `json:"started_at"`
StreamLanguage string `json:"language"`
StreamThumbnailURL string `json:"thumbnail_url"`
TagIDs []string `json:"tag_ids"`
}

type ChannelUpdateEventSubResponse struct {
Subscription EventsubSubscription `json:"subscription"`
Event ChannelUpdateEventSubEvent `json:"event"`
}

0 comments on commit e460762

Please sign in to comment.