using Discord;
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.Modules.Permissions.Classes;
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Games.Commands
{
///
/// 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
///
class PlantPick : DiscordCommand
{
private Random rng;
public PlantPick(DiscordModule module) : base(module)
{
NadekoBot.Client.MessageReceived += PotentialFlowerGeneration;
rng = new Random();
}
private static readonly ConcurrentDictionary plantpickCooldowns = new ConcurrentDictionary();
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(GetRandomNumber());
if ((rnd % 50) == 0)
{
var msg = await e.Channel.SendFile(GetRandomCurrencyImagePath());
var msg2 = await e.Channel.SendMessage($"❗ A random {NadekoBot.Config.CurrencyName} appeared! Pick it up by typing `>pick`");
plantedFlowerChannels.AddOrUpdate(e.Channel.Id, msg, (u, m) => { m.Delete().GetAwaiter().GetResult(); return msg; });
plantpickCooldowns.AddOrUpdate(e.Channel.Id, now, (i, d) => now);
await Task.Delay(5000);
await msg2.Delete();
}
}
}
catch { }
}
//channelid/messageid pair
ConcurrentDictionary plantedFlowerChannels = new ConcurrentDictionary();
private object locker = new object();
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "pick")
.Description("Picks a flower planted in this channel.")
.Do(async e =>
{
Message msg;
await e.Message.Delete().ConfigureAwait(false);
if (!plantedFlowerChannels.TryRemove(e.Channel.Id, out msg))
return;
await msg.Delete().ConfigureAwait(false);
await FlowersHandler.AddFlowersAsync(e.User, "Picked a flower.", 1, true).ConfigureAwait(false);
msg = await e.Channel.SendMessage($"**{e.User.Name}** picked a {NadekoBot.Config.CurrencyName}!").ConfigureAwait(false);
await Task.Delay(10000).ConfigureAwait(false);
await msg.Delete().ConfigureAwait(false);
});
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)")
.Do(async e =>
{
lock (locker)
{
if (plantedFlowerChannels.ContainsKey(e.Channel.Id))
{
e.Channel.SendMessage($"There is already a {NadekoBot.Config.CurrencyName} in this channel.");
return;
}
var removed = FlowersHandler.RemoveFlowers(e.User, "Planted a flower.", 1).GetAwaiter().GetResult();
if (!removed)
{
e.Channel.SendMessage($"You don't have any {NadekoBot.Config.CurrencyName}s.").Wait();
return;
}
var file = GetRandomCurrencyImagePath();
Message msg;
//todo send message after, not in lock
if (file == null)
msg = e.Channel.SendMessage(NadekoBot.Config.CurrencySign).GetAwaiter().GetResult();
else
msg = e.Channel.SendFile(file).GetAwaiter().GetResult();
plantedFlowerChannels.TryAdd(e.Channel.Id, msg);
}
var vowelFirst = new[] { 'a', 'e', 'i', 'o', 'u' }.Contains(NadekoBot.Config.CurrencyName[0]);
var msg2 = await e.Channel.SendMessage($"Oh how Nice! **{e.User.Name}** planted {(vowelFirst ? "an" : "a")} {NadekoBot.Config.CurrencyName}. Pick it using {Module.Prefix}pick");
await Task.Delay(20000).ConfigureAwait(false);
await msg2.Delete().ConfigureAwait(false);
});
cgb.CreateCommand(Prefix + "gencurrency")
.Alias(Prefix + "gc")
.Description($"Toggles currency generation on this channel. Every posted message will have 2% chance to spawn a {NadekoBot.Config.CurrencyName}. Optional parameter cooldown time in minutes, 5 minutes by default. Requires Manage Messages permission. | `>gc` or `>gc 60`")
.AddCheck(SimpleCheckers.ManageMessages())
.Parameter("cd", ParameterType.Unparsed)
.Do(async e =>
{
var cdStr = e.GetArg("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 e.Channel.SendMessage("`Currency generation disabled on this channel.`");
}
else
{
if (config.GenerateCurrencyChannels.TryAdd(e.Channel.Id, cd))
await e.Channel.SendMessage($"`Currency generation enabled on this channel. Cooldown is {cd} minutes.`");
}
});
}
private string GetRandomCurrencyImagePath() =>
Directory.GetFiles("data/currency_images").OrderBy(s => rng.Next()).FirstOrDefault();
int GetRandomNumber()
{
using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider())
{
byte[] rno = new byte[4];
rg.GetBytes(rno);
int randomvalue = BitConverter.ToInt32(rno, 0);
return randomvalue;
}
}
}
}