diff --git a/Admin/Application.csproj b/Admin/Application.csproj index 2e92bb4b0..e5faee5df 100644 --- a/Admin/Application.csproj +++ b/Admin/Application.csproj @@ -144,7 +144,6 @@ - True @@ -182,12 +181,6 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - Always @@ -245,7 +238,9 @@ PreserveNewest - + + PreserveNewest + @@ -363,6 +358,7 @@ copy /Y "$(SolutionDir)_customcallbacks.gsc" "$(SolutionDir)BUILD\userraw\script copy /Y "$(TargetDir)$(TargetName).exe" "$(SolutionDir)BUILD" copy /Y "$(TargetDir)IW4MAdmin.exe.config" "$(SolutionDir)BUILD" copy /Y "$(ProjectDir)lib\Kayak.dll" "$(SolutionDir)BUILD\lib" +xcopy /Y /I /E "$(SolutionDir)SharedLibrary\$(OutDir)*" "$(TargetDir)Lib" xcopy /Y /I /E "$(ProjectDir)webfront\*" "$(SolutionDir)BUILD\Webfront" xcopy /Y /I /E "$(SolutionDir)Admin\Config\*" "$(SolutionDir)BUILD\Config" diff --git a/Admin/IW4MAdmin.exe.config b/Admin/IW4MAdmin.exe.config index 2e57e9ad8..ee80f1361 100644 --- a/Admin/IW4MAdmin.exe.config +++ b/Admin/IW4MAdmin.exe.config @@ -1,11 +1,37 @@ - + + + +
+ + - + + + + + + + + + + + + + + + + + + + + diff --git a/Admin/Main.cs b/Admin/Main.cs index 823a01474..72a91df4d 100644 --- a/Admin/Main.cs +++ b/Admin/Main.cs @@ -6,6 +6,11 @@ using SharedLibrary; using System.Threading.Tasks; using System.IO; +#if DEBUG +using SharedLibrary.Database; +using SharedLibrary.Objects; +#endif + namespace IW4MAdmin { class Program @@ -38,7 +43,7 @@ namespace IW4MAdmin Task.Run(() => { String userInput; - Player Origin = new Player("IW4MAdmin", "", -1, Player.Permission.Console, -1, "", 0, ""); + Player Origin = ServerManager.GetClientService().Get(1).Result.AsPlayer(); do { @@ -50,8 +55,8 @@ namespace IW4MAdmin if (ServerManager.Servers.Count == 0) return; + Origin.CurrentServer = ServerManager.Servers[0]; Event E = new Event(Event.GType.Say, userInput, Origin, null, ServerManager.Servers[0]); - Origin.lastEvent = E; ServerManager.Servers[0].ExecuteEvent(E); Console.Write('>'); @@ -60,7 +65,7 @@ namespace IW4MAdmin } - catch(Exception e) + catch (Exception e) { Console.WriteLine($"Fatal Error during initialization: {e.Message}"); Console.WriteLine("Press any key to exit..."); diff --git a/Admin/Manager.cs b/Admin/Manager.cs index cb4635fe0..758971fba 100644 --- a/Admin/Manager.cs +++ b/Admin/Manager.cs @@ -10,6 +10,10 @@ using SharedLibrary.Interfaces; using SharedLibrary.Commands; using SharedLibrary.Helpers; using SharedLibrary.Exceptions; +using SharedLibrary.Objects; +using SharedLibrary.Database; +using SharedLibrary.Database.Models; +using SharedLibrary.Services; namespace IW4MAdmin { @@ -22,14 +26,13 @@ namespace IW4MAdmin static ApplicationManager Instance; List TaskStatuses; - Database ClientDatabase; - Database AliasesDatabase; - IPenaltyList ClientPenalties; List Commands; List MessageTokens; Kayak.IScheduler webServiceTask; Thread WebThread; - List PrivilegedClients; + ClientService ClientSvc; + AliasService AliasSvc; + PenaltyService PenaltySvc; #if FTP_LOG const int UPDATE_FREQUENCY = 15000; #else @@ -43,10 +46,9 @@ namespace IW4MAdmin Commands = new List(); TaskStatuses = new List(); MessageTokens = new List(); - - ClientDatabase = new ClientsDB("Database/clients.rm", Logger); - AliasesDatabase = new AliasesDB("Database/aliases.rm", Logger); - ClientPenalties = new PenaltyList(); + ClientSvc = new ClientService(); + AliasSvc = new AliasService(); + PenaltySvc = new PenaltyService(); } public IList GetServers() @@ -145,7 +147,7 @@ namespace IW4MAdmin #endregion #region COMMANDS - if ((ClientDatabase as ClientsDB).GetOwner() == null) + if (ClientSvc.GetOwners().Result.Count == 0) Commands.Add(new COwner()); Commands.Add(new CQuit()); @@ -185,11 +187,6 @@ namespace IW4MAdmin Commands.Add(C); #endregion - #region ADMINS - PrivilegedClients = GetClientDatabase().GetAdmins(); - #endregion - - Running = true; } @@ -225,21 +222,6 @@ namespace IW4MAdmin Running = false; } - public ClientsDB GetClientDatabase() - { - return ClientDatabase as ClientsDB; - } - - public AliasesDB GetAliasesDatabase() - { - return AliasesDatabase as AliasesDB; - } - - public IPenaltyList GetClientPenalties() - { - return ClientPenalties; - } - public ILogger GetLogger() { return Logger; @@ -260,54 +242,8 @@ namespace IW4MAdmin return ActiveClients; } - public IList GetAliasClients(Player Origin) - { - List databaseIDs = new List(); - - foreach (Aliases A in GetAliases(Origin)) - databaseIDs.Add(A.Number); - - return GetClientDatabase().GetPlayers(databaseIDs); - } - - public IList GetAliases(Player Origin) - { - List allAliases = new List(); - - if (Origin == null) - return allAliases; - - Aliases currentIdentityAliases = GetAliasesDatabase().GetPlayerAliases(Origin.DatabaseID); - - if (currentIdentityAliases == null) - return allAliases; - - GetAliases(allAliases, currentIdentityAliases); - if (Origin.Alias != null) - allAliases.Add(Origin.Alias); - allAliases.Add(currentIdentityAliases); - return allAliases; - } - - public IList GetPrivilegedClients() - { - return PrivilegedClients; - } - - private void GetAliases(List returnAliases, Aliases currentAlias) - { - foreach (String IP in currentAlias.IPS) - { - List Matching = GetAliasesDatabase().GetPlayerAliases(IP); - foreach (Aliases I in Matching) - { - if (!returnAliases.Contains(I) && returnAliases.Find(x => x.Number == I.Number) == null) - { - returnAliases.Add(I); - GetAliases(returnAliases, I); - } - } - } - } + public ClientService GetClientService() => ClientSvc; + public AliasService GetAliasService() => AliasSvc; + public PenaltyService GetPenaltyService() => PenaltySvc; } } diff --git a/Admin/PenaltyList.cs b/Admin/PenaltyList.cs deleted file mode 100644 index 3279a1989..000000000 --- a/Admin/PenaltyList.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using SharedLibrary; - -namespace IW4MAdmin -{ - class PenaltyList : SharedLibrary.Interfaces.IPenaltyList - { - public PenaltyList() - { - } - - public void AddPenalty(Penalty P) - { - ApplicationManager.GetInstance().GetClientDatabase().AddPenalty(P); - } - - public void RemovePenalty(Penalty P) - { - ApplicationManager.GetInstance().GetClientDatabase().RemoveBan(P.OffenderID); - } - - public List FindPenalties(Player P) - { - return ApplicationManager.GetInstance().GetClientDatabase().GetClientPenalties(P); - } - - public List AsChronoList(int offset, int count, Penalty.Type penaltyType = Penalty.Type.Any) - { - return ApplicationManager.GetInstance().GetClientDatabase().GetPenaltiesChronologically(offset, count, penaltyType); - } - } -} diff --git a/Admin/Server.cs b/Admin/Server.cs index 796882cc4..c30ced944 100644 --- a/Admin/Server.cs +++ b/Admin/Server.cs @@ -8,6 +8,8 @@ using System.Threading.Tasks; using SharedLibrary; using SharedLibrary.Network; using SharedLibrary.Interfaces; +using SharedLibrary.Objects; +using System.Text.RegularExpressions; namespace IW4MAdmin { @@ -15,128 +17,109 @@ namespace IW4MAdmin { public IW4MServer(IManager mgr, ServerConfiguration cfg) : base(mgr, cfg) { } - override public async Task AddPlayer(Player P) + override public async Task AddPlayer(Player polledPlayer) { - if (P.ClientID < 0 || P.ClientID > (Players.Count - 1) || P.Ping < 1 || P.Ping == 999) // invalid index - return false; - - if (Players[P.ClientID] != null && Players[P.ClientID].NetworkID == P.NetworkID) // if someone has left and a new person has taken their spot between polls + if (Players[polledPlayer.ClientNumber] != null && + Players[polledPlayer.ClientNumber].NetworkId == polledPlayer.NetworkId) { // update their ping - Players[P.ClientID].Ping = P.Ping; + Players[polledPlayer.ClientNumber].Ping = polledPlayer.Ping; return true; } - if (P.Name.Length < 3) + if (polledPlayer.Name.Length < 3) { - await this.ExecuteCommandAsync($"clientkick {P.ClientID} \"Your name must contain atleast 3 characters.\""); + await this.ExecuteCommandAsync($"clientkick {polledPlayer.ClientNumber} \"Your name must contain atleast 3 characters.\""); return false; } - Logger.WriteDebug($"Client slot #{P.ClientID} now reserved"); + Logger.WriteDebug($"Client slot #{polledPlayer.ClientNumber} now reserved"); try { - Player NewPlayer = Manager.GetClientDatabase().GetPlayer(P.NetworkID, P.ClientID); + Player player = null; + var client = (await Manager.GetClientService().GetUnique(polledPlayer.NetworkId)); - if (NewPlayer == null) // first time connecting + // first time client is connecting to server + if (client == null) { - Logger.WriteDebug($"Client slot #{P.ClientID} first time connecting"); - Manager.GetClientDatabase().AddPlayer(P); - NewPlayer = Manager.GetClientDatabase().GetPlayer(P.NetworkID, P.ClientID); - Manager.GetAliasesDatabase().AddPlayerAliases(new Aliases(NewPlayer.DatabaseID, NewPlayer.Name, NewPlayer.IP)); + Logger.WriteDebug($"Client {polledPlayer} first time connecting"); + player = (await Manager.GetClientService().Create(polledPlayer)).AsPlayer(); } - List Admins = Manager.GetClientDatabase().GetAdmins(); - if (Admins.Find(x => x.Name == P.Name) != null) - { - if ((Admins.Find(x => x.Name == P.Name).NetworkID != P.NetworkID) && NewPlayer.Level < Player.Permission.Moderator) - await this.ExecuteCommandAsync("clientkick " + P.ClientID + " \"Please do not impersonate an admin^7\""); - } - - // below this needs to be optimized ~ 425ms runtime - NewPlayer.UpdateName(P.Name.Trim()); - NewPlayer.Alias = Manager.GetAliasesDatabase().GetPlayerAliases(NewPlayer.DatabaseID); - - if (NewPlayer.Alias == null) - { - Manager.GetAliasesDatabase().AddPlayerAliases(new Aliases(NewPlayer.DatabaseID, NewPlayer.Name, NewPlayer.IP)); - NewPlayer.Alias = Manager.GetAliasesDatabase().GetPlayerAliases(NewPlayer.DatabaseID); - } - - if (P.lastEvent == null || P.lastEvent.Owner == null) - NewPlayer.lastEvent = new Event(Event.GType.Say, null, NewPlayer, null, this); // this is messy but its throwing an error when they've started in too late + // client has connected in the past else - NewPlayer.lastEvent = P.lastEvent; - - // lets check aliases - if ((NewPlayer.Alias.Names.Find(m => m.Equals(P.Name))) == null || NewPlayer.Name == null || NewPlayer.Name == String.Empty) { - NewPlayer.UpdateName(P.Name.Trim()); - NewPlayer.Alias.Names.Add(NewPlayer.Name); + client.Connections += 1; + bool aliasExists = client.AliasLink.Children + .FirstOrDefault(a => a.Name == polledPlayer.Name && a.IP == polledPlayer.IPAddress) != null; + + if (!aliasExists) + { + Logger.WriteDebug($"Client {polledPlayer} has connected previously under a different alias"); + await Manager.GetAliasService().Create(new SharedLibrary.Database.Models.EFAlias() + { + Active = true, + IP = polledPlayer.IPAddress, + Name = polledPlayer.Name, + DateAdded = DateTime.UtcNow, + Link = client.AliasLink, + }); + } + + client.Name = polledPlayer.Name; + client.IPAddress = polledPlayer.IPAddress; + player = client.AsPlayer(); } - // and ips - if (NewPlayer.Alias.IPS.Find(i => i.Equals(P.IP)) == null || P.IP == null || P.IP == String.Empty) - NewPlayer.Alias.IPS.Add(P.IP); - NewPlayer.SetIP(P.IP); - Manager.GetAliasesDatabase().UpdatePlayerAliases(NewPlayer.Alias); - Manager.GetClientDatabase().UpdatePlayer(NewPlayer); - - await ExecuteEvent(new Event(Event.GType.Connect, "", NewPlayer, null, this)); - - if (NewPlayer.Level == Player.Permission.Banned) // their guid is already banned so no need to check aliases + /*var Admins = Manager.GetDatabase().GetPrivilegedClients(); + if (Admins.Where(x => x.Name == polledPlayer.Name).Count() > 0) { - Logger.WriteInfo($"Banned client {P.Name}::{P.NetworkID} trying to connect..."); - await NewPlayer.Kick(NewPlayer.lastOffense != null ? "^7Previously banned for ^5 " + NewPlayer.lastOffense : "^7Previous Ban", NewPlayer); + if ((Admins.First(x => x.Name == polledPlayer.Name).NetworkId != polledPlayer.NetworkId) && NewPlayer.Level < Player.Permission.Moderator) + await this.ExecuteCommandAsync("clientkick " + polledPlayer.ClientNumber + " \"Please do not impersonate an admin^7\""); + }*/ + player.CurrentServer = this; + var ban = (await Manager.GetPenaltyService().Find(p => p.LinkId == player.AliasLink.AliasLinkId + && p.Expires > DateTime.UtcNow)).FirstOrDefault(); + + if (ban != null) + { + Logger.WriteInfo($"Banned client {player} trying to connect..."); + var autoKickClient = (await Manager.GetClientService().Get(1)).AsPlayer(); + autoKickClient.CurrentServer = this; + + if (ban.Type == Penalty.PenaltyType.TempBan) + await this.ExecuteCommandAsync($"clientkick {player.ClientNumber} \"You are temporarily banned. ({(ban.Expires - DateTime.Now).TimeSpanText()} left)\""); + else + await player.Kick($"previously banned for {ban.Offense}", autoKickClient); + + if (player.Level != Player.Permission.Banned && ban.Type == Penalty.PenaltyType.Ban) + await player.Ban($"previously banned for {ban.Offense}", autoKickClient); return true; } - var newPlayerAliases = Manager.GetAliasClients(NewPlayer); + // if (aP.Level == Player.Permission.Flagged) + // NewPlayer.Level = Player.Permission.Flagged; + // Do the player specific stuff + player.ClientNumber = polledPlayer.ClientNumber; + Players[player.ClientNumber] = player; + await Manager.GetClientService().Update(player); + Logger.WriteInfo($"Client {player} connecting..."); // they're clean - foreach (Player aP in newPlayerAliases) // lets check their aliases - { - if (aP == null) - continue; + await ExecuteEvent(new Event(Event.GType.Connect, "", player, null, this)); - if (aP.Level == Player.Permission.Flagged) - NewPlayer.SetLevel(Player.Permission.Flagged); - - Penalty B = IsBanned(aP); - - if (B != null && B.BType == Penalty.Type.Ban) - { - Logger.WriteDebug($"Banned client {aP.Name}::{aP.NetworkID} is connecting with new alias {NewPlayer.Name}"); - NewPlayer.lastOffense = String.Format("Evading ( {0} )", aP.Name); - - await NewPlayer.Ban(B.Reason != null ? "^7Previously banned for ^5 " + B.Reason : "^7Previous Ban", NewPlayer); - Players[NewPlayer.ClientID] = null; - - return true; - } - - var activeTB = IsTempBanned(aP); - if (activeTB != null) - { - await this.ExecuteCommandAsync($"clientkick {NewPlayer.ClientID} \"You are temporarily banned. ({(activeTB.Expires - DateTime.Now).TimeSpanText()} left)\""); - } - } - - Players[NewPlayer.ClientID] = NewPlayer; - Logger.WriteInfo($"Client {NewPlayer.Name}::{NewPlayer.NetworkID} connecting..."); // they're clean - - if (NewPlayer.Level > Player.Permission.Moderator) - await NewPlayer.Tell("There are ^5" + Reports.Count + " ^7recent reports!"); + // if (NewPlayer.Level > Player.Permission.Moderator) + // await NewPlayer.Tell("There are ^5" + Reports.Count + " ^7recent reports!"); return true; } catch (Exception E) { - Manager.GetLogger().WriteError($"Unable to add player {P.Name}::{P.NetworkID}"); + Manager.GetLogger().WriteError($"Unable to add player {polledPlayer.Name}::{polledPlayer.NetworkId}"); Manager.GetLogger().WriteDebug(E.StackTrace); return false; } @@ -148,10 +131,10 @@ namespace IW4MAdmin if (cNum >= 0) { Player Leaving = Players[cNum]; - Leaving.Connections++; - Manager.GetClientDatabase().UpdatePlayer(Leaving); + Leaving.TotalConnectionTime += (int)(DateTime.UtcNow - Leaving.ConnectionTime).TotalSeconds; + await Manager.GetClientService().Update(Leaving); - Logger.WriteInfo($"Client {Leaving.Name}::{Leaving.NetworkID} disconnecting..."); + Logger.WriteInfo($"Client {Leaving} disconnecting..."); await ExecuteEvent(new Event(Event.GType.Disconnect, "", Leaving, null, this)); Players[cNum] = null; } @@ -182,17 +165,6 @@ namespace IW4MAdmin return Players[pID]; } - //Check ban list for every banned player and return ban if match is found - override public Penalty IsBanned(Player C) - { - return Manager.GetClientPenalties().FindPenalties(C).Where(b => b.BType == Penalty.Type.Ban).FirstOrDefault(); - } - - public Penalty IsTempBanned(Player C) - { - return Manager.GetClientPenalties().FindPenalties(C).FirstOrDefault(b => b.BType == Penalty.Type.TempBan && b.Expires > DateTime.Now); - } - //Process requested command correlating to an event // todo: this needs to be removed out of here override public async Task ValidateCommand(Event E) @@ -234,19 +206,16 @@ namespace IW4MAdmin int cNum = -1; int.TryParse(Args[0], out cNum); - if (Args[0] == String.Empty) - return C; - if (Args[0][0] == '@') // user specifying target by database ID { int dbID = -1; int.TryParse(Args[0].Substring(1, Args[0].Length - 1), out dbID); - Player found = Manager.GetClientDatabase().GetPlayer(dbID); + var found = await Manager.GetClientService().Get(dbID); if (found != null) { - E.Target = found; - E.Target.lastEvent = E; + E.Target = found.AsPlayer(); + E.Target.CurrentServer = this as IW4MServer; E.Owner = this as IW4MServer; } } @@ -254,7 +223,10 @@ namespace IW4MAdmin else if (Args[0].Length < 3 && cNum > -1 && cNum < 18) // user specifying target by client num { if (Players[cNum] != null) + { E.Target = Players[cNum]; + E.Data = String.Join(" ", Args.Skip(1)); + } } List matchingPlayers; @@ -268,7 +240,10 @@ namespace IW4MAdmin throw new SharedLibrary.Exceptions.CommandException($"{E.Origin} had multiple players found for {C.Name}"); } else if (matchingPlayers.Count == 1) + { E.Target = matchingPlayers.First(); + E.Data = Regex.Replace(E.Data, $"\"{E.Target.Name}\"", "", RegexOptions.IgnoreCase).Trim(); + } } if (E.Target == null) // Find active player as single word @@ -278,11 +253,14 @@ namespace IW4MAdmin { await E.Origin.Tell("Multiple players match that name"); foreach (var p in matchingPlayers) - await E.Origin.Tell($"[^3{p.ClientID}^7] {p.Name}"); + await E.Origin.Tell($"[^3{p.ClientNumber}^7] {p.Name}"); throw new SharedLibrary.Exceptions.CommandException($"{E.Origin} had multiple players found for {C.Name}"); } else if (matchingPlayers.Count == 1) + { E.Target = matchingPlayers.First(); + E.Data = Regex.Replace(E.Data, $"{E.Target.Name}", "", RegexOptions.IgnoreCase).Trim(); + } } if (E.Target == null && C.RequiresTarget) @@ -327,12 +305,21 @@ namespace IW4MAdmin for (int i = 0; i < Players.Count; i++) { - if (CurrentPlayers.Find(p => p.ClientID == i) == null && Players[i] != null) + if (CurrentPlayers.Find(p => p.ClientNumber == i) == null && Players[i] != null) await RemovePlayer(i); } + //polledPlayer.ClientNumber < 0 || polledPlayer.ClientNumber > (Players.Count - 1) || polledPlayer.Ping < 1 || polledPlayer.Ping == 999 foreach (var P in CurrentPlayers) + { + if (P.Ping == 999 || P.ClientNumber > MaxClients - 1 || P.ClientNumber < 0) + { + Logger.WriteDebug($"Skipping client not in connected state {P}"); + continue; + } + await AddPlayer(P); + } return CurrentPlayers.Count; } @@ -441,8 +428,6 @@ namespace IW4MAdmin if (event_.Origin == null) continue; - event_.Origin.lastEvent = event_; - event_.Origin.lastEvent.Owner = this; await ExecuteEvent(event_); } } @@ -623,9 +608,6 @@ namespace IW4MAdmin else // Not a command { E.Data = E.Data.StripColors(); - // this should not be done for all messages. - //if (E.Data.Length > 50) - // E.Data = E.Data.Substring(0, 50) + "..."; ChatHistory.Add(new Chat(E.Origin.Name, E.Data, DateTime.Now)); } @@ -661,46 +643,98 @@ namespace IW4MAdmin public override async Task Warn(String Reason, Player Target, Player Origin) { if (Target.Warnings >= 4) - await Target.Kick("Too many warnings!", Origin); + await Target.Kick("Too many warnings!", (await Manager.GetClientService().Get(1)).AsPlayer()); else { - Penalty newPenalty = new Penalty(Penalty.Type.Warning, Reason.StripColors(), Target.NetworkID, Origin.NetworkID, DateTime.Now, Target.IP, DateTime.Now); - Manager.GetClientPenalties().AddPenalty(newPenalty); + Penalty newPenalty = new Penalty() + { + Type = Penalty.PenaltyType.Warning, + Expires = DateTime.UtcNow, + Offender = Target, + Offense = Reason, + Punisher = Origin, + Active = true, + When = DateTime.UtcNow, + Link = Target.AliasLink + }; + + await Manager.GetPenaltyService().Create(newPenalty); Target.Warnings++; - String Message = String.Format("^1WARNING ^7[^3{0}^7]: ^3{1}^7, {2}", Target.Warnings, Target.Name, Target.lastOffense); + + String Message = String.Format("^1WARNING ^7[^3{0}^7]: ^3{1}^7, {2}", Target.Warnings, Target.Name, Reason); await Broadcast(Message); } } public override async Task Kick(String Reason, Player Target, Player Origin) { - if (Target.ClientID > -1) + if (Target.ClientNumber > -1) { String Message = "^1Player Kicked: ^5" + Reason; - Penalty newPenalty = new Penalty(Penalty.Type.Kick, Reason.StripColors().Trim(), Target.NetworkID, Origin.NetworkID, DateTime.Now, Target.IP, DateTime.Now); - Manager.GetClientPenalties().AddPenalty(newPenalty); - await this.ExecuteCommandAsync($"clientkick {Target.ClientID} \"{Message}^7\""); + await Manager.GetPenaltyService().Create(new Penalty() + { + Type = Penalty.PenaltyType.Kick, + Expires = DateTime.UtcNow, + Offender = Target, + Offense = Reason, + Punisher = Origin, + Active = true, + When = DateTime.UtcNow, + Link = Target.AliasLink + }); + await this.ExecuteCommandAsync($"clientkick {Target.ClientNumber} \"{Message}^7\""); } } public override async Task TempBan(String Reason, TimeSpan length, Player Target, Player Origin) { - await this.ExecuteCommandAsync($"clientkick {Target.ClientID } \"^1Player Temporarily Banned: ^5{ Reason }\""); - Penalty newPenalty = new Penalty(Penalty.Type.TempBan, Reason.StripColors(), Target.NetworkID, Origin.NetworkID, DateTime.Now, Target.IP, DateTime.Now + length); - await Task.Run(() => + await this.ExecuteCommandAsync($"clientkick {Target.ClientNumber } \"^1Player Temporarily Banned: ^5{ Reason }\""); + Penalty newPenalty = new Penalty() { - Manager.GetClientPenalties().AddPenalty(newPenalty); - }); + Type = Penalty.PenaltyType.TempBan, + Expires = DateTime.UtcNow + length, + Offender = Target, + Offense = Reason, + Punisher = Origin, + Active = true, + When = DateTime.UtcNow, + Link = Target.AliasLink + }; + + await Manager.GetPenaltyService().Create(newPenalty); } override public async Task Ban(String Message, Player Target, Player Origin) { - if (Target == null) + Penalty newPenalty = new Penalty() { - Logger.WriteError("Ban target is null"); - Logger.WriteDebug($"Message: {Message}"); - Logger.WriteDebug($"Origin: {Origin.Name}::{Origin.NetworkID}"); - return; + Type = Penalty.PenaltyType.Ban, + Expires = DateTime.MinValue, + Offender = Target, + Offense = Message, + Punisher = Origin, + Active = true, + When = DateTime.UtcNow, + Link = Target.AliasLink + }; + await Manager.GetPenaltyService().Create(newPenalty); + Target.Level = Player.Permission.Banned; + await Manager.GetClientService().Update(Target); + + lock (Reports) // threading seems to do something weird here + { + List toRemove = new List(); + foreach (Report R in Reports) + { + if (R.Target.NetworkId == Target.NetworkId) + toRemove.Add(R); + } + + foreach (Report R in toRemove) + { + Reports.Remove(R); + Logger.WriteInfo("Removing report for banned GUID - " + R.Origin.NetworkId); + } } // banned from all servers if active @@ -708,65 +742,19 @@ namespace IW4MAdmin { if (server.GetPlayersAsList().Count > 0) { - var activeClient = server.GetPlayersAsList().SingleOrDefault(x => x.NetworkID == Target.NetworkID); + var activeClient = server.GetPlayersAsList().SingleOrDefault(x => x.NetworkId == Target.NetworkId); if (activeClient != null) { - await server.ExecuteCommandAsync($"clientkick {activeClient.ClientID} \"{Message} ^7 ({Website}) ^7\""); + await server.ExecuteCommandAsync($"clientkick {activeClient.ClientNumber} \"Player Banned: ^5{Message} ^7(appeal at {Website}) ^7\""); break; } } } - - if (Origin != null) - { - Target.SetLevel(Player.Permission.Banned); - Penalty newBan = new Penalty(Penalty.Type.Ban, Target.lastOffense, Target.NetworkID, Origin.NetworkID, DateTime.Now, Target.IP, DateTime.MaxValue); - - await Task.Run(() => - { - Manager.GetClientPenalties().AddPenalty(newBan); - Manager.GetClientDatabase().UpdatePlayer(Target); - }); - - lock (Reports) // threading seems to do something weird here - { - List toRemove = new List(); - foreach (Report R in Reports) - { - if (R.Target.NetworkID == Target.NetworkID) - toRemove.Add(R); - } - - foreach (Report R in toRemove) - { - Reports.Remove(R); - Logger.WriteInfo("Removing report for banned GUID - " + R.Origin.NetworkID); - } - } - } } override public async Task Unban(Player Target) { - // database stuff can be time consuming - await Task.Run(() => - { - var FoundPenalties = Manager.GetClientPenalties().FindPenalties(Target); - - FoundPenalties.Where(p => p.BType > Penalty.Type.Kick) - .All(p => - { - Manager.GetClientPenalties().RemovePenalty(p); - return true; - }); - - Player P = Manager.GetClientDatabase().GetPlayer(Target.NetworkID, -1); - if (P.Level < Player.Permission.Trusted) - { - P.SetLevel(Player.Permission.User); - Manager.GetClientDatabase().UpdatePlayer(P); - } - }); + await Manager.GetPenaltyService().RemoveActivePenalties(Target.AliasLink.AliasLinkId); } public override bool Reload() @@ -790,7 +778,7 @@ namespace IW4MAdmin override public void InitializeTokens() { - Manager.GetMessageTokens().Add(new SharedLibrary.Helpers.MessageToken("TOTALPLAYERS", Manager.GetClientDatabase().TotalPlayers().ToString)); + Manager.GetMessageTokens().Add(new SharedLibrary.Helpers.MessageToken("TOTALPLAYERS", Manager.GetClientService().GetTotalClientsAsync().Result.ToString)); Manager.GetMessageTokens().Add(new SharedLibrary.Helpers.MessageToken("VERSION", Program.Version.ToString)); } } diff --git a/Admin/WebService.cs b/Admin/WebService.cs index da77339cc..73d376c09 100644 --- a/Admin/WebService.cs +++ b/Admin/WebService.cs @@ -9,6 +9,12 @@ using System.Net; using System.Text; using System.Threading; +using SharedLibrary.Objects; +using System.Threading.Tasks; +using SharedLibrary.Services; +using System.Linq.Expressions; +using SharedLibrary.Database.Models; + namespace IW4MAdmin { public class WebService @@ -81,7 +87,7 @@ namespace IW4MAdmin IPage requestedPage = SharedLibrary.WebService.PageList.Find(x => x.GetPath().ToLower() == path.ToLower()); if (requestedPage != null) - return requestedPage.GetPage(queryset, headers); + return Task.Run(async () => await requestedPage.GetPage(queryset, headers)).Result; else { if (File.Exists(path.Replace("/", "\\").Substring(1))) @@ -127,7 +133,7 @@ namespace IW4MAdmin } requestedPage = new Error404(); - return requestedPage.GetPage(queryset, headers); + return Task.Run(async () => await requestedPage.GetPage(queryset, headers)).Result; } } } @@ -144,7 +150,7 @@ namespace IW4MAdmin return ""; } - public HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) + public async Task GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) { HttpResponse resp = new HttpResponse() { @@ -203,7 +209,7 @@ namespace IW4MAdmin return "/_servers"; } - public HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) + public async Task GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) { var info = new List(); foreach (Server S in ApplicationManager.GetInstance().Servers) @@ -221,8 +227,8 @@ namespace IW4MAdmin PlayerHistory = S.PlayerHistory.ToArray() }; - bool authed = ApplicationManager.GetInstance().GetPrivilegedClients() - .Where(x => x.IP == querySet["IP"]) + bool authed = (await (ApplicationManager.GetInstance().GetClientService() as ClientService).GetPrivilegedClients()) + .Where(x => x.IPAddress == querySet["IP"]) .Where(x => x.Level > Player.Permission.Trusted).Count() > 0 || querySet["IP"] == "127.0.0.1"; @@ -230,7 +236,7 @@ namespace IW4MAdmin { PlayerInfo pInfo = new PlayerInfo() { - playerID = P.DatabaseID, + playerID = P.ClientNumber, playerName = P.Name, playerLevel = authed ? P.Level.ToString() : Player.Permission.User.ToString() }; @@ -249,7 +255,7 @@ namespace IW4MAdmin return resp; } - public string GetContentType() + public string GetContentType() { return "application/json"; } @@ -273,7 +279,7 @@ namespace IW4MAdmin return "/_playerhistory"; } - public HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) + public async Task GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) { var history = new SharedLibrary.Helpers.PlayerHistory[0]; @@ -320,7 +326,7 @@ namespace IW4MAdmin return "/_info"; } - public HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) + public async Task GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) { ApplicationInfo info = new ApplicationInfo() { @@ -360,12 +366,9 @@ namespace IW4MAdmin return "/_console"; } - public HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) + public async Task GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) { - CommandInfo cmd = new CommandInfo() - { - Result = new List() - }; + var cmd = new List(); if (querySet["command"] != null) { @@ -376,32 +379,37 @@ namespace IW4MAdmin if (S != null) { - Player admin = ApplicationManager.GetInstance().GetClientDatabase().GetPlayer(querySet["IP"]); + // fixme + Func predicate = c => c.IPAddress == querySet["IP"]; + Player admin = (await ApplicationManager.GetInstance().GetClientService().Find(predicate)).First()?.AsPlayer(); if (admin == null) - admin = new Player("RestUser", "-1", -1, (int)Player.Permission.User); + admin = new Player() { Name = "RestUser", Level = Player.Permission.User }; Event remoteEvent = new Event(Event.GType.Say, querySet["command"], admin, null, S) { Remote = true }; - admin.lastEvent = remoteEvent; + admin.CurrentServer = S; + await S.ExecuteEvent(remoteEvent); - S.ExecuteEvent(remoteEvent); + var results = S.commandResult.Where(c => c.Clientd == admin.ClientId).ToList(); + cmd.AddRange(results); + + for (int i = 0; i < results.Count(); i++) + S.commandResult.Remove(results[i]); - while (S.commandResult.Count > 0) - cmd.Result.Add(S.commandResult.Dequeue()); } else - cmd.Result.Add("Invalid server selected."); + cmd.Add(new SharedLibrary.Helpers.CommandResult() { Clientd = 0, Message = "Invalid server selected" }); } else - cmd.Result.Add("Invalid server selected."); + cmd.Add(new SharedLibrary.Helpers.CommandResult() { Clientd = 0, Message = "No server selected" }); } else { - cmd.Result.Add("No command entered."); + cmd.Add(new SharedLibrary.Helpers.CommandResult() { Clientd = 0, Message = "No command entered" }); } HttpResponse resp = new HttpResponse() @@ -437,51 +445,28 @@ namespace IW4MAdmin return "/_penalties"; } - public HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) + public async Task GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) { int from = 0; if (querySet["from"] != null) from = Int32.Parse(querySet["from"]); - List selectedPenalties; - - try - { - selectedPenalties = ((ApplicationManager.GetInstance().GetClientPenalties()) as PenaltyList).AsChronoList(Convert.ToInt32(querySet["from"]), 15).OrderByDescending(b => b.When).ToList(); - } - - catch (Exception) - { - selectedPenalties = new List(); - } List info = new List(); - foreach (var p in selectedPenalties) + foreach (var penalty in await ApplicationManager.GetInstance().GetPenaltyService().GetRecentPenalties(15, from)) { - Player admin = ApplicationManager.GetInstance().GetClientDatabase().GetPlayer(p.PenaltyOriginID, 0) ?? - new Player("IW4MAdmin", "-1", -1, (int)Player.Permission.Banned); - - Player penalized = ApplicationManager.GetInstance().GetClientDatabase().GetPlayer(p.OffenderID, 0); - if (admin == null && penalized == null) - continue; PenaltyInfo pInfo = new PenaltyInfo() { - adminName = admin.Name, - adminLevel = admin.Level.ToString(), - penaltyReason = p.Reason, - penaltyTime = Utilities.GetTimePassed(p.When), - penaltyType = p.BType.ToString(), - playerName = penalized.Name, - playerID = penalized.DatabaseID, - Expires = p.Expires > DateTime.Now ? (p.Expires - DateTime.Now).TimeSpanText() : "" + adminName = penalty.Punisher.Name, + adminLevel = penalty.Punisher.Level.ToString(), + penaltyReason = penalty.Offense, + penaltyTime = Utilities.GetTimePassed(penalty.When), + penaltyType = penalty.Type.ToString(), + playerName = penalty.Offender.Name, + playerID = penalty.Offender.ClientId, + Expires = penalty.Expires > DateTime.Now ? (penalty.Expires - DateTime.Now).TimeSpanText() : "" }; - - if (admin.NetworkID == penalized.NetworkID) - { - pInfo.adminName = "IW4MAdmin"; - pInfo.adminLevel = Player.Permission.Console.ToString(); - } info.Add(pInfo); } @@ -626,9 +611,11 @@ namespace IW4MAdmin return "/GetAdmins"; } - public HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) + public async Task GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) { - var Admins = ApplicationManager.GetInstance().GetClientDatabase().GetAdmins().OrderByDescending(a => a.Level); + var Admins = (await (ApplicationManager.GetInstance().GetClientService() as ClientService) + .GetPrivilegedClients()) + .OrderByDescending(a => a.Level).ToList(); HttpResponse resp = new HttpResponse() { contentType = GetContentType(), @@ -661,17 +648,17 @@ namespace IW4MAdmin return "/pubbans"; } - public HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) + public async Task GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) { HttpResponse resp = new HttpResponse() { - contentType = GetContentType(), - content = Newtonsoft.Json.JsonConvert - .SerializeObject(((ApplicationManager.GetInstance().GetClientPenalties()) as PenaltyList) - .AsChronoList(Convert.ToInt32(querySet["from"]), 50, Penalty.Type.Ban), Newtonsoft.Json.Formatting.Indented, new Newtonsoft.Json.JsonConverter[] { - new Newtonsoft.Json.Converters.StringEnumConverter() - }), - additionalHeaders = new Dictionary() + /* contentType = GetContentType(), + content = Newtonsoft.Json.JsonConvert + .SerializeObject(((ApplicationManager.GetInstance().GetClientPenalties()) as PenaltyList) + .AsChronoList(Convert.ToInt32(querySet["from"]), 50, Penalty.Type.Ban), Newtonsoft.Json.Formatting.Indented, new Newtonsoft.Json.JsonConverter[] { + new Newtonsoft.Json.Converters.StringEnumConverter() + }), + additionalHeaders = new Dictionary()*/ }; return resp; } @@ -699,9 +686,9 @@ namespace IW4MAdmin return "/pages"; } - public HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) + public async Task GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) { - + var pages = SharedLibrary.WebService.PageList.Select(p => new { pagePath = p.GetPath(), @@ -746,33 +733,34 @@ namespace IW4MAdmin return "GetPlayer"; } - public HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) + public async Task GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) { List pInfo = new List(); - List matchedPlayers = new List(); + IList matchedPlayers = new List(); HttpResponse resp = new HttpResponse() { contentType = GetContentType(), additionalHeaders = new Dictionary() }; - bool authed = ApplicationManager.GetInstance().GetClientDatabase().GetAdmins().FindAll(x => x.IP == querySet["IP"] && x.Level > Player.Permission.Trusted).Count > 0 + Func predicate = c => c.IPAddress == querySet["IP"] && c.Level > Player.Permission.Trusted; + bool authed = (await ApplicationManager.GetInstance().GetClientService().Find(predicate)).Count > 0 || querySet["IP"] == "127.0.0.1"; bool recent = false; bool individual = querySet["id"] != null; if (individual) { - matchedPlayers.Add(ApplicationManager.GetInstance().GetClientDatabase().GetPlayer(Convert.ToInt32(querySet["id"]))); + matchedPlayers.Add(await ApplicationManager.GetInstance().GetClientService().Get(Convert.ToInt32(querySet["id"]))); } else if (querySet["npID"] != null) { - matchedPlayers.Add(ApplicationManager.GetInstance().GetClientDatabase().GetPlayers(new List { querySet["npID"] }).First()); + matchedPlayers.Add(await ApplicationManager.GetInstance().GetClientService().GetUnique(querySet["npID"])); } else if (querySet["name"] != null) { - matchedPlayers = ApplicationManager.GetInstance().GetClientDatabase().FindPlayers(querySet["name"]); + matchedPlayers = await ApplicationManager.GetInstance().GetClientService().Find(c => c.Name.Contains(querySet["name"])); } else if (querySet["recent"] != null) @@ -783,7 +771,7 @@ namespace IW4MAdmin if (offset < 0) throw new FormatException("Invalid offset"); - matchedPlayers = ApplicationManager.GetInstance().GetClientDatabase().GetRecentPlayers(15, offset); + matchedPlayers = await ApplicationManager.GetInstance().GetClientService().GetRecentClients(offset, 15); recent = true; } @@ -795,26 +783,23 @@ namespace IW4MAdmin PlayerInfo eachPlayer = new PlayerInfo() { - playerID = pp.DatabaseID, - playerIP = pp.IP, + playerIP = pp.IPAddress, + playerID = pp.ClientId, playerLevel = pp.Level.ToString(), playerName = pp.Name, - playernpID = pp.NetworkID, + playernpID = pp.NetworkId, forumID = -1, authed = authed, showV2Features = false, playerAliases = new List(), playerIPs = new List() - }; if (!recent && individual && authed) { - foreach (var a in ApplicationManager.GetInstance().GetAliases(pp)) - { - eachPlayer.playerAliases.AddRange(a.Names); - eachPlayer.playerIPs.AddRange(a.IPS); - } + + eachPlayer.playerAliases = pp.AliasLink.Children.OrderBy(a => a.Name).Select(a => a.Name).ToList(); + eachPlayer.playerIPs = pp.AliasLink.Children.Select(a => a.IP).ToList(); } eachPlayer.playerAliases = eachPlayer.playerAliases.Distinct().ToList(); diff --git a/Admin/lib/SharedLibrary.dll b/Admin/lib/SharedLibrary.dll index 116e0d226..c6107f87f 100644 Binary files a/Admin/lib/SharedLibrary.dll and b/Admin/lib/SharedLibrary.dll differ diff --git a/Admin/lib/System.Data.SQLite.dll b/Admin/lib/System.Data.SQLite.dll deleted file mode 100644 index 54fba4e66..000000000 Binary files a/Admin/lib/System.Data.SQLite.dll and /dev/null differ diff --git a/Admin/webfront/admins.html b/Admin/webfront/admins.html index 7d964f154..4b69216c8 100644 --- a/Admin/webfront/admins.html +++ b/Admin/webfront/admins.html @@ -1,6 +1,6 @@ diff --git a/Database/Database.csproj b/Database/Database.csproj new file mode 100644 index 000000000..17e44be3b --- /dev/null +++ b/Database/Database.csproj @@ -0,0 +1,90 @@ + + + + + Debug + AnyCPU + {D076ABC9-DDD6-4E30-9584-E45273950902} + Library + Properties + Database + Database + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + bin\Release-Nightly\ + TRACE + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + bin\Release-Stable\ + + + + ..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll + + + ..\packages\EntityFramework.SqlServerCompact.6.2.0\lib\net45\EntityFramework.SqlServerCompact.dll + + + + + + ..\packages\Microsoft.SqlServer.Compact.4.0.8876.1\lib\net40\System.Data.SqlServerCe.dll + True + + + + + + + + + + + + + + + + + + + {d51eeceb-438a-47da-870f-7d7b41bc24d6} + SharedLibrary + + + + + + + + + if not exist "$(TargetDir)x86" md "$(TargetDir)x86" + xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\NativeBinaries\x86\*.*" "$(TargetDir)x86" + if not exist "$(TargetDir)amd64" md "$(TargetDir)amd64" + xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\NativeBinaries\amd64\*.*" "$(TargetDir)amd64" + + \ No newline at end of file diff --git a/Database/IW4MAdminDatabase.cs b/Database/IW4MAdminDatabase.cs new file mode 100644 index 000000000..9147a7576 --- /dev/null +++ b/Database/IW4MAdminDatabase.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Database.Models; + +namespace Database +{ + public class IW4MAdminDatabase : SharedLibrary.Interfaces.IDatabase + { + private IW4MAdminDatabaseContext _context; + + public IW4MAdminDatabase() + { + _context = new IW4MAdminDatabaseContext(); + } + + public SharedLibrary.Interfaces.IDatabaseContext GetContext() => _context; + + public async Task AddClient(Client newClient) + { + var client = _context.Clients.Add(newClient); + await _context.SaveChangesAsync(); + return client; + } + + public Client GetClient(int clientID) => _context.Clients.SingleOrDefault(c => c.ClientId == clientID); + public Client GetClient(string networkID) => _context.Clients.SingleOrDefault(c => c.NetworkId == networkID); + public IList GetOwners() => _context.Clients.Where(c => c.Level == SharedLibrary.Player.Permission.Owner).ToList(); + public IList GetPlayers(IList networkIDs) => _context.Clients.Where(c => networkIDs.Contains(c.NetworkId)).Select(c => c.ToPlayer()).ToList(); + public IList GetPenalties (int clientID) => _context.Penalties.Where(p => p.OffenderId == clientID).ToList(); + public IList GetAdmins() => _context.Clients.Where(c => c.Level > SharedLibrary.Player.Permission.Flagged).Select(c => c.ToPlayer()).ToList(); + + + } +} diff --git a/Database/IW4MAdminDatabaseContext.cs b/Database/IW4MAdminDatabaseContext.cs new file mode 100644 index 000000000..e30898b73 --- /dev/null +++ b/Database/IW4MAdminDatabaseContext.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Data.Entity; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Database.Models; +using System.Data.SqlServerCe; + +namespace Database +{ + public class IW4MAdminDatabaseContext : DbContext, SharedLibrary.Interfaces.IDatabaseContext + { + public DbSet Clients { get; set; } + public DbSet Aliases { get; set; } + public DbSet Penalties { get; set; } + + public IW4MAdminDatabaseContext() : base("DefaultConnection") { } + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + var instance = System.Data.Entity.SqlServerCompact.SqlCeProviderServices.Instance; + // todo custom load DBSets from plugins + // https://aleemkhan.wordpress.com/2013/02/28/dynamically-adding-dbset-properties-in-dbcontext-for-entity-framework-code-first/ + base.OnModelCreating(modelBuilder); + } + } +} diff --git a/Database/Models/Alias.cs b/Database/Models/Alias.cs new file mode 100644 index 000000000..e670deb8d --- /dev/null +++ b/Database/Models/Alias.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Database.Models +{ + public class Alias + { + [Key] + public int AliasId { get; set; } + public int ClientId { get; set; } + public string Name { get; set; } + public string IP { get; set; } + } +} diff --git a/Database/Models/Client.cs b/Database/Models/Client.cs new file mode 100644 index 000000000..2e6e10e84 --- /dev/null +++ b/Database/Models/Client.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Database.Models +{ + public class Client + { + [Key] + public int ClientId { get; set; } + + [Required] + public string Name { get; set; } + [Required] + public string NetworkId { get; set; } + [Required] + public SharedLibrary.Player.Permission Level { get; set; } + public int Connections { get; set; } + [Required] + public string IPAddress { get; set; } + [Required] + public DateTime LastConnection { get; set; } + public bool Masked { get; set; } + + public SharedLibrary.Player ToPlayer() + { + return new SharedLibrary.Player() + { + Name = Name, + Connections = Connections, + DatabaseID = ClientId, + NetworkID = NetworkId, + Level = Level, + IP = IPAddress, + LastConnection = LastConnection, + Masked = Masked + }; + } + } +} diff --git a/Database/Models/Penalty.cs b/Database/Models/Penalty.cs new file mode 100644 index 000000000..4b841a6e3 --- /dev/null +++ b/Database/Models/Penalty.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Database.Models +{ + public class Penalty + { + [Key] + public int PenaltyId { get; set; } + public int OffenderId { get; set; } + public Client Offender { get; set; } + public int PunisherId { get; set; } + public Client Punisher { get; set; } + public DateTime When { get; set; } + public DateTime Expires { get; set; } + public SharedLibrary.Penalty.Type Type { get; set; } + } +} diff --git a/Database/Properties/AssemblyInfo.cs b/Database/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..18e5f7e50 --- /dev/null +++ b/Database/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Database")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Database")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("d076abc9-ddd6-4e30-9584-e45273950902")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Database/packages.config b/Database/packages.config new file mode 100644 index 000000000..82f88f367 --- /dev/null +++ b/Database/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/IW4MAdmin.sln b/IW4MAdmin.sln index 5fce63708..03226e498 100644 --- a/IW4MAdmin.sln +++ b/IW4MAdmin.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27004.2006 +VisualStudioVersion = 15.0.27004.2009 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Application", "Admin\Application.csproj", "{DD5DCDA2-51DB-4B1A-922F-5705546E6115}" ProjectSection(ProjectDependencies) = postProject @@ -49,6 +49,10 @@ Global Debug|Mixed Platforms = Debug|Mixed Platforms Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x64 = Release|x64 + Release|x86 = Release|x86 Release-Nightly|Any CPU = Release-Nightly|Any CPU Release-Nightly|Mixed Platforms = Release-Nightly|Mixed Platforms Release-Nightly|x64 = Release-Nightly|x64 @@ -67,6 +71,14 @@ Global {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Debug|x64.Build.0 = Debug|Any CPU {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Debug|x86.ActiveCfg = Debug|x86 {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Debug|x86.Build.0 = Debug|x86 + {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|Any CPU.ActiveCfg = Release-Stable|Any CPU + {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|Any CPU.Build.0 = Release-Stable|Any CPU + {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|Mixed Platforms.ActiveCfg = Release-Stable|x86 + {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|Mixed Platforms.Build.0 = Release-Stable|x86 + {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|x64.ActiveCfg = Release-Stable|Any CPU + {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|x64.Build.0 = Release-Stable|Any CPU + {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|x86.ActiveCfg = Release-Stable|x86 + {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release|x86.Build.0 = Release-Stable|x86 {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release-Nightly|Any CPU.ActiveCfg = Release-Nightly|Any CPU {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release-Nightly|Any CPU.Build.0 = Release-Nightly|Any CPU {DD5DCDA2-51DB-4B1A-922F-5705546E6115}.Release-Nightly|Mixed Platforms.ActiveCfg = Release-Nightly|x86 @@ -91,6 +103,14 @@ Global {4785AB75-66F3-4391-985D-63A5A049A0FA}.Debug|x64.Build.0 = Debug|Any CPU {4785AB75-66F3-4391-985D-63A5A049A0FA}.Debug|x86.ActiveCfg = Debug|x86 {4785AB75-66F3-4391-985D-63A5A049A0FA}.Debug|x86.Build.0 = Debug|x86 + {4785AB75-66F3-4391-985D-63A5A049A0FA}.Release|Any CPU.ActiveCfg = Release-Stable|Any CPU + {4785AB75-66F3-4391-985D-63A5A049A0FA}.Release|Any CPU.Build.0 = Release-Stable|Any CPU + {4785AB75-66F3-4391-985D-63A5A049A0FA}.Release|Mixed Platforms.ActiveCfg = Release-Stable|x86 + {4785AB75-66F3-4391-985D-63A5A049A0FA}.Release|Mixed Platforms.Build.0 = Release-Stable|x86 + {4785AB75-66F3-4391-985D-63A5A049A0FA}.Release|x64.ActiveCfg = Release-Stable|Any CPU + {4785AB75-66F3-4391-985D-63A5A049A0FA}.Release|x64.Build.0 = Release-Stable|Any CPU + {4785AB75-66F3-4391-985D-63A5A049A0FA}.Release|x86.ActiveCfg = Release-Stable|x86 + {4785AB75-66F3-4391-985D-63A5A049A0FA}.Release|x86.Build.0 = Release-Stable|x86 {4785AB75-66F3-4391-985D-63A5A049A0FA}.Release-Nightly|Any CPU.ActiveCfg = Release-Nightly|Any CPU {4785AB75-66F3-4391-985D-63A5A049A0FA}.Release-Nightly|Any CPU.Build.0 = Release-Nightly|Any CPU {4785AB75-66F3-4391-985D-63A5A049A0FA}.Release-Nightly|Mixed Platforms.ActiveCfg = Release-Nightly|x86 @@ -115,6 +135,14 @@ Global {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Debug|x64.Build.0 = Debug|Any CPU {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Debug|x86.ActiveCfg = Debug|x86 {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Debug|x86.Build.0 = Debug|x86 + {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Release|Any CPU.ActiveCfg = Release-Stable|Any CPU + {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Release|Any CPU.Build.0 = Release-Stable|Any CPU + {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Release|Mixed Platforms.ActiveCfg = Release-Stable|x86 + {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Release|Mixed Platforms.Build.0 = Release-Stable|x86 + {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Release|x64.ActiveCfg = Release-Stable|Any CPU + {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Release|x64.Build.0 = Release-Stable|Any CPU + {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Release|x86.ActiveCfg = Release-Stable|x86 + {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Release|x86.Build.0 = Release-Stable|x86 {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Release-Nightly|Any CPU.ActiveCfg = Release-Nightly|Any CPU {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Release-Nightly|Any CPU.Build.0 = Release-Nightly|Any CPU {D51EECEB-438A-47DA-870F-7D7B41BC24D6}.Release-Nightly|Mixed Platforms.ActiveCfg = Release-Nightly|x86 @@ -139,6 +167,14 @@ Global {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Debug|x64.Build.0 = Debug|Any CPU {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Debug|x86.ActiveCfg = Debug|x86 {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Debug|x86.Build.0 = Debug|x86 + {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Release|Any CPU.ActiveCfg = Release-Stable|Any CPU + {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Release|Any CPU.Build.0 = Release-Stable|Any CPU + {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Release|Mixed Platforms.ActiveCfg = Release-Stable|x86 + {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Release|Mixed Platforms.Build.0 = Release-Stable|x86 + {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Release|x64.ActiveCfg = Release-Stable|Any CPU + {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Release|x64.Build.0 = Release-Stable|Any CPU + {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Release|x86.ActiveCfg = Release-Stable|x86 + {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Release|x86.Build.0 = Release-Stable|x86 {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Release-Nightly|Any CPU.ActiveCfg = Release-Nightly|Any CPU {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Release-Nightly|Any CPU.Build.0 = Release-Nightly|Any CPU {AF097E6B-48D5-4452-9CCF-0A81A21F341D}.Release-Nightly|Mixed Platforms.ActiveCfg = Release-Nightly|x86 @@ -163,6 +199,14 @@ Global {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Debug|x64.Build.0 = Debug|Any CPU {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Debug|x86.ActiveCfg = Debug|x86 {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Debug|x86.Build.0 = Debug|x86 + {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|Any CPU.ActiveCfg = Release-Stable|Any CPU + {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|Any CPU.Build.0 = Release-Stable|Any CPU + {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|Mixed Platforms.ActiveCfg = Release-Stable|x86 + {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|Mixed Platforms.Build.0 = Release-Stable|x86 + {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|x64.ActiveCfg = Release-Stable|Any CPU + {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|x64.Build.0 = Release-Stable|Any CPU + {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|x86.ActiveCfg = Release-Stable|x86 + {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release|x86.Build.0 = Release-Stable|x86 {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Nightly|Any CPU.ActiveCfg = Release-Nightly|Any CPU {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Nightly|Mixed Platforms.ActiveCfg = Release-Nightly|x86 {428D8EB9-ECA3-4A66-AA59-3A944378C33F}.Release-Nightly|Mixed Platforms.Build.0 = Release-Nightly|x86 @@ -183,6 +227,14 @@ Global {E46C85BD-A99C-484E-BCCE-0F1831C5925E}.Debug|x64.ActiveCfg = Release-Stable|Any CPU {E46C85BD-A99C-484E-BCCE-0F1831C5925E}.Debug|x86.ActiveCfg = Debug|x86 {E46C85BD-A99C-484E-BCCE-0F1831C5925E}.Debug|x86.Build.0 = Debug|x86 + {E46C85BD-A99C-484E-BCCE-0F1831C5925E}.Release|Any CPU.ActiveCfg = Release-Nightly|Any CPU + {E46C85BD-A99C-484E-BCCE-0F1831C5925E}.Release|Any CPU.Build.0 = Release-Nightly|Any CPU + {E46C85BD-A99C-484E-BCCE-0F1831C5925E}.Release|Mixed Platforms.ActiveCfg = Release-Stable|x86 + {E46C85BD-A99C-484E-BCCE-0F1831C5925E}.Release|Mixed Platforms.Build.0 = Release-Stable|x86 + {E46C85BD-A99C-484E-BCCE-0F1831C5925E}.Release|x64.ActiveCfg = Release-Nightly|Any CPU + {E46C85BD-A99C-484E-BCCE-0F1831C5925E}.Release|x64.Build.0 = Release-Nightly|Any CPU + {E46C85BD-A99C-484E-BCCE-0F1831C5925E}.Release|x86.ActiveCfg = Release-Stable|x86 + {E46C85BD-A99C-484E-BCCE-0F1831C5925E}.Release|x86.Build.0 = Release-Stable|x86 {E46C85BD-A99C-484E-BCCE-0F1831C5925E}.Release-Nightly|Any CPU.ActiveCfg = Release-Nightly|Any CPU {E46C85BD-A99C-484E-BCCE-0F1831C5925E}.Release-Nightly|Mixed Platforms.ActiveCfg = Release-Stable|Any CPU {E46C85BD-A99C-484E-BCCE-0F1831C5925E}.Release-Nightly|x64.ActiveCfg = Release-Stable|Any CPU @@ -201,6 +253,14 @@ Global {C9E821BF-23AD-4CB5-B7F9-B3B99B606650}.Debug|x64.Build.0 = Debug|Any CPU {C9E821BF-23AD-4CB5-B7F9-B3B99B606650}.Debug|x86.ActiveCfg = Debug|x86 {C9E821BF-23AD-4CB5-B7F9-B3B99B606650}.Debug|x86.Build.0 = Debug|x86 + {C9E821BF-23AD-4CB5-B7F9-B3B99B606650}.Release|Any CPU.ActiveCfg = Release-Stable|Any CPU + {C9E821BF-23AD-4CB5-B7F9-B3B99B606650}.Release|Any CPU.Build.0 = Release-Stable|Any CPU + {C9E821BF-23AD-4CB5-B7F9-B3B99B606650}.Release|Mixed Platforms.ActiveCfg = Release-Stable|x86 + {C9E821BF-23AD-4CB5-B7F9-B3B99B606650}.Release|Mixed Platforms.Build.0 = Release-Stable|x86 + {C9E821BF-23AD-4CB5-B7F9-B3B99B606650}.Release|x64.ActiveCfg = Release-Stable|Any CPU + {C9E821BF-23AD-4CB5-B7F9-B3B99B606650}.Release|x64.Build.0 = Release-Stable|Any CPU + {C9E821BF-23AD-4CB5-B7F9-B3B99B606650}.Release|x86.ActiveCfg = Release-Stable|x86 + {C9E821BF-23AD-4CB5-B7F9-B3B99B606650}.Release|x86.Build.0 = Release-Stable|x86 {C9E821BF-23AD-4CB5-B7F9-B3B99B606650}.Release-Nightly|Any CPU.ActiveCfg = Release-Nightly|Any CPU {C9E821BF-23AD-4CB5-B7F9-B3B99B606650}.Release-Nightly|Any CPU.Build.0 = Release-Nightly|Any CPU {C9E821BF-23AD-4CB5-B7F9-B3B99B606650}.Release-Nightly|Mixed Platforms.ActiveCfg = Release-Nightly|x86 @@ -225,6 +285,14 @@ Global {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Debug|x64.Build.0 = Debug|Any CPU {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Debug|x86.ActiveCfg = Debug|x86 {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Debug|x86.Build.0 = Debug|x86 + {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|Any CPU.ActiveCfg = Release-Stable|Any CPU + {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|Any CPU.Build.0 = Release-Stable|Any CPU + {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|Mixed Platforms.ActiveCfg = Release-Stable|x86 + {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|Mixed Platforms.Build.0 = Release-Stable|x86 + {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|x64.ActiveCfg = Release-Stable|Any CPU + {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|x64.Build.0 = Release-Stable|Any CPU + {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|x86.ActiveCfg = Release-Stable|x86 + {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release|x86.Build.0 = Release-Stable|x86 {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Nightly|Any CPU.ActiveCfg = Release-Nightly|Any CPU {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Nightly|Mixed Platforms.ActiveCfg = Release-Nightly|x86 {1479DE87-ACB5-4046-81C8-A0BA5041227D}.Release-Nightly|Mixed Platforms.Build.0 = Release-Nightly|x86 @@ -247,6 +315,14 @@ Global {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Debug|x64.Build.0 = Debug|Any CPU {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Debug|x86.ActiveCfg = Debug|x86 {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Debug|x86.Build.0 = Debug|x86 + {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Release|Any CPU.ActiveCfg = Release-Stable|Any CPU + {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Release|Any CPU.Build.0 = Release-Stable|Any CPU + {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Release|Mixed Platforms.ActiveCfg = Release-Stable|x86 + {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Release|Mixed Platforms.Build.0 = Release-Stable|x86 + {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Release|x64.ActiveCfg = Release-Stable|Any CPU + {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Release|x64.Build.0 = Release-Stable|Any CPU + {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Release|x86.ActiveCfg = Release-Stable|x86 + {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Release|x86.Build.0 = Release-Stable|x86 {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Release-Nightly|Any CPU.ActiveCfg = Release-Nightly|Any CPU {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Release-Nightly|Mixed Platforms.ActiveCfg = Release-Nightly|x86 {B8C2A759-8663-4F6F-9BA4-19595F5E12C1}.Release-Nightly|Mixed Platforms.Build.0 = Release-Nightly|x86 diff --git a/Plugins/EventAPI/Plugin.cs b/Plugins/EventAPI/Plugin.cs index dd64eaadd..8cf79cd5b 100644 --- a/Plugins/EventAPI/Plugin.cs +++ b/Plugins/EventAPI/Plugin.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; + using SharedLibrary; using SharedLibrary.Interfaces; -using System.Threading.Tasks; +using SharedLibrary.Objects; namespace EventAPI { @@ -25,7 +27,7 @@ namespace EventAPI return "/api/events"; } - public HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) + public async Task GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) { bool shouldQuery = querySet.Get("status") != null; EventResponse requestedEvent = new EventResponse(); diff --git a/Plugins/FastRestart/Plugin.cs b/Plugins/FastRestart/Plugin.cs index 11ed699c0..14599452d 100644 --- a/Plugins/FastRestart/Plugin.cs +++ b/Plugins/FastRestart/Plugin.cs @@ -6,6 +6,7 @@ using SharedLibrary; using SharedLibrary.Interfaces; using SharedLibrary.Network; using SharedLibrary.Helpers; +using SharedLibrary.Objects; namespace Plugin { diff --git a/Plugins/MessageBoard/Rank.cs b/Plugins/MessageBoard/Rank.cs index eb725d779..c438f68bb 100644 --- a/Plugins/MessageBoard/Rank.cs +++ b/Plugins/MessageBoard/Rank.cs @@ -3,12 +3,14 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using SharedLibrary.Objects; + namespace MessageBoard { public class Rank : Identifiable { public string name; - public SharedLibrary.Player.Permission equivalentRank; + public Player.Permission equivalentRank; public int id; /// @@ -17,14 +19,14 @@ namespace MessageBoard /// /// /// - public Rank(string name, SharedLibrary.Player.Permission equivalentRank) + public Rank(string name, Player.Permission equivalentRank) { this.name = name; this.equivalentRank = equivalentRank; id = 0; } - public Rank(int id, string name, SharedLibrary.Player.Permission equivalentRank) + public Rank(int id, string name, Player.Permission equivalentRank) { this.name = name; this.equivalentRank = equivalentRank; diff --git a/Plugins/MessageBoard/Storage.cs b/Plugins/MessageBoard/Storage.cs index 4dfe3ee53..7d89c6fc8 100644 --- a/Plugins/MessageBoard/Storage.cs +++ b/Plugins/MessageBoard/Storage.cs @@ -5,7 +5,7 @@ using System.Data; namespace MessageBoard.Storage { - class Database : SharedLibrary.Database + class Database : SharedLibrary._Database { public Database(String FN, SharedLibrary.Interfaces.ILogger logger) : base(FN, logger) { } diff --git a/Plugins/SimpleStats/Chat/ChatDatabase.cs b/Plugins/SimpleStats/Chat/ChatDatabase.cs index 8acc07dbf..e3089b5b0 100644 --- a/Plugins/SimpleStats/Chat/ChatDatabase.cs +++ b/Plugins/SimpleStats/Chat/ChatDatabase.cs @@ -10,7 +10,7 @@ using System.Data; namespace StatsPlugin { - public class ChatDatabase : Database + public class ChatDatabase : _Database { private string[] CommonWords = new string[] { "for", "with", diff --git a/Plugins/SimpleStats/Chat/ChatHistoryPage.cs b/Plugins/SimpleStats/Chat/ChatHistoryPage.cs index ce0c16bf7..6dd91c1fb 100644 --- a/Plugins/SimpleStats/Chat/ChatHistoryPage.cs +++ b/Plugins/SimpleStats/Chat/ChatHistoryPage.cs @@ -67,7 +67,7 @@ namespace StatsPlugin.Chat public HttpResponse GetPage(NameValueCollection querySet, IDictionary headers) { int clientID = Convert.ToInt32(querySet["clientid"]); - var client = Stats.ManagerInstance.GetClientDatabase().GetPlayer(clientID); + var name = Stats.ManagerInstance.GetDatabase().GetClient(clientID).Name; HttpResponse resp = new HttpResponse() { @@ -78,7 +78,7 @@ namespace StatsPlugin.Chat ServerID = c.ServerID, Message = c.Message, TimeSent = c.TimeSent, - ClientName = client.Name, + ClientName = name, }), additionalHeaders = new Dictionary() }; diff --git a/Plugins/SimpleStats/Plugin.cs b/Plugins/SimpleStats/Plugin.cs index 6dc73be56..564f93533 100644 --- a/Plugins/SimpleStats/Plugin.cs +++ b/Plugins/SimpleStats/Plugin.cs @@ -7,6 +7,8 @@ using System.IO; using System.Text; using System.Threading.Tasks; +using SharedLibrary.Objects; + namespace StatsPlugin { public class CViewStats : Command @@ -74,7 +76,7 @@ namespace StatsPlugin await E.Origin.Tell("^5--Top Players--"); foreach (KeyValuePair pStat in pStats) { - Player P = E.Owner.Manager.GetClientDatabase().GetPlayer(pStat.Key, -1); + Player P = E.Owner.Manager.GetDatabase().GetClient(pStat.Key) as Player; if (P == null) continue; await E.Origin.Tell(String.Format("^3{0}^7 - ^5{1} ^7KDR | ^5{2} ^7SKILL", P.Name, pStat.Value.KDR, pStat.Value.Skill)); @@ -132,8 +134,8 @@ namespace StatsPlugin return; } - E.Owner.Manager.GetClientDatabase().PruneAdmins(inactiveDays); - await E.Origin.Tell("Pruned inactive privileged users"); + var inactiveAdmins = await E.Owner.Manager.GetDatabase().PruneInactivePrivilegedClients(inactiveDays); + await E.Origin.Tell($"Pruned inactive {inactiveAdmins.Count} privileged users"); } } @@ -289,7 +291,7 @@ namespace StatsPlugin if (E.Type == Event.GType.Connect) { - ResetCounters(E.Origin.ClientID, S.GetPort()); + ResetCounters(E.Origin.ClientNumber, S.GetPort()); var config = new ConfigurationManager(E.Owner); @@ -300,8 +302,8 @@ namespace StatsPlugin //todo: move this out of here!! if (checkForTrusted.TotalPlayTime >= 4320 && E.Origin.Level < Player.Permission.Trusted && E.Origin.Level != Player.Permission.Flagged) { - E.Origin.SetLevel(Player.Permission.Trusted); - E.Owner.Manager.GetClientDatabase().UpdatePlayer(E.Origin); + E.Origin.Level = Player.Permission.Trusted; + await E.Owner.Manager.GetDatabase().UpdateClient(E.Origin); await E.Origin.Tell("Congratulations, you are now a ^5trusted ^7player! Type ^5!help ^7to view new commands."); await E.Origin.Tell("You earned this by playing for ^53 ^7full days!"); } @@ -316,10 +318,10 @@ namespace StatsPlugin continue; CalculateAndSaveSkill(P, statLists.Find(x => x.Port == S.GetPort())); - ResetCounters(P.ClientID, S.GetPort()); + ResetCounters(P.ClientNumber, S.GetPort()); E.Owner.Logger.WriteInfo($"Updated skill for {P}"); - //E.Owner.Log.Write(String.Format("\r\nJoin: {0}\r\nInactive Minutes: {1}\r\nnewPlayTime: {2}\r\nnewSPM: {3}\r\nkdrWeight: {4}\r\nMultiplier: {5}\r\nscoreWeight: {6}\r\nnewSkillFactor: {7}\r\nprojectedNewSkill: {8}\r\nKills: {9}\r\nDeaths: {10}", connectionTime[P.clientID].ToShortTimeString(), inactiveMinutes[P.clientID], newPlayTime, newSPM, kdrWeight, Multiplier, scoreWeight, newSkillFactor, disconnectStats.Skill, disconnectStats.Kills, disconnectStats.Deaths)); + //E.Owner.Log.Write(String.Format("\r\nJoin: {0}\r\nInactive Minutes: {1}\r\nnewPlayTime: {2}\r\nnewSPM: {3}\r\nkdrWeight: {4}\r\nMultiplier: {5}\r\nscoreWeight: {6}\r\nnewSkillFactor: {7}\r\nprojectedNewSkill: {8}\r\nKills: {9}\r\nDeaths: {10}", connectionTime[P.ClientNumber].ToShortTimeString(), inactiveMinutes[P.ClientNumber], newPlayTime, newSPM, kdrWeight, Multiplier, scoreWeight, newSkillFactor, disconnectStats.Skill, disconnectStats.Kills, disconnectStats.Deaths)); } } @@ -332,7 +334,7 @@ namespace StatsPlugin if (E.Type == Event.GType.Disconnect) { CalculateAndSaveSkill(E.Origin, statLists.Find(x => x.Port == S.GetPort())); - ResetCounters(E.Origin.ClientID, S.GetPort()); + ResetCounters(E.Origin.ClientNumber, S.GetPort()); E.Owner.Logger.WriteInfo($"Updated skill for disconnecting client {E.Origin}"); } @@ -345,7 +347,7 @@ namespace StatsPlugin if (killInfo.Length >= 9 && killInfo[0].Contains("ScriptKill")) { - var killEvent = new KillInfo(E.Origin.DatabaseID, E.Target.DatabaseID, S.CurrentMap.Name, killInfo[7], killInfo[8], killInfo[5], killInfo[6], killInfo[3], killInfo[4]) + var killEvent = new KillInfo(E.Origin.ClientNumber, E.Target.ClientNumber, S.CurrentMap.Name, killInfo[7], killInfo[8], killInfo[5], killInfo[6], killInfo[3], killInfo[4]) { KillerPlayer = E.Origin.Name, VictimPlayer = E.Target.Name, @@ -366,11 +368,11 @@ namespace StatsPlugin if (killerStats == null) killerStats = new PlayerStats(0, 0, 0, 0, 0, 0); - curServer.lastKill[E.Origin.ClientID] = DateTime.Now; - curServer.Kills[E.Origin.ClientID]++; + curServer.lastKill[E.Origin.ClientNumber] = DateTime.Now; + curServer.Kills[E.Origin.ClientNumber]++; - if ((DateTime.Now - curServer.lastKill[E.Origin.ClientID]).TotalSeconds > 120) - curServer.inactiveMinutes[E.Origin.ClientID] += 2; + if ((DateTime.Now - curServer.lastKill[E.Origin.ClientNumber]).TotalSeconds > 120) + curServer.inactiveMinutes[E.Origin.ClientNumber] += 2; killerStats.Kills++; @@ -378,10 +380,10 @@ namespace StatsPlugin curServer.playerStats.UpdateStats(Killer, killerStats); - curServer.killStreaks[Killer.ClientID] += 1; - curServer.deathStreaks[Killer.ClientID] = 0; + curServer.killStreaks[Killer.ClientNumber] += 1; + curServer.deathStreaks[Killer.ClientNumber] = 0; - await Killer.Tell(MessageOnStreak(curServer.killStreaks[Killer.ClientID], curServer.deathStreaks[Killer.ClientID])); + await Killer.Tell(MessageOnStreak(curServer.killStreaks[Killer.ClientNumber], curServer.deathStreaks[Killer.ClientNumber])); } if (E.Type == Event.GType.Death) @@ -401,15 +403,15 @@ namespace StatsPlugin curServer.playerStats.UpdateStats(Victim, victimStats); - curServer.deathStreaks[Victim.ClientID] += 1; - curServer.killStreaks[Victim.ClientID] = 0; + curServer.deathStreaks[Victim.ClientNumber] += 1; + curServer.killStreaks[Victim.ClientNumber] = 0; - await Victim.Tell(MessageOnStreak(curServer.killStreaks[Victim.ClientID], curServer.deathStreaks[Victim.ClientID])); + await Victim.Tell(MessageOnStreak(curServer.killStreaks[Victim.ClientNumber], curServer.deathStreaks[Victim.ClientNumber])); } if (E.Type == Event.GType.Say) { - ChatDB.AddChatHistory(E.Origin.DatabaseID, E.Owner.GetPort(), E.Data); + ChatDB.AddChatHistory(E.Origin.ClientNumber, E.Owner.GetPort(), E.Data); } } @@ -444,19 +446,19 @@ namespace StatsPlugin PlayerStats DisconnectingPlayerStats = curServer.playerStats.GetStats(P); - if (DisconnectingPlayerStats == null || curServer.Kills[P.ClientID] == 0) + if (DisconnectingPlayerStats == null || curServer.Kills[P.ClientNumber] == 0) return; - else if (curServer.lastKill[P.ClientID] > curServer.connectionTime[P.ClientID]) - curServer.inactiveMinutes[P.ClientID] += (int)(DateTime.Now - curServer.lastKill[P.ClientID]).TotalMinutes; + else if (curServer.lastKill[P.ClientNumber] > curServer.connectionTime[P.ClientNumber]) + curServer.inactiveMinutes[P.ClientNumber] += (int)(DateTime.Now - curServer.lastKill[P.ClientNumber]).TotalMinutes; - int newPlayTime = (int)(DateTime.Now - curServer.connectionTime[P.ClientID]).TotalMinutes - curServer.inactiveMinutes[P.ClientID]; + int newPlayTime = (int)(DateTime.Now - curServer.connectionTime[P.ClientNumber]).TotalMinutes - curServer.inactiveMinutes[P.ClientNumber]; if (newPlayTime < 2) return; // calculate the players Score Per Minute for the current session - double SessionSPM = curServer.Kills[P.ClientID] * 100 / Math.Max(1, newPlayTime); + double SessionSPM = curServer.Kills[P.ClientNumber] * 100 / Math.Max(1, newPlayTime); // calculate how much the KDR should way // 1.637 is a Eddie-Generated number that weights the KDR nicely double KDRWeight = Math.Round(Math.Pow(DisconnectingPlayerStats.KDR, 1.637 / Math.E), 3); @@ -520,7 +522,7 @@ namespace StatsPlugin } } - public class StatsDB : Database + public class StatsDB : _Database { public StatsDB(String FN, SharedLibrary.Interfaces.ILogger logger) : base(FN, logger) { } @@ -624,7 +626,7 @@ namespace StatsPlugin { Dictionary newPlayer = new Dictionary { - { "npID", P.NetworkID }, + { "npID", P.NetworkId }, { "KILLS", 0 }, { "DEATHS", 0 }, { "KDR", 0.0 }, @@ -637,7 +639,7 @@ namespace StatsPlugin public PlayerStats GetStats(Player P) { - DataTable Result = GetDataTable("STATS", new KeyValuePair("npID", P.NetworkID)); + DataTable Result = GetDataTable("STATS", new KeyValuePair("npID", P.NetworkId)); if (Result != null && Result.Rows.Count > 0) { @@ -682,7 +684,7 @@ namespace StatsPlugin { "SPM", Math.Round(S.scorePerMinute, 2) }, { "PLAYTIME", S.TotalPlayTime } }; - Update("STATS", updatedPlayer, new KeyValuePair("npID", P.NetworkID)); + Update("STATS", updatedPlayer, new KeyValuePair("npID", P.NetworkId)); } public List> GetTopStats() diff --git a/Plugins/Tests/Plugin.cs b/Plugins/Tests/Plugin.cs index c743a2fa7..f920433af 100644 --- a/Plugins/Tests/Plugin.cs +++ b/Plugins/Tests/Plugin.cs @@ -4,9 +4,11 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; + using SharedLibrary; using SharedLibrary.Interfaces; using SharedLibrary.Helpers; +using SharedLibrary.Objects; namespace IW4MAdmin.Plugins { @@ -63,17 +65,20 @@ namespace IW4MAdmin.Plugins { var rand = new Random(); int index = rand.Next(0, 17); - var p = new Player($"?!'\"\"'<>Test_{index}", $"_test{index}", index, (int)Player.Permission.User) + var p = new Player() { - Ping = 1 + Name = $"Test{index}", + NetworkId = $"_test{index}", + ClientNumber = index, + Level = Player.Permission.User, + Ping = 1, + IPAddress = "127.0.0.1" }; - p.SetIP("127.0.0.1"); - if (S.Players.ElementAt(index) != null) await S.RemovePlayer(index); await S.AddPlayer(p); - + /* Interval = DateTime.Now; if (S.ClientNum > 0) @@ -83,7 +88,7 @@ namespace IW4MAdmin.Plugins var victimPlayer = S.Players.Where(pl => pl != null).ToList()[rand.Next(0, S.ClientNum - 1)]; var attackerPlayer = S.Players.Where(pl => pl != null).ToList()[rand.Next(0, S.ClientNum - 1)]; - await S.ExecuteEvent(new Event(Event.GType.Say, $"test_{attackerPlayer.ClientID}", victimPlayer, attackerPlayer, S)); + await S.ExecuteEvent(new Event(Event.GType.Say, $"test_{attackerPlayer.ClientNumber}", victimPlayer, attackerPlayer, S)); string[] eventLine = null; @@ -99,8 +104,8 @@ namespace IW4MAdmin.Plugins eventLine = new string[] { "ScriptKill", - attackerPlayer.NetworkID, - victimPlayer.NetworkID, + attackerPlayer.NetworkId, + victimPlayer.NetworkId, new Vector3(rand.Next(minimapInfo.MaxRight, minimapInfo.MaxLeft), rand.Next(minimapInfo.MaxBottom, minimapInfo.MaxTop), rand.Next(0, 100)).ToString(), new Vector3(rand.Next(minimapInfo.MaxRight, minimapInfo.MaxLeft), rand.Next(minimapInfo.MaxBottom, minimapInfo.MaxTop), rand.Next(0, 100)).ToString(), rand.Next(50, 105).ToString(), @@ -115,12 +120,12 @@ namespace IW4MAdmin.Plugins eventLine = new string[] { "K", - victimPlayer.NetworkID, - victimPlayer.ClientID.ToString(), + victimPlayer.NetworkId, + victimPlayer.ClientNumber.ToString(), rand.Next(0, 1) == 0 ? "allies" : "axis", victimPlayer.Name, - attackerPlayer.NetworkID, - attackerPlayer.ClientID.ToString(), + attackerPlayer.NetworkId, + attackerPlayer.ClientNumber.ToString(), rand.Next(0, 1) == 0 ? "allies" : "axis", attackerPlayer.Name.ToString(), ((StatsPlugin.IW4Info.WeaponName)rand.Next(0, Enum.GetValues(typeof(StatsPlugin.IW4Info.WeaponName)).Length - 1)).ToString(), // Weapon @@ -133,7 +138,7 @@ namespace IW4MAdmin.Plugins var _event = Event.ParseEventString(eventLine, S); await S.ExecuteEvent(_event); } - } + }*/ } } diff --git a/Plugins/VoteMap/Plugin.cs b/Plugins/VoteMap/Plugin.cs index 99696d209..e47c32425 100644 --- a/Plugins/VoteMap/Plugin.cs +++ b/Plugins/VoteMap/Plugin.cs @@ -1,10 +1,11 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using SharedLibrary; using SharedLibrary.Network; using SharedLibrary.Interfaces; -using System.Threading.Tasks; +using SharedLibrary.Objects; namespace Votemap_Plugin { @@ -39,7 +40,7 @@ namespace Votemap_Plugin // we only want to allow a vote during a vote session if (voting.voteInSession) { - if (voting.ClientHasVoted(E.Origin.NetworkID)) + if (voting.ClientHasVoted(E.Origin.NetworkId)) await E.Origin.Tell("You have already voted. Use ^5!vc ^7to ^5cancel ^7your vote"); else { @@ -50,7 +51,7 @@ namespace Votemap_Plugin await E.Origin.Tell("^1" + E.Data + " is not a recognized map"); else { - voting.CastClientVote(E.Origin.NetworkID, votedMap); + voting.CastClientVote(E.Origin.NetworkId, votedMap); await E.Origin.Tell("You voted for ^5" + votedMap.Alias); } } @@ -71,9 +72,9 @@ namespace Votemap_Plugin if (voting.voteInSession) { - if (voting.ClientHasVoted(E.Origin.NetworkID)) + if (voting.ClientHasVoted(E.Origin.NetworkId)) { - voting.CancelClientVote(E.Origin.NetworkID); + voting.CancelClientVote(E.Origin.NetworkId); await E.Origin.Tell("Vote cancelled"); } diff --git a/Plugins/Welcome/Plugin.cs b/Plugins/Welcome/Plugin.cs index caec2f11a..412214e76 100644 --- a/Plugins/Welcome/Plugin.cs +++ b/Plugins/Welcome/Plugin.cs @@ -5,14 +5,12 @@ using SharedLibrary.Interfaces; using System.Threading.Tasks; using SharedLibrary.Network; +using SharedLibrary.Objects; namespace Welcome_Plugin { public class Plugin : IPlugin { - Dictionary PlayerPings; - int PingAverageCount; - String TimesConnected(Player P) { int connection = P.Connections; @@ -68,37 +66,14 @@ namespace Welcome_Plugin public async Task OnLoadAsync(IManager manager) { - PlayerPings = new Dictionary(); - PingAverageCount = 1; } public async Task OnUnloadAsync() { - PlayerPings.Clear(); - PlayerPings = null; } public async Task OnTickAsync(Server S) { - return; - - // TODO: check if this works - - int MaxPing = (await S.GetDvarAsync("sv_maxping")).Value; - - if (MaxPing == 0) - return; - - foreach (int PlayerID in PlayerPings.Keys) - { - var Player = S.Players.Find(p => p.DatabaseID == PlayerID); - PlayerPings[PlayerID] = PlayerPings[PlayerID] + (Player.Ping - PlayerPings[PlayerID]) / PingAverageCount; - if (PlayerPings[PlayerID] > MaxPing) - await Player.Kick($"Your average ping of ^5{PlayerPings[PlayerID]} ^7is too high for this server", null); - } - - if (PingAverageCount > 100) - PingAverageCount = 1; } public async Task OnEventAsync(Event E, Server S) @@ -120,7 +95,7 @@ namespace Welcome_Plugin try { CountryLookupProj.CountryLookup CLT = new CountryLookupProj.CountryLookup("Plugins/GeoIP.dat"); - await E.Owner.Broadcast($"^5{newPlayer.Name} ^7hails from ^5{CLT.lookupCountryName(newPlayer.IP)}"); + await E.Owner.Broadcast($"^5{newPlayer.Name} ^7hails from ^5{CLT.lookupCountryName(newPlayer.IPAddress)}"); } catch (Exception) @@ -129,13 +104,10 @@ namespace Welcome_Plugin } } - - //PlayerPings.Add(E.Origin.DatabaseID, 1.0f); } if (E.Type == Event.GType.Disconnect) { - //PlayerPings.Remove(E.Origin.DatabaseID); } } } diff --git a/SharedLibrary/Command.cs b/SharedLibrary/Command.cs index e4680df50..768967f55 100644 --- a/SharedLibrary/Command.cs +++ b/SharedLibrary/Command.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Threading.Tasks; +using SharedLibrary.Objects; + namespace SharedLibrary { public class CommandArgument diff --git a/SharedLibrary/Commands/NativeCommands.cs b/SharedLibrary/Commands/NativeCommands.cs index fd794d970..1a80af5b9 100644 --- a/SharedLibrary/Commands/NativeCommands.cs +++ b/SharedLibrary/Commands/NativeCommands.cs @@ -2,9 +2,12 @@ using System.Collections.Generic; using System.Text; using System.Linq; +using System.Threading.Tasks; + using SharedLibrary.Network; using SharedLibrary.Helpers; -using System.Threading.Tasks; +using SharedLibrary.Objects; + namespace SharedLibrary.Commands { @@ -28,11 +31,11 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - if (E.Owner.Manager.GetClientDatabase().GetOwner() == null) + if ((await (E.Owner.Manager.GetClientService() as Services.ClientService).GetOwners()).Count == 0) { - E.Origin.SetLevel(Player.Permission.Owner); + E.Origin.Level = Player.Permission.Owner; await E.Origin.Tell("Congratulations, you have claimed ownership of this server!"); - E.Owner.Manager.GetClientDatabase().UpdatePlayer(E.Origin); + await E.Owner.Manager.GetClientService().Update(E.Origin); } else await E.Origin.Tell("This server already has an owner!"); @@ -59,11 +62,10 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - E.Target.lastOffense = E.Data.RemoveWords(1); if (E.Origin.Level <= E.Target.Level) await E.Origin.Tell($"You do not have the required privileges to warn {E.Target.Name}"); else - await E.Target.Warn(E.Target.lastOffense, E.Origin); + await E.Target.Warn(E.Data.RemoveWords(1), E.Origin); } } @@ -82,7 +84,6 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - E.Target.lastOffense = String.Empty; E.Target.Warnings = 0; String Message = String.Format("All warning cleared for {0}", E.Target.Name); await E.Owner.Broadcast(Message); @@ -109,11 +110,10 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - E.Target.lastOffense = E.Data.RemoveWords(1); if (E.Origin.Level > E.Target.Level) { await E.Owner.ExecuteEvent(new Event(Event.GType.Kick, E.Data, E.Origin, E.Target, E.Owner)); - await E.Target.Kick(E.Target.lastOffense, E.Origin); + await E.Target.Kick(E.Data.RemoveWords(1), E.Origin); await E.Origin.Tell($"^5{E.Target} ^7has been kicked"); } else @@ -165,8 +165,7 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - E.Target.lastOffense = Utilities.RemoveWords(E.Data, 1); - String Message = E.Target.lastOffense; + String Message = Utilities.RemoveWords(E.Data, 1); var length = Message.ParseTimespan(); if (length.TotalHours != 1) @@ -202,17 +201,9 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - E.Target.lastOffense = Utilities.RemoveWords(E.Data, 1); - E.Target.lastEvent = E; // needs to be fixed - String Message; - if (E.Owner.Website == null) - Message = "^1Player Banned: ^5" + E.Target.lastOffense; - else - Message = "^1Player Banned: ^5" + E.Target.lastOffense; if (E.Origin.Level > E.Target.Level) { - await E.Owner.ExecuteEvent(new Event(Event.GType.Ban, E.Data, E.Origin, E.Target, E.Owner)); - await E.Target.Ban(Message, E.Origin); + await E.Target.Ban(E.Data, E.Origin); await E.Origin.Tell($"^5{E.Target} ^7has been permanently banned"); } else @@ -248,7 +239,7 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - String You = String.Format("{0} [^3#{1}^7] {2} [^3@{3}^7] [{4}^7] IP: {5}", E.Origin.Name, E.Origin.ClientID, E.Origin.NetworkID, E.Origin.DatabaseID, Utilities.ConvertLevelToColor(E.Origin.Level), E.Origin.IP); + String You = String.Format("{0} [^3#{1}^7] {2} [^3@{3}^7] [{4}^7] IP: {5}", E.Origin.Name, E.Origin.ClientNumber, E.Origin.NetworkId, E.Origin.ClientNumber, Utilities.ConvertLevelToColor(E.Origin.Level), E.Origin.IPAddress); await E.Origin.Tell(You); } } @@ -271,9 +262,9 @@ namespace SharedLibrary.Commands continue; if (P.Masked) - playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(Player.Permission.User), P.ClientID, P.Name, Utilities.GetSpaces(Player.Permission.SeniorAdmin.ToString().Length - Player.Permission.User.ToString().Length)); + playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(Player.Permission.User), P.ClientNumber, P.Name, Utilities.GetSpaces(Player.Permission.SeniorAdmin.ToString().Length - Player.Permission.User.ToString().Length)); else - playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(P.Level), P.ClientID, P.Name, Utilities.GetSpaces(Player.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length)); + playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(P.Level), P.ClientNumber, P.Name, Utilities.GetSpaces(Player.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length)); if (count == 2 || E.Owner.GetPlayersAsList().Count == 1) { @@ -424,16 +415,16 @@ namespace SharedLibrary.Commands if (newPerm > Player.Permission.Banned) { - var ActiveClient = E.Owner.Manager.GetActiveClients().FirstOrDefault(p => p.NetworkID == E.Target.NetworkID); - ActiveClient?.SetLevel(newPerm); + var ActiveClient = E.Owner.Manager.GetActiveClients().FirstOrDefault(p => p.NetworkId == E.Target.NetworkId); + ActiveClient.Level = newPerm; if (ActiveClient != null) await ActiveClient.Tell("Congratulations! You have been promoted to ^3" + newPerm); await E.Origin.Tell($"{E.Target.Name} was successfully promoted!"); - E.Target.SetLevel(newPerm); - E.Owner.Manager.GetClientDatabase().UpdatePlayer(E.Target); + E.Target.Level = newPerm; + await E.Owner.Manager.GetClientService().Update(E.Target); } else @@ -536,9 +527,9 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - var db_players = E.Owner.Manager.GetClientDatabase().FindPlayers(E.Data.Trim()); + var db_players = await E.Owner.Manager.GetClientService().Find(c => c.Name.Contains(E.Data)); - if (db_players == null) + if (db_players.Count == 0) { await E.Origin.Tell("No players found"); return; @@ -546,7 +537,7 @@ namespace SharedLibrary.Commands foreach (Player P in db_players) { - String mesg = String.Format("[^3{0}^7] [^3@{1}^7] - [{2}^7] - {3} | last seen {4}", P.Name, P.DatabaseID, Utilities.ConvertLevelToColor(P.Level), P.IP, P.GetLastConnection()); + String mesg = String.Format("[^3{0}^7] [^3@{1}^7] - [{2}^7] - {3} | last seen {4}", P.Name, P.ClientNumber, Utilities.ConvertLevelToColor(P.Level), P.IPAddress, P.GetLastConnection()); await E.Origin.Tell(mesg); } } @@ -575,36 +566,17 @@ namespace SharedLibrary.Commands return; } - var db_aliases = E.Owner.Manager.GetAliasesDatabase().FindPlayerAliases(E.Data); + var db_aliases = await E.Owner.Manager.GetAliasService().Find(a => a.Name.Contains(E.Data)); - if (db_aliases == null || db_aliases.Count() == 0) + if (db_aliases.Count == 0) { await E.Origin.Tell("No players found"); return; } - foreach (Aliases P in db_aliases) + foreach (var P in db_aliases) { - if (P == null) - continue; - - String lookingFor = null; - - foreach (String S in P.Names) - { - if (S.ToLower().Contains(E.Data.ToLower())) - lookingFor = S; - } - - lookingFor = lookingFor ?? P.Names.First(); - - Player Current = E.Owner.Manager.GetClientDatabase().GetPlayer(P.Number); - - if (Current != null && Current.Name != lookingFor) - { - String mesg = String.Format("^1{0} ^7now goes by ^5{1}^7 [^3{2}^7]", lookingFor, Current.Name, Current.DatabaseID); - await E.Origin.Tell(mesg); - } + await E.Origin.Tell($"^4{P.Name} ^7now goes by ^5{P.Link.Children.OrderByDescending(a => a.DateAdded).First().Name}"); } } } @@ -707,21 +679,33 @@ namespace SharedLibrary.Commands if (E.Target.Level == Player.Permission.Flagged) { - E.Target.SetLevel(Player.Permission.User); - E.Owner.Manager.GetClientPenalties().RemovePenalty(new Penalty(Penalty.Type.Flag, "", E.Target.NetworkID, "", DateTime.Now, "", DateTime.Now)); + E.Target.Level = Player.Permission.User; + //E.Owner.Manager.GetClientPenalties().RemovePenalty(new Penalty(Penalty.PenaltyType.Flag, "", E.Target.NetworkId, "", DateTime.Now, "", DateTime.Now)); await E.Origin.Tell("You have ^5unflagged ^7" + E.Target.Name); } else { E.Data = Utilities.RemoveWords(E.Data, 1); - E.Target.SetLevel(Player.Permission.Flagged); - E.Owner.Manager.GetClientPenalties().AddPenalty(new Penalty(Penalty.Type.Flag, E.Data, E.Target.NetworkID, E.Origin.NetworkID, DateTime.Now, E.Target.IP, DateTime.Now)); + E.Target.Level = Player.Permission.Flagged; + + Penalty newPenalty = new Penalty() + { + Type = Penalty.PenaltyType.Flag, + Expires = DateTime.UtcNow, + Offender = E.Target, + Offense = E.Data, + Punisher = E.Origin, + Active = true, + When = DateTime.UtcNow + }; + + await E.Owner.Manager.GetPenaltyService().Create(newPenalty); await E.Owner.ExecuteEvent(new Event(Event.GType.Flag, E.Data, E.Origin, E.Target, E.Owner)); await E.Origin.Tell("You have ^5flagged ^7" + E.Target.Name); } - E.Owner.Manager.GetClientDatabase().UpdatePlayer(E.Target); + await E.Owner.Manager.GetClientService().Update(E.Target); } } @@ -745,7 +729,7 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - if (E.Owner.Reports.Find(x => (x.Origin == E.Origin && x.Target.NetworkID == E.Target.NetworkID)) != null) + if (E.Owner.Reports.Find(x => (x.Origin == E.Origin && x.Target.NetworkId == E.Target.NetworkId)) != null) { await E.Origin.Tell("You have already reported this player"); return; @@ -824,7 +808,7 @@ namespace SharedLibrary.Commands await E.Origin.Tell("You are now masked"); } - E.Owner.Manager.GetClientDatabase().UpdatePlayer(E.Origin); + await E.Owner.Manager.GetClientService().Update(E.Origin); } } @@ -843,18 +827,17 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - var B = E.Owner.Manager.GetClientPenalties().FindPenalties(E.Target); - var BannedPenalty = B.Find(b => b.BType > Penalty.Type.Kick && b.Expires > DateTime.Now); + var B = await E.Owner.Manager.GetPenaltyService().GetClientPenaltiesAsync(E.Target.ClientId); - if (BannedPenalty == null) + var penalty = B.FirstOrDefault(b => b.Type > Penalty.PenaltyType.Kick && b.Expires > DateTime.UtcNow); + + if (penalty == null) { await E.Origin.Tell("No active ban was found for that player"); return; } - Player Banner = E.Owner.Manager.GetClientDatabase().GetPlayer(BannedPenalty.PenaltyOriginID, -1); - - await E.Origin.Tell(String.Format("^1{0} ^7was banned by ^5{1} ^7for: {2} {3}", E.Target.Name, Banner?.Name ?? "IW4MAdmin", BannedPenalty.Reason, BannedPenalty.BType == Penalty.Type.TempBan ? $"({(BannedPenalty.Expires - DateTime.Now).TimeSpanText()} remaining)" : "")); + await E.Origin.Tell(String.Format("^1{0} ^7was banned by ^5{1} ^7for: {2} {3}", E.Target.Name, penalty.Punisher.Name, penalty.Offense, penalty.Type == Penalty.PenaltyType.TempBan ? $"({(penalty.Expires - DateTime.Now).TimeSpanText()} remaining)" : "")); } } @@ -873,37 +856,19 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - E.Target.Alias = E.Owner.Manager.GetAliasesDatabase().GetPlayerAliases(E.Target.DatabaseID); - - if (E.Target.Alias == null) - { - await E.Target.Tell("Could not find alias info for that player"); - return; - } - - await E.Target.Tell("[^3" + E.Target.Name + "^7]"); StringBuilder message = new StringBuilder(); + var names = new List(E.Target.AliasLink.Children.Select(a => a.Name)); + var IPs = new List(E.Target.AliasLink.Children.Select(a => a.IP)); - var playerAliases = E.Owner.GetAliases(E.Target); + await E.Target.Tell($"[^3{E.Target}^7]"); message.Append("Aliases: "); - - var names = new List(); - var ips = new List(); - - foreach (var alias in playerAliases) - { - names.AddRange(alias.Names); - ips.AddRange(alias.IPS); - } - message.Append(String.Join(" | ", names.Distinct())); - + message.Append(String.Join(" | ", names)); await E.Origin.Tell(message.ToString()); message.Clear(); message.Append("IPs: "); - message.Append(String.Join(" | ", ips.Distinct())); - + message.Append(String.Join(" | ", IPs)); await E.Origin.Tell(message.ToString()); } } @@ -955,7 +920,7 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - await E.Origin.Tell($"Your external IP is ^5{E.Origin.IP}"); + await E.Origin.Tell($"Your external IP is ^5{E.Origin.IPAddress}"); } } } diff --git a/SharedLibrary/Database.cs b/SharedLibrary/Database.cs deleted file mode 100644 index 9c0928ad3..000000000 --- a/SharedLibrary/Database.cs +++ /dev/null @@ -1,735 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Data.SQLite; -using System.Data; -using System.IO; - -namespace SharedLibrary -{ - public abstract class Database - { - private Interfaces.ILogger Logger; - - public Database(String FN, Interfaces.ILogger logger) - { - FileName = FN; - Logger = logger; - Init(); - } - - protected SQLiteConnection GetNewConnection() - { - return new SQLiteConnection($"Data Source={FileName}"); - } - - abstract public void Init(); - - protected bool Insert(String tableName, Dictionary data, bool ignore = false) - { - string names = ""; - string parameters = ""; - foreach (string key in data.Keys) - { - names += key + ','; - parameters += '@' + key + ','; - } - names = names.Substring(0, names.Length - 1); - parameters = parameters.Substring(0, parameters.Length - 1); - - var Con = GetNewConnection(); - - string ignoreCmd = ignore ? " OR IGNORE " : " "; - - SQLiteCommand insertcmd = new SQLiteCommand() - { - Connection = Con, - CommandText = String.Format("INSERT{0}INTO `{1}` ({2}) VALUES ({3});", ignoreCmd, tableName, names, parameters) - }; - foreach (string key in data.Keys) - { - insertcmd.Parameters.AddWithValue('@' + key, data[key]); - } - - try - { - Con.Open(); - insertcmd.ExecuteNonQuery(); - Con.Close(); - return true; - } - - catch (Exception E) - { - Logger.WriteWarning($"Database Insert failed"); - Logger.WriteDebug($"Exception Message: {E.Message}"); - Logger.WriteDebug($"SQL command: {insertcmd.CommandText}"); - Logger.WriteDebug($"Database File: {FileName}"); - return false; - } - - } - - protected void UpdateIncrement(String tableName, string columnName, Dictionary data, KeyValuePair where) - { - string parameters = ""; - foreach (string key in data.Keys) - { - parameters += $"{key}={key}+1,"; - } - - parameters = parameters.Substring(0, parameters.Length - 1); - var Con = GetNewConnection(); - - SQLiteCommand updatecmd = new SQLiteCommand() - { - Connection = Con, - CommandText = String.Format("UPDATE `{0}` SET {1} WHERE {2}=@{2}", tableName, parameters, where.Key) - }; - foreach (string key in data.Keys) - { - updatecmd.Parameters.AddWithValue('@' + key, data[key]); - } - - updatecmd.Parameters.AddWithValue('@' + where.Key, where.Value); - - try - { - Con.Open(); - updatecmd.ExecuteNonQuery(); - Con.Close(); - } - - catch (Exception E) - { - Logger.WriteWarning($"Database UpdateIncrement failed"); - Logger.WriteDebug($"Exception Message: {E.Message}"); - Logger.WriteDebug($"SQL command: {updatecmd?.CommandText}"); - Logger.WriteDebug($"Database File: {FileName}"); - } - } - - protected bool Update(String tableName, Dictionary data, KeyValuePair where) - { - string parameters = ""; - foreach (string key in data.Keys) - { - parameters += key + '=' + '@' + key + ','; - } - - parameters = parameters.Substring(0, parameters.Length - 1); - var Con = GetNewConnection(); - - SQLiteCommand updatecmd = new SQLiteCommand() - { - Connection = Con, - CommandText = String.Format("UPDATE `{0}` SET {1} WHERE {2}=@{2}", tableName, parameters, where.Key) - }; - foreach (string key in data.Keys) - { - updatecmd.Parameters.AddWithValue('@' + key, data[key]); - } - - updatecmd.Parameters.AddWithValue('@' + where.Key, where.Value); - - try - { - Con.Open(); - updatecmd.ExecuteNonQuery(); - Con.Close(); - return true; - } - - catch (Exception E) - { - Logger.WriteWarning($"Database update failed"); - Logger.WriteDebug($"Exception Message: {E.Message}"); - Logger.WriteDebug($"SQL Query: {updatecmd.CommandText}"); - Logger.WriteDebug($"Database File: {FileName}"); - return false; - } - } - - protected DataRow GetDataRow(String Q) - { - DataRow Result = GetDataTable(Q).Rows[0]; - return Result; - } - - protected int ExecuteNonQuery(String Request) - { - int rowsUpdated = 0; - Request = Request.Replace("!'", "").Replace("!", ""); - var Con = GetNewConnection(); - SQLiteCommand CMD = null; - try - { - - Con.Open(); - CMD = new SQLiteCommand(Con) - { - CommandText = Request - }; - rowsUpdated = CMD.ExecuteNonQuery(); - Con.Close(); - return rowsUpdated; - } - - catch (Exception E) - { - Logger.WriteWarning($"Database command failed"); - Logger.WriteDebug($"Exception Message: {E.Message}"); - Logger.WriteDebug($"SQL command: {CMD?.CommandText}"); - Logger.WriteDebug($"Database File: {FileName}"); - return 0; - } - } - - protected DataTable GetDataTable(string tableName, KeyValuePair where) - { - DataTable dt = new DataTable(); - SQLiteCommand updatecmd = new SQLiteCommand() - { - CommandText = String.Format("SELECT * FROM {0} WHERE `{1}`=@{1};", tableName, where.Key) - }; - var Con = GetNewConnection(); - updatecmd.Parameters.AddWithValue('@' + where.Key, where.Value); - updatecmd.Connection = Con; - - - try - { - Con.Open(); - SQLiteDataReader reader = updatecmd.ExecuteReader(); - dt.Load(reader); - reader.Close(); - Con.Close(); - } - - catch (Exception E) - { - Logger.WriteWarning($"Database GetDataTable failed"); - Logger.WriteDebug($"Exception Message: {E.Message}"); - Logger.WriteDebug($"SQL command: {updatecmd.CommandText}"); - Logger.WriteDebug($"Database File: {FileName}"); - } - - return dt; - } - - protected DataTable GetDataTable(SQLiteCommand cmd) - { - DataTable dt = new DataTable(); - var Con = GetNewConnection(); - cmd.Connection = Con; - try - { - Con.Open(); - SQLiteDataReader reader = cmd.ExecuteReader(); - dt.Load(reader); - reader.Close(); - Con.Close(); - } - - catch (Exception E) - { - Logger.WriteWarning($"Database GetDataTable failed"); - Logger.WriteDebug($"Exception Message: {E.Message}"); - Logger.WriteDebug($"SQL command: {cmd.CommandText}"); - Logger.WriteDebug($"Database File: {FileName}"); - } - - return dt; - } - - protected DataTable GetDataTable(String sql) - { - DataTable dt = new DataTable(); - var Con = GetNewConnection(); - SQLiteCommand cmd = null; - - try - { - - Con.Open(); - cmd = new SQLiteCommand(Con) - { - CommandText = sql - }; - SQLiteDataReader reader = cmd.ExecuteReader(); - dt.Load(reader); - reader.Close(); - Con.Close(); - - } - catch (Exception E) - { - Logger.WriteWarning($"Database GetDataTable failed"); - Logger.WriteDebug($"Exception Message: {E.Message}"); - Logger.WriteDebug($"SQL command: {cmd?.CommandText}"); - Logger.WriteDebug($"Database File: {FileName}"); - return new DataTable(); - } - return dt; - } - - protected String FileName; - } - - public class ClientsDB : Database - { - public ClientsDB(String FN, Interfaces.ILogger logger) : base(FN, logger) { } - - public override void Init() - { - if (!File.Exists(FileName)) - { - String Create = "CREATE TABLE [CLIENTS] ( [Name] TEXT NULL, [npID] TEXT NULL, [Number] INTEGER PRIMARY KEY AUTOINCREMENT, [Level] INT DEFAULT 0 NULL, [LastOffense] TEXT NULL, [Connections] INT DEFAULT 1 NULL, [IP] TEXT NULL, [LastConnection] TEXT NULL, [UID] TEXT NULL, [Masked] INT DEFAULT 0, [Reserved] INT DEFAULT 0);"; - ExecuteNonQuery(Create); - Create = "CREATE TABLE [BANS] ( [TYPE] TEXT NULL, [Reason] TEXT NULL, [npID] TEXT NULL, [bannedByID] TEXT NULL, [IP] TEXT NULL, [TIME] TEXT NULL, [EXPIRES] TEXT);"; - ExecuteNonQuery(Create); - } - } - - - public List GetRecentPlayers(int count = 15, int offset = 0) - { - List returnssss = new List(); - var Result = GetDataTable($"SELECT * FROM CLIENTS LIMIT {count} OFFSET (SELECT COUNT(*) FROM CLIENTS)-{offset + count}"); - - if (Result != null && Result.Rows.Count > 0) - { - foreach (DataRow ResponseRow in Result.Rows) - { - DateTime lastCon = DateTime.MinValue; - DateTime.TryParse(ResponseRow["LastConnection"].ToString(), out lastCon); - - returnssss.Add(new Player(ResponseRow["Name"].ToString(), ResponseRow["npID"].ToString(), -1, (Player.Permission)(ResponseRow["Level"]), Convert.ToInt32(ResponseRow["Number"]), ResponseRow["LastOffense"].ToString(), (int)ResponseRow["Connections"], ResponseRow["IP"].ToString(), lastCon, ResponseRow["UID"].ToString(), ResponseRow["Masked"].ToString() == "1")); - } - } - - return returnssss.OrderByDescending(p => p.LastConnection).ToList(); ; - } - - public List GetPlayers(List npIDs) - { - List returnssss = new List(); - String test = String.Join("' OR npID = '", npIDs); - - String Query = String.Format("SELECT * FROM CLIENTS WHERE npID = '{0}'", test); - DataTable Result = GetDataTable(Query); - - if (Result != null && Result.Rows.Count > 0) - { - foreach (DataRow ResponseRow in Result.Rows) - { - DateTime lastCon = DateTime.MinValue; - DateTime.TryParse(ResponseRow["LastConnection"].ToString(), out lastCon); - - returnssss.Add(new Player(ResponseRow["Name"].ToString(), ResponseRow["npID"].ToString(), -1, (Player.Permission)(ResponseRow["Level"]), Convert.ToInt32(ResponseRow["Number"]), ResponseRow["LastOffense"].ToString(), (int)ResponseRow["Connections"], ResponseRow["IP"].ToString(), lastCon, ResponseRow["UID"].ToString(), ResponseRow["Masked"].ToString() == "1")); - } - } - - return returnssss; - } - - public List GetPlayers(List databaseIDs) - { - List returnssss = new List(); - String Condition = String.Join("' OR Number = '", databaseIDs); - - String Query = String.Format("SELECT * FROM CLIENTS WHERE Number = '{0}'", Condition); - DataTable Result = GetDataTable(Query); - - if (Result != null && Result.Rows.Count > 0) - { - foreach (DataRow ResponseRow in Result.Rows) - { - DateTime lastCon = DateTime.MinValue; - DateTime.TryParse(ResponseRow["LastConnection"].ToString(), out lastCon); - - returnssss.Add(new Player(ResponseRow["Name"].ToString(), ResponseRow["npID"].ToString(), -1, (Player.Permission)(ResponseRow["Level"]), Convert.ToInt32(ResponseRow["Number"]), ResponseRow["LastOffense"].ToString(), (int)ResponseRow["Connections"], ResponseRow["IP"].ToString(), lastCon, ResponseRow["UID"].ToString(), ResponseRow["Masked"].ToString() == "1")); - } - } - - return returnssss; - } - - //Overloaded method for getPlayer, returns Client with matching DBIndex, null if none found - public Player GetPlayer(int dbIndex) - { - DataTable Result = GetDataTable("CLIENTS", new KeyValuePair("Number", dbIndex)); - - if (Result != null && Result.Rows.Count > 0) - { - DataRow p = Result.Rows[0]; - DateTime LC; - try - { - LC = DateTime.Parse(p["LastConnection"].ToString()); - } - catch (Exception) - { - LC = DateTime.MinValue; - } - - return new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), Convert.ToInt32(p["Connections"]), p["IP"].ToString(), LC, p["UID"].ToString(), p["Masked"].ToString() == "1"); - } - - else - return null; - } - - //get player by ip, (used for webfront) - public Player GetPlayer(String IP) - { - DataTable Result = GetDataTable("CLIENTS", new KeyValuePair("IP", IP)); - - if (Result != null && Result.Rows.Count > 0) - { - List lastKnown = new List(); - foreach (DataRow p in Result.Rows) - { - DateTime LC; - try - { - LC = DateTime.Parse(p["LastConnection"].ToString()); - lastKnown.Add(new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), Convert.ToInt32((DateTime.Now - LC).TotalSeconds), p["IP"].ToString(), LC, p["UID"].ToString(), p["Masked"].ToString() == "1")); - } - - catch (Exception) - { - continue; - } - } - - if (lastKnown.Count > 0) - { - List Returning = lastKnown.OrderBy(t => t.Connections).ToList(); - return Returning[0]; - } - - else - return null; - } - - else - return null; - } - - //Returns a single player object with matching GUID, false if no matches - public Player GetPlayer(String ID, int cNum) - { - DataTable Result = GetDataTable("CLIENTS", new KeyValuePair("npID", ID)); - - if (Result != null && Result.Rows.Count > 0) - { - DataRow ResponseRow = Result.Rows[0]; - DateTime lastCon = DateTime.MinValue; - DateTime.TryParse(ResponseRow["LastConnection"].ToString(), out lastCon); - - return new Player(ResponseRow["Name"].ToString(), ResponseRow["npID"].ToString(), cNum, (Player.Permission)(ResponseRow["Level"]), Convert.ToInt32(ResponseRow["Number"]), ResponseRow["LastOffense"].ToString(), (int)ResponseRow["Connections"], ResponseRow["IP"].ToString(), lastCon, ResponseRow["UID"].ToString(), ResponseRow["Masked"].ToString() == "1"); - } - - else - return null; - } - - //Returns a list of players matching name parameter, null if no players found matching - public List FindPlayers(String name) - { - var Con = GetNewConnection(); - SQLiteCommand cmd = new SQLiteCommand(Con) - { - CommandText = "SELECT * FROM CLIENTS WHERE Name LIKE @Name" - }; - cmd.Parameters.AddWithValue("@Name", '%' + name + '%'); - - var Result = GetDataTable(cmd); - - List Players = new List(); - - if (Result != null && Result.Rows.Count > 0) - { - foreach (DataRow p in Result.Rows) - { - DateTime LC; - string Masked = null; - try - { - LC = DateTime.Parse(p["LastConnection"].ToString()); - Masked = p["Masked"].ToString(); - - } - catch (Exception) - { - if (Masked == null) - Masked = "0"; - - LC = DateTime.MinValue; - } - Players.Add(new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), Convert.ToInt32(p["Connections"]), p["IP"].ToString(), LC, p["IP"].ToString(), Masked == "1")); - } - return Players; - } - - else - return null; - } - - //Returns any player with level 4 permissions, null if no owner found - public Player GetOwner() - { - String Query = String.Format("SELECT * FROM CLIENTS WHERE Level > '{0}'", 4); - DataTable Result = GetDataTable(Query); - - if (Result != null && Result.Rows.Count > 0) - { - DataRow ResponseRow = Result.Rows[0]; - if (ResponseRow["IP"].ToString().Length < 6) - ResponseRow["IP"] = "0"; - return new Player(ResponseRow["Name"].ToString(), ResponseRow["npID"].ToString(), -1, (Player.Permission)(ResponseRow["Level"]), Convert.ToInt32(ResponseRow["Number"]), null, 0, ResponseRow["IP"].ToString()); - } - - else - return null; - } - - public List GetClientPenalties(Player P) - { - List ClientPenalties = new List(); - String Query = $"SELECT * FROM `BANS` WHERE `npID` = '{P.NetworkID}' OR `IP` = '{P.IP}'"; - DataTable Result = GetDataTable(Query); - - foreach (DataRow Row in Result.Rows) - { - if (Row["TIME"].ToString().Length < 2) //compatibility with my old database - Row["TIME"] = DateTime.Now.ToString(); - - Penalty.Type BanType = Penalty.Type.Ban; - if (Row["TYPE"].ToString().Length != 0) - BanType = (Penalty.Type)Enum.Parse(typeof(Penalty.Type), Row["TYPE"].ToString()); - - ClientPenalties.Add(new Penalty(BanType, Row["Reason"].ToString().Trim(), Row["npID"].ToString(), Row["bannedByID"].ToString(), DateTime.Parse(Row["TIME"].ToString()), Row["IP"].ToString(), DateTime.Parse(Row["EXPIRES"].ToString()))); - - } - - return ClientPenalties; - } - - public List GetPenaltiesChronologically(int offset, int count, Penalty.Type penaltyType) - { - List ClientPenalties = new List(); - DataTable Result = GetDataTable($"SELECT * FROM BANS {(penaltyType != Penalty.Type.Any ? $"WHERE `TYPE`={(int)penaltyType}" : "")} LIMIT {count} OFFSET (SELECT COUNT(*) FROM BANS {(penaltyType != Penalty.Type.Any ? $"WHERE `TYPE`={(int)penaltyType}" : "")})-{offset + count}"); - - foreach (DataRow Row in Result.Rows) - { - if (Row["TIME"].ToString().Length < 2) //compatibility with my old database - Row["TIME"] = DateTime.Now.ToString(); - - var BanType = (Penalty.Type)Enum.Parse(typeof(Penalty.Type), Row["TYPE"].ToString()); - ClientPenalties.Add(new Penalty(BanType, Row["Reason"].ToString().Trim(), Row["npID"].ToString(), Row["bannedByID"].ToString(), DateTime.Parse(Row["TIME"].ToString()), Row["IP"].ToString(), DateTime.Parse(Row["EXPIRES"].ToString()))); - } - - return ClientPenalties; - } - - //Returns all players with level > Flagged - public List GetAdmins() - { - List Admins = new List(); - String Query = String.Format("SELECT * FROM CLIENTS WHERE Level >= '{0}' ORDER BY Name", (int)Player.Permission.Trusted); - DataTable Result = GetDataTable(Query); - - foreach (DataRow P in Result.Rows) - Admins.Add(new Player(P["Name"].ToString(), P["npID"].ToString(), (Player.Permission)P["Level"], P["IP"].ToString(), P["UID"].ToString(), Convert.ToInt32(P["Number"].ToString()))); - - return Admins; - } - - //Returns total number of player entries in database - public int TotalPlayers() - { - DataTable Result = GetDataTable("SELECT * from CLIENTS ORDER BY Number DESC LIMIT 1"); - if (Result.Rows.Count > 0) - return Convert.ToInt32(Result.Rows[0]["Number"]); - else - return 0; - } - - //Add specified player to database - public void AddPlayer(Player P) - { - Dictionary newPlayer = new Dictionary - { - { "Name", P.Name }, - { "npID", P.NetworkID }, - { "Level", (int)P.Level }, - { "LastOffense", "" }, - { "Connections", 1 }, - { "IP", P.IP }, - { "LastConnection", Utilities.DateTimeSQLite(DateTime.Now) }, - { "UID", P.UID }, - { "Masked", Convert.ToInt32(P.Masked) } - }; - Insert("CLIENTS", newPlayer); - } - - ///Update information of specified player - public void UpdatePlayer(Player P) - { - Dictionary updatedPlayer = new Dictionary - { - { "Name", P.Name }, - { "npID", P.NetworkID }, - { "Level", (int)P.Level }, - { "LastOffense", P.lastOffense }, - { "Connections", P.Connections }, - { "IP", P.IP }, - { "LastConnection", Utilities.DateTimeSQLite(DateTime.Now) }, - { "UID", P.UID }, - { "Masked", Convert.ToInt32(P.Masked) } - }; - Update("CLIENTS", updatedPlayer, new KeyValuePair("npID", P.NetworkID)); - } - - - public void PruneAdmins(int inactiveDays) - { - ExecuteNonQuery($"UPDATE CLIENTS SET Level={(int)Player.Permission.User} WHERE LastConnection < '{Utilities.DateTimeSQLite(DateTime.Now.AddDays(-inactiveDays))}'"); - } - - //Add specified ban to database - public void AddPenalty(Penalty B) - { - Dictionary newBan = new Dictionary - { - { "Reason", B.Reason }, - { "npID", B.OffenderID }, - { "bannedByID", B.PenaltyOriginID }, - { "IP", B.IP }, - { "TIME", Utilities.DateTimeSQLite(DateTime.Now) }, - { "TYPE", B.BType }, - { "EXPIRES", B.Expires } - }; - Insert("BANS", newBan); - } - - - //Deletes ban with matching GUID - public void RemoveBan(String GUID) - { - String Query = String.Format("DELETE FROM BANS WHERE npID = '{0}'", GUID); - ExecuteNonQuery(Query); - } - - public void RemoveBan(String GUID, String IP) - { - String Query = String.Format("DELETE FROM BANS WHERE npID = '{0}' or IP = '{1}'", GUID, IP); - ExecuteNonQuery(Query); - } - } - - public class AliasesDB : Database - { - public AliasesDB(String FN, Interfaces.ILogger logger) : base(FN, logger) { } - - public override void Init() - { - if (!File.Exists(FileName)) - { - String Create = "CREATE TABLE [ALIASES] ( [Number] INTEGER, [NAMES] TEXT NULL, [IPS] TEXTNULL );"; - ExecuteNonQuery(Create); - } - } - - public Aliases GetPlayerAliases(int dbIndex) - { - String Query = String.Format("SELECT * FROM ALIASES WHERE Number = '{0}' LIMIT 1", dbIndex); - DataTable Result = GetDataTable(Query); - - if (Result != null && Result.Rows.Count > 0) - { - DataRow p = Result.Rows[0]; - return new Aliases(Convert.ToInt32(p["Number"]), p["NAMES"].ToString(), p["IPS"].ToString()); - } - - else - return null; - } - - public List GetPlayerAliases(String IP) - { - var Con = GetNewConnection(); - SQLiteCommand cmd = new SQLiteCommand(Con) - { - CommandText = "SELECT * FROM ALIASES WHERE IPS LIKE @IP" - }; - cmd.Parameters.AddWithValue("@IP", $"%{IP}%"); - - var Result = GetDataTable(cmd); - - List players = new List(); - - if (Result != null && Result.Rows.Count > 0) - { - foreach (DataRow p in Result.Rows) - players.Add(new Aliases(Convert.ToInt32(p["Number"]), p["NAMES"].ToString(), p["IPS"].ToString())); - } - - return players; - } - - public List FindPlayerAliases(String name) - { - name = name.Replace("'", ""); - String[] IP = name.Split('.'); - String DefaultIP = "LEGACY_INVALID_IP"; - if (IP.Length > 1) - DefaultIP = (IP[0] + '.' + IP[1] + '.'); - var Con = GetNewConnection(); - - SQLiteCommand cmd = new SQLiteCommand(Con) - { - CommandText = "SELECT * FROM ALIASES WHERE NAMES LIKE @name OR IPS LIKE @ip LIMIT 15" - }; - cmd.Parameters.AddWithValue("@name", '%' + name + '%'); - cmd.Parameters.AddWithValue("@ip", '%' + DefaultIP + '%'); - - var Result = GetDataTable(cmd); - - - List players = new List(); - - if (Result != null && Result.Rows.Count > 0) - { - foreach (DataRow p in Result.Rows) - players.Add(new Aliases(Convert.ToInt32(p["Number"]), p["NAMES"].ToString(), p["IPS"].ToString())); - } - - return players; - } - - public void AddPlayerAliases(Aliases Alias) - { - Dictionary newPlayer = new Dictionary - { - { "Number", Alias.Number }, - { "NAMES", String.Join(";", Alias.Names) }, - { "IPS", String.Join(";", Alias.IPS) } - }; - Insert("ALIASES", newPlayer); - } - - public void UpdatePlayerAliases(Aliases Alias) - { - Dictionary updatedPlayer = new Dictionary - { - { "Number", Alias.Number }, - { "NAMES", String.Join(";", Alias.Names) }, - { "IPS", String.Join(";", Alias.IPS) } - }; - Update("ALIASES", updatedPlayer, new KeyValuePair("Number", Alias.Number)); - } - } -} diff --git a/SharedLibrary/Database/IW4MAdminDatabaseContext.cs b/SharedLibrary/Database/IW4MAdminDatabaseContext.cs new file mode 100644 index 000000000..9ad8d5918 --- /dev/null +++ b/SharedLibrary/Database/IW4MAdminDatabaseContext.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Data.Entity; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharedLibrary.Database.Models; +using System.Data.SqlServerCe; + +namespace SharedLibrary.Database +{ + public class IW4MAdminDatabaseContext : DbContext + { + public DbSet Clients { get; set; } + public DbSet Aliases { get; set; } + public DbSet AliasLinks { get; set; } + public DbSet Penalties { get; set; } + + public IW4MAdminDatabaseContext() : base("DefaultConnection") + { + System.Data.Entity.Database.SetInitializer(new Initializer()); + } + + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + modelBuilder.Entity() + .HasRequired(p => p.Punisher) + .WithMany(c => c.AdministeredPenalties) + .HasForeignKey(c => c.PunisherId) + .WillCascadeOnDelete(false); + + modelBuilder.Entity() + .HasRequired(p => p.Offender) + .WithMany(c => c.ReceivedPenalties) + .HasForeignKey(c => c.OffenderId) + .WillCascadeOnDelete(false); + + modelBuilder.Entity() + .HasMany(e => e.Children) + .WithRequired(a => a.Link) + .HasForeignKey(a => a.LinkId) + .WillCascadeOnDelete(true); + + // todo custom load DBSets from plugins + // https://aleemkhan.wordpress.com/2013/02/28/dynamically-adding-dbset-properties-in-dbcontext-for-entity-framework-code-first/ + base.OnModelCreating(modelBuilder); + } + } +} diff --git a/SharedLibrary/Database/Initializer.cs b/SharedLibrary/Database/Initializer.cs new file mode 100644 index 000000000..a15e6af29 --- /dev/null +++ b/SharedLibrary/Database/Initializer.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Data.Entity; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary.Database +{ + public class Initializer : DropCreateDatabaseIfModelChanges + { + protected override void Seed(IW4MAdminDatabaseContext context) + { + context.Clients.Add(new Models.EFClient() + { + Active = false, + Connections = 0, + AliasLink = new Models.EFAliasLink(), + FirstConnection = DateTime.UtcNow, + IPAddress = "127.0.0.1", + LastConnection = DateTime.UtcNow, + Level = Objects.Player.Permission.Console, + Name = "IW4MAdmin", + Masked = true, + NetworkId = "0000000000000000", + }); + + base.Seed(context); + } + + } +} diff --git a/SharedLibrary/Database/Models/EFAlias.cs b/SharedLibrary/Database/Models/EFAlias.cs new file mode 100644 index 000000000..49d035b67 --- /dev/null +++ b/SharedLibrary/Database/Models/EFAlias.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary.Database.Models +{ + public class EFAlias : SharedEntity + { + [Key] + public int AliasId { get; set; } + [Required] + public int LinkId { get; set; } + [ForeignKey("LinkId")] + public virtual EFAliasLink Link { get; set; } + [Required] + public string Name { get; set; } + [Required] + public string IP { get; set; } + [Required] + public DateTime DateAdded { get; set; } + } +} diff --git a/SharedLibrary/Database/Models/EFAliasLink.cs b/SharedLibrary/Database/Models/EFAliasLink.cs new file mode 100644 index 000000000..fcbc1f838 --- /dev/null +++ b/SharedLibrary/Database/Models/EFAliasLink.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace SharedLibrary.Database.Models +{ + public class EFAliasLink : SharedEntity + { + [Key] + public int AliasLinkId { get; set; } + public virtual ICollection Children { get; set; } + + public EFAliasLink() + { + Children = new List(); + } + } +} diff --git a/SharedLibrary/Database/Models/EFClient.cs b/SharedLibrary/Database/Models/EFClient.cs new file mode 100644 index 000000000..d8cfbfa24 --- /dev/null +++ b/SharedLibrary/Database/Models/EFClient.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary.Database.Models +{ + public class EFClient : SharedEntity + { + [Key] + public int ClientId { get; set; } + [Index(IsUnique = true)] + public string NetworkId { get; set; } + + [Required] + public string Name { get; set; } + [Required] + public Objects.Player.Permission Level { get; set; } + [Required] + public int Connections { get; set; } + [Required] + public int TotalConnectionTime { get; set; } + [Required] + public string IPAddress { get; set; } + [Required] + public DateTime FirstConnection { get; set; } + [Required] + public DateTime LastConnection { get; set; } + public bool Masked { get; set; } + [Required] + public int AliasLinkId { get; set; } + [ForeignKey("AliasLinkId")] + public virtual EFAliasLink AliasLink { get; set; } + public virtual ICollection ReceivedPenalties { get; set; } + public virtual ICollection AdministeredPenalties { get; set; } + + public EFClient() + { + ReceivedPenalties = new List(); + AdministeredPenalties = new List(); + } + } +} diff --git a/SharedLibrary/Database/Models/EFPenalty.cs b/SharedLibrary/Database/Models/EFPenalty.cs new file mode 100644 index 000000000..624594b19 --- /dev/null +++ b/SharedLibrary/Database/Models/EFPenalty.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary.Database.Models +{ + public class EFPenalty : SharedEntity + { + [Key] + public int PenaltyId { get; set; } + [Required] + public int LinkId { get; set; } + [ForeignKey("LinkId")] + public virtual EFAliasLink Link { get; set; } + [Required] + public int OffenderId { get; set; } + [ForeignKey("OffenderId")] + public virtual EFClient Offender { get; set; } + [Required] + public int PunisherId { get; set; } + [ForeignKey("PunisherId")] + public virtual EFClient Punisher { get; set; } + [Required] + public DateTime When { get; set; } + [Required] + public DateTime Expires { get; set; } + [Required] + public string Offense { get; set; } + public Objects.Penalty.PenaltyType Type { get; set; } + } +} diff --git a/SharedLibrary/Database/Models/SharedEntity.cs b/SharedLibrary/Database/Models/SharedEntity.cs new file mode 100644 index 000000000..6def65bdb --- /dev/null +++ b/SharedLibrary/Database/Models/SharedEntity.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary.Database.Models +{ + public class SharedEntity + { + public bool Active { get; set; } + } +} diff --git a/SharedLibrary/Event.cs b/SharedLibrary/Event.cs index b19dad0d0..9609d863f 100644 --- a/SharedLibrary/Event.cs +++ b/SharedLibrary/Event.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; +using SharedLibrary.Objects; + namespace SharedLibrary { [Serializable] @@ -93,7 +95,7 @@ namespace SharedLibrary public Event(GType t, string d, Player O, Player T, Server S) { Type = t; - Data = d; + Data = d.Trim(); Origin = O; Target = T; Owner = S; @@ -129,14 +131,14 @@ namespace SharedLibrary if (removeTime.Contains("ScriptKill")) { - return new Event(GType.Script, String.Join(";", line), SV.Players.FirstOrDefault(p => p != null && p.NetworkID == line[1]), SV.Players.FirstOrDefault(p => p != null && p.NetworkID == line[2]), SV); + return new Event(GType.Script, String.Join(";", line), SV.Players.FirstOrDefault(p => p != null && p.NetworkId == line[1]), SV.Players.FirstOrDefault(p => p != null && p.NetworkId == line[2]), SV); } if (removeTime.Contains("ExitLevel")) - return new Event(GType.MapEnd, line[0], new Player("WORLD", "WORLD", 0, 0), null, SV); + return new Event(GType.MapEnd, line[0], null, null, SV); if (removeTime.Contains("InitGame")) - return new Event(GType.MapChange, line[0], new Player("WORLD", "WORLD", 0, 0), null, SV); + return new Event(GType.MapChange, line[0], null, null, SV); return null; diff --git a/SharedLibrary/Exceptions/DatabaseException.cs b/SharedLibrary/Exceptions/DatabaseException.cs new file mode 100644 index 000000000..f4229a5be --- /dev/null +++ b/SharedLibrary/Exceptions/DatabaseException.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary.Exceptions +{ + public class DatabaseException : Exception + { + public DatabaseException(string msg) : base(msg) { } + } +} diff --git a/SharedLibrary/Helpers/CommandResult.cs b/SharedLibrary/Helpers/CommandResult.cs new file mode 100644 index 000000000..61c7db18f --- /dev/null +++ b/SharedLibrary/Helpers/CommandResult.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary.Helpers +{ + public class CommandResult + { + public string Message { get; set; } + public int Clientd { get; set; } + } +} diff --git a/SharedLibrary/Interfaces/IEntityService.cs b/SharedLibrary/Interfaces/IEntityService.cs new file mode 100644 index 000000000..3621e957c --- /dev/null +++ b/SharedLibrary/Interfaces/IEntityService.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary.Interfaces +{ + public interface IEntityService + { + Task CreateProxy(); + Task Create(T entity); + Task Delete(T entity); + Task Update(T entity); + Task Get(int entityID); + Task GetUnique(string entityProperty); + Task> Find(Func expression); + } +} diff --git a/SharedLibrary/Interfaces/IManager.cs b/SharedLibrary/Interfaces/IManager.cs index 943984873..99344b486 100644 --- a/SharedLibrary/Interfaces/IManager.cs +++ b/SharedLibrary/Interfaces/IManager.cs @@ -1,4 +1,7 @@ using System.Collections.Generic; +using SharedLibrary.Objects; +using SharedLibrary.Database.Models; +using SharedLibrary.Services; namespace SharedLibrary.Interfaces { @@ -10,13 +13,10 @@ namespace SharedLibrary.Interfaces ILogger GetLogger(); IList GetServers(); IList GetCommands(); - IPenaltyList GetClientPenalties(); - ClientsDB GetClientDatabase(); - AliasesDB GetAliasesDatabase(); IList GetMessageTokens(); IList GetActiveClients(); - IList GetAliasClients(Player player); - IList GetAliases(Player player); - IList GetPrivilegedClients(); + ClientService GetClientService(); + AliasService GetAliasService(); + PenaltyService GetPenaltyService(); } } diff --git a/SharedLibrary/Interfaces/IPenaltyList.cs b/SharedLibrary/Interfaces/IPenaltyList.cs deleted file mode 100644 index 3a85b9f65..000000000 --- a/SharedLibrary/Interfaces/IPenaltyList.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SharedLibrary.Interfaces -{ - public interface IPenaltyList - { - void AddPenalty(Penalty P); - void RemovePenalty(Penalty P); - List FindPenalties(Player P); - } -} diff --git a/SharedLibrary/Objects/Alias.cs b/SharedLibrary/Objects/Alias.cs new file mode 100644 index 000000000..c38554876 --- /dev/null +++ b/SharedLibrary/Objects/Alias.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary.Objects +{ + public class Alias : Database.Models.EFAlias + { + + } +} diff --git a/SharedLibrary/Objects/Penalty.cs b/SharedLibrary/Objects/Penalty.cs new file mode 100644 index 000000000..d4b69a933 --- /dev/null +++ b/SharedLibrary/Objects/Penalty.cs @@ -0,0 +1,24 @@ +using System; +using SharedLibrary; + +namespace SharedLibrary.Objects +{ + public class Penalty : Database.Models.EFPenalty + { + public enum PenaltyType + { + Report, + Warning, + Flag, + Kick, + TempBan, + Ban, + Any, + } + + public String GetWhenFormatted() + { + return When.ToString("MM/dd/yy HH:mm:ss"); ; + } + } +} diff --git a/SharedLibrary/Objects/Player.cs b/SharedLibrary/Objects/Player.cs new file mode 100644 index 000000000..a642b9bb9 --- /dev/null +++ b/SharedLibrary/Objects/Player.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Threading.Tasks; + +namespace SharedLibrary.Objects +{ + public class Player : Database.Models.EFClient + { + public enum Permission + { + Banned = -1, + User = 0, + Flagged = 1, + Trusted = 2, + Moderator = 3, + Administrator = 4, + SeniorAdmin = 5, + Owner = 6, + Creator = 7, + Console = 8, + } + + public Player() + { + ConnectionTime = DateTime.UtcNow; + } + + public override string ToString() + { + return $"{Name}::{NetworkId}"; + } + + public String GetLastConnection() + { + return Utilities.GetTimePassed(LastConnection); + } + + public async Task Tell(String Message) + { + await CurrentServer.Tell(Message, this); + } + + public async Task Kick(String Message, Player Sender) + { + await CurrentServer.Kick(Message, this, Sender); + } + + public async Task TempBan(String Message, TimeSpan Length, Player Sender) + { + await CurrentServer.TempBan(Message, Length, this, Sender); + } + + public async Task Warn(String Message, Player Sender) + { + await CurrentServer.Warn(Message, this, Sender); + } + + public async Task Ban(String Message, Player Sender) + { + await CurrentServer.Ban(Message, this, Sender); + } + + [NotMapped] + public int ClientNumber { get; set; } + [NotMapped] + public int Ping { get; set; } + [NotMapped] + public int Warnings { get; set; } + [NotMapped] + public DateTime ConnectionTime { get; set; } + [NotMapped] + public Server CurrentServer { get; set; } + } +} diff --git a/SharedLibrary/Objects/Report.cs b/SharedLibrary/Objects/Report.cs new file mode 100644 index 000000000..e1955dff1 --- /dev/null +++ b/SharedLibrary/Objects/Report.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharedLibrary.Objects +{ + public class Report + { + public Report(Player T, Player O, String R) + { + Target = T; + Origin = O; + Reason = R; + } + + public Player Target { get; private set; } + public Player Origin { get; private set; } + public String Reason { get; private set; } + } +} diff --git a/SharedLibrary/Penalty.cs b/SharedLibrary/Penalty.cs deleted file mode 100644 index e2b5627ed..000000000 --- a/SharedLibrary/Penalty.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using SharedLibrary; - -namespace SharedLibrary -{ - public class Penalty - { - public Penalty(Type BType, String Reas, String TargID, String From, DateTime time, String ip, DateTime exp) - { - Reason = Reas.StripColors(); - OffenderID = TargID; - PenaltyOriginID = From; - When = time; - Expires = exp; - IP = ip; - this.BType = BType; - } - - public String GetWhenFormatted() - { - return When.ToString("MM/dd/yy HH:mm:ss"); ; - } - - public enum Type - { - Report, - Warning, - Flag, - Kick, - TempBan, - Ban, - Any, - } - - public String Reason { get; private set; } - public String OffenderID { get; private set; } - public String PenaltyOriginID { get; private set; } - public DateTime When { get; private set; } - public DateTime Expires { get; private set; } - public String IP { get; private set; } - public Type BType { get; private set; } - } - - public class Report - { - public Report(Player T, Player O, String R) - { - Target = T; - Origin = O; - Reason = R; - } - - public Player Target { get; private set; } - public Player Origin { get; private set; } - public String Reason { get; private set; } - } -} diff --git a/SharedLibrary/Player.cs b/SharedLibrary/Player.cs deleted file mode 100644 index 9513a0856..000000000 --- a/SharedLibrary/Player.cs +++ /dev/null @@ -1,184 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace SharedLibrary -{ - public class Aliases - { - public Aliases(int Num, String N, String I) - { - Number = Num; - Names = N.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToList(); - IPS = new List(I.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); - } - - public List Names { get; private set; } - public List IPS { get; private set; } - public int Number { get; private set; } - } - - public class Player - { - public enum Permission - { - Banned = -1, - User = 0, - Flagged = 1, - Trusted = 2, - Moderator = 3, - Administrator = 4, - SeniorAdmin = 5, - Owner = 6, - Creator = 7, - Console = 8, - } - - public override int GetHashCode() - { - return base.GetHashCode(); - } - - public Player(string n, string id, int num, int l) - { - Name = n; - NetworkID = id; - ClientID = num; - Level = (Player.Permission)l; - lastOffense = String.Empty; - Connections = 0; - IP = ""; - Warnings = 0; - Alias = new Aliases(0, "", ""); - LastConnection = DateTime.Now; - - } - - public Player(string n, string id, int num, String I) - { - Name = n; - NetworkID = id; - ClientID = num; - IP = I; - LastConnection = DateTime.Now; - } - - public Player(String n, String id, Player.Permission P, String I, String UID, int dbid) - { - Name = n; - NetworkID = id; - Level = P; - IP = I; - ClientID = -1; - this.UID = UID; - DatabaseID = dbid; - } - - public Player(string n, string id, int num, Player.Permission l, int cind, String lo, int con, String IP2) - { - Name = n; - NetworkID = id; - ClientID = num; - Level = l; - DatabaseID = cind; - if (lo == null) - lastOffense = String.Empty; - else - lastOffense = lo; - Connections = con; - IP = IP2; - Warnings = 0; - Masked = false; - LastConnection = DateTime.Now; - } - - public Player(string n, string id, int num, Player.Permission l, int cind, String lo, int con, String IP2, DateTime LC, string UID, bool masked) - { - Name = n; - NetworkID = id; - ClientID = num; - Level = l; - DatabaseID = cind; - if (lo == null) - lastOffense = String.Empty; - else - lastOffense = lo; - Connections = con; - IP = IP2; - Warnings = 0; - Masked = false; - LastConnection = LC; - this.UID = UID.Trim(); - Masked = masked; - } - - public override string ToString() - { - return $"{Name}::{NetworkID}"; - } - - public String GetLastConnection() - { - return Utilities.GetTimePassed(LastConnection); - } - - public void UpdateName(String n) - { - if (n.Trim() != String.Empty) - Name = n; - } - - public void SetIP(String I) - { - IP = I; - } - - public void SetLevel(Permission Perm) - { - Level = Perm; - } - - public async Task Tell(String Message) - { - await lastEvent.Owner.Tell(Message, this); - } - - public async Task Kick(String Message, Player Sender) - { - await lastEvent.Owner.Kick(Message, this, Sender); - } - - public async Task TempBan(String Message, TimeSpan Length, Player Sender) - { - await lastEvent.Owner.TempBan(Message, Length, this, Sender); - } - - public async Task Warn(String Message, Player Sender) - { - await lastEvent.Owner.Warn(Message, this, Sender); - } - - public async Task Ban(String Message, Player Sender) - { - await lastEvent.Owner.Ban(Message, this, Sender); - } - - public String Name { get; private set; } - public string NetworkID { get; private set; } - public int ClientID { get; private set; } - public Permission Level { get; private set; } - public int DatabaseID { get; private set; } - public int Connections { get; set; } - public String IP { get; private set; } - public String UID { get; private set; } - public DateTime LastConnection { get; private set; } - public int Ping; - - public Event lastEvent; - public String lastOffense; - public int Warnings; - public Aliases Alias; - public bool Masked; - } -} diff --git a/SharedLibrary/RCON.cs b/SharedLibrary/RCON.cs index afc1c4217..138f82849 100644 --- a/SharedLibrary/RCON.cs +++ b/SharedLibrary/RCON.cs @@ -8,6 +8,8 @@ using System.Threading.Tasks; using System.Text.RegularExpressions; using System.Net.Sockets; +using SharedLibrary.Objects; + namespace SharedLibrary.Network { public static class RCON diff --git a/SharedLibrary/Server.cs b/SharedLibrary/Server.cs index b83ddb44f..2335eac31 100644 --- a/SharedLibrary/Server.cs +++ b/SharedLibrary/Server.cs @@ -9,6 +9,7 @@ using SharedLibrary.Network; using SharedLibrary.Commands; using System.Threading.Tasks; using SharedLibrary.Helpers; +using SharedLibrary.Objects; namespace SharedLibrary { @@ -106,13 +107,6 @@ namespace SharedLibrary return Players.Where(p => p != null && p.Name.ToLower().Contains(pName.ToLower())).ToList(); } - /// - /// Check ban list for every banned player and return ban if match is found - /// - /// Player to check if banned - /// Matching ban if found - abstract public Penalty IsBanned(Player C); - /// /// Process requested command correlating to an event /// @@ -126,16 +120,6 @@ namespace SharedLibrary return null; } - /// - /// Legacy method for the alias command - /// - /// - /// - public IList GetAliases(Player P) - { - return Manager.GetAliases(P); - } - /// /// Process any server event /// @@ -170,14 +154,10 @@ namespace SharedLibrary /// Player to send message to public async Task Tell(String Message, Player Target) { -#if DEBUG - //if (!Target.lastEvent.Remote) - // return; -#endif string tellCommand = (GameName == Game.IW4) ? "tellraw" : "tell"; - if (Target.ClientID > -1 && Message.Length > 0 && Target.Level != Player.Permission.Console && !Target.lastEvent.Remote) - await this.ExecuteCommandAsync($"{tellCommand} {Target.ClientID} {Message}^7"); + if (Target.ClientNumber > -1 && Message.Length > 0 && Target.Level != Player.Permission.Console) + await this.ExecuteCommandAsync($"{tellCommand} {Target.ClientNumber} {Message}^7"); if (Target.Level == Player.Permission.Console) { @@ -185,9 +165,13 @@ namespace SharedLibrary Console.WriteLine(Utilities.StripColors(Message)); Console.ForegroundColor = ConsoleColor.Gray; } - - if (Target.lastEvent.Remote) - commandResult.Enqueue(Utilities.StripColors(Message)); + if (commandResult.Count > 15) + commandResult.RemoveAt(0); + commandResult.Add(new CommandResult() + { + Message = Utilities.StripColors(Message), + Clientd = Target.ClientId + }); } /// @@ -353,14 +337,14 @@ namespace SharedLibrary return $"{IP}_{Port}"; } - protected async Task ScriptLoaded() + protected async Task ScriptLoaded() { try { return (await this.GetDvarAsync("sv_customcallbacks")).Value == "1"; } - - catch(Exceptions.DvarException) + + catch (Exceptions.DvarException) { return false; } @@ -408,6 +392,6 @@ namespace SharedLibrary protected DateTime LastPoll; //Remote - public Queue commandResult = new Queue(); + public IList commandResult = new List(); } } diff --git a/SharedLibrary/Services/AliasService.cs b/SharedLibrary/Services/AliasService.cs new file mode 100644 index 000000000..a19c17fe9 --- /dev/null +++ b/SharedLibrary/Services/AliasService.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Linq.Expressions; +using System.Data.Entity; + +using SharedLibrary.Interfaces; +using SharedLibrary.Database.Models; +using SharedLibrary.Database; + +namespace SharedLibrary.Services +{ + public class AliasService : IEntityService + { + public async Task Create(EFAlias entity) + { + using (var context = new IW4MAdminDatabaseContext()) + { + entity.Link = await context.AliasLinks.FirstAsync(a => a.AliasLinkId == entity.Link.AliasLinkId); + var addedEntity = context.Aliases.Add(entity); + await context.SaveChangesAsync(); + return addedEntity; + } + } + + public Task CreateProxy() + { + return null; + } + + public async Task Delete(EFAlias entity) + { + using (var context = new IW4MAdminDatabaseContext()) + { + entity = context.Aliases.Single(e => e.AliasId == entity.AliasId); + entity.Active = false; + context.Entry(entity).State = EntityState.Modified; + await context.SaveChangesAsync(); + return entity; + } + } + + public async Task> Find(Func expression) + { + using (var context = new IW4MAdminDatabaseContext()) + return await Task.Run(() => context.Aliases.Where(expression).ToList()); + } + + public async Task Get(int entityID) + { + using (var context = new IW4MAdminDatabaseContext()) + return await context.Aliases + .SingleOrDefaultAsync(e => e.AliasId == entityID); + } + + public Task GetUnique(string entityProperty) + { + throw new NotImplementedException(); + } + + public async Task Update(EFAlias entity) + { + using (var context = new IW4MAdminDatabaseContext()) + { + entity = context.Aliases.Attach(entity); + context.Entry(entity).State = EntityState.Modified; + await context.SaveChangesAsync(); + return entity; + } + } + + public async Task CreateLink(EFAliasLink link) + { + using (var context = new IW4MAdminDatabaseContext()) + { + context.AliasLinks.Add(link); + await context.SaveChangesAsync(); + return link; + } + } + } +} diff --git a/SharedLibrary/Services/ClientService.cs b/SharedLibrary/Services/ClientService.cs new file mode 100644 index 000000000..214fe9c99 --- /dev/null +++ b/SharedLibrary/Services/ClientService.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Data.Entity; + +using SharedLibrary.Database; +using SharedLibrary.Database.Models; +using System.Linq.Expressions; + +namespace SharedLibrary.Services +{ + public class ClientService : Interfaces.IEntityService + { + private Dictionary _context; + + public ClientService() + { + _context = new Dictionary(); + } + public async Task Create(EFClient entity) + { + using (var context = new IW4MAdminDatabaseContext()) + { + + // get all aliases by IP + var alias = await context.Aliases.FirstOrDefaultAsync(a => a.IP == entity.IPAddress); + EFAliasLink link = alias?.Link; + + var client = new EFClient() + { + Active = true, + Name = entity.Name, + FirstConnection = DateTime.UtcNow, + Connections = 1, + IPAddress = entity.IPAddress, + LastConnection = DateTime.UtcNow, + Level = Objects.Player.Permission.User, + Masked = false, + NetworkId = entity.NetworkId, + AliasLink = link ?? new EFAliasLink() { Active = true } + }; + + client.AliasLink.Children.Add(new EFAlias() + { + Active = true, + DateAdded = DateTime.UtcNow, + IP = entity.IPAddress, + Link = client.AliasLink, + Name = entity.Name + }); + + context.Clients.Add(client); + await context.SaveChangesAsync(); + + return client; + } + } + + public async Task Delete(EFClient entity) + { + using (var context = new IW4MAdminDatabaseContext()) + { + entity = context.Clients.Single(e => e.ClientId == entity.ClientId); + entity.Active = false; + entity.Level = Objects.Player.Permission.User; + context.Entry(entity).State = EntityState.Modified; + await context.SaveChangesAsync(); + return entity; + } + } + + public async Task> Find(Func e) + { + using (var context = new IW4MAdminDatabaseContext()) + return await Task.Run(() => context.Clients + .Include(c => c.AliasLink.Children) + .Where(e).ToList()); + } + + public async Task Get(int entityID) + { + using (var context = new IW4MAdminDatabaseContext()) + return await new IW4MAdminDatabaseContext().Clients + .Include(c => c.AliasLink.Children) + .SingleOrDefaultAsync(e => e.ClientId == entityID); + } + + public async Task GetUnique(string entityAttribute) + { + using (var context = new IW4MAdminDatabaseContext()) + { + return await context.Clients + .Include(c => c.AliasLink.Children) + .SingleOrDefaultAsync(c => c.NetworkId == entityAttribute); + } + } + + public async Task Update(EFClient entity) + { + using (var context = new IW4MAdminDatabaseContext()) + { + entity = context.Clients.Attach(entity); + context.Entry(entity).State = EntityState.Modified; + await context.SaveChangesAsync(); + return entity; + } + } + + #region ServiceSpecific + public async Task> GetOwners() + { + using (var context = new IW4MAdminDatabaseContext()) + return await context.Clients.Where(c => c.Level == Objects.Player.Permission.Owner).ToListAsync(); + } + + public async Task> GetPrivilegedClients() + { + using (var context = new IW4MAdminDatabaseContext()) + return await new IW4MAdminDatabaseContext().Clients + .Where(c => c.Level >= Objects.Player.Permission.Trusted) + .ToListAsync(); + } + + + public async Task> GetRecentClients(int offset, int count) + { + using (var context = new IW4MAdminDatabaseContext()) + return await context.Clients.OrderByDescending(p => p.ClientId).Skip(offset).Take(count).ToListAsync(); + } + + public async Task> PruneInactivePrivilegedClients(int inactiveDays) + { + using (var context = new IW4MAdminDatabaseContext()) + { + var inactive = await context.Clients.Where(c => c.Level > Objects.Player.Permission.Flagged) + .Where(c => (DateTime.UtcNow - c.LastConnection).TotalDays >= inactiveDays) + .ToListAsync(); + inactive.ForEach(c => c.Level = Objects.Player.Permission.User); + await context.SaveChangesAsync(); + return inactive; + } + } + + public async Task GetTotalClientsAsync() + { + using (var context = new IW4MAdminDatabaseContext()) + return await context.Clients.CountAsync(); + } + + public Task CreateProxy() + { + throw new NotImplementedException(); + } + #endregion + } +} diff --git a/SharedLibrary/Services/PenaltyService.cs b/SharedLibrary/Services/PenaltyService.cs new file mode 100644 index 000000000..d2237b36b --- /dev/null +++ b/SharedLibrary/Services/PenaltyService.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Data.Entity; + +using SharedLibrary.Database; +using SharedLibrary.Database.Models; +using System.Linq.Expressions; + +namespace SharedLibrary.Services +{ + public class PenaltyService : Interfaces.IEntityService + { + public async Task Create(EFPenalty entity) + { + using (var context = new IW4MAdminDatabaseContext()) + { + entity.Offender = context.Clients.First(e => e.ClientId == entity.Offender.ClientId); + entity.Punisher = context.Clients.First(e => e.ClientId == entity.Punisher.ClientId); + entity.Link = context.AliasLinks.First(l => l.AliasLinkId == entity.Link.AliasLinkId); + if (entity.Expires == DateTime.MinValue) + entity.Expires = DateTime.Parse(System.Data.SqlTypes.SqlDateTime.MaxValue.ToString()); + context.Penalties.Add(entity); + await context.SaveChangesAsync(); + return entity; + } + } + + public Task CreateProxy() + { + throw new NotImplementedException(); + } + + public Task Delete(EFPenalty entity) + { + throw new NotImplementedException(); + } + + public async Task> Find(Func expression) + { + using (var context = new IW4MAdminDatabaseContext()) + { + return await Task.Run(() => context.Penalties + .Include(p => p.Offender) + .Include(p => p.Punisher) + .Where(expression) + .Where(p => p.Active) + .ToList()); + } + } + + public Task Get(int entityID) + { + throw new NotImplementedException(); + } + + public Task GetUnique(string entityProperty) + { + throw new NotImplementedException(); + } + + public Task Update(EFPenalty entity) + { + throw new NotImplementedException(); + } + + public async Task> GetRecentPenalties(int count, int offset) + { + using (var context = new IW4MAdminDatabaseContext()) + return await context.Penalties + .Include(p => p.Offender) + .Include(p => p.Punisher) + .Where(p => p.Active) + .OrderByDescending(p => p.When) + .Skip(offset) + .Take(count) + .ToListAsync(); + } + + public async Task> GetClientPenaltiesAsync(int clientId) + { + using (var context = new IW4MAdminDatabaseContext()) + return await context.Penalties + .Where(p => p.OffenderId == clientId) + .Where(p => p.Active) + .Include(p => p.Offender) + .Include(p => p.Punisher) + .ToListAsync(); + } + + public async Task RemoveActivePenalties(int aliasLinkId) + { + using (var context = new IW4MAdminDatabaseContext()) + { + var now = DateTime.UtcNow; + var penalties = await context.Penalties + .Include(p => p.Link.Children) + .Where(p => p.LinkId == aliasLinkId) + .Where(p => p.Expires > now) + .ToListAsync(); + + penalties.ForEach(async p => + { + p.Active = false; + var clients = await context.Clients.Where(cl => cl.AliasLinkId == p.LinkId).ToListAsync(); + foreach (var c in clients) + if (c.Level == Objects.Player.Permission.Banned) + c.Level = Objects.Player.Permission.User; + }); + + await context.SaveChangesAsync(); + } + } + } +} diff --git a/SharedLibrary/SharedLibrary.csproj b/SharedLibrary/SharedLibrary.csproj index 77a372a3e..51b5e1f02 100644 --- a/SharedLibrary/SharedLibrary.csproj +++ b/SharedLibrary/SharedLibrary.csproj @@ -66,13 +66,24 @@ true + + ..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll + + + ..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll + + + ..\packages\EntityFramework.SqlServerCompact.6.2.0\lib\net45\EntityFramework.SqlServerCompact.dll + ..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll + False + - - ..\packages\System.Data.SQLite.Core.1.0.105.1\lib\net45\System.Data.SQLite.dll + + ..\packages\Microsoft.SqlServer.Compact.4.0.8876.1\lib\net40\System.Data.SqlServerCe.dll True @@ -83,6 +94,14 @@ + + + + + + + + @@ -90,29 +109,34 @@ + + - - + + - - + + + + + @@ -134,15 +158,12 @@ copy /Y "$(TargetDir)System.Data.SQLite.dll" "$(SolutionDir)Admin\lib" copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)BUILD\lib" copy /Y "$(TargetDir)$(TargetName).dll" "$(SolutionDir)Admin\lib" copy /Y "$(TargetDir)Newtonsoft.Json.dll" "$(SolutionDir)BUILD\lib" -copy /Y "$(TargetDir)Newtonsoft.Json.dll" "$(SolutionDir)Admin\lib" +copy /Y "$(TargetDir)Newtonsoft.Json.dll" "$(SolutionDir)Admin\lib" + if not exist "$(TargetDir)x86" md "$(TargetDir)x86" + xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\NativeBinaries\x86\*.*" "$(TargetDir)x86" + if not exist "$(TargetDir)amd64" md "$(TargetDir)amd64" + xcopy /s /y "$(SolutionDir)packages\Microsoft.SqlServer.Compact.4.0.8876.1\NativeBinaries\amd64\*.*" "$(TargetDir)amd64" - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - if exist "$(SolutionDir)BUILD\Plugins" rmdir /Q /S "$(SolutionDir)BUILD\Plugins" mkdir "$(SolutionDir)BUILD\Plugins" diff --git a/SharedLibrary/Utilities.cs b/SharedLibrary/Utilities.cs index 8df15c780..9dddeb6c4 100644 --- a/SharedLibrary/Utilities.cs +++ b/SharedLibrary/Utilities.cs @@ -4,6 +4,8 @@ using System.Text; using System.Text.RegularExpressions; using System.Linq; using System.Collections.Generic; + +using SharedLibrary.Objects; using static SharedLibrary.Server; namespace SharedLibrary @@ -60,7 +62,7 @@ namespace SharedLibrary int.TryParse(playerInfo[0], out cID); var regex = Regex.Match(responseLine, @"\d+\.\d+\.\d+.\d+\:\d{1,5}"); string cIP = regex.Value.Split(':')[0]; - Player P = new Player(cName, npID, cID, cIP) { Ping = Ping }; + Player P = new Player() { Name = cName, NetworkId = npID, ClientNumber = cID, IPAddress = cIP, Ping = Ping }; StatusPlayers.Add(P); } } @@ -224,7 +226,7 @@ namespace SharedLibrary } if (Elapsed.TotalDays <= 365) { - if (Elapsed.TotalDays < 1.5) + if (Elapsed.TotalDays < 1.5) return $"1 day{ago}"; return Math.Round(Elapsed.TotalDays, 0) + $" days{ago}"; } @@ -297,5 +299,26 @@ namespace SharedLibrary { return markdownString.Replace("<", "\\<").Replace(">", "\\>").Replace("|", "\\|"); } + + public static Player AsPlayer(this Database.Models.EFClient client) + { + return client == null ? null : new Player() + { + Active = client.Active, + AliasLink =client.AliasLink, + AliasLinkId = client.AliasLinkId, + ClientId = client.ClientId, + ClientNumber = 0, + FirstConnection = client.FirstConnection, + Connections = client.Connections, + IPAddress = client.IPAddress, + NetworkId = client.NetworkId, + Name = client.Name, + Level = client.Level, + TotalConnectionTime = client.TotalConnectionTime, + Masked = client.Masked, + LastConnection = DateTime.UtcNow + }; + } } } diff --git a/SharedLibrary/WebService.cs b/SharedLibrary/WebService.cs index 0f9d36a0a..7b1bcc126 100644 --- a/SharedLibrary/WebService.cs +++ b/SharedLibrary/WebService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading.Tasks; namespace SharedLibrary { @@ -27,7 +28,7 @@ namespace SharedLibrary { string GetPath(); string GetName(); - HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers); + Task GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers); bool Visible(); } @@ -89,7 +90,7 @@ namespace SharedLibrary abstract public string GetContent(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers); - public HttpResponse GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) + public async Task GetPage(System.Collections.Specialized.NameValueCollection querySet, IDictionary headers) { HttpResponse resp = new HttpResponse() { diff --git a/SharedLibrary/packages.config b/SharedLibrary/packages.config index 9c77c3fa3..975fcdfe8 100644 --- a/SharedLibrary/packages.config +++ b/SharedLibrary/packages.config @@ -1,5 +1,7 @@  + + + - \ No newline at end of file