internal async Task <StreamPrediction> GetCurrentPredictionAsync()
        {
            DebugLogging.Log("Getting current prediction", true);

            if (BroadcasterID == "")
            {
                await GetUserIDAsync();
            }

            if (BroadcasterID == "")
            {
                DebugLogging.Log("[ERROR] Broadcaster ID wasn't set despite multiple requests!");
                return(null);
            }

            var requestResult = await PerformGetRequestAsync(
                BuildURI(new string[] { "predictions" }, new Tuple <string, string>[] { new Tuple <string, string>("broadcaster_id", BroadcasterID) }),
                new Dictionary <string, string>() { }
                );

            if (requestResult["data"] != null)
            {
                var dataNode = ((IEnumerable <dynamic>)requestResult["data"]).First();

                if (dataNode["status"] != null)
                {
                    DebugLogging.Log("Converting response to Stream Prediction object.", true);
                    StreamPrediction prediction = StreamPrediction.ConvertNode(dataNode);
                    DebugLogging.Log("Current prediction is: '" + prediction.Title + "' and the status is " + prediction.Status, true);
                    return(prediction);
                }
            }
            DebugLogging.Log("Failed to get current (or last) prediction.");
            return(null);
        }
        internal async Task <StreamPrediction> CompleteWithOptionAsync(int winningOption)
        {
            if (BroadcasterID == "")
            {
                await GetUserIDAsync();
            }

            if (BroadcasterID != "")
            {
                StreamPrediction prediction = TwitchConnection.GetInstance().CurrentPrediction;
                if (prediction == null)
                {
                    prediction = await GetCurrentPredictionAsync();
                }

                if (prediction != null && (prediction.Status == StreamPrediction.PredictionStatus.ACTIVE || prediction.Status == StreamPrediction.PredictionStatus.LOCKED))
                {
                    DebugLogging.Log("Trying to close a prediction (" + prediction.ID + ") with outcome #" + (winningOption + 1).ToString(), true);

                    var parameters = new StringBuilder();
                    parameters.AppendLine("{");
                    parameters.AppendLine("\"broadcaster_id\": \"" + BroadcasterID + "\",");
                    parameters.AppendLine("\"id\": \"" + prediction.ID + "\",");

                    parameters.AppendLine("\"status\": \"" + StreamPrediction.PredictionStatus.RESOLVED + "\",");
                    parameters.AppendLine("\"winning_outcome_id\": \"" + (winningOption == 0 ? prediction.FirstOutcome.ID : prediction.SecondOutcome.ID) + "\"");
                    parameters.AppendLine("}");

                    var response = await PerformPatchRequestAsync(BuildURI(new string[] { "predictions" }, new Tuple <string, string>[] { }),
                                                                  new Dictionary <string, string>() { }, parameters.ToString()
                                                                  );

                    if (response["data"] != null)
                    {
                        var dataNode = ((IEnumerable <dynamic>)response["data"]).First();
                        if (dataNode["id"] != null)
                        {
                            if (dataNode["status"] != null)
                            {
                                StreamPrediction newPredictionState = StreamPrediction.ConvertNode(dataNode);
                                if (newPredictionState.Status == StreamPrediction.PredictionStatus.RESOLVED)
                                {
                                    DebugLogging.Log("Successfully closed a prediction!", true);
                                    return(newPredictionState);
                                }
                                else
                                {
                                    DebugLogging.Log("Failed to close a new prediction!");
                                    return(null);
                                }
                            }
                        }
                    }
                }
                DebugLogging.Log("Prediction already closed", true);
                return(prediction);
            }
            return(null);
        }
        internal async void WriteInChat(string text)
        {
            if (TriedConnectingToIrc)
            {
                return;
            }
            TriedConnectingToIrc = true;

            if (_irc == null || !_irc.IsConnected)
            {
                Connect();
                await Task.Delay(2 * 1000);
            }

            if (!_irc.IsConnected)
            {
                DebugLogging.Log("Failed to connect to IRC!", true);
                return;
            }

            if (!_irc.IsRegistered)
            {
                await Task.Delay(2 * 1000);
            }

            if (!_irc.IsRegistered)
            {
                DebugLogging.Log("Failed to register with IRC!", true);
                return;
            }

            if (!_irc.Channels.Any(x => x.Name == _connectionData.Channel))
            {
                if (_irc.LocalUser == null)
                {
                    DebugLogging.Log("Local user was null!", true);
                    return;
                }
                _irc.LocalUser.JoinedChannel += LocalUser_JoinedChannel1;
                _irc.Channels.Join("#" + _connectionData.Channel);
                await Task.Delay(1 * 1000);
            }

            var channel = _irc.Channels.FirstOrDefault(x => x.Name == "#" + _connectionData.Channel.ToLower());

            if (channel == null)
            {
                DebugLogging.Log("Failed to join specified channel!", true);
                return;
            }
            else
            {
                TriedConnectingToIrc = false;
                _irc.LocalUser.SendMessage(channel, text);
            }
        }
        public TwitchPredictionsSettings(Model.LiveSplitState splitStates)
        {
            InitializeComponent();
            DebugLogging._settings = this;
            DebugLogging.Log("Created settings and set reference", true);
            this.splitStates  = splitStates;
            _twitchConnection = TwitchConnection.GetInstance();

            //Set bindings
            TB_ServerAdress.DataBindings.Add("Text", this, "Address", false, DataSourceUpdateMode.OnPropertyChanged);
            NumB_Port.DataBindings.Add("Value", this, "Port", false, DataSourceUpdateMode.OnPropertyChanged);
            TB_UserName.DataBindings.Add("Text", this, "Username", false, DataSourceUpdateMode.OnPropertyChanged);
            TB_Oauth.DataBindings.Add("Text", this, "Oauth", false, DataSourceUpdateMode.OnPropertyChanged);
            TB_Channel.DataBindings.Add("Text", this, "Channel", false, DataSourceUpdateMode.OnPropertyChanged);
            CB_ConnectOnComponentLaunch.DataBindings.Add("Checked", this, "ConnectOnLaunch", false, DataSourceUpdateMode.OnPropertyChanged);
        }
        internal async Task GetUserIDAsync()
        {
            DebugLogging.Log("Getting user ID", true);
            var userTokenResult = await PerformGetRequestAsync(
                BuildURI(new string[] { "users" }, new Tuple <string, string>[] { new Tuple <string, string>("login", Channel) }),
                new Dictionary <string, string>() { }
                );

            if (userTokenResult["data"] != null)
            {
                var dataNode = ((IEnumerable <dynamic>)userTokenResult["data"]).First();
                if (dataNode["id"] != null)
                {
                    DebugLogging.Log("Request returned user ID!", true);
                    BroadcasterID = dataNode["id"];
                    return;
                }
            }
            DebugLogging.Log("Incorrect \"get user ID\" request!");
        }
        internal void Connect()
        {
            DebugLogging.Log("Connecting", true);

            if (_irc == null)
            {
                _irc = new IrcDotNet.IrcClient();
            }
            else
            {
                Disconnect();
            }

            _irc.Connect(_connectionData.Address, _connectionData.Port, new IrcDotNet.IrcUserRegistrationInfo()
            {
                NickName = _connectionData.Username, UserName = _connectionData.Username, RealName = _connectionData.Username, Password = "******" + _connectionData.Oauth
            });
            _irc.ErrorMessageReceived += _irc_ErrorMessageReceived;
            _irc.Connected            += _irc_Connected;
            _irc.Disconnected         += _irc_Disconnected;
            _irc.ClientInfoReceived   += _irc_ClientInfoReceived;
            _irc.RawMessageReceived   += _irc_RawMessageReceived;
            _irc.Registered           += _irc_Registered;
        }
 private void _irc_Disconnected(object sender, EventArgs e)
 {
     DebugLogging.Log("[IRC] Disconnected!", true);
 }
 private void _irc_Connected(object sender, EventArgs e)
 {
     DebugLogging.Log("[IRC] Connected!");
 }
 private void _irc_ClientInfoReceived(object sender, EventArgs e)
 {
     DebugLogging.Log("[IRC] Client Info Received.", true);
 }
 private void _irc_ErrorMessageReceived(object sender, IrcDotNet.IrcErrorMessageEventArgs e)
 {
     DebugLogging.Log("[IRC] Error Received: " + e.Message, true);
 }
 private void _irc_RawMessageReceived(object sender, IrcDotNet.IrcRawMessageEventArgs e)
 {
     DebugLogging.Log("[IRC] MSG: " + (e.Message.Source != null ? e.Message.Source + ": " : "") + string.Join(" ", e.Message.Parameters.Where(x => x != null).ToArray()), true);
 }
 private void LocalUser_JoinedChannel(object sender, IrcDotNet.IrcChannelEventArgs e)
 {
     DebugLogging.Log("[IRC] Joined channel: " + e.Channel.Name, true);
 }
 private void _irc_Registered(object sender, EventArgs e)
 {
     DebugLogging.Log("[IRC] Registered", true);
 }
        internal async Task <StreamPrediction> CancelPredictionAsync()
        {
            if (BroadcasterID == "")
            {
                await GetUserIDAsync();
            }

            if (BroadcasterID != "")
            {
                StreamPrediction prediction = TwitchConnection.GetInstance().CurrentPrediction;
                if (prediction == null)
                {
                    prediction = await GetCurrentPredictionAsync();
                }

                if (prediction != null && (prediction.Status == StreamPrediction.PredictionStatus.ACTIVE || prediction.Status == StreamPrediction.PredictionStatus.LOCKED))
                {
                    DebugLogging.Log("Trying to cancel a cancel prediction (" + prediction.ID + ")", true);

                    var parameters = new StringBuilder();
                    parameters.AppendLine("{");
                    parameters.AppendLine("\"broadcaster_id\": \"" + BroadcasterID + "\",");
                    parameters.AppendLine("\"id\": \"" + prediction.ID + "\",");

                    parameters.AppendLine("\"status\": \"" + StreamPrediction.PredictionStatus.CANCELED + "\"");
                    parameters.AppendLine("}");

                    var response = await PerformPatchRequestAsync(BuildURI(new string[] { "predictions" }, new Tuple <string, string>[] { }),
                                                                  new Dictionary <string, string>() { }, parameters.ToString()
                                                                  );

                    if (response["data"] != null)
                    {
                        var dataNode = ((IEnumerable <dynamic>)response["data"]).First();
                        if (dataNode["id"] != null)
                        {
                            if (dataNode["status"] != null)
                            {
                                StreamPrediction newPredictionState = StreamPrediction.ConvertNode(dataNode);
                                if (newPredictionState.Status == StreamPrediction.PredictionStatus.CANCELED)
                                {
                                    DebugLogging.Log("Successfully cancelled a new prediction!", true);
                                    return(newPredictionState);
                                }
                                else
                                {
                                    DebugLogging.Log("Failed to cancelled a new prediction!");
                                    return(null);
                                }
                            }
                        }
                    }
                    DebugLogging.Log("[ERROR] Incorrect response?");
                    return(null);
                }
                DebugLogging.Log("Prediction already closed", true);
                return(prediction);
            }

            DebugLogging.Log("[ERROR] Can not cancel prediction. Broadcaster ID is null!");
            return(null);
        }
        internal async Task <StreamPrediction> StartPredictionAsync(string header, string option1, string option2, uint lenght)
        {
            StreamPrediction newPrediction;

            DebugLogging.Log("Trying to start a new prediction.", true);

            if (BroadcasterID == "")
            {
                await GetUserIDAsync();
            }

            if (BroadcasterID == "")
            {
                DebugLogging.Log("[ERROR] Broadcaster ID wasn't set despite multiple requests!");
                return(null);
            }

            newPrediction = null;
            if (lenght > 1800)
            {
                lenght = 1779;
            }
            if (lenght < 1)
            {
                lenght = 1;
            }

            var parameters = new StringBuilder();

            parameters.AppendLine("{");
            parameters.AppendLine("\"broadcaster_id\": \"" + BroadcasterID + "\",");
            parameters.AppendLine("\"title\": \"" + JSON.Escape(header) + "\",");

            parameters.AppendLine("\"outcomes\": [");
            parameters.AppendLine("{");
            parameters.AppendLine("\"title\": \"" + JSON.Escape(option1) + "\"");
            parameters.AppendLine("},");
            parameters.AppendLine("{");
            parameters.AppendLine("\"title\": \"" + JSON.Escape(option2) + "\"");
            parameters.AppendLine("}");
            parameters.AppendLine("],");

            parameters.AppendLine("\"prediction_window\": " + lenght.ToString() + "");
            parameters.AppendLine("}");

            try
            {
                var response = await PerformPostRequestAsync(
                    BuildURI(new string[] { "predictions" }, new Tuple <string, string>[] { }),
                    new Dictionary <string, string>() { }, parameters.ToString()
                    );

                if (response["data"] != null)
                {
                    var dataNode = ((IEnumerable <dynamic>)response["data"]).First();
                    if (dataNode["id"] != null)
                    {
                        if (dataNode["status"] != null)
                        {
                            newPrediction = StreamPrediction.ConvertNode(dataNode);
                            DebugLogging.Log("Successfully created a new prediction!", true);
                            return(newPrediction);
                        }
                        DebugLogging.Log("[ERROR] Incorrect response?");
                        return(newPrediction);
                    }
                }
                DebugLogging.Log("[ERROR] Incorrect response?");
                return(newPrediction);
            }
            catch (WebException e)
            {
                if (e.Status == WebExceptionStatus.ProtocolError)
                {
                    if (((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.BadRequest)
                    {
                        var rawResponse = string.Empty;

                        var alreadyClosedStream = e.Response.GetResponseStream() as MemoryStream;
                        using (var brandNewStream = new MemoryStream(alreadyClosedStream.ToArray()))
                            using (var reader = new StreamReader(brandNewStream))
                                rawResponse = reader.ReadToEnd();

                        DebugLogging.Log("Error creating a prediction: " + rawResponse);
                        return(newPrediction);
                    }
                    DebugLogging.Log("[ERROR] " + e);
                    return(newPrediction);
                }
                DebugLogging.Log("[ERROR] " + e);
                return(newPrediction);
            }
        }