NadekoBot/src/NadekoBot/Modules/Administration/Commands/MessageRepeater.cs

162 lines
6.3 KiB
C#
Raw Normal View History

2016-08-28 12:19:50 +00:00
using Discord;
using Discord.Commands;
2016-08-28 20:59:12 +00:00
using NadekoBot.Attributes;
2016-12-11 16:18:25 +00:00
using NadekoBot.Extensions;
2016-08-28 20:59:12 +00:00
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
2016-10-05 05:01:19 +00:00
using NLog;
2016-08-28 12:19:50 +00:00
using System;
using System.Collections.Concurrent;
2016-08-28 20:59:12 +00:00
using System.Linq;
2016-08-29 12:34:46 +00:00
using System.Threading;
2016-08-28 12:19:50 +00:00
using System.Threading.Tasks;
2016-08-28 12:19:50 +00:00
namespace NadekoBot.Modules.Administration
{
2016-08-28 20:59:12 +00:00
public partial class Administration
2016-08-28 12:19:50 +00:00
{
2016-08-28 20:59:12 +00:00
[Group]
2016-12-17 00:16:14 +00:00
public class RepeatCommands : ModuleBase
2016-08-28 20:59:12 +00:00
{
2016-12-08 17:35:34 +00:00
public static ConcurrentDictionary<ulong, RepeatRunner> repeaters { get; }
2016-08-29 12:34:46 +00:00
public class RepeatRunner
{
2016-10-05 05:01:19 +00:00
private Logger _log { get; }
2016-08-29 12:34:46 +00:00
private CancellationTokenSource source { get; set; }
private CancellationToken token { get; set; }
public Repeater Repeater { get; }
public ITextChannel Channel { get; }
public RepeatRunner(Repeater repeater, ITextChannel channel = null)
2016-08-29 12:34:46 +00:00
{
2016-10-05 05:01:19 +00:00
_log = LogManager.GetCurrentClassLogger();
2016-08-29 12:34:46 +00:00
this.Repeater = repeater;
2016-12-17 04:09:04 +00:00
this.Channel = channel ?? NadekoBot.Client.GetGuild(repeater.GuildId)?.GetTextChannelAsync(repeater.ChannelId).GetAwaiter().GetResult();
2016-08-29 12:34:46 +00:00
if (Channel == null)
return;
Task.Run(Run);
}
private async Task Run()
{
source = new CancellationTokenSource();
token = source.Token;
IUserMessage oldMsg = null;
2016-08-29 12:34:46 +00:00
try
{
while (!token.IsCancellationRequested)
{
await Task.Delay(Repeater.Interval, token).ConfigureAwait(false);
if (oldMsg != null)
try { await oldMsg.DeleteAsync(); } catch { }
2016-12-17 00:16:14 +00:00
try { oldMsg = await Channel.SendMessageAsync("🔄 " + Repeater.Message).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); try { source.Cancel(); } catch { } }
2016-08-29 12:34:46 +00:00
}
}
catch (OperationCanceledException) { }
}
public void Reset()
{
source.Cancel();
var t = Task.Run(Run);
}
public void Stop()
{
source.Cancel();
}
}
2016-05-23 20:50:16 +00:00
2016-12-08 17:35:34 +00:00
static RepeatCommands()
2016-08-28 12:19:50 +00:00
{
2016-08-28 20:59:12 +00:00
using (var uow = DbHandler.UnitOfWork())
{
2016-08-29 12:34:46 +00:00
repeaters = new ConcurrentDictionary<ulong, RepeatRunner>(uow.Repeaters.GetAll().Select(r => new RepeatRunner(r)).Where(r => r != null).ToDictionary(r => r.Repeater.ChannelId));
2016-08-28 20:59:12 +00:00
}
2016-08-28 12:19:50 +00:00
}
[NadekoCommand, Usage, Description, Aliases]
2016-08-28 20:59:12 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 18:43:57 +00:00
[RequireUserPermission(GuildPermission.ManageMessages)]
public async Task RepeatInvoke()
2016-08-28 12:19:50 +00:00
{
2016-08-29 12:34:46 +00:00
RepeatRunner rep;
2016-12-17 00:16:14 +00:00
if (!repeaters.TryGetValue(Context.Channel.Id, out rep))
2016-08-28 12:19:50 +00:00
{
2016-12-16 21:44:26 +00:00
await Context.Channel.SendErrorAsync(" **No repeating message found on this server.**").ConfigureAwait(false);
2016-08-28 20:59:12 +00:00
return;
2016-08-28 12:19:50 +00:00
}
2016-08-29 12:34:46 +00:00
rep.Reset();
2016-12-16 21:44:26 +00:00
await Context.Channel.SendMessageAsync("🔄 " + rep.Repeater.Message).ConfigureAwait(false);
2016-08-28 12:19:50 +00:00
}
2016-05-23 20:50:16 +00:00
[NadekoCommand, Usage, Description, Aliases]
2016-08-28 20:59:12 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 18:43:57 +00:00
[RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Repeat()
2016-08-28 20:59:12 +00:00
{
2016-08-29 12:34:46 +00:00
RepeatRunner rep;
2016-12-17 00:16:14 +00:00
if (repeaters.TryRemove(Context.Channel.Id, out rep))
2016-08-28 12:19:50 +00:00
{
using (var uow = DbHandler.UnitOfWork())
2016-08-28 12:19:50 +00:00
{
uow.Repeaters.Remove(rep.Repeater);
await uow.CompleteAsync();
2016-08-28 12:19:50 +00:00
}
rep.Stop();
2016-12-16 21:44:26 +00:00
await Context.Channel.SendConfirmAsync("✅ **Stopped repeating a message.**").ConfigureAwait(false);
2016-08-28 20:59:12 +00:00
}
else
2016-12-16 21:44:26 +00:00
await Context.Channel.SendConfirmAsync(" **No message is repeating.**").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
2016-12-16 18:43:57 +00:00
[RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Repeat(IUserMessage imsg, int minutes, [Remainder] string message)
{
if (minutes < 1 || minutes > 10080)
return;
if (string.IsNullOrWhiteSpace(message))
return;
RepeatRunner rep;
2016-05-23 20:50:16 +00:00
2016-12-17 00:16:14 +00:00
rep = repeaters.AddOrUpdate(Context.Channel.Id, (cid) =>
2016-08-28 12:19:50 +00:00
{
2016-08-28 20:59:12 +00:00
using (var uow = DbHandler.UnitOfWork())
2016-08-28 12:19:50 +00:00
{
2016-08-28 20:59:12 +00:00
var localRep = new Repeater
{
2016-12-17 00:16:14 +00:00
ChannelId = Context.Channel.Id,
2016-12-16 21:44:26 +00:00
GuildId = Context.Guild.Id,
2016-08-28 20:59:12 +00:00
Interval = TimeSpan.FromMinutes(minutes),
Message = message,
};
uow.Repeaters.Add(localRep);
uow.Complete();
2016-12-17 00:16:14 +00:00
return new RepeatRunner(localRep, (ITextChannel)Context.Channel);
2016-08-28 12:19:50 +00:00
}
2016-08-28 20:59:12 +00:00
}, (cid, old) =>
{
using (var uow = DbHandler.UnitOfWork())
2016-08-28 12:19:50 +00:00
{
2016-08-29 12:34:46 +00:00
old.Repeater.Message = message;
old.Repeater.Interval = TimeSpan.FromMinutes(minutes);
uow.Repeaters.Update(old.Repeater);
2016-08-28 20:59:12 +00:00
uow.Complete();
2016-08-28 12:19:50 +00:00
}
2016-08-29 12:34:46 +00:00
old.Reset();
return old;
2016-08-28 12:19:50 +00:00
});
2016-12-16 21:44:26 +00:00
await Context.Channel.SendConfirmAsync($"🔁 Repeating **\"{rep.Repeater.Message}\"** every `{rep.Repeater.Interval.Days} day(s), {rep.Repeater.Interval.Hours} hour(s) and {rep.Repeater.Interval.Minutes} minute(s)`.").ConfigureAwait(false);
}
2016-08-28 20:59:12 +00:00
}
2016-08-28 12:19:50 +00:00
}
}