[webfront] search by ip and name

[application] levels set properly with multiple GUIDs
[stats] require 3 hours of playtime for top stats recognition
[application] configurable rcon polling rate
This commit is contained in:
RaidMax 2018-06-07 21:19:12 -05:00
parent e60f612f95
commit 5be6b75ccf
10 changed files with 64 additions and 23 deletions

View File

@ -15,6 +15,7 @@ namespace IW4MAdmin.Application.EventParsers
string[] lineSplit = logLine.Split(';'); string[] lineSplit = logLine.Split(';');
string cleanedEventLine = Regex.Replace(lineSplit[0], @"([0-9]+:[0-9]+ |^[0-9]+ )", "").Trim(); string cleanedEventLine = Regex.Replace(lineSplit[0], @"([0-9]+:[0-9]+ |^[0-9]+ )", "").Trim();
// kill
if (cleanedEventLine[0] == 'K') if (cleanedEventLine[0] == 'K')
{ {
if (!server.CustomCallback) if (!server.CustomCallback)
@ -91,6 +92,7 @@ namespace IW4MAdmin.Application.EventParsers
}; };
} }
// damage
if (cleanedEventLine[0] == 'D') if (cleanedEventLine[0] == 'D')
{ {
if (Regex.Match(cleanedEventLine, @"^(D);((?:bot[0-9]+)|(?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$").Success) if (Regex.Match(cleanedEventLine, @"^(D);((?:bot[0-9]+)|(?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[A-Z]|[0-9])+);([0-9]+);(axis|allies);(.+);((?:[0-9]+|[a-z]+|_)+);([0-9]+);((?:[A-Z]|_)+);((?:[a-z]|_)+)$").Success)
@ -106,6 +108,27 @@ namespace IW4MAdmin.Application.EventParsers
} }
} }
// join
if (cleanedEventLine[0] == 'J')
{
var regexMatch = Regex.Match(cleanedEventLine, @"^(J;)(.{4,32});([0-9]+);(.*)$");
if (regexMatch.Success)
{
return new GameEvent()
{
Type = GameEvent.EventType.Join,
Data = cleanedEventLine,
Owner = server,
Origin = new Player()
{
Name = regexMatch.Groups[4].ToString(),
NetworkId = regexMatch.Groups[2].ToString().ConvertLong(),
ClientNumber = Convert.ToInt32(regexMatch.Groups[3].ToString())
}
};
}
}
if (cleanedEventLine.Contains("ExitLevel")) if (cleanedEventLine.Contains("ExitLevel"))
{ {
return new GameEvent() return new GameEvent()

View File

@ -139,7 +139,7 @@ namespace IW4MAdmin.Application
sensitiveEvent.OnProcessed.Set(); sensitiveEvent.OnProcessed.Set();
} }
await Task.Delay(2500); await Task.Delay(ConfigHandler.Configuration().RConPollRate);
} }
} }

View File

@ -480,6 +480,11 @@ namespace IW4MAdmin
await AddPlayer(client); await AddPlayer(client);
} }
/*else
{
await AddPlayer(E.Origin);
}*/
} }
else if (E.Type == GameEvent.EventType.Disconnect) else if (E.Type == GameEvent.EventType.Disconnect)

View File

@ -23,7 +23,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
public int TeamCount(IW4Info.Team teamName) public int TeamCount(IW4Info.Team teamName)
{ {
if (PlayerStats.Count(p => p.Value.Team == IW4Info.Team.Spectator) / (double)PlayerStats.Count <= 0.25) if (PlayerStats.Count(p => p.Value.Team == IW4Info.Team.None) / (double)PlayerStats.Count <= 0.25)
{ {
return IsTeamBased ? Math.Max(PlayerStats.Count(p => p.Value.Team == teamName), 1) : Math.Max(PlayerStats.Count - 1, 1); return IsTeamBased ? Math.Max(PlayerStats.Count(p => p.Value.Team == teamName), 1) : Math.Max(PlayerStats.Count - 1, 1);
} }

View File

@ -53,7 +53,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
var thirtyDaysAgo = DateTime.UtcNow.AddMonths(-1); var thirtyDaysAgo = DateTime.UtcNow.AddMonths(-1);
var iqClientRatings = (from rating in context.Set<EFRating>() var iqClientRatings = (from rating in context.Set<EFRating>()
#if !DEBUG #if !DEBUG
where rating.ActivityAmount > 3600 where rating.ActivityAmount > 10800
#endif #endif
where rating.RatingHistory.Client.Level != Player.Permission.Banned where rating.RatingHistory.Client.Level != Player.Permission.Banned
where rating.RatingHistory.Client.LastConnection > thirtyDaysAgo where rating.RatingHistory.Client.LastConnection > thirtyDaysAgo
@ -255,6 +255,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
clientStats.LastActive = DateTime.UtcNow; clientStats.LastActive = DateTime.UtcNow;
clientStats.LastStatCalculation = DateTime.UtcNow; clientStats.LastStatCalculation = DateTime.UtcNow;
clientStats.SessionScore = pl.Score; clientStats.SessionScore = pl.Score;
clientStats.LastScore = pl.Score;
Log.WriteInfo($"Adding {pl} to stats"); Log.WriteInfo($"Adding {pl} to stats");
@ -429,14 +430,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
{ {
async Task executePenalty(Cheat.DetectionPenaltyResult penalty) async Task executePenalty(Cheat.DetectionPenaltyResult penalty)
{ {
// prevent multiple bans/flags from occuring async Task saveLog()
if (attacker.Level != Player.Permission.User)
{
return;
}
// this happens when a client is detected as cheating
if (penalty.ClientPenalty != Penalty.PenaltyType.Any)
{ {
using (var ctx = new DatabaseContext()) using (var ctx = new DatabaseContext())
{ {
@ -451,6 +445,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
switch (penalty.ClientPenalty) switch (penalty.ClientPenalty)
{ {
case Penalty.PenaltyType.Ban: case Penalty.PenaltyType.Ban:
await saveLog();
await attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], new Player() await attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], new Player()
{ {
ClientId = 1, ClientId = 1,
@ -466,6 +461,9 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
}); });
break; break;
case Penalty.PenaltyType.Flag: case Penalty.PenaltyType.Flag:
if (attacker.Level == Player.Permission.Flagged)
break;
await saveLog();
var e = new GameEvent() var e = new GameEvent()
{ {
Data = penalty.Type == Cheat.Detection.DetectionType.Bone ? Data = penalty.Type == Cheat.Detection.DetectionType.Bone ?

View File

@ -3,7 +3,7 @@
Layout = null; Layout = null;
} }
<div class="client-message-context bg-dark p-2 mt-2 mb-2 border-top border-bottom"> <div class="penalty-info-context bg-dark p-2 mt-2 mb-2 border-top border-bottom">
@foreach (var snapshot in Model) @foreach (var snapshot in Model)
{ {
<!-- this is not ideal, but I didn't want to manually write out all the properties--> <!-- this is not ideal, but I didn't want to manually write out all the properties-->

View File

@ -21,6 +21,7 @@ namespace SharedLibraryCore.Configuration
public string CustomParserEncoding { get; set; } public string CustomParserEncoding { get; set; }
public string CustomLocale { get; set; } public string CustomLocale { get; set; }
public string ConnectionString { get; set; } public string ConnectionString { get; set; }
public int RConPollRate { get; set; } = 5000;
public string Id { get; set; } public string Id { get; set; }
public List<ServerConfiguration> Servers { get; set; } public List<ServerConfiguration> Servers { get; set; }
public int AutoMessagePeriod { get; set; } public int AutoMessagePeriod { get; set; }
@ -59,6 +60,8 @@ namespace SharedLibraryCore.Configuration
SocialLinkAddress = Utilities.PromptString(loc["SETUP_SOCIAL_LINK"]); SocialLinkAddress = Utilities.PromptString(loc["SETUP_SOCIAL_LINK"]);
} }
RConPollRate = 5000;
return this; return this;
} }

View File

@ -57,7 +57,9 @@ namespace SharedLibraryCore.Services
// set the level to the level of the existing client if they have the same IP + Name but new NetworkId // set the level to the level of the existing client if they have the same IP + Name but new NetworkId
// fixme: issues? // fixme: issues?
Level = hasExistingAlias ? Level = hasExistingAlias ?
context.Clients.First(c => c.AliasLinkId == existingAlias.LinkId).Level : (await context.Clients.Where(c => c.AliasLinkId == existingAlias.LinkId)
.OrderByDescending(c => c.Level)
.FirstAsync()).Level :
Player.Permission.User, Player.Permission.User,
FirstConnection = DateTime.UtcNow, FirstConnection = DateTime.UtcNow,
Connections = 1, Connections = 1,
@ -260,10 +262,18 @@ namespace SharedLibraryCore.Services
using (var context = new DatabaseContext()) using (var context = new DatabaseContext())
{ {
context.ChangeTracker.AutoDetectChangesEnabled = false;
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
int asIP = name.ConvertToIP();
// hack: so IW4MAdmin doesn't show up in search results
asIP = asIP == 0 ? int.MinValue : asIP;
var iqClients = (from alias in context.Aliases var iqClients = (from alias in context.Aliases
.AsNoTracking() .AsNoTracking()
where alias.Name.ToLower() where alias.Name.ToLower()
.Contains(name.ToLower()) .Contains(name.ToLower()) ||
alias.IPAddress == asIP
join link in context.AliasLinks join link in context.AliasLinks
on alias.LinkId equals link.AliasLinkId on alias.LinkId equals link.AliasLinkId
join client in context.Clients join client in context.Clients

View File

@ -202,6 +202,7 @@ select {
font-size: 1rem; font-size: 1rem;
} }
.client-message { .client-message, .automated-penalty-info-detailed {
cursor: pointer; cursor: pointer;
} }

View File

@ -85,6 +85,7 @@ $(document).ready(function () {
'clientId': $(this).data('clientid'), 'clientId': $(this).data('clientid'),
}) })
.done(function (response) { .done(function (response) {
$('.penalty-info-context').remove();
location.after(response); location.after(response);
hideLoader(); hideLoader();
}) })