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

123 lines
4.6 KiB
C#
Raw Normal View History

2016-08-20 14:02:06 +00:00
using Discord;
using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Extensions;
2016-10-18 01:03:46 +00:00
using NLog;
2016-08-20 14:02:06 +00:00
using System;
using System.Collections.Concurrent;
2016-09-03 13:04:07 +00:00
using System.Threading;
2016-08-20 14:02:06 +00:00
using System.Threading.Tasks;
namespace NadekoBot.Modules.Administration
2016-08-20 14:02:06 +00:00
{
public partial class Administration
{
[Group]
public class RatelimitCommand : NadekoSubmodule
2016-08-20 14:02:06 +00:00
{
2016-09-03 13:04:07 +00:00
public static ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>();
2017-02-14 19:35:10 +00:00
private new static readonly Logger _log;
2016-08-20 14:02:06 +00:00
2016-09-03 13:04:07 +00:00
public class Ratelimiter
2016-08-20 14:02:06 +00:00
{
2016-09-03 13:04:07 +00:00
public class RatelimitedUser
{
public ulong UserId { get; set; }
public int MessageCount { get; set; } = 0;
}
2016-08-20 14:02:06 +00:00
2016-09-03 13:04:07 +00:00
public ulong ChannelId { get; set; }
2016-08-20 14:02:06 +00:00
2016-09-03 13:04:07 +00:00
public int MaxMessages { get; set; }
public int PerSeconds { get; set; }
2016-09-03 15:50:10 +00:00
public CancellationTokenSource cancelSource { get; set; } = new CancellationTokenSource();
2016-09-03 13:04:07 +00:00
2016-09-03 15:50:10 +00:00
public ConcurrentDictionary<ulong, RatelimitedUser> Users { get; set; } = new ConcurrentDictionary<ulong, RatelimitedUser>();
2016-09-03 13:04:07 +00:00
public bool CheckUserRatelimit(ulong id)
2016-08-20 14:02:06 +00:00
{
2017-02-14 13:30:21 +00:00
var usr = Users.GetOrAdd(id, (key) => new RatelimitedUser() { UserId = id });
2016-09-03 13:04:07 +00:00
if (usr.MessageCount == MaxMessages)
2016-08-20 14:02:06 +00:00
{
2016-09-03 13:04:07 +00:00
return true;
}
2017-02-14 13:30:21 +00:00
usr.MessageCount++;
var _ = Task.Run(async () =>
2016-09-03 13:04:07 +00:00
{
2017-02-14 13:30:21 +00:00
try
2016-12-28 06:56:44 +00:00
{
2017-02-14 13:30:21 +00:00
await Task.Delay(PerSeconds * 1000, cancelSource.Token);
}
catch (OperationCanceledException) { }
usr.MessageCount--;
});
return false;
2016-09-03 13:04:07 +00:00
}
}
2016-12-08 17:35:34 +00:00
static RatelimitCommand()
2016-09-03 13:04:07 +00:00
{
2016-12-28 06:56:44 +00:00
_log = LogManager.GetCurrentClassLogger();
2016-09-03 13:04:07 +00:00
2016-12-28 06:56:44 +00:00
NadekoBot.Client.MessageReceived += async (umsg) =>
{
try
{
var usrMsg = umsg as IUserMessage;
2017-02-14 19:35:10 +00:00
var channel = usrMsg?.Channel as ITextChannel;
2016-09-03 13:04:07 +00:00
2016-12-28 06:56:44 +00:00
if (channel == null || usrMsg.IsAuthor())
return;
Ratelimiter limiter;
if (!RatelimitingChannels.TryGetValue(channel.Id, out limiter))
return;
2016-09-03 13:04:07 +00:00
2016-12-28 06:56:44 +00:00
if (limiter.CheckUserRatelimit(usrMsg.Author.Id))
await usrMsg.DeleteAsync();
}
catch (Exception ex) { _log.Warn(ex); }
};
2016-08-20 14:02:06 +00:00
}
[NadekoCommand, Usage, Description, Aliases]
2016-08-20 14:02:06 +00:00
[RequireContext(ContextType.Guild)]
2016-12-16 18:43:57 +00:00
[RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Slowmode()
2016-08-20 14:02:06 +00:00
{
2016-09-03 13:04:07 +00:00
Ratelimiter throwaway;
2016-12-17 00:16:14 +00:00
if (RatelimitingChannels.TryRemove(Context.Channel.Id, out throwaway))
2016-08-20 14:02:06 +00:00
{
2016-09-03 15:50:10 +00:00
throwaway.cancelSource.Cancel();
2017-02-14 19:35:10 +00:00
await ReplyConfirmLocalized("slowmode_disabled").ConfigureAwait(false);
2016-08-20 14:02:06 +00:00
}
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
2016-12-16 18:43:57 +00:00
[RequireUserPermission(GuildPermission.ManageMessages)]
2016-12-17 00:16:14 +00:00
public async Task Slowmode(int msg, int perSec)
{
2016-12-17 00:16:14 +00:00
await Slowmode().ConfigureAwait(false); // disable if exists
if (msg < 1 || perSec < 1 || msg > 100 || perSec > 3600)
2016-09-03 13:04:07 +00:00
{
2017-02-14 19:35:10 +00:00
await ReplyErrorLocalized("invalid_params").ConfigureAwait(false);
2016-09-03 13:04:07 +00:00
return;
}
var toAdd = new Ratelimiter()
{
2016-12-17 00:16:14 +00:00
ChannelId = Context.Channel.Id,
2016-09-03 15:50:10 +00:00
MaxMessages = msg,
PerSeconds = perSec,
};
2016-12-17 00:16:14 +00:00
if(RatelimitingChannels.TryAdd(Context.Channel.Id, toAdd))
2016-08-20 14:02:06 +00:00
{
2017-02-14 19:35:10 +00:00
await Context.Channel.SendConfirmAsync(GetText("slowmode_init"),
GetText("slowmode_desc", Format.Bold(toAdd.MaxMessages.ToString()), Format.Bold(toAdd.PerSeconds.ToString())))
2016-08-20 14:02:06 +00:00
.ConfigureAwait(false);
}
}
}
}
2016-12-28 06:56:44 +00:00
}