[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 cleanedEventLine = Regex.Replace(lineSplit[0], @"([0-9]+:[0-9]+ |^[0-9]+ )", "").Trim();
// kill
if (cleanedEventLine[0] == 'K')
{
if (!server.CustomCallback)
@ -91,6 +92,7 @@ namespace IW4MAdmin.Application.EventParsers
};
}
// damage
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)
@ -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"))
{
return new GameEvent()

View File

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

View File

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

View File

@ -23,7 +23,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
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);
}

View File

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

View File

@ -3,7 +3,7 @@
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)
{
<!-- 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 CustomLocale { get; set; }
public string ConnectionString { get; set; }
public int RConPollRate { get; set; } = 5000;
public string Id { get; set; }
public List<ServerConfiguration> Servers { get; set; }
public int AutoMessagePeriod { get; set; }
@ -59,6 +60,8 @@ namespace SharedLibraryCore.Configuration
SocialLinkAddress = Utilities.PromptString(loc["SETUP_SOCIAL_LINK"]);
}
RConPollRate = 5000;
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
// fixme: issues?
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,
FirstConnection = DateTime.UtcNow,
Connections = 1,
@ -260,10 +262,18 @@ namespace SharedLibraryCore.Services
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
.AsNoTracking()
where alias.Name.ToLower()
.Contains(name.ToLower())
.Contains(name.ToLower()) ||
alias.IPAddress == asIP
join link in context.AliasLinks
on alias.LinkId equals link.AliasLinkId
join client in context.Clients

View File

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

View File

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