/// <summary>
        /// Creates a YouTubeLiveConnection object from an OAuth authentication locally.
        /// </summary>
        /// <param name="clientID">The ID of the client application</param>
        /// <param name="clientSecret">The secret of the client application</param>
        /// <param name="scopes">The authorization scopes to request</param>
        /// <param name="forceApprovalPrompt">Whether to force an approval from the user</param>
        /// <param name="oauthListenerURL">The URL to listen for the OAuth successful authentication</param>
        /// <param name="successResponse">The response to send back upon successful authentication</param>
        /// <returns>The YouTubeLiveConnection object</returns>
        public static async Task <YouTubeConnection> ConnectViaLocalhostOAuthBrowser(string clientID, string clientSecret, IEnumerable <OAuthClientScopeEnum> scopes, bool forceApprovalPrompt = false, string oauthListenerURL = DEFAULT_OAUTH_LOCALHOST_URL, string successResponse = null)
        {
            Validator.ValidateString(clientID, "clientID");
            Validator.ValidateList(scopes, "scopes");

            LocalOAuthHttpListenerServer oauthServer = new LocalOAuthHttpListenerServer(oauthListenerURL, DEFAULT_AUTHORIZATION_CODE_URL_PARAMETER, successResponse);

            oauthServer.Start();

            string url = await YouTubeConnection.GetAuthorizationCodeURLForOAuthBrowser(clientID, scopes, oauthListenerURL, forceApprovalPrompt);

            ProcessStartInfo startInfo = new ProcessStartInfo()
            {
                FileName = url, UseShellExecute = true
            };

            Process.Start(startInfo);

            string authorizationCode = await oauthServer.WaitForAuthorizationCode(secondsToWait : 60);

            oauthServer.Stop();

            if (authorizationCode != null)
            {
                return(await YouTubeConnection.ConnectViaAuthorizationCode(clientID, clientSecret, authorizationCode, redirectUrl : oauthListenerURL));
            }
            return(null);
        }
        /// <summary>
        /// Generates the OAuth authorization URL to use for authentication.
        /// </summary>
        /// <param name="clientID">The ID of the client application</param>
        /// <param name="scopes">The authorization scopes to request</param>
        /// <param name="redirectUri">The redirect URL for the client application</param>
        /// <param name="forceApprovalPrompt">Whether to force an approval from the user</param>
        /// <returns>The authorization URL</returns>
        public static async Task <string> GetAuthorizationCodeURLForOAuthBrowser(string clientID, IEnumerable <OAuthClientScopeEnum> scopes, string redirectUri, bool forceApprovalPrompt = false)
        {
            Validator.ValidateString(clientID, "clientID");
            Validator.ValidateList(scopes, "scopes");
            Validator.ValidateString(redirectUri, "redirectUri");

            string url = "https://accounts.google.com/o/oauth2/v2/auth";

            Dictionary <string, string> parameters = new Dictionary <string, string>()
            {
                { "client_id", clientID },
                { "scope", YouTubeConnection.ConvertClientScopesToString(scopes) },
                { "response_type", "code" },
                { "redirect_uri", redirectUri },
            };

            if (forceApprovalPrompt)
            {
                parameters.Add("force_verify", "force");
            }

            FormUrlEncodedContent content = new FormUrlEncodedContent(parameters.AsEnumerable());

            return(url + "?" + await content.ReadAsStringAsync());
        }
        /// <summary>
        /// Creates a YouTubeLiveConnection object from an OAuth token.
        /// </summary>
        /// <param name="token">The OAuth token to use</param>
        /// <param name="refreshToken">Whether to refresh the token</param>
        /// <returns>The YouTubeLiveConnection object</returns>
        public static async Task <YouTubeConnection> ConnectViaOAuthToken(OAuthTokenModel token, bool refreshToken = true)
        {
            Validator.ValidateVariable(token, "token");

            YouTubeConnection connection = new YouTubeConnection(token);

            if (refreshToken)
            {
                await connection.RefreshOAuthToken();
            }

            return(connection);
        }