Skip to content

Commit dad323d

Browse files
authored
Merge pull request #222 from twitchdev/fix-221
Fix 221
2 parents 25dfc79 + 762b7f4 commit dad323d

File tree

6 files changed

+52
-25
lines changed

6 files changed

+52
-25
lines changed

cmd/events.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ var (
4545
clientId string
4646
version string
4747
websocketClient string
48+
websocketServerIP string
49+
websocketServerPort int
4850
)
4951

5052
// websocketCmd-specific flags
@@ -173,7 +175,8 @@ func init() {
173175

174176
// websocket flags
175177
/// flags for start-server
176-
websocketCmd.Flags().IntVarP(&port, "port", "p", 8080, "Defines the port that the mock EventSub websocket server will run on.")
178+
websocketCmd.Flags().StringVar(&websocketServerIP, "ip", "127.0.0.1", "Defines the ip that the mock EventSub websocket server will bind to.")
179+
websocketCmd.Flags().IntVarP(&websocketServerPort, "port", "p", 8080, "Defines the port that the mock EventSub websocket server will run on.")
177180
websocketCmd.Flags().BoolVar(&wsDebug, "debug", false, "Set on/off for debug messages for the EventSub WebSocket server.")
178181
websocketCmd.Flags().BoolVarP(&wsStrict, "require-subscription", "S", false, "Requires subscriptions for all events, and activates 10 second subscription requirement.")
179182

@@ -332,7 +335,7 @@ func websocketCmdRun(cmd *cobra.Command, args []string) {
332335

333336
if args[0] == "start-server" || args[0] == "start" {
334337
log.Printf("`Ctrl + C` to exit mock WebSocket servers.")
335-
mock_server.StartWebsocketServer(wsDebug, port, wsStrict)
338+
mock_server.StartWebsocketServer(wsDebug, websocketServerIP, websocketServerPort, wsStrict)
336339
} else {
337340
// Forward all other commands via RPC
338341
websocket.ForwardWebsocketCommand(args[0], websocket.WebsocketCommandParameters{

cmd/token.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
package cmd
44

55
import (
6+
"fmt"
7+
"strconv"
8+
69
"github.com/twitchdev/twitch-cli/internal/login"
710

811
"github.com/spf13/cobra"
@@ -13,6 +16,8 @@ var isUserToken bool
1316
var userScopes string
1417
var revokeToken string
1518
var overrideClientId string
19+
var tokenServerPort int
20+
var tokenServerIP string
1621

1722
// loginCmd represents the login command
1823
var loginCmd = &cobra.Command{
@@ -28,13 +33,16 @@ func init() {
2833
loginCmd.Flags().StringVarP(&userScopes, "scopes", "s", "", "Space seperated list of scopes to request with your user token.")
2934
loginCmd.Flags().StringVarP(&revokeToken, "revoke", "r", "", "Instead of generating a new token, revoke the one passed to this parameter.")
3035
loginCmd.Flags().StringVar(&overrideClientId, "client-id", "", "Override/manually set client ID for token actions. By default client ID from CLI config will be used.")
36+
loginCmd.Flags().StringVar(&tokenServerIP, "ip", "localhost", "Manually set the IP address to be binded to for the User Token web server.")
37+
loginCmd.Flags().IntVarP(&tokenServerPort, "port", "p", 3000, "Manually set the port to be used for the User Token web server.")
3138
}
3239

3340
func loginCmdRun(cmd *cobra.Command, args []string) {
3441
clientID = viper.GetString("clientId")
3542
clientSecret = viper.GetString("clientSecret")
3643

37-
redirectURL := "http://localhost:3000"
44+
webserverPort := strconv.Itoa(tokenServerPort)
45+
redirectURL := fmt.Sprintf("http://%v:%v", tokenServerIP, webserverPort)
3846

3947
if clientID == "" || clientSecret == "" {
4048
println("No Client ID or Secret found in configuration. Triggering configuration now.")
@@ -61,7 +69,7 @@ func loginCmdRun(cmd *cobra.Command, args []string) {
6169
login.CredentialsLogout(p)
6270
} else if isUserToken == true {
6371
p.URL = login.UserCredentialsURL
64-
login.UserCredentialsLogin(p)
72+
login.UserCredentialsLogin(p, tokenServerIP, webserverPort)
6573
} else {
6674
p.URL = login.ClientCredentialsURL
6775
login.ClientCredentialsLogin(p)

internal/events/websocket/mock_server/manager.go

+8-6
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,20 @@ type ServerManager struct {
2424
serverList *util.List[WebSocketServer]
2525
reconnectTesting bool
2626
primaryServer string
27+
ip string
2728
port int
2829
debugEnabled bool
2930
strictMode bool
3031
}
3132

3233
var serverManager *ServerManager
3334

34-
func StartWebsocketServer(enableDebug bool, port int, strictMode bool) {
35+
func StartWebsocketServer(enableDebug bool, ip string, port int, strictMode bool) {
3536
serverManager = &ServerManager{
3637
serverList: &util.List[WebSocketServer]{
3738
Elements: make(map[string]*WebSocketServer),
3839
},
40+
ip: ip,
3941
port: port,
4042
reconnectTesting: false,
4143
strictMode: strictMode,
@@ -75,7 +77,7 @@ func StartWebsocketServer(enableDebug bool, port int, strictMode bool) {
7577
// Start HTTP server
7678
go func() {
7779
// Listen to port
78-
listen, err := net.Listen("tcp", fmt.Sprintf(":%v", port))
80+
listen, err := net.Listen("tcp", fmt.Sprintf("%v:%v", ip, port))
7981
if err != nil {
8082
log.Fatalf("Cannot start HTTP server: %v", err)
8183
return
@@ -86,14 +88,14 @@ func StartWebsocketServer(enableDebug bool, port int, strictMode bool) {
8688
lightYellow := color.New(color.FgHiYellow).SprintFunc()
8789
yellow := color.New(color.FgYellow).SprintFunc()
8890

89-
log.Printf(lightBlue("Started WebSocket server on 127.0.0.1:%v"), port)
91+
log.Printf(lightBlue("Started WebSocket server on %v:%v"), ip, port)
9092
if serverManager.strictMode {
9193
log.Printf(lightBlue("--require-subscription enabled. Clients will have 10 seconds to subscribe before being disconnected."))
9294
}
9395

9496
fmt.Println()
9597

96-
log.Printf(yellow("Simulate subscribing to events at: http://127.0.0.1:%v/eventsub/subscriptions"), port)
98+
log.Printf(yellow("Simulate subscribing to events at: http://%v:%v/eventsub/subscriptions"), ip, port)
9799
log.Printf(yellow("POST, GET, and DELETE are supported"))
98100
log.Printf(yellow("For more info: https://dev.twitch.tv/docs/cli/websocket-event-command/#simulate-subscribing-to-mock-eventsub"))
99101

@@ -107,7 +109,7 @@ func StartWebsocketServer(enableDebug bool, port int, strictMode bool) {
107109
log.Printf(lightGreen("For further usage information, please see our official documentation:\nhttps://dev.twitch.tv/docs/cli/websocket-event-command/"))
108110
fmt.Println()
109111

110-
log.Printf(lightBlue("Connect to the WebSocket server at: ")+"ws://127.0.0.1:%v/ws", port)
112+
log.Printf(lightBlue("Connect to the WebSocket server at: ")+"ws://%v:%v/ws", ip, port)
111113

112114
// Serve HTTP server
113115
if err := http.Serve(listen, m); err != nil {
@@ -136,7 +138,7 @@ func StartWebsocketServer(enableDebug bool, port int, strictMode bool) {
136138
func wsPageHandler(w http.ResponseWriter, r *http.Request) {
137139
server, ok := serverManager.serverList.Get(serverManager.primaryServer)
138140
if !ok {
139-
log.Printf("Failed to find primary server [%v] when new client was accessing ws://127.0.0.1:%v/ws -- Aborting...", serverManager.primaryServer, serverManager.port)
141+
log.Printf("Failed to find primary server [%v] when new client was accessing ws://%v:%v/ws -- Aborting...", serverManager.primaryServer, serverManager.ip, serverManager.port)
140142
return
141143
}
142144

internal/events/websocket/mock_server/rpc_handler.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ func RPCSubscriptionHandler(args rpc.RPCArgs) rpc.RPCResponse {
215215
return rpc.RPCResponse{
216216
ResponseCode: COMMAND_RESPONSE_MISSING_FLAG,
217217
DetailedInfo: "Command \"subscription\" requires flags --status, --subscription, and --session" +
218-
fmt.Sprintf("\nThe flag --subscription must be the ID of the subscription made at http://localhost:%v/eventsub/subscriptions", serverManager.port) +
218+
fmt.Sprintf("\nThe flag --subscription must be the ID of the subscription made at http://%v:%v/eventsub/subscriptions", serverManager.ip, serverManager.port) +
219219
"\nThe flag --status must be one of the non-webhook status options defined here:" +
220220
"\nhttps://dev.twitch.tv/docs/api/reference/#get-eventsub-subscriptions" +
221221
"\n\nExample: twitch event websocket subscription --status=user_removed --subscription=82a855-fae8-93bff0",

internal/login/login.go

+26-12
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"errors"
1111
"fmt"
1212
"log"
13+
"net"
1314
"net/http"
1415
"net/url"
1516
"os/exec"
@@ -95,7 +96,7 @@ func ClientCredentialsLogin(p LoginParameters) (LoginResponse, error) {
9596
return r, nil
9697
}
9798

98-
func UserCredentialsLogin(p LoginParameters) (LoginResponse, error) {
99+
func UserCredentialsLogin(p LoginParameters, webserverIP string, webserverPort string) (LoginResponse, error) {
99100
u, err := url.Parse(p.AuthorizeURL)
100101
if err != nil {
101102
log.Fatal(err)
@@ -115,17 +116,20 @@ func UserCredentialsLogin(p LoginParameters) (LoginResponse, error) {
115116
q.Set("state", state)
116117
u.RawQuery = q.Encode()
117118

118-
fmt.Println("Opening browser. Press Ctrl+C to cancel...")
119-
err = openBrowser(u.String())
120-
if err != nil {
121-
fmt.Printf("Unable to open default browser. You can manually navigate to this URL to complete the login: %s\n", u.String())
119+
execOpenBrowser := func() {
120+
fmt.Println("Opening browser. Press Ctrl+C to cancel...")
121+
err = openBrowser(u.String())
122+
if err != nil {
123+
fmt.Printf("Unable to open default browser. You can manually navigate to this URL to complete the login: %s\n", u.String())
124+
}
122125
}
123126

124-
ur, err := userAuthServer()
127+
urp, err := userAuthServer(webserverIP, webserverPort, execOpenBrowser)
125128
if err != nil {
126129
fmt.Printf("Error processing request; %v\n", err.Error())
127130
return LoginResponse{}, err
128131
}
132+
ur := *urp
129133

130134
if ur.State != state {
131135
log.Fatal("state mismatch")
@@ -175,7 +179,7 @@ func CredentialsLogout(p LoginParameters) (LoginResponse, error) {
175179
}
176180

177181
if resp.StatusCode != http.StatusOK {
178-
log.Printf("API responded with an error while revoking token: %v", string(resp.Body))
182+
log.Printf("API responded with an error while revoking token: [%v] %v", resp.StatusCode, string(resp.Body))
179183
return LoginResponse{}, errors.New("API responded with an error while revoking token")
180184
}
181185

@@ -256,9 +260,9 @@ func openBrowser(url string) error {
256260
return err
257261
}
258262

259-
func userAuthServer() (UserAuthorizationQueryResponse, error) {
263+
func userAuthServer(ip string, port string, onSuccessfulListenCallback func()) (*UserAuthorizationQueryResponse, error) {
260264
m := http.NewServeMux()
261-
s := http.Server{Addr: ":3000", Handler: m}
265+
s := http.Server{Addr: fmt.Sprintf("%v:%v", ip, port), Handler: m}
262266
userAuth := make(chan UserAuthorizationQueryResponse)
263267
m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
264268
if r.URL.Path == "/favicon.ico" {
@@ -282,8 +286,19 @@ func userAuthServer() (UserAuthorizationQueryResponse, error) {
282286
userAuth <- u
283287
}
284288
})
289+
290+
ln, err := net.Listen("tcp", s.Addr)
291+
defer s.Shutdown(context.Background())
292+
if err != nil {
293+
return nil, err
294+
}
295+
296+
if onSuccessfulListenCallback != nil {
297+
onSuccessfulListenCallback()
298+
}
299+
285300
go func() {
286-
if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed {
301+
if err := s.Serve(ln); err != nil && err != http.ErrServerClosed {
287302
log.Fatal(err)
288303
return
289304
}
@@ -292,8 +307,7 @@ func userAuthServer() (UserAuthorizationQueryResponse, error) {
292307
log.Printf("Waiting for authorization response ...")
293308
userAuthResponse := <-userAuth
294309
log.Printf("Closing local server ...")
295-
s.Shutdown(context.Background())
296-
return userAuthResponse, userAuthResponse.Error
310+
return &userAuthResponse, userAuthResponse.Error
297311
}
298312

299313
func storeInConfig(token string, refresh string, scopes []string, expiresAt time.Time) {

internal/login/login_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@ func TestUserAuthServer(t *testing.T) {
146146
userResponse := make(chan UserAuthorizationQueryResponse)
147147

148148
go func() {
149-
res, err := userAuthServer()
149+
res, err := userAuthServer("", "3000", nil)
150150
a.Nil(err)
151-
userResponse <- res
151+
userResponse <- *res
152152
}()
153153

154154
time.Sleep(25)

0 commit comments

Comments
 (0)