Merge branch 'feature/antiflood' into dev

This commit is contained in:
2022-02-16 19:45:01 +03:00
4 changed files with 89 additions and 4 deletions
+9
View File
@@ -0,0 +1,9 @@
using Telegram.Bot.Types;
namespace Kruzya.TelegramBot.Core.Service;
public interface IAntiFlood
{
public bool IsUserFlooding(Chat chat, User user);
public void RecordAction(Chat chat, User user);
}
+63
View File
@@ -0,0 +1,63 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Configuration;
using Telegram.Bot.Types;
namespace Kruzya.TelegramBot.Core.Service;
public class MemoryAntiFloodService : IAntiFlood
{
private IDictionary<string, IList<DateTime>> _floodUsers;
private IDictionary<string, DateTime> _bannedUsers;
private int _floodStartsAfter = 3;
private TimeSpan _banningTimeSpan;
public MemoryAntiFloodService(IConfiguration configuration)
{
_floodUsers = new Dictionary<string, IList<DateTime>>();
_bannedUsers = new Dictionary<string, DateTime>();
_floodStartsAfter = configuration.GetValue<int>("FloodActions");
_banningTimeSpan = TimeSpan.FromMinutes(configuration.GetValue<double>("FloodBanTime"));
}
public bool IsUserFlooding(Chat chat, User user)
{
var dictKey = DictKey(chat, user);
if (_bannedUsers.TryGetValue(dictKey, out var expirationTime))
{
if (DateTime.UtcNow <= expirationTime)
{
expirationTime = DateTime.MinValue;
_bannedUsers.Remove(dictKey);
}
}
return (DateTime.UtcNow >= expirationTime);
}
public void RecordAction(Chat chat, User user)
{
var dictKey = DictKey(chat, user);
if (!_floodUsers.TryGetValue(dictKey, out var actionTimeList))
{
actionTimeList = new List<DateTime>();
}
actionTimeList.Add(DateTime.UtcNow);
actionTimeList = actionTimeList.Where(e => e.Subtract(_banningTimeSpan) <= DateTime.UtcNow).ToList();
_floodUsers[dictKey] = actionTimeList;
if (actionTimeList.Count > _floodStartsAfter)
{
actionTimeList.Clear();
_bannedUsers[dictKey] = DateTime.UtcNow.Add(_banningTimeSpan);
}
}
private string DictKey(Chat chat, User user)
{
return $"{chat.Id}-{user.Id}";
}
}
+1
View File
@@ -43,6 +43,7 @@ namespace Kruzya.TelegramBot.Core
services.AddSingleton<ICacheStorage<long, User>, MemoryCache<long, User>>(); services.AddSingleton<ICacheStorage<long, User>, MemoryCache<long, User>>();
services.AddSingleton<UserService>(); services.AddSingleton<UserService>();
services.AddSingleton<IAntiFlood, MemoryAntiFloodService>();
// Trigger module handlers. // Trigger module handlers.
_core.Modules.ConfigureServices(services); _core.Modules.ConfigureServices(services);
+14 -2
View File
@@ -19,6 +19,7 @@ public class Reputation : CommonHandler
private readonly UserService _userService; private readonly UserService _userService;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IReputation _reputationService; private readonly IReputation _reputationService;
private readonly IAntiFlood _antiFlood;
private static readonly List<string> RepUpChars = new() private static readonly List<string> RepUpChars = new()
{ {
@@ -45,10 +46,12 @@ public class Reputation : CommonHandler
CoreContext db, CoreContext db,
UserService userService, UserService userService,
IReputation reputationService, IReputation reputationService,
IAntiFlood antiFlood,
ILogger<Reputation> logger) : base(db) ILogger<Reputation> logger) : base(db)
{ {
_reputationService = reputationService; _reputationService = reputationService;
_userService = userService; _userService = userService;
_antiFlood = antiFlood;
_logger = logger; _logger = logger;
} }
@@ -71,8 +74,17 @@ public class Reputation : CommonHandler
if (canChangeRep && (RepUpChars.Contains(text) || RepDownChars.Contains(text))) if (canChangeRep && (RepUpChars.Contains(text) || RepDownChars.Contains(text)))
{ {
var senderRepCount = await GetUserReputation(From); if (!_userService.IsUserSuper(From))
{
if (_antiFlood.IsUserFlooding(Chat, From))
{
return;
}
_antiFlood.RecordAction(Chat, From);
}
var senderRepCount = await GetUserReputation(From);
if (senderRepCount < 0) if (senderRepCount < 0)
{ {
await Reply(new HtmlString() await Reply(new HtmlString()
@@ -143,7 +155,7 @@ public class Reputation : CommonHandler
i++; i++;
} }
await Bot.SendTextMessageAsync(Chat, msg.ToString(), ParseMode.Html, await Bot.SendTextMessageAsync(Chat!, msg.ToString(), ParseMode.Html,
disableNotification: true); disableNotification: true);
} }