diff --git a/NadekoBot/Classes/DBHandler.cs b/NadekoBot/Classes/DBHandler.cs index 463cba18..ba99b635 100644 --- a/NadekoBot/Classes/DBHandler.cs +++ b/NadekoBot/Classes/DBHandler.cs @@ -29,6 +29,7 @@ namespace NadekoBot.Classes conn.CreateTable(); conn.CreateTable(); conn.CreateTable(); + conn.CreateTable(); conn.Execute(Queries.TransactionTriggerQuery); } } @@ -41,6 +42,16 @@ namespace NadekoBot.Classes } } + internal void DeleteWhere(Expression> p) where T : IDataModel, new() + { + using (var conn = new SQLiteConnection(FilePath)) + { + var id = conn.Table().Where(p).FirstOrDefault()?.Id; + if (id.HasValue) + conn.Delete(id); + } + } + internal void InsertData(T o) where T : IDataModel { using (var conn = new SQLiteConnection(FilePath)) diff --git a/NadekoBot/Classes/_DataModels/Reminder.cs b/NadekoBot/Classes/_DataModels/Reminder.cs new file mode 100644 index 00000000..6be3d0a7 --- /dev/null +++ b/NadekoBot/Classes/_DataModels/Reminder.cs @@ -0,0 +1,14 @@ +using System; + +namespace NadekoBot.Classes._DataModels +{ + class Reminder : IDataModel + { + public DateTime When { get; set; } + public long ChannelId { get; set; } + public long ServerId { get; set; } + public long UserId { get; set; } + public string Message { get; set; } + public bool IsPrivate { get; set; } + } +} diff --git a/NadekoBot/Modules/Administration/AdministrationModule.cs b/NadekoBot/Modules/Administration/AdministrationModule.cs index 6dd68fe2..cc07e6a1 100644 --- a/NadekoBot/Modules/Administration/AdministrationModule.cs +++ b/NadekoBot/Modules/Administration/AdministrationModule.cs @@ -26,6 +26,7 @@ namespace NadekoBot.Modules.Administration commands.Add(new VoicePlusTextCommand(this)); commands.Add(new CrossServerTextChannel(this)); commands.Add(new SelfAssignedRolesCommand(this)); + commands.Add(new Remind(this)); } public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.Administration; diff --git a/NadekoBot/Modules/Administration/Commands/Remind.cs b/NadekoBot/Modules/Administration/Commands/Remind.cs new file mode 100644 index 00000000..6b4374a5 --- /dev/null +++ b/NadekoBot/Modules/Administration/Commands/Remind.cs @@ -0,0 +1,166 @@ +using Discord; +using Discord.Commands; +using NadekoBot.Classes; +using NadekoBot.Classes._DataModels; +using NadekoBot.Commands; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Timers; + +namespace NadekoBot.Modules.Administration.Commands +{ + class Remind : DiscordCommand + { + + Regex regex = new Regex(@"^(?:(?\d)mo)?(?:(?\d)w)?(?:(?\d{1,2})d)?(?:(?\d{1,2})h)?(?:(?\d{1,2})m)?$", + RegexOptions.Compiled | RegexOptions.Multiline); + + List reminders = new List(); + + public Remind(DiscordModule module) : base(module) + { + var remList = DbHandler.Instance.GetAllRows(); + + Console.WriteLine(string.Join("\n-", remList.Select(r => r.When.ToString()))); + reminders = remList.Select(StartNewReminder).ToList(); + } + + private Timer StartNewReminder(Reminder r) + { + var now = DateTime.Now; + var twoMins = new TimeSpan(0, 2, 0); + TimeSpan time = (r.When - now) < twoMins + ? twoMins //if the time is less than 2 minutes, + : r.When - now; //it will send the message 2 minutes after start + //To account for high bot startup times + + var t = new Timer(time.TotalMilliseconds); + t.Elapsed += async (s, e) => + { + try + { + Channel ch; + if (r.IsPrivate) + { + ch = NadekoBot.Client.PrivateChannels.FirstOrDefault(c => (long)c.Id == r.ChannelId); + if (ch == null) + ch = await NadekoBot.Client.CreatePrivateChannel((ulong)r.ChannelId); + } + else + ch = NadekoBot.Client.GetServer((ulong)r.ServerId)?.GetChannel((ulong)r.ChannelId); + + if (ch == null) + return; + + await ch.SendMessage($"❗⏰**I've been told to remind you to '{r.Message}' now by <@{r.UserId}>.**⏰❗"); + } + catch (Exception ex) + { + Console.WriteLine($"Timer error! {ex}"); + } + finally + { + DbHandler.Instance.Delete(r.Id); + t.Stop(); + t.Dispose(); + } + }; + t.Start(); + return t; + } + + internal override void Init(CommandGroupBuilder cgb) + { + cgb.CreateCommand(Module.Prefix + "remind") + .Parameter("meorchannel", ParameterType.Required) + .Parameter("time", ParameterType.Required) + .Parameter("message", ParameterType.Unparsed) + .Do(async e => + { + var meorchStr = e.GetArg("meorchannel").ToUpperInvariant(); + Channel ch; + bool isPrivate = false; + if (meorchStr == "ME") + { + isPrivate = true; + ch = await e.User.CreatePMChannel(); + } + else if (meorchStr == "HERE") + { + ch = e.Channel; + } + else { + ch = e.Server.FindChannels(meorchStr).FirstOrDefault(); + } + + if (ch == null) + { + await e.Channel.SendMessage($"{e.User.Mention} Something went wrong (channel cannot be found) ;("); + return; + } + + var timeStr = e.GetArg("time"); + + var m = regex.Match(timeStr); + + if (m.Length == 0) + { + await e.Channel.SendMessage("Not a valid time format blablabla"); + return; + } + + string output = ""; + var namesAndValues = new Dictionary(); + + foreach (var groupName in regex.GetGroupNames()) + { + if (groupName == "0") continue; + int value = 0; + int.TryParse(m.Groups[groupName].Value, out value); + + if (string.IsNullOrEmpty(m.Groups[groupName].Value)) + { + namesAndValues[groupName] = 0; + continue; + } + else if (value < 1 || + (groupName == "months" && value > 1) || + (groupName == "weeks" && value > 4) || + (groupName == "days" && value >= 7) || + (groupName == "hours" && value > 23) || + (groupName == "minutes" && value > 59)) + { + await e.Channel.SendMessage($"Invalid {groupName} value."); + return; + } + else + namesAndValues[groupName] = value; + output += m.Groups[groupName].Value + " " + groupName + " "; + } + var time = DateTime.Now + new TimeSpan(30 * namesAndValues["months"] + + 7 * namesAndValues["weeks"] + + namesAndValues["days"], + namesAndValues["hours"], + namesAndValues["minutes"], + 0); + + var rem = new Reminder + { + ChannelId = (long)ch.Id, + IsPrivate = isPrivate, + When = time, + Message = e.GetArg("message"), + UserId = (long)e.User.Id, + ServerId = (long)e.Server.Id + }; + DbHandler.Instance.InsertData(rem); + + reminders.Add(StartNewReminder(rem)); + + await e.Channel.SendMessage($"⏰ I will remind \"{ch.Name}\" to \"{e.GetArg("message").ToString()}\" in {output}. ({time:d.M.yyyy.} at {time:HH:m})"); + }); + } + } +} diff --git a/NadekoBot/NadekoBot.csproj b/NadekoBot/NadekoBot.csproj index bd4d6e03..dcd4fa07 100644 --- a/NadekoBot/NadekoBot.csproj +++ b/NadekoBot/NadekoBot.csproj @@ -145,12 +145,14 @@ + +