Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix 221 #222

Merged
merged 2 commits into from
Apr 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions cmd/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ var (
clientId string
version string
websocketClient string
websocketServerIP string
websocketServerPort int
)

// websocketCmd-specific flags
Expand Down Expand Up @@ -173,7 +175,8 @@ func init() {

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

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

if args[0] == "start-server" || args[0] == "start" {
log.Printf("`Ctrl + C` to exit mock WebSocket servers.")
mock_server.StartWebsocketServer(wsDebug, port, wsStrict)
mock_server.StartWebsocketServer(wsDebug, websocketServerIP, websocketServerPort, wsStrict)
} else {
// Forward all other commands via RPC
websocket.ForwardWebsocketCommand(args[0], websocket.WebsocketCommandParameters{
Expand Down
12 changes: 10 additions & 2 deletions cmd/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
package cmd

import (
"fmt"
"strconv"

"github.com/twitchdev/twitch-cli/internal/login"

"github.com/spf13/cobra"
Expand All @@ -13,6 +16,8 @@ var isUserToken bool
var userScopes string
var revokeToken string
var overrideClientId string
var tokenServerPort int
var tokenServerIP string

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

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

redirectURL := "http://localhost:3000"
webserverPort := strconv.Itoa(tokenServerPort)
redirectURL := fmt.Sprintf("http://%v:%v", tokenServerIP, webserverPort)

if clientID == "" || clientSecret == "" {
println("No Client ID or Secret found in configuration. Triggering configuration now.")
Expand All @@ -61,7 +69,7 @@ func loginCmdRun(cmd *cobra.Command, args []string) {
login.CredentialsLogout(p)
} else if isUserToken == true {
p.URL = login.UserCredentialsURL
login.UserCredentialsLogin(p)
login.UserCredentialsLogin(p, tokenServerIP, webserverPort)
} else {
p.URL = login.ClientCredentialsURL
login.ClientCredentialsLogin(p)
Expand Down
14 changes: 8 additions & 6 deletions internal/events/websocket/mock_server/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,20 @@ type ServerManager struct {
serverList *util.List[WebSocketServer]
reconnectTesting bool
primaryServer string
ip string
port int
debugEnabled bool
strictMode bool
}

var serverManager *ServerManager

func StartWebsocketServer(enableDebug bool, port int, strictMode bool) {
func StartWebsocketServer(enableDebug bool, ip string, port int, strictMode bool) {
serverManager = &ServerManager{
serverList: &util.List[WebSocketServer]{
Elements: make(map[string]*WebSocketServer),
},
ip: ip,
port: port,
reconnectTesting: false,
strictMode: strictMode,
Expand Down Expand Up @@ -75,7 +77,7 @@ func StartWebsocketServer(enableDebug bool, port int, strictMode bool) {
// Start HTTP server
go func() {
// Listen to port
listen, err := net.Listen("tcp", fmt.Sprintf(":%v", port))
listen, err := net.Listen("tcp", fmt.Sprintf("%v:%v", ip, port))
if err != nil {
log.Fatalf("Cannot start HTTP server: %v", err)
return
Expand All @@ -86,14 +88,14 @@ func StartWebsocketServer(enableDebug bool, port int, strictMode bool) {
lightYellow := color.New(color.FgHiYellow).SprintFunc()
yellow := color.New(color.FgYellow).SprintFunc()

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

fmt.Println()

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

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

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

// Serve HTTP server
if err := http.Serve(listen, m); err != nil {
Expand Down Expand Up @@ -136,7 +138,7 @@ func StartWebsocketServer(enableDebug bool, port int, strictMode bool) {
func wsPageHandler(w http.ResponseWriter, r *http.Request) {
server, ok := serverManager.serverList.Get(serverManager.primaryServer)
if !ok {
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)
log.Printf("Failed to find primary server [%v] when new client was accessing ws://%v:%v/ws -- Aborting...", serverManager.primaryServer, serverManager.ip, serverManager.port)
return
}

Expand Down
2 changes: 1 addition & 1 deletion internal/events/websocket/mock_server/rpc_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ func RPCSubscriptionHandler(args rpc.RPCArgs) rpc.RPCResponse {
return rpc.RPCResponse{
ResponseCode: COMMAND_RESPONSE_MISSING_FLAG,
DetailedInfo: "Command \"subscription\" requires flags --status, --subscription, and --session" +
fmt.Sprintf("\nThe flag --subscription must be the ID of the subscription made at http://localhost:%v/eventsub/subscriptions", serverManager.port) +
fmt.Sprintf("\nThe flag --subscription must be the ID of the subscription made at http://%v:%v/eventsub/subscriptions", serverManager.ip, serverManager.port) +
"\nThe flag --status must be one of the non-webhook status options defined here:" +
"\nhttps://dev.twitch.tv/docs/api/reference/#get-eventsub-subscriptions" +
"\n\nExample: twitch event websocket subscription --status=user_removed --subscription=82a855-fae8-93bff0",
Expand Down
38 changes: 26 additions & 12 deletions internal/login/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"errors"
"fmt"
"log"
"net"
"net/http"
"net/url"
"os/exec"
Expand Down Expand Up @@ -95,7 +96,7 @@ func ClientCredentialsLogin(p LoginParameters) (LoginResponse, error) {
return r, nil
}

func UserCredentialsLogin(p LoginParameters) (LoginResponse, error) {
func UserCredentialsLogin(p LoginParameters, webserverIP string, webserverPort string) (LoginResponse, error) {
u, err := url.Parse(p.AuthorizeURL)
if err != nil {
log.Fatal(err)
Expand All @@ -115,17 +116,20 @@ func UserCredentialsLogin(p LoginParameters) (LoginResponse, error) {
q.Set("state", state)
u.RawQuery = q.Encode()

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

ur, err := userAuthServer()
urp, err := userAuthServer(webserverIP, webserverPort, execOpenBrowser)
if err != nil {
fmt.Printf("Error processing request; %v\n", err.Error())
return LoginResponse{}, err
}
ur := *urp

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

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

Expand Down Expand Up @@ -256,9 +260,9 @@ func openBrowser(url string) error {
return err
}

func userAuthServer() (UserAuthorizationQueryResponse, error) {
func userAuthServer(ip string, port string, onSuccessfulListenCallback func()) (*UserAuthorizationQueryResponse, error) {
m := http.NewServeMux()
s := http.Server{Addr: ":3000", Handler: m}
s := http.Server{Addr: fmt.Sprintf("%v:%v", ip, port), Handler: m}
userAuth := make(chan UserAuthorizationQueryResponse)
m.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/favicon.ico" {
Expand All @@ -282,8 +286,19 @@ func userAuthServer() (UserAuthorizationQueryResponse, error) {
userAuth <- u
}
})

ln, err := net.Listen("tcp", s.Addr)
defer s.Shutdown(context.Background())
if err != nil {
return nil, err
}

if onSuccessfulListenCallback != nil {
onSuccessfulListenCallback()
}

go func() {
if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed {
if err := s.Serve(ln); err != nil && err != http.ErrServerClosed {
log.Fatal(err)
return
}
Expand All @@ -292,8 +307,7 @@ func userAuthServer() (UserAuthorizationQueryResponse, error) {
log.Printf("Waiting for authorization response ...")
userAuthResponse := <-userAuth
log.Printf("Closing local server ...")
s.Shutdown(context.Background())
return userAuthResponse, userAuthResponse.Error
return &userAuthResponse, userAuthResponse.Error
}

func storeInConfig(token string, refresh string, scopes []string, expiresAt time.Time) {
Expand Down
4 changes: 2 additions & 2 deletions internal/login/login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ func TestUserAuthServer(t *testing.T) {
userResponse := make(chan UserAuthorizationQueryResponse)

go func() {
res, err := userAuthServer()
res, err := userAuthServer("", "3000", nil)
a.Nil(err)
userResponse <- res
userResponse <- *res
}()

time.Sleep(25)
Expand Down