1
0
mirror of https://github.com/RaidMax/IW4M-Admin.git synced 2025-06-07 21:58:06 -05:00

Update projects to .net 8 (#326)

* Update codebase to target .NET 8.0 and improve JSON serialization

This commit switches our target framework from .NET 6.0 to .NET 8.0 and replaces Newtonsoft.Json with System.Text.Json for serialization. The JsonConverter classes have been updated to support the new JSON model and some enhancements were applied to the codebase such as fixing a command property and updating various package references.

* Align with Develop

* Update SharedLibraryCore package version

The version of the SharedLibraryCore package reference has been updated across multiple projects from '2024.2.4.85' to '2024.2.5.9'. Meanwhile, version within SharedLibraryCore.csproj has been changed from '2024.02.04.085' to '2024.01.01.1'. Changes also include removal of .NET 8 requirement notice and reenabling of status upload to master communicator.

* Update properties in IRConParser and IRConParserConfiguration to be settable

The properties in the `IRConParser` and `IRConParserConfiguration` interfaces were updated to include setters. Previously, the properties in these interfaces were read-only. This change allows for the modifications and extensions of properties defined, thereby bolstering flexibility for the handling of games and parsers.

* Replace RestEase with Refit in API usage

Refit has been implemented as a replacement for RestEase in all API calls. As such, all related code, parameters and imports have been adjusted to function with Refit. Logic has also been added to handle certain Refit-specific behaviours. Occurrences of the RestEase package have been removed from the project.

* Enable auto-redirect in HttpClient

The HttpClient instance used in Application/Main.cs has been modified to automatically follow redirect responses. This was accomplished by adding "AllowAutoRedirect = true" to the HttpClientHandler used when creating the HttpClient.

---------

Co-authored-by: Amos <amos2580@hotmail.co.uk>
This commit is contained in:
RaidMax 2024-06-22 10:19:06 -05:00 committed by GitHub
parent 1f82596582
commit 34af7a332c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 558 additions and 432 deletions

View File

@ -1,12 +1,12 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using RestEase; using Refit;
namespace IW4MAdmin.Application.API.GameLogServer namespace IW4MAdmin.Application.API.GameLogServer
{ {
[Header("User-Agent", "IW4MAdmin-RestEase")] [Headers("User-Agent: IW4MAdmin-RestEase")]
public interface IGameLogServer public interface IGameLogServer
{ {
[Get("log/{path}/{key}")] [Get("/log/{path}/{key}")]
Task<LogInfo> Log([Path] string path, [Path] string key); Task<LogInfo> Log(string path, string key);
} }
} }

View File

@ -1,19 +1,16 @@
using Newtonsoft.Json; using System.Text.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Text;
namespace IW4MAdmin.Application.API.GameLogServer namespace IW4MAdmin.Application.API.GameLogServer
{ {
public class LogInfo public class LogInfo
{ {
[JsonProperty("success")] [JsonPropertyName("success")]
public bool Success { get; set; } public bool Success { get; set; }
[JsonProperty("length")] [JsonPropertyName("length")]
public int Length { get; set; } public int Length { get; set; }
[JsonProperty("data")] [JsonPropertyName("data")]
public string Data { get; set; } public string Data { get; set; }
[JsonProperty("next_key")] [JsonPropertyName("next_key")]
public string NextKey { get; set; } public string NextKey { get; set; }
} }
} }

View File

@ -1,5 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json; using System.Text.Json.Serialization;
using SharedLibraryCore.Helpers; using SharedLibraryCore.Helpers;
namespace IW4MAdmin.Application.API.Master namespace IW4MAdmin.Application.API.Master
@ -12,32 +12,32 @@ namespace IW4MAdmin.Application.API.Master
/// <summary> /// <summary>
/// Unique ID of the instance /// Unique ID of the instance
/// </summary> /// </summary>
[JsonProperty("id")] [JsonPropertyName("id")]
public string Id { get; set; } public string Id { get; set; }
/// <summary> /// <summary>
/// Indicates how long the instance has been running /// Indicates how long the instance has been running
/// </summary> /// </summary>
[JsonProperty("uptime")] [JsonPropertyName("uptime")]
public int Uptime { get; set; } public int Uptime { get; set; }
/// <summary> /// <summary>
/// Specifies the version of the instance /// Specifies the version of the instance
/// </summary> /// </summary>
[JsonProperty("version")] [JsonPropertyName("version")]
[JsonConverter(typeof(BuildNumberJsonConverter))] [JsonConverter(typeof(BuildNumberJsonConverter))]
public BuildNumber Version { get; set; } public BuildNumber Version { get; set; }
/// <summary> /// <summary>
/// List of servers the instance is monitoring /// List of servers the instance is monitoring
/// </summary> /// </summary>
[JsonProperty("servers")] [JsonPropertyName("servers")]
public List<ApiServer> Servers { get; set; } public List<ApiServer> Servers { get; set; }
/// <summary> /// <summary>
/// Url IW4MAdmin is listening on /// Url IW4MAdmin is listening on
/// </summary> /// </summary>
[JsonProperty("webfront_url")] [JsonPropertyName("webfront_url")]
public string WebfrontUrl { get; set; } public string WebfrontUrl { get; set; }
} }
} }

View File

@ -1,31 +1,28 @@
using Newtonsoft.Json; using System.Text.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Text;
namespace IW4MAdmin.Application.API.Master namespace IW4MAdmin.Application.API.Master
{ {
public class ApiServer public class ApiServer
{ {
[JsonProperty("id")] [JsonPropertyName("id")]
public long Id { get; set; } public long Id { get; set; }
[JsonProperty("ip")] [JsonPropertyName("ip")]
public string IPAddress { get; set; } public string IPAddress { get; set; }
[JsonProperty("port")] [JsonPropertyName("port")]
public short Port { get; set; } public short Port { get; set; }
[JsonProperty("version")] [JsonPropertyName("version")]
public string Version { get; set; } public string Version { get; set; }
[JsonProperty("gametype")] [JsonPropertyName("gametype")]
public string Gametype { get; set; } public string Gametype { get; set; }
[JsonProperty("map")] [JsonPropertyName("map")]
public string Map { get; set; } public string Map { get; set; }
[JsonProperty("game")] [JsonPropertyName("game")]
public string Game { get; set; } public string Game { get; set; }
[JsonProperty("hostname")] [JsonPropertyName("hostname")]
public string Hostname { get; set; } public string Hostname { get; set; }
[JsonProperty("clientnum")] [JsonPropertyName("clientnum")]
public int ClientNum { get; set; } public int ClientNum { get; set; }
[JsonProperty("maxclientnum")] [JsonPropertyName("maxclientnum")]
public int MaxClientNum { get; set; } public int MaxClientNum { get; set; }
} }
} }

View File

@ -1,79 +1,70 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Serialization;
using System.Threading.Tasks; using System.Threading.Tasks;
using IW4MAdmin.Application.Plugin; using IW4MAdmin.Application.Plugin;
using Newtonsoft.Json; using Refit;
using RestEase;
using SharedLibraryCore.Helpers; using SharedLibraryCore.Helpers;
namespace IW4MAdmin.Application.API.Master namespace IW4MAdmin.Application.API.Master;
public class AuthenticationId
{ {
public class AuthenticationId [JsonPropertyName("id")] public string Id { get; set; }
{ }
[JsonProperty("id")]
public string Id { get; set; } public class TokenId
} {
[JsonPropertyName("access_token")] public string AccessToken { get; set; }
public class TokenId }
{
[JsonProperty("access_token")] public class VersionInfo
public string AccessToken { get; set; } {
} [JsonPropertyName("current-version-stable")]
[JsonConverter(typeof(BuildNumberJsonConverter))]
public class VersionInfo public BuildNumber CurrentVersionStable { get; set; }
{
[JsonProperty("current-version-stable")] [JsonPropertyName("current-version-prerelease")]
[JsonConverter(typeof(BuildNumberJsonConverter))] [JsonConverter(typeof(BuildNumberJsonConverter))]
public BuildNumber CurrentVersionStable { get; set; } public BuildNumber CurrentVersionPrerelease { get; set; }
}
[JsonProperty("current-version-prerelease")]
[JsonConverter(typeof(BuildNumberJsonConverter))] public class ResultMessage
public BuildNumber CurrentVersionPrerelease { get; set; } {
} [JsonPropertyName("message")] public string Message { get; set; }
}
public class ResultMessage
{ public class PluginSubscriptionContent
[JsonProperty("message")] {
public string Message { get; set; } public string Content { get; set; }
} public PluginType Type { get; set; }
}
public class PluginSubscriptionContent
{ /// <summary>
public string Content { get; set; } /// Defines the capabilities of the master API
public PluginType Type { get; set; } /// </summary>
} [Headers("User-Agent: IW4MAdmin-RestEase")]
public interface IMasterApi
{
/// <summary> [Post("/authenticate")]
/// Defines the capabilities of the master API Task<TokenId> Authenticate([Body] AuthenticationId Id);
/// </summary>
[Header("User-Agent", "IW4MAdmin-RestEase")] [Post("/instance/")]
public interface IMasterApi Task<IApiResponse<ResultMessage>> AddInstance([Body] ApiInstance instance, [Header("Authorization")] string authorization);
{
[Header("Authorization")] [Put("/instance/{id}")]
string AuthorizationToken { get; set; } Task<IApiResponse<ResultMessage>> UpdateInstance(string id, [Body] ApiInstance instance, [Header("Authorization")] string authorization);
[Post("authenticate")] [Get("/version/{apiVersion}")]
Task<TokenId> Authenticate([Body] AuthenticationId Id); Task<VersionInfo> GetVersion(int apiVersion);
[Post("instance/")] [Get("/localization")]
[AllowAnyStatusCode] Task<List<SharedLibraryCore.Localization.Layout>> GetLocalization();
Task<Response<ResultMessage>> AddInstance([Body] ApiInstance instance);
[Get("/localization/{languageTag}")]
[Put("instance/{id}")] Task<SharedLibraryCore.Localization.Layout> GetLocalization(string languageTag);
[AllowAnyStatusCode]
Task<Response<ResultMessage>> UpdateInstance([Path] string id, [Body] ApiInstance instance); [Get("/plugin_subscriptions")]
Task<IEnumerable<PluginSubscriptionContent>> GetPluginSubscription([Query("instance_id")] Guid instanceId,
[Get("version/{apiVersion}")] [Query("subscription_id")] string subscription_id);
Task<VersionInfo> GetVersion([Path] int apiVersion);
[Get("localization")]
Task<List<SharedLibraryCore.Localization.Layout>> GetLocalization();
[Get("localization/{languageTag}")]
Task<SharedLibraryCore.Localization.Layout> GetLocalization([Path("languageTag")] string languageTag);
[Get("plugin_subscriptions")]
Task<IEnumerable<PluginSubscriptionContent>> GetPluginSubscription([Query("instance_id")] Guid instanceId, [Query("subscription_id")] string subscription_id);
}
} }

View File

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish> <MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
<PackageId>RaidMax.IW4MAdmin.Application</PackageId> <PackageId>RaidMax.IW4MAdmin.Application</PackageId>
<Version>2020.0.0.0</Version> <Version>2020.0.0.0</Version>
@ -21,20 +21,21 @@
<Win32Resource /> <Win32Resource />
<RootNamespace>IW4MAdmin.Application</RootNamespace> <RootNamespace>IW4MAdmin.Application</RootNamespace>
<PublishWithAspNetCoreTargetManifest>false</PublishWithAspNetCoreTargetManifest> <PublishWithAspNetCoreTargetManifest>false</PublishWithAspNetCoreTargetManifest>
<Nullable>disable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Jint" Version="3.0.0-beta-2049" /> <PackageReference Include="Jint" Version="3.0.0" />
<PackageReference Include="MaxMind.GeoIP2" Version="5.1.0" /> <PackageReference Include="MaxMind.GeoIP2" Version="5.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.8"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.1">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="RestEase" Version="1.5.7" /> <PackageReference Include="Refit" Version="7.0.0" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" /> <PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageReference Include="System.CommandLine.DragonFruit" Version="0.4.0-alpha.22272.1" /> <PackageReference Include="System.CommandLine.DragonFruit" Version="0.4.0-alpha.22272.1" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
</ItemGroup> </ItemGroup>
<PropertyGroup> <PropertyGroup>

View File

@ -82,7 +82,7 @@ namespace IW4MAdmin.Application.IO
{ {
if ((gameEvent.RequiredEntity & GameEvent.EventRequiredEntity.Origin) == GameEvent.EventRequiredEntity.Origin && gameEvent.Origin.NetworkId != Utilities.WORLD_ID) if ((gameEvent.RequiredEntity & GameEvent.EventRequiredEntity.Origin) == GameEvent.EventRequiredEntity.Origin && gameEvent.Origin.NetworkId != Utilities.WORLD_ID)
{ {
gameEvent.Origin = _server.GetClientsAsList().First(_client => _client.NetworkId == gameEvent.Origin?.NetworkId);; gameEvent.Origin = _server.GetClientsAsList().First(_client => _client.NetworkId == gameEvent.Origin?.NetworkId);
} }
if ((gameEvent.RequiredEntity & GameEvent.EventRequiredEntity.Target) == GameEvent.EventRequiredEntity.Target) if ((gameEvent.RequiredEntity & GameEvent.EventRequiredEntity.Target) == GameEvent.EventRequiredEntity.Target)

View File

@ -1,5 +1,4 @@
using IW4MAdmin.Application.API.GameLogServer; using IW4MAdmin.Application.API.GameLogServer;
using RestEase;
using SharedLibraryCore; using SharedLibraryCore;
using SharedLibraryCore.Interfaces; using SharedLibraryCore.Interfaces;
using System; using System;
@ -7,6 +6,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Refit;
using ILogger = Microsoft.Extensions.Logging.ILogger; using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.IO namespace IW4MAdmin.Application.IO
@ -25,7 +25,7 @@ namespace IW4MAdmin.Application.IO
public GameLogReaderHttp(Uri[] gameLogServerUris, IEventParser parser, ILogger<GameLogReaderHttp> logger) public GameLogReaderHttp(Uri[] gameLogServerUris, IEventParser parser, ILogger<GameLogReaderHttp> logger)
{ {
_eventParser = parser; _eventParser = parser;
_logServerApi = RestClient.For<IGameLogServer>(gameLogServerUris[0].ToString()); _logServerApi = RestService.For<IGameLogServer>(gameLogServerUris[0].ToString());
_safeLogPath = gameLogServerUris[1].LocalPath.ToBase64UrlSafeString(); _safeLogPath = gameLogServerUris[1].LocalPath.ToBase64UrlSafeString();
_logger = logger; _logger = logger;
} }

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using SharedLibraryCore.Configuration; using SharedLibraryCore.Configuration;
using ILogger = Microsoft.Extensions.Logging.ILogger; using ILogger = Microsoft.Extensions.Logging.ILogger;
@ -59,11 +60,11 @@ namespace IW4MAdmin.Application.Localization
var localizationDict = new Dictionary<string, string>(); var localizationDict = new Dictionary<string, string>();
foreach (string filePath in localizationFiles) foreach (var filePath in localizationFiles)
{ {
var localizationContents = File.ReadAllText(filePath, Encoding.UTF8); var localizationContents = File.ReadAllText(filePath, Encoding.UTF8);
var eachLocalizationFile = Newtonsoft.Json.JsonConvert.DeserializeObject<SharedLibraryCore.Localization.Layout>(localizationContents); var eachLocalizationFile = JsonSerializer.Deserialize<SharedLibraryCore.Localization.Layout>(localizationContents);
if (eachLocalizationFile == null) if (eachLocalizationFile is null)
{ {
continue; continue;
} }
@ -72,7 +73,7 @@ namespace IW4MAdmin.Application.Localization
{ {
if (!localizationDict.TryAdd(item.Key, item.Value)) if (!localizationDict.TryAdd(item.Key, item.Value))
{ {
logger.LogError("Could not add locale string {key} to localization", item.Key); logger.LogError("Could not add locale string {Key} to localization", item.Key);
} }
} }
} }

View File

@ -5,7 +5,6 @@ using IW4MAdmin.Application.Meta;
using IW4MAdmin.Application.Migration; using IW4MAdmin.Application.Migration;
using IW4MAdmin.Application.Misc; using IW4MAdmin.Application.Misc;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using RestEase;
using SharedLibraryCore; using SharedLibraryCore;
using SharedLibraryCore.Configuration; using SharedLibraryCore.Configuration;
using SharedLibraryCore.Database.Models; using SharedLibraryCore.Database.Models;
@ -39,6 +38,7 @@ using ILogger = Microsoft.Extensions.Logging.ILogger;
using IW4MAdmin.Plugins.Stats.Client.Abstractions; using IW4MAdmin.Plugins.Stats.Client.Abstractions;
using IW4MAdmin.Plugins.Stats.Client; using IW4MAdmin.Plugins.Stats.Client;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Refit;
using Stats.Client.Abstractions; using Stats.Client.Abstractions;
using Stats.Client; using Stats.Client;
using Stats.Config; using Stats.Config;
@ -94,15 +94,6 @@ namespace IW4MAdmin.Application
Console.WriteLine($" Version {Utilities.GetVersionAsString()}"); Console.WriteLine($" Version {Utilities.GetVersionAsString()}");
Console.WriteLine("====================================================="); Console.WriteLine("=====================================================");
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("!!!! IMPORTANT !!!!");
Console.WriteLine("The next update of IW4MAdmin will require .NET 8.");
Console.WriteLine("This is a breaking change!");
Console.WriteLine(
"Please update the ASP.NET Core Runtime: https://dotnet.microsoft.com/en-us/download/dotnet/8.0");
Console.WriteLine("!!!!!!!!!!!!!!!!!!!");
Console.ForegroundColor = ConsoleColor.Gray;
await LaunchAsync(); await LaunchAsync();
} }
@ -451,12 +442,12 @@ namespace IW4MAdmin.Application
var masterUri = Utilities.IsDevelopment var masterUri = Utilities.IsDevelopment
? new Uri("http://127.0.0.1:8080") ? new Uri("http://127.0.0.1:8080")
: appConfig?.MasterUrl ?? new ApplicationConfiguration().MasterUrl; : appConfig?.MasterUrl ?? new ApplicationConfiguration().MasterUrl;
var httpClient = new HttpClient var httpClient = new HttpClient(new HttpClientHandler {AllowAutoRedirect = true})
{ {
BaseAddress = masterUri, BaseAddress = masterUri,
Timeout = TimeSpan.FromSeconds(15) Timeout = TimeSpan.FromSeconds(15)
}; };
var masterRestClient = RestClient.For<IMasterApi>(httpClient); var masterRestClient = RestService.For<IMasterApi>(httpClient);
var translationLookup = Configure.Initialize(Utilities.DefaultLogger, masterRestClient, appConfig); var translationLookup = Configure.Initialize(Utilities.DefaultLogger, masterRestClient, appConfig);
if (appConfig == null) if (appConfig == null)
@ -469,10 +460,7 @@ namespace IW4MAdmin.Application
// register override level names // register override level names
foreach (var (key, value) in appConfig.OverridePermissionLevelNames) foreach (var (key, value) in appConfig.OverridePermissionLevelNames)
{ {
if (!Utilities.PermissionLevelOverrides.ContainsKey(key)) Utilities.PermissionLevelOverrides.TryAdd(key, value);
{
Utilities.PermissionLevelOverrides.Add(key, value);
}
} }
// build the dependency list // build the dependency list

View File

@ -1,5 +1,4 @@
using IW4MAdmin.Application.API.Master; using IW4MAdmin.Application.API.Master;
using RestEase;
using SharedLibraryCore; using SharedLibraryCore;
using SharedLibraryCore.Configuration; using SharedLibraryCore.Configuration;
using SharedLibraryCore.Helpers; using SharedLibraryCore.Helpers;
@ -9,6 +8,7 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Refit;
using ILogger = Microsoft.Extensions.Logging.ILogger; using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace IW4MAdmin.Application.Misc namespace IW4MAdmin.Application.Misc
@ -28,6 +28,7 @@ namespace IW4MAdmin.Application.Misc
private readonly int _apiVersion = 1; private readonly int _apiVersion = 1;
private bool _firstHeartBeat = true; private bool _firstHeartBeat = true;
private static readonly TimeSpan Interval = TimeSpan.FromSeconds(30); private static readonly TimeSpan Interval = TimeSpan.FromSeconds(30);
private string _authorizationToken;
public MasterCommunication(ILogger<MasterCommunication> logger, ApplicationConfiguration appConfig, ITranslationLookup translationLookup, IMasterApi apiInstance, IManager manager) public MasterCommunication(ILogger<MasterCommunication> logger, ApplicationConfiguration appConfig, ITranslationLookup translationLookup, IMasterApi apiInstance, IManager manager)
{ {
@ -128,7 +129,7 @@ namespace IW4MAdmin.Application.Misc
Id = _appConfig.Id Id = _appConfig.Id
}); });
_apiInstance.AuthorizationToken = $"Bearer {token.AccessToken}"; _authorizationToken = $"Bearer {token.AccessToken}";
} }
var instance = new ApiInstance var instance = new ApiInstance
@ -153,22 +154,22 @@ namespace IW4MAdmin.Application.Misc
WebfrontUrl = _appConfig.WebfrontUrl WebfrontUrl = _appConfig.WebfrontUrl
}; };
Response<ResultMessage> response; IApiResponse<ResultMessage> response;
if (_firstHeartBeat) if (_firstHeartBeat)
{ {
response = await _apiInstance.AddInstance(instance); response = await _apiInstance.AddInstance(instance, _authorizationToken);
} }
else else
{ {
response = await _apiInstance.UpdateInstance(instance.Id, instance); response = await _apiInstance.UpdateInstance(instance.Id, instance, _authorizationToken);
_firstHeartBeat = false; _firstHeartBeat = false;
} }
if (response.ResponseMessage.StatusCode != System.Net.HttpStatusCode.OK) if (response.StatusCode != System.Net.HttpStatusCode.OK)
{ {
_logger.LogWarning("Non success response code from master is {StatusCode}, message is {Message}", response.ResponseMessage.StatusCode, response.StringContent); _logger.LogWarning("Non success response code from master is {StatusCode}, message is {Message}", response.StatusCode, response.Error?.Content);
} }
} }
} }

View File

@ -1,150 +1,255 @@
using Newtonsoft.Json; using SharedLibraryCore;
using Newtonsoft.Json.Linq;
using SharedLibraryCore;
using SharedLibraryCore.Database.Models; using SharedLibraryCore.Database.Models;
using System; using System;
using System.Net; using System.Net;
using System.Text.Json;
using System.Text.Json.Serialization;
using Data.Models; using Data.Models;
using static SharedLibraryCore.Database.Models.EFClient; using static SharedLibraryCore.Database.Models.EFClient;
using static SharedLibraryCore.GameEvent; using static SharedLibraryCore.GameEvent;
namespace IW4MAdmin.Application.Misc namespace IW4MAdmin.Application.Misc;
public class IPAddressConverter : JsonConverter<IPAddress>
{ {
class IPAddressConverter : JsonConverter public override IPAddress Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{ {
public override bool CanConvert(Type objectType) var ipAddressString = reader.GetString();
{ return IPAddress.Parse(ipAddressString);
return (objectType == typeof(IPAddress));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return IPAddress.Parse((string)reader.Value);
}
} }
class IPEndPointConverter : JsonConverter public override void Write(Utf8JsonWriter writer, IPAddress value, JsonSerializerOptions options)
{ {
public override bool CanConvert(Type objectType) writer.WriteStringValue(value.ToString());
{ }
return (objectType == typeof(IPEndPoint)); }
}
public class IPEndPointConverter : JsonConverter<IPEndPoint>
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
{ public override IPEndPoint Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
IPEndPoint ep = (IPEndPoint)value; {
JObject jo = new JObject(); IPAddress address = null;
jo.Add("Address", JToken.FromObject(ep.Address, serializer)); var port = 0;
jo.Add("Port", ep.Port);
jo.WriteTo(writer); while (reader.Read())
} {
if (reader.TokenType == JsonTokenType.PropertyName)
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
{ var propertyName = reader.GetString();
JObject jo = JObject.Load(reader); reader.Read();
IPAddress address = jo["Address"].ToObject<IPAddress>(serializer); switch (propertyName)
int port = (int)jo["Port"]; {
return new IPEndPoint(address, port); case "Address":
} var addressString = reader.GetString();
} address = IPAddress.Parse(addressString);
break;
class ClientEntityConverter : JsonConverter case "Port":
{ port = reader.GetInt32();
public override bool CanConvert(Type objectType) => objectType == typeof(EFClient); break;
}
public override object ReadJson(JsonReader reader, Type objectType,object existingValue, JsonSerializer serializer) }
{
if (reader.Value == null) if (reader.TokenType == JsonTokenType.EndObject)
{ {
return null; break;
} }
}
var jsonObject = JObject.Load(reader);
return new IPEndPoint(address, port);
return new EFClient }
{
NetworkId = (long)jsonObject["NetworkId"], public override void Write(Utf8JsonWriter writer, IPEndPoint value, JsonSerializerOptions options)
ClientNumber = (int)jsonObject["ClientNumber"], {
State = Enum.Parse<ClientState>(jsonObject["state"].ToString()), writer.WriteStartObject();
CurrentAlias = new EFAlias() writer.WriteString("Address", value.Address.ToString());
{ writer.WriteNumber("Port", value.Port);
IPAddress = (int?)jsonObject["IPAddress"], writer.WriteEndObject();
Name = jsonObject["Name"].ToString() }
} }
};
} public class ClientEntityConverter : JsonConverter<EFClient>
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) public override EFClient Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{ {
var client = value as EFClient; if (reader.TokenType == JsonTokenType.Null)
var jsonObject = new JObject {
{ return null;
{ "NetworkId", client.NetworkId }, }
{ "ClientNumber", client.ClientNumber },
{ "IPAddress", client.CurrentAlias?.IPAddress }, long networkId = default;
{ "Name", client.CurrentAlias?.Name }, int clientNumber = default;
{ "State", (int)client.State } ClientState state = default;
}; var currentAlias = new EFAlias();
int? ipAddress = null;
jsonObject.WriteTo(writer); string name = null;
}
} while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
{
class GameEventConverter : JsonConverter if (reader.TokenType == JsonTokenType.PropertyName)
{ {
public override bool CanConvert(Type objectType) =>objectType == typeof(GameEvent); var propertyName = reader.GetString();
reader.Read(); // Advance to the value.
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) switch (propertyName)
{ {
var jsonObject = JObject.Load(reader); case "NetworkId":
networkId = reader.GetInt64();
return new GameEvent break;
{ case "ClientNumber":
Type = Enum.Parse<EventType>(jsonObject["Type"].ToString()), clientNumber = reader.GetInt32();
Subtype = jsonObject["Subtype"]?.ToString(), break;
Source = Enum.Parse<EventSource>(jsonObject["Source"].ToString()), case "State":
RequiredEntity = Enum.Parse<EventRequiredEntity>(jsonObject["RequiredEntity"].ToString()), state = (ClientState)reader.GetInt32();
Data = jsonObject["Data"].ToString(), break;
Message = jsonObject["Message"].ToString(), case "IPAddress":
GameTime = (int?)jsonObject["GameTime"], ipAddress = reader.TokenType != JsonTokenType.Null ? reader.GetInt32() : null;
Origin = jsonObject["Origin"]?.ToObject<EFClient>(serializer), break;
Target = jsonObject["Target"]?.ToObject<EFClient>(serializer), case "Name":
ImpersonationOrigin = jsonObject["ImpersonationOrigin"]?.ToObject<EFClient>(serializer), name = reader.GetString();
IsRemote = (bool)jsonObject["IsRemote"], break;
Extra = null, // fix }
Time = (DateTime)jsonObject["Time"], }
IsBlocking = (bool)jsonObject["IsBlocking"] }
};
} currentAlias.IPAddress = ipAddress;
currentAlias.Name = name;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ return new EFClient
var gameEvent = value as GameEvent; {
NetworkId = networkId,
var jsonObject = new JObject ClientNumber = clientNumber,
{ State = state,
{ "Type", (int)gameEvent.Type }, CurrentAlias = currentAlias
{ "Subtype", gameEvent.Subtype }, };
{ "Source", (int)gameEvent.Source }, }
{ "RequiredEntity", (int)gameEvent.RequiredEntity },
{ "Data", gameEvent.Data }, public override void Write(Utf8JsonWriter writer, EFClient value, JsonSerializerOptions options)
{ "Message", gameEvent.Message }, {
{ "GameTime", gameEvent.GameTime }, writer.WriteStartObject();
{ "Origin", gameEvent.Origin != null ? JToken.FromObject(gameEvent.Origin, serializer) : null },
{ "Target", gameEvent.Target != null ? JToken.FromObject(gameEvent.Target, serializer) : null }, writer.WriteNumber("NetworkId", value.NetworkId);
{ "ImpersonationOrigin", gameEvent.ImpersonationOrigin != null ? JToken.FromObject(gameEvent.ImpersonationOrigin, serializer) : null}, writer.WriteNumber("ClientNumber", value.ClientNumber);
{ "IsRemote", gameEvent.IsRemote }, writer.WriteString("State", value.State.ToString());
{ "Extra", gameEvent.Extra?.ToString() },
{ "Time", gameEvent.Time }, if (value.CurrentAlias != null)
{ "IsBlocking", gameEvent.IsBlocking } {
}; writer.WriteNumber("IPAddress", value.CurrentAlias.IPAddress ?? 0);
writer.WriteString("Name", value.CurrentAlias.Name);
jsonObject.WriteTo(writer); }
} else
{
writer.WriteNull("IPAddress");
writer.WriteNull("Name");
}
writer.WriteEndObject();
}
}
public class GameEventConverter : JsonConverter<GameEvent>
{
public override GameEvent Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null)
{
return null;
}
var gameEvent = new GameEvent();
while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
var propertyName = reader.GetString();
reader.Read();
switch (propertyName)
{
case "Type":
gameEvent.Type = (EventType)reader.GetInt32();
break;
case "Subtype":
gameEvent.Subtype = reader.GetString();
break;
case "Source":
gameEvent.Source = (EventSource)reader.GetInt32();
break;
case "RequiredEntity":
gameEvent.RequiredEntity = (EventRequiredEntity)reader.GetInt32();
break;
case "Data":
gameEvent.Data = reader.GetString();
break;
case "Message":
gameEvent.Message = reader.GetString();
break;
case "GameTime":
gameEvent.GameTime = reader.TokenType != JsonTokenType.Null ? reader.GetInt32() : null;
break;
case "Origin":
gameEvent.Origin = JsonSerializer.Deserialize<EFClient>(ref reader, options);
break;
case "Target":
gameEvent.Target = JsonSerializer.Deserialize<EFClient>(ref reader, options);
break;
case "ImpersonationOrigin":
gameEvent.ImpersonationOrigin = JsonSerializer.Deserialize<EFClient>(ref reader, options);
break;
case "IsRemote":
gameEvent.IsRemote = reader.GetBoolean();
break;
case "Time":
gameEvent.Time = reader.GetDateTime();
break;
case "IsBlocking":
gameEvent.IsBlocking = reader.GetBoolean();
break;
}
}
}
return gameEvent;
}
public override void Write(Utf8JsonWriter writer, GameEvent value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WriteNumber("Type", (int)value.Type);
writer.WriteString("Subtype", value.Subtype);
writer.WriteNumber("Source", (int)value.Source);
writer.WriteNumber("RequiredEntity", (int)value.RequiredEntity);
writer.WriteString("Data", value.Data);
writer.WriteString("Message", value.Message);
if (value.GameTime.HasValue)
{
writer.WriteNumber("GameTime", value.GameTime.Value);
}
else
{
writer.WriteNull("GameTime");
}
if (value.Origin != null)
{
writer.WritePropertyName("Origin");
JsonSerializer.Serialize(writer, value.Origin, options);
}
if (value.Target != null)
{
writer.WritePropertyName("Target");
JsonSerializer.Serialize(writer, value.Target, options);
}
if (value.ImpersonationOrigin != null)
{
writer.WritePropertyName("ImpersonationOrigin");
JsonSerializer.Serialize(writer, value.ImpersonationOrigin, options);
}
writer.WriteBoolean("IsRemote", value.IsRemote);
writer.WriteString("Time", value.Time.ToString("o"));
writer.WriteBoolean("IsBlocking", value.IsBlocking);
writer.WriteEndObject();
} }
} }

View File

@ -23,6 +23,7 @@ using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Exceptions; using SharedLibraryCore.Exceptions;
using SharedLibraryCore.Interfaces; using SharedLibraryCore.Interfaces;
using ILogger = Microsoft.Extensions.Logging.ILogger; using ILogger = Microsoft.Extensions.Logging.ILogger;
using Reference = Data.Models.Reference;
namespace IW4MAdmin.Application.Plugin.Script namespace IW4MAdmin.Application.Plugin.Script
{ {

View File

@ -26,6 +26,7 @@ using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Interfaces.Events; using SharedLibraryCore.Interfaces.Events;
using ILogger = Microsoft.Extensions.Logging.ILogger; using ILogger = Microsoft.Extensions.Logging.ILogger;
using JavascriptEngine = Jint.Engine; using JavascriptEngine = Jint.Engine;
using Reference = Data.Models.Reference;
namespace IW4MAdmin.Application.Plugin.Script; namespace IW4MAdmin.Application.Plugin.Script;

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Configurations>Debug;Release;Prerelease</Configurations> <Configurations>Debug;Release;Prerelease</Configurations>
<Platforms>AnyCPU</Platforms> <Platforms>AnyCPU</Platforms>
<Title>RaidMax.IW4MAdmin.Data</Title> <Title>RaidMax.IW4MAdmin.Data</Title>
@ -9,16 +9,20 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="6.0.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.1">
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.1"> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.1">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Npgsql" Version="6.0.2" /> <PackageReference Include="Npgsql" Version="8.0.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.2" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.1" /> <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.0-beta.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AssemblyName>Integrations.Cod</AssemblyName> <AssemblyName>Integrations.Cod</AssemblyName>
<RootNamespace>Integrations.Cod</RootNamespace> <RootNamespace>Integrations.Cod</RootNamespace>
<Configurations>Debug;Release;Prerelease</Configurations> <Configurations>Debug;Release;Prerelease</Configurations>
@ -17,7 +17,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="protobuf-net" Version="3.2.26" /> <PackageReference Include="protobuf-net" Version="3.2.30" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<AssemblyName>Integrations.Source</AssemblyName> <AssemblyName>Integrations.Source</AssemblyName>
<RootNamespace>Integrations.Source</RootNamespace> <RootNamespace>Integrations.Source</RootNamespace>
<Configurations>Debug;Release;Prerelease</Configurations> <Configurations>Debug;Release;Prerelease</Configurations>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<LangVersion>Latest</LangVersion> <LangVersion>Latest</LangVersion>
<Configurations>Debug;Release;Prerelease</Configurations> <Configurations>Debug;Release;Prerelease</Configurations>
@ -10,7 +10,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.SyndicationFeed.ReaderWriter" Version="1.0.2" /> <PackageReference Include="Microsoft.SyndicationFeed.ReaderWriter" Version="1.0.2" />
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.3" PrivateAssets="All" /> <PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.9" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<RazorCompileOnBuild Condition="'$(CONFIG)'!='Debug'">true</RazorCompileOnBuild> <RazorCompileOnBuild Condition="'$(CONFIG)'!='Debug'">true</RazorCompileOnBuild>
<RazorCompiledOnPublish Condition="'$(CONFIG)'!='Debug'">true</RazorCompiledOnPublish> <RazorCompiledOnPublish Condition="'$(CONFIG)'!='Debug'">true</RazorCompiledOnPublish>
<PreserveCompilationContext Condition="'$(CONFIG)'!='Debug'">false</PreserveCompilationContext> <PreserveCompilationContext Condition="'$(CONFIG)'!='Debug'">false</PreserveCompilationContext>
@ -16,7 +16,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.3" PrivateAssets="All" /> <PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.9" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ApplicationIcon /> <ApplicationIcon />
<StartupObject /> <StartupObject />
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies> <CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
@ -19,7 +19,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.3" PrivateAssets="All" /> <PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.9" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -1,18 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Authors>MrAmos123</Authors> <Authors>MrAmos123</Authors>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<Configurations>Debug;Release;Prerelease</Configurations> <Configurations>Debug;Release;Prerelease</Configurations>
<Platforms>AnyCPU</Platforms> <Platforms>AnyCPU</Platforms>
<RootNamespace>IW4MAdmin.Plugins.Mute</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.3" PrivateAssets="All" /> <PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.9" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -22,7 +22,7 @@ public class Plugin : IPluginV2
public const string MuteKey = "IW4MMute"; public const string MuteKey = "IW4MMute";
public static IManager Manager { get; private set; } = null!; public static IManager Manager { get; private set; } = null!;
public static Server.Game[] SupportedGames { get; private set; } = Array.Empty<Server.Game>(); public static Server.Game[] SupportedGames { get; private set; } = Array.Empty<Server.Game>();
private static readonly string[] DisabledCommands = {nameof(PrivateMessageAdminsCommand), "PrivateMessageCommand"}; private static readonly string[] DisabledCommands = [nameof(PrivateMessageAdminsCommand), "PrivateMessageCommand"];
private readonly IInteractionRegistration _interactionRegistration; private readonly IInteractionRegistration _interactionRegistration;
private readonly IRemoteCommandService _remoteCommandService; private readonly IRemoteCommandService _remoteCommandService;
private readonly MuteManager _muteManager; private readonly MuteManager _muteManager;
@ -37,6 +37,7 @@ public class Plugin : IPluginV2
IManagementEventSubscriptions.Load += OnLoad; IManagementEventSubscriptions.Load += OnLoad;
IManagementEventSubscriptions.Unload += OnUnload; IManagementEventSubscriptions.Unload += OnUnload;
IManagementEventSubscriptions.ClientStateInitialized += OnClientStateInitialized; IManagementEventSubscriptions.ClientStateInitialized += OnClientStateInitialized;
IGameServerEventSubscriptions.ClientDataUpdated += OnClientDataUpdated; IGameServerEventSubscriptions.ClientDataUpdated += OnClientDataUpdated;

View File

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ApplicationIcon /> <ApplicationIcon />
<StartupObject /> <StartupObject />
<PackageId>RaidMax.IW4MAdmin.Plugins.ProfanityDeterment</PackageId> <PackageId>RaidMax.IW4MAdmin.Plugins.ProfanityDeterment</PackageId>
@ -16,7 +16,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.3" PrivateAssets="All" /> <PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.9" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ApplicationIcon /> <ApplicationIcon />
<StartupObject /> <StartupObject />
<PackageId>RaidMax.IW4MAdmin.Plugins.Stats</PackageId> <PackageId>RaidMax.IW4MAdmin.Plugins.Stats</PackageId>
@ -17,7 +17,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.3" PrivateAssets="All" /> <PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.9" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent"> <Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -6,8 +6,8 @@ using SharedLibraryCore.Database.Models;
using System.Linq; using System.Linq;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System.Net.Http; using System.Net.Http;
using System.Text.Json;
using System.Threading; using System.Threading;
using Newtonsoft.Json.Linq;
using Humanizer; using Humanizer;
using Data.Abstractions; using Data.Abstractions;
using Data.Models; using Data.Models;
@ -108,8 +108,9 @@ public class Plugin : IPluginV2
var response = var response =
await wc.GetStringAsync(new Uri( await wc.GetStringAsync(new Uri(
$"http://ip-api.com/json/{ip}?lang={Utilities.CurrentLocalization.LocalizationName.Split("-").First().ToLower()}")); $"http://ip-api.com/json/{ip}?lang={Utilities.CurrentLocalization.LocalizationName.Split("-").First().ToLower()}"));
var responseObj = JObject.Parse(response);
response = responseObj["country"]?.ToString(); var json = JsonDocument.Parse(response);
response = json.RootElement.TryGetProperty("country", out var countryElement) ? countryElement.GetString() : null;
return string.IsNullOrEmpty(response) return string.IsNullOrEmpty(response)
? Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_WELCOME_UNKNOWN_COUNTRY"] ? Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_WELCOME_UNKNOWN_COUNTRY"]

View File

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ApplicationIcon /> <ApplicationIcon />
<StartupObject /> <StartupObject />
<PackageId>RaidMax.IW4MAdmin.Plugins.Welcome</PackageId> <PackageId>RaidMax.IW4MAdmin.Plugins.Welcome</PackageId>
@ -20,7 +20,7 @@
</Target> </Target>
<ItemGroup> <ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.3" PrivateAssets="All" /> <PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2024.2.5.9" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -2,8 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Text.Json.Serialization;
using Data.Models.Misc; using Data.Models.Misc;
using Newtonsoft.Json;
using SharedLibraryCore.Configuration.Attributes; using SharedLibraryCore.Configuration.Attributes;
using SharedLibraryCore.Interfaces; using SharedLibraryCore.Interfaces;
using static Data.Models.Client.EFClient; using static Data.Models.Client.EFClient;

View File

@ -1,41 +1,40 @@
using System; using System;
using Newtonsoft.Json; using System.Text.Json.Serialization;
using Newtonsoft.Json.Converters; using SharedLibraryCore.Helpers;
using static Data.Models.Client.EFClient; using static Data.Models.Client.EFClient;
using static SharedLibraryCore.Server; using static SharedLibraryCore.Server;
namespace SharedLibraryCore.Configuration namespace SharedLibraryCore.Configuration;
/// <summary>
/// Config driven command properties
/// </summary>
public class CommandProperties
{ {
/// <summary> /// <summary>
/// Config driven command properties /// Specifies the command name
/// </summary> /// </summary>
public class CommandProperties public string Name { get; set; }
{
/// <summary>
/// Specifies the command name
/// </summary>
public string Name { get; set; }
/// <summary> /// <summary>
/// Alias of this command /// Alias of this command
/// </summary> /// </summary>
public string Alias { get; set; } public string Alias { get; set; }
/// <summary> /// <summary>
/// Specifies the minimum permission level needed to execute the /// Specifies the minimum permission level needed to execute the
/// </summary> /// </summary>
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(JsonStringEnumConverter))]
public Permission MinimumPermission { get; set; } public Permission MinimumPermission { get; set; }
/// <summary> /// <summary>
/// Indicates if the command can be run by another user (impersonation) /// Indicates if the command can be run by another user (impersonation)
/// </summary> /// </summary>
public bool AllowImpersonation { get; set; } public bool AllowImpersonation { get; set; }
/// <summary> /// <summary>
/// Specifies the games supporting the functionality of the command /// Specifies the games supporting the functionality of the command
/// </summary> /// </summary>
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))] [JsonConverter(typeof(GameArrayJsonConverter))]
public Game[] SupportedGames { get; set; } = Array.Empty<Game>(); public Game[] SupportedGames { get; set; } = Array.Empty<Game>();
}
} }

View File

@ -6,7 +6,7 @@ public abstract class CoreEvent
{ {
public Guid Id { get; } = Guid.NewGuid(); public Guid Id { get; } = Guid.NewGuid();
public Guid? CorrelationId { get; init; } public Guid? CorrelationId { get; init; }
public object Source { get; init; } public object Source { get; set; }
public DateTimeOffset CreatedAt { get; } = DateTimeOffset.UtcNow; public DateTimeOffset CreatedAt { get; } = DateTimeOffset.UtcNow;
public DateTimeOffset? ProcessedAt { get; set; } public DateTimeOffset? ProcessedAt { get; set; }
} }

View File

@ -1,27 +1,58 @@
using System; using System;
using Newtonsoft.Json; using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SharedLibraryCore.Helpers namespace SharedLibraryCore.Helpers;
/// <summary>
/// JSON converter for the build number
/// </summary>
public class BuildNumberJsonConverter : JsonConverter<BuildNumber>
{ {
/// <summary> public override BuildNumber Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
/// JSON converter for the build number
/// </summary>
public class BuildNumberJsonConverter : JsonConverter
{ {
public override bool CanConvert(Type objectType) var stringValue = reader.GetString();
{ return BuildNumber.Parse(stringValue);
return objectType == typeof(string);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
return BuildNumber.Parse(reader.Value.ToString());
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}
} }
}
public override void Write(Utf8JsonWriter writer, BuildNumber value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
public class GameArrayJsonConverter : JsonConverter<Server.Game[]>
{
public override Server.Game[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
List<Server.Game> games = [];
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray)
{
break;
}
var gameString = reader.GetString();
var game = Enum.Parse<Server.Game>(gameString);
games.Add(game);
}
return games.ToArray();
}
public override void Write(Utf8JsonWriter writer, Server.Game[] value, JsonSerializerOptions options)
{
writer.WriteStartArray();
foreach (var game in value)
{
writer.WriteStringValue(game.ToString());
}
writer.WriteEndArray();
}
}

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Data.Models; using Data.Models;
@ -19,6 +20,9 @@ namespace SharedLibraryCore.Interfaces
/// <returns></returns> /// <returns></returns>
Task Kick(string reason, EFClient target, EFClient origin, EFPenalty previousPenalty = null); Task Kick(string reason, EFClient target, EFClient origin, EFPenalty previousPenalty = null);
IPEndPoint ResolvedIpEndPoint { get; }
IRConParser RconParser { get; }
/// <summary> /// <summary>
/// Execute a server command /// Execute a server command
/// </summary> /// </summary>
@ -35,72 +39,72 @@ namespace SharedLibraryCore.Interfaces
/// <param name="token"><see cref="CancellationToken"/></param> /// <param name="token"><see cref="CancellationToken"/></param>
/// <returns></returns> /// <returns></returns>
Task SetDvarAsync(string name, object value, CancellationToken token = default); Task SetDvarAsync(string name, object value, CancellationToken token = default);
/// <summary> /// <summary>
/// Time the most recent match ended /// Time the most recent match ended
/// </summary> /// </summary>
DateTime? MatchEndTime { get; } DateTime? MatchEndTime { get; }
/// <summary> /// <summary>
/// Time the current match started /// Time the current match started
/// </summary> /// </summary>
DateTime? MatchStartTime { get; } DateTime? MatchStartTime { get; }
/// <summary> /// <summary>
/// List of connected clients /// List of connected clients
/// </summary> /// </summary>
IReadOnlyList<EFClient> ConnectedClients { get; } IReadOnlyList<EFClient> ConnectedClients { get; }
/// <summary> /// <summary>
/// Game code corresponding to the development studio project /// Game code corresponding to the development studio project
/// </summary> /// </summary>
Reference.Game GameCode { get; } Reference.Game GameCode { get; }
/// <summary> /// <summary>
/// Indicates if the anticheat/custom callbacks/live radar integration is enabled /// Indicates if the anticheat/custom callbacks/live radar integration is enabled
/// </summary> /// </summary>
bool IsLegacyGameIntegrationEnabled { get; } bool IsLegacyGameIntegrationEnabled { get; }
/// <summary> /// <summary>
/// Unique identifier for the server (typically ip:port) /// Unique identifier for the server (typically ip:port)
/// </summary> /// </summary>
string Id { get; } string Id { get; }
/// <summary> /// <summary>
/// Network address the server is listening on /// Network address the server is listening on
/// </summary> /// </summary>
string ListenAddress { get; } string ListenAddress { get; }
/// <summary> /// <summary>
/// Network port the server is listening on /// Network port the server is listening on
/// </summary> /// </summary>
int ListenPort { get; } int ListenPort { get; }
/// <summary> /// <summary>
/// Name of the server (hostname) /// Name of the server (hostname)
/// </summary> /// </summary>
string ServerName { get; } string ServerName { get; }
/// <summary> /// <summary>
/// Current gametype /// Current gametype
/// </summary> /// </summary>
string Gametype { get; } string Gametype { get; }
/// <summary> /// <summary>
/// Game password (required to join) /// Game password (required to join)
/// </summary> /// </summary>
string GamePassword { get; } string GamePassword { get; }
/// <summary> /// <summary>
/// Number of private client slots /// Number of private client slots
/// </summary> /// </summary>
int PrivateClientSlots { get; } int PrivateClientSlots { get; }
/// <summary> /// <summary>
/// Current map the game server is running /// Current map the game server is running
/// </summary> /// </summary>
Map Map { get; } Map Map { get; }
/// <summary> /// <summary>
/// Database id for EFServer table and references /// Database id for EFServer table and references
/// </summary> /// </summary>

View File

@ -41,6 +41,7 @@ namespace SharedLibraryCore.Interfaces
ILogger GetLogger(long serverId); ILogger GetLogger(long serverId);
IList<Server> GetServers(); IList<Server> GetServers();
List<Server> Servers { get; }
IList<IManagerCommand> GetCommands(); IList<IManagerCommand> GetCommands();
IList<MessageToken> GetMessageTokens(); IList<MessageToken> GetMessageTokens();
IList<EFClient> GetActiveClients(); IList<EFClient> GetActiveClients();

View File

@ -15,35 +15,35 @@ namespace SharedLibraryCore.Interfaces
/// <summary> /// <summary>
/// stores the game/client specific version (usually the value of the "version" DVAR) /// stores the game/client specific version (usually the value of the "version" DVAR)
/// </summary> /// </summary>
string Version { get; } string Version { get; set; }
/// <summary> /// <summary>
/// specifies the game name (usually the internal studio iteration ie: IW4, T5 etc...) /// specifies the game name (usually the internal studio iteration ie: IW4, T5 etc...)
/// </summary> /// </summary>
Game GameName { get; } Game GameName { get; set; }
/// <summary> /// <summary>
/// indicates if the game supports generating a log path from DVAR retrieval /// indicates if the game supports generating a log path from DVAR retrieval
/// of fs_game, fs_basepath, g_log /// of fs_game, fs_basepath, g_log
/// </summary> /// </summary>
bool CanGenerateLogPath { get; } bool CanGenerateLogPath { get; set; }
/// <summary> /// <summary>
/// specifies the name of the parser /// specifies the name of the parser
/// </summary> /// </summary>
string Name { get; } string Name { get; set; }
/// <summary> /// <summary>
/// specifies the type of rcon engine /// specifies the type of rcon engine
/// eg: COD, Source /// eg: COD, Source
/// </summary> /// </summary>
string RConEngine { get; } string RConEngine { get; set; }
/// <summary> /// <summary>
/// indicates that the game does not log to the mods folder (when mod is loaded), /// indicates that the game does not log to the mods folder (when mod is loaded),
/// but rather always to the fs_basegame directory /// but rather always to the fs_basegame directory
/// </summary> /// </summary>
bool IsOneLog { get; } bool IsOneLog { get; set; }
/// <summary> /// <summary>
/// retrieves the value of a given DVAR /// retrieves the value of a given DVAR
@ -54,7 +54,8 @@ namespace SharedLibraryCore.Interfaces
/// <param name="fallbackValue">default value to return if dvar retrieval fails</param> /// <param name="fallbackValue">default value to return if dvar retrieval fails</param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<Dvar<T>> GetDvarAsync<T>(IRConConnection connection, string dvarName, T fallbackValue = default, CancellationToken token = default); Task<Dvar<T>> GetDvarAsync<T>(IRConConnection connection, string dvarName, T fallbackValue = default,
CancellationToken token = default);
/// <summary> /// <summary>
/// set value of DVAR by name /// set value of DVAR by name
@ -65,7 +66,7 @@ namespace SharedLibraryCore.Interfaces
/// <param name="token"></param> /// <param name="token"></param>
/// <returns></returns> /// <returns></returns>
Task<bool> SetDvarAsync(IRConConnection connection, string dvarName, object dvarValue, CancellationToken token = default); Task<bool> SetDvarAsync(IRConConnection connection, string dvarName, object dvarValue, CancellationToken token = default);
/// <summary> /// <summary>
/// executes a console command on the server /// executes a console command on the server
/// </summary> /// </summary>

View File

@ -10,74 +10,74 @@ namespace SharedLibraryCore.Interfaces
/// <summary> /// <summary>
/// stores the command format for console commands /// stores the command format for console commands
/// </summary> /// </summary>
CommandPrefix CommandPrefixes { get; } CommandPrefix CommandPrefixes { get; set; }
/// <summary> /// <summary>
/// stores the regex info for parsing get status response /// stores the regex info for parsing get status response
/// </summary> /// </summary>
ParserRegex Status { get; } ParserRegex Status { get; set; }
/// <summary> /// <summary>
/// stores regex info for parsing the map line from rcon status response /// stores regex info for parsing the map line from rcon status response
/// </summary> /// </summary>
ParserRegex MapStatus { get; } ParserRegex MapStatus { get; set; }
/// <summary> /// <summary>
/// stores regex info for parsing the gametype line from rcon status response /// stores regex info for parsing the gametype line from rcon status response
/// </summary> /// </summary>
ParserRegex GametypeStatus { get; } ParserRegex GametypeStatus { get; set; }
/// <summary> /// <summary>
/// stores regex info for parsing hostname line from rcon status response /// stores regex info for parsing hostname line from rcon status response
/// </summary> /// </summary>
ParserRegex HostnameStatus { get; } ParserRegex HostnameStatus { get; set; }
/// <summary> /// <summary>
/// stores regex info for parsing max players line from rcon status response /// stores regex info for parsing max players line from rcon status response
/// </summary> /// </summary>
ParserRegex MaxPlayersStatus { get; } ParserRegex MaxPlayersStatus { get; set; }
/// <summary> /// <summary>
/// stores the regex info for parsing get DVAR responses /// stores the regex info for parsing get DVAR responses
/// </summary> /// </summary>
ParserRegex Dvar { get; } ParserRegex Dvar { get; set; }
/// <summary> /// <summary>
/// stores the regex info for parsing the header of a status response /// stores the regex info for parsing the header of a status response
/// </summary> /// </summary>
ParserRegex StatusHeader { get; } ParserRegex StatusHeader { get; set; }
/// <summary> /// <summary>
/// Specifies the expected response message from rcon when the server is not running /// Specifies the expected response message from rcon when the server is not running
/// </summary> /// </summary>
string ServerNotRunningResponse { get; } string ServerNotRunningResponse { get; set; }
/// <summary> /// <summary>
/// indicates if the application should wait for response from server /// indicates if the application should wait for response from server
/// when executing a command /// when executing a command
/// </summary> /// </summary>
bool WaitForResponse { get; } bool WaitForResponse { get; set; }
/// <summary> /// <summary>
/// indicates the format expected for parsed guids /// indicates the format expected for parsed guids
/// </summary> /// </summary>
NumberStyles GuidNumberStyle { get; } NumberStyles GuidNumberStyle { get; set; }
/// <summary> /// <summary>
/// specifies simple mappings for dvar names in scenarios where the needed /// specifies simple mappings for dvar names in scenarios where the needed
/// information is not stored in a traditional dvar name /// information is not stored in a traditional dvar name
/// </summary> /// </summary>
IDictionary<string, string> OverrideDvarNameMapping { get; } IDictionary<string, string> OverrideDvarNameMapping { get; set; }
/// <summary> /// <summary>
/// specifies the default dvar values for games that don't support certain dvars /// specifies the default dvar values for games that don't support certain dvars
/// </summary> /// </summary>
IDictionary<string, string> DefaultDvarValues { get; } IDictionary<string, string> DefaultDvarValues { get; set; }
/// <summary> /// <summary>
/// contains a setup of commands that have override timeouts /// contains a setup of commands that have override timeouts
/// </summary> /// </summary>
IDictionary<string, int?> OverrideCommandTimeouts { get; } IDictionary<string, int?> OverrideCommandTimeouts { get; set; }
/// <summary> /// <summary>
/// specifies how many lines can be used for ingame notice /// specifies how many lines can be used for ingame notice
@ -87,29 +87,30 @@ namespace SharedLibraryCore.Interfaces
/// <summary> /// <summary>
/// specifies how many characters can be displayed per notice line /// specifies how many characters can be displayed per notice line
/// </summary> /// </summary>
int NoticeMaxCharactersPerLine { get; } int NoticeMaxCharactersPerLine { get; set; }
/// <summary> /// <summary>
/// specifies the characters used to split a line /// specifies the characters used to split a line
/// </summary> /// </summary>
string NoticeLineSeparator { get; } string NoticeLineSeparator { get; set; }
/// <summary> /// <summary>
/// Default port the game listens to RCon requests on /// Default port the game listens to RCon requests on
/// </summary> /// </summary>
int? DefaultRConPort { get; } int? DefaultRConPort { get; set; }
/// <summary> /// <summary>
/// Default Indicator of where the game is installed (ex file path or registry entry) /// Default Indicator of where the game is installed (ex file path or registry entry)
/// </summary> /// </summary>
string DefaultInstallationDirectoryHint { get; } string DefaultInstallationDirectoryHint { get; set; }
ColorCodeMapping ColorCodeMapping { get; } ColorCodeMapping ColorCodeMapping { get; set; }
short FloodProtectInterval { get; set; }
short FloodProtectInterval { get; }
/// <summary> /// <summary>
/// indicates if diacritics (accented characters) should be normalized /// indicates if diacritics (accented characters) should be normalized
/// </summary> /// </summary>
bool ShouldRemoveDiacritics { get; } bool ShouldRemoveDiacritics { get; set; }
} }
} }

View File

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Text.Json.Serialization;
using SharedLibraryCore.Interfaces; using SharedLibraryCore.Interfaces;
namespace SharedLibraryCore.Localization namespace SharedLibraryCore.Localization
@ -8,6 +9,8 @@ namespace SharedLibraryCore.Localization
{ {
private string localizationName; private string localizationName;
public Layout() { }
public Layout(Dictionary<string, string> set) public Layout(Dictionary<string, string> set)
{ {
LocalizationIndex = new TranslationLookup LocalizationIndex = new TranslationLookup
@ -27,7 +30,7 @@ namespace SharedLibraryCore.Localization
} }
public TranslationLookup LocalizationIndex { get; set; } public TranslationLookup LocalizationIndex { get; set; }
public CultureInfo Culture { get; private set; } [JsonIgnore] public CultureInfo Culture { get; private set; }
} }
public class TranslationLookup : ITranslationLookup public class TranslationLookup : ITranslationLookup
@ -47,4 +50,4 @@ namespace SharedLibraryCore.Localization
} }
} }
} }
} }

View File

@ -2,9 +2,9 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<PackageId>RaidMax.IW4MAdmin.SharedLibraryCore</PackageId> <PackageId>RaidMax.IW4MAdmin.SharedLibraryCore</PackageId>
<Version>2023.4.5.1</Version> <Version>2024.01.01.1</Version>
<Authors>RaidMax</Authors> <Authors>RaidMax</Authors>
<Company>Forever None</Company> <Company>Forever None</Company>
<Configurations>Debug;Release;Prerelease</Configurations> <Configurations>Debug;Release;Prerelease</Configurations>
@ -19,7 +19,7 @@
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
<Description>Shared Library for IW4MAdmin</Description> <Description>Shared Library for IW4MAdmin</Description>
<PackageVersion>2023.4.5.1</PackageVersion> <PackageVersion>2024.01.01.1</PackageVersion>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn> <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup> </PropertyGroup>
@ -34,31 +34,30 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="FluentValidation" Version="11.2.1" /> <PackageReference Include="FluentValidation" Version="11.9.0" />
<PackageReference Include="Humanizer.Core" Version="2.14.1" /> <PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="Humanizer.Core.ru" Version="2.14.1" /> <PackageReference Include="Humanizer.Core.ru" Version="2.14.1" />
<PackageReference Include="Humanizer.Core.de" Version="2.14.1" /> <PackageReference Include="Humanizer.Core.de" Version="2.14.1" />
<PackageReference Include="Humanizer.Core.es" Version="2.14.1" /> <PackageReference Include="Humanizer.Core.es" Version="2.14.1" />
<PackageReference Include="Humanizer.Core.pt" Version="2.14.1" /> <PackageReference Include="Humanizer.Core.pt" Version="2.14.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Localization" Version="6.0.8" /> <PackageReference Include="Microsoft.Extensions.Localization" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
<PackageReference Include="Serilog.AspNetCore" Version="6.0.1" />
<PackageReference Include="SimpleCrypto.NetCore" Version="1.0.0" /> <PackageReference Include="SimpleCrypto.NetCore" Version="1.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Data\Data.csproj"> <ProjectReference Include="..\Data\Data.csproj">
<ReferenceOutputAssembly>true</ReferenceOutputAssembly> <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<IncludeAssets>Data.dll</IncludeAssets> <IncludeAssets>Data.dll</IncludeAssets>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent"> <Target Name="PreBuild" BeforeTargets="PreBuildEvent">

View File

@ -10,10 +10,9 @@ using SharedLibraryCore.Interfaces;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using WebfrontCore.ViewModels; using WebfrontCore.ViewModels;
namespace WebfrontCore.Controllers namespace WebfrontCore.Controllers
@ -92,15 +91,15 @@ namespace WebfrontCore.Controllers
try try
{ {
var file = JObject.Parse(content); var jsonDocument = JsonDocument.Parse(content);
} }
catch (JsonReaderException ex) catch (JsonException ex)
{ {
return BadRequest($"{fileName}: {ex.Message}"); return BadRequest($"{fileName}: {ex.Message}");
} }
var path = System.IO.Path.Join(Utilities.OperatingDirectory, "Configuration", var path = Path.Join(Utilities.OperatingDirectory, "Configuration",
fileName.Replace($"{System.IO.Path.DirectorySeparatorChar}", "")); fileName.Replace($"{Path.DirectorySeparatorChar}", ""));
// todo: move into a service at some point // todo: move into a service at some point
if (!System.IO.File.Exists(path)) if (!System.IO.File.Exists(path))

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<RazorCompileOnBuild Condition="'$(CONFIG)'!='Debug'">true</RazorCompileOnBuild> <RazorCompileOnBuild Condition="'$(CONFIG)'!='Debug'">true</RazorCompileOnBuild>
<RazorCompiledOnPublish Condition="'$(CONFIG)'!='Debug'">true</RazorCompiledOnPublish> <RazorCompiledOnPublish Condition="'$(CONFIG)'!='Debug'">true</RazorCompiledOnPublish>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc> <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
@ -46,9 +46,9 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="BuildWebCompiler2022" Version="1.14.10" /> <PackageReference Include="BuildWebCompiler2022" Version="1.14.10" />
<PackageReference Include="FluentValidation.AspNetCore" Version="11.2.2" /> <PackageReference Include="FluentValidation.AspNetCore" Version="11.3.0" />
<PackageReference Include="Microsoft.AspNetCore.ConcurrencyLimiter" Version="6.0.16" /> <PackageReference Include="Microsoft.AspNetCore.ConcurrencyLimiter" Version="8.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.8" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.1" />
<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="2.1.175" /> <PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="2.1.175" />
</ItemGroup> </ItemGroup>