protected override async Task <Result> InitializeInternal() { this.cancellationTokenSource = new CancellationTokenSource(); this.startTime = DateTimeOffset.Now; this.user = await this.GetCurrentAccount(); if (this.user != null) { if (!string.IsNullOrEmpty(ChannelSession.Settings.JustGivingPageShortName)) { IEnumerable <JustGivingFundraiser> fundraisers = await this.GetCurrentFundraisers(); this.fundraiser = fundraisers.FirstOrDefault(f => f.pageShortName.Equals(ChannelSession.Settings.JustGivingPageShortName)); } AsyncRunner.RunBackgroundTask(this.cancellationTokenSource.Token, 60000, this.BackgroundDonationCheck); this.TrackServiceTelemetry("JustGiving"); return(new Result()); } return(new Result("Unable to get User data")); }
public async Task PerformTradeCommand(UserViewModel user, IEnumerable <string> arguments = null, StreamingPlatformTypeEnum platform = StreamingPlatformTypeEnum.None) { try { if (ChannelSession.Services.Chat != null && arguments != null) { if (this.tradeReceiver == null && arguments.Count() >= 2) { UserViewModel targetUser = await SpecialIdentifierStringBuilder.GetUserFromArgument(arguments.First(), platform); if (targetUser == null) { await ChannelSession.Services.Chat.SendMessage("The specified user does not exist"); return; } int amount = 1; IEnumerable <string> itemArgs = arguments.Skip(1); UserInventoryItemModel item = this.GetItem(string.Join(" ", itemArgs)); if (item == null && itemArgs.Count() > 1) { itemArgs = itemArgs.Take(itemArgs.Count() - 1); item = this.GetItem(string.Join(" ", itemArgs)); if (item != null) { if (!int.TryParse(arguments.Last(), out amount) || amount <= 0) { await ChannelSession.Services.Chat.SendMessage("A valid amount greater than 0 must be specified"); return; } } } if (item == null) { await ChannelSession.Services.Chat.SendMessage("The item you specified does not exist"); return; } if (!this.HasAmount(user.Data, item, amount)) { await ChannelSession.Services.Chat.SendMessage(string.Format("You do not have the required {0} {1} to trade", amount, item.Name)); return; } this.tradeSender = new UserInventoryTradeModel() { User = user, Item = item, Amount = amount }; this.tradeReceiver = new UserInventoryTradeModel() { User = targetUser }; this.tradeTimeCheckToken = new CancellationTokenSource(); #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed AsyncRunner.RunBackgroundTask(this.tradeTimeCheckToken.Token, async(token) => { await Task.Delay(60000); if (!token.IsCancellationRequested) { this.tradeSender = null; this.tradeReceiver = null; this.tradeTimeCheckToken = null; await ChannelSession.Services.Chat.SendMessage("The trade could not be completed in time and was cancelled..."); } }); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed await ChannelSession.Services.Chat.SendMessage(string.Format("@{0} has started a trade with @{1} for {2} {3}. Type {4} <ITEM NAME> [AMOUNT] in chat to reply back with your offer in the next 60 seconds.", this.tradeSender.User.Username, this.tradeReceiver.User.Username, this.tradeSender.Amount, this.tradeSender.Item.Name, this.TradeCommand)); return; } else if (this.tradeSender != null && this.tradeReceiver != null && this.tradeReceiver.User.Equals(user) && this.tradeReceiver.Amount == 0 && arguments.Count() >= 1) { int amount = 1; IEnumerable <string> itemArgs = arguments.ToList(); UserInventoryItemModel item = this.GetItem(string.Join(" ", itemArgs)); if (item == null && itemArgs.Count() > 1) { itemArgs = itemArgs.Take(itemArgs.Count() - 1); item = this.GetItem(string.Join(" ", itemArgs)); if (item != null) { if (!int.TryParse(arguments.Last(), out amount) || amount <= 0) { await ChannelSession.Services.Chat.SendMessage("A valid amount greater than 0 must be specified"); return; } } } if (item == null) { await ChannelSession.Services.Chat.SendMessage("The item you specified does not exist"); return; } if (!this.HasAmount(user.Data, item, amount)) { await ChannelSession.Services.Chat.SendMessage(string.Format("You do not have the required {0} {1} to trade", amount, item.Name)); return; } this.tradeReceiver.Item = item; this.tradeReceiver.Amount = amount; await ChannelSession.Services.Chat.SendMessage(string.Format("@{0} has replied back to the offer by @{1} with {2} {3}. Type {4} in chat to accept the trade.", this.tradeReceiver.User.Username, this.tradeSender.User.Username, this.tradeReceiver.Amount, this.tradeReceiver.Item.Name, this.TradeCommand)); return; } else if (this.tradeSender != null && this.tradeReceiver != null && this.tradeReceiver.Amount > 0 && this.tradeSender.User.Equals(user)) { int senderItemMaxAmount = (this.tradeReceiver.Item.HasMaxAmount) ? this.tradeReceiver.Item.MaxAmount : this.DefaultMaxAmount; if ((this.GetAmount(this.tradeSender.User.Data, this.tradeReceiver.Item) + this.tradeReceiver.Amount) > senderItemMaxAmount) { await ChannelSession.Services.Chat.SendMessage(string.Format("You can only have {0} {1} in total", senderItemMaxAmount, this.tradeReceiver.Item.Name)); return; } int receiverItemMaxAmount = (this.tradeSender.Item.HasMaxAmount) ? this.tradeSender.Item.MaxAmount : this.DefaultMaxAmount; if ((this.GetAmount(this.tradeReceiver.User.Data, this.tradeSender.Item) + this.tradeSender.Amount) > receiverItemMaxAmount) { await ChannelSession.Services.Chat.SendMessage(string.Format("You can only have {0} {1} in total", receiverItemMaxAmount, this.tradeSender.Item.Name)); return; } this.SubtractAmount(this.tradeSender.User.Data, this.tradeSender.Item, this.tradeSender.Amount); this.AddAmount(this.tradeReceiver.User.Data, this.tradeSender.Item, this.tradeSender.Amount); this.SubtractAmount(this.tradeReceiver.User.Data, this.tradeReceiver.Item, this.tradeReceiver.Amount); this.AddAmount(this.tradeSender.User.Data, this.tradeReceiver.Item, this.tradeReceiver.Amount); if (this.ItemsTradedCommand != null) { Dictionary <string, string> specialIdentifiers = new Dictionary <string, string>(); specialIdentifiers["itemtotal"] = this.tradeSender.Amount.ToString(); specialIdentifiers["itemname"] = this.tradeSender.Item.Name; specialIdentifiers["targetitemtotal"] = this.tradeReceiver.Amount.ToString(); specialIdentifiers["targetitemname"] = this.tradeReceiver.Item.Name; await this.ItemsTradedCommand.Perform(user, arguments : new string[] { this.tradeReceiver.User.Username }, extraSpecialIdentifiers : specialIdentifiers); } this.tradeSender = null; this.tradeReceiver = null; this.tradeTimeCheckToken.Cancel(); this.tradeTimeCheckToken = null; return; } else if (this.tradeSender != null && this.tradeReceiver != null && !this.tradeReceiver.User.Equals(user)) { await ChannelSession.Services.Chat.SendMessage("A trade is already underway, please wait until it is completed"); return; } } await ChannelSession.Services.Chat.SendMessage(this.TradeCommand + " <USERNAME> <ITEM NAME> [AMOUNT] = Trades 1 or the amount specified of the item to the specified user"); } catch (Exception ex) { Logger.Log(ex); } }
public async Task <Result> Connect() { this.IsConnected = false; if (ChannelSession.TwitchUserConnection != null) { return(await this.AttemptConnect((Func <Task <Result> >)(async() => { try { this.pubSub = new PubSubClient(ChannelSession.TwitchUserConnection.Connection); if (ChannelSession.AppSettings.DiagnosticLogging) { this.pubSub.OnSentOccurred += PubSub_OnSentOccurred; this.pubSub.OnTextReceivedOccurred += PubSub_OnTextReceivedOccurred; this.pubSub.OnMessageReceived += PubSub_OnMessageReceived; } this.pubSub.OnReconnectReceived += PubSub_OnReconnectReceived; this.pubSub.OnDisconnectOccurred += PubSub_OnDisconnectOccurred; this.pubSub.OnPongReceived += PubSub_OnPongReceived; this.pubSub.OnResponseReceived += PubSub_OnResponseReceived; this.pubSub.OnWhisperReceived += PubSub_OnWhisperReceived; this.pubSub.OnBitsV2Received += PubSub_OnBitsV2Received; this.pubSub.OnSubscribedReceived += PubSub_OnSubscribedReceived; this.pubSub.OnSubscriptionsGiftedReceived += PubSub_OnSubscriptionsGiftedReceived; this.pubSub.OnChannelPointsRedeemed += PubSub_OnChannelPointsRedeemed; await this.pubSub.Connect(); await Task.Delay(1000); List <PubSubListenTopicModel> topics = new List <PubSubListenTopicModel>(); foreach (PubSubTopicsEnum topic in TwitchEventService.topicTypes) { topics.Add(new PubSubListenTopicModel(topic, (string)ChannelSession.TwitchUserNewAPI.id)); } await this.pubSub.Listen(topics); await Task.Delay(1000); await this.pubSub.Ping(); this.cancellationTokenSource = new CancellationTokenSource(); AsyncRunner.RunBackgroundTask(this.cancellationTokenSource.Token, 60000, this.BackgroundEventChecks); this.IsConnected = true; return new Result(); } catch (Exception ex) { Logger.Log(ex); return new Result(ex); } }))); } return(new Result("Twitch connection has not been established")); }
public static async Task <bool> InitializeSession() { try { TwitchNewAPI.Users.UserModel twitchChannelNew = await ChannelSession.TwitchUserConnection.GetNewAPICurrentUser(); TwitchV5API.Channel.ChannelModel twitchChannelv5 = await ChannelSession.TwitchUserConnection.GetCurrentV5APIChannel(); if (twitchChannelNew != null && twitchChannelv5 != null) { try { ChannelSession.TwitchUserNewAPI = twitchChannelNew; ChannelSession.TwitchChannelV5 = twitchChannelv5; ChannelSession.TwitchStreamNewAPI = await ChannelSession.TwitchUserConnection.GetStream(ChannelSession.TwitchUserNewAPI); ChannelSession.TwitchStreamV5 = await ChannelSession.TwitchUserConnection.GetV5LiveStream(ChannelSession.TwitchChannelV5); IEnumerable <TwitchV5API.Users.UserModel> channelEditors = await ChannelSession.TwitchUserConnection.GetV5APIChannelEditors(ChannelSession.TwitchChannelV5); if (channelEditors != null) { foreach (TwitchV5API.Users.UserModel channelEditor in channelEditors) { ChannelSession.TwitchChannelEditorsV5.Add(channelEditor.id); } } if (ChannelSession.Settings == null) { IEnumerable <SettingsV2Model> currentSettings = await ChannelSession.Services.Settings.GetAllSettings(); if (currentSettings.Any(s => !string.IsNullOrEmpty(s.TwitchChannelID) && string.Equals(s.TwitchChannelID, twitchChannelNew.id))) { GlobalEvents.ShowMessageBox($"There already exists settings for the account {twitchChannelNew.display_name}. Please sign in with a different account or re-launch Mix It Up to select those settings from the drop-down."); return(false); } ChannelSession.Settings = await ChannelSession.Services.Settings.Create(twitchChannelNew.display_name, isStreamer : true); } await ChannelSession.Services.Settings.Initialize(ChannelSession.Settings); if (!string.IsNullOrEmpty(ChannelSession.Settings.TwitchUserID) && !string.Equals(ChannelSession.TwitchUserNewAPI.id, ChannelSession.Settings.TwitchUserID)) { Logger.Log(LogLevel.Error, $"Signed in account does not match settings account: {ChannelSession.TwitchUserNewAPI.display_name} - {ChannelSession.TwitchUserNewAPI.id} - {ChannelSession.Settings.TwitchUserID}"); GlobalEvents.ShowMessageBox("The account you are logged in as on Twitch does not match the account for this settings. Please log in as the correct account on Twitch."); ChannelSession.Settings.TwitchUserOAuthToken.accessToken = string.Empty; ChannelSession.Settings.TwitchUserOAuthToken.refreshToken = string.Empty; ChannelSession.Settings.TwitchUserOAuthToken.expiresIn = 0; return(false); } ChannelSession.Settings.Name = ChannelSession.TwitchUserNewAPI.display_name; ChannelSession.Settings.TwitchUserID = ChannelSession.TwitchUserNewAPI.id; ChannelSession.Settings.TwitchChannelID = ChannelSession.TwitchUserNewAPI.id; } catch (Exception ex) { Logger.Log(ex); Logger.Log(LogLevel.Error, "Initialize Settings - " + JSONSerializerHelper.SerializeToString(ex)); await DialogHelper.ShowMessage("Failed to initialize settings. If this continues, please visit the Mix It Up Discord for assistance." + Environment.NewLine + Environment.NewLine + "Error Details: " + ex.Message); return(false); } try { await ChannelSession.Services.Telemetry.Connect(); ChannelSession.Services.Telemetry.SetUserID(ChannelSession.Settings.TelemetryUserID); TwitchChatService twitchChatService = new TwitchChatService(); TwitchEventService twitchEventService = new TwitchEventService(); List <Task <Result> > twitchPlatformServiceTasks = new List <Task <Result> >(); twitchPlatformServiceTasks.Add(twitchChatService.ConnectUser()); twitchPlatformServiceTasks.Add(twitchEventService.Connect()); await Task.WhenAll(twitchPlatformServiceTasks); if (twitchPlatformServiceTasks.Any(c => !c.Result.Success)) { string errors = string.Join(Environment.NewLine, twitchPlatformServiceTasks.Where(c => !c.Result.Success).Select(c => c.Result.Message)); GlobalEvents.ShowMessageBox("Failed to connect to Twitch services:" + Environment.NewLine + Environment.NewLine + errors); return(false); } await ChannelSession.Services.Chat.Initialize(twitchChatService); await ChannelSession.Services.Events.Initialize(twitchEventService); } catch (Exception ex) { Logger.Log(ex); Logger.Log(LogLevel.Error, "Twitch Services - " + JSONSerializerHelper.SerializeToString(ex)); await DialogHelper.ShowMessage("Failed to connect to Twitch services. If this continues, please visit the Mix It Up Discord for assistance." + Environment.NewLine + Environment.NewLine + "Error Details: " + ex.Message); return(false); } if (ChannelSession.IsStreamer) { Result result = await ChannelSession.InitializeBotInternal(); if (!result.Success) { await DialogHelper.ShowMessage("Failed to initialize Bot account"); return(false); } try { // Connect External Services Dictionary <IExternalService, OAuthTokenModel> externalServiceToConnect = new Dictionary <IExternalService, OAuthTokenModel>(); if (ChannelSession.Settings.StreamlabsOAuthToken != null) { externalServiceToConnect[ChannelSession.Services.Streamlabs] = ChannelSession.Settings.StreamlabsOAuthToken; } if (ChannelSession.Settings.StreamElementsOAuthToken != null) { externalServiceToConnect[ChannelSession.Services.StreamElements] = ChannelSession.Settings.StreamElementsOAuthToken; } if (ChannelSession.Settings.StreamJarOAuthToken != null) { externalServiceToConnect[ChannelSession.Services.StreamJar] = ChannelSession.Settings.StreamJarOAuthToken; } if (ChannelSession.Settings.TipeeeStreamOAuthToken != null) { externalServiceToConnect[ChannelSession.Services.TipeeeStream] = ChannelSession.Settings.TipeeeStreamOAuthToken; } if (ChannelSession.Settings.TreatStreamOAuthToken != null) { externalServiceToConnect[ChannelSession.Services.TreatStream] = ChannelSession.Settings.TreatStreamOAuthToken; } if (ChannelSession.Settings.StreamlootsOAuthToken != null) { externalServiceToConnect[ChannelSession.Services.Streamloots] = ChannelSession.Settings.StreamlootsOAuthToken; } if (ChannelSession.Settings.TiltifyOAuthToken != null) { externalServiceToConnect[ChannelSession.Services.Tiltify] = ChannelSession.Settings.TiltifyOAuthToken; } if (ChannelSession.Settings.JustGivingOAuthToken != null) { externalServiceToConnect[ChannelSession.Services.JustGiving] = ChannelSession.Settings.JustGivingOAuthToken; } if (ChannelSession.Settings.IFTTTOAuthToken != null) { externalServiceToConnect[ChannelSession.Services.IFTTT] = ChannelSession.Settings.IFTTTOAuthToken; } if (ChannelSession.Settings.ExtraLifeTeamID > 0) { externalServiceToConnect[ChannelSession.Services.ExtraLife] = new OAuthTokenModel(); } if (ChannelSession.Settings.PatreonOAuthToken != null) { externalServiceToConnect[ChannelSession.Services.Patreon] = ChannelSession.Settings.PatreonOAuthToken; } if (ChannelSession.Settings.DiscordOAuthToken != null) { externalServiceToConnect[ChannelSession.Services.Discord] = ChannelSession.Settings.DiscordOAuthToken; } if (ChannelSession.Settings.TwitterOAuthToken != null) { externalServiceToConnect[ChannelSession.Services.Twitter] = ChannelSession.Settings.TwitterOAuthToken; } if (ChannelSession.Services.OBSStudio.IsEnabled) { externalServiceToConnect[ChannelSession.Services.OBSStudio] = null; } if (ChannelSession.Services.StreamlabsOBS.IsEnabled) { externalServiceToConnect[ChannelSession.Services.StreamlabsOBS] = null; } if (ChannelSession.Services.XSplit.IsEnabled) { externalServiceToConnect[ChannelSession.Services.XSplit] = null; } if (!string.IsNullOrEmpty(ChannelSession.Settings.OvrStreamServerIP)) { externalServiceToConnect[ChannelSession.Services.OvrStream] = null; } if (ChannelSession.Settings.EnableOverlay) { externalServiceToConnect[ChannelSession.Services.Overlay] = null; } if (ChannelSession.Settings.EnableDeveloperAPI) { externalServiceToConnect[ChannelSession.Services.DeveloperAPI] = null; } if (externalServiceToConnect.Count > 0) { Dictionary <IExternalService, Task <Result> > externalServiceTasks = new Dictionary <IExternalService, Task <Result> >(); foreach (var kvp in externalServiceToConnect) { Logger.Log(LogLevel.Debug, "Trying automatic OAuth service connection: " + kvp.Key.Name); try { if (kvp.Key is IOAuthExternalService && kvp.Value != null) { externalServiceTasks[kvp.Key] = ((IOAuthExternalService)kvp.Key).Connect(kvp.Value); } else { externalServiceTasks[kvp.Key] = kvp.Key.Connect(); } } catch (Exception sex) { Logger.Log(LogLevel.Error, "Error in external service initial connection: " + kvp.Key.Name); Logger.Log(sex); } } try { await Task.WhenAll(externalServiceTasks.Values); } catch (Exception sex) { Logger.Log(LogLevel.Error, "Error in batch external service connection"); Logger.Log(sex); } List <IExternalService> failedServices = new List <IExternalService>(); foreach (var kvp in externalServiceTasks) { try { if (kvp.Value.Result != null && !kvp.Value.Result.Success && kvp.Key is IOAuthExternalService) { Logger.Log(LogLevel.Debug, "Automatic OAuth token connection failed, trying manual connection: " + kvp.Key.Name); result = await kvp.Key.Connect(); if (!result.Success) { failedServices.Add(kvp.Key); } } } catch (Exception sex) { Logger.Log(LogLevel.Error, "Error in external service failed re-connection: " + kvp.Key.Name); Logger.Log(sex); failedServices.Add(kvp.Key); } } if (failedServices.Count > 0) { Logger.Log(LogLevel.Debug, "Connection failed for services: " + string.Join(", ", failedServices.Select(s => s.Name))); StringBuilder message = new StringBuilder(); message.AppendLine("The following services could not be connected:"); message.AppendLine(); foreach (IExternalService service in failedServices) { message.AppendLine(" - " + service.Name); } message.AppendLine(); message.Append("Please go to the Services page to reconnect them manually."); await DialogHelper.ShowMessage(message.ToString()); } } } catch (Exception ex) { Logger.Log(ex); Logger.Log(LogLevel.Error, "External Services - " + JSONSerializerHelper.SerializeToString(ex)); await DialogHelper.ShowMessage("Failed to initialize external services. If this continues, please visit the Mix It Up Discord for assistance." + Environment.NewLine + Environment.NewLine + "Error Details: " + ex.Message); return(false); } try { //if (ChannelSession.Settings.RemoteHostConnection != null) //{ // await ChannelSession.Services.RemoteService.InitializeConnection(ChannelSession.Settings.RemoteHostConnection); //} foreach (CurrencyModel currency in ChannelSession.Settings.Currency.Values) { if (currency.ShouldBeReset()) { await currency.Reset(); } } if (ChannelSession.Settings.ModerationResetStrikesOnLaunch) { foreach (UserDataModel userData in ChannelSession.Settings.UserData.Values) { if (userData.ModerationStrikes > 0) { userData.ModerationStrikes = 0; ChannelSession.Settings.UserData.ManualValueChanged(userData.ID); } } } ChannelSession.PreMadeChatCommands.Clear(); foreach (PreMadeChatCommand command in ReflectionHelper.CreateInstancesOfImplementingType <PreMadeChatCommand>()) { #pragma warning disable CS0612 // Type or member is obsolete if (!(command is ObsoletePreMadeCommand)) { ChannelSession.PreMadeChatCommands.Add(command); } #pragma warning restore CS0612 // Type or member is obsolete } foreach (PreMadeChatCommandSettings commandSetting in ChannelSession.Settings.PreMadeChatCommandSettings) { PreMadeChatCommand command = ChannelSession.PreMadeChatCommands.FirstOrDefault(c => c.Name.Equals(commandSetting.Name)); if (command != null) { command.UpdateFromSettings(commandSetting); } } ChannelSession.Services.Chat.RebuildCommandTriggers(); ChannelSession.Services.TimerService.Initialize(); await ChannelSession.Services.Moderation.Initialize(); } catch (Exception ex) { Logger.Log(ex); Logger.Log(LogLevel.Error, "Streamer Services - " + JSONSerializerHelper.SerializeToString(ex)); await DialogHelper.ShowMessage("Failed to initialize streamer-based services. If this continues, please visit the Mix It Up Discord for assistance." + Environment.NewLine + Environment.NewLine + "Error Details: " + ex.Message); return(false); } } try { ChannelSession.Services.Statistics.Initialize(); ChannelSession.Services.InputService.HotKeyPressed += InputService_HotKeyPressed; foreach (RedemptionStoreProductModel product in ChannelSession.Settings.RedemptionStoreProducts.Values) { product.ReplenishAmount(); } foreach (RedemptionStorePurchaseModel purchase in ChannelSession.Settings.RedemptionStorePurchases.ToList()) { if (purchase.State != RedemptionStorePurchaseRedemptionState.ManualRedeemNeeded) { ChannelSession.Settings.RedemptionStorePurchases.Remove(purchase); } } ChannelSession.Services.Telemetry.TrackLogin(ChannelSession.Settings.TelemetryUserID, ChannelSession.TwitchUserNewAPI?.broadcaster_type); await ChannelSession.SaveSettings(); await ChannelSession.Services.Settings.SaveLocalBackup(ChannelSession.Settings); await ChannelSession.Services.Settings.PerformAutomaticBackupIfApplicable(ChannelSession.Settings); AsyncRunner.RunBackgroundTask(sessionBackgroundCancellationTokenSource.Token, 60000, SessionBackgroundTask); } catch (Exception ex) { Logger.Log(ex); Logger.Log(LogLevel.Error, "Finalize Initialization - " + JSONSerializerHelper.SerializeToString(ex)); await DialogHelper.ShowMessage("Failed to finalize initialization. If this continues, please visit the Mix It Up Discord for assistance." + Environment.NewLine + Environment.NewLine + "Error Details: " + ex.Message); return(false); } return(true); } } catch (Exception ex) { Logger.Log(ex); Logger.Log(LogLevel.Error, "Channel Information - " + JSONSerializerHelper.SerializeToString(ex)); await DialogHelper.ShowMessage("Failed to get channel information. If this continues, please visit the Mix It Up Discord for assistance." + Environment.NewLine + Environment.NewLine + "Error Details: " + ex.Message); } return(false); }