1.7.7-alpha
- Fixed (@all,@team,@lifestate) spam with discord webhook - Currently `small` actions for ban optimizations
This commit is contained in:
parent
b6c876d709
commit
f69f1277f8
20 changed files with 460 additions and 241 deletions
168
CS2-SimpleAdmin/Managers/CacheManager.cs
Normal file
168
CS2-SimpleAdmin/Managers/CacheManager.cs
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue