Skip to content

Commit

Permalink
EventSub WebSocket reconnect testing (#179)
Browse files Browse the repository at this point in the history
* Added in WSS (websocket secure) support for EventSub WebSockets. Currently only supports connecting and reconnect testing.
  • Loading branch information
Xemdo authored Oct 18, 2022
1 parent 99ede5e commit f9d8ee0
Show file tree
Hide file tree
Showing 6 changed files with 561 additions and 19 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,8 @@ twitch-cli

# junk files
.DS_Store

# SSL certs for HTTPS/WSS
*.crt
*.csr
*.key
63 changes: 44 additions & 19 deletions cmd/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,37 @@ package cmd

import (
"fmt"
"log"
"net/url"

"github.com/spf13/cobra"
"github.com/twitchdev/twitch-cli/internal/events"
"github.com/twitchdev/twitch-cli/internal/events/mock_wss_server"
"github.com/twitchdev/twitch-cli/internal/events/trigger"
"github.com/twitchdev/twitch-cli/internal/events/verify"
)

const websubDeprecationNotice = "Halt! It appears you are trying to use WebSub, which has been deprecated. For more information, see: https://discuss.dev.twitch.tv/t/deprecation-of-websub-based-webhooks/32152"

var (
isAnonymous bool
forwardAddress string
event string
transport string
fromUser string
toUser string
giftUser string
eventID string
secret string
status string
itemID string
itemName string
cost int64
count int
description string
gameID string
isAnonymous bool
forwardAddress string
event string
transport string
fromUser string
toUser string
giftUser string
eventID string
secret string
status string
itemID string
itemName string
cost int64
count int
description string
gameID string
debug bool
wssReconnectTest int
)

var eventCmd = &cobra.Command{
Expand All @@ -47,7 +51,7 @@ var triggerCmd = &cobra.Command{
Args: cobra.MaximumNArgs(1),
ValidArgs: events.ValidTriggers(),
Run: triggerCmdRun,
Example: `twitch trigger subscribe`,
Example: `twitch event trigger subscribe`,
Aliases: []string{
"fire", "emit",
},
Expand All @@ -72,12 +76,22 @@ var retriggerCmd = &cobra.Command{
Use: "retrigger",
Short: "Refires events based on the event ID. Can be forwarded to the local webserver for event testing.",
Run: retriggerCmdRun,
Example: `twitch trigger subscribe`,
Example: `twitch event retrigger subscribe`,
}

var startWebsocketServerCmd = &cobra.Command{
Use: "start-websocket-server",
Short: "Starts a local websocket server at wss://localhost:8000",
Run: startWebsocketServerCmdRun,
Example: `twitch event start-websocket-server`,
Aliases: []string{
"wss",
},
}

func init() {
rootCmd.AddCommand(eventCmd)
eventCmd.AddCommand(triggerCmd, retriggerCmd, verifyCmd)
eventCmd.AddCommand(triggerCmd, retriggerCmd, verifyCmd, startWebsocketServerCmd)

// trigger flags
// flags for forwarding functionality/changing payloads
Expand Down Expand Up @@ -109,6 +123,12 @@ func init() {
verifyCmd.Flags().StringVarP(&transport, "transport", "T", "eventsub", fmt.Sprintf("Preferred transport method for event. Defaults to EventSub.\nSupported values: %s", events.ValidTransports()))
verifyCmd.Flags().StringVarP(&secret, "secret", "s", "", "Webhook secret. If defined, signs all forwarded events with the SHA256 HMAC and must be 10-100 characters in length.")
verifyCmd.MarkFlagRequired("forward-address")

// start-websocket-server flags
startWebsocketServerCmd.Flags().IntVarP(&port, "port", "p", 8080, "Defines the port that the mock EventSub websocket server will run on.")
startWebsocketServerCmd.Flags().BoolVar(&debug, "debug", false, "Set on/off for debug messages for the EventSub WebSocket server.")
// TODO: This next flag is temporary, until I create a better way to test reconnecting.
startWebsocketServerCmd.Flags().IntVarP(&wssReconnectTest, "reconnect", "r", 0, "Used to test WebSocket Reconnect message. Sets delay (in seconds) from startup until the reconnect occurs.")
}

func triggerCmdRun(cmd *cobra.Command, args []string) {
Expand Down Expand Up @@ -223,3 +243,8 @@ func verifyCmdRun(cmd *cobra.Command, args []string) {
return
}
}

func startWebsocketServerCmdRun(cmd *cobra.Command, args []string) {
log.Printf("Starting mock EventSub WebSocket servers on wss://localhost:%v and wss://localhost:%v", port, port+1)
mock_wss_server.StartServer(port, debug, wssReconnectTest)
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2
github.com/fatih/color v1.12.0
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/gorilla/websocket v1.5.0
github.com/hokaccha/go-prettyjson v0.0.0-20201222001619-a42f9ac2ec8e // indirect
github.com/jmoiron/sqlx v1.3.4
github.com/lunixbochs/vtclean v1.0.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
Expand Down
81 changes: 81 additions & 0 deletions internal/events/mock_wss_server/message_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package mock_wss_server

// Generic response message Metadata; Always the same

type MessageMetadata struct {
MessageID string `json:"message_id"`
MessageType string `json:"message_type"`
MessageTimestamp string `json:"message_timestamp"`
}

/* ** Welcome message **
{ // <1>
"metadata": { // <MessageMetadata>
"message_id": "befa7b53-d79d-478f-86b9-120f112b044e",
"message_type": "session_welcome",
"message_timestamp": "2019-11-16T10:11:12.123Z"
},
"payload": { // <2>
"session": { // <3>
"id": "AQoQexAWVYKSTIu4ec_2VAxyuhAB",
"status": "connected",
"minimum_message_frequency_seconds": 10,
"reconnect_url": null,
"connected_at": "2019-11-16T10:11:12.123Z"
}
}
}
*/

type WelcomeMessage struct { // <1>
Metadata MessageMetadata `json:"metadata"`
Payload WelcomeMessagePayload `json:"payload"`
}

type WelcomeMessagePayload struct { // <2>
Session WelcomeMessagePayloadSession `json:"session"`
}

type WelcomeMessagePayloadSession struct { // <3>
ID string `json:"id"`
Status string `json:"status"`
MinimumMessageFrequencySeconds int `json:"minimum_message_frequency_seconds"`
ReconnectUrl *string `json:"reconnect_url"`
ConnectedAt string `json:"connected_at"`
}

/* ** Reconnect message **
{ // <1>
"metadata": { // <MessageMetadata>
"message_id": "84c1e79a-2a4b-4c13-ba0b-4312293e9308",
"message_type": "session_reconnect",
"message_timestamp": "2019-11-18T09:10:11.234Z"
},
"payload": { // <2>
"session": { // <3>
"id": "AQoQexAWVYKSTIu4ec_2VAxyuhAB",
"status": "reconnecting",
"minimum_message_frequency_seconds": null,
"reconnect_url": "wss://eventsub-experimental.wss.twitch.tv?...",
"connected_at": "2019-11-16T10:11:12.123Z"
}
}
}
*/

type ReconnectMessage struct { // <1>
Metadata MessageMetadata `json:"metadata"`
Payload ReconnectMessagePayload `json:"payload"`
}

type ReconnectMessagePayload struct { // <2>
Session ReconnectMessagePayloadSession `json:"session"`
}

type ReconnectMessagePayloadSession struct { // <3>
ID string `json:"id"`
Status string `json:"status"`
MinimumMessageFrequencySeconds *int `json:"minimum_message_frequency_seconds"`
ReconnectUrl string `json:"reconnect_url"`
ConnectedAt string `json:"connected_at"`
}
Loading

0 comments on commit f9d8ee0

Please sign in to comment.