mirror of
https://github.com/daffyyyy/CS2-SimpleAdmin.git
synced 2026-02-17 18:39:07 +00:00
- Fixed (@all,@team,@lifestate) spam with discord webhook - Currently `small` actions for ban optimizations
168 lines
6.0 KiB
C#
168 lines
6.0 KiB
C#
using System.Collections.Concurrent;
|
|
using CS2_SimpleAdmin.Models;
|
|
using Dapper;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace CS2_SimpleAdmin.Managers;
|
|
|
|
internal class CacheManager
|
|
{
|
|
private readonly ConcurrentDictionary<int, BanRecord> _banCache = new();
|
|
private readonly ConcurrentDictionary<ulong, (HashSet<string> ips, DateTime used_at)> _playerIpsCache = new();
|
|
|
|
private DateTime _lastUpdateTime = DateTime.MinValue;
|
|
private bool _isInitialized;
|
|
|
|
public async Task InitializeCacheAsync()
|
|
{
|
|
if (CS2_SimpleAdmin.Database == null) return;
|
|
if (!CS2_SimpleAdmin.ServerLoaded)
|
|
return;
|
|
if (_isInitialized) return;
|
|
|
|
try
|
|
{
|
|
await using var connection = await CS2_SimpleAdmin.Database.GetConnectionAsync();
|
|
var bans = await connection.QueryAsync<BanRecord>(
|
|
"""
|
|
SELECT
|
|
id AS Id,
|
|
player_name AS PlayerName,
|
|
player_steamid AS PlayerSteamId,
|
|
player_ip AS PlayerIp,
|
|
admin_steamid AS AdminSteamId,
|
|
admin_name AS AdminName,
|
|
reason AS Reason,
|
|
duration AS Duration,
|
|
ends AS Ends,
|
|
created AS Created,
|
|
server_id AS ServerId,
|
|
status AS Status,
|
|
updated_at AS UpdatedAt
|
|
FROM sa_bans
|
|
""");
|
|
var ipHistory = await connection.QueryAsync<(ulong steamid, string address, DateTime used_at)>(
|
|
"SELECT steamid, address, used_at FROM sa_players_ips");
|
|
|
|
|
|
foreach (var ban in bans)
|
|
{
|
|
_banCache.TryAdd(ban.Id, ban);
|
|
}
|
|
|
|
foreach (var group in ipHistory.GroupBy(x => x.steamid))
|
|
{
|
|
var ips = new HashSet<string>(group.Select(x => x.address));
|
|
var lastUsed = group.Max(x => x.used_at);
|
|
_playerIpsCache[group.Key] = (ips, lastUsed);
|
|
}
|
|
|
|
_lastUpdateTime = DateTime.Now;
|
|
_isInitialized = true;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine(e.ToString());
|
|
}
|
|
}
|
|
|
|
public async Task RefreshCacheAsync()
|
|
{
|
|
if (CS2_SimpleAdmin.Database == null) return;
|
|
if (!_isInitialized) return;
|
|
|
|
try
|
|
{
|
|
await using var connection = await CS2_SimpleAdmin.Database.GetConnectionAsync();
|
|
var updatedBans = (await connection.QueryAsync<BanRecord>(
|
|
"SELECT * FROM `sa_bans` WHERE updated_at > @lastUpdate OR created > @lastUpdate ORDER BY updated_at DESC",
|
|
new { lastUpdate = _lastUpdateTime }
|
|
)).ToList();
|
|
|
|
var ipHistory = await connection.QueryAsync<(ulong steamid, string address, DateTime used_at)>(
|
|
"SELECT steamid, address, used_at FROM sa_players_ips");
|
|
|
|
// foreach (var group in ipHistory.GroupBy(x => x.steamid))
|
|
// {
|
|
// var ips = new HashSet<string>(group.Select(x => x.address));
|
|
// var lastUsed = group.Max(x => x.used_at);
|
|
// _playerIpsCache[group.Key] = (ips, lastUsed);
|
|
// }
|
|
|
|
var groupedData = ipHistory.GroupBy(x => x.steamid).ToList();
|
|
Parallel.ForEach(groupedData, group =>
|
|
{
|
|
var ips = new HashSet<string>(group.Select(x => x.address));
|
|
var lastUsed = group.Max(x => x.used_at);
|
|
|
|
_playerIpsCache.AddOrUpdate(
|
|
group.Key,
|
|
_ => (ips, lastUsed),
|
|
(_, existing) =>
|
|
{
|
|
existing.ips.UnionWith(ips);
|
|
return (existing.ips,
|
|
lastUsed > existing.used_at ? lastUsed : existing.used_at);
|
|
});
|
|
});
|
|
|
|
if (updatedBans.Count == 0)
|
|
return;
|
|
|
|
foreach (var ban in updatedBans)
|
|
{
|
|
_banCache.AddOrUpdate(ban.Id, ban, (_, _) => ban);
|
|
}
|
|
|
|
_lastUpdateTime = DateTime.Now;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
|
|
public List<BanRecord> GetAllBans() => _banCache.Values.ToList();
|
|
public List<BanRecord> GetActiveBans() => _banCache.Values.Where(b => b.Status == "ACTIVE").ToList();
|
|
public List<BanRecord> GetPlayerBansBySteamId(string steamId) => _banCache.Values.Where(b => b.PlayerSteamId == steamId).ToList();
|
|
|
|
|
|
private bool IsIpBanned(string ipAddress)
|
|
{
|
|
return _banCache.Values.Any(b =>
|
|
b.Status == "ACTIVE" &&
|
|
!string.IsNullOrEmpty(b.PlayerIp) &&
|
|
b.PlayerIp.Equals(ipAddress, StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
|
|
public bool IsPlayerBanned(string? steamId, string? ipAddress) =>
|
|
_banCache.Values.Any(b =>
|
|
b.Status == "ACTIVE" && (
|
|
(steamId != null &&
|
|
b.PlayerSteamId != null &&
|
|
b.PlayerSteamId.Equals(steamId, StringComparison.OrdinalIgnoreCase)) ||
|
|
(ipAddress != null &&
|
|
b.PlayerIp != null &&
|
|
b.PlayerIp.Equals(ipAddress, StringComparison.OrdinalIgnoreCase))
|
|
));
|
|
|
|
public bool IsPlayerOrAnyIpBanned(ulong steamId)
|
|
{
|
|
var steamIdStr = steamId.ToString();
|
|
if (_banCache.Values.Any(b =>
|
|
b.Status == "ACTIVE" &&
|
|
b.PlayerSteamId?.Equals(steamIdStr, StringComparison.OrdinalIgnoreCase) == true))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return _playerIpsCache.TryGetValue(steamId, out var ipList) && ipList.ips.Any(IsIpBanned);
|
|
}
|
|
|
|
public bool HasIpForPlayer(ulong steamId, string ipAddress)
|
|
{
|
|
return _playerIpsCache.TryGetValue(steamId, out var ipList)
|
|
&& ipList.ips.Contains(ipAddress);
|
|
}
|
|
|
|
} |