clean up the profanity determent plugin by using the Get/Set Additional properties
cleaned up the base event parser to not need the server object to generate the event Hopefully prevent anticheat from freaking out when database connection is lost
This commit is contained in:
parent
b99cc424e7
commit
5f588bb0f7
@ -75,27 +75,12 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
|
|
||||||
public string URLProtocolFormat { get; set; } = "CoD://{{ip}}:{{port}}";
|
public string URLProtocolFormat { get; set; } = "CoD://{{ip}}:{{port}}";
|
||||||
|
|
||||||
public virtual GameEvent GetEvent(Server server, string logLine)
|
public virtual GameEvent GenerateGameEvent(string logLine)
|
||||||
{
|
{
|
||||||
logLine = Regex.Replace(logLine, @"([0-9]+:[0-9]+ |^[0-9]+ )", "").Trim();
|
logLine = Regex.Replace(logLine, @"([0-9]+:[0-9]+ |^[0-9]+ )", "").Trim();
|
||||||
string[] lineSplit = logLine.Split(';');
|
string[] lineSplit = logLine.Split(';');
|
||||||
string eventType = lineSplit[0];
|
string eventType = lineSplit[0];
|
||||||
|
|
||||||
// this is a "custom callback" event
|
|
||||||
if (eventType == "JoinTeam")
|
|
||||||
{
|
|
||||||
var origin = server.GetClientsAsList()
|
|
||||||
.FirstOrDefault(c => c.NetworkId == lineSplit[1].ConvertGuidToLong());
|
|
||||||
|
|
||||||
return new GameEvent()
|
|
||||||
{
|
|
||||||
Type = GameEvent.EventType.JoinTeam,
|
|
||||||
Data = logLine,
|
|
||||||
Origin = origin,
|
|
||||||
Owner = server
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eventType == "say" || eventType == "sayteam")
|
if (eventType == "say" || eventType == "sayteam")
|
||||||
{
|
{
|
||||||
var matchResult = Regex.Match(logLine, Configuration.Say.Pattern);
|
var matchResult = Regex.Match(logLine, Configuration.Say.Pattern);
|
||||||
@ -110,8 +95,7 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
|
|
||||||
if (message.Length > 0)
|
if (message.Length > 0)
|
||||||
{
|
{
|
||||||
var origin = server.GetClientsAsList()
|
long originId = matchResult.Groups[Configuration.Say.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().ConvertGuidToLong();
|
||||||
.First(c => c.NetworkId == matchResult.Groups[Configuration.Say.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().ConvertGuidToLong());
|
|
||||||
|
|
||||||
if (message[0] == '!' || message[0] == '@')
|
if (message[0] == '!' || message[0] == '@')
|
||||||
{
|
{
|
||||||
@ -119,8 +103,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
{
|
{
|
||||||
Type = GameEvent.EventType.Command,
|
Type = GameEvent.EventType.Command,
|
||||||
Data = message,
|
Data = message,
|
||||||
Origin = origin,
|
Origin = new EFClient() { NetworkId = originId },
|
||||||
Owner = server,
|
Target = Utilities.IW4MAdminClient(),
|
||||||
Message = message
|
Message = message
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -129,8 +113,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
{
|
{
|
||||||
Type = GameEvent.EventType.Say,
|
Type = GameEvent.EventType.Say,
|
||||||
Data = message,
|
Data = message,
|
||||||
Origin = origin,
|
Origin = new EFClient() { NetworkId = originId },
|
||||||
Owner = server,
|
Target = Utilities.IW4MAdminClient(),
|
||||||
Message = message
|
Message = message
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -139,111 +123,47 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
|
|
||||||
if (eventType == "K")
|
if (eventType == "K")
|
||||||
{
|
{
|
||||||
if (!server.CustomCallback)
|
|
||||||
{
|
|
||||||
var match = Regex.Match(logLine, Configuration.Kill.Pattern);
|
var match = Regex.Match(logLine, Configuration.Kill.Pattern);
|
||||||
|
|
||||||
if (match.Success)
|
if (match.Success)
|
||||||
{
|
{
|
||||||
string originId = match.Groups[Configuration.Kill.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].Value.ToString();
|
long originId = match.Groups[Configuration.Kill.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].Value.ToString().ConvertGuidToLong(1);
|
||||||
string targetId = match.Groups[Configuration.Kill.GroupMapping[ParserRegex.GroupType.TargetNetworkId]].Value.ToString();
|
long targetId = match.Groups[Configuration.Kill.GroupMapping[ParserRegex.GroupType.TargetNetworkId]].Value.ToString().ConvertGuidToLong();
|
||||||
|
|
||||||
var origin = !string.IsNullOrEmpty(originId) ? server.GetClientsAsList()
|
|
||||||
.First(c => c.NetworkId == originId.ConvertGuidToLong()) :
|
|
||||||
Utilities.IW4MAdminClient(server);
|
|
||||||
|
|
||||||
var target = !string.IsNullOrEmpty(targetId) ? server.GetClientsAsList()
|
|
||||||
.First(c => c.NetworkId == targetId.ConvertGuidToLong()) :
|
|
||||||
Utilities.IW4MAdminClient(server);
|
|
||||||
|
|
||||||
return new GameEvent()
|
return new GameEvent()
|
||||||
{
|
{
|
||||||
Type = GameEvent.EventType.Kill,
|
Type = GameEvent.EventType.Kill,
|
||||||
Data = logLine,
|
Data = logLine,
|
||||||
Origin = origin,
|
Origin = new EFClient() { NetworkId = originId },
|
||||||
Target = target,
|
Target = new EFClient() { NetworkId = targetId },
|
||||||
Owner = server
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (eventType == "ScriptKill")
|
|
||||||
{
|
|
||||||
long originId = lineSplit[1].ConvertGuidToLong();
|
|
||||||
long targetId = lineSplit[2].ConvertGuidToLong();
|
|
||||||
|
|
||||||
var origin = originId == long.MinValue ? Utilities.IW4MAdminClient(server) :
|
|
||||||
server.GetClientsAsList().First(c => c.NetworkId == originId);
|
|
||||||
var target = targetId == long.MinValue ? Utilities.IW4MAdminClient(server) :
|
|
||||||
server.GetClientsAsList().FirstOrDefault(c => c.NetworkId == targetId) ?? Utilities.IW4MAdminClient(server);
|
|
||||||
|
|
||||||
return new GameEvent()
|
|
||||||
{
|
|
||||||
Type = GameEvent.EventType.ScriptKill,
|
|
||||||
Data = logLine,
|
|
||||||
Origin = origin,
|
|
||||||
Target = target,
|
|
||||||
Owner = server
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eventType == "ScriptDamage")
|
|
||||||
{
|
|
||||||
long originId = lineSplit[1].ConvertGuidToLong();
|
|
||||||
long targetId = lineSplit[2].ConvertGuidToLong();
|
|
||||||
|
|
||||||
var origin = originId == long.MinValue ? Utilities.IW4MAdminClient(server) :
|
|
||||||
server.GetClientsAsList().First(c => c.NetworkId == originId);
|
|
||||||
var target = targetId == long.MinValue ? Utilities.IW4MAdminClient(server) :
|
|
||||||
server.GetClientsAsList().FirstOrDefault(c => c.NetworkId == targetId) ?? Utilities.IW4MAdminClient(server);
|
|
||||||
|
|
||||||
return new GameEvent()
|
|
||||||
{
|
|
||||||
Type = GameEvent.EventType.ScriptDamage,
|
|
||||||
Data = logLine,
|
|
||||||
Origin = origin,
|
|
||||||
Target = target,
|
|
||||||
Owner = server
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// damage
|
|
||||||
if (eventType == "D")
|
if (eventType == "D")
|
||||||
{
|
|
||||||
if (!server.CustomCallback)
|
|
||||||
{
|
{
|
||||||
var regexMatch = Regex.Match(logLine, Configuration.Damage.Pattern);
|
var regexMatch = Regex.Match(logLine, Configuration.Damage.Pattern);
|
||||||
|
|
||||||
if (regexMatch.Success)
|
if (regexMatch.Success)
|
||||||
{
|
{
|
||||||
string originId = regexMatch.Groups[Configuration.Damage.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString();
|
long originId = regexMatch.Groups[Configuration.Damage.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().ConvertGuidToLong(1);
|
||||||
string targetId = regexMatch.Groups[Configuration.Damage.GroupMapping[ParserRegex.GroupType.TargetNetworkId]].ToString();
|
long targetId = regexMatch.Groups[Configuration.Damage.GroupMapping[ParserRegex.GroupType.TargetNetworkId]].ToString().ConvertGuidToLong();
|
||||||
|
|
||||||
var origin = !string.IsNullOrEmpty(originId) ? server.GetClientsAsList()
|
|
||||||
.First(c => c.NetworkId == originId.ConvertGuidToLong()) :
|
|
||||||
Utilities.IW4MAdminClient(server);
|
|
||||||
|
|
||||||
var target = !string.IsNullOrEmpty(targetId) ? server.GetClientsAsList()
|
|
||||||
.First(c => c.NetworkId == targetId.ConvertGuidToLong()) :
|
|
||||||
Utilities.IW4MAdminClient(server);
|
|
||||||
|
|
||||||
return new GameEvent()
|
return new GameEvent()
|
||||||
{
|
{
|
||||||
Type = GameEvent.EventType.Damage,
|
Type = GameEvent.EventType.Damage,
|
||||||
Data = logLine,
|
Data = logLine,
|
||||||
Origin = origin,
|
Origin = new EFClient() { NetworkId = originId },
|
||||||
Target = target,
|
Target = new EFClient() { NetworkId = targetId }
|
||||||
Owner = server
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// join
|
|
||||||
if (eventType == "J")
|
if (eventType == "J")
|
||||||
{
|
{
|
||||||
var regexMatch = Regex.Match(logLine, Configuration.Join.Pattern);
|
var regexMatch = Regex.Match(logLine, Configuration.Join.Pattern);
|
||||||
|
|
||||||
if (regexMatch.Success)
|
if (regexMatch.Success)
|
||||||
{
|
{
|
||||||
bool isBot = regexMatch.Groups[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().Contains("bot");
|
bool isBot = regexMatch.Groups[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().Contains("bot");
|
||||||
@ -252,7 +172,6 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
{
|
{
|
||||||
Type = GameEvent.EventType.PreConnect,
|
Type = GameEvent.EventType.PreConnect,
|
||||||
Data = logLine,
|
Data = logLine,
|
||||||
Owner = server,
|
|
||||||
Origin = new EFClient()
|
Origin = new EFClient()
|
||||||
{
|
{
|
||||||
CurrentAlias = new EFAlias()
|
CurrentAlias = new EFAlias()
|
||||||
@ -262,9 +181,9 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
NetworkId = regexMatch.Groups[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().ConvertGuidToLong(),
|
NetworkId = regexMatch.Groups[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().ConvertGuidToLong(),
|
||||||
ClientNumber = Convert.ToInt32(regexMatch.Groups[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginClientNumber]].ToString()),
|
ClientNumber = Convert.ToInt32(regexMatch.Groups[Configuration.Join.GroupMapping[ParserRegex.GroupType.OriginClientNumber]].ToString()),
|
||||||
State = EFClient.ClientState.Connecting,
|
State = EFClient.ClientState.Connecting,
|
||||||
CurrentServer = server,
|
|
||||||
IsBot = isBot
|
IsBot = isBot
|
||||||
}
|
},
|
||||||
|
Target = Utilities.IW4MAdminClient()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -278,7 +197,6 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
{
|
{
|
||||||
Type = GameEvent.EventType.PreDisconnect,
|
Type = GameEvent.EventType.PreDisconnect,
|
||||||
Data = logLine,
|
Data = logLine,
|
||||||
Owner = server,
|
|
||||||
Origin = new EFClient()
|
Origin = new EFClient()
|
||||||
{
|
{
|
||||||
CurrentAlias = new EFAlias()
|
CurrentAlias = new EFAlias()
|
||||||
@ -288,7 +206,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
NetworkId = regexMatch.Groups[Configuration.Quit.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().ConvertGuidToLong(),
|
NetworkId = regexMatch.Groups[Configuration.Quit.GroupMapping[ParserRegex.GroupType.OriginNetworkId]].ToString().ConvertGuidToLong(),
|
||||||
ClientNumber = Convert.ToInt32(regexMatch.Groups[Configuration.Quit.GroupMapping[ParserRegex.GroupType.OriginClientNumber]].ToString()),
|
ClientNumber = Convert.ToInt32(regexMatch.Groups[Configuration.Quit.GroupMapping[ParserRegex.GroupType.OriginClientNumber]].ToString()),
|
||||||
State = EFClient.ClientState.Disconnecting
|
State = EFClient.ClientState.Disconnecting
|
||||||
}
|
},
|
||||||
|
Target = Utilities.IW4MAdminClient()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,9 +218,8 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
{
|
{
|
||||||
Type = GameEvent.EventType.MapEnd,
|
Type = GameEvent.EventType.MapEnd,
|
||||||
Data = lineSplit[0],
|
Data = lineSplit[0],
|
||||||
Origin = Utilities.IW4MAdminClient(server),
|
Origin = Utilities.IW4MAdminClient(),
|
||||||
Target = Utilities.IW4MAdminClient(server),
|
Target = Utilities.IW4MAdminClient(),
|
||||||
Owner = server
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,19 +231,59 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
{
|
{
|
||||||
Type = GameEvent.EventType.MapChange,
|
Type = GameEvent.EventType.MapChange,
|
||||||
Data = lineSplit[0],
|
Data = lineSplit[0],
|
||||||
Origin = Utilities.IW4MAdminClient(server),
|
Origin = Utilities.IW4MAdminClient(),
|
||||||
Target = Utilities.IW4MAdminClient(server),
|
Target = Utilities.IW4MAdminClient(),
|
||||||
Owner = server,
|
|
||||||
Extra = dump.DictionaryFromKeyValue()
|
Extra = dump.DictionaryFromKeyValue()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is a custom event printed out by _customcallbacks.gsc (used for team balance)
|
||||||
|
if (eventType == "JoinTeam")
|
||||||
|
{
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.JoinTeam,
|
||||||
|
Data = logLine,
|
||||||
|
Origin = new EFClient() { NetworkId = lineSplit[1].ConvertGuidToLong() },
|
||||||
|
Target = Utilities.IW4MAdminClient()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a custom event printed out by _customcallbacks.gsc (used for anticheat)
|
||||||
|
if (eventType == "ScriptKill")
|
||||||
|
{
|
||||||
|
long originId = lineSplit[1].ConvertGuidToLong(1);
|
||||||
|
long targetId = lineSplit[2].ConvertGuidToLong();
|
||||||
|
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.ScriptKill,
|
||||||
|
Data = logLine,
|
||||||
|
Origin = new EFClient() { NetworkId = originId },
|
||||||
|
Target = new EFClient() { NetworkId = targetId }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a custom event printed out by _customcallbacks.gsc (used for anticheat)
|
||||||
|
if (eventType == "ScriptDamage")
|
||||||
|
{
|
||||||
|
long originId = lineSplit[1].ConvertGuidToLong(1);
|
||||||
|
long targetId = lineSplit[2].ConvertGuidToLong();
|
||||||
|
|
||||||
|
return new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.ScriptDamage,
|
||||||
|
Data = logLine,
|
||||||
|
Origin = new EFClient() { NetworkId = originId },
|
||||||
|
Target = new EFClient() { NetworkId = targetId }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return new GameEvent()
|
return new GameEvent()
|
||||||
{
|
{
|
||||||
Type = GameEvent.EventType.Unknown,
|
Type = GameEvent.EventType.Unknown,
|
||||||
Origin = Utilities.IW4MAdminClient(server),
|
Origin = Utilities.IW4MAdminClient(),
|
||||||
Target = Utilities.IW4MAdminClient(server),
|
Target = Utilities.IW4MAdminClient()
|
||||||
Owner = server
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ using SharedLibraryCore.Interfaces;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace IW4MAdmin.Application.IO
|
namespace IW4MAdmin.Application.IO
|
||||||
@ -12,6 +12,7 @@ namespace IW4MAdmin.Application.IO
|
|||||||
{
|
{
|
||||||
IEventParser Parser;
|
IEventParser Parser;
|
||||||
readonly string LogFile;
|
readonly string LogFile;
|
||||||
|
private bool? ignoreBots;
|
||||||
|
|
||||||
public long Length => new FileInfo(LogFile).Length;
|
public long Length => new FileInfo(LogFile).Length;
|
||||||
|
|
||||||
@ -25,13 +26,17 @@ namespace IW4MAdmin.Application.IO
|
|||||||
|
|
||||||
public async Task<ICollection<GameEvent>> ReadEventsFromLog(Server server, long fileSizeDiff, long startPosition)
|
public async Task<ICollection<GameEvent>> ReadEventsFromLog(Server server, long fileSizeDiff, long startPosition)
|
||||||
{
|
{
|
||||||
|
if (!ignoreBots.HasValue)
|
||||||
|
{
|
||||||
|
ignoreBots = server.Manager.GetApplicationSettings().Configuration().IgnoreBots;
|
||||||
|
}
|
||||||
|
|
||||||
// allocate the bytes for the new log lines
|
// allocate the bytes for the new log lines
|
||||||
List<string> logLines = new List<string>();
|
List<string> logLines = new List<string>();
|
||||||
|
|
||||||
// open the file as a stream
|
// open the file as a stream
|
||||||
using (var rd = new StreamReader(new FileStream(LogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Utilities.EncodingType))
|
using (var rd = new StreamReader(new FileStream(LogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Utilities.EncodingType))
|
||||||
{
|
{
|
||||||
// todo: max async
|
|
||||||
// take the old start position and go back the number of new characters
|
// take the old start position and go back the number of new characters
|
||||||
rd.BaseStream.Seek(-fileSizeDiff, SeekOrigin.End);
|
rd.BaseStream.Seek(-fileSizeDiff, SeekOrigin.End);
|
||||||
|
|
||||||
@ -51,8 +56,25 @@ namespace IW4MAdmin.Application.IO
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// todo: catch elsewhere
|
var gameEvent = Parser.GenerateGameEvent(eventLine);
|
||||||
events.Add(Parser.GetEvent(server, eventLine));
|
// we don't want to add the even if ignoreBots is on and the event comes froma bot
|
||||||
|
if (!ignoreBots.Value || (ignoreBots.Value && (gameEvent.Origin.NetworkId != -1 || gameEvent.Target.NetworkId != -1)))
|
||||||
|
{
|
||||||
|
gameEvent.Owner = server;
|
||||||
|
// we need to pull the "live" versions of the client (only if the client id isn't IW4MAdmin
|
||||||
|
gameEvent.Origin = gameEvent.Origin.ClientId == 1 ? gameEvent.Origin : server.GetClientsAsList().First(_client => _client.NetworkId == gameEvent.Origin.NetworkId);
|
||||||
|
gameEvent.Target = gameEvent.Target.ClientId == 1 ? gameEvent.Target : server.GetClientsAsList().First(_client => _client.NetworkId == gameEvent.Target.NetworkId);
|
||||||
|
|
||||||
|
events.Add(gameEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
if (!ignoreBots.Value)
|
||||||
|
{
|
||||||
|
server.Logger.WriteWarning("Could not find client in client list when parsing event line");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -4,6 +4,7 @@ using SharedLibraryCore;
|
|||||||
using SharedLibraryCore.Interfaces;
|
using SharedLibraryCore.Interfaces;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using static SharedLibraryCore.Utilities;
|
using static SharedLibraryCore.Utilities;
|
||||||
@ -18,6 +19,7 @@ namespace IW4MAdmin.Application.IO
|
|||||||
readonly IEventParser Parser;
|
readonly IEventParser Parser;
|
||||||
readonly IGameLogServer Api;
|
readonly IGameLogServer Api;
|
||||||
readonly string logPath;
|
readonly string logPath;
|
||||||
|
private bool? ignoreBots;
|
||||||
|
|
||||||
public GameLogReaderHttp(Uri gameLogServerUri, string logPath, IEventParser parser)
|
public GameLogReaderHttp(Uri gameLogServerUri, string logPath, IEventParser parser)
|
||||||
{
|
{
|
||||||
@ -35,6 +37,12 @@ namespace IW4MAdmin.Application.IO
|
|||||||
#if DEBUG == true
|
#if DEBUG == true
|
||||||
server.Logger.WriteDebug($"Begin reading from http log");
|
server.Logger.WriteDebug($"Begin reading from http log");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!ignoreBots.HasValue)
|
||||||
|
{
|
||||||
|
ignoreBots = server.Manager.GetApplicationSettings().Configuration().IgnoreBots;
|
||||||
|
}
|
||||||
|
|
||||||
var events = new List<GameEvent>();
|
var events = new List<GameEvent>();
|
||||||
string b64Path = logPath;
|
string b64Path = logPath;
|
||||||
var response = await Api.Log(b64Path);
|
var response = await Api.Log(b64Path);
|
||||||
@ -52,16 +60,33 @@ namespace IW4MAdmin.Application.IO
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var e = Parser.GetEvent(server, eventLine);
|
var gameEvent = Parser.GenerateGameEvent(eventLine);
|
||||||
|
// we don't want to add the even if ignoreBots is on and the event comes froma bot
|
||||||
|
if (!ignoreBots.Value || (ignoreBots.Value && (gameEvent.Origin.NetworkId != -1 || gameEvent.Target.NetworkId != -1)))
|
||||||
|
{
|
||||||
|
gameEvent.Owner = server;
|
||||||
|
// we need to pull the "live" versions of the client (only if the client id isn't IW4MAdmin
|
||||||
|
gameEvent.Origin = gameEvent.Origin.ClientId == 1 ? gameEvent.Origin : server.GetClientsAsList().First(_client => _client.NetworkId == gameEvent.Origin.NetworkId);
|
||||||
|
gameEvent.Target = gameEvent.Target.ClientId == 1 ? gameEvent.Target : server.GetClientsAsList().First(_client => _client.NetworkId == gameEvent.Target.NetworkId);
|
||||||
|
|
||||||
|
events.Add(gameEvent);
|
||||||
|
}
|
||||||
#if DEBUG == true
|
#if DEBUG == true
|
||||||
server.Logger.WriteDebug($"Parsed event with id {e.Id} from http");
|
server.Logger.WriteDebug($"Parsed event with id {gameEvent.Id} from http");
|
||||||
#endif
|
#endif
|
||||||
events.Add(e);
|
}
|
||||||
|
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
if (!ignoreBots.Value)
|
||||||
|
{
|
||||||
|
server.Logger.WriteWarning("Could not find client in client list when parsing event line");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
server.Logger.WriteWarning("Could not properly parse event line");
|
server.Logger.WriteWarning("Could not properly parse remote event line");
|
||||||
server.Logger.WriteDebug(e.Message);
|
server.Logger.WriteDebug(e.Message);
|
||||||
server.Logger.WriteDebug(eventLine);
|
server.Logger.WriteDebug(eventLine);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Linq;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using SharedLibraryCore;
|
using SharedLibraryCore;
|
||||||
using SharedLibraryCore.Configuration;
|
using SharedLibraryCore.Configuration;
|
||||||
using SharedLibraryCore.Database.Models;
|
|
||||||
using SharedLibraryCore.Interfaces;
|
using SharedLibraryCore.Interfaces;
|
||||||
|
|
||||||
namespace IW4MAdmin.Plugins.ProfanityDeterment
|
namespace IW4MAdmin.Plugins.ProfanityDeterment
|
||||||
@ -19,8 +17,6 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
|
|||||||
public string Author => "RaidMax";
|
public string Author => "RaidMax";
|
||||||
|
|
||||||
BaseConfigurationHandler<Configuration> Settings;
|
BaseConfigurationHandler<Configuration> Settings;
|
||||||
ConcurrentDictionary<int, Tracking> ProfanityCounts;
|
|
||||||
IManager Manager;
|
|
||||||
|
|
||||||
public Task OnEventAsync(GameEvent E, Server S)
|
public Task OnEventAsync(GameEvent E, Server S)
|
||||||
{
|
{
|
||||||
@ -29,10 +25,7 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
|
|||||||
|
|
||||||
if (E.Type == GameEvent.EventType.Connect)
|
if (E.Type == GameEvent.EventType.Connect)
|
||||||
{
|
{
|
||||||
if (!ProfanityCounts.TryAdd(E.Origin.ClientId, new Tracking(E.Origin)))
|
E.Origin.SetAdditionalProperty("_profanityInfringements", 0);
|
||||||
{
|
|
||||||
S.Logger.WriteWarning("Could not add client to profanity tracking");
|
|
||||||
}
|
|
||||||
|
|
||||||
var objectionalWords = Settings.Configuration().OffensiveWords;
|
var objectionalWords = Settings.Configuration().OffensiveWords;
|
||||||
bool containsObjectionalWord = objectionalWords.FirstOrDefault(w => E.Origin.Name.ToLower().Contains(w)) != null;
|
bool containsObjectionalWord = objectionalWords.FirstOrDefault(w => E.Origin.Name.ToLower().Contains(w)) != null;
|
||||||
@ -54,10 +47,7 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
|
|||||||
|
|
||||||
if (E.Type == GameEvent.EventType.Disconnect)
|
if (E.Type == GameEvent.EventType.Disconnect)
|
||||||
{
|
{
|
||||||
if (!ProfanityCounts.TryRemove(E.Origin.ClientId, out Tracking old))
|
E.Origin.SetAdditionalProperty("_profanityInfringements", 0);
|
||||||
{
|
|
||||||
S.Logger.WriteWarning("Could not remove client from profanity tracking");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Type == GameEvent.EventType.Say)
|
if (E.Type == GameEvent.EventType.Say)
|
||||||
@ -78,17 +68,17 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
|
|||||||
|
|
||||||
if (containsObjectionalWord)
|
if (containsObjectionalWord)
|
||||||
{
|
{
|
||||||
var clientProfanity = ProfanityCounts[E.Origin.ClientId];
|
int profanityInfringments = E.Origin.GetAdditionalProperty<int>("_profanityInfringements");
|
||||||
if (clientProfanity.Infringements >= Settings.Configuration().KickAfterInfringementCount)
|
|
||||||
|
if (profanityInfringments >= Settings.Configuration().KickAfterInfringementCount)
|
||||||
{
|
{
|
||||||
clientProfanity.Client.Kick(Settings.Configuration().ProfanityKickMessage, Utilities.IW4MAdminClient(E.Owner));
|
E.Origin.Kick(Settings.Configuration().ProfanityKickMessage, Utilities.IW4MAdminClient(E.Owner));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (clientProfanity.Infringements < Settings.Configuration().KickAfterInfringementCount)
|
else if (profanityInfringments < Settings.Configuration().KickAfterInfringementCount)
|
||||||
{
|
{
|
||||||
clientProfanity.Infringements++;
|
E.Origin.SetAdditionalProperty("_profanityInfringements", profanityInfringments + 1);
|
||||||
|
E.Origin.Warn(Settings.Configuration().ProfanityWarningMessage, Utilities.IW4MAdminClient(E.Owner));
|
||||||
clientProfanity.Client.Warn(Settings.Configuration().ProfanityWarningMessage, Utilities.IW4MAdminClient(E.Owner));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,9 +94,6 @@ namespace IW4MAdmin.Plugins.ProfanityDeterment
|
|||||||
Settings.Set((Configuration)new Configuration().Generate());
|
Settings.Set((Configuration)new Configuration().Generate());
|
||||||
await Settings.Save();
|
await Settings.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfanityCounts = new ConcurrentDictionary<int, Tracking>();
|
|
||||||
Manager = manager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task OnTickAsync(Server S) => Task.CompletedTask;
|
public Task OnTickAsync(Server S) => Task.CompletedTask;
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using SharedLibraryCore.Database.Models;
|
|
||||||
using SharedLibraryCore.Objects;
|
|
||||||
|
|
||||||
namespace IW4MAdmin.Plugins.ProfanityDeterment
|
|
||||||
{
|
|
||||||
class Tracking
|
|
||||||
{
|
|
||||||
public EFClient Client { get; private set; }
|
|
||||||
public int Infringements { get; set; }
|
|
||||||
|
|
||||||
public Tracking(EFClient client)
|
|
||||||
{
|
|
||||||
Client = client;
|
|
||||||
Infringements = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -568,7 +568,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
ctx.Set<EFClientKill>().Add(hit);
|
ctx.Set<EFClientKill>().Add(hit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Plugin.Config.Configuration().EnableAntiCheat && !attacker.IsBot)
|
if (Plugin.Config.Configuration().EnableAntiCheat && !attacker.IsBot && attacker.ClientId != victim.ClientId)
|
||||||
{
|
{
|
||||||
if (clientDetection.QueuedHits.Count > Detection.QUEUE_COUNT)
|
if (clientDetection.QueuedHits.Count > Detection.QUEUE_COUNT)
|
||||||
{
|
{
|
||||||
@ -577,8 +577,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
clientDetection.QueuedHits = clientDetection.QueuedHits.OrderBy(_hits => _hits.TimeOffset).ToList();
|
clientDetection.QueuedHits = clientDetection.QueuedHits.OrderBy(_hits => _hits.TimeOffset).ToList();
|
||||||
var oldestHit = clientDetection.QueuedHits.First();
|
var oldestHit = clientDetection.QueuedHits.First();
|
||||||
clientDetection.QueuedHits.RemoveAt(0);
|
clientDetection.QueuedHits.RemoveAt(0);
|
||||||
await ApplyPenalty(clientDetection.ProcessHit(oldestHit, isDamage), clientDetection, attacker, ctx);
|
await ApplyPenalty(clientDetection.ProcessHit(oldestHit, isDamage), attacker, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await ApplyPenalty(clientDetection.ProcessTotalRatio(clientStats), attacker, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -586,7 +588,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
clientDetection.QueuedHits.Add(hit);
|
clientDetection.QueuedHits.Add(hit);
|
||||||
}
|
}
|
||||||
|
|
||||||
await ApplyPenalty(clientDetection.ProcessTotalRatio(clientStats), clientDetection, attacker, ctx);
|
if (clientDetection.Tracker.HasChanges)
|
||||||
|
{
|
||||||
|
SaveTrackedSnapshots(clientDetection, ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Set<EFHitLocationCount>().UpdateRange(clientStats.HitLocations);
|
ctx.Set<EFHitLocationCount>().UpdateRange(clientStats.HitLocations);
|
||||||
@ -604,7 +609,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task ApplyPenalty(DetectionPenaltyResult penalty, Detection clientDetection, EFClient attacker, DatabaseContext ctx)
|
async Task ApplyPenalty(DetectionPenaltyResult penalty, EFClient attacker, DatabaseContext ctx)
|
||||||
{
|
{
|
||||||
var penaltyClient = Utilities.IW4MAdminClient(attacker.CurrentServer);
|
var penaltyClient = Utilities.IW4MAdminClient(attacker.CurrentServer);
|
||||||
switch (penalty.ClientPenalty)
|
switch (penalty.ClientPenalty)
|
||||||
@ -626,11 +631,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
};
|
};
|
||||||
|
|
||||||
await attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], penaltyClient, false).WaitAsync(Utilities.DefaultCommandTimeout, attacker.CurrentServer.Manager.CancellationToken);
|
await attacker.Ban(Utilities.CurrentLocalization.LocalizationIndex["PLUGIN_STATS_CHEAT_DETECTED"], penaltyClient, false).WaitAsync(Utilities.DefaultCommandTimeout, attacker.CurrentServer.Manager.CancellationToken);
|
||||||
|
|
||||||
if (clientDetection.Tracker.HasChanges)
|
|
||||||
{
|
|
||||||
SaveTrackedSnapshots(clientDetection, ctx);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case Penalty.PenaltyType.Flag:
|
case Penalty.PenaltyType.Flag:
|
||||||
if (attacker.Level != EFClient.Permission.User)
|
if (attacker.Level != EFClient.Permission.User)
|
||||||
@ -643,11 +643,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
$"{penalty.Type}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}";
|
$"{penalty.Type}-{Math.Round(penalty.Value, 2)}@{penalty.HitCount}";
|
||||||
|
|
||||||
await attacker.Flag(flagReason, penaltyClient).WaitAsync(Utilities.DefaultCommandTimeout, attacker.CurrentServer.Manager.CancellationToken);
|
await attacker.Flag(flagReason, penaltyClient).WaitAsync(Utilities.DefaultCommandTimeout, attacker.CurrentServer.Manager.CancellationToken);
|
||||||
|
|
||||||
if (clientDetection.Tracker.HasChanges)
|
|
||||||
{
|
|
||||||
SaveTrackedSnapshots(clientDetection, ctx);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -655,7 +650,8 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
void SaveTrackedSnapshots(Detection clientDetection, DatabaseContext ctx)
|
void SaveTrackedSnapshots(Detection clientDetection, DatabaseContext ctx)
|
||||||
{
|
{
|
||||||
// todo: why does this cause duplicate primary key
|
// todo: why does this cause duplicate primary key
|
||||||
var change = clientDetection.Tracker.GetNextChange();
|
_ = clientDetection.Tracker.GetNextChange();
|
||||||
|
EFACSnapshot change;
|
||||||
while ((change = clientDetection.Tracker.GetNextChange()) != default(EFACSnapshot))
|
while ((change = clientDetection.Tracker.GetNextChange()) != default(EFACSnapshot))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -80,16 +80,11 @@ namespace IW4MAdmin.Plugins.Stats
|
|||||||
if (killInfo.Length >= 14 && !ShouldIgnoreEvent(E.Origin, E.Target))
|
if (killInfo.Length >= 14 && !ShouldIgnoreEvent(E.Origin, E.Target))
|
||||||
{
|
{
|
||||||
// this treats "world" damage as self damage
|
// this treats "world" damage as self damage
|
||||||
if (E.Origin.ClientId <= 1)
|
if (E.Origin.ClientId == 1)
|
||||||
{
|
{
|
||||||
E.Origin = E.Target;
|
E.Origin = E.Target;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Target.ClientId <= 1)
|
|
||||||
{
|
|
||||||
E.Target = E.Origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Manager.AddScriptHit(false, E.Time, E.Origin, E.Target, await StatManager.GetIdForServer(E.Owner), S.CurrentMap.Name, killInfo[7], killInfo[8],
|
await Manager.AddScriptHit(false, E.Time, E.Origin, E.Target, await StatManager.GetIdForServer(E.Owner), S.CurrentMap.Name, killInfo[7], killInfo[8],
|
||||||
killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15]);
|
killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15]);
|
||||||
}
|
}
|
||||||
@ -98,16 +93,11 @@ namespace IW4MAdmin.Plugins.Stats
|
|||||||
if (!E.Owner.CustomCallback && !ShouldIgnoreEvent(E.Origin, E.Target))
|
if (!E.Owner.CustomCallback && !ShouldIgnoreEvent(E.Origin, E.Target))
|
||||||
{
|
{
|
||||||
// this treats "world" damage as self damage
|
// this treats "world" damage as self damage
|
||||||
if (E.Origin.ClientId <= 1)
|
if (E.Origin.ClientId == 1)
|
||||||
{
|
{
|
||||||
E.Origin = E.Target;
|
E.Origin = E.Target;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Target.ClientId <= 1)
|
|
||||||
{
|
|
||||||
E.Target = E.Origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Manager.AddStandardKill(E.Origin, E.Target);
|
await Manager.AddStandardKill(E.Origin, E.Target);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -115,16 +105,11 @@ namespace IW4MAdmin.Plugins.Stats
|
|||||||
if (!E.Owner.CustomCallback && !ShouldIgnoreEvent(E.Origin, E.Target))
|
if (!E.Owner.CustomCallback && !ShouldIgnoreEvent(E.Origin, E.Target))
|
||||||
{
|
{
|
||||||
// this treats "world" damage as self damage
|
// this treats "world" damage as self damage
|
||||||
if (E.Origin.ClientId <= 1)
|
if (E.Origin.ClientId == 1)
|
||||||
{
|
{
|
||||||
E.Origin = E.Target;
|
E.Origin = E.Target;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Target.ClientId <= 1)
|
|
||||||
{
|
|
||||||
E.Target = E.Origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
Manager.AddDamageEvent(E.Data, E.Origin.ClientId, E.Target.ClientId, await StatManager.GetIdForServer(E.Owner));
|
Manager.AddDamageEvent(E.Data, E.Origin.ClientId, E.Target.ClientId, await StatManager.GetIdForServer(E.Owner));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -133,16 +118,11 @@ namespace IW4MAdmin.Plugins.Stats
|
|||||||
if (killInfo.Length >= 14 && !ShouldIgnoreEvent(E.Origin, E.Target))
|
if (killInfo.Length >= 14 && !ShouldIgnoreEvent(E.Origin, E.Target))
|
||||||
{
|
{
|
||||||
// this treats "world" damage as self damage
|
// this treats "world" damage as self damage
|
||||||
if (E.Origin.ClientId <= 1)
|
if (E.Origin.ClientId == 1)
|
||||||
{
|
{
|
||||||
E.Origin = E.Target;
|
E.Origin = E.Target;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (E.Target.ClientId <= 1)
|
|
||||||
{
|
|
||||||
E.Target = E.Origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Manager.AddScriptHit(true, E.Time, E.Origin, E.Target, await StatManager.GetIdForServer(E.Owner), S.CurrentMap.Name, killInfo[7], killInfo[8],
|
await Manager.AddScriptHit(true, E.Time, E.Origin, E.Target, await StatManager.GetIdForServer(E.Owner), S.CurrentMap.Name, killInfo[7], killInfo[8],
|
||||||
killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15]);
|
killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15]);
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,10 @@ namespace SharedLibraryCore.Interfaces
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates a game event based on log line input
|
/// Generates a game event based on log line input
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="server">server the event occurred on</param>
|
|
||||||
/// <param name="logLine">single log line string</param>
|
/// <param name="logLine">single log line string</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// todo: make this integrate without needing the server
|
/// todo: make this integrate without needing the server
|
||||||
GameEvent GetEvent(Server server, string logLine);
|
GameEvent GenerateGameEvent(string logLine);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get game specific folder prefix for log files
|
/// Get game specific folder prefix for log files
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -268,11 +268,16 @@ namespace SharedLibraryCore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long ConvertGuidToLong(this string str)
|
public static long ConvertGuidToLong(this string str, long? fallback = null)
|
||||||
{
|
{
|
||||||
str = str.Substring(0, Math.Min(str.Length, 16));
|
str = str.Substring(0, Math.Min(str.Length, 16));
|
||||||
var bot = Regex.Match(str, @"bot[0-9]+").Value;
|
var bot = Regex.Match(str, @"bot[0-9]+").Value;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(str) && fallback.HasValue)
|
||||||
|
{
|
||||||
|
return fallback.Value;
|
||||||
|
}
|
||||||
|
|
||||||
// this is a special case for Plutonium T6
|
// this is a special case for Plutonium T6
|
||||||
if (str.Length <= 11 &&
|
if (str.Length <= 11 &&
|
||||||
long.TryParse(str, NumberStyles.Integer, CultureInfo.InvariantCulture, out long id)) // 10 numeric characters + signed character
|
long.TryParse(str, NumberStyles.Integer, CultureInfo.InvariantCulture, out long id)) // 10 numeric characters + signed character
|
||||||
|
@ -121,6 +121,11 @@ namespace WebfrontCore.Controllers
|
|||||||
|
|
||||||
public async Task<IActionResult> FindAsync(string clientName)
|
public async Task<IActionResult> FindAsync(string clientName)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(clientName))
|
||||||
|
{
|
||||||
|
return StatusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
var clientsDto = await Manager.GetClientService().FindClientsByIdentifier(clientName);
|
var clientsDto = await Manager.GetClientService().FindClientsByIdentifier(clientName);
|
||||||
|
|
||||||
ViewBag.Title = $"{clientsDto.Count} {Localization["WEBFRONT_CLIENT_SEARCH_MATCHING"]} \"{clientName}\"";
|
ViewBag.Title = $"{clientsDto.Count} {Localization["WEBFRONT_CLIENT_SEARCH_MATCHING"]} \"{clientName}\"";
|
||||||
|
Loading…
Reference in New Issue
Block a user