Removed module projects because it can't work like that atm. Commented out package commands.
This commit is contained in:
		| @@ -0,0 +1,161 @@ | ||||
| using NadekoBot.Common; | ||||
| using NadekoBot.Extensions; | ||||
| using NadekoBot.Modules.Gambling.Common.AnimalRacing.Exceptions; | ||||
| using NadekoBot.Core.Services; | ||||
| using NadekoBot.Core.Services.Database.Models; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | ||||
| using System.Linq; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace NadekoBot.Modules.Gambling.Common.AnimalRacing | ||||
| { | ||||
|     public class AnimalRace : IDisposable | ||||
|     { | ||||
|         public enum Phase | ||||
|         { | ||||
|             WaitingForPlayers, | ||||
|             Running, | ||||
|             Ended, | ||||
|         } | ||||
|  | ||||
|         private const int _startingDelayMiliseconds = 20_000; | ||||
|  | ||||
|         public Phase CurrentPhase = Phase.WaitingForPlayers; | ||||
|  | ||||
|         public event Func<AnimalRace, Task> OnStarted = delegate { return Task.CompletedTask; }; | ||||
|         public event Func<AnimalRace, Task> OnStartingFailed = delegate { return Task.CompletedTask; }; | ||||
|         public event Func<AnimalRace, Task> OnStateUpdate = delegate { return Task.CompletedTask; }; | ||||
|         public event Func<AnimalRace, Task> OnEnded = delegate { return Task.CompletedTask; }; | ||||
|  | ||||
|         public ImmutableArray<AnimalRacingUser> Users => _users.ToImmutableArray(); | ||||
|         public List<AnimalRacingUser> FinishedUsers { get; } = new List<AnimalRacingUser>(); | ||||
|  | ||||
|         private readonly SemaphoreSlim _locker = new SemaphoreSlim(1, 1); | ||||
|         private readonly HashSet<AnimalRacingUser> _users = new HashSet<AnimalRacingUser>(); | ||||
|         private readonly CurrencyService _currency; | ||||
|         private readonly Queue<RaceAnimal> _animalsQueue; | ||||
|         public int MaxUsers { get; } | ||||
|  | ||||
|         public AnimalRace(CurrencyService currency, RaceAnimal[] availableAnimals) | ||||
|         { | ||||
|             this._currency = currency; | ||||
|             this._animalsQueue = new Queue<RaceAnimal>(availableAnimals); | ||||
|             this.MaxUsers = availableAnimals.Length; | ||||
|  | ||||
|             if (this._animalsQueue.Count == 0) | ||||
|                 CurrentPhase = Phase.Ended; | ||||
|         } | ||||
|  | ||||
|         public void Initialize() //lame name | ||||
|         { | ||||
|             var _t = Task.Run(async () => | ||||
|             { | ||||
|                 await Task.Delay(_startingDelayMiliseconds).ConfigureAwait(false); | ||||
|  | ||||
|                 await _locker.WaitAsync().ConfigureAwait(false); | ||||
|                 try | ||||
|                 { | ||||
|                     if (CurrentPhase != Phase.WaitingForPlayers) | ||||
|                         return; | ||||
|  | ||||
|                     await Start().ConfigureAwait(false); | ||||
|                 } | ||||
|                 finally { _locker.Release(); } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         public async Task<AnimalRacingUser> JoinRace(ulong userId, string userName, int bet = 0) | ||||
|         { | ||||
|             if (bet < 0) | ||||
|                 throw new ArgumentOutOfRangeException(nameof(bet)); | ||||
|  | ||||
|             var user = new AnimalRacingUser(userName, userId, bet); | ||||
|  | ||||
|             await _locker.WaitAsync().ConfigureAwait(false); | ||||
|             try | ||||
|             { | ||||
|                 if (_users.Count == MaxUsers) | ||||
|                     throw new AnimalRaceFullException(); | ||||
|  | ||||
|                 if (CurrentPhase != Phase.WaitingForPlayers) | ||||
|                     throw new AlreadyStartedException(); | ||||
|  | ||||
|                 if (!await _currency.RemoveAsync(userId, "BetRace", bet).ConfigureAwait(false)) | ||||
|                     throw new NotEnoughFundsException(); | ||||
|  | ||||
|                 if (_users.Contains(user)) | ||||
|                     throw new AlreadyJoinedException(); | ||||
|  | ||||
|                 var animal = _animalsQueue.Dequeue(); | ||||
|                 user.Animal = animal; | ||||
|                 _users.Add(user); | ||||
|                  | ||||
|                 if (_animalsQueue.Count == 0) //start if no more spots left | ||||
|                     await Start().ConfigureAwait(false); | ||||
|  | ||||
|                 return user; | ||||
|             } | ||||
|             finally { _locker.Release(); } | ||||
|         } | ||||
|  | ||||
|         private async Task Start() | ||||
|         { | ||||
|             CurrentPhase = Phase.Running; | ||||
|             if (_users.Count <= 1) | ||||
|             { | ||||
|                 foreach (var user in _users) | ||||
|                 { | ||||
|                     if(user.Bet > 0) | ||||
|                         await _currency.AddAsync(user.UserId, "Race refund", user.Bet).ConfigureAwait(false); | ||||
|                 } | ||||
|                  | ||||
|                 var _sf = OnStartingFailed?.Invoke(this); | ||||
|                 CurrentPhase = Phase.Ended; | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             var _ = OnStarted?.Invoke(this); | ||||
|             var _t = Task.Run(async () => | ||||
|             { | ||||
|                 var rng = new NadekoRandom(); | ||||
|                 while (!_users.All(x => x.Progress >= 60)) | ||||
|                 { | ||||
|                     foreach (var user in _users) | ||||
|                     { | ||||
|                         user.Progress += rng.Next(1, 11); | ||||
|                         if (user.Progress >= 60) | ||||
|                             user.Progress = 60; | ||||
|                     } | ||||
|  | ||||
|                     var finished = _users.Where(x => x.Progress >= 60 && !FinishedUsers.Contains(x)) | ||||
|                         .Shuffle(); | ||||
|  | ||||
|                     FinishedUsers.AddRange(finished); | ||||
|  | ||||
|                     var _ignore = OnStateUpdate?.Invoke(this); | ||||
|                     await Task.Delay(2500).ConfigureAwait(false); | ||||
|                 } | ||||
|  | ||||
|                 if (FinishedUsers[0].Bet > 0) | ||||
|                     await _currency.AddAsync(FinishedUsers[0].UserId, "Won a Race", FinishedUsers[0].Bet * (_users.Count - 1)) | ||||
|                         .ConfigureAwait(false); | ||||
|  | ||||
|                 var _ended = OnEnded?.Invoke(this); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         public void Dispose() | ||||
|         { | ||||
|             CurrentPhase = Phase.Ended; | ||||
|             OnStarted = null; | ||||
|             OnEnded = null; | ||||
|             OnStartingFailed = null; | ||||
|             OnStateUpdate = null; | ||||
|             _locker.Dispose(); | ||||
|             _users.Clear(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,32 @@ | ||||
| using NadekoBot.Core.Services.Database.Models; | ||||
|  | ||||
| namespace NadekoBot.Modules.Gambling.Common.AnimalRacing | ||||
| { | ||||
|     public class AnimalRacingUser | ||||
|     { | ||||
|         public int Bet { get; } | ||||
|         public string Username { get; } | ||||
|         public ulong UserId { get; } | ||||
|         public RaceAnimal Animal { get; set; } | ||||
|         public int Progress { get; set; } | ||||
|  | ||||
|         public AnimalRacingUser(string username, ulong userId, int bet) | ||||
|         { | ||||
|             this.Bet = bet; | ||||
|             this.Username = username; | ||||
|             this.UserId = userId; | ||||
|         } | ||||
|  | ||||
|         public override bool Equals(object obj) | ||||
|         { | ||||
|             return obj is AnimalRacingUser x | ||||
|                 ? x.UserId == this.UserId | ||||
|                 : false; | ||||
|         } | ||||
|  | ||||
|         public override int GetHashCode() | ||||
|         { | ||||
|             return this.UserId.GetHashCode(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,9 @@ | ||||
| using System; | ||||
|  | ||||
| namespace NadekoBot.Modules.Gambling.Common.AnimalRacing.Exceptions | ||||
| { | ||||
|     public class AlreadyJoinedException : Exception | ||||
|     { | ||||
|          | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,9 @@ | ||||
| using System; | ||||
|  | ||||
| namespace NadekoBot.Modules.Gambling.Common.AnimalRacing.Exceptions | ||||
| { | ||||
|     public class AlreadyStartedException : Exception | ||||
|     { | ||||
|          | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,8 @@ | ||||
| using System; | ||||
|  | ||||
| namespace NadekoBot.Modules.Gambling.Common.AnimalRacing.Exceptions | ||||
| { | ||||
|     public class AnimalRaceFullException : Exception | ||||
|     { | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,9 @@ | ||||
| using System; | ||||
|  | ||||
| namespace NadekoBot.Modules.Gambling.Common.AnimalRacing.Exceptions | ||||
| { | ||||
|     public class NotEnoughFundsException : Exception | ||||
|     { | ||||
|          | ||||
|     } | ||||
| } | ||||
							
								
								
									
										234
									
								
								NadekoBot.Core/Modules/Gambling/Common/Cards.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								NadekoBot.Core/Modules/Gambling/Common/Cards.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,234 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using NadekoBot.Common; | ||||
| using NadekoBot.Extensions; | ||||
|  | ||||
| namespace NadekoBot.Modules.Gambling.Common | ||||
| { | ||||
|     public class Cards | ||||
|     { | ||||
|         private static readonly Dictionary<int, string> cardNames = new Dictionary<int, string>() { | ||||
|         { 1, "Ace" }, | ||||
|         { 2, "Two" }, | ||||
|         { 3, "Three" }, | ||||
|         { 4, "Four" }, | ||||
|         { 5, "Five" }, | ||||
|         { 6, "Six" }, | ||||
|         { 7, "Seven" }, | ||||
|         { 8, "Eight" }, | ||||
|         { 9, "Nine" }, | ||||
|         { 10, "Ten" }, | ||||
|         { 11, "Jack" }, | ||||
|         { 12, "Queen" }, | ||||
|         { 13, "King" } | ||||
|     }; | ||||
|         private static Dictionary<string, Func<List<Card>, bool>> handValues; | ||||
|  | ||||
|  | ||||
|         public enum CardSuit | ||||
|         { | ||||
|             Spades = 1, | ||||
|             Hearts = 2, | ||||
|             Diamonds = 3, | ||||
|             Clubs = 4 | ||||
|         } | ||||
|  | ||||
|         public class Card : IComparable | ||||
|         { | ||||
|             public CardSuit Suit { get; } | ||||
|             public int Number { get; } | ||||
|  | ||||
|             public string Name | ||||
|             { | ||||
|                 get | ||||
|                 { | ||||
|                     var str = ""; | ||||
|  | ||||
|                     if (Number <= 10 && Number > 1) | ||||
|                     { | ||||
|                         str += "_" + Number; | ||||
|                     } | ||||
|                     else { | ||||
|                         str += GetName().ToLower(); | ||||
|                     } | ||||
|                     return str + "_of_" + Suit.ToString().ToLower(); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             public Card(CardSuit s, int cardNum) | ||||
|             { | ||||
|                 this.Suit = s; | ||||
|                 this.Number = cardNum; | ||||
|             } | ||||
|  | ||||
|             public string GetName() => cardNames[Number]; | ||||
|  | ||||
|             public override string ToString() => cardNames[Number] + " Of " + Suit; | ||||
|  | ||||
|             public int CompareTo(object obj) | ||||
|             { | ||||
|                 if (!(obj is Card)) return 0; | ||||
|                 var c = (Card)obj; | ||||
|                 return this.Number - c.Number; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private List<Card> cardPool; | ||||
|         public List<Card> CardPool | ||||
|         { | ||||
|             get { return cardPool; } | ||||
|             set { cardPool = value; } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Creates a new instance of the BlackJackGame, this allows you to create multiple games running at one time. | ||||
|         /// </summary> | ||||
|         public Cards() | ||||
|         { | ||||
|             cardPool = new List<Card>(52); | ||||
|             RefillPool(); | ||||
|             InitHandValues(); | ||||
|         } | ||||
|         /// <summary> | ||||
|         /// Restart the game of blackjack. It will only refill the pool for now. Probably wont be used, unless you want to have only 1 bjg running at one time, | ||||
|         /// then you will restart the same game every time. | ||||
|         /// </summary> | ||||
|         public void Restart() => RefillPool(); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Removes all cards from the pool and refills the pool with all of the possible cards. NOTE: I think this is too expensive. | ||||
|         /// We should probably make it so it copies another premade list with all the cards, or something. | ||||
|         /// </summary> | ||||
|         private void RefillPool() | ||||
|         { | ||||
|             cardPool.Clear(); | ||||
|             //foreach suit | ||||
|             for (var j = 1; j < 14; j++) | ||||
|             { | ||||
|                 // and number | ||||
|                 for (var i = 1; i < 5; i++) | ||||
|                 { | ||||
|                     //generate a card of that suit and number and add it to the pool | ||||
|  | ||||
|                     // the pool will go from ace of spades,hears,diamonds,clubs all the way to the king of spades. hearts, ... | ||||
|                     cardPool.Add(new Card((CardSuit)i, j)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         private Random r = new NadekoRandom(); | ||||
|         /// <summary> | ||||
|         /// Take a card from the pool, you either take it from the top if the deck is shuffled, or from a random place if the deck is in the default order. | ||||
|         /// </summary> | ||||
|         /// <returns>A card from the pool</returns> | ||||
|         public Card DrawACard() | ||||
|         { | ||||
|             if (CardPool.Count == 0) | ||||
|                 Restart(); | ||||
|             //you can either do this if your deck is not shuffled | ||||
|  | ||||
|             var num = r.Next(0, cardPool.Count); | ||||
|             var c = cardPool[num]; | ||||
|             cardPool.RemoveAt(num); | ||||
|             return c; | ||||
|  | ||||
|             // if you want to shuffle when you fill, then take the first one | ||||
|             /* | ||||
|             Card c = cardPool[0]; | ||||
|             cardPool.RemoveAt(0); | ||||
|             return c; | ||||
|             */ | ||||
|         } | ||||
|         /// <summary> | ||||
|         /// Shuffles the deck. Use this if you want to take cards from the top of the deck, instead of randomly. See DrawACard method. | ||||
|         /// </summary> | ||||
|         private void Shuffle() | ||||
|         { | ||||
|             if (cardPool.Count <= 1) return; | ||||
|             var orderedPool = cardPool.Shuffle(); | ||||
|             cardPool = cardPool as List<Card> ?? orderedPool.ToList(); | ||||
|         } | ||||
|         public override string ToString() => string.Concat(cardPool.Select(c => c.ToString())) + Environment.NewLine; | ||||
|  | ||||
|         private static void InitHandValues() | ||||
|         { | ||||
|             Func<List<Card>, bool> hasPair = | ||||
|                                   cards => cards.GroupBy(card => card.Number) | ||||
|                                                 .Count(group => group.Count() == 2) == 1; | ||||
|             Func<List<Card>, bool> isPair = | ||||
|                                   cards => cards.GroupBy(card => card.Number) | ||||
|                                                 .Count(group => group.Count() == 3) == 0 | ||||
|                                            && hasPair(cards); | ||||
|  | ||||
|             Func<List<Card>, bool> isTwoPair = | ||||
|                                   cards => cards.GroupBy(card => card.Number) | ||||
|                                                 .Count(group => group.Count() == 2) == 2; | ||||
|  | ||||
|             Func<List<Card>, bool> isStraight = | ||||
|                 cards => | ||||
|                 { | ||||
|                     if (cards.GroupBy(card => card.Number).Count() != cards.Count()) | ||||
|                         return false; | ||||
|                     var toReturn = (cards.Max(card => (int)card.Number) | ||||
|                                         - cards.Min(card => (int)card.Number) == 4); | ||||
|                     if (toReturn || cards.All(c => c.Number != 1)) return toReturn; | ||||
|  | ||||
|                     var newCards = cards.Select(c => c.Number == 1 ? new Card(c.Suit, 14) : c); | ||||
|                     return (newCards.Max(card => (int)card.Number) | ||||
|                             - newCards.Min(card => (int)card.Number) == 4); | ||||
|                 }; | ||||
|  | ||||
|             Func<List<Card>, bool> hasThreeOfKind = | ||||
|                                   cards => cards.GroupBy(card => card.Number) | ||||
|                                                 .Any(group => group.Count() == 3); | ||||
|  | ||||
|             Func<List<Card>, bool> isThreeOfKind = | ||||
|                                   cards => hasThreeOfKind(cards) && !hasPair(cards); | ||||
|  | ||||
|             Func<List<Card>, bool> isFlush = | ||||
|                                   cards => cards.GroupBy(card => card.Suit).Count() == 1; | ||||
|  | ||||
|             Func<List<Card>, bool> isFourOfKind = | ||||
|                                   cards => cards.GroupBy(card => card.Number) | ||||
|                                                 .Any(group => group.Count() == 4); | ||||
|  | ||||
|             Func<List<Card>, bool> isFullHouse = | ||||
|                                   cards => hasPair(cards) && hasThreeOfKind(cards); | ||||
|  | ||||
|             Func<List<Card>, bool> hasStraightFlush = | ||||
|                                   cards => isFlush(cards) && isStraight(cards); | ||||
|  | ||||
|             Func<List<Card>, bool> isRoyalFlush = | ||||
|                                   cards => cards.Min(card => card.Number) == 1 && | ||||
|                                            cards.Max(card => card.Number) == 13 | ||||
|                                            && hasStraightFlush(cards); | ||||
|  | ||||
|             Func<List<Card>, bool> isStraightFlush = | ||||
|                                   cards => hasStraightFlush(cards) && !isRoyalFlush(cards); | ||||
|  | ||||
|             handValues = new Dictionary<string, Func<List<Card>, bool>> | ||||
|             { | ||||
|                 { "Royal Flush", isRoyalFlush }, | ||||
|                 { "Straight Flush", isStraightFlush }, | ||||
|                 { "Four Of A Kind", isFourOfKind }, | ||||
|                 { "Full House", isFullHouse }, | ||||
|                 { "Flush", isFlush }, | ||||
|                 { "Straight", isStraight }, | ||||
|                 { "Three Of A Kind", isThreeOfKind }, | ||||
|                 { "Two Pairs", isTwoPair }, | ||||
|                 { "A Pair", isPair } | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         public static string GetHandValue(List<Card> cards) | ||||
|         { | ||||
|             if (handValues == null) | ||||
|                 InitHandValues(); | ||||
|             foreach (var kvp in handValues.Where(x => x.Value(cards))) | ||||
|             { | ||||
|                 return kvp.Key; | ||||
|             } | ||||
|             return "High card " + (cards.FirstOrDefault(c => c.Number == 1)?.GetName() ?? cards.Max().GetName()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,12 @@ | ||||
| using Discord; | ||||
| using Discord.Commands; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace NadekoBot.Modules.Gambling.Common | ||||
| { | ||||
|     public abstract class CurrencyEvent | ||||
|     { | ||||
|         public abstract Task Stop(); | ||||
|         public abstract Task Start(IUserMessage msg, ICommandContext channel); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,144 @@ | ||||
| using Discord; | ||||
| using Discord.Commands; | ||||
| using Discord.WebSocket; | ||||
| using NadekoBot.Common.Collections; | ||||
| using NadekoBot.Extensions; | ||||
| using NadekoBot.Core.Services; | ||||
| using NadekoBot.Core.Services.Database.Models; | ||||
| using NLog; | ||||
| using System; | ||||
| using System.Collections.Concurrent; | ||||
| using System.Collections.Generic; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace NadekoBot.Modules.Gambling.Common | ||||
| { | ||||
|     public class ReactionEvent : CurrencyEvent | ||||
|     { | ||||
|         private readonly ConcurrentHashSet<ulong> _reactionAwardedUsers = new ConcurrentHashSet<ulong>(); | ||||
|         private readonly BotConfig _bc; | ||||
|         private readonly Logger _log; | ||||
|         private readonly DiscordSocketClient _client; | ||||
|         private readonly CurrencyService _cs; | ||||
|         private readonly SocketSelfUser _botUser; | ||||
|  | ||||
|         private IUserMessage StartingMessage { get; set; } | ||||
|  | ||||
|         private CancellationTokenSource Source { get; } | ||||
|         private CancellationToken CancelToken { get; } | ||||
|  | ||||
|         private readonly ConcurrentQueue<ulong> _toGiveTo = new ConcurrentQueue<ulong>(); | ||||
|         private readonly int _amount; | ||||
|  | ||||
|         public ReactionEvent(BotConfig bc, DiscordSocketClient client, CurrencyService cs, int amount) | ||||
|         { | ||||
|             _bc = bc; | ||||
|             _log = LogManager.GetCurrentClassLogger(); | ||||
|             _client = client; | ||||
|             _cs = cs; | ||||
|             _botUser = client.CurrentUser; | ||||
|             _amount = amount; | ||||
|             Source = new CancellationTokenSource(); | ||||
|             CancelToken = Source.Token; | ||||
|  | ||||
|             var _ = Task.Run(async () => | ||||
|             { | ||||
|                 var users = new List<ulong>(); | ||||
|                 while (!CancelToken.IsCancellationRequested) | ||||
|                 { | ||||
|                     await Task.Delay(1000).ConfigureAwait(false); | ||||
|                     while (_toGiveTo.TryDequeue(out var usrId)) | ||||
|                     { | ||||
|                         users.Add(usrId); | ||||
|                     } | ||||
|  | ||||
|                     if (users.Count > 0) | ||||
|                     { | ||||
|                         await _cs.AddToManyAsync("Reaction Event", _amount, users.ToArray()).ConfigureAwait(false); | ||||
|                     } | ||||
|  | ||||
|                     users.Clear(); | ||||
|                 } | ||||
|             }, CancelToken); | ||||
|         } | ||||
|  | ||||
|         public override async Task Stop() | ||||
|         { | ||||
|             if (StartingMessage != null) | ||||
|                 await StartingMessage.DeleteAsync().ConfigureAwait(false); | ||||
|  | ||||
|             if (!Source.IsCancellationRequested) | ||||
|                 Source.Cancel(); | ||||
|  | ||||
|             _client.MessageDeleted -= MessageDeletedEventHandler; | ||||
|         } | ||||
|  | ||||
|         private Task MessageDeletedEventHandler(Cacheable<IMessage, ulong> msg, ISocketMessageChannel channel) | ||||
|         { | ||||
|             if (StartingMessage?.Id == msg.Id) | ||||
|             { | ||||
|                 _log.Warn("Stopping flower reaction event because message is deleted."); | ||||
|                 var __ = Task.Run(Stop); | ||||
|             } | ||||
|  | ||||
|             return Task.CompletedTask; | ||||
|         } | ||||
|  | ||||
|         public override async Task Start(IUserMessage umsg, ICommandContext context) | ||||
|         { | ||||
|             StartingMessage = umsg; | ||||
|             _client.MessageDeleted += MessageDeletedEventHandler; | ||||
|  | ||||
|             IEmote iemote; | ||||
|             if (Emote.TryParse(_bc.CurrencySign, out var emote)) | ||||
|             { | ||||
|                 iemote = emote; | ||||
|             } | ||||
|             else | ||||
|                 iemote = new Emoji(_bc.CurrencySign); | ||||
|             try { await StartingMessage.AddReactionAsync(iemote).ConfigureAwait(false); } | ||||
|             catch | ||||
|             { | ||||
|                 try { await StartingMessage.AddReactionAsync(iemote).ConfigureAwait(false); } | ||||
|                 catch | ||||
|                 { | ||||
|                     try { await StartingMessage.DeleteAsync().ConfigureAwait(false); } | ||||
|                     catch { return; } | ||||
|                 } | ||||
|             } | ||||
|             using (StartingMessage.OnReaction(_client, (r) => | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     if (r.UserId == _botUser.Id) | ||||
|                         return; | ||||
|  | ||||
|                     if (r.Emote.Name == iemote.Name && r.User.IsSpecified && ((DateTime.UtcNow - r.User.Value.CreatedAt).TotalDays > 5) && _reactionAwardedUsers.Add(r.User.Value.Id)) | ||||
|                     { | ||||
|                         _toGiveTo.Enqueue(r.UserId); | ||||
|                     } | ||||
|                 } | ||||
|                 catch | ||||
|                 { | ||||
|                     // ignored | ||||
|                 } | ||||
|             })) | ||||
|             { | ||||
|                 try | ||||
|                 { | ||||
|                     await Task.Delay(TimeSpan.FromHours(24), CancelToken).ConfigureAwait(false); | ||||
|                 } | ||||
|                 catch (OperationCanceledException) | ||||
|                 { | ||||
|  | ||||
|                 } | ||||
|                 if (CancelToken.IsCancellationRequested) | ||||
|                     return; | ||||
|  | ||||
|                 _log.Warn("Stopping flower reaction event because it expired."); | ||||
|                 await Stop(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,99 @@ | ||||
| using Discord; | ||||
| using Discord.Commands; | ||||
| using Discord.WebSocket; | ||||
| using NadekoBot.Common; | ||||
| using NadekoBot.Common.Collections; | ||||
| using NadekoBot.Core.Services; | ||||
| using System; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace NadekoBot.Modules.Gambling.Common.CurrencyEvents | ||||
| { | ||||
|     public class SneakyEvent : CurrencyEvent | ||||
|     { | ||||
|         public event Action OnEnded; | ||||
|         public string Code { get; private set; } = string.Empty; | ||||
|         private readonly ConcurrentHashSet<ulong> _sneakyGameAwardedUsers = new ConcurrentHashSet<ulong>(); | ||||
|  | ||||
|         private readonly char[] _sneakyGameStatusChars = Enumerable.Range(48, 10) | ||||
|             .Concat(Enumerable.Range(65, 26)) | ||||
|             .Concat(Enumerable.Range(97, 26)) | ||||
|             .Select(x => (char)x) | ||||
|             .ToArray(); | ||||
|  | ||||
|         private readonly CurrencyService _cs; | ||||
|         private readonly DiscordSocketClient _client; | ||||
|         private readonly IBotConfigProvider _bc; | ||||
|         private readonly int _length; | ||||
|  | ||||
|         public SneakyEvent(CurrencyService cs, DiscordSocketClient client, | ||||
|             IBotConfigProvider bc, int len) | ||||
|         { | ||||
|             _cs = cs; | ||||
|             _client = client; | ||||
|             _bc = bc; | ||||
|             _length = len; | ||||
|         } | ||||
|  | ||||
|         public override async Task Start(IUserMessage msg, ICommandContext channel) | ||||
|         { | ||||
|             GenerateCode(); | ||||
|  | ||||
|             //start the event | ||||
|             _client.MessageReceived += SneakyGameMessageReceivedEventHandler; | ||||
|             await _client.SetGameAsync($"type {Code} for " + _bc.BotConfig.CurrencyPluralName) | ||||
|                 .ConfigureAwait(false); | ||||
|             await Task.Delay(_length * 1000).ConfigureAwait(false); | ||||
|             await Stop().ConfigureAwait(false); | ||||
|         } | ||||
|  | ||||
|         private void GenerateCode() | ||||
|         { | ||||
|             var rng = new NadekoRandom(); | ||||
|  | ||||
|             for (var i = 0; i < 5; i++) | ||||
|             { | ||||
|                 Code += _sneakyGameStatusChars[rng.Next(0, _sneakyGameStatusChars.Length)]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public override async Task Stop() | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 _client.MessageReceived -= SneakyGameMessageReceivedEventHandler; | ||||
|                 Code = string.Empty; | ||||
|                 _sneakyGameAwardedUsers.Clear(); | ||||
|                 await _client.SetGameAsync(null).ConfigureAwait(false); | ||||
|             } | ||||
|             catch { } | ||||
|             finally | ||||
|             { | ||||
|  | ||||
|                 OnEnded?.Invoke(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private Task SneakyGameMessageReceivedEventHandler(SocketMessage arg) | ||||
|         { | ||||
|             if (arg.Content == Code && | ||||
|                 _sneakyGameAwardedUsers.Add(arg.Author.Id)) | ||||
|             { | ||||
|                 var _ = Task.Run(async () => | ||||
|                 { | ||||
|                     await _cs.AddAsync(arg.Author, "Sneaky Game Event", 100, false) | ||||
|                         .ConfigureAwait(false); | ||||
|  | ||||
|                     try { await arg.DeleteAsync(new RequestOptions() { RetryMode = RetryMode.AlwaysFail }).ConfigureAwait(false); } | ||||
|                     catch | ||||
|                     { | ||||
|                         // ignored | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             return Task.CompletedTask; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,45 @@ | ||||
| using NadekoBot.Common; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace NadekoBot.Modules.Gambling.Common.WheelOfFortune | ||||
| { | ||||
|     public class WheelOfFortune | ||||
|     { | ||||
|         private static readonly NadekoRandom _rng = new NadekoRandom(); | ||||
|  | ||||
|         private static readonly ImmutableArray<string> _emojis = new string[] { | ||||
|             "⬆", | ||||
|             "↖", | ||||
|             "⬅", | ||||
|             "↙", | ||||
|             "⬇", | ||||
|             "↘", | ||||
|             "➡", | ||||
|             "↗" }.ToImmutableArray(); | ||||
|  | ||||
|         public static readonly ImmutableArray<float> Multipliers = new float[] { | ||||
|             1.7f, | ||||
|             1.5f, | ||||
|             0.2f, | ||||
|             0.1f, | ||||
|             0.3f, | ||||
|             0.5f, | ||||
|             1.2f, | ||||
|             2.4f, | ||||
|         }.ToImmutableArray(); | ||||
|  | ||||
|         public int Result { get; } | ||||
|         public string Emoji => _emojis[Result]; | ||||
|         public float Multiplier => Multipliers[Result]; | ||||
|  | ||||
|         public WheelOfFortune() | ||||
|         { | ||||
|             this.Result = _rng.Next(0, 8); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user