Files
Radicade/Server/PlayersBanned/GameBlockMonitor.cs
T
2026-10-16 23:33:13 -07:00

117 lines
2.3 KiB
C#

using Microsoft.EntityFrameworkCore;
using RadicadeServer.DB;
namespace RadicadeServer.Utils
{
public static class GameBlockMonitor
{
private static readonly object Lock = new();
private static readonly SemaphoreSlim RefreshGate = new(1, 1);
private static Dictionary<string, DateTime?> Active = new();
private static DateTime LastRefresh = DateTime.MinValue;
private const double RefreshIntervalSeconds = 10;
public static async Task<bool> IsBlockedAsync(IDbContextFactory<RecDBContext> factory, string ipAddress)
{
if (string.IsNullOrWhiteSpace(ipAddress)) return false;
DateTime lastRefresh;
lock (Lock) lastRefresh = LastRefresh;
if ((DateTime.UtcNow - lastRefresh).TotalSeconds > RefreshIntervalSeconds)
await RefreshAsync(factory);
lock (Lock)
{
if (Active.TryGetValue(NormalizeIp(ipAddress), out var expiresAt))
return !expiresAt.HasValue || expiresAt.Value > DateTime.UtcNow;
return false;
}
}
public static void Invalidate()
{
lock (Lock) LastRefresh = DateTime.MinValue;
}
public static async Task RefreshAsync(IDbContextFactory<RecDBContext> factory)
{
await RefreshGate.WaitAsync();
try
{
DateTime lastRefresh;
lock (Lock) lastRefresh = LastRefresh;
if ((DateTime.UtcNow - lastRefresh).TotalSeconds <= RefreshIntervalSeconds)
return;
try
{
await using var db = await factory.CreateDbContextAsync();
var now = DateTime.UtcNow;
var rows = await db.GameBlocks.AsNoTracking().ToListAsync();
var expired = rows.Where(b => b.ExpiresAt.HasValue && b.ExpiresAt.Value < now).ToList();
if (expired.Count > 0)
{
db.GameBlocks.RemoveRange(expired);
await db.SaveChangesAsync();
}
var active = new Dictionary<string, DateTime?>();
foreach (var row in rows.Where(b => !expired.Contains(b)))
active[NormalizeIp(row.IpAddress)] = row.ExpiresAt;
lock (Lock)
{
Active = active;
LastRefresh = DateTime.UtcNow;
}
}
catch
{
lock (Lock) LastRefresh = DateTime.UtcNow;
}
}
finally
{
RefreshGate.Release();
}
}
public static string NormalizeIp(string ip)
{
ip = (ip ?? "").Trim();
if (ip.StartsWith("::ffff:", StringComparison.OrdinalIgnoreCase))
ip = ip.Substring("::ffff:".Length);
return ip;
}
}
}