using System; using System.Threading.Tasks; using DeukBot4.MessageHandlers.CommandHandler; using DeukBot4.Utilities; using StackExchange.Redis; namespace DeukBot4.Database { public static class BirthdayHandler { private static ConnectionMultiplexer Redis => ReminderHandler.Redis; public static async Task GetBirthday(ulong server, ulong user) { 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)); break; } } return bday; } return null; } 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); } public static void Initialize() { var db = Redis.GetDatabase(); var dbValue = db.StringGet("lastCheckedBirthday"); if (dbValue.HasValue) _lastCheckedDate = DateTime.FromBinary(long.Parse(dbValue)); } private static DateTime _lastCheckedDate; // ReSharper disable once FunctionRecursiveOnAllPaths public static async Task CheckBirthdays() { var today = DateTime.UtcNow.Date - new TimeSpan(6, 0 , 0); while (!Program.IsConnected) { await Task.Delay(500); } try { if (today != _lastCheckedDate) { _lastCheckedDate = today; var db = Redis.GetDatabase(); db.StringSet("lastCheckedBirthday", _lastCheckedDate.ToBinary().ToString("D")); await ActualBirthdayCheck(today); } } catch (Exception e) { Logger.Main.LogError(e); } await Task.Delay(TimeSpan.FromHours(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); db.SetRemove(birthday.ToString("ddMM"), val); return; } var eb = EmbedFactory.GetStandardEmbedBuilder(); eb.Title = $":confetti_ball::confetti_ball: Happy Birthday! :confetti_ball::confetti_ball: "; var age = Years(birthday, today); string ageString = EnglishNumberParser.GetShortOrdinalNumber(age); eb.Description = $"It's <@!{guildUser.Id}>'s {ageString} birthday!! Have a good one!"; eb.ThumbnailUrl = guildUser.GetAvatarUrl(); guild.SystemChannel.SendMessageAsync("", embed: eb.Build()); } } } } }