[code-watcher] handle message edit & message delayed delete service

Message delayed deleter service deals with issue when you need to delete some message with delay without blocking the execution. This is replacement for dumb Task.Delay call. Use of it could be used before as exploit, to stop responding for a long time.
This commit is contained in:
Andriy
2022-07-07 17:15:40 +03:00
parent e1ec7937fe
commit a4f05bacab
4 changed files with 99 additions and 9 deletions
+9 -1
View File
@@ -1,9 +1,17 @@
using Kruzya.TelegramBot.Core;
using System.Collections.Concurrent;
using Kruzya.TelegramBot.Core;
using Microsoft.Extensions.DependencyInjection;
namespace West.TelegramBot.CodeWatcher
{
public class CodeWatcher : Module
{
public CodeWatcher(Core core) : base(core) {}
public override void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ConcurrentBag<DeleteRequest>>();
services.AddHostedService<DeleteService>();
}
}
}
+10
View File
@@ -0,0 +1,10 @@
using Telegram.Bot.Types;
namespace West.TelegramBot.CodeWatcher;
public class DeleteRequest
{
public ChatId ChatId { get; set; }
public int MessageId { get; set; }
public DateTime DeleteAt { get; set; }
}
+59
View File
@@ -0,0 +1,59 @@
using System.Collections.Concurrent;
using BotFramework.Abstractions;
using Kruzya.TelegramBot.Core.Service;
using Microsoft.Extensions.Logging;
using Telegram.Bot;
using Telegram.Bot.Exceptions;
namespace West.TelegramBot.CodeWatcher;
public class DeleteService : AbstractTimedHostedService
{
private readonly ConcurrentBag<DeleteRequest> _deleteRequests;
protected override TimeSpan TimerPeriod => TimeSpan.FromSeconds(10);
public DeleteService(ILogger<DeleteService> logger, IBotInstance bot, ConcurrentBag<DeleteRequest> deleteRequests) : base(logger,
bot)
{
_deleteRequests = deleteRequests;
}
protected override async Task OnRun()
{
var now = DateTime.Now;
var skippedRequestList = new List<DeleteRequest>();
_logger.LogDebug("Spinning up the delete requests loop. Request count: {RequestCount}", _deleteRequests.Count);
for (var i = 0; i < _deleteRequests.Count; i++)
{
if (!_deleteRequests.TryTake(out var request))
{
_logger.LogDebug("Nothing to take, breaking...");
break;
}
if (request.DeleteAt < now)
{
try
{
await _bot.BotClient.DeleteMessageAsync(request.ChatId, request.MessageId);
}
catch (ApiRequestException e)
{
_logger.LogError("Error deleting message, code - {ErrorCode}, msg - {ErrorMessage}", e.ErrorCode,
e.Message);
}
}
else
{
_logger.LogDebug("Skipping {MessageId}", request.MessageId);
skippedRequestList.Add(request);
}
}
foreach (var request in skippedRequestList)
{
_deleteRequests.Add(request);
}
}
}
+19 -6
View File
@@ -1,4 +1,5 @@
using BotFramework;
using System.Collections.Concurrent;
using BotFramework;
using BotFramework.Attributes;
using BotFramework.Enums;
using Kruzya.TelegramBot.Core.Extensions;
@@ -10,12 +11,19 @@ namespace West.TelegramBot.CodeWatcher;
public class Handler : BotEventHandler
{
[Message(InChat.Public, MessageFlag.HasText)]
private readonly ConcurrentBag<DeleteRequest> _requests;
public Handler(ConcurrentBag<DeleteRequest> requests)
{
_requests = requests;
}
[Update(InChat.Public, UpdateFlag.Message | UpdateFlag.EditedMessage)]
public async Task HandleMessage()
{
var message = RawUpdate.Message!;
var message = RawUpdate.Message ?? RawUpdate.EditedMessage;
if (message.Entities == null)
if (message?.Entities == null)
{
return;
}
@@ -56,7 +64,12 @@ public class Handler : BotEventHandler
"Вместо этого загрузите его на https://pastebin.com и отправьте в виде ссылки.",
ParseMode.Html);
await Task.Delay(TimeSpan.FromMinutes(1));
await Bot.DeleteMessageAsync(Chat.Id, notifyMsg.MessageId);
// TODO: maybe write a wrapper-service around collection to avoid direct interactions with the collection, West, 07.07.2022, 16:53
_requests.Add(new DeleteRequest
{
ChatId = notifyMsg.Chat.Id,
MessageId = notifyMsg.MessageId,
DeleteAt = DateTime.Now.AddSeconds(30)
});
}
}