DeukBot4/DeukBot4/Database/ReminderHandler.cs

101 lines
4.1 KiB
C#

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}.");
}
}
}
}
}