diff --git a/Application/Main.cs b/Application/Main.cs index 358dc478..701a67cb 100644 --- a/Application/Main.cs +++ b/Application/Main.cs @@ -10,6 +10,7 @@ using System.Text; using System.Threading; using System.Collections.Generic; using SharedLibraryCore.Localization; +using IW4MAdmin.Application.Migration; namespace IW4MAdmin.Application { @@ -42,6 +43,9 @@ namespace IW4MAdmin.Application Console.CancelKeyPress += new ConsoleCancelEventHandler(OnCancelKey); CheckDirectories(); + // do any needed migrations + // todo: move out + ConfigurationMigration.MoveConfigFolder10518(null); ServerManager = ApplicationManager.GetInstance(); Localization.Configure.Initialize(ServerManager.GetApplicationSettings().Configuration()?.CustomLocale); diff --git a/Application/Manager.cs b/Application/Manager.cs index b34241aa..dd5e98ce 100644 --- a/Application/Manager.cs +++ b/Application/Manager.cs @@ -53,9 +53,6 @@ namespace IW4MAdmin.Application private ApplicationManager() { - // do any needed migrations - // todo: move out - ConfigurationMigration.MoveConfigFolder10518(Logger); _servers = new List(); Commands = new List(); TaskStatuses = new List(); diff --git a/Application/Migration/ConfigurationMigration.cs b/Application/Migration/ConfigurationMigration.cs index ae20113b..496aa2e5 100644 --- a/Application/Migration/ConfigurationMigration.cs +++ b/Application/Migration/ConfigurationMigration.cs @@ -30,7 +30,7 @@ namespace IW4MAdmin.Application.Migration if (!Directory.Exists(configDirectory)) { - log.WriteDebug($"Creating directory for configs {configDirectory}"); + log?.WriteDebug($"Creating directory for configs {configDirectory}"); Directory.CreateDirectory(configDirectory); } @@ -40,7 +40,7 @@ namespace IW4MAdmin.Application.Migration foreach (var configFile in configurationFiles) { - log.WriteDebug($"Moving config file {configFile}"); + log?.WriteDebug($"Moving config file {configFile}"); string destinationPath = Path.Join("Configuration", configFile); if (!File.Exists(destinationPath)) { @@ -51,7 +51,7 @@ namespace IW4MAdmin.Application.Migration if (!File.Exists(Path.Join("Database", "Database.db")) && File.Exists("Database.db")) { - log.WriteDebug("Moving database file"); + log?.WriteDebug("Moving database file"); File.Move("Database.db", Path.Join("Database", "Database.db")); } } diff --git a/IW4MAdmin.sln b/IW4MAdmin.sln index efe8e838..dbb34eeb 100644 --- a/IW4MAdmin.sln +++ b/IW4MAdmin.sln @@ -11,6 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution _customcallbacks.gsc = _customcallbacks.gsc README.md = README.md RunPublishPre.cmd = RunPublishPre.cmd + RunPublishRelease.cmd = RunPublishRelease.cmd version.txt = version.txt EndProjectSection EndProject diff --git a/Plugins/Tests/ManagerFixture.cs b/Plugins/Tests/ManagerFixture.cs index 557d257a..e8dca5a3 100644 --- a/Plugins/Tests/ManagerFixture.cs +++ b/Plugins/Tests/ManagerFixture.cs @@ -18,7 +18,9 @@ namespace Tests { File.WriteAllText("test_mp.log", "test_log_file"); - Manager = Program.ServerManager; + IW4MAdmin.Application.Localization.Configure.Initialize("en-US"); + + Manager = ApplicationManager.GetInstance(); var config = new ApplicationConfiguration { @@ -43,6 +45,7 @@ namespace Tests Manager.ConfigHandler.Set(config); Manager.Init().Wait(); + Task.Run(() => Manager.Start()); } diff --git a/Plugins/Tests/ManagerTests.cs b/Plugins/Tests/ManagerTests.cs index 4e8f447e..1f8a1a7b 100644 --- a/Plugins/Tests/ManagerTests.cs +++ b/Plugins/Tests/ManagerTests.cs @@ -188,6 +188,22 @@ namespace Tests resetEvent.Wait(5000); } + + [Fact] + public void PrintCommands() + { + var sb = new StringBuilder(); + + sb.AppendLine("|Name |Alias|Description |Requires Target|Syntax |Required Level|"); + sb.AppendLine("|--------------| -----| --------------------------------------------------------| -----------------| -------------| ----------------|"); + + foreach (var command in Manager.GetCommands().OrderByDescending(c => c.Permission).ThenBy(c => c.Name)) + { + sb.AppendLine($"|{command.Name}|{command.Alias}|{command.Description}|{command.RequiresTarget}|{command.Syntax.Substring(8).EscapeMarkdown()}|{command.Permission}|"); + } + + Assert.True(false, sb.ToString()); + } } } diff --git a/README.md b/README.md index f831df69..20953343 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,15 @@ _______ ### About **IW4MAdmin** is an administration tool for [IW4x](https://iw4xcachep26muba.onion.link/), [Pluto T6](https://forum.plutonium.pw/category/33/plutonium-t6), ~~[Pluto IW5](https://forum.plutonium.pw/category/5/plutonium-iw5)~~, and most Call of DutyŽ dedicated servers. It allows complete control of your server; from changing maps, to banning players, **IW4MAdmin** monitors and records activity on your server(s). With plugin support, extending its functionality is a breeze. ### Download -Latest binary builds are always available at https://raidmax.org/IW4MAdmin +Latest binary builds are always available at: +- [RaidMax](https://raidmax.org/IW4MAdmin) +- [GitHub](https://github.com/RaidMax/IW4M-Admin/releases) --- ### Setup **IW4MAdmin** requires minimal effort to get up and running. #### Prerequisites -* [.NET Core 2.1 Runtime](https://www.microsoft.com/net/download) *or newer* +* [.NET Core 2.1.5 Runtime](https://www.microsoft.com/net/download) *or newer* #### Installation 1. Install .NET Core Runtime 2. Extract `IW4MAdmin-.zip` @@ -105,6 +107,11 @@ If you wish to further customize your experience of **IW4MAdmin**, the following `ConnectionString` * Specifies the [connection string](https://www.connectionstrings.com/mysql/) to a MySQL server that is used instead of SQLite * Default — `null` + +`DatabaseProvider` +* Specifies the database provider **IW4MAdmin** should use +* Possible values — `sqlite`, `mysql`, `postgresql` +* Default — `sqlite` `RConPollRate` * Specifies (in milliseconds) how often to poll each server for updates @@ -163,9 +170,9 @@ If you wish to further customize your experience of **IW4MAdmin**, the following ___ ### Commands -|Name |Alias|Description |Requires Target|Syntax |Required Level| -|--------------| -----| --------------------------------------------------------| -----------------| -------------| ----------------| -|prune|pa|demote any privileged clients that have not connected recently (defaults to 30 days)|False|!pa \|Owner| +|Name |Alias|Description |Requires Target|Syntax |Required Level| +|--------------| -----| --------------------------------------------------------| -----------------| -------------| ---------------| +|prune|pa|demote any trusted clients that have not connected recently (defaults to 30 days)|False|!pa \|Owner| |quit|q|quit IW4MAdmin|False|!q |Owner| |rcon|rcon|send rcon command to server|False|!rcon \|Owner| |ban|b|permanently ban a client from the server|True|!b \ \|SeniorAdmin| @@ -190,24 +197,21 @@ ___ |unflag|uf|Remove flag for client|True|!uf \|Moderator| |uptime|up|get current application running time|False|!up |Moderator| |usage|us|get application memory usage|False|!us |Moderator| -|balance|bal|balance teams|False|!bal |Trusted| -|login|li|login using password|False|!li \|Trusted| |warn|w|warn client for infringing rules|True|!w \ \|Trusted| |warnclear|wc|remove all warnings for a client|True|!wc \|Trusted| |admins|a|list currently connected privileged clients|False|!a |User| |getexternalip|ip|view your external IP address|False|!ip |User| |help|h|list all available commands|False|!h \|User| -|mostplayed|mp|view the top 5 dedicated players on the server|False|!mp |User| +|nextmap|nm|view next map in rotation|False|!nm |User| |owner|iamgod|claim ownership of the server|False|!iamgod |User| |ping|pi|get client's latency|False|!pi \|User| |privatemessage|pm|send message to other client|True|!pm \ \|User| |report|rep|report a client for suspicious behavior|True|!rep \ \|User| -|resetstats|rs|reset your stats to factory-new|False|!rs |User| |rules|r|list server rules|False|!r |User| -|stats|xlrstats|view your stats|False|!xlrstats \|User| -|topstats|ts|view the top 5 players in this server|False|!ts |User| +|setgravatar|sg|set gravatar for webfront profile|False|!sg \|User| |whoami|who|give information about yourself|False|!who |User| + _These commands include all shipped plugin commands._ --- @@ -302,6 +306,11 @@ ___ #### VPN Detection [Script Plugin] - This plugin detects if a client is using a VPN and kicks them if they are - To disable this plugin, delete `Plugins\VPNDetection.js` +- Adding ClientIds to `vpnExceptionIds` will prevent a client from being kicked. + +#### Shared GUID Kicker [Script Plugin] +- This plugin kicks users using a specific GUID +- GUID `F4D2C30B712AC6E3` on IW4x was packed into a torrent version of the game. ___ ### Webfront `Home` @@ -432,9 +441,13 @@ python DiscordWebhook.py #### Anti-cheat This is an [IW4x](https://iw4xcachep26muba.onion.link/) only feature (wider game support planned), that uses analytics to detect aimbots and aim-assist tools. To utilize anti-cheat, enable it during setup **and** copy `_customcallbacks.gsc` from `userraw` into your `IW4x Server\userraw\scripts` folder. + The anti-cheat feature is a work in progress and as such will be constantly tweaked and may not be 100% accurate, however the goal is to deter as many cheaters as possible from IW4x. #### Database Storage -By default, all **IW4MAdmin** information is stored in `Database.db`. +By default, all **IW4MAdmin** information is stored in `Database.db`. + Should you need to reset your database, this file can simply be deleted. Additionally, this file should be preserved during updates to retain client information. -Setting the `ConnectionString` property in `IW4MAdminSettings.json` will cause **IW4MAdmin** to attempt to use a MySQL connection for database storage. \ No newline at end of file + +Setting the `ConnectionString` and `DatabaseProvider` properties in `IW4MAdminSettings.json` +will allow **IW4MAdmin** to use alternate methods for database storage. \ No newline at end of file diff --git a/version.txt b/version.txt index b890e099..a13a5388 100644 --- a/version.txt +++ b/version.txt @@ -3,15 +3,23 @@ Version 2.2: -added top player stats page -added JavaScript plugin support -added webhook script to send notifications to discord +-added remote log server to read log files on external machines -added abillity to exempt specific clients from VPN check +-added ability to tempban through webfront with customizable times -added reserved slots for privileged users -added support for localized permission levels -added linux support! -added {{NEXTMAP}}, {{ADMINS}}, and {{MOSTPLAYED}} automessage tokens +-added link to profile on client chat +-added shared GUID kicker plugin +-added PostgreSQL support +-updated welcome plugin to use webapi instead of hardcoded file -updated event api -updated webfront tweak -update client search by IP -updated event management and client authentication +-refactor RCon queries +-cleaned up the folder structure of the application -fixed some namespace discrepancies -fixed parsing of certain chat messages -fixed various bugs @@ -173,7 +181,7 @@ CHANGELOG: -fixed crash when RCON stops responding and removing a player -version on footer -?VERSION: 0.8.1 +VERSION: 0.8.1 CHANGELOG: -no longer have `world` client handle broken events -hopefully fixed an issue with clients missing connection event @@ -215,7 +223,7 @@ CHANGELOG: -stability fixes -welcome has post-fixed connection indicator -?VERSION: 0.5 +VERSION: 0.5 CHANGELOG: -close config files after reading oops -added reload command