Ratelimiting done, untested
This commit is contained in:
parent
6d2c9970a7
commit
1c34b97e97
@ -5,9 +5,10 @@ using NadekoBot.Attributes;
|
||||
using NadekoBot.Extensions;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
//todo rewrite to accept msg/sec (for example 1/5 - 1 message every 5 seconds)
|
||||
//todo rewrite
|
||||
namespace NadekoBot.Modules.Administration
|
||||
{
|
||||
public partial class Administration
|
||||
@ -15,58 +16,101 @@ namespace NadekoBot.Modules.Administration
|
||||
[Group]
|
||||
public class RatelimitCommand
|
||||
{
|
||||
public static ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, DateTime>> RatelimitingChannels = new ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, DateTime>>();
|
||||
public static ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>();
|
||||
|
||||
private static readonly TimeSpan ratelimitTime = new TimeSpan(0, 0, 0, 5);
|
||||
private DiscordSocketClient _client { get; }
|
||||
|
||||
public class Ratelimiter
|
||||
{
|
||||
public class RatelimitedUser
|
||||
{
|
||||
public ulong UserId { get; set; }
|
||||
public int MessageCount { get; set; } = 0;
|
||||
}
|
||||
|
||||
public ulong ChannelId { get; set; }
|
||||
|
||||
public int MaxMessages { get; set; }
|
||||
public int PerSeconds { get; set; }
|
||||
|
||||
public CancellationTokenSource cancelSource { get; set; }
|
||||
public CancellationToken cancelToken { get; set; }
|
||||
|
||||
public ConcurrentDictionary<ulong, RatelimitedUser> Users { get; set; }
|
||||
|
||||
public bool CheckUserRatelimit(ulong id)
|
||||
{
|
||||
RatelimitedUser usr = Users.GetOrAdd(id, (key) => new RatelimitedUser() { UserId = id });
|
||||
if (usr.MessageCount == MaxMessages)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
usr.MessageCount++;
|
||||
var t = Task.Run(async () => {
|
||||
try
|
||||
{
|
||||
await Task.Delay(PerSeconds * 1000, cancelToken);
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
usr.MessageCount--;
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public RatelimitCommand()
|
||||
{
|
||||
|
||||
this._client = NadekoBot.Client;
|
||||
|
||||
_client.MessageReceived += async (umsg) =>
|
||||
_client.MessageReceived += (umsg) =>
|
||||
{
|
||||
var usrMsg = umsg as IUserMessage;
|
||||
var channel = usrMsg.Channel as ITextChannel;
|
||||
|
||||
if (channel == null || await usrMsg.IsAuthor())
|
||||
return;
|
||||
ConcurrentDictionary<ulong, DateTime> userTimePair;
|
||||
if (!RatelimitingChannels.TryGetValue(channel.Id, out userTimePair)) return;
|
||||
DateTime lastMessageTime;
|
||||
if (userTimePair.TryGetValue(usrMsg.Author.Id, out lastMessageTime))
|
||||
var t = Task.Run(async () =>
|
||||
{
|
||||
if (DateTime.Now - lastMessageTime < ratelimitTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
var usrMsg = umsg as IUserMessage;
|
||||
var channel = usrMsg.Channel as ITextChannel;
|
||||
|
||||
if (channel == null || await usrMsg.IsAuthor())
|
||||
return;
|
||||
}
|
||||
}
|
||||
userTimePair.AddOrUpdate(usrMsg.Author.Id, id => DateTime.Now, (id, dt) => DateTime.Now);
|
||||
Ratelimiter limiter;
|
||||
if (!RatelimitingChannels.TryGetValue(channel.Id, out limiter))
|
||||
return;
|
||||
|
||||
if (limiter.CheckUserRatelimit(usrMsg.Author.Id))
|
||||
await usrMsg.DeleteAsync();
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Slowmode(IUserMessage umsg)
|
||||
public async Task Slowmode(IUserMessage umsg, int msg = 1, int perSec = 5)
|
||||
{
|
||||
var channel = (ITextChannel)umsg.Channel;
|
||||
|
||||
ConcurrentDictionary<ulong, DateTime> throwaway;
|
||||
Ratelimiter throwaway;
|
||||
if (RatelimitingChannels.TryRemove(channel.Id, out throwaway))
|
||||
{
|
||||
await channel.SendMessageAsync("Slow mode disabled.").ConfigureAwait(false);
|
||||
await channel.SendMessageAsync("`Slow mode disabled.`").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
if (RatelimitingChannels.TryAdd(channel.Id, new ConcurrentDictionary<ulong, DateTime>()))
|
||||
|
||||
if (msg < 1 || perSec < 1)
|
||||
{
|
||||
await channel.SendMessageAsync("Slow mode initiated. " +
|
||||
"Users can't send more than 1 message every 5 seconds.")
|
||||
await channel.SendMessageAsync("`Invalid parameters.`");
|
||||
return;
|
||||
}
|
||||
|
||||
if (RatelimitingChannels.TryAdd(channel.Id,throwaway = new Ratelimiter() {
|
||||
ChannelId = channel.Id
|
||||
}))
|
||||
{
|
||||
await channel.SendMessageAsync("`Slow mode initiated.` " +
|
||||
$"Users can't send more than {throwaway.MaxMessages} message(s) every {throwaway.PerSeconds} second(s).")
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// todo rewrite
|
||||
namespace NadekoBot.Modules.Games.Trivia
|
||||
{
|
||||
public class TriviaGame
|
||||
|
@ -417,7 +417,7 @@ namespace NadekoBot.Modules.Music
|
||||
musicPlayer.RemoveSongAt(num - 1);
|
||||
await channel.SendMessageAsync($"🎵**Track {song.PrettyName} at position `#{num}` has been removed.**").ConfigureAwait(false);
|
||||
}
|
||||
//todo fix
|
||||
|
||||
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Remove(IUserMessage umsg, string all)
|
||||
|
@ -117,7 +117,6 @@ namespace NadekoBot.Modules.Searches
|
||||
{
|
||||
var res = await http.GetStringAsync("http://anilist.co/api/manga/search/" + Uri.EscapeUriString(query) + $"?access_token={anilistToken}").ConfigureAwait(false);
|
||||
var smallObj = JArray.Parse(res)[0];
|
||||
//todo check if successfull
|
||||
var aniData = await http.GetStringAsync("http://anilist.co/api/manga/" + smallObj["id"] + $"?access_token={anilistToken}").ConfigureAwait(false);
|
||||
|
||||
return await Task.Run(() => JsonConvert.DeserializeObject<MangaResult>(aniData)).ConfigureAwait(false);
|
||||
|
Loading…
Reference in New Issue
Block a user