using System; using System.Threading.Tasks; using Discord; using StackExchange.Redis; namespace DeukBot4.Database { public class ReminderHandler { public static ReminderHandler Main = new ReminderHandler(); public static ConnectionMultiplexer Redis = ConnectionMultiplexer.Connect("localhost:6379"); public async Task AddReminder(TimeSpan time, string message, ulong channel, ulong author, ulong recipient) { try { var db = Redis.GetDatabase(); var id = Guid.NewGuid().ToString(); var expectedTime = DateTime.UtcNow.Add(time); db.SortedSetAddAsync("deukbot_reminders", (RedisValue)id, expectedTime.ToBinary()); db.HashSetAsync((RedisKey) id, new[] { new HashEntry("channel", channel.ToString("D")), new HashEntry("message", message), new HashEntry("author", author.ToString("D")), new HashEntry("recipient", recipient.ToString("D")), }); } catch (Exception e) { Logger.Main.LogError(e); } } public async Task CheckReminders() { var checkTime = TimeSpan.FromSeconds(70); try { var startTime = DateTime.UtcNow; var desiredTopScore = (startTime + checkTime).ToBinary(); var db = Redis.GetDatabase(); var reminders = db.SortedSetRangeByScoreWithScores("deukbot_reminders", start: Double.MinValue, stop: desiredTopScore); foreach (var sortedSetEntry in reminders) { var val = sortedSetEntry.Element.ToString(); var timeLong = sortedSetEntry.Score; var time = DateTime.FromBinary((long) timeLong); var data = db.HashGetAll(val); ulong channel = 0; ulong author = 0; ulong recipient = 0; string message = null; foreach (var hashEntry in data) { if (hashEntry.Name == "channel") channel = ulong.Parse(hashEntry.Value); else if (hashEntry.Name == "message") message = hashEntry.Value; else if (hashEntry.Name == "author") author = ulong.Parse(hashEntry.Value); else if (hashEntry.Name == "recipient") recipient = ulong.Parse(hashEntry.Value); } var diff = time - DateTime.UtcNow; FireReminderAtTime((int) diff.TotalSeconds, channel, message, author, recipient); db.KeyDelete(val); } db.SortedSetRemoveRangeByScoreAsync("deukbot_reminders", Double.MinValue, desiredTopScore); } catch (Exception e) { Logger.Main.LogError(e); } await Task.Delay(checkTime); await CheckReminders(); } private async Task FireReminderAtTime(int seconds, ulong channelId, string message, ulong author, ulong recipient) { if (seconds > 0) await Task.Delay(TimeSpan.FromSeconds(seconds)); await FireReminder(channelId, message, author, recipient); } private async Task FireReminder(ulong channelId, string message, ulong author, ulong recipient) { if (Program.Client.GetChannel(channelId) is ITextChannel channel) { if (author == recipient) { channel.SendMessageAsync($"Hey <@{recipient}>, don't forget to {message}."); } else { channel.SendMessageAsync($"Hey <@{recipient}>, <@{author}> asked me to remind you to {message}."); } } } } }