/// <summary> /// Greet a user (new or returning) with a welcome message and a "thank-you" deposit of stream currency /// </summary> ///<param name="chatter"></param> private async Task GreetUserAsync(TwitchChatter chatter) { try { if (!_greetedUsers.Any(u => u == chatter.Username) && chatter.Username != _botConfig.Broadcaster.ToLower() && chatter.Message.Length > 1 && TwitchStreamStatus.IsLive) { // check if user has a stream currency account int funds = await _bank.CheckBalanceAsync(chatter.Username, _broadcasterInstance.DatabaseId); int greetedDeposit = 500; // ToDo: Make greeted deposit config setting if (funds > -1 || chatter.Badges.Contains("moderator") || chatter.Badges.Contains("vip") || chatter.Badges.Contains("bits")) { int currentExp = await _follower.CurrentExpAsync(chatter.Username, _broadcasterInstance.DatabaseId); IEnumerable <Rank> rankList = await _follower.GetRankListAsync(_broadcasterInstance.DatabaseId); Rank rank = _follower.GetCurrentRank(rankList, currentExp); string rankName = ""; if (rank != null) { rankName = rank.Name; } funds += greetedDeposit; // deposit stream currency await _bank.UpdateFundsAsync(chatter.Username, _broadcasterInstance.DatabaseId, funds); _irc.SendPublicChatMessage($"Welcome back {rankName} @{chatter.DisplayName} ! " + $"Let me reward your return with {greetedDeposit} {_botConfig.CurrencyType}"); } else { await _bank.CreateAccountAsync(chatter.Username, _broadcasterInstance.DatabaseId, greetedDeposit); _irc.SendPublicChatMessage($"Welcome to the channel @{chatter.DisplayName} ! Thanks for saying something! " + $"Let me show you my appreciation with {greetedDeposit} {_botConfig.CurrencyType}"); } _greetedUsers.Add(chatter.Username); // make sure user doesn't get greeted again as long as this bot is alive } } catch (Exception ex) { await _errHndlrInstance.LogError(ex, "TwitchBotApplication", "GreetUser(TwitchChatter)", false); } }
private async Task ConsumeAsync() { BankHeistLevel heistLevel = _heistSettings.Levels[HeistLevel() - 1]; BankHeistPayout payout = _heistSettings.Payouts[HeistLevel() - 1]; _irc.SendPublicChatMessage(_heistSettings.GameStart .Replace("@bankname@", heistLevel.LevelBankName)); Thread.Sleep(5000); // wait in anticipation Random rnd = new Random(); int chance = rnd.Next(1, 101); // 1 - 100 if (chance >= payout.SuccessRate) // failed { if (_heistSettings.Robbers.Count == 1) { _irc.SendPublicChatMessage(_heistSettings.SingleUserFail .Replace("user@", _heistSettings.Robbers.First().Username) .Replace("@bankname@", heistLevel.LevelBankName)); } else { _irc.SendPublicChatMessage(_heistSettings.Success0); } return; } int numWinners = (int)Math.Ceiling(_heistSettings.Robbers.Count * (payout.SuccessRate / 100)); IEnumerable <BankRobber> winners = _heistSettings.Robbers.OrderBy(x => rnd.Next()).Take(numWinners); foreach (BankRobber winner in winners) { int funds = await _bank.CheckBalanceAsync(winner.Username.ToLower(), _broadcasterId); decimal earnings = Math.Ceiling(winner.Gamble * payout.WinMultiplier); await _bank.UpdateFundsAsync(winner.Username.ToLower(), _broadcasterId, (int)earnings + funds); _resultMessage += $" {winner.Username} ({(int)earnings} {_botConfig.CurrencyType}),"; } // remove extra "," _resultMessage = _resultMessage.Remove(_resultMessage.LastIndexOf(','), 1); decimal numWinnersPercentage = numWinners / (decimal)_heistSettings.Robbers.Count; // display success outcome if (winners.Count() == 1 && numWinners == _heistSettings.Robbers.Count) { BankRobber onlyWinner = winners.First(); int earnings = (int)Math.Ceiling(onlyWinner.Gamble * payout.WinMultiplier); _irc.SendPublicChatMessage(_heistSettings.SingleUserSuccess .Replace("user@", onlyWinner.Username) .Replace("@bankname@", heistLevel.LevelBankName) .Replace("@winamount@", earnings.ToString()) .Replace("@pointsname@", _botConfig.CurrencyType)); } else if (numWinners == _heistSettings.Robbers.Count) { _irc.SendPublicChatMessage(_heistSettings.Success100 + " " + _resultMessage); } else if (numWinnersPercentage >= 0.34m) { _irc.SendPublicChatMessage(_heistSettings.Success34 + " " + _resultMessage); } else if (numWinnersPercentage > 0) { _irc.SendPublicChatMessage(_heistSettings.Success1 + " " + _resultMessage); } // show in case Twitch deletes the message because of exceeding character length Console.WriteLine("\n" + _resultMessage + "\n"); }
private async Task CheckFollowerAsync(string chatter, string userTwitchId) { try { TwitchChatter follower = await GetTwitchFollowerInfoAsync(chatter, userTwitchId); if (follower == null) { return; } /* Manage follower experience */ int currentExp = await _follower.CurrentExpAsync(chatter, _broadcasterId); if (TwitchStreamStatus.IsLive) { if (currentExp > -1) { await _follower.UpdateExpAsync(chatter, _broadcasterId, ++currentExp); } else { // add new user to the ranks await _follower.EnlistRecruitAsync(chatter, _broadcasterId); } } // check if follower has a stream currency account int setIncrementFunds = 10; // default to normal follower amount if (_follower.IsRegularFollower(currentExp, _botConfig.RegularFollowerHours)) { setIncrementFunds = 15; if (!_twitchChatterListInstance.TwitchRegularFollowers.Any(c => c.Username == chatter)) { _twitchChatterListInstance.TwitchRegularFollowers.Add(follower); } } /* Manage follower streaming currency */ if (TwitchStreamStatus.IsLive) { int funds = await _bank.CheckBalanceAsync(chatter, _broadcasterId); if (funds > -1) { funds += setIncrementFunds; await _bank.UpdateFundsAsync(chatter, _broadcasterId, funds); } else // ToDo: Make currency auto-increment setting { await _bank.CreateAccountAsync(chatter, _broadcasterId, setIncrementFunds); } } } catch (Exception ex) { Console.WriteLine($"Error inside FollowerSubscriberListener.CheckFollower(string, string): {ex.Message}"); if (ex.InnerException != null) { Console.WriteLine($"Inner Exception: {ex.InnerException.Message}"); } } }
/// <summary> /// Play a friendly game of Russian Roulette and risk chat privileges for stream currency /// </summary> /// <param name="chatter">User that sent the message</param> public async Task <DateTime> RussianRoulette(TwitchChatter chatter) { try { RouletteUser rouletteUser = _rouletteSingleton.RouletteUsers.FirstOrDefault(u => u.Username == chatter.Username); Random rnd = new Random(DateTime.Now.Millisecond); int bullet = rnd.Next(6); // between 0 and 5 if (bullet == 0) // user was shot { if (rouletteUser != null) { _rouletteSingleton.RouletteUsers.Remove(rouletteUser); } if (_botConfig.Broadcaster.ToLower() == chatter.Username || chatter.Badges.Contains("moderator")) { _irc.SendPublicChatMessage($"Enjoy your 15 minutes without russian roulette @{chatter.DisplayName}"); return(DateTime.Now.AddMinutes(15)); } _irc.SendChatTimeout(chatter.Username, 300); // 5 minute timeout _irc.SendPublicChatMessage($"You are dead @{chatter.DisplayName}. Enjoy your 5 minutes in limbo (cannot talk)"); return(DateTime.Now.AddMinutes(5)); } if (rouletteUser == null) // new roulette user { rouletteUser = new RouletteUser() { Username = chatter.Username, ShotsTaken = 1 }; _rouletteSingleton.RouletteUsers.Add(rouletteUser); _irc.SendPublicChatMessage($"@{chatter.DisplayName} -> 1/6 attempts...good luck Kappa"); } else // existing roulette user { if (rouletteUser.ShotsTaken < 6) { foreach (RouletteUser user in _rouletteSingleton.RouletteUsers) { if (user.Username == chatter.Username) { user.ShotsTaken++; break; } } } if (rouletteUser.ShotsTaken == 6) { int funds = await _bank.CheckBalanceAsync(chatter.Username, _broadcasterInstance.DatabaseId); int reward = 3000; // ToDo: Make roulette reward deposit config setting if (funds > -1) { funds += reward; // deposit 500 stream currency await _bank.UpdateFundsAsync(chatter.Username, _broadcasterInstance.DatabaseId, funds); } else { await _bank.CreateAccountAsync(chatter.Username, _broadcasterInstance.DatabaseId, reward); } _rouletteSingleton.RouletteUsers.RemoveAll(u => u.Username == chatter.Username); _irc.SendPublicChatMessage($"Congrats on surviving russian roulette. Here's {reward} {_botConfig.CurrencyType}!"); return(DateTime.Now.AddMinutes(5)); } } } catch (Exception ex) { await _errHndlrInstance.LogError(ex, "MinigameFeature", "RussianRoulette(TwitchChatter)", false, "!roulette"); } return(DateTime.Now); }
private async Task ConsumeAsync() { Boss boss = _bossSettings.Bosses[BossLevel() - 1]; _irc.SendPublicChatMessage(_bossSettings.GameStart .Replace("@bossname@", boss.Name)); Thread.Sleep(5000); // wait in anticipation // Raid the boss bool isBossAlive = true; string lastAttackFighter = ""; int turn; for (turn = 0; turn < boss.TurnLimit; turn++) { foreach (BossFighter fighter in _bossSettings.Fighters) { if (fighter.FighterClass.Health <= 0) { continue; } Random rnd = new Random(DateTime.Now.Millisecond); int chance = rnd.Next(1, 101); // 1 - 100 // check if boss dodged the attack if (boss.Evasion <= chance && fighter.FighterClass.Attack - boss.Defense > 0) { boss.Health -= fighter.FighterClass.Attack - boss.Defense; } if (boss.Health <= 0) { lastAttackFighter = fighter.Username; isBossAlive = false; break; } rnd = new Random(DateTime.Now.Millisecond); chance = rnd.Next(1, 101); // 1 - 100 // check if fighter dodged the attack if (fighter.FighterClass.Evasion <= chance && boss.Attack - fighter.FighterClass.Defense > 0) { fighter.FighterClass.Health -= boss.Attack - fighter.FighterClass.Defense; } } if (!isBossAlive) { break; } } // Evaluate the fight if (isBossAlive) { string bossAliveMessage = ""; if (turn == boss.TurnLimit) { // ToDo: Add boss alive message to database bossAliveMessage = $"It took too long to kill {boss.Name}. Gas floods the room, killing the entire raid party."; } else if (_bossSettings.Fighters.Count == 1) { bossAliveMessage = _bossSettings.SingleUserFail .Replace("user@", _bossSettings.Fighters.First().Username) .Replace("@bossname@", boss.Name); } else { bossAliveMessage = _bossSettings.Success0; } _irc.SendPublicChatMessage(bossAliveMessage); return; } // Calculate surviving raid party earnings IEnumerable <BossFighter> survivors = _bossSettings.Fighters.Where(f => f.FighterClass.Health > 0); int numSurvivors = survivors.Count(); foreach (BossFighter champion in survivors) { int funds = await _bank.CheckBalanceAsync(champion.Username.ToLower(), _broadcasterId); decimal earnings = Math.Ceiling(boss.Loot / (decimal)numSurvivors); // give last attack bonus to specified fighter if (champion.Username == lastAttackFighter) { earnings += boss.LastAttackBonus; } await _bank.UpdateFundsAsync(champion.Username.ToLower(), _broadcasterId, (int)earnings + funds); _resultMessage += $" {champion.Username} ({(int)earnings} {_botConfig.CurrencyType}),"; } // remove extra "," _resultMessage = _resultMessage.Remove(_resultMessage.LastIndexOf(','), 1); decimal survivorsPercentage = numSurvivors / (decimal)_bossSettings.Fighters.Count; // Display success outcome if (numSurvivors == 1 && numSurvivors == _bossSettings.Fighters.Count) { BossFighter onlyWinner = _bossSettings.Fighters.First(); int earnings = boss.Loot; _irc.SendPublicChatMessage(_bossSettings.SingleUserSuccess .Replace("user@", onlyWinner.Username) .Replace("@bossname@", boss.Name) .Replace("@winamount@", earnings.ToString()) .Replace("@pointsname@", _botConfig.CurrencyType) .Replace("@lastattackbonus@", boss.LastAttackBonus.ToString())); } else if (survivorsPercentage == 1.0m) { _irc.SendPublicChatMessage(_bossSettings.Success100.Replace("@bossname@", boss.Name) + " " + _resultMessage); } else if (survivorsPercentage >= 0.34m) { _irc.SendPublicChatMessage(_bossSettings.Success34 + " " + _resultMessage); } else if (survivorsPercentage > 0) { _irc.SendPublicChatMessage(_bossSettings.Success1 + " " + _resultMessage); } // show in case Twitch deletes the message because of exceeding character length Console.WriteLine("\n" + _resultMessage + "\n"); }
/// <summary> /// Takes money away from a user /// </summary> /// <param name="chatter"></param> private async Task <DateTime> ChargeAsync(TwitchChatter chatter) { try { if (chatter.Message.StartsWith("!charge @", StringComparison.CurrentCultureIgnoreCase)) { _irc.SendPublicChatMessage($"Please enter a valid amount @{chatter.DisplayName}"); } else { int indexAction = chatter.Message.IndexOf(" "); int fee = -1; bool isValidFee = int.TryParse(chatter.Message.Substring(indexAction, chatter.Message.IndexOf("@") - indexAction - 1), out fee); string recipient = chatter.Message.Substring(chatter.Message.IndexOf("@") + 1).ToLower(); int wallet = await _bank.CheckBalanceAsync(recipient, _broadcasterInstance.DatabaseId); // Check user's bank account exist or has currency if (wallet == -1) { _irc.SendPublicChatMessage($"{recipient} is not currently banking with us @{chatter.DisplayName}"); } else if (wallet == 0) { _irc.SendPublicChatMessage($"{recipient} is out of {_botConfig.CurrencyType} @{chatter.DisplayName}"); } // Check if fee can be accepted else if (fee > 0) { _irc.SendPublicChatMessage("Please insert a negative whole amount (no decimal numbers) " + $" or use the !deposit command to add {_botConfig.CurrencyType} to a user's account"); } else if (!isValidFee) { _irc.SendPublicChatMessage($"The fee wasn't accepted. Please try again with negative whole amount (no decimals) @{chatter.DisplayName}"); } else if (chatter.Username != _botConfig.Broadcaster.ToLower() && _twitchChatterListInstance.GetUserChatterType(recipient) == ChatterType.Moderator) { _irc.SendPublicChatMessage($"Entire deposit voided. You cannot remove {_botConfig.CurrencyType} from another moderator's account @{chatter.DisplayName}"); } else /* Deduct funds from wallet */ { wallet += fee; // Zero out account balance if user is being charged more than they have if (wallet < 0) { wallet = 0; } await _bank.UpdateFundsAsync(recipient, _broadcasterInstance.DatabaseId, wallet); // Prompt user's balance if (wallet == 0) { _irc.SendPublicChatMessage($"Charged {fee.ToString().Replace("-", "")} {_botConfig.CurrencyType} to {recipient}" + $"'s account! They are out of {_botConfig.CurrencyType} to spend"); } else { _irc.SendPublicChatMessage($"Charged {fee.ToString().Replace("-", "")} {_botConfig.CurrencyType} to {recipient}" + $"'s account! They only have {wallet} {_botConfig.CurrencyType} to spend"); } } } } catch (Exception ex) { await _errHndlrInstance.LogError(ex, "BankFeature", "Charge(TwitchChatter)", false, "!charge"); } return(DateTime.Now); }