strip drive letter on gamelog server if running on linux
strip undecodable chacters from gamelog server log file finish re work on alias add/update ( I think)
This commit is contained in:
parent
8ab89e113d
commit
863ba8b096
1
.gitignore
vendored
1
.gitignore
vendored
@ -233,3 +233,4 @@ launchSettings.json
|
||||
/VpnDetectionPrivate.js
|
||||
/Plugins/ScriptPlugins/VpnDetectionPrivate.js
|
||||
**/Master/env_master
|
||||
/GameLogServer/log_env
|
||||
|
@ -36,7 +36,6 @@ namespace IW4MAdmin
|
||||
override public async Task OnClientConnected(EFClient clientFromLog)
|
||||
{
|
||||
Logger.WriteDebug($"Client slot #{clientFromLog.ClientNumber} now reserved");
|
||||
Clients[clientFromLog.ClientNumber] = new EFClient();
|
||||
|
||||
try
|
||||
{
|
||||
@ -71,7 +70,7 @@ namespace IW4MAdmin
|
||||
|
||||
Clients[client.ClientNumber] = client;
|
||||
|
||||
client.State = EFClient.ClientState.Connected;
|
||||
client.State = ClientState.Connected;
|
||||
#if DEBUG == true
|
||||
Logger.WriteDebug($"End PreConnect for {client}");
|
||||
#endif
|
||||
@ -207,7 +206,14 @@ namespace IW4MAdmin
|
||||
|
||||
var existingClient = GetClientsAsList().FirstOrDefault(_client => _client.Equals(E.Origin));
|
||||
|
||||
// they're already connected
|
||||
if (existingClient != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CONNECT:
|
||||
// we can go ahead and put them in
|
||||
if (Clients[E.Origin.ClientNumber] == null)
|
||||
{
|
||||
#if DEBUG == true
|
||||
@ -229,17 +235,12 @@ namespace IW4MAdmin
|
||||
}
|
||||
|
||||
// for some reason there's still a client in the spot
|
||||
else if (existingClient == null)
|
||||
else
|
||||
{
|
||||
Logger.WriteWarning($"{E.Origin} is connecteding but {Clients[E.Origin.ClientNumber]} is currently in that client slot");
|
||||
await OnClientDisconnected(Clients[E.Origin.ClientNumber]);
|
||||
goto CONNECT;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
else if (E.Type == GameEvent.EventType.Flag)
|
||||
|
@ -17,7 +17,7 @@
|
||||
<SuppressCollectPythonCloudServiceFiles>true</SuppressCollectPythonCloudServiceFiles>
|
||||
<Name>GameLogServer</Name>
|
||||
<RootNamespace>GameLogServer</RootNamespace>
|
||||
<InterpreterId>MSBuild|env|$(MSBuildProjectFullPath)</InterpreterId>
|
||||
<InterpreterId>MSBuild|log_env|$(MSBuildProjectFullPath)</InterpreterId>
|
||||
<EnableNativeCodeDebugging>False</EnableNativeCodeDebugging>
|
||||
<Environment>DEBUG=True</Environment>
|
||||
</PropertyGroup>
|
||||
@ -50,7 +50,6 @@
|
||||
<Folder Include="GameLogServer\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="requirements.txt" />
|
||||
<None Include="Stable.pubxml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -63,6 +62,18 @@
|
||||
<PathEnvironmentVariable>PYTHONPATH</PathEnvironmentVariable>
|
||||
<Architecture>X64</Architecture>
|
||||
</Interpreter>
|
||||
<Interpreter Include="log_env\">
|
||||
<Id>log_env</Id>
|
||||
<Version>3.6</Version>
|
||||
<Description>log_env (Python 3.6 (64-bit))</Description>
|
||||
<InterpreterPath>Scripts\python.exe</InterpreterPath>
|
||||
<WindowsInterpreterPath>Scripts\pythonw.exe</WindowsInterpreterPath>
|
||||
<PathEnvironmentVariable>PYTHONPATH</PathEnvironmentVariable>
|
||||
<Architecture>X64</Architecture>
|
||||
</Interpreter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="requirements.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.Web.targets" />
|
||||
<!-- Specify pre- and post-build commands in the BeforeBuild and
|
||||
|
@ -6,8 +6,7 @@ class LogReader(object):
|
||||
def __init__(self):
|
||||
self.log_file_sizes = {}
|
||||
# (if the time between checks is greater, ignore ) - in seconds
|
||||
# self.max_file_time_change = 60
|
||||
self.max_file_time_change = 10
|
||||
self.max_file_time_change = 30
|
||||
|
||||
def read_file(self, path):
|
||||
# this removes old entries that are no longer valid
|
||||
@ -17,33 +16,34 @@ class LogReader(object):
|
||||
print('could not clear old logs')
|
||||
print(e)
|
||||
|
||||
if os.name != 'nt':
|
||||
path = re.sub(r'^[A-Z]\:', '', path)
|
||||
path = re.sub(r'\\+', '/', path)
|
||||
|
||||
# prevent traversing directories
|
||||
if re.search('r^.+\.\.\\.+$', path):
|
||||
return False
|
||||
# must be a valid log path and log file
|
||||
if not re.search(r'^.+[\\|\/](.+)[\\|\/].+.log$', path):
|
||||
return False
|
||||
# set the initial size to the current file size
|
||||
file_size = 0
|
||||
|
||||
# this is the first time the log has been requested
|
||||
if path not in self.log_file_sizes:
|
||||
self.log_file_sizes[path] = {
|
||||
'length' : self.file_length(path),
|
||||
'read': time.time()
|
||||
}
|
||||
return ''
|
||||
|
||||
# grab the previous values
|
||||
last_length = self.log_file_sizes[path]['length']
|
||||
|
||||
# the file is being tracked already
|
||||
# get the new file size
|
||||
new_file_size = self.file_length(path)
|
||||
|
||||
# the log size was unable to be read (probably the wrong path)
|
||||
if new_file_size < 0:
|
||||
return False
|
||||
|
||||
# this is the first time the log has been requested
|
||||
if path not in self.log_file_sizes:
|
||||
self.log_file_sizes[path] = {
|
||||
'length' : new_file_size,
|
||||
'read': time.time()
|
||||
}
|
||||
return ''
|
||||
|
||||
# grab the previous values
|
||||
last_length = self.log_file_sizes[path]['length']
|
||||
file_size_difference = new_file_size - last_length
|
||||
|
||||
# update the new size and actually read the data
|
||||
@ -61,7 +61,8 @@ class LogReader(object):
|
||||
file_handle.seek(-length, 2)
|
||||
file_data = file_handle.read(length)
|
||||
file_handle.close()
|
||||
return file_data.decode('utf-8')
|
||||
# using ignore errors omits the pesky 0xb2 bytes we're reading in for some reason
|
||||
return file_data.decode('utf-8', errors='ignore')
|
||||
except Exception as e:
|
||||
print('could not read the log file at {0}, wanted to read {1} bytes'.format(path, length))
|
||||
print(e)
|
||||
|
@ -6,7 +6,6 @@ class LogResource(Resource):
|
||||
def get(self, path):
|
||||
path = urlsafe_b64decode(path).decode('utf-8')
|
||||
log_info = reader.read_file(path)
|
||||
print(log_info)
|
||||
|
||||
return {
|
||||
'success' : log_info is not False,
|
||||
|
@ -1,29 +1,29 @@
|
||||
from flask_restful import Resource
|
||||
from flask import request
|
||||
import requests
|
||||
import os
|
||||
import subprocess
|
||||
import re
|
||||
#from flask_restful import Resource
|
||||
#from flask import request
|
||||
#import requests
|
||||
#import os
|
||||
#import subprocess
|
||||
#import re
|
||||
|
||||
def get_pid_of_server_windows(port):
|
||||
process = subprocess.Popen('netstat -aon', shell=True, stdout=subprocess.PIPE)
|
||||
output = process.communicate()[0]
|
||||
matches = re.search(' *(UDP) +([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}):'+ str(port) + ' +[^\w]*([0-9]+)', output.decode('utf-8'))
|
||||
if matches is not None:
|
||||
return matches.group(3)
|
||||
else:
|
||||
return 0
|
||||
#def get_pid_of_server_windows(port):
|
||||
# process = subprocess.Popen('netstat -aon', shell=True, stdout=subprocess.PIPE)
|
||||
# output = process.communicate()[0]
|
||||
# matches = re.search(' *(UDP) +([0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}):'+ str(port) + ' +[^\w]*([0-9]+)', output.decode('utf-8'))
|
||||
# if matches is not None:
|
||||
# return matches.group(3)
|
||||
# else:
|
||||
# return 0
|
||||
|
||||
class RestartResource(Resource):
|
||||
def get(self):
|
||||
try:
|
||||
response = requests.get('http://' + request.remote_addr + ':1624/api/restartapproved')
|
||||
if response.status_code == 200:
|
||||
pid = get_pid_of_server_windows(response.json()['port'])
|
||||
subprocess.check_output("Taskkill /PID %s /F" % pid)
|
||||
else:
|
||||
return {}, 400
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return {}, 500
|
||||
return {}, 200
|
||||
#class RestartResource(Resource):
|
||||
# def get(self):
|
||||
# try:
|
||||
# response = requests.get('http://' + request.remote_addr + ':1624/api/restartapproved')
|
||||
# if response.status_code == 200:
|
||||
# pid = get_pid_of_server_windows(response.json()['port'])
|
||||
# subprocess.check_output("Taskkill /PID %s /F" % pid)
|
||||
# else:
|
||||
# return {}, 400
|
||||
# except Exception as e:
|
||||
# print(e)
|
||||
# return {}, 500
|
||||
# return {}, 200
|
||||
|
@ -1,7 +1,7 @@
|
||||
from flask import Flask
|
||||
from flask_restful import Api
|
||||
from .log_resource import LogResource
|
||||
from .restart_resource import RestartResource
|
||||
#from .restart_resource import RestartResource
|
||||
import logging
|
||||
|
||||
app = Flask(__name__)
|
||||
@ -11,4 +11,4 @@ def init():
|
||||
log.setLevel(logging.ERROR)
|
||||
api = Api(app)
|
||||
api.add_resource(LogResource, '/log/<string:path>')
|
||||
api.add_resource(RestartResource, '/restart')
|
||||
#api.add_resource(RestartResource, '/restart')
|
||||
|
@ -1,26 +1,12 @@
|
||||
aniso8601==3.0.2
|
||||
APScheduler==3.5.3
|
||||
certifi==2018.10.15
|
||||
chardet==3.0.4
|
||||
click==6.7
|
||||
aniso8601==6.0.0
|
||||
Click==7.0
|
||||
Flask==1.0.2
|
||||
Flask-JWT==0.3.2
|
||||
Flask-JWT-Extended==3.8.1
|
||||
Flask-RESTful==0.3.6
|
||||
idna==2.7
|
||||
itsdangerous==0.24
|
||||
Flask-RESTful==0.3.7
|
||||
itsdangerous==1.1.0
|
||||
Jinja2==2.10
|
||||
MarkupSafe==1.0
|
||||
marshmallow==3.0.0b8
|
||||
pip==9.0.3
|
||||
psutil==5.4.8
|
||||
pygal==2.4.0
|
||||
PyJWT==1.4.2
|
||||
pytz==2018.7
|
||||
requests==2.20.0
|
||||
setuptools==40.5.0
|
||||
six==1.11.0
|
||||
timeago==1.0.8
|
||||
tzlocal==1.5.1
|
||||
urllib3==1.24
|
||||
Werkzeug==0.14.1
|
||||
MarkupSafe==1.1.1
|
||||
pip==10.0.1
|
||||
pytz==2018.9
|
||||
setuptools==39.0.1
|
||||
six==1.12.0
|
||||
Werkzeug==0.15.2
|
||||
|
@ -51,7 +51,6 @@ namespace IW4MAdmin.Plugins.Stats
|
||||
{
|
||||
await Manager.AddMessageAsync(E.Origin.ClientId, await StatManager.GetIdForServer(E.Owner), E.Data);
|
||||
}
|
||||
|
||||
break;
|
||||
case GameEvent.EventType.MapChange:
|
||||
Manager.SetTeamBased(await StatManager.GetIdForServer(E.Owner), E.Owner.Gametype != "dm");
|
||||
@ -79,6 +78,22 @@ namespace IW4MAdmin.Plugins.Stats
|
||||
string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0];
|
||||
if (killInfo.Length >= 14)
|
||||
{
|
||||
if (E.Origin.ClientId <= 1 && E.Target.ClientId <= 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// this treats "world" damage as self damage
|
||||
if (E.Origin.ClientId <= 1)
|
||||
{
|
||||
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],
|
||||
killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15]);
|
||||
}
|
||||
@ -86,13 +101,18 @@ namespace IW4MAdmin.Plugins.Stats
|
||||
case GameEvent.EventType.Kill:
|
||||
if (!E.Owner.CustomCallback)
|
||||
{
|
||||
if (E.Origin.ClientId <= 1 && E.Target.ClientId <= 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// this treats "world" damage as self damage
|
||||
if (E.Origin.ClientId == 1)
|
||||
if (E.Origin.ClientId <= 1)
|
||||
{
|
||||
E.Origin = E.Target;
|
||||
}
|
||||
|
||||
if (E.Target.ClientId == 1)
|
||||
if (E.Target.ClientId <= 1)
|
||||
{
|
||||
E.Target = E.Origin;
|
||||
}
|
||||
@ -103,13 +123,18 @@ namespace IW4MAdmin.Plugins.Stats
|
||||
case GameEvent.EventType.Damage:
|
||||
if (!E.Owner.CustomCallback)
|
||||
{
|
||||
if (E.Origin.ClientId <= 1 && E.Target.ClientId <= 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// this treats "world" damage as self damage
|
||||
if (E.Origin.ClientId == 1)
|
||||
if (E.Origin.ClientId <= 1)
|
||||
{
|
||||
E.Origin = E.Target;
|
||||
}
|
||||
|
||||
if (E.Target.ClientId == 1)
|
||||
if (E.Target.ClientId <= 1)
|
||||
{
|
||||
E.Target = E.Origin;
|
||||
}
|
||||
@ -121,6 +146,22 @@ namespace IW4MAdmin.Plugins.Stats
|
||||
killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0];
|
||||
if (killInfo.Length >= 14)
|
||||
{
|
||||
if (E.Origin.ClientId <= 1 && E.Target.ClientId <= 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// this treats "world" damage as self damage
|
||||
if (E.Origin.ClientId <= 1)
|
||||
{
|
||||
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],
|
||||
killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15]);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ namespace Tests
|
||||
{
|
||||
File.WriteAllText("test_mp.log", "test_log_file");
|
||||
|
||||
IW4MAdmin.Application.Localization.Configure.Initialize("en-US");
|
||||
//IW4MAdmin.Application.Localization.Configure.Initialize("en-US");
|
||||
|
||||
Manager = ApplicationManager.GetInstance();
|
||||
|
||||
@ -41,7 +41,7 @@ namespace Tests
|
||||
Maps = new List<MapConfiguration>(),
|
||||
RConPollRate = 10000
|
||||
};
|
||||
Manager.ConfigHandler = new BaseConfigurationHandler<ApplicationConfiguration>("test.json");
|
||||
Manager.ConfigHandler = new BaseConfigurationHandler<ApplicationConfiguration>("test");
|
||||
Manager.ConfigHandler.Set(config);
|
||||
|
||||
Manager.Init().Wait();
|
||||
|
@ -34,7 +34,7 @@ namespace Tests
|
||||
[Fact]
|
||||
public void AreCommandAliasesUnique()
|
||||
{
|
||||
var mgr = IW4MAdmin.Application.Program.ServerManager;
|
||||
var mgr = Program.ServerManager;
|
||||
bool test = mgr.GetCommands().Count == mgr.GetCommands().Select(c => c.Alias).Distinct().Count();
|
||||
|
||||
Assert.True(test, "command aliases are not unique");
|
||||
|
@ -28,7 +28,7 @@ namespace SharedLibraryCore.Configuration
|
||||
public string WebfrontBindUrl { get; set; }
|
||||
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_MANUAL_URL")]
|
||||
public string ManualWebfrontUrl { get; set; }
|
||||
public string WebfrontUrl => string.IsNullOrEmpty(ManualWebfrontUrl) ? WebfrontBindUrl.Replace("0.0.0.0", "127.0.0.1") : ManualWebfrontUrl;
|
||||
public string WebfrontUrl => string.IsNullOrEmpty(ManualWebfrontUrl) ? WebfrontBindUrl?.Replace("0.0.0.0", "127.0.0.1") : ManualWebfrontUrl;
|
||||
[LocalizedDisplayName("SETUP_USE_CUSTOMENCODING")]
|
||||
public bool EnableCustomParserEncoding { get; set; }
|
||||
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_ENCODING")]
|
||||
|
@ -17,7 +17,6 @@ namespace SharedLibraryCore.Services
|
||||
{
|
||||
using (var context = new DatabaseContext())
|
||||
{
|
||||
|
||||
int? linkId = null;
|
||||
int? aliasId = null;
|
||||
|
||||
@ -45,23 +44,31 @@ namespace SharedLibraryCore.Services
|
||||
NetworkId = entity.NetworkId
|
||||
};
|
||||
|
||||
if (linkId.HasValue)
|
||||
{
|
||||
client.AliasLinkId = linkId.Value;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
client.AliasLink = new EFAliasLink();
|
||||
}
|
||||
|
||||
// they're just using a new GUID
|
||||
if (aliasId.HasValue)
|
||||
{
|
||||
client.CurrentAliasId = aliasId.Value;
|
||||
client.AliasLinkId = linkId.Value;
|
||||
}
|
||||
|
||||
// link was found but they don't have an exact alias
|
||||
else if (!aliasId.HasValue && linkId.HasValue)
|
||||
{
|
||||
client.AliasLinkId = linkId.Value;
|
||||
client.CurrentAlias = new Alias()
|
||||
{
|
||||
Name = entity.Name,
|
||||
DateAdded = DateTime.UtcNow,
|
||||
IPAddress = entity.IPAddress,
|
||||
LinkId = linkId.Value
|
||||
};
|
||||
}
|
||||
|
||||
// brand new players (supposedly)
|
||||
else
|
||||
{
|
||||
client.AliasLink = new EFAliasLink();
|
||||
|
||||
client.CurrentAlias = new Alias()
|
||||
{
|
||||
Name = entity.Name,
|
||||
@ -69,11 +76,6 @@ namespace SharedLibraryCore.Services
|
||||
IPAddress = entity.IPAddress,
|
||||
Link = client.AliasLink,
|
||||
};
|
||||
|
||||
if (client.CurrentAlias.Link == null)
|
||||
{
|
||||
client.CurrentAlias.LinkId = linkId.Value;
|
||||
}
|
||||
}
|
||||
|
||||
context.Clients.Add(client);
|
||||
@ -126,6 +128,11 @@ namespace SharedLibraryCore.Services
|
||||
|
||||
var oldAliasLink = entity.AliasLink;
|
||||
|
||||
// update all the clients that have the old alias link
|
||||
await context.Clients
|
||||
.Where(_client => _client.AliasLinkId == oldAliasLink.AliasLinkId)
|
||||
.ForEachAsync(_client => _client.AliasLinkId = newAliasLink.AliasLinkId);
|
||||
|
||||
entity.AliasLink = newAliasLink;
|
||||
entity.AliasLinkId = newAliasLink.AliasLinkId;
|
||||
|
||||
|
@ -22,7 +22,8 @@ namespace SharedLibraryCore
|
||||
public static class Utilities
|
||||
{
|
||||
#if DEBUG == true
|
||||
public static string OperatingDirectory => $"{Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)}{Path.DirectorySeparatorChar}";
|
||||
public static string OperatingDirectory => @"X:\IW4MAdmin\Application\bin\Debug\netcoreapp2.2\";
|
||||
//public static string OperatingDirectory => $"{Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)}{Path.DirectorySeparatorChar}";
|
||||
#else
|
||||
public static string OperatingDirectory => $"{Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)}{Path.DirectorySeparatorChar}..{Path.DirectorySeparatorChar}";
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user