started work on T6M parsing rest api

fixed bug in login program preventing regular users from executing commands
make log reading async and changed encoding to UTF7
This commit is contained in:
RaidMax 2018-04-15 20:27:43 -05:00
parent 2964fd71b2
commit 2fc2109a2e
10 changed files with 131 additions and 35 deletions

View File

@ -12,22 +12,34 @@ namespace Application.EventParsers
{
public GameEvent GetEvent(Server server, string logLine)
{
string[] lineSplit = logLine.Split(';');
string cleanedEventName = Regex.Replace(lineSplit[0], @" +[0-9]+:[0-9]+ +", "");
string cleanedLogLine = Regex.Replace(logLine, @"^ *[0-9]+:[0-9]+ *", "");
string[] lineSplit = cleanedLogLine.Split(';');
if (cleanedEventName[0] == 'K')
if (lineSplit[0][0] == 'K')
{
return new GameEvent()
{
Type = GameEvent.EventType.Script,
Data = logLine,
Data = cleanedLogLine,
Origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 6)),
Target = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2)),
Owner = server
};
}
if (cleanedEventName == "say")
if (lineSplit[0][0] == 'D')
{
return new GameEvent()
{
Type = GameEvent.EventType.Damage,
Data = cleanedLogLine,
Origin = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 6)),
Target = server.GetPlayersAsList().First(c => c.ClientNumber == Utilities.ClientIdFromString(lineSplit, 2)),
Owner = server
};
}
if (lineSplit[0] == "say")
{
return new GameEvent()
{
@ -39,7 +51,7 @@ namespace Application.EventParsers
};
}
if (cleanedEventName.Contains("ShutdownGame"))
if (lineSplit[0].Contains("ShutdownGame"))
{
return new GameEvent()
{
@ -57,7 +69,7 @@ namespace Application.EventParsers
};
}
if (cleanedEventName.Contains("InitGame"))
if (lineSplit[0].Contains("InitGame"))
{
return new GameEvent()
{

View File

@ -313,13 +313,9 @@ namespace IW4MAdmin.Application
public ClientService GetClientService() => ClientSvc;
public AliasService GetAliasService() => AliasSvc;
public PenaltyService GetPenaltyService() => PenaltySvc;
public IConfigurationHandler<ApplicationConfiguration> GetApplicationSettings() => ConfigHandler;
public IDictionary<int, Player> GetPrivilegedClients() => PrivilegedClients;
public IEventApi GetEventApi() => Api;
public bool ShutdownRequested() => !Running;
}
}

View File

@ -9,11 +9,49 @@ using SharedLibraryCore.Objects;
using SharedLibraryCore.RCon;
using SharedLibraryCore.Exceptions;
using System.Text;
using System.Linq;
using System.Net.Http;
namespace Application.RconParsers
{
public class T6MRConParser : IRConParser
{
class T6MResponse
{
public class SInfo
{
public short Com_maxclients { get; set; }
public string Game { get; set; }
public string Gametype { get; set; }
public string Mapname { get; set; }
public short NumBots { get; set; }
public short NumClients { get; set; }
public short Round { get; set; }
public string Sv_hostname { get; set; }
}
public class PInfo
{
public short Assists { get; set; }
public string Clan { get; set; }
public short Deaths { get; set; }
public short Downs { get; set; }
public short Headshots { get; set; }
public short Id { get; set; }
public bool IsBot { get; set; }
public short Kills { get; set; }
public string Name { get; set; }
public short Ping { get; set; }
public short Revives { get; set; }
public int Score { get; set; }
public long Xuid { get; set; }
public string Ip { get; set; }
}
public SInfo Info { get; set; }
public PInfo[] Players { get; set; }
}
private static CommandPrefix Prefixes = new CommandPrefix()
{
Tell = "tell {0} {1}",
@ -65,6 +103,8 @@ namespace Application.RconParsers
{
string[] response = await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, "status");
return ClientsFromStatus(response);
//return ClientsFromResponse(connection);
}
public async Task<bool> SetDvarAsync(Connection connection, string dvarName, object dvarValue)
@ -74,6 +114,42 @@ namespace Application.RconParsers
return true;
}
private async Task<List<Player>> ClientsFromResponse(Connection conn)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri($"http://{conn.Endpoint.Address}:{conn.Endpoint.Port}/");
try
{
var parameters = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("rcon_password", conn.RConPassword)
});
var serverResponse = await client.PostAsync("/info", parameters);
var serverResponseObject = Newtonsoft.Json.JsonConvert.DeserializeObject<T6MResponse>(await serverResponse.Content.ReadAsStringAsync());
return serverResponseObject.Players.Select(p => new Player()
{
Name = p.Name,
NetworkId = p.Xuid,
ClientNumber = p.Id,
IPAddress = p.Ip.Split(':')[0].ConvertToIP(),
Ping = p.Ping,
Score = p.Score,
IsBot = p.IsBot,
}).ToList();
}
catch (HttpRequestException e)
{
throw new NetworkException(e.Message);
}
}
}
private List<Player> ClientsFromStatus(string[] status)
{
List<Player> StatusPlayers = new List<Player>();

View File

@ -48,7 +48,10 @@ namespace IW4MAdmin
override public async Task<bool> AddPlayer(Player polledPlayer)
{
if (polledPlayer.Ping == 999 || polledPlayer.Ping < 1 || polledPlayer.ClientNumber > (MaxClients) || polledPlayer.ClientNumber < 0)
if ((polledPlayer.Ping == 999 && !polledPlayer.IsBot)||
polledPlayer.Ping < 1 || polledPlayer.ClientNumber > (MaxClients) ||
polledPlayer.ClientNumber < 0)
{
//Logger.WriteDebug($"Skipping client not in connected state {P}");
return true;
@ -430,6 +433,7 @@ namespace IW4MAdmin
DateTime lastCount = DateTime.Now;
DateTime tickTime = DateTime.Now;
bool firstRun = true;
int count = 0;
override public async Task<bool> ProcessUpdatesAsync(CancellationToken cts)
{
@ -510,14 +514,13 @@ namespace IW4MAdmin
if (l_size != LogFile.Length())
{
// this should be the longest running task
await Task.FromResult(lines = LogFile.Tail(12));
lines = l_size != -1 ? await LogFile.Tail(12) : lines;
if (lines != oldLines)
{
l_size = LogFile.Length();
int end = (lines.Length == oldLines.Length) ? lines.Length - 1 : Math.Abs((lines.Length - oldLines.Length)) - 1;
for (int count = 0; count < lines.Length; count++)
for (count = 0; count < lines.Length; count++)
{
if (lines.Length < 1 && oldLines.Length < 1)
continue;
@ -561,6 +564,13 @@ namespace IW4MAdmin
return false;
}
catch (InvalidOperationException)
{
Logger.WriteWarning("Event could not parsed properly");
Logger.WriteDebug($"Log Line: {lines[count]}");
return false;
}
catch (Exception E)
{
Logger.WriteError($"Encountered error on {IP}:{Port}");
@ -654,7 +664,7 @@ namespace IW4MAdmin
string mainPath = EventParser.GetGameDir();
mainPath = (GameName == Game.IW4 && onelog.Value > 0) ? "main" : mainPath;
#if DEBUG
// basepath.Value = @"\\192.168.88.253\Call of Duty Black Ops II";
basepath.Value = @"\\192.168.88.253\Call of Duty Black Ops II";
#endif
string logPath = game.Value == string.Empty ?
$"{basepath.Value.Replace('\\', Path.DirectorySeparatorChar)}{Path.DirectorySeparatorChar}{mainPath}{Path.DirectorySeparatorChar}{logfile.Value}" :
@ -680,7 +690,7 @@ namespace IW4MAdmin
Logger.WriteInfo($"Log file is {logPath}");
#if DEBUG
// LogFile = new RemoteFile("https://raidmax.org/IW4MAdmin/getlog.php");
// LogFile = new RemoteFile("https://raidmax.org/IW4MAdmin/getlog.php");
#else
await Broadcast("IW4M Admin is now ^2ONLINE");
#endif

View File

@ -36,6 +36,9 @@ namespace IW4MAdmin.Plugins.Login
if (E.Type == GameEvent.EventType.Command)
{
if (E.Origin.Level < SharedLibraryCore.Objects.Player.Permission.Moderator)
return Task.CompletedTask;
if (((Command)E.Extra).Name == new SharedLibraryCore.Commands.CSetPassword().Name &&
E.Owner.Manager.GetPrivilegedClients()[E.Origin.ClientId].Password == null)
return Task.CompletedTask;

View File

@ -36,6 +36,7 @@ namespace SharedLibraryCore
// FROM GAME
Script,
Kill,
Damage,
Death,
}

View File

@ -4,6 +4,7 @@ using System.Text;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
namespace SharedLibraryCore
{
@ -23,12 +24,6 @@ namespace SharedLibraryCore
FileCache = cl.GetStringAsync(Location).Result.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
}
public override string[] Tail(int lineCount)
{
// Retrieve();
return FileCache;
}
public override long Length()
{
Retrieve();
@ -44,7 +39,8 @@ namespace SharedLibraryCore
if (fileName != string.Empty)
{
Name = fileName;
Handle = new StreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
Handle = new StreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, true), Encoding.UTF7);
sze = Handle.BaseStream.Length;
}
}
@ -70,20 +66,20 @@ namespace SharedLibraryCore
return Handle?.ReadToEnd();
}
public virtual String[] Tail(int lineCount)
public virtual async Task<String[]> Tail(int lineCount)
{
var buffer = new List<string>(lineCount);
string line;
for (int i = 0; i < lineCount; i++)
{
line = Handle.ReadLine();
line = await Handle.ReadLineAsync();
if (line == null) return buffer.ToArray();
buffer.Add(line);
}
int lastLine = lineCount - 1; //The index of the last line read from the buffer. Everything > this index was read earlier than everything <= this indes
while (null != (line = Handle.ReadLine()))
while (null != (line = await Handle.ReadLineAsync()))
{
lastLine++;
if (lastLine == lineCount) lastLine = 0;

View File

@ -77,7 +77,8 @@ namespace SharedLibraryCore.Objects
public int Score { get; set; }
[NotMapped]
public IList<Dtos.ProfileMeta> Meta { get; set; }
[NotMapped]
public bool IsBot { get; set; }
private int _ipaddress;
public override int IPAddress
{

View File

@ -34,8 +34,8 @@ namespace SharedLibraryCore.RCon
public class Connection
{
IPEndPoint Endpoint;
string RConPassword;
public IPEndPoint Endpoint { get; private set; }
public string RConPassword { get; private set; }
Socket ServerConnection;
ILogger Log;
int FailedSends;

View File

@ -331,7 +331,8 @@ namespace SharedLibraryCore
Level = client.Level,
LastConnection = client.LastConnection == DateTime.MinValue ? DateTime.UtcNow : client.LastConnection,
CurrentAlias = client.CurrentAlias,
CurrentAliasId = client.CurrentAlias.AliasId
CurrentAliasId = client.CurrentAlias.AliasId,
IsBot = client.NetworkId == -1
};
}
@ -366,13 +367,13 @@ namespace SharedLibraryCore
return pID;
}
public static async Task<Dvar<T>> GetDvarAsync<T>(this Server server, string dvarName) => await server.RconParser.GetDvarAsync<T>(server.RemoteConnection, dvarName);
public static Task<Dvar<T>> GetDvarAsync<T>(this Server server, string dvarName) => server.RconParser.GetDvarAsync<T>(server.RemoteConnection, dvarName);
public static async Task SetDvarAsync(this Server server, string dvarName, object dvarValue) => await server.RconParser.SetDvarAsync(server.RemoteConnection, dvarName, dvarValue);
public static Task SetDvarAsync(this Server server, string dvarName, object dvarValue) => server.RconParser.SetDvarAsync(server.RemoteConnection, dvarName, dvarValue);
public static async Task<string[]> ExecuteCommandAsync(this Server server, string commandName) => await server.RconParser.ExecuteCommandAsync(server.RemoteConnection, commandName);
public static Task<string[]> ExecuteCommandAsync(this Server server, string commandName) => server.RconParser.ExecuteCommandAsync(server.RemoteConnection, commandName);
public static async Task<List<Player>> GetStatusAsync(this Server server) => await server.RconParser.GetStatusAsync(server.RemoteConnection);
public static Task<List<Player>> GetStatusAsync(this Server server) => server.RconParser.GetStatusAsync(server.RemoteConnection);
}
}