From 23eb641113e3f198a5f5aaefd00bb71c262e1aa2 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sat, 25 Nov 2017 19:29:58 -0600 Subject: [PATCH] Moved from SQLITE to EntityFramework. Lots of things are broken! --- Admin/Application.csproj | 12 +- Admin/IW4MAdmin.exe.config | 30 +- Admin/Main.cs | 11 +- Admin/Manager.cs | 92 +-- Admin/PenaltyList.cs | 36 - Admin/Server.cs | 350 ++++----- Admin/WebService.cs | 155 ++-- Admin/lib/SharedLibrary.dll | Bin 117760 -> 136704 bytes Admin/lib/System.Data.SQLite.dll | Bin 320000 -> 0 bytes Admin/webfront/admins.html | 2 +- Admin/webfront/console.html | 119 ++- Database/Database.csproj | 90 +++ Database/IW4MAdminDatabase.cs | 38 + Database/IW4MAdminDatabaseContext.cs | 27 + Database/Models/Alias.cs | 18 + Database/Models/Client.cs | 43 + Database/Models/Penalty.cs | 23 + Database/Properties/AssemblyInfo.cs | 36 + Database/packages.config | 6 + IW4MAdmin.sln | 78 +- Plugins/EventAPI/Plugin.cs | 6 +- Plugins/FastRestart/Plugin.cs | 1 + Plugins/MessageBoard/Rank.cs | 8 +- Plugins/MessageBoard/Storage.cs | 2 +- Plugins/SimpleStats/Chat/ChatDatabase.cs | 2 +- Plugins/SimpleStats/Chat/ChatHistoryPage.cs | 4 +- Plugins/SimpleStats/Plugin.cs | 62 +- Plugins/Tests/Plugin.cs | 31 +- Plugins/VoteMap/Plugin.cs | 11 +- Plugins/Welcome/Plugin.cs | 32 +- SharedLibrary/Command.cs | 2 + SharedLibrary/Commands/NativeCommands.cs | 145 ++-- SharedLibrary/Database.cs | 735 ------------------ .../Database/IW4MAdminDatabaseContext.cs | 49 ++ SharedLibrary/Database/Initializer.cs | 32 + SharedLibrary/Database/Models/EFAlias.cs | 26 + SharedLibrary/Database/Models/EFAliasLink.cs | 17 + SharedLibrary/Database/Models/EFClient.cs | 46 ++ SharedLibrary/Database/Models/EFPenalty.cs | 35 + SharedLibrary/Database/Models/SharedEntity.cs | 13 + SharedLibrary/Event.cs | 10 +- SharedLibrary/Exceptions/DatabaseException.cs | 13 + SharedLibrary/Helpers/CommandResult.cs | 14 + SharedLibrary/Interfaces/IEntityService.cs | 20 + SharedLibrary/Interfaces/IManager.cs | 12 +- SharedLibrary/Interfaces/IPenaltyList.cs | 15 - SharedLibrary/Objects/Alias.cs | 13 + SharedLibrary/Objects/Penalty.cs | 24 + SharedLibrary/Objects/Player.cs | 76 ++ SharedLibrary/Objects/Report.cs | 22 + SharedLibrary/Penalty.cs | 57 -- SharedLibrary/Player.cs | 184 ----- SharedLibrary/RCON.cs | 2 + SharedLibrary/Server.cs | 44 +- SharedLibrary/Services/AliasService.cs | 84 ++ SharedLibrary/Services/ClientService.cs | 158 ++++ SharedLibrary/Services/PenaltyService.cs | 117 +++ SharedLibrary/SharedLibrary.csproj | 49 +- SharedLibrary/Utilities.cs | 27 +- SharedLibrary/WebService.cs | 5 +- SharedLibrary/packages.config | 4 +- 61 files changed, 1690 insertions(+), 1685 deletions(-) delete mode 100644 Admin/PenaltyList.cs delete mode 100644 Admin/lib/System.Data.SQLite.dll create mode 100644 Database/Database.csproj create mode 100644 Database/IW4MAdminDatabase.cs create mode 100644 Database/IW4MAdminDatabaseContext.cs create mode 100644 Database/Models/Alias.cs create mode 100644 Database/Models/Client.cs create mode 100644 Database/Models/Penalty.cs create mode 100644 Database/Properties/AssemblyInfo.cs create mode 100644 Database/packages.config delete mode 100644 SharedLibrary/Database.cs create mode 100644 SharedLibrary/Database/IW4MAdminDatabaseContext.cs create mode 100644 SharedLibrary/Database/Initializer.cs create mode 100644 SharedLibrary/Database/Models/EFAlias.cs create mode 100644 SharedLibrary/Database/Models/EFAliasLink.cs create mode 100644 SharedLibrary/Database/Models/EFClient.cs create mode 100644 SharedLibrary/Database/Models/EFPenalty.cs create mode 100644 SharedLibrary/Database/Models/SharedEntity.cs create mode 100644 SharedLibrary/Exceptions/DatabaseException.cs create mode 100644 SharedLibrary/Helpers/CommandResult.cs create mode 100644 SharedLibrary/Interfaces/IEntityService.cs delete mode 100644 SharedLibrary/Interfaces/IPenaltyList.cs create mode 100644 SharedLibrary/Objects/Alias.cs create mode 100644 SharedLibrary/Objects/Penalty.cs create mode 100644 SharedLibrary/Objects/Player.cs create mode 100644 SharedLibrary/Objects/Report.cs delete mode 100644 SharedLibrary/Penalty.cs delete mode 100644 SharedLibrary/Player.cs create mode 100644 SharedLibrary/Services/AliasService.cs create mode 100644 SharedLibrary/Services/ClientService.cs create mode 100644 SharedLibrary/Services/PenaltyService.cs 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 116e0d22661c847247d5490d4f068c859a1ec4a5..c6107f87fa9615f6d30c04a756a70b6fe8bd8383 100644 GIT binary patch literal 136704 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 _RT#(ps5y)@|NW@(fBtVA!XU*z{?q&YnlX*I zha9AZ!_w+e{J4J!_{`#!Jv#vv zw)o~Qj1nD3If5^Q;L9qO^sSC)$A5X5^C3G2If64g+%czEzZv-VnpVtv3}f;2SbS;J za*S^7#ZBSc%CH|4JjeS~W4jvH2c*vs=)sp_@H;~Kx~?1b(-qrmHevX9&=2rgmw);9 I{~rea54lvZ;Q#;t literal 117760 zcmeGFcYs_~*$0lFxifR8Y{|~f&TLI~Q+9Kc*$oMyOcF{6gx;hk^w3Ml4R>i~a$|y2 z=@t+K#Q-Ysq9{m_UR9a`DpC>%q7?B(iYS81_w#wqZ8JLo^!4}q{__p&DbG3QIZr#! zDfiqvyX<$7iYuiO`1|A&rEW*ee{&`L^k5~5n|puOtZvCXG5+@0&QFZr>*!;K`<6QP zQO=^{`wm;QWQl!Z-=RnJIVUaYJ7!7WHoNWFcf5W05!0HQvXea2yU$l@=U7}lxJhn5 zzqgmwguaH@bfq4ODP?Ntt*;>6$F#wqMbb!;ZvOMCfp7q&iUMDUoWZL6Ka9OBLHKt# z@a`rlL;Zt-sQuSxs7AmB*Tqy%ZP};g`;(Np5=0%!G@|%<^{*g9ACDqY? zf!N`73nE)gK z0F_KoS5zI=Y6J(DI#{pB`7+*2+9?^?9UB@JQ*G7-EMwwb(74F#Cs6 z1I6>fzF`d#M0%V2z9azvG@?6~M1H!d=6iiQz`WG3CZVabog_<0t~e77`iI&FR-A#v zi23c9GKZnUZ2wA@SWr;O>PFtexXQB2F@6t{_@QA5nzO3We1~Yp3L2JJP-}^eVJMnB zNdS=Z0g?cq)dxsoS*SF(4JAgxh3*oDy@5!8_6FiOjB?7^iCk4!&FV$h!w_vYTTAp*;mrHdRbT^9_bI4dgc_hf<=6QqnmI z*qer-@@zhpOQmhdG^=tc=X}7s&WCJb{l(1c{`UCl{tk0>e`jhnZ6Iq8>3aD@6(ead zlGco5R4!qox2$F$V?l7)L@r}bXY&~d1{CTBjHIg=fp@ewL>(fT$+~HKBWBz4*|m1Q zK^YZl!&w6=?FOja2OzyP*I;jqx}pj@8!4Q{!i2p^-NOA*7}23_SVVU!mz}C&kSaAk zYcB=sWBOG!Yivx?N)5$&c8J;IAS~+p>+~(5zEv{RbW^FXHLm58z-U+{1mzN9;v%4| zLb=G~StvJNC6ij^YGpQv^7>O+bN$Yxz!^8kB&oN5ydQ1<++e&8o z-%+MotEOr_wyB}5d_7*N%D>fV*j%i0e9ZCncpdbZjOZ~kVw*}EhkEQje>)i_7#{7p z1jdQeYpA6dE6jAsSYB<-hB!jyKJb52ZhW+IBgB1{auffFa=k7^x$)0bZhJnpc1b?% ztG6HW7_Hv)deploYX4h`EuuI0EI2W5oVKZX`}q3(i7LP8>vwFdyBu3W{nCGTp}tA| z8p51u&w-AL_GZ+SDGLTTR?MA`p&oo}P8G9p=L8TZ9^Bp>^_)|xvMn)hOtv*D&*)Rb zTcBQl+#7^?3}n4AU^cBCh6nYW8P+0oq?A~Xl<3USO*pA3#p|Vz~#abqDbrWQQ1(+`rPrY%^ z+xkk53qy@?N5W8AGZZ+wW1D;x*X1YkDH@Ld+w3I3PGYLoZ&6uWsAGLzehyx;qj>og zQ>~|^fT>geFIxH!3|EXYpIn;^G^TlMQJZe3P9=}ijCjJrx&&hyYhFWP{h%7iuQ#o4 z4fcy8v8*{bPB}wywY0%VSy)w=1I|~IksS9E-P4=YIq?5jNkjMBpk>x@9yT!)&f6Vb zCE^Pt))O~oTC*WF*pdZQ0>C$YfVDHw0PsB@ zAm{r`)0nWifNwxrIBQavG=Gq-}U<<$!3ybCwcZH>V3P!E{dkfcI zyQ%l)#R?QG^>h?O+!X4``2h69W$V!3w5HY4l&l0BjWm6j*_0V<$mGYHk)+);!r7W{nS!S)W%vxocwaPMUl|`Crlx2P{ zWr0J{Rx7nt%q6wD(z!I$l@8RE&p->_++nCa)!(*{71yVO!y)&$h1FB3!8!f^)4}H$ zF#lH_G^!5RFE-!sch2(=xfqmoSHpY3nyrmt{cwIQdZ80>Qw^zEzo#OjE1*V|uCZ?m zP9@u<);0|2A%G<6RJ)~gt)ZuD>^xm#=II(MPlrY>J}X^gZ~Q1=T7{O@`9wTS_>Hs(9|hNzRrDFVDk%JUj&8^^Yob&Wi| z$t;y#@s(Hvn{;1Qxk|jL+^L&0Lmnqr@q9mU!W!n%ykvLT0ZXA<|9JcPKo}Cd( zP?v_gr)2Q*%@8Sit5_Cg#tw|HS{n{$)n~Z`wcS z${#^4m_m6*%9Eh1skbN2n{XK3!roia&&$At?1~^Rp`1qP{XAApI6^TSWm(je9&Ab1 zolfU+j9^vIU6qUuOs8?cYNpdRY!gS#rQ&OFAXPhkq3+so11gtp8;Rv%AcHAq50IEo z>lIWAE-8aXHN)z^J^kv{RNd*fX8Dw^zc})J{W~Mk`8J!&V&r7Kk(0?c(BiQV%{5F_ zTVb8bf9K;5`zv)9{$Tg~gY7GYm6s|)xaZ+dCS~OF(=+OKh;fLAv&VfPr!Ku{;Ru!zIJ=X;$`!x)|7P!&09F`mK8i6Rzz0t(zrMh7xy>$*H|SR z)*`e3n(B(yp@3e?@_f?FaoN3LHKN0GtLg~?)#g@J^T-Rg5HgYgtuf4mvrkn!sWuE@ znD*i5C|JM0Obhkb?;LPxoZ#y9yXkx5t>BAkgE*&ElYwGC{K?`RdFtnD$m6uu*N@>G ziLU*#`(YN;Itna|Q)TCe6C zWm-<_#eDU&Z06JOD`|ZWWT=Yz=wyFCl~yl9R&Am$+4nl*8`RQ{P%Y~jNvES#)kyjr zn^xH6s6Fc_L#^4-M0T~ZMYWEAZiY{!<;u>}+jyQ3U6W9!X*gZqa7{38${C4)Gq6h@ z)aJ@F1Dp{s!!`8Rz_yrDwtB$~k2x;7Qm%1Zjip4fv7{i|{Pcu+6!_qeVf#md%zp8S zaeEc1J&NP3U%aCBRz8FxiQ8wPjtJccbMLNC9=(>_ySG)ReN$usMR%c zqEnCCIM}GsKX%FigdRO^ry>x|c~b;J=QUcdoKoU8_A};roJo9n($&Z927+PRF%5=Z zk8iBet08L#JTJ$3;S?0c<>Z7*g^;H>WubJPds#<6y^2)gIGThy=&;V&TZ?igHdURr zahza8@cBLZeF%km*BW%rd3!zUl)>$47b(?eUKwXlZR- zlmowXX;&P0ZHIa%_JKESF_Ku>*2ursrch)3^4D|m&~=c%HxpMc^PwSsjnDIJL%pu{ z-&&um(f43-tC~MZO5C;?m zg*BrBNX$ZWaToh4b^^;mC+-ABz&}yqqzjjrz;g*xbz!lLesaUt;Orx78tyeH0e=<7 z7%*qhxH-_QrNG>fD%vL??%io5hUW=i1ygF+0ia1YxZs%H42BywVY5|l20Np^j4sI~ zFBiSb6McIaO$Ktw_669bB>kp(S2OgairdeE0z4hz$Qaz9cT7eWS8-jj$HsQh^fDbf zGrSO>e7d{~JVZddu3o%cwmqE-Z7j>Oympp#t_4%_kU+NWyDH~K0Jx#U@lGzQ+jU*8 z{maROHgx40PUY5TZF{;U6(};JrcMexT^YC&6u0@zpVPv}i*eeJfKz1sm zLEDG%DVQ(jue#NY3MkhN$5f2yc zO{RT10C}_g4Ky-S_8G{bX#%DUtB=EmVY5RI#M>7(mbz8CeL-V7jUjAo3hW8 z7M>)Cy}zLidvfe&hklhtJJhCE#zJ5BRGJo-I~`3Xuw{zz^g>*yI*UlmVn%X+Yd|Ki zHxuwcXQP5#C6vUrp$@Hc*mUZV5y+9?gcl!=X3YC(B`S{>6D0uvZdqx7B=XZ^a(7eK zU50fOngz0icaVP(^l%(RAE;@Lr=}I(6HVjN-L*)Jn7HC%4u6FLS;-RKxGeGVWXZyW zPKP@R!|=JNO<$8|1}EeDBkN)o{tQSAhC$4 zQ+Z8D)TfgodC}KAw4VTd4PWog=Rbuo&A59DBkMw%=*>(P+@CP2Fw@W)!;%7StYj`{ zo|N&y2KB!K@J%E>Je-pC!JTXtckf`7aDT=~qrIKUf_odI3NspQgP>*JM=N-D2i{4< zdy|Lv0k(^~_cBVj_c2Pk_cPMy?_sjw-p#1Oj7Hxm=$Y5(eVVZv$_?M_;r<01#ob33 zCETAg(nud>vfw_%sKSg!+9XJsucDc<7$DwTJ-kn{UEF<~QNn$Kk;eNNlLhxtMipi> z-e$qeyv7TUG#wdnwUPi}h7XVg02}%MNdPd@2S@?{?1wcDNdU0150C@^oA>}p0I;bK zkOTl_A0P>>dk9MY8N;ytta|{e1a2TvIT%^%H!xrL_R4|CxO=cdqH++^domrjV0|bz zESR5Zw?J$b?1L>V7!cy#*7IAiTpj)zI`I_!~?=sMD7)4T}(jmm)K~ zoCtp`kfOT}d$j*Ya@G%Zbfb=b#E9#N=)6@Sxxu)E9jQL(7SldS_uz2_wW!Ggx1Iu) z6~9NJ+!A>fi4hamsmEK!8$uAzqf8Vws!CjG2R{I zS}Ld7wAbNyX$1_!o#zYGQ{3((y>ew-#wvYEiG18Ad>HOpFaWz>!$=$ai%b^W7Z_ET z(FPCQ!ly9r4+MJ+e-bWkIIYhj8 z=R|zfpV=<%zR5@EU~q&EoDmj5NN#GFfon zW>jHD!y7|Z^Pf> z*nn#`ahVMB4HZ7P^o$B5CG9y|_vlqRlm7i4mY%kxQ?MqrJzwKej< zM4y~+2Q~!<)YwLGKFZQGRX-TM5K3T*{c{7}+n3v<;H`?Y>GRY1$;<5mSY!-(`JelFL zz1gUcI24>AJVFEuD4$#sJl^FASLWWcLCJ<8PuATOyE8xc8T#1L*T-O>51$4(xN0`6 zyC~$OPk^`Cpp2ggWqcI+(K7aFf?Ee}JvB%|WFP1H!dt8S9BmA7gxc-t)8roT=?#C; z)g08H3BHDZ<=O2=z-n6GK{fZEOcvY^8C96k23rt=W#0NOs&P{>7a5u9BmuxyK0p!x zV7%!Xk^o?9A0P<;w($Xy0ARikkOTnR`T$7)u$>Q(1OVIn07(F_gAb4d06Y2sNdT~u z50C@^JNp1h@SUcOA)`Lgy`CqYLygEhaTg>fPP>04ODu8SMF>gc42-+@7$pI~u0B8# z0PN-iBmuzgK0p!xe8C4ug5xZz>t{vRa0LlNrsx`7PcW>jY2O&2^nDzs8<8Jbfo4m2 z?|msbzsVZy3tKR4uDrwr{FG{hdFRsz>iY<=y@xx+(|WI&GY93? z4_MNG*M(Rm=+N`W#mjM&l*wgtsa)gmFq}buF73{OD)UWduF1RQs!tmrmn~cHywS`z zs*NR5M(A+MpQ z3nFFO6xP7r^Ax?q(~4~<`~NQ5l%@ZySy(tfjjVw`x)%5f z1tV9BB7abXDjn>c3v`9^NTPMU;5*p4n8J*Lc6KfWs3!`VflVj~n9mx1gj(8CaO7g&Aaop=(g*XiaqitX{4_>)6CUY{b`u$$=ty%h zn(fkWzqy}q;AKY4XXptqb7y%}TcVNk^oI{9a`9XOPJTy}c~3R)I0=J2JM`7Hg;c#K z=eWtCpPYjVjz^r%J7q zq4Qv>D%IDT*<;SeyQTWhc<`0>jmM_?4oL51&RK@>1+5Bj&eq73F9ViT-|~*Zp*c&S zQWoBPY~SoT6TA%3%)yIbs?0}?slJPs?7IWe9oDtSwsR(Xl?a^kWn{`bN~NRbKDGOt zgS^6xf8BH799}3QZW1_$r`F{@srjw9i?@=>*RQ?v2%??+LeJrIzCrUrWdi5e>>DpT zAb-==t*6fE^Ds@H`t8f+Z0==XS2v!T>gzPWaqFCUUZorV@!rdG zKJaj}#vE9sDqkus?z{1$*MpjsM~;4L8qU#Decihp|L&YGk%XnFW;##6n&j+xHqN_L zd4B;u69B(M;I;yMApm}Zz!?JkV*ostz#akqB>=7>FeSkE0wC`smET2RIv)kVV+mX% zzUQGiTqi&~0NzjF z;{yCr0K|Ssm2X4fTnJcW`6ec>l_Wic^ROf@XYwUUUdUvujdf3FvYpA&a%V{56P+z3 zUhFKA_;BZZi4Sn@m3S}bj}q_fyd&{8PO`xEn>pYgqeu36O@6u2Zv6=o3w=dg(c0jwb4tz}4Y|>q zjpNl_>?W4t)!jb=Ujt5&uvE@Y1Rng`V(v&HelRAJ2Ip;*HkEe(4pjMJSmhv8kyZL0 zH3k3J5(QiULH1CHb1DMJ1d=pNlAd^Tt=U-^ zplK@2^lC-BIW8#ox@mUY0HhZ@oL7$pk(-GRcdkXT%-=XFOmsAq_A;CseGsSg_J-0{ zhI5+_!gear)liydIQRM>QAMJ=q10(OPX$1#A<@}@t3<(kp1_k~r8d|7K8KpJe8GnE zCy)cg4BTVd@gVAEWb=tKwlA1DIXmi5Z*LabCjf%&DGTtfI3vGg3er4`$TniLmP_^? zy>Sb|!>7&0e23h$fzrW~e{kRFf#G!T1_GhU;) zy#~$m&_QjZ8ZQh##&hUpKm3pKp$raakdiLO?ZL zbl4$Xq<1ds58nx1eRx6^=35btJwl;?wPkAzZ#3Hf0y*yCK#Z(~S=e+B)0u?*F>^;E zm&$q@Lbzya~;RNsy!^WXVw(o2lklFVj1-B3a?j;~@e;tUd`;d;?-#~Ksek2=Y z&)A6j$grSZ4)%_P?VA{-9;cy$7fqf)MSb_H5k@ft7$-g}!G$^O8Ko)v0qHM;V-x#9 zBnSFbAMUUpfe9pU$|VLI1z}5MKZHWe6DjLqB=CmdBZ%~d%>Fr&`tkw@{{=GGHfj#+ zUn0k`gJ-uxx108($l^6YS1)ZmqY2ItP8hVvnk zecUWrj{zt4oEoXWMa-q2@;9ZJSn^G4m*<(p7oWN}f( zTIT)ZRl!R-=M(Sq9^Njti@SI?69|6~0$iMw6CvJq143pr!Y)C`yam7O)5*>5w#0{J zx6p|dED&Ldnss}bEV$zsRhZF;x&;yQ)*3;?`-#ATH;gbgt+jv|_Dcw}IIr#4U#uA? z9;Kq0z8E+CF(IT=>5l!8yF%_Fpq96vUyF&A;|MbB22LAV+Fo$J3~cr~1lB7EoC{$E za_HlHm#IJKzUYW~y4r=qgBEb(+=xQ`nUZ$ATEo2`x*C2JwHt6wY~qqzX)Ml6QK7A9UE3%jeoo1V+Q11SPLHhP~!T%ymFA{4UYI$L5fB zF;@hkUWE!P+wY^ur)>y*NaInqD#N0;t%DK)X1Lkdn%^s!sYTerux)TswNW zJ|r%~{wE^S`UoM!GOj^6I}oLSy${5Mc)jl)#8gM88t3Dj8Q_ecXJP1B8gYQL)5kd) zo%fv#!6!6wUWX#R^^Qz6GJ#LUgVzm2b5oi8Sg4)4#Bk0BvCgFoeu|){*k+A|EsMbE zM`6xtC-6Ir@2tT;#oc~bnZhH-KOjH+FQBnT5Xde7*zO>rhZ(@(FD-`Hd>_9valISt--wE6FoiSd|q01X!RAENDJdgw*&%E!9`3~g*(8hm;lSF6E7zSTJ(9zx@9|P+z z4ny*0zq2=hHXORC`rB=|PgCL59k1-L(Ph2_e461Ga>K8AG{ZbdGiGX^=0PS4Zi!Ka z8BH^^3!0ga(!7}_88n|ja?fD!FoKTu_Rplbmabh%*P9+)GueII-H?%fZa9O_P;O7-AMCaJep^bw76Slq-oxi$%2bRBhbu@rnygO zWDr9Rf;)#%g&9rP zc%h5=C|xH8I^Lfo9mn8*NmqO4XX-ex%lAjq+~4u}ZT1V~=RJ=f9L$j)99jDOz_pT} zxr{2zXnrOLKg>t@32g%|YpFB903S42+WlW1XM2$54?LQ2=0}=wKIGH9J(C4@J4O{| zG|dx*X6Bl3f9{fRQ}?#D>?wUEhzi^UWAVn+8hAbl}kU*5;E zPb^=SI{$;9SUVPP0??Cp(euT%V{sqSWf*!rd^o$0yN5B-bREiM!Cl0t!i=VCve3nR zAcOlz#qSwp`_?0aec4yi>&qd^xO)O4-Pckk3$D$m!i??A}gM7oE^Zvie6t|CCa#aF(b{_MNAgl3mH|I(S2dn z3K=pV)qCjI{=q(RuXCw09YI&^IAif===MO;)#=f78M}|W-(;lex|GR+dkLcoGn%ex zLKpM(>Dq`SZNXqkJ-X_w#cId@L8J>$v1C8|U3MRLuVSR>`VNx?7Y~|17c-i!4TLV{ z>(k|sq|+EY^dHi7FzLdl6NRqp*?ru-j*+J82TT^+?=z|}qv@J1bTJ>;%%h~@cMSfC zpsvjv!oIL&mcDKy%D8(gBi+|enJl=sFsd-4`W_(IfXugM}#ofCZX`1h1vf$pysKSh%^L~L%-5%R0F*i#F*qH;zopa9vG+NgG-Dqqa(IA861M{oTUsNK+yRg?Ej7;U7LAyy~6I}?m9-Au9ulCxGyoPFr(=z3ti0D zr|TCa={F4UA)Eh*E*!$-hPU+SdXwG9-8UF%x?X3p;J(JF!i=VCme9p~eY&QC8fPO0 zO!d^xcae3azsIkgS8ybh8=mLU^*44Oci(5E>3WaJg8MF`3NxCn*+Lidfz2!?70Vg? z4}!XDy<^$ee6KGYceAfgh*|eF!eqhy7o!R@y01CX7xO`1H?f0hpM>oNuJ*gfGu!SiW_$mP3K`rps<5f|Ov>OHpF&;#PCOBWgyQo9&2Q7qnnfiF^ppF0hdN}ZD zhW_+B_?E#o4l1j);|K6~>sFjeIh&zepM)C2@vs74+{K9k@bW$v-o{s56V!OfDYi@r zPNTwNdGcyhh?I}GcxjV#fMorCHcmP%UhE}_ax55^P|kF%BpPIm3c1i=(>4LZH`ICt zAjuFeUkUNccqprBimCD}g>?l^$F1@KRyYgBtHtvTb` zI?g)|3MVkMA+kLt#;>7dDMIfvs$EqDD3@NdD&aK|u~p2~^jCP+ZjQ+)wT;?RhIzXm+?$zNm*k!wsos3CGSDg@hY zz!yF}pzJaV>wEcLfse{6pii*phFp+lV*>T%yIiKwz`o! zWJz)EkVGxy?v-Rt-t)k&SiueFjKL{=4`11{ikGR|jFgSBlr_GXfk?7 zG$uiiu_g$-tr~1iBs7?#QtGsGR0sVNogbfX-vz!-7QSvnZysO!gReW0jq-H|@)~MX zeugyP4yel=@qjxZ7Vd6GEZlA3bH@^J$0))bo7He9n3fYk6?Y-n<4(`NDRuURnm69B zc>sK!B7EJA_8wo0z!wUt__`N)qjH~wEHf(iBecJ_9`1+@+&#z$y1NIlaJQw;9ZSF+ zqX>6wR>PfO5(HJ;h2T-TyWkr>e_C&+3V#m)bwqE!KsKtkN02uvgc_BfBeZ|89?pmd zoc)p!IC~hea5mTHj3wZVQG_!#tKm#A34$ulLhyR^rul;N#W;Huh$DPGiENaw$B{QG zgc_A65b~O2U3(-R@bxQ3;OjBO!q-+lUn~J%j3RuoSq)!;Nf1==6@u5p*RC$E$E zMUl10TadZgF)bxuc7Z3|4Gz_P2?e^?IS_fHq5*4IzXzzfGB@ph&_Ta7fY|d}>;aN| znGq!UB4Ux`JYSM5fg~A?6gGf^5x>P|Kr|VM20Xtdm;^zUBt!5h+h2X1Z~IAw`2t@< zB+u)BT6j*Dp+2nhjLIJY3fMkgPavm|?LVQwsJx1h?+coR88eK^ADFYib8*H*uk0+8 zjhj}`Ic;$LsD*_Qw1SUtV|IZTVK2^EBE1^Ca-&0ImW5X+%|^I*k>=Ji3y^ladHEWn zCS&<4h+7SOvv_Mta}B&Bx?v$C%_t&JwgfH_Xq0O2?$HF*+hAFcHV}|O{ljfj2pFs3 zD4-ld?&SJlk7lcK0E!|l?Wt_JwkvOPY7wf1*qj-iazc2ZI<*z7iT_ggJ1T~KD*n2V z=KRAsbz9_@iymJ`m!9onnuiwuOuC=qh%TXb_bp@<=iFrZ%Ro@R9)V#jC)gTfg}<ryNo8tT_)&lL^UMG$hiN@D4#Io z1?bjzYr@(_bc2NkFtZeTV-#^4YzkyDNh_mG2=fRX0->|FUc z(Zk!I-qXWwU=aus&edY&?;t7L>(HKSyaU_9JG{pTHv3n^;vMGu-hn0X4vZqk%w{#- zK`;q|D(?`2Yy9l;FZ;eBuCVY@D}BhyV=zgAo|| z8)9K-Tc078fFVW^hS;ozA;BaFsu&8vfeO8|gp^u!cF5B@@bo3&=|kZ5c!Cb~B6K@2 z_YvUE%}|uJ9f-51!P4k$Hb6Y2y$xH!+l(-R)&3K)c$@9TqEAB)Muml7l+j3GL*IQ% zOCX!UarQCW8x=;C4GH)c0TqVfSF{_}_6?|F11vZ}3l;>@BYs3}CK{==g=#o{;f3I- zphDk~ZBgI4L7C&loKx!hAFHl$D01TVS2;E5Df1KbDM?wqvn_wutsMhkrO0Yyp!8(5 ztLnhFK9I);J`nPp%d~c&q&Umf_+_?(q-HUKq-G-)N$n_-!b}cHu@I7C6w$o2^c=Ih z8QUAYCzItRnk;;QfGW&fa7^b&%)cwTCHCRZ$siNrdNCah!>O6>7Hn2wsBa|W4l!nH zR?^pvb=flXLY(cF2Rri#-pyxsOTobKf@8XMkGv?p-X7;leTM7nk!9?WIPn?0@gOOD zuhrd(?R8;#F*Hu#*GN3 z>R2wgr}@sv>F3H zdEq76H*h`iG0LM>|4+s&norzMJOYjpQ+PDMp%kcMtD=&Y@e1YWy@zn zd}UYz9UKrwQNZ?1dn+K5#nr4EP{*${0dBa*#&R6TX}TF9&b|Rne7CU{NQ8 z%`@6@#3F>{64jJ(Jtvf{-CL8zC1E|f65iR2w{jC?a$&c6`#}B&;xF_` zadjQ?XNbEi>Meui zI$V)K`4G8BlkkJpkzUBxDpW{;LaS(@LWLG8lqFPXJxXd6D#+wEbG1T4c({&>>U0?T zS%$x;PO>u+J=1Q5Lu*}o*(;njVFh8*b^An?ps@M#OWF&gKdch>O zs;lOw5L`1q-S=~UjcclPhEivVJg`oKJmx1T3jA@RZp2>>f2FqaZxEF^NXpMJSimay zN*mgErZ369TGJQkgwXVZ2A=7|?tch;J}Qc>H{;C99enH;OsQW!7q8S>Q&IWm#4YP zvUI&8o>(#Bw`2s1!?r|^_`UoQ&k~GyMiEnFvzievm;^!9h!4R5)BYL#C0F`mKB2w| zzA@W?PwXl<=Ht{q{`@gt8dJ`~D9c}E(7_Vf6Zk`Y9$Hn%ZgiH5)R1Yy#dd-VGDg+!(}hVza{HNYvR zFR!P%JE5Oa-)GhE=$Syo+QI`|p@n}RJouE$6p1Z+KzjtkXy)onku}y&5yJYh?bFu3 zJrZL5`-t_g6YFOwte;WD`q?zJ{(x?LpAH2Pvh0=XGk576=3d=9&0Y6?SkODoyp27 zjIVC|g<}r)ouG+xWz6jYbiw`=U$HFhTYeHUf_?6W67OleB_CmRy6<0yLc%d{3g5%defP$Zfi^9JwRdMnZw#F*JuZk;RA)KDb zdRgjsN8#raWDR1{aQ6WTks_l)Ksc4uY<9>Hw7oAQXnRk@qU{C#(uXBbHKT~C+00k9 zx7iU)f}m>Y6M_Sit~ztfLAD+IgE)Dn-90^}euxPH9AO=_0R8y#MkRc})*+7v0E}NU z!MOmVgAkSZfjB-W+YcGBb@}BCe8CcV`9W6qVAifM^q+`nA4-V)h!`G+onlmo+sRGC z6<$xPMNi<+C9BHAQhBH;Y7~%Gc4s$iIr^bQ3$zyNz!vgT4(4hbHk=*sp39Bu*6S^z z@&Al~2%gU(#i&rC9n)ZPp%^a#sq%Zc?R?_f&aXMlx&X39ZFi(VB$UUns8SPQl4i&MAx|2FJ$OI_U+Sr}@wpN}!me0XY z(2pclKTh8uI@t9hkb(7miY$A73B(!iuNiS3f2CsSnDPOrQGS3yTN1&S5YW&u1?$DW zd_UAZLKtHx&+qXm7i{5o7UV_uNPvSjvR0CV&{m#eVt{7dqgWw&_Q?~?GR|F98501T zvW5-!kadq1WEDm>p3PwGFTG+u$;y!{R{lUt`w$W*aK@dF@nnQeoL$2Fc%YD9*a|Ht zm=g5UX9^1|p(TvC4>%MFSqbeYcJnkOhimEpVp?DnF&j1wS3&_j9x0dy&9K*~z4Gi+ zx`n+~_scbq?svbSU)pQEj(vM=*9xFTQfi(safqIsy_z4z=)~jiHVqwY^hzhARK186 z6ueQP2Kju9pQRg)N_JmJGQvZ!Y|)D-%|oh&2QFJQ50_vyp=E~wQkMsB<$|R;sw#Nf zV@Qu4ddD*95mRkd?r|uh*)Y~7wwMsJa~jXryX1WR9oiV!Q{|s(8)Fr1W5-ML(15%p zIKljIuBku#i=jHp(WXXHoD0ROq!JBNtW1A0kY-KPZN)6c!%V}k zpUN-mR3fb5jRf|MXP(*c7$M)#+Tbr)xk%K~Zm5xVLm+Lun&wLzQ))enY0w_7ghwk8 zV-33w_ot1mjegf%LD!8nT{i|@-$)6|AjxBzuh(^>=UgMI)yhUY$}Qhyl{r<-2{wN|DAZ;=jFrBn;IuRQY7nW;@E=ogq zFrBEab_Q?Y?^66Ng93BNbRx}vg#Q!4D}cWUh4^rmaawsB)5Hh(3+JD>+6DD5l=;Vo zCf0wZj6J+6;}(Z1V}@7dhY&! zBhPC^lBRbd(Yrz*$OJ|8p->2q*l7=#!9Us^@0*OnU#;EYQ4ZEUC!yni*X~Y1oBDPq zB_f!|AQ-$p;@A8fc1KEJcVA=#S)Ghn?C!vb-LVjM$0%ZVY#Ft?kc#f28wM-O%oIH`?x`8`xdFZUVat8FRtd`t45lXu5Dw zp)6^42l;l#651W(h~0@KYwS*ti8`w7E`)zRyTjcm?yHST1%1k~qU0lYqwua^LaB?z zE|;Sc>{6E2o+10s*ow%PI?F#mRKA+-@FG}uxd*GEGQW#%3^(8*g5|o1#c~f8%Uw;HDlCNMGKyF( zTl$u}<_K1d64ZyD^$|Zm7ihYxP}`_5?3p<>T9G8mf^3{TA>h~X_=&%iQK)Lu8*Rf; zYTpjDl|@Kl@?a}oy>dr$|7;ca;ZrK@zJ>jqSIuL*7F=_<)Fgie zeD@OH6`b_|)LShRAzSuJ?bs`6hDOXrXgvHePWLns6hrwrN-TSb)T)46kU}`W+|SQE zyE^M!G=uJnwZb122=$%Mv}XJXiw_Ak$C+x5GXcjp$%I8tv0<&tamHT(h1Mu$_Lh(l z0w+>Qt3Yb%y8Be(PF_~&zQUgJ63m%T-^yW z8Irli=;|(n``#;hRzJ~T#f!XwwJ%HCV#7+mv<7@D;UxN!Cb%yg82$!5zHcA zFf4&!7)1obW;KElOoE_FFd^6zj4zj8{K}V0Lg95p^>vZUg+L6sgm={b4B?b91wcea z_iHFE(;d)>U5rfhAe4prAoS}<85M?ucqNpvc=PrdEjs6~@Adl~+X_C7ZajUryuR3r zp9sN0&o|gt*p<^bla4JwDJQ31eii)+7K)LrK+QQ1nZr5HHyCjZbP*DA&U2{DY(pT# zsIU~X9;1lB*%U)|JWNBCVM0Dp7!8TfM^rF0YL9`0DjWkZeB`+_R;q zkNGF07lR#zJ|?dCy=!O?>+(y`J=Q-spA60;QI{KiIg{jhWGPqLu6#S7#Io=@Ow5x%2V+!N2uHyvVxDa2FTCWN=8@%l&F)k>!7iby7uvS& z<*=X^j*xoY1b31GExqsX{T z)a9vff2eQvbXu_Yq7RiiQY_~i=`UTszqIy={=*DGCYD?MFe8Nf^Rxf%)CpkepOD^hFuZo8 z{eRr+uZb)5D*i&BVyZn*4=xct1!p(aa}|!BRGA{8Z@3DjdU}%Ob(<{g1lSiilesWf zcQq;+6^8n;9p2^CjVEvbUjYLNXYZN;OA0VxzsCpz_B)7Wz#c9G_6D&D7Gl6MiVRq` z^at!3oR$j7q(Q%acQsPHCC>Nn9z$XIpHgEv;rji%Ygof@?g4q-!P8*^WqmCVh9!3n zSPUN~3g|3=Wa3=ik7vRHlE=IKc*rHWQ&GWt*n2H7M#N!M2ngj-d-Np&fpe*n2%U?T z$YtcB!a_QidLr?h3uiLvy3Hj;hGrZSbawU!kzr18)V$9ppsM%zgeK8V^(EpE?wh3Y zZSob+*#o7F;IGyu`9oI|@fX@;QgtTe3>7x{eNcpX4mK4C0hn&xgjfhopLhMFE$Qqblc&@?-{y?6GCCk5Ktv2_EQl<;-MvfL*6D$JyeGP)zJ6-NsZV?inF7Wnt%!f0Sl??AIjk| z6p0u5tfQa>!8}@#+9OI;o2+b3Mg9majS9m-Tp?j>uL4{nmtUskxeA|)-3Zab0XZ;4 zU0PLLS_ZyH_CW4W1b1M=_^=1jhwI{+QwePanQANGsf4xyo|k!6fK!QjR^XjVP;u%*Nv!cQlP=O%KcK9{l5&7z-9$&d^bT=-f%eV_% zOYp4aBbX9SO4S0`rte#5rf4JQ+7DyY`EY>c%=-_3y@|ij=fqVn^52ws@D`9-=giyl zJLdw2OdsXV(E~(wE2`^>@h+Z4>LHg3$}!}>K_gM6?s)DPMR-XOn{?j%6r-T0Wo|ye&4_UW=Z>7j#NPaze(Z$Wa zH!`PFiZxzNK;q^2RRp;-BjkvERj)HcxIgmzIejq%1Wl?(VT85g>kYvEiobAtB^8ch z6xJ)4)9(aDRc9hNHdEzJltbcolNAXoebBUbg`G(cI*~TapO5wOv}y6FPOIpi2&8Gv z9hKk&P2ZX%5jZHiml5XeyAaDk(J?ZzUKUzdh_fO_k&(rg{#j9k24^tro-}%XJ|w4y z(^Oy&!ARG)D21F%H95RRDdg}LC5gZ&uSZMGElNQp3{~Hv4B@^iRrI`JFUWs?{DnG; zt1XegTy%CHx({^5yQ)W&d9xG>djKWc{e2f+3=69hJQx+@><*!XOxG;;i4^OqhZupk z`w`2!>R8bMHy%cXh0qV9hz{7&Usv(+xSrOpM@o-aPgiwGKPg>uZ^jb3 z+Ik&&i)oA*`LKl`6RN8h!XexjbX3mta4l7GPOBK!yWbKyKaB3{%sn~C0`HDpiKu)9 z8ke8O=qi5!Qx-(@bF|S9%(xTr@-i%#m)kR#jd(}EuPl;!OYAjlyb6`I(+rHXMqeZj z`uZg!=<5;0qA#r6unyi5)EE^OLSKv``eI98Uuz7h73u(_@tkxRlm1 z;Oh}u2Am!12_cvr;o5zDcr^5Z-zt9>P}crwQi!yUGDBH-d9elN+-r{p; zFqruDr3+04J`)C$46K+ZLPEyc!?Wt+#P)vW*Kgrk`=aQ^*0Z^eN+| z`T#hD`<_Bo`Q*pqNp zWRgl)7dr(lQCXXo9>m&TRvKqSApR>sHjRk;yll<#A(1kTDBp2mmhzoHB) zI(!0Ym;FPFgj9qU8L{^W%><5^8}L!=;aH^DMM2Toqpm-HoRBEg39fEAnfL&yx#Z zf!7b0%KDvG%}c797mgUs%grzkEpM)r>+#|Znl&d$&47TYNc%ubmG28`>9s{@LfWqC z>8cjrFlJ5DJ`!d&S{5CfM(ryfEY9c4;#_lFV_`hP)f{7?;&Y6(c|DH3wRw~xj)dN( zD1k0bATvMH`rkd9iglewJNGgs9>XPi;O@Oa$;2DA-6Q7W4 zh@K&Y@cO>?8Muw-@#p(meuI;H8?3poXL$+))IW#(HilYx8U$Om5x_2n+P zf{dJ6Ir5tbr(kWOAJv|V27U|CE*=_ZZ9G@wIz^gN&dvi>##*x|BV}-g&oY8Dd>XMh z!{fyn;;s`=u@KIXQN$UtW#9~-6w{DCNeO?$*R+p7fswtX= zf8kh&tBX+|wvMszdr(xh7hG2U2#CP#^C*#JiQGuQrUOg+DtOV|0>%}o=u9g|9dV6q zvnSa0i;Q5~&mk7uULv+_fFh&9LfAH=h;6f_Z`-PTS`8WPqsUlLMMmwmQRu+7v5F9G z8-)^-8M%kY>1&|7X~VOz zy+YPjEZj-FzU~*g~!k(t56<~!4*|HsxcK33sdGBFhv!c-VVOoc6dQ(3b) zD~@7LFYZZ~jn%SQu(w3${tN{-6Ht2eTdElqOp^9-1Tr6knezEt5Gs3>;;^<&0xpYA|_aJ zm7HkFA}3C@ETJXWlTytAh#(VDSDR=E_e?Z;{(+xRQ)BTL`j&*^z1*wB=3YbZ>p%av zkp@_XiptjmLwNz3!2`U3Hr{s#BpD8{f*55`Zu0?(y()!QR2_GGo#x!BQS*K2Nyn~R-#V)qt1nlRe|%L5*fzYfK!<*ccuIR0&_ zgReE{V-QWXSxq%pFG4jPfsl-)OFfdkrHjA(5M*Ni)yt0%9+|5)f*E4mLbCE3Gut53 ziM;=h#}PMR===nKp^u0w%wp=h;v?P#`;oPH0u3_wD>arDl`-P=mr7tY@1vf~P+qbR z8kI|L;hPbBC@=tld*7HPW;_)5h!FDPZd05oF|_O5puCVsG>LN(@W!H3CBx4YQ6CSJRp{{$tn#&vpT zM|rGyzC;8tr8s_>iy9e0R!r$c(a6DKN-TsaF^Xt}E&b<9%2U|Q5ax1)=uB44xFsj)BNCR5D~?Mri` zw>o44_EnD?&%WrfNq|T4Ng#RlW|6H985t?gjc#=WR3HfImT!&tn?7&P9p~XUY`~p9@;!N@Y1608oIY~~E@3E@R5))@Uq1}@u~r~)xKeY6klyn| z=a?l&!IK~lP2V&du)X(Ge|-$ku>hO6-QGKF!@|dvdI&S^#CePDLz%}v46oR}y{j8C z&B**SHj_Wn!`@HE-v#&st7=F5T?OC_##FuYJ;_`EqoCApV_!*;N0MaJM|+r*|>Dt#jNYQyrJsw=1ij z==oy7RF@?_PG{BjEnh4gr>^eduSoTbCq3tnWqk*w&FU+qM-kqfdlWTWd)ew|@sHD{ zY8wAXVEbK8Fbn=n8`FpM7E7(_hSDP_ozc5JY91i)twjO{6-nC;y`*z>o?&kv!yf_O zs&*61hs8CdYpB(juZctNM9&);&i0*kx8xUs2+xU_MDkD)hf{3suPedMtPII7m<6FL&(Q)vTtqJUTY3PJw)~ zYE0i33(e}jo=3+vtBZRmhY!awO!huH)>NCclDl64PqVte?NOwUol2bJ;>7u(NamSw z`*wAyw+3HDX-6mN@9$!(cUu@s9y*aa+{CJtNYe=RCAbim;JAXk~nTpAw~ zW!XVfm}|iIcvc~|sD-&EHCA%}Xk#v~hNR}4)B%GXs-Vh}o8jelRh!` zxBHlzj^CvtoqJ1eOT0bAn(uTUFlgcy*K=wWT-GBKSo2Wzf|T7N9386utTHHTDv+|n z)Z1JOs@B{AgZO0*Bk!=3Zh(drYyvQ^)bNz5fx5x?@+N=FGUxjf;`aeUY1wcD+(_TDLBnBxRGwmisS4SxIsSc)3Bz?d0W# zBv(f6i>NtGa>shP4J7xJb@TW(luei1KYMjD)$=`-PX=L~_S>>aw!repAx9 z*^>Kam(Fb_xpTbS7Lxm}mzyiO*0ioUPjZ({)wykS&g*Ym$?f5lZ7;dQ3cBWwl6%Rc zWoOB4m(yjtO75(@&h0L_pH0%aJtTLC*TY_tJE>2X?IXFt0i9bQxp5P9Za>K#>Gg1c z$?sC3o?7UGrGU^?OoUEV`Ir*`E+KVG)SNAe^f?6)QW8=)7q|TJw#H7xhExFgam^)Q{RdUx1 zGPjJYlo;kjc!v4-wUckfxU4^*jk_pUT@j0qZ&Ck9v+Rtj+}W62S#v9?d9J!fa*MFv zU5IZ>=-i+4%w3FJ98~kE#C&xPa{{uxuYTg?zL#L`Hg%(v zmGHcIzPel8B)Q*7?jd!vj*-s_c5qn;8d=qQF8W&q5IW56Sv6m&cm-Nsddqr}O z3(kSqtC3tO_F5!2J@#fKw@K_Tk=&fvUn9A>vG*dm?P4E9a=XMnjO6x+eH_Uxh#!U^FWPZmaSA~bQVdc_&G{Q4;glvtPrkdQ%@W&Rzk5bQJ&2m87@u>5Bnh;%c za`&!){Mcfc=(`Jb?kKSL_6`Rj@#9xVTTeoobebyOaa6NUv!?cn=4B{d)WER6`8gbi zX^vhHnape;WFz6_-YnCPOC2qr>!r>ukejKt=pcp9OgRmd#0u=IVG<#ij6V~QH5pR% zji#?4+`Rchg!?ofjBrik*ATwZd?~^+gp%FHT!r-eW3EH^+c7^uxI^Pz2oDpvJtX1v z5@wq32fSkpsrsb(VWeLbt^G*!^0&r4AoJrPtAsjf>T~IY+5u8csIBu%pO#~I_yEJJ zCM-kElXFiZoZ0#e!j3L-^e5|CP)-b{U;r;IO#isV@V5Rv+H&g7F)yLc#%%(h@;cI2 zPx&*#FZaI7A7eIeZb%JZtyf^(^ zdY_e*sXMgov+|M-hCLE4>16t{E{0c1xbxr+ZJVf%%*_f#tSz@f_^#R!I6pG?MEV%D z0O14b(1MS1!}MWjd#;3EMd-sfp(T6$?mYE))VXFH!*LeF0SSLwV){EdhLc+uo+UM# zyO>_m$?!@^-%((CykMwEot_Rt=1V#+b^1}?R8Qxhz>UF=%;P|3Of3!Q%w+dQ{cIn@ z-)0ydFOc|nrYB1{x0~sN)cHulIjwsG=aK?#cuDW6*zM^N*EWfM;7^7N$mr5aFGu31 z*V&-+N!0l~HUFbJp5(`;?*d0ZNiaM-$uMm)TqNlv(v;O{kkwV{EQA}yE&@kSi02v2 zSKB1o-r5-b$)AkxH`n7`dm&x(@%7ZaK>VAo^OA8HEcv;3eR)16l<1nHdpv90{UT>l zRb9FoT=@8}2mS*Sn&uw^{&p|MsVASa(svj3S-GWzj)WtryCXV%9C|-MJnA!`B&Lox zo`B~ZOfbAhaGshZyv<~Ig-Q5r=2HmQNmxx4?I*-$st?*Z(yQw{5Y#zVdVEQGtgiEz zS0|<>OX-0^kFHY~d=8~%njSc+K@Dk}vy9tKmyd#)>*qxkKaJBQN-r?9RjiMfEb6$%7=)WA=uw}LaA~r>t@^aJ zq5cCRr8nZ7?|PD*fE=BifN+*cJg!Nc_nHF;-#1zMiOJIS^RmJJL*2UvMpa$=<7=PE zWG3$ym?vREfDk|)0t$+lkno5G2qXw7N+!twk;x=vCO{NxB8Z^)Dv0kI6sz{yZ?(0p zv|fwVTHDf>ZEd~RYN)nXd#%-$THDflzn``CK6Bb<{H(QoJaPkrI4msXYQ|M&^g!Q zx}R>O+qGB)%>~jgS0t?g{<9>W-%sB%&CpqI@w|UU5=WA+NL_A|QF;1QA*8y*x(e`$ zq$uE5lJ+2ndnMJBWNwZ7lXrsu1sT`x3Os#oyP^4}#roMM&YaGp_Ce?L`P_O&>4CWP z^gVkwbndnuh-;42`wv0-ru8V`3D1*f)O^}Vd5$=G)>%09eeSH0ec;>B{F*urSeNuO zz+e6Yk9rL{e^)#T3XCUt7`;z$TIQ6kJs12j?+OQBP{E^3(S<<^SCn zrhX<=zyISg**F7y!^mFp)v6TwjgkG#hciR^y^(zevQ+xBk$n-eRH8D%zdimR6t(1} zkzc5O|Idr^^V2BD$ePPra?+{L$in6M`RO#y$S(EQstlTJWLNlcGDowF?B{u7@-yiI zBRi2-4ysnmP`}CfS+vn;c1)U;pGy&=xnt5?P}_~HpmSBb^kSS^kZ(UJ zdda&er9OWQorN<)ZZj^SluCu__j3uQRAFRy!LqS5-N+t=Wn*csk=;F|Rt0FEp}NYL zy2EH*jgyuD-D_kMCg-X$oP+A}c1_9z^#h}MXwqnO-p`FJQrwt7j@~q~Ym3)`ddJA- zRy60A(+5VjxMCxyzi1h1+mSz>3d*^J-E`KNSpGyt@$V(?@kt8jyH!TEVRA2IGbXTX zH!ZKcA-|G77UkWvVDw%2XVWhxY1xfa9?PFWI1Coe*wioN&!l$@^<>V|`RC9nyko|> zJel)+{%m@AicNhde-1r?lUzLlI`Yq@XM}o**p|8Uv6j)2i9gDpO9RtHljcu+J^y?f zk0Ox{)O-0C&|~}<3DkXoQ~C4h^>b{>D!7oIo^4b9f(3MZj;8V^W))P?v*&3_1!m<} z(*Sf@;w6)dIq40UT!Hq}vfmDaqqXi>q%u6C)X*&@^J zvYgtC<`>E@DOgS?tRE2Wl1d)QSu~(NfTe zA0rdWzdWZ_T}q!3s^5QEPBvXij~dy`yq26b^aUe3KQBLj4Lze}$mObnwN$jo&T~h> zmDC{AA$ql7PeChfTVl(yDMU|eil!I-C21r5%1{-Enj7h3LtR{cTfs(}u~gF0W{jha z)MTjN7aoMHvQAsgV{;SD6iScHO?1AN!Ln>T0jQ5tiwfFlV?w$u6iG<8g|-_RkJK<- zXJkB5!?ahZm*|CpTGc@VS`#JQThKvcF4nf3TYk8pizW!w@2@KV9H?nVw%vcYU@M(# zWY_sW2kIgt`$cK4>ZT<|_ExEvx~V~^m*_XyxhhJVwI<4Yx*$rwiBr!OY^T5_cI&=a za1C|EsUH>e)2TT1M!`P1yPh?59S+hlq4rP`BG^G1G}M<7-40UfGRc#!LY%*oMjL9d za9#c(3K%N0=!1g0sLN21!jB5>rk4$MPtkuB+)Lw^>s*pbKPq^Db{gt|qK^t5q#tWa zV(VdgO(@-ehv`>Fc0J~?hv>IPc01;=hv<(+_O>rqJxqTyvJZV;JU>ptD`6OM{_hnw z<{zPSq5AzlgVjf9w2@tbbdS&&BMT$lBQ(*-J|3T|K17S76ntz^baYDdb2gtA+D5$T*sjsDE zs;^Saq`PtQ2L)fH7Y&t(o_>Z(R>T19~69to{dwTh2M>9E*r1#H|5hCnX#L$n!wb{hT1od zsr&ix7_!WAre>^WYLEZf;%$ZBqq#!$`+rcp6I88GdgL6Zm{7av<&<58$LZ@P-OXe7 zgL*;B{CADL1JrRNdwJ|#h2N*23f1rb$=Lfr{nE(F3LYx_0sY#@rWQO3>U|?yJK^(% zKctU@+U*Zc_$sLXHnP8tJ6!N1@?9!*@FyYK{D`uJ+T(Ak_-5gcslZUp6~{r98S0Bu ze_r?sRho3)oO%M(IYxHt)b|R1Lgx$B?;n`@XHYdp_UT+t(NF0TlkUOX6i`h@mY-Lv zen#t!Y1Wh zvTN19lV=ULV88#<+1Ypkoi5ZK|9`@-U#C$*?e_mAWi-B>7-M8h3NzI&X@ZemRydk| zNi&3ciM(iuH|Pqji4l%7F4`>AA(}aEV$mBkV5szQQ;OcCz*;W-5bdv+S#*NtuG7?m z#TOR+igp`n?ZoSo-lAs=^?IPT=xy43nbsUEx}@mWH1%>#U5W?v|3USJx@Oe%N$=47 z4O+H;^xC3#X}zH)r>-sfE$xU?R~G#zWe2rpLvE<(ceK|~$BM#5@6*l}ExUY5wCMK~ zXwy_~>Geq;P_w4|4^FsW@4!73vT@oswGYQ;B;Szw(DgvtUu#ZAI9+%DLtv6S`cxhgEwZxqY&)G;HwZ}e5^c`Cbu3w%lO=pXIs6(}29@>80M z9jZL#7CtsKvinjlFLtO^DQ(3Cwk(5JxaMUydMRUd@s?tTdJ?`{sQ3dk%v=}`+2p2* zT(V*{D?ziwMU7Dl;xdKj+Us?Vha#HdcL{APcDV5w_(eNf%I02&G4A znL3#uD^sBgy#6J+J8s>{iUPSTsMZUm%bTb^mmsT9FDJ+<)LHT-q|S4ank|%0H%aYIkX5SV39?F66m!a(tmX=( z(@j=;5@b`Niz=Rw!-D+3Ljv+1V<0n^WF2HA5&}-Zb^81le?T ze}ZhfdM`mXL(Sgqls7}|7D|^lQyou`%~U1$l|$`yiq27OLh16(QD01u%~C%~kj+wo zUMJmbwOc5iZnkq$E&qZpLQ2qY7Ii1B9smqNluX2`ErCN=w ztTI+yrNTybci}DGY85lG&lUC-SF3Ba3{m5{;)UvIO;K|34aK$UxS`hOm3nH`$A(%k zx)-wTePRpJ1@Lzl55}pRix;a?LiN)ZvA$lSO8P~U28(YlUZQR{RQ}m_6fadD$EgR3 zFIH98Yt3@VE>VxgsRxResSgb0EqSzfxf-=gYo2rV1=b2xFVrDAf6|wV8(eXBl{%<3 z{rCB|6t7bE3)SyGjP?C0^@x!@3R$E2ypeq#vPSh4Bl{9$P3k!#I|^Bo`nHy#?#~ym zR__U=cLi(J)ZJ{^A(}h-<>IyKh@rlb{lnsQD*pztT6VjatFc1q-R|XTl9nOQ*NWGx zTA_5FSE|i%nHRsk^@}+5cJT&PwMXaqX`GG(Rhyw+nvx4@r%-puN+76q3v~eBf&OQ4 zP(7C*YjL$%i~6p}cF{QcptwbSV5n2{QE{vKI3Zn|D_xsPx{+#Ej#ce9xP~Rg@ zNyw$SQH?UPeJZ77qnd80FIy=ko7BZZX{$H8(rs3k8qHL^2kw@&t7eg%P#IGcwX4~C z*_IRP%Xt-`5?4r9skuhRnpe3ruX1T_QQ7-+F08r5rMbnW8CD-8Xog*yVV7oydif?N z&kmPnhZ?waY`w1s0C=jPM2nv`l8W{Le`~zW~c|zx?5eE-RfhJ z={DtcJ61zhJcQkKwY2N74+^Y^g;b`u4Y3_At?o*?_UHMW(%HzblvhF3nriv1gs~ZgFYe;?lfTJ^ina=B+NxTV0yBspHQ% znzy+$Z*ythuEsy_Xx{G9yxpaFhuZNiNAnJs<{d80PpkBo9nDX>G(YXqJfQlHJDLYv zng?8(2i4#Y9nFI-&4Vt@JJrD-JDPX8H1Bk29#W@XaWoIPG!MBn?^2U~&YIlQB_(&c zWOu7(k?Eek+m*}RF3o$?!PlMg?r~|}4}^L|&J_q%d=K%IKaDg6PL<^wLxsVj^<}vnxAoLKB#v8*3o>> zrTL&sb3pBX&(R!kX$~mF!P|!;=IN!YQAd0!CjP$?-iY^MJpa6Y z3h`g^PL&eV=CyN7iOkpfnxkQ&{ZCC|om-_wr!b-|ywlIMs6ZPk(wuXp zUd&H&@rP?Bau~<+GO_B$e=;I{k~aAyI_#y2>M^D)@jyj)RoEQO$2S0|ouVtpvkq(8 ze4oUDPsylXC*y*lMXRJPPe{GA&Ud7grxW6B8|rS+7o=Z)D{Y%8`3wjrQJRSJH(Q9q z0gisZ7R~k2?>~{U9NdGqc-cGIe7M6dh*FFxGUrdM)1{8>DNqb`3b;k1dJBtfNTd8fwjNiQk?MvQ_R>I_>H76ZyKtL{1{Eb57*^zvG|WwlkM?I@@$FoIY(n zzMC$^>~bl-eq4iVEv|LAF2i*tt_`@FaRqU;;A+LS5!WVMn{l<{3gha)6~Wbss|(jw zT-~^$xMH|^aBai29oG(ASL3<{*G^p5;`$V>>u~kq>c@3Gu3flxEj|g6mdXDa21xa{%$zcmyv4OvSG>@KdFE0;>hq30x^~oxq^LcEHiFne}@G_6xiN zP|;z)A_}UD$^tl*V@|J}*Y(Od-9F*$6V1o*j@3dc0ltDNt^7%=X`WSI+ynT2MIVhf z{CSga6V4O#9dNQ~D*dG5Rho^rSMkJ~B9(uI^!1AW7MQH&Q^u4`RjJO#1GstCl)_wm z_xB$KXW^{@w&XQ>s-y&*_bbM!YU`XS+2EX*PzlcK71PyJT2wSg)mel2^VK>lt5{LB z6`Pt1oZngdkodj1YHJ)$VQWcE<#OMz*aZC5{7%W?7L}qtQ*plvT8oMv0_TbBr={Ey z@OA0sV~+!WI^`9$Rr2h$dMn7P7u)t(Uc3pk&nhfC+bUBLobf+SzstwhSZYzx1=c=! zAMJ6PGrG#U!}`8wsWs1fW$H4deKDmG`dsTK(_&2pEmoy&l{9)h0G@J|{g>MRO`R|1Nf>COuA1R*Xst3qLHH^Q@O9U6b^b<;%Gq zQhx94sC9qYjY)OtiEQr2-U*K+RZELit4Q|elDG$-f|Prob)H7shQ@yd{QBarC&i4- zKcDp7r01=R%HBv?3C;HaXB7Q0=>&Y>FG=r8Yrkua!FwQFda`#XQhDiJ>oz>c-AQjw znF%bPn*!(s|z9@;&2j;`e~}ODUY{3hzF#d7hPX_Ql?L)*I-Bt!mNeUhh^_ zKlwVq+wctLAT+TK5&ioGKO*o6f%~X*)cfA2fv z8U14Ni?nF;e*$v;FVby=e}n$K$zET&=+~*|#x3%_rnm>|@bO-QPkCO=uNC}q-#n`o z&yLx{w?T)!OL=%)9GB8(s-KsadX8GxWk2Jasjiz?3a|K9MX4vp^T@R%gNQeLodTUKjWwG%;S(yvl|CLeJZi5obIn z0n0pdM=$mN1=1D%4^`=;HGu8eR{~}gg#0r-et!h;ctOlR&l;V5HTeIUldB3nbMbEX zhlAn89rS!MuYpJ)1zrA`-+U;$8g?AiM z{;uIYX~XxV4Nr>nq;O6O=ag_x3Fnk>W_tdX%~rirUY&wJr!ut<@C$f0w$5`h_xhxu z=fiP(Qj$<3FQr(mMTb(-6?@SrwDT8IN-&E53jP~Yzll_9%8#e4Q@5g3*Qrx^?|a)l z{Jejw=jH65q>PtT>(qnUzk<#yQ-7N>m0Jm4*7am3rOp=Vcxlzy0(-56Q?5_y_jo52 zr1pFMR53YqzPyppYb~F0Zt90Uzx`@-t+oWJ6k#tw-*-@rStkJE+lz{lx0o?$&s4P^|U%V%G@ zF8lYsqt>Y6%}*e(6CTVm#ZNp(tV&M_R-}D_( z{N3LX#b5RvQT+Aa5yjv49Z~!Z;1R{&03K2N4d8C+uRE*{^Ipx|E#Fx`A+>t~wQEEq zKUkWPRcXCBC6IMeEIcVzofNB13Fnk>P6?-4y;HFkF_Jy-S*ht!dTq-0vY+xiHL)t^ zDNmjEFNmD4S1bnJg}1$*l{R@%G+&f92@B`AaCQp*Q^9{K(n{-%$;r9L1>Y&N#_RB+ z75EDT?5p=n?7Cn0_exJJS{3gj^t>my?a%h$u+N?C>v)Rf93|pfC zyR0I>m^Bt~hczB>r&S5qXH5g#ZLytut+{~vtqTDMtc8F_q{PRh#3!W0C#A%vrNn2X z#Al_%V^ZRaQev%#?O*C)`|CYi(*_UMw8_IYUF%V!GU-n^J3$L1v8F$XHPe$=GdtCS+1A-qmkU7T$f8Idm z3<`e2K<1F*x+nvg6A--2K;~2lUTq+AngtIU$ecdG`we8yfZ&G>WX>_cpEr;>gMyzh zkU3jVT=3G5R%AaGD1c|}KHnSoqNmEg?+g9b9cPw;*NnR8h1!(PUp z7yNm_PY8ZOaFs0Wlgv70f|m(iEqJxyLBWH9_Y2-H_+h~h3;w*|&kKG+@DqY7pXBf3 z{7(peLU835zF*1}yiD+F!K(!i3LX@^U+{jx4-0-+@aF}8UhorwpAcN7Nd763zu;wp zR|{S(cu?@5;QfO43%*P6!v=B=&kO#%NM8{Agn=x5OK_DcC8kP=f|m*2DtMp3T>=LL z9uxS2z(Ij;3G}3KKIH;y1nv^}u)r4tz9rC;&YA&%cL_XfAZtD>`11xzS%RN1P)ZS8Wl1SnlE2{P0&4`e3hc`|Kz|$4mvtZN zzDqa*;FOgP2Q0fEN^4hp0K(HB@HuvuWAzyX2B1P%(M zLeUpkC9qjwpTGfug952YGzC@(Y!=uja6sTOfrA36nDzULIpz-vtSVug#>gxnuu5R_ z7||3+fdllFu@vAop@3+D^Pgh_!U+hc3Y^kFm2j$r(+tkqK(la~HD}@hx+Ty&k@Fb< z{z70t@Il}o2L=TXR2-ml$^sSAN5D6gH48of{JydQ!3Tl=q-;>|z@!7@8yA=)`oJ$7 z*DUw|@YuKk!3TjqK5kI(K;;2^!x^X)ec(mq&4LdAZz>-Ud=U68<%5C;Cd1D1z+}+} z{@3zm!3TiP89yNSAn=aygMtU99H7U>2d0QV@c$U!EcgKMvIzr%4+3wVFerFn>H)fI zLSU-s13x~YS?~eio{0m34+6hv;-KJxvr(^!fwM&)_>&Wx1s?$Z+ld2$4+5W9F(`Oo z+5x(uylSp+1kyaln*|;d7&xCf#{>p0V7yP@pul7EnG?8B_yPw7RxM!8fIzy4@n(U? z1O}=^U*Mp?s%qv83anZvX$4Y^q!oBfV4zmg3LF$zwMg^@RxK7>AT441n83hNNhNSl zU{xJ+=HvUnFVa#KQwP-J>TBvX^{)CGeo5_K>-*Nb)&-uRr^oXp&#RulcvMnWQc+TA z(v+mtN&A!jo}|3l-p$^yx6Au!?_uwg-fwtMdh?SPCND`|ncSS*nf$5bTaxcj{&Mp7 zl7Eq$mD*(q~UmZW5-j!(TP zbw%oxsU4|1Q*TbaH}&z$FO8Z&b+i8DHv(j_Y1L@P#=cLb1zbXA-`rYaOlK%Dd*V9j=XJm}aI4`38~{+yMcJw3ZN`>O26vfs$g%$c2Y zX--$p{+y#ZujJ(A&d#mR4dvdD`*iMWxqrBLEnR}&-^1?!kC{|L^qP<1R|Nih z(Ny4FQ-XOu(lmod;M^%uuJIJeHQF&Ii=^bCTQrQ<#6KjA7;ED!_XuvCfg= zTEL4dE(Y9_!_wY7E=8x+P^YRbZvcOnpW%O$at>O0P%QkDk2!A@a&BFMr%zyxwsxK9 z_{MO~{*rZoPmbLHcw%fD;EaNHz}SQcV7ZjCwPFYGm!@71cx38+z=w110-PkZdulY> zdE+RCJ4+t`yt;_XI=g~l!^DRG4`s9T?7%Xmtr@NB0Q_;=BA{Dp1^_;Iux-iZLT=m&UmX3-DP zehR-Px&`=;(SC|v0kr5RXg@_i1+?%r>Q>;d0$TXOGz$C|fEIpZxCi)qfEGJfzXj03 zue$C7egM#-yVcEr_o!RoC6{_C0oQt_ptaTmUqe>{UrQ~(*HRnsb+j4yI=Tw@WfTE^ z8Fc}_lCB4SCG7^jf%XF5KsNzzrdxqG)9t{6bP#xu4gqhWdx5vm{lHsk0C+1s1bicX z4){iT0{A9+68I+k9gZpR%dY_6OwRysr)Pn;({sSX^j+X#Iu5*pegwP&f3I{3{Pk7f z5&8x2PI?`9C%pl@i+%;Xi{1u~6FT5q>9@eU>3!hc^a1cFodh1GkATPMufSt;3OGJ) zN~+|ZNt%MEp2@(s;mm3Zo_?kS-%gppcTg_y9W)B~)l>rfYQjuQ*U&iN*U)(2J82T| zoirKvwKNU*wKN0xr)W0tPtm!+ucPyUUq|zS_fZw_K3WL8pB4k}r=`HJr+VPm({kXu zXch2X)C7Dttp&cDE(5-YT7d7tF9l7(Xxt3^M!E|4UWx$UOI^TkqN{=5L_2}sOnty_ zrt5+4r#-;;(_Y}W(0<^z(5=94rB4IDl@0=*h8VE~dHxV*oPVTd{5~q4LVE7?EKB-k z(gbgfcbWGG-k*7Y>HUrOzr3GMemnV~@1!r?|Fr*@-%1&ma!bksDW6R_n(}WcCsR(P zOi!JkT9e+8-jcpG{afi=*?EtyYd-j;n=_G3AJ&iU`0hjV|No0@li z-om^`^OE}by@14j{CnI<35*x>evgAzt<`RHzn|ATnt5)$?~0zAw+3(A4AuKA-kfmr zUd?-3(&ELj_`f&veu=l7NMhD<%q}Z1t2AIfS&3^EW|Br+O_(`WWB#}l*BV@FajnC3 z8LrDQldQ*e1+FV`ZNSxxD~PKFS1YbI%rGI$DjRWa!nGM!JFcrRt8BsS5XOAbftewK zxuO%ZLKo(Vt(XzIF-Jr(8^q9mJ(vl$(G2+SO!)0Ncv3zKK06D(IvYMZ2fleOeDXZ_ z;#~OPJow)E67_fCsWwOa8?XY}gX=~_{Jm6#IA0B4;`7vn@SPg?Of7tcS4R97F8Cc5 zLJs;q-`sCE_v7ZStV8}eu=qm!zQ)5ip?-w!v>v7JSVw8P=TE@rP?Pr&TIVfOH{!Yv z*XM8@#r3jxj=B@inJ-H&Q|-8R;JOjlq2y}yr{qPD{fQp%eO|rpFH^twe@UgL997d( zK2&2<%hXz2n{aKzbpx)0xE{v!MO@G0`Vp=-alMc0@3_*_%2Y9~$++g>T8e88u8p{Q zaP7u*0M|pfp2Bqu*AH>Mf$Mj;PT@*RFH=RhD$}d2|H4(6QEg4bRfB6SuA6cF3$C|u z{T&zn{D8I28?;ttZnYlD+-^OaS#7ugSaouH2%X+|Cl~rwZ;@XSr0bI}G`Z2Ee zab;##TN80zfGddWL0sR&^!Cc zoa7vqE(yg}g<3THhXxaWWBb#^<^;SR|aGIcg@? z>^x4uHCq+h+SA@0YOC(v)YAc@YC3x&lDAeFn!{X9$0g34XXj88Zb!Q1Jsn)EW)E!@ zq^a)=wy}b40G(!G@A6-8-Psz7Mwj6VZVEMZZV5$Cfkix zB(!~5u*(o_EgOR2_Fyy=br|de+{Zf8`u0euu`ApjGqjdUZ)$~gojpdhV6IdS&N8&E zQ00-@3T#)iw@La1QGM&NbF1AJ?AG22g>#x`QthSHt8iP~6KTb*Zczko&>d_EhnQN? z-4=p#xS5Ti?sio4YNONuh4$89j1#Qv3H9*ZR$;s;7~O)Kwi&qtudC?{heNHg_Ra_> zF^9F5g<_jK+ZOh;hf%6YS-m~j9uvwo4WpE^;8w$ZeiJ%<0ax}MYU-?u#AcmCbq(jB zjkqCkUuEta;n?C9;DtkxO|i{JfIe&pb$1x5+uU{6R6G5NWS0iRJx>3D(JF&Qm$NV! ziGU8i9yltcfE6uSS{MLfW&~R(3pxr37HHg^F{tCwCP`E2G(10Zogo^;qIp7xe@bip`xJz8Z z-86w6LcnS2tZwUQk3^-6xkeLryJdlLzI>Z!x&`-Toozkg&;s<2?!&r{u5gIwgCGym z+E6Um9*!=+GRlmI+J&UOCkm{-hU8CPu@CT{zKWVV)3w1^umv&EuoK9pVD~0)S!sDF zw!O1^i_vi?mYET?qPu-ld&FoA<+0w1jT=J|#0{g8K(bUDYh-bvX2r5))yr$K8f2a7 z#+tf1s#&wSv$~@W@0Ts3#mi~+CCjPC_}i+Q70YS)il(~7bv4yZbs&~3YT8h@eDMlu z?2X1k9n!o2r}eSH!C87p-cd#!E$K zt!S(je4XIy1iwu1%V--%qzxMoV{Hq#fkj1-Hl~biYeFs55pC`44!5_U^IL7c6N{tM zmV_b*?ya;U!ULq5S2e&_N5XMxgrP@?^A6OT5Ug}k)I1(jxB(oZK~L+eyI^5R4;yZ$ zgi(ZyWHq33S``YmQPbvbzOiXkvns?!QB!wsbz2)Hj%r#Q4sO~MYNKVCQ*i6hH|}EO z&>4$`!Q{SisJf^Q-_mmSl1Oyo1gvYq@}L3hIV9)I5UeAJji6+bS{;c7H-=V3FeEW{ zn9WLcQHO5o?tz!IaYff`4n+{zI)X7~m>x>(iN>x_tIVjoI4H-bg6`bKSTxJiS;gY(Bk$8>6nQMo$)(vM}Hk=jjvf(1T zr-nZ%f`@Kw-!uXre%RSj6AXu2;7!Bj+>{}9RbG`17uScjg~G$x z?9;=!I&cr?^O~zY8pZ4~T&C^r>6Xc7xVRous2O}CCa(=eWs)CJh)5D0u}r-f;T6rW zzQyLICDc8fzbqJm>x>|%??eC^fiJV?@O)Nb?u`y-vpbEzUbLeNJGK!7PMeG%M8!tn znl0t?Sd%w0A6uv=L7_O`VLP@%UETV%A%PbzwVCT{hjg zvK}MQrZAn@OFf&_h+0r}7gvTBw*#~?SjC$XnJ4TRC6i8^z)XQHO{jZgur&m8uqnYE z!yWspZS6pD$`A`ifYe}SjD_kVhGaRGLN~GQKp{ z5ndD#w2qsVmNqS`7X(S=j?UZQL`yw2#)Bu-tmfUhWNE^tXxMm7d}koLc;W$U%a(_B z#BsR0(is>TOt=3gv84c~gbmdsNt$wny7p zd7HV{cJ?rdy6|qFL+w(W7l4DTnOfZ4*!=+lPI)yhI=|9 zf_4PERMPY=SP}{QhaJW4hYVC})MTO7FvB>L|wG{CPig9K&tL5xPMjRiK(3)-xC&B7u z0muu((6V6bW)@;4>7wEEjxfv`T#QVkVy4EHaPN|KCqYFCTN5ENk z;1)w~$FLm|HmVcHWsNFaoPBin3Wh<>hX8_eA>4y8F5K=;A&_Z(XDi~!)uFby276ZH z=3qBkU^7l$XuH7p`VgGN2zd=rYYkXMOP5jn1l zb8tQxlf@pSOJlM4c2xJkrJ?SYPDpCP4E3mj$9MP2X%1;eG{J{zLoGc#?IHGUm$4_E zL^T-1t2()hua&99TD<1fy3cdW98q`67H1&pUB28DbXJtkzGJz zEY!s-*PczA9br7XZX88)1iQC5B0U){?uOs+zSt4i87^&aYYRmj{-PalNM1`hEIWJl zD0JhL!`zq zMl`aGchZPItsxwYQS@rK7H=cP|8y&f`xz7w0PRK%m>_IVM*m{DzzjJwUD(TwhuNMv zGPN>N6G9D~G^TdbO#iS%yq=G*n2=GXV>eGr`d}RU+3qcEo!cXZZ0a-!>SC~==fl+4 z(-M_GT8LM9;dha{JE#?V2}z*4l__4hPz??s;C>yQ+d_=hn8Q}g zjFA@5on0H2$P%x+3F{%OIXZ9<4McjHsVGxC9(Wffh6rNLS?oEQAD>|Az=|;(mT@Z& zRJfxxvI0{VVVFoxdgms28MIE%jeMfJOimdI%i8wNZjE2uiG&y#lGwO3$^2*&Y@f65 zlbjRCZu2NAfhF#lKywB>Y4V|@ZpFj^CK>7xYC;;1e>X#~jNLp`-_0=d?UHb33(wEG zI6gB+sptuerdW4SlSXw_XrpUYnBq*wdYC29dWu8m@ya07ogm=}aaHH`1P&e; zBv8DBfU$h=#MbbRBu?0ykT^q{%e7gSCUWnex%Y>2mWN9^emOKoszb2h36qalok+K8dlFfuBV<9r=E6wSA;ydJjj?GL zW6v)Rvr4xAlA%FsINHjHiXtA(s^P6C zhN=*FjJ}8b4ytp6ZbLIU+TNL!mBe+|u4fHB0eq zfV#RnLB{}=VD->Np&cOgQ8O0DTP4?Zpj(+i}*-&aaWx zQBXt1CFYCh7V`v>HEopJad9WspZGI0vRlC85*&Mgludwkbu>J0!tqqHzH>Y72u1p| z1uF~e{SB@sF+=G1ZwQoUur4{yppH$tU#olYn6z8^6@w_W37!!_lnaB0w&Fc$oIv?{ z{%h*gJXu~W>h5OUZcOXA^I-r^+JGfIVddJI4K+(7z{B6Qo;*F26!OjlO>5=7Btb0w zu(Y$Mo40o6U^+^XuDaSN@9m-@mraS7uQ4;2H6g=Fqtz`@+u3W|gV^>&W9_YA@%AXb zelU?KO6HNK4h&JYKQ7t?k7&XUB;2TXqGE+G68EQO_FaR6;-Q7a&tN29OuTp{!8Xla z!--C37xz6*W`>DjjBHfma=nzt;NbR;VjtHY)93x@-cB=LM=5@e6z4Ps@!(d@M520H zLE_ahUKqCn6VH6CaF+$VQ85-3Qq%qcOr{!rbDrq&w zaR93--m^==y!+LqnDa`}wek31kgkTJGbC(I;>fUhsE{5L2@D(MUe=odU99O~-W`ZR zyh9MgtRmyIOx95{i|#0*)a(r#Vw>CJeHdTbPvdwHrA1qNf?>%jab1d=5tFl67d>+4>LOX22U6c649i`T~+J;V@Kc+pMu^^6b z3CX<$H|~y7u&oWg+ley_JvB+g+9b{69I z-4X(e?Zi`k7A}{BqtmuNek2ld!gUfCinJ8P+nmXg4LuI;}q7+ z((c$P@QGi{oV@Ebr?Yrn(Q*~m(b(T&s@B2Ra2i9rn&*MbJ;w)MtqvN)5--NBYL7cK zHml-90E<|InGFat;K6tu28h@x&q1VJ^eK;UIVABj9mC=!%n%k2gai%Ux74|DBXmi| zsZ1eMv$Cf>2IuLJ-W@?xNV&Fa=tO$eYqwoOP@0A|G;crY>03@&X(9T$8(Sbvp&$6{ z)qdwdwwGjvf+qMxQ)8%*!Ri_oVa0|0sqO@Qc<5rudymA2#~RblsBvx)(;e>jB+;;V zj9^|qz?jFmHWqg%pG#%}PhhYDBi?JkxB2>Xme2soPDxha=-ZkJqF$66U}zy-1FIE-Y6 z$n{INc>AFa8-*Qu{-MROF1&EKv3-Yq%tlSUqOBn!01kZsYH>8#%kyS;H|}~Zv6u%@ zDAL+X8{-%oglNH|R_18Nu^U_7iETnJ+qEbX!z(7{=vUg?UQ5;BL^pzE_a?mk7!LPR zb)+}(bw2lOFWa4!90_dKUEUedbglg`M(Uv*&pe*geJ&krbJ$=GX*MnWkwD{oViB)T za8Sx;6?GBRSyOzxuUCq&6`K+5C}!DfQ;RyfkdVdLdct4rwu_T!k~n@fKCxSd_oSxd z&HpyQUi=rJrTFiByyxEmhy?&XAdG?^!Q1^oywQI?G|KQc{|vmzAHaPk?&Jv&jje^8 zbprSnp%dQ$bmNpz-YZbm^ z(5aZy1dRZ`RnTQM1D^!^9F$uL{8GHsR*$b979pjU%o523_yo|ls0CIezJOeqot*%GiuuVeF z8}T2z5DzYQ9o#8uWMD<0)rxd_m_^T6>daxK)}fwfD#NyFq_WPGZuJN~;I@95)OQQ4 zZ#$#SGfc0pf~F2P+`9iLO(nZ$|I9Nv*+O&&$4IV*cCRLMa05E(Oci4@xT83xok?$G zCv-Of$I=M?0}jd~rOqP7=%sH8t?>)oAu6H2GwibezEB&b<;J!RbJw#+=CuDaDQolwvnJ zr8%RJG7?8R<=c6=#~J01@CNV&yJ&2p!tHUINcbo|zy!x1%r=_KBN zX$iOozkTkRLDcv^Ez9wM06u}_{)pEndZs*^F%)%R;3Yz0uQX$*>Y0Tlx{vKVZ69dH zXlRhdg)Qf)5`L;AK{pa@J(J~b7jrkfyDRO6<#1yU2cBMe(q1T2wCzwTG`z%( znC^L%85pw2&>c85A7_c6r|?Fka)&*HfT(+gIkYBh0|!W_7Iupat)*T7j1-6h_@Y<4 zuzPK>ck}Sk^GO@S?hLnC5v+H3`ECcxkxXw#h#fk@<`7|Ouv2rzSc^R9 zuq=1e(Adkdn?4)g!e4>?-}%@KIMjONt9-ow?8VR0T#hgIgV4Mh4RJQU>eqS!;APM| z8x4Wq9U0vydpa&Hh7ADkZ^QVd8{XZvgX4^7N?Rj~fO<3`%n`aV z9eecqISk$V~i#1Ln>-T6;bEV<_fu&KDV{nJT~iK!xk!!<@VA<2#{oJ_4EYUI{G% zoF@?D2lzPxX9+x)Xv}()&)4N<1n`Ji4{P{RUVJNt5VBo7i&D10uVVNO3-a++b0hNL zQ!etgfzNt8s#?H}3U{0M8KrE3ZUnzxK`EW!#NgYM#-7TX+aT~Zj6U8+g^&`j7lMNa zBec0pygG)F&)&@AQTGpJ>6|u#!zWBMx)%BJSlJAHzPGad zW1ED_^Z$tQ!lfc_!*6l)AQhi&@c{v!+|_{Q@x)`0V^|aNQql!!8X^ihQVFe^yAC6vj3SK2`hTJ|Vp|on~ zn*PhH1>Ole0*IfcA9I!$R5roxQXYtDkXrjHX&cixe7Jq-U*s1-6J*9k%Z4^6S+|nGboSs zx&G`?MmNvl#PxDmkIxxT^6q4n@8Rjl)K*K88n1Ai1L-58sa5@In#M%vJE)6@Hy;0-AA31_J0F>H1mG0~pY@WL<1<~t9>udY+iUA`?fFEXV*-y(t|5=; z?Vva^vw!L+nmDi01h!qr1df_v_#^k5`-uXLNldc=dOTv;Gi2t-S&w>#QSv5f2}JO; z$>_~C@X+fsm%}n{yF?8>qvksB(+7Jk#UqJxCLDt3y6C49RJjTzao*f>>?s^yhCagx z;MW4lgDZ>Ix=vX%tKQ_RQzhELY4ivhhx{%F&by~8h%Oqbg>C!Xb#eTSSANFlHn_{Q zM`>c&+|Rmx0jbgO`suue)|1y~v}7dvcogY=YL}jD$DGd|z)_j!Alp*?9EWR4H6!Ko zPv()r^Edk#jj=JF**Ny`kv^{>*vH7T6@J0do98~vf*0`2$WO9(h2Zd`@KT<`n70vd zM6dN=R!Gq+CgfagW4dQJdUFZd$N0|WbJXFx_EC=4&We{jm{T&ickHy3!CuCrkz)$w z*(Er$IbFmWJj-)*1CQGS;qg6xr|-lXh`IJ^buRk{<-H!}7yS4rLscZF3W+8BB8C7|Nnb{0S1V zz}b>bf}uO%E<2IaPBi>Z*adx`F?}VM&dU)VW*kOipTKf%Qg+CZ-41r7anLd)oaf-~ z&b2#?ml8bLus#nfc0~j@Zx7dK^iV0E3Q)#&)QG#4hYeM;yJ`p1PRzZa7un9nloz+W z3<{wBdWpkjh0(SM71&sCew4x!96JeB*ckVnex9XEVCQZ(EyeDE;GM!#Mi~7_=Ow1n zt{#+0kNv@U^w^5BoCnLC3$_ATZZ73>ud^*Yg!s;W1s-U2?s&$eb(1YaBc%w zg^dbANuH*-@ATA;MSe{yT0;+4+pp|CWpCi62`{NQ7abtDOgp{VPGme=OHa=EN~e9&CuR z>@+%*QngKw6#sOv*51Y&BG%#B>lk1b*YI4_C@oOz;|BavZv`Ssvc#DzQIcc?zyXQ=RV}9 z!2ZX!+go?MxRpSS)N9VHHIj9_6lb5~0~a1olWi4(oZWE4gI;L?Q zbOalcE=AMGA~oJc`l7V(VfM0s6r_8NVhzYJf z0kK|}Kv{Zz<9xYQXr)~zn{%c)h!;9Ky|VxtzW8ZDS$srgj|(UI=nWW0IY-L1a(sf9 zhfM1Q;;_8aw!m(^pd_@ajx2PZGcIhN_Gf3dvPVeb=%XwiBMDoZ>FfdcMBdoPOFnyi z4Bud&H$CvgV%>gv*5Q$-w_02ey1>cLp1t`%ndc`*lNZztQle|)<&_-H)-~ku#|PXE zE_?a7l%I{nk4yVrs6pe5JcyT}$=NhES355cJoi5Hbi0g1BZe;2?9jjuka$I{CtTh$ zI6D<~Enbzo7lrPS6W<3+-2f zB0U*t`Dw=gj@EiUF|NK8t;>@f2Z&kH7VOOSKAzh_*IF-kSkoRz91O5bsvPP3tO@65 z?h~}jNaf5oEud?U6Pi3eMYNaDJizb^1~7=cn5^RGOJb|kgbAMi92&X z`_>`AZY3TdW;vVJCR1TIa*ywiviQ8-=~b1_Lz>%BTNAGvYOWWIY!z+SBV&`)kI#pA z`m)<9Dqf_AD4!hiRKUTQgSFnp>fwLpoh;j|z1W`K%dk{!LVm*~IskG==WxwiF8h3l zM=6ItdoPVVHmw8Q11`6f<4um8_TrcG)BAMB^of^VPUz{I$3EMrr&)V9YquPoS1o-u ze4pz~S~^#IIyL=2{Yso~+O5wXV%NnvofLBc~ZzxLO;8^63>aW zKeLtU@_%ginK#HhHFGQ5?VRv%x7&Qa+oToj~(+sL!$Zx7lfyPNhrGX>@v<&+TpJW!^IO zX&I&1d^(TE|Iqo)S?Kc!;&?E0*+6(wVe(qngmKC(%x|09TW5Zwq!sb5O*NJ1Eo+t6cli;z9_88Q4rcM7_ zx$??^m#Nyt09=U7&GVJ`G{#=LwJ3yj+%34m%L;*i5*a1=xEdAIMiz36n%wggj{B4eEw7Wg& zaPRBkr#0OUta%*bojsOwiYBi@lr2a5x_9&3a$IjthpD}NB#SkV!+v6@=0_?V`gy@_ z*G)fW;mIL@6JH)ec3@xqBIyIM$qnp1s_)m#^##90?Lm zguL7ys*w9~7TT%-(clVcE4`di=)LC9 zC}MB(;FWc&VX1Q}to71gq+IkK6EdVoD(IQZfiKPg?oX$&DP@Smd6nH98DQn ze?;9&hU@aCg==Cj${Dv$ne6CgFXuUq+DkT?W9Q|rNn(2EY=?WCPw*XU&y-5{EM3c< z#XhnHb?ucA=PW!mZJ$Hg7W0PKjxb!K;iuI49BX(y)4u6E+o37$cdcavgy8L4G(AZ+{l_GUewI4#Suk7Fa{+4GV!i&6YQ zM9<+|D~|R$;^WC#BhTZfUjVb`>r-rffWu|~!`k_D+@?IX&>Qnbh=YIy;g8W13gqe{ndrV&tLLL%}-t^_;&aZe|f5s0!sP406C)>&17H+ zy(}4MZr|ti?O&5e=k8FsOL2>-Jo5UioYkzHnduvy8?Gra*zl@t_aTh{2@{z6r% z^o>|tN~Ox1%37&pWoC*bGnqV@nI$DAJ%q~gyV6)msVX-+$)|EdUQPzx^vulMP-bq& z=$sxav&2EH++JAL4qj>iC2qCyC{Ka2)o`G$Ig&0ZfIrqH#lw6`%H)4&3=0?9!pihZ zi{yrqxzsTw-T>wHPY@F_(HeQEzb|0r_E%<>AVp@r&kv*GHrb}Zpqy(_ycAGUQo@C* z0$<7qy0G3$DsxPx-)H6a_2YjjawZA`?oai3{ak<_YOpRdGsl;l+jm252bg{Pa(jWZ ze&0Uns{T1yJ}-;oLZglxZ1p6cWo0IjvNFf|(B^%&sN56R%dv8Dl^^ZwT;i6U*=13)px$B zZ#?7qrqKClnK3*@6B=i}HB1|hIwo_B2jyn68~XhPzO3B-dTzYKmLK|4fjyFGSr$Ca z1_Cem7EDI z2%C~p0pO3BsTc|3^Ld1#{J1P0-2H2F`i^?xX?;h1Gn7)%$C%=z<6#r6u zK9dgPEQ5m?_x{>sWSlz#^No%G?7j#DpglQF{NDs$Zf@USa{K>UFKhpX!(!JTB;qcL$AF~d_`x}k$&|(($YIeDlc|i6^h83Gj->gL$9PdMv;$XTj5l+xuV4(X zXi)2Z)K@zu=oF^$zcmJtn=d~ugz-_i{g0I(#9_)ui+JI|2$>i861~398wp1JPNT6iji)md%>y6PLS`Oe zA%!7Pioc+n3Le&ZnYq2_kIWLd$PVTZrm;+{rr=n){ZHgx;e)|f@3pv*& z=X(Edd)FHq#c{=F&xdbq@2!1{Lr80))54^V378fwQzqo-Lb&T8R$L zyA=gs99XctxiIahH)o2~A~4RQ+_#;d;M&9T#6mMI5S z+AWll3W(88YpO0`CSymh$Ehmn{<{Uh(EQJ-;j}*=-fZC8|9rg-N$e9-5k$t1o73 zC^Sx$f?}f9PU4MgMTUxOBm@(C&;@ZU85L9z241Rm3Mta}%T-4xuz*ribGMtuFn9u^ zN*8rttW2lkWjd8ZnV_^y-JHf6YSA3W&VrTha9UX}lhZ4J4=%ZE3W=PJ=W({3RUBxq40MUn5V$h4Tq zO9>P&xhNYks!*|Yc<+ZfU5SWYS)OSnF-~!aa?M6#wK?jX!MfQrzH2?1oXHZZc!6m# zkpRRW^TMBQ0T}2ysWdQlb{g#KPlOVH;$~VS@=&BVpl&dGuCJmS5f=1&BG%3N^f$XQ z*+9;Bgf+vT@Md_q6AIyOFn<4;W(2J6O^Ul=ihCG0p>%een0sC%cnlj0BC0?Mef)XK zky%wSgpk|tkAh*J_KJqkCs6~!08>{*_g7@vG?f~cv4M=k+N!ZXd043lxe~k8ZLITT zw1>>OJbzqQCy3TCI!Q&<=TJ+V#!-_dVk)3!hb(d2idd>S(%KkQ>j)}57T?hg7xYr_ z+Dc&=vEiTAn3%3OLD6d~rDY4bu7F%rJXn&XWKP5k2EsaKeCP%&v~#x1KiqflYv=650tt8-YWRC2$Ga2|5UJ1P^doAd#yU zFe5Lgnp1opNjG`rH($A;bIl5Y9v{MUkQO#*p<8){D!%xre-ag z2gf}0v@l9mwIs*XVItedT_dDjfz~IBe z23O)HbqWvCkjuc3sAb6YL48cV*A}Sb!w3M*A?_|__1eXZj2dI9?rz-^42(A;{Fx(gUc9Y;k z5+r9O6IYUwLHjWJ4#8c5djua7d;(CDEbki}2i!Oat}4d$2u*fc2Bl37HWEpQ*k5XQAEZZ_7`Fp!pEfl@T&VZvC>Vy;OP z41H+qNQgzy8o?UTSR;7RF_zpg1xAMefyp+%$;_EkIhv`03ADBscSNx|fVAhUw0_yH z!?E>c%v{8>%m|o)CBe&Xn{SMnw%s0Bbpktu`_MbhnA(_$LSdy2Xv1QqYpD!M!J~}` zzexvUehpD*%LykwA_frRa**Uo5rvW%f}tNFH%gVVf+Bz#fW+LazYK4~u%X~z#a6KP zVS-$NXs{BeVGt$+*f6jr7Ap<(L<=M?Ou)!Mabbm|@8FcRK)Z@-XMLM-c(Gxv$@y*d zZ@XRouZFjeW(q*B-0C;s4xOQ`#omlJtR-;S5@RhV6iizde$dXmvKGr_^aXEChQy#Y zbQs&2S8frKESBS^4RNom+eUCJqE$fIv5DZOONboVE@nicGklzuM`IBCWraVh~ogp(&r_31afw8(gXfbweEUzHhHf35!H!QF~ z8R3o6cMuPn5JR;WYcYiF#+nZh20D_K+Qv`WVwDSH{#8I zgjlQwb*rV$4&JjqtPx=>>}}o1{8g{wVgP2_*GrNo6+&#-<@Vv;1=b{nP0a0(5-^!4 zO0NQ5VZs4Sc{5sYC_^QD>ZD8#6Y#%pJYS1ZiW#N}ngs$;@w%>OI0c3}@GAPf0*kYQ z{%d6kVB~^~_ldy^{RivPs}fQ{2S(<)Z%dPxUangh7st|Bu&marV#{GSaU2Ii^{PEC zj67M~@z=^esmCewZ74GvmDs|*<$4`}7^%P)|DOaeXx9=%)?v`;m6ziJ9f5XJFN{IG zn8_{!s21?(l@XT0&z7JOK&UvoSJ$eGSF~-Wn<1Dc7;Xt-y<+&}gik%K606%Ja}mTS zWx2&REe5$d_+{~vEcV$Jj0L=&w3MYrQY)T60&kGBhr)yT>3!}8M=hkwa1x|EOJ!qc z_$#%>QeWo5&a;PncnGI+E`J*AkTIy0hZYeMH_~yTJ&i4oN1K9iV6-)Ju7lsOBQ$zW_@rmM8Utw^4zVF~rab4f! z(Ab9c`KkQi)F6&@alrIIf1dxaoyAh0>)-axk zT59c5T(TClo1H||MlCZ?fQfjGvW)y6C89oMsSQhUOVr3MO(J@u%4A{1$5SF^qm1KT zy%W(JRSvwzLaQgDHR>XC%bJMPI4?TeNJMMYNklf zxR0txafX$M*(g`z;!g(8gdwI;gAd$QCFZ$!$c;vsEjtoXFhkWB=ZEVCCWeZG8z%dv z#>Xc63WbTGzOk|O<9%xfCdP{6gA?lyj$_#5_3padw|S>=uL~rGZ&_;iT}$oURoQj# z!RE*Q^vgFl{iHLyv+|2Se2Y0eyK$5b|BebAg#)1P!pY+3(PQ76ni}QgwNJW#{bQ{6 zjn0mJ2UzfTJsJz|KRhu;HvT8BSN>{bt<>v$_LJE@S(i>JIDa`(nVESG4$a_9cpS6; z$$t9I<@I0{XwWkH+4WzQfF(j*snmR&EEju9VO6v!oau(~+lwA?ipK8XI@N^9soJA< z;TzpOI1+a!p0>!DYWh&z&3NYZ`}9Bl1zQB3_~WJTPwN+z#+`kw{;J@`0#$DA-i!^# z{G4M8wh41{GOr%N8bK_#x$}6H=$l?ipw6f7gQx|bcp#154854rbxD&)x%IySwg*E7 z*l^zqTyC7^He|g)86QA|A^K8MR^Z z;SmY^5M&$f%#+t<(Bc+&ewBO#F`6>Z_uUF!6pj{hfp5xHK`OXzLrQ+^WxjDH9dl+R zw@z=3am_l%=75j}zhmdeF~MOuz#YKX^ZD?{JUygmZSeCVbL>IH_0oCuBX{}c9PNoT zwgUeJly*ksdKhIV=Py9|$B-|j9}n}@Impw;heLUAg=HpOAh6v=baad07IAKaKcc@s zM><|xCC}|a9&8cJ*~pG>TI!#M|AK<0P3-_Jex%3GY>vh1En%BJK3<}n<2VmX`(arZ l1!oiLgWKeJim3i*@KJcW!~wi%DgL+91(+Z{yZ-+q@NecDxRU?? diff --git a/Admin/lib/System.Data.SQLite.dll b/Admin/lib/System.Data.SQLite.dll deleted file mode 100644 index 54fba4e661cf84cb3bc77e1842f727c2f4932623..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 320000 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 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