1.7.7-alpha-associated-accounts
- Added possibility to view player associated account (by ip)
This commit is contained in:
parent
d34ca64970
commit
d75a092047
20 changed files with 105 additions and 17 deletions
|
|
@ -2,14 +2,15 @@ using System.Collections.Concurrent;
|
|||
using CS2_SimpleAdmin.Models;
|
||||
using Dapper;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ZLinq;
|
||||
|
||||
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 readonly HashSet<string> _cachedIgnoredIps = [..CS2_SimpleAdmin.Instance.Config.OtherSettings.IgnoredIps];
|
||||
private readonly ConcurrentDictionary<ulong, (HashSet<string> ips, DateTime usedAt, string playerName)> _playerIpsCache = new();
|
||||
private HashSet<string> _cachedIgnoredIps;
|
||||
|
||||
private DateTime _lastUpdateTime = DateTime.MinValue;
|
||||
private bool _isInitialized;
|
||||
|
|
@ -20,6 +21,8 @@ internal class CacheManager
|
|||
if (!CS2_SimpleAdmin.ServerLoaded)
|
||||
return;
|
||||
if (_isInitialized) return;
|
||||
|
||||
_cachedIgnoredIps = [..CS2_SimpleAdmin.Instance.Config.OtherSettings.IgnoredIps];
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -42,8 +45,8 @@ internal class CacheManager
|
|||
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");
|
||||
var ipHistory = await connection.QueryAsync<(ulong steamid, string? name, string address, DateTime used_at)>(
|
||||
"SELECT steamid, name, address, used_at FROM sa_players_ips ORDER BY used_at DESC");
|
||||
|
||||
|
||||
foreach (var ban in bans)
|
||||
|
|
@ -55,7 +58,10 @@ internal class CacheManager
|
|||
{
|
||||
var ips = new HashSet<string>(group.Select(x => x.address));
|
||||
var lastUsed = group.Max(x => x.used_at);
|
||||
_playerIpsCache[group.Key] = (ips, lastUsed);
|
||||
var playerName = group.FirstOrDefault(x => !string.IsNullOrEmpty(x.name)).name
|
||||
?? CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown";
|
||||
|
||||
_playerIpsCache[group.Key] = (ips, lastUsed, playerName);
|
||||
}
|
||||
|
||||
_lastUpdateTime = DateTime.Now;
|
||||
|
|
@ -80,8 +86,8 @@ internal class CacheManager
|
|||
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");
|
||||
var ipHistory = await connection.QueryAsync<(ulong steamid, string? name, string address, DateTime used_at)>(
|
||||
"SELECT steamid, name, address, used_at FROM sa_players_ips ORDER BY used_at DESC");
|
||||
|
||||
// foreach (var group in ipHistory.GroupBy(x => x.steamid))
|
||||
// {
|
||||
|
|
@ -90,20 +96,39 @@ internal class CacheManager
|
|||
// _playerIpsCache[group.Key] = (ips, lastUsed);
|
||||
// }
|
||||
|
||||
var groupedData = ipHistory.GroupBy(x => x.steamid).ToList();
|
||||
var groupedData = ipHistory
|
||||
.GroupBy(x => x.steamid)
|
||||
.AsParallel()
|
||||
.ToList();
|
||||
|
||||
Parallel.ForEach(groupedData, group =>
|
||||
{
|
||||
var ips = new HashSet<string>(group.Select(x => x.address));
|
||||
var lastUsed = group.Max(x => x.used_at);
|
||||
var ips = new HashSet<string>(
|
||||
group.Select(x => x.address),
|
||||
StringComparer.OrdinalIgnoreCase
|
||||
);
|
||||
|
||||
var lastUsed = group.Max(x => x.used_at);
|
||||
var playerName = group
|
||||
.OrderByDescending(x => x.used_at) // Prefer newer records
|
||||
.Select(x => x.name)
|
||||
.FirstOrDefault(name => !string.IsNullOrEmpty(name))
|
||||
?? CS2_SimpleAdmin._localizer?["sa_unknown"]
|
||||
?? "Unknown";
|
||||
|
||||
_playerIpsCache.AddOrUpdate(
|
||||
group.Key,
|
||||
_ => (ips, lastUsed),
|
||||
// Add new entry
|
||||
_ => (ips, lastUsed, playerName),
|
||||
// Update existing
|
||||
(_, existing) =>
|
||||
{
|
||||
existing.ips.UnionWith(ips);
|
||||
return (existing.ips,
|
||||
lastUsed > existing.used_at ? lastUsed : existing.used_at);
|
||||
existing.ips.UnionWith(ips);
|
||||
return (
|
||||
existing.ips,
|
||||
lastUsed > existing.usedAt ? lastUsed : existing.usedAt,
|
||||
string.IsNullOrEmpty(existing.playerName) ? playerName : existing.playerName
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -126,7 +151,13 @@ internal class CacheManager
|
|||
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();
|
||||
|
||||
public List<(ulong SteamId, string PlayerName)> GetAccountsByIp(string ipAddress)
|
||||
{
|
||||
return _playerIpsCache.AsValueEnumerable()
|
||||
.Where(kvp => kvp.Value.ips.Contains(ipAddress))
|
||||
.Select(kvp => (kvp.Key, kvp.Value.playerName))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private bool IsIpBanned(string ipAddress)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -137,6 +137,10 @@ public class PlayerManager
|
|||
CS2_SimpleAdmin._logger?.LogError(
|
||||
$"Unable to save ip address for {CS2_SimpleAdmin.PlayersInfo[userId].Name} ({ipAddress}) {ex.Message}");
|
||||
}
|
||||
|
||||
// Get all accounts associated to the player (ip address)
|
||||
CS2_SimpleAdmin.PlayersInfo[userId].AccountsAssociated =
|
||||
CS2_SimpleAdmin.Instance.CacheManager.GetAccountsByIp(ipAddress);
|
||||
}
|
||||
|
||||
try
|
||||
|
|
@ -204,6 +208,8 @@ public class PlayerManager
|
|||
|
||||
if (CS2_SimpleAdmin.Instance.Config.OtherSettings.NotifyPenaltiesToAdminOnConnect && fullConnect)
|
||||
{
|
||||
var associatedAcccountsChunks = CS2_SimpleAdmin.PlayersInfo[userId].AccountsAssociated.ChunkBy(5).ToList();
|
||||
|
||||
await Server.NextFrameAsync(() =>
|
||||
{
|
||||
foreach (var admin in Helper.GetValidPlayers()
|
||||
|
|
@ -212,6 +218,7 @@ public class PlayerManager
|
|||
p.Connected == PlayerConnectedState.PlayerConnected && !CS2_SimpleAdmin.AdminDisabledJoinComms.Contains(p.SteamID)))
|
||||
{
|
||||
if (CS2_SimpleAdmin._localizer != null && admin != player)
|
||||
{
|
||||
admin.SendLocalizedMessage(CS2_SimpleAdmin._localizer, "sa_admin_penalty_info",
|
||||
player.PlayerName,
|
||||
CS2_SimpleAdmin.PlayersInfo[userId].TotalBans,
|
||||
|
|
@ -220,6 +227,16 @@ public class PlayerManager
|
|||
CS2_SimpleAdmin.PlayersInfo[userId].TotalSilences,
|
||||
CS2_SimpleAdmin.PlayersInfo[userId].TotalWarns
|
||||
);
|
||||
|
||||
foreach (var chunk in associatedAcccountsChunks)
|
||||
{
|
||||
admin.SendLocalizedMessage(CS2_SimpleAdmin._localizer, "sa_admin_associated_accounts",
|
||||
player.PlayerName,
|
||||
string.Join(", ",
|
||||
chunk.Select(a => $"{a.PlayerName} ({a.SteamId})"))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue