hermes-client/Twitch/Socket/Handlers/ChannelRaidHandler.cs
2024-08-10 19:28:48 +00:00

92 lines
3.4 KiB
C#

using Serilog;
using TwitchChatTTS.Twitch.Socket.Messages;
namespace TwitchChatTTS.Twitch.Socket.Handlers
{
public class ChannelRaidHandler : ITwitchSocketHandler
{
public string Name => "channel.raid";
private readonly TwitchApiClient _api;
private readonly User _user;
private readonly ILogger _logger;
private readonly object _lock;
public ChannelRaidHandler(TwitchApiClient api, User user, ILogger logger)
{
_api = api;
_user = user;
_logger = logger;
_lock = new object();
}
public async Task Execute(TwitchWebsocketClient sender, object data)
{
if (data is not ChannelRaidMessage message)
return;
_logger.Information($"A raid has started. Starting raid spam prevention. [from: {message.FromBroadcasterUserLogin}][from id: {message.FromBroadcasterUserId}].");
EventResponse<ChatterMessage>? chatters = null;
if (!_user.Raids.ContainsKey(message.ToBroadcasterUserId))
{
chatters = await _api.GetChatters(_user.TwitchUserId.ToString(), _user.TwitchUserId.ToString());
if (chatters?.Data == null)
{
var extraErrorInfo = _user.TwitchUserId.ToString() != message.ToBroadcasterUserId ? " Ensure you have moderator status in your joined channel(s) to prevent raid spam." : string.Empty;
_logger.Error("Could not fetch the list of chatters in chat." + extraErrorInfo);
return;
}
}
var startDate = DateTime.Now;
var endDate = startDate + TimeSpan.FromSeconds(30);
lock (_lock)
{
if (_user.Raids.TryGetValue(message.ToBroadcasterUserId, out var raid))
raid.RaidSpamPreventionEndDate = endDate;
else
{
var chatterIds = chatters!.Data!.Select(c => long.Parse(c.UserId));
_user.Raids.Add(message.ToBroadcasterUserId, new RaidInfo(endDate, new HashSet<long>(chatterIds)));
}
}
Task.Run(async () => await EndOfRaidSpamProtection(message.ToBroadcasterUserId, endDate));
}
private async Task EndOfRaidSpamProtection(string raidedId, DateTime endDate)
{
await Task.Delay(endDate - DateTime.Now);
lock (_lock)
{
if (_user.Raids.TryGetValue(raidedId, out var raid))
{
if (raid.RaidSpamPreventionEndDate == endDate)
{
_logger.Information("Raid message spam prevention ended.");
_user.Raids.Remove(raidedId);
}
else
_logger.Debug("Raid spam prevention would have stopped now if it wasn't for the consecutive raid.");
}
else
_logger.Error("Something went wrong ending a raid spam prevention.");
}
}
}
public sealed class RaidInfo
{
public DateTime RaidSpamPreventionEndDate { get; set; }
public HashSet<long> Chatters { get; set; }
public RaidInfo(DateTime raidEnd, HashSet<long> chatters)
{
RaidSpamPreventionEndDate = raidEnd;
Chatters = chatters;
}
}
}