DeukBot4/DeukBot4/Database/BirthdayHandler.cs

155 lines
5.9 KiB
C#

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<DateTime?> 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;
public static async Task CheckBirthdays()
{
while (true)
{
try
{
var today = DateTime.UtcNow - new TimeSpan(6, 0, 0);
while (!Program.IsConnected)
{
await Task.Delay(500);
}
if (today.Date != _lastCheckedDate)
{
_lastCheckedDate = today.Date;
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));
}
}
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());
}
}
}
}
}