/// <summary>
        /// Connect this instance to the specified URL, and authenticate (if needed) with the specified password
        /// </summary>
        /// <param name="url">Server URL in standard URL format</param>
        /// <param name="password">Server password</param>
        public void Connect(string url, string password)
        {
            if (WSConnection != null && WSConnection.IsAlive)
            {
                Disconnect();
            }

            WSConnection            = new WebSocket(url);
            WSConnection.WaitTime   = _pWSTimeout;
            WSConnection.OnMessage += WebsocketMessageHandler;
            WSConnection.OnClose   += (s, e) =>
            {
                if (Disconnected != null)
                {
                    Disconnected(this, e);
                }
            };
            WSConnection.Connect();

            if (WSConnection.IsAlive)
            {
                OBSAuthInfo authInfo = GetAuthInfo();

                if (authInfo.AuthRequired)
                {
                    Authenticate(password, authInfo);
                }

                if (Connected != null)
                {
                    Connected(this, null);
                }
            }
        }
        /// <summary>
        /// Connect this instance to the specified URL, and authenticate (if needed) with the specified password
        /// </summary>
        /// <param name="url">Server URL in standard URL format</param>
        /// <param name="password">Server password</param>
        public async Task Connect(string url, string password)
        {
            if (WSConnection?.IsAlive == true)
            {
                Disconnect();
            }

            WSConnection = new WebSocket(url)
            {
                WaitTime = _pWSTimeout
            };

            WSConnection.Log.Level = LogLevel.Debug;

            WSConnection.OnMessage += WebsocketMessageHandler;
            WSConnection.OnClose   += (s, e) => Disconnected?.Invoke(this, e);
            WSConnection.OnError   += WSConnection_OnError;
            WSConnection.Connect();

            if (!WSConnection.IsAlive)
            {
                return;
            }

            OBSAuthInfo authInfo = await GetAuthInfo();

            if (authInfo.AuthRequired)
            {
                await Authenticate(password, authInfo);
            }

            Connected?.Invoke(this, null);
        }
        /// <summary>
        /// Connect this instance to the specified URL, and authenticate (if needed) with the specified password
        /// </summary>
        /// <param name="url">Server URL in standard URL format</param>
        /// <param name="password">Server password</param>
        public void Connect(string url, string password)
        {
            if (_ws != null && _ws.IsAlive)
            {
                Disconnect();
            }

            _ws            = new WebSocket(url);
            _ws.OnMessage += WebsocketMessageHandler;
            _ws.Connect();

            OBSAuthInfo authInfo = GetAuthInfo();

            if (authInfo.AuthRequired)
            {
                Authenticate(password, authInfo);
            }
        }
        /// <summary>
        /// Authenticates to the Websocket server using the challenge and salt given in the passed <see cref="OBSAuthInfo"/> object
        /// </summary>
        /// <param name="password">User password</param>
        /// <param name="authInfo">Authentication data</param>
        /// <returns>true if authentication succeeds, false otherwise</returns>
        public bool Authenticate(string password, OBSAuthInfo authInfo)
        {
            string secret       = HashEncode(password + authInfo.PasswordSalt);
            string authResponse = HashEncode(secret + authInfo.Challenge);

            var requestFields = new JObject();

            requestFields.Add("auth", authResponse);

            try
            {
                // Throws ErrorResponseException if auth fails
                SendRequest("Authenticate", requestFields);
            }
            catch (ErrorResponseException)
            {
                throw new AuthFailureException();
            }

            return(true);
        }
        /// <summary>
        /// Connect this instance to the specified URL, and authenticate (if needed) with the specified password
        /// </summary>
        /// <param name="url">Server URL in standard URL format.</param>
        /// <param name="password">Server password</param>
        public void Connect(string url, string password)
        {
            if (!url.ToLower().StartsWith(WEBSOCKET_URL_PREFIX))
            {
                throw new ArgumentException($"Invalid url, must start with '{WEBSOCKET_URL_PREFIX}'");
            }

            if (WSConnection != null && WSConnection.IsAlive)
            {
                Disconnect();
            }

            WSConnection = new WebSocket(url)
            {
                WaitTime = wsTimeout
            };
            WSConnection.OnMessage += WebsocketMessageHandler;
            WSConnection.OnClose   += (s, e) =>
            {
                Disconnected?.Invoke(this, e);
            };
            WSConnection.Connect();

            if (!WSConnection.IsAlive)
            {
                return;
            }

            OBSAuthInfo authInfo = GetAuthInfo();

            if (authInfo.AuthRequired)
            {
                Authenticate(password, authInfo);
            }

            Connected?.Invoke(this, null);
        }