From 599d24ab3f473fc5e1848e9f3b0298eb7083860c Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Mon, 8 Oct 2018 18:36:22 +0200 Subject: [PATCH] Added Birthday handling --- DeukBot4/Database/BirthdayHandler.cs | 119 ++++++++++++++++++ .../Commands/GeneralCommands.cs | 29 ++++- DeukBot4/Program.cs | 3 + 3 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 DeukBot4/Database/BirthdayHandler.cs diff --git a/DeukBot4/Database/BirthdayHandler.cs b/DeukBot4/Database/BirthdayHandler.cs new file mode 100644 index 0000000..c9db23e --- /dev/null +++ b/DeukBot4/Database/BirthdayHandler.cs @@ -0,0 +1,119 @@ +using System; +using System.Threading.Tasks; +using DeukBot4.MessageHandlers.CommandHandler; +using StackExchange.Redis; + +namespace DeukBot4.Database +{ + public static class BirthdayHandler + { + private static ConnectionMultiplexer Redis => ReminderHandler.Redis; + + public static async Task AddBirthday(DateTime birthday, ulong server, ulong user) + { + try + { + var db = Redis.GetDatabase(); + var exists = db.HashGet("birthdays", (RedisValue) $"{server}-{user}"); + if (exists.HasValue) + { + var bdayEntries = db.HashGetAll(exists.ToString()); + DateTime bday = DateTime.MinValue; + foreach (var bdayEntry in bdayEntries) + { + if (bdayEntry.Name == "birthday") bday = DateTime.FromBinary(long.Parse(bdayEntry.Value)); + } + db.SetRemove(bday.ToString("ddMM"), exists); + db.KeyDelete(exists.ToString()); + } + var id = Guid.NewGuid().ToString(); + db.HashSet("birthdays", (RedisValue) $"{server}-{user}", id); + db.SetAdd(birthday.ToString("ddMM"), id); + db.HashSetAsync((RedisKey) id, new[] + { + new HashEntry("server", server.ToString("D")), + new HashEntry("user", user.ToString("D")), + new HashEntry("birthday", birthday.ToBinary().ToString("D")), + }); + + } + catch (Exception e) + { + Logger.Main.LogError(e); + } + } + + private static int Years(DateTime start, DateTime end) + { + return (end.Year - start.Year - 1) + + (((end.Month > start.Month) || + ((end.Month == start.Month) && (end.Day >= start.Day))) ? 1 : 0); + } + + private static DateTime _lastCheckedDate; + // ReSharper disable once FunctionRecursiveOnAllPaths + public static async Task CheckBirthdays() + { + var today = DateTime.UtcNow.Date; + while (!Program.IsConnected) + { + await Task.Delay(500); + } + try + { + if (today != _lastCheckedDate) + { + _lastCheckedDate = today; + await ActualBirthdayCheck(today); + } + } + catch (Exception e) + { + Logger.Main.LogError(e); + } + await Task.Delay(TimeSpan.FromSeconds(1)); + await CheckBirthdays(); + } + + + private static async Task ActualBirthdayCheck(DateTime today) + { + var db = Redis.GetDatabase(); + var reminders = db.SetMembers(today.ToString("ddMM")); + foreach (var redisValue in reminders) + { + ulong server = 0; + ulong user = 0; + DateTime birthday = today; + var val = redisValue.ToString(); + var data = db.HashGetAll(val); + foreach (var hashEntry in data) + { + if (hashEntry.Name == "server") server = ulong.Parse(hashEntry.Value); + else if (hashEntry.Name == "user") user = ulong.Parse(hashEntry.Value); + else if (hashEntry.Name == "birthday") birthday = DateTime.FromBinary(long.Parse(hashEntry.Value)); + } + + var guild = Program.Client.GetGuild(server); + if (guild != null) + { + var guildUser = guild.GetUser(user); + if (guildUser == null) + { + Console.WriteLine("Can't celebrate birthday for user, not in guild anymore :("); + db.KeyDelete(val); + return; + } + + var eb = EmbedFactory.GetStandardEmbedBuilder(); + eb.Title = $":confetti_ball::confetti_ball: Happy Birthday! :confetti_ball::confetti_ball: "; + var age = Years(birthday, today); + eb.Description = $"It's <@!{guildUser.Id}>'s {age}th birthday!! Have a good one!"; + eb.ThumbnailUrl = guildUser.GetAvatarUrl(); + + guild.DefaultChannel.SendMessageAsync("", embed: eb.Build()); + } + } + } + } +} \ No newline at end of file diff --git a/DeukBot4/MessageHandlers/CommandHandler/Commands/GeneralCommands.cs b/DeukBot4/MessageHandlers/CommandHandler/Commands/GeneralCommands.cs index 73fd785..c30b925 100644 --- a/DeukBot4/MessageHandlers/CommandHandler/Commands/GeneralCommands.cs +++ b/DeukBot4/MessageHandlers/CommandHandler/Commands/GeneralCommands.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Net; using System.Text; @@ -175,7 +176,7 @@ namespace DeukBot4.MessageHandlers.CommandHandler } [Command("user", PermissionLevel.Everyone)] - [CommandHelp("Gets a users avatar", "Gets a users avatar. Returns avatar of user using the command if no user was specified.")] + [CommandHelp("Gets information on a user", "Returns detailed information on a user. Returns more information if the user is in the current server")] [CommandParameters(ParameterMatcher.ParameterType.User)] public async Task GetUser(CommandRequest request) { @@ -245,5 +246,31 @@ namespace DeukBot4.MessageHandlers.CommandHandler await request.SendMessageAsync("", embed: eb.Build()); } + + [Command("birthday", PermissionLevel.Everyone)] + [CommandParameters(ParameterMatcher.ParameterType.Remainder)] + [BlockUsageInPm] + public async Task SetBirthday(CommandRequest request) + { + var guildChannel = request.OriginalMessage.Channel as IGuildChannel; + if (guildChannel == null) + return; + if (request.Parameters.Length == 0) + { + await request.SendSimpleEmbed("Birthday", "You can use this command to set a birthday"); + return; + } + + var parameter = request.Parameters[0].AsString(); + if (!DateTime.TryParseExact(parameter, "dd/MM/yyyy", CultureInfo.InvariantCulture,DateTimeStyles.None, out var bday)) + { + await request.SendSimpleEmbed("Birthday", + "Couldn't parse that parameter as a date. Please rewrite the date string to format dd/MM/yyyy."); + return; + } + + BirthdayHandler.AddBirthday(bday, guildChannel.GuildId, request.OriginalMessage.Author.Id); + await request.SendSimpleEmbed("Birthday", $"Success! Added {bday:dd MMMM yyyy} as your birthday!"); + } } } \ No newline at end of file diff --git a/DeukBot4/Program.cs b/DeukBot4/Program.cs index d1def0e..283e30b 100644 --- a/DeukBot4/Program.cs +++ b/DeukBot4/Program.cs @@ -17,6 +17,7 @@ namespace DeukBot4 public static DiscordSocketClient Client { get; private set; } public static Settings Settings { get; private set; } public static ulong BotId { get; private set; } + public static bool IsConnected { get; private set; } private static void Main(string[] args) { @@ -26,6 +27,7 @@ namespace DeukBot4 private static async Task SetupScheduler() { ReminderHandler.Main.CheckReminders(); + BirthdayHandler.CheckBirthdays(); } private static async Task MainAsync() @@ -70,6 +72,7 @@ namespace DeukBot4 Console.WriteLine($"- {clientGuild.Id}: {clientGuild.Name}"); } BotId = Client.CurrentUser.Id; + IsConnected = true; } } } \ No newline at end of file