Plantpick and currency generation
This commit is contained in:
		| @@ -1,167 +1,219 @@ | ||||
| //using Discord; | ||||
| //using Discord.Commands; | ||||
| //using NadekoBot.Classes; | ||||
| //using NadekoBot.Extensions; | ||||
| //using NadekoBot.Modules.Permissions.Classes; | ||||
| //using System; | ||||
| //using System.Collections.Concurrent; | ||||
| //using System.Collections.Generic; | ||||
| //using System.IO; | ||||
| //using System.Linq; | ||||
| //using System.Security.Cryptography; | ||||
| //using System.Threading; | ||||
| //using System.Threading.Tasks; | ||||
| using Discord; | ||||
| using Discord.Commands; | ||||
| using Discord.WebSocket; | ||||
| using NadekoBot.Attributes; | ||||
| using NadekoBot.Extensions; | ||||
| using NadekoBot.Services; | ||||
| using NadekoBot.Services.Database; | ||||
| using System; | ||||
| using System.Collections.Concurrent; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Security.Cryptography; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| ////todo rewrite | ||||
| //namespace NadekoBot.Modules.Games | ||||
| //{ | ||||
| //    /// <summary> | ||||
| //    /// Flower picking/planting idea is given to me by its | ||||
| //    /// inceptor Violent Crumble from Game Developers League discord server | ||||
| //    /// (he has !cookie and !nom) Thanks a lot Violent! | ||||
| //    /// Check out GDL (its a growing gamedev community): | ||||
| //    /// https://discord.gg/0TYNJfCU4De7YIk8 | ||||
| //    /// </summary> | ||||
| //    class PlantPick : DiscordCommand | ||||
| //    { | ||||
| //todo rewrite | ||||
| namespace NadekoBot.Modules.Games | ||||
| { | ||||
|     public partial class Games | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Flower picking/planting idea is given to me by its | ||||
|         /// inceptor Violent Crumble from Game Developers League discord server | ||||
|         /// (he has !cookie and !nom) Thanks a lot Violent! | ||||
|         /// Check out GDL (its a growing gamedev community): | ||||
|         /// https://discord.gg/0TYNJfCU4De7YIk8 | ||||
|         /// </summary> | ||||
|         public class PlantPick | ||||
|         { | ||||
|  | ||||
| //        private Random rng; | ||||
| //        public PlantPick(DiscordModule module) : base(module) | ||||
| //        { | ||||
| //            NadekoBot.Client.MessageReceived += PotentialFlowerGeneration; | ||||
| //            rng = new Random(); | ||||
| //        } | ||||
|             private Random rng; | ||||
|  | ||||
| //        private static readonly ConcurrentDictionary<ulong, DateTime> plantpickCooldowns = new ConcurrentDictionary<ulong, DateTime>(); | ||||
|             private ConcurrentDictionary<ulong, bool> generationChannels = new ConcurrentDictionary<ulong, bool>(); | ||||
|             //channelid/message | ||||
|             private ConcurrentDictionary<ulong, List<IUserMessage>> plantedFlowers = new ConcurrentDictionary<ulong, List<IUserMessage>>(); | ||||
|             //channelId/last generation | ||||
|             private ConcurrentDictionary<ulong, DateTime> lastGenerations = new ConcurrentDictionary<ulong, DateTime>(); | ||||
|  | ||||
| //        private async void PotentialFlowerGeneration(object sender, Discord.MessageEventArgs e) | ||||
| //        { | ||||
| //            try | ||||
| //            { | ||||
| //                if (e.Server == null || e.Channel.IsPrivate || e.Message.IsAuthor) | ||||
| //                    return; | ||||
| //                var config = Classes.SpecificConfigurations.Default.Of(e.Server.Id); | ||||
| //                var now = DateTime.Now; | ||||
| //                int cd; | ||||
| //                DateTime lastSpawned; | ||||
| //                if (config.GenerateCurrencyChannels.TryGetValue(e.Channel.Id, out cd)) | ||||
| //                    if (!plantpickCooldowns.TryGetValue(e.Channel.Id, out lastSpawned) || (lastSpawned + new TimeSpan(0, cd, 0)) < now) | ||||
| //                    { | ||||
| //                        var rnd = Math.Abs(rng.Next(0,101)); | ||||
| //                        if (rnd == 0) | ||||
| //                        { | ||||
| //                            var msgs = new[] { await e.Channel.SendFile(GetRandomCurrencyImagePath()), await channel.SendMessageAsync($"❗ A random {Gambling.CurrencyName} appeared! Pick it up by typing `>pick`") }; | ||||
| //                            plantedFlowerChannels.AddOrUpdate(e.Channel.Id, msgs, (u, m) => { m.ForEach(async msgToDelete => { try { await msgToDelete.Delete(); } catch { } }); return msgs; }); | ||||
| //                            plantpickCooldowns.AddOrUpdate(e.Channel.Id, now, (i, d) => now); | ||||
| //                        } | ||||
| //                    } | ||||
| //            } | ||||
| //            catch { } | ||||
| //        } | ||||
| //        //channelid/messageid pair | ||||
| //        ConcurrentDictionary<ulong, IEnumerable<Message>> plantedFlowerChannels = new ConcurrentDictionary<ulong, IEnumerable<Message>>(); | ||||
|             private float chance; | ||||
|             private int cooldown; | ||||
|  | ||||
| //        private SemaphoreSlim locker = new SemaphoreSlim(1,1); | ||||
|             public PlantPick(DiscordModule module) | ||||
|             { | ||||
|                 NadekoBot.Client.MessageReceived += PotentialFlowerGeneration; | ||||
|                 rng = new Random(); | ||||
|  | ||||
| //        public override void Init(CommandGroupBuilder cgb) | ||||
| //        { | ||||
| //            cgb.CreateCommand(Module.Prefix + "pick") | ||||
| //                .Description($"Picks a flower planted in this channel. | `{Prefix}pick`") | ||||
| //                .Do(async e => | ||||
| //                { | ||||
| //                    IEnumerable<Message> msgs; | ||||
|                 using (var uow = DbHandler.UnitOfWork()) | ||||
|                 { | ||||
|                     var conf = uow.BotConfig.GetOrCreate(); | ||||
|                     var x = | ||||
|                     generationChannels = new ConcurrentDictionary<ulong, bool>(uow.GuildConfigs.GetAll() | ||||
|                         .Where(c => c.GenerateCurrencyChannelId != null) | ||||
|                         .ToDictionary(c => c.GenerateCurrencyChannelId.Value, c => true)); | ||||
|                     chance = conf.CurrencyGenerationChance; | ||||
|                     cooldown = conf.CurrencyGenerationCooldown; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
| //                    await e.Message.Delete().ConfigureAwait(false); | ||||
| //                    if (!plantedFlowerChannels.TryRemove(e.Channel.Id, out msgs)) | ||||
| //                        return; | ||||
|             private Task PotentialFlowerGeneration(IMessage imsg) | ||||
|             { | ||||
|                 var msg = imsg as IUserMessage; | ||||
|                 if (msg == null) | ||||
|                     return Task.CompletedTask; | ||||
|  | ||||
| //                    foreach(var msgToDelete in msgs) | ||||
| //                        await msgToDelete.Delete().ConfigureAwait(false); | ||||
|                 var channel = imsg.Channel as ITextChannel; | ||||
|                 if (channel == null) | ||||
|                     return Task.CompletedTask; | ||||
|  | ||||
| //                    await CurrencyHandler.AddFlowersAsync(umsg.Author, "Picked a flower.", 1, true).ConfigureAwait(false); | ||||
| //                    var msg = await channel.SendMessageAsync($"**{umsg.Author.Username}** picked a {Gambling.CurrencyName}!").ConfigureAwait(false); | ||||
| //                    ThreadPool.QueueUserWorkItem(async (state) => | ||||
| //                    { | ||||
| //                        try | ||||
| //                        { | ||||
| //                            await Task.Delay(10000).ConfigureAwait(false); | ||||
| //                            await msg.Delete().ConfigureAwait(false); | ||||
| //                        } | ||||
| //                        catch { } | ||||
| //                    }); | ||||
| //                }); | ||||
|                 bool shouldGenerate; | ||||
|                 if (!generationChannels.TryGetValue(channel.Id, out shouldGenerate) || !shouldGenerate) | ||||
|                     return Task.CompletedTask; | ||||
|  | ||||
| //            cgb.CreateCommand(Module.Prefix + "plant") | ||||
| //                .Description($"Spend a flower to plant it in this channel. (If bot is restarted or crashes, flower will be lost) | `{Prefix}plant`") | ||||
| //                .Do(async e => | ||||
| //                { | ||||
| //                    await locker.WaitAsync().ConfigureAwait(false); | ||||
| //                    try | ||||
| //                    { | ||||
| //                        if (plantedFlowerChannels.ContainsKey(e.Channel.Id)) | ||||
| //                        { | ||||
| //                            await channel.SendMessageAsync($"There is already a {Gambling.CurrencyName} in this channel.").ConfigureAwait(false); | ||||
| //                            return; | ||||
| //                        } | ||||
| //                        var removed = await CurrencyHandler.RemoveFlowers(umsg.Author, "Planted a flower.", 1, true).ConfigureAwait(false); | ||||
| //                        if (!removed) | ||||
| //                        { | ||||
| //                            await channel.SendMessageAsync($"You don't have any {Gambling.CurrencyName}s.").ConfigureAwait(false); | ||||
| //                            return; | ||||
| //                        } | ||||
|                 var t = Task.Run(async () => | ||||
|                 { | ||||
|                     var lastGeneration = lastGenerations.GetOrAdd(channel.Id, DateTime.MinValue); | ||||
|  | ||||
| //                        var file = GetRandomCurrencyImagePath(); | ||||
| //                        Message msg; | ||||
| //                        if (file == null) | ||||
| //                            msg = await channel.SendMessageAsync(Gambling.CurrencySign).ConfigureAwait(false); | ||||
| //                        else | ||||
| //                            msg = await e.Channel.SendFile(file).ConfigureAwait(false); | ||||
| //                        var vowelFirst = new[] { 'a', 'e', 'i', 'o', 'u' }.Contains(Gambling.CurrencyName[0]); | ||||
| //                        var msg2 = await channel.SendMessageAsync($"Oh how Nice! **{umsg.Author.Username}** planted {(vowelFirst ? "an" : "a")} {Gambling.CurrencyName}. Pick it using {Module.Prefix}pick").ConfigureAwait(false); | ||||
| //                        plantedFlowerChannels.TryAdd(e.Channel.Id, new[] { msg, msg2 }); | ||||
| //                    } | ||||
| //                    finally { locker.Release();  } | ||||
| //                }); | ||||
|                     if (DateTime.Now - TimeSpan.FromSeconds(cooldown) < lastGeneration) //recently generated in this channel, don't generate again | ||||
|                         return; | ||||
|  | ||||
| //            cgb.CreateCommand(Prefix + "gencurrency") | ||||
| //                .Alias(Prefix + "gc") | ||||
| //                .Description($"Toggles currency generation on this channel. Every posted message will have 2% chance to spawn a {Gambling.CurrencyName}. Optional parameter cooldown time in minutes, 5 minutes by default. Requires Manage Messages permission. | `{Prefix}gc` or `{Prefix}gc 60`") | ||||
| //                .AddCheck(SimpleCheckers.ManageMessages()) | ||||
| //                .Parameter("cd", ParameterType.Unparsed) | ||||
| //                .Do(async e => | ||||
| //                { | ||||
| //                    var cdStr = cd; | ||||
| //                    int cd = 2; | ||||
| //                    if (!int.TryParse(cdStr, out cd) || cd < 0) | ||||
| //                    { | ||||
| //                        cd = 2; | ||||
| //                    } | ||||
| //                    var config = SpecificConfigurations.Default.Of(e.Server.Id); | ||||
| //                    int throwaway; | ||||
| //                    if (config.GenerateCurrencyChannels.TryRemove(e.Channel.Id, out throwaway)) | ||||
| //                    { | ||||
| //                        await channel.SendMessageAsync("`Currency generation disabled on this channel.`").ConfigureAwait(false); | ||||
| //                    } | ||||
| //                    else | ||||
| //                    { | ||||
| //                        if (config.GenerateCurrencyChannels.TryAdd(e.Channel.Id, cd)) | ||||
| //                            await channel.SendMessageAsync($"`Currency generation enabled on this channel. Cooldown is {cd} minutes.`").ConfigureAwait(false); | ||||
| //                    } | ||||
| //                }); | ||||
| //        } | ||||
|                     var num = rng.Next(1, 101) + chance * 100; | ||||
|  | ||||
| //        private string GetRandomCurrencyImagePath() => | ||||
| //            Directory.GetFiles("data/currency_images").OrderBy(s => rng.Next()).FirstOrDefault(); | ||||
|                     if (num > 100) | ||||
|                     { | ||||
|                         lastGenerations.AddOrUpdate(channel.Id, DateTime.Now, (id, old) => DateTime.Now); | ||||
|                         //todo get prefix | ||||
|                         try | ||||
|                         { | ||||
|                             var sent = await channel.SendFileAsync( | ||||
|                                 GetRandomCurrencyImagePath(),  | ||||
|                                 $"❗ A random { Gambling.Gambling.CurrencyName } appeared! Pick it up by typing `>pick`") | ||||
|                                     .ConfigureAwait(false); | ||||
|                             plantedFlowers.AddOrUpdate(channel.Id, new List<IUserMessage>() { sent }, (id, old) => { old.Add(sent); return old; }); | ||||
|                         } | ||||
|                         catch { } | ||||
|                          | ||||
|                     } | ||||
|                 }); | ||||
|                 return Task.CompletedTask; | ||||
|             } | ||||
|             [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] | ||||
|             [RequireContext(ContextType.Guild)] | ||||
|             public async Task Pick(IUserMessage imsg) | ||||
|             { | ||||
|                 var channel = (ITextChannel)imsg.Channel; | ||||
|  | ||||
| //        int GetRandomNumber() | ||||
| //        { | ||||
| //            using (var rg = RandomNumberGenerator.Create()) | ||||
| //            { | ||||
| //                byte[] rno = new byte[4]; | ||||
| //                rg.GetBytes(rno); | ||||
| //                int randomvalue = BitConverter.ToInt32(rno, 0); | ||||
| //                return randomvalue; | ||||
| //            } | ||||
| //        } | ||||
| //    } | ||||
| //} | ||||
|                 if (!channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages) | ||||
|                 { | ||||
|                     await channel.SendMessageAsync("`I need manage channel permissions in order to process this command.`").ConfigureAwait(false); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 List<IUserMessage> msgs; | ||||
|  | ||||
|                 await imsg.DeleteAsync().ConfigureAwait(false); | ||||
|                 if (!plantedFlowers.TryRemove(channel.Id, out msgs)) | ||||
|                     return; | ||||
|  | ||||
|                 await Task.WhenAll(msgs.Select(toDelete => toDelete.DeleteAsync())).ConfigureAwait(false); | ||||
|  | ||||
|                 await CurrencyHandler.AddCurrencyAsync((IGuildUser)imsg.Author, "Picked a flower.", 1, false).ConfigureAwait(false); | ||||
|                 var msg = await channel.SendMessageAsync($"**{imsg.Author.Username}** picked a {Gambling.Gambling.CurrencyName}!").ConfigureAwait(false); | ||||
|                 var t = Task.Run(async () => | ||||
|                  { | ||||
|                      try | ||||
|                      { | ||||
|                          await Task.Delay(10000).ConfigureAwait(false); | ||||
|                          await msg.DeleteAsync().ConfigureAwait(false); | ||||
|                      } | ||||
|                      catch { } | ||||
|                  }); | ||||
|             } | ||||
|  | ||||
|             [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] | ||||
|             [RequireContext(ContextType.Guild)] | ||||
|             public async Task Plant(IUserMessage imsg) | ||||
|             { | ||||
|                 var channel = (ITextChannel)imsg.Channel; | ||||
|                 if (channel == null) | ||||
|                     return; | ||||
|  | ||||
|                 var removed = await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)imsg.Author, "Planted a flower.", 1, true).ConfigureAwait(false); | ||||
|                 if (!removed) | ||||
|                 { | ||||
|                     await channel.SendMessageAsync($"You don't have any {Gambling.Gambling.CurrencyName}s.").ConfigureAwait(false); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 var file = GetRandomCurrencyImagePath(); | ||||
|                 IUserMessage msg; | ||||
|                 var vowelFirst = new[] { 'a', 'e', 'i', 'o', 'u' }.Contains(Gambling.Gambling.CurrencyName[0]); | ||||
|                 var msgToSend = $"Oh how Nice! **{imsg.Author.Username}** planted {(vowelFirst ? "an" : "a")} {Gambling.Gambling.CurrencyName}. Pick it using >pick"; | ||||
|                 if (file == null) | ||||
|                 { | ||||
|                     msg = await channel.SendMessageAsync(Gambling.Gambling.CurrencySign).ConfigureAwait(false); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     //todo add prefix | ||||
|                     msg = await channel.SendFileAsync(file, msgToSend).ConfigureAwait(false); | ||||
|                 } | ||||
|                 plantedFlowers.AddOrUpdate(channel.Id, new List<IUserMessage>() { msg }, (id, old) => { old.Add(msg); return old; }); | ||||
|             } | ||||
|              | ||||
|             [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] | ||||
|             [RequireContext(ContextType.Guild)] | ||||
|             [RequirePermission(GuildPermission.ManageMessages)] | ||||
|             public async Task Gencurrency(IUserMessage imsg) | ||||
|             { | ||||
|                 var channel = imsg.Channel as ITextChannel; | ||||
|                 if (channel == null) | ||||
|                     return; | ||||
|  | ||||
|                 bool enabled; | ||||
|                 using (var uow = DbHandler.UnitOfWork()) | ||||
|                 { | ||||
|                     var guildConfig = uow.GuildConfigs.For(channel.Id); | ||||
|  | ||||
|                     if (guildConfig.GenerateCurrencyChannelId == null) | ||||
|                     { | ||||
|                         guildConfig.GenerateCurrencyChannelId = channel.Id; | ||||
|                         generationChannels.TryAdd(channel.Id, true); | ||||
|                         enabled = true; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         guildConfig.GenerateCurrencyChannelId = null; | ||||
|                         bool throwaway; | ||||
|                         generationChannels.TryRemove(channel.Id, out throwaway); | ||||
|                         enabled = false; | ||||
|                     } | ||||
|  | ||||
|                 } | ||||
|                 if (enabled) | ||||
|                 { | ||||
|                     await channel.SendMessageAsync("`Currency generation disabled on this channel.`").ConfigureAwait(false); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     await channel.SendMessageAsync($"`Currency generation enabled on this channel.`").ConfigureAwait(false); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             private string GetRandomCurrencyImagePath() => | ||||
|                 Directory.GetFiles("data/currency_images").OrderBy(s => rng.Next()).FirstOrDefault(); | ||||
|  | ||||
|             int GetRandomNumber() | ||||
|             { | ||||
|                 using (var rg = RandomNumberGenerator.Create()) | ||||
|                 { | ||||
|                     byte[] rno = new byte[4]; | ||||
|                     rg.GetBytes(rno); | ||||
|                     int randomvalue = BitConverter.ToInt32(rno, 0); | ||||
|                     return randomvalue; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -15,6 +15,9 @@ namespace NadekoBot.Services.Database.Models | ||||
|         public bool ForwardMessages { get; set; } = true; | ||||
|         public bool ForwardToAllOwners { get; set; } = true; | ||||
|  | ||||
|         public float CurrencyGenerationChance { get; set; } = 0.1f; | ||||
|         public int CurrencyGenerationCooldown { get; set; } = 10; | ||||
|  | ||||
|         public List<ModulePrefix> ModulePrefixes { get; set; } = new List<ModulePrefix>() | ||||
|         { | ||||
|            new ModulePrefix() { ModuleName="Administration", Prefix="." }, | ||||
|   | ||||
| @@ -38,5 +38,8 @@ namespace NadekoBot.Services.Database.Models | ||||
|  | ||||
|         //stream notifications | ||||
|         public List<FollowedStream> FollowedStreams { get; set; } = new List<FollowedStream>(); | ||||
|  | ||||
|         //currencyGeneration | ||||
|         public ulong? GenerateCurrencyChannelId { get; set; } | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user