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

163 lines
6.0 KiB
C#
Raw Normal View History

2016-08-28 12:19:50 +00:00
using Discord;
using Discord.Commands;
2016-08-29 12:34:46 +00:00
using Discord.WebSocket;
2016-08-28 20:59:12 +00:00
using NadekoBot.Attributes;
using NadekoBot.Services;
using NadekoBot.Services.Database;
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.Collections.Generic;
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]
public class RepeatCommands
{
2016-08-29 12:34:46 +00:00
public ConcurrentDictionary<ulong, RepeatRunner> repeaters;
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;
this.Channel = channel ?? NadekoBot.Client.GetGuild(repeater.GuildId)?.GetTextChannel(repeater.ChannelId);
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;
try
{
while (!token.IsCancellationRequested)
{
await Task.Delay(Repeater.Interval, token).ConfigureAwait(false);
2016-10-12 21:41:31 +00:00
try { 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-08-28 20:59:12 +00:00
public 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)]
[RequirePermission(GuildPermission.ManageMessages)]
2016-08-29 12:34:46 +00:00
public async Task RepeatInvoke(IUserMessage imsg)
2016-08-28 12:19:50 +00:00
{
2016-08-28 20:59:12 +00:00
var channel = (ITextChannel)imsg.Channel;
2016-08-29 12:34:46 +00:00
RepeatRunner rep;
2016-08-28 20:59:12 +00:00
if (!repeaters.TryGetValue(channel.Id, out rep))
2016-08-28 12:19:50 +00:00
{
2016-08-28 20:59:12 +00:00
await channel.SendMessageAsync("`No repeating message found on this server.`").ConfigureAwait(false);
return;
2016-08-28 12:19:50 +00:00
}
2016-08-29 12:34:46 +00:00
rep.Reset();
await 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)]
public async Task Repeat(IUserMessage imsg)
2016-08-28 20:59:12 +00:00
{
var channel = (ITextChannel)imsg.Channel;
2016-08-29 12:34:46 +00:00
RepeatRunner rep;
if (repeaters.TryRemove(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();
await channel.SendMessageAsync("`Stopped repeating a message.`").ConfigureAwait(false);
2016-08-28 20:59:12 +00:00
}
else
await channel.SendMessageAsync("`No message is repeating.`").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task Repeat(IUserMessage imsg, int minutes, [Remainder] string message)
{
var channel = (ITextChannel)imsg.Channel;
if (minutes < 1 || minutes > 1500)
return;
if (string.IsNullOrWhiteSpace(message))
return;
RepeatRunner rep;
2016-05-23 20:50:16 +00:00
2016-08-28 20:59:12 +00:00
rep = repeaters.AddOrUpdate(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
{
ChannelId = channel.Id,
GuildId = channel.Guild.Id,
Interval = TimeSpan.FromMinutes(minutes),
Message = message,
};
uow.Repeaters.Add(localRep);
uow.Complete();
return new RepeatRunner(localRep, 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
});
await channel.SendMessageAsync($"Repeating \"{rep.Repeater.Message}\" every {rep.Repeater.Interval} minutes").ConfigureAwait(false);
}
2016-08-28 20:59:12 +00:00
}
2016-08-28 12:19:50 +00:00
}
2016-08-28 20:59:12 +00:00
}