From 7ff822be0f20cd23174d889e8e192dcd3256ca7f Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 14 Jan 2025 11:42:27 +0000 Subject: [PATCH] refactored File, Path and Directory usages into FileUtil and cleaned up logs --- Core/Servers/ConfigServer.cs | 17 ++-- Core/Services/I18nService.cs | 52 ++++++++--- Core/Services/LocalisationService.cs | 4 +- Core/Utils/FileUtil.cs | 5 ++ Core/Utils/ImporterUtil.cs | 125 ++------------------------- Server/Logger/AbstractFormatter.cs | 3 +- Server/Program.cs | 4 +- Server/Server.csproj | 1 + Server/appsettings.json | 15 +++- 9 files changed, 81 insertions(+), 145 deletions(-) diff --git a/Core/Servers/ConfigServer.cs b/Core/Servers/ConfigServer.cs index 1231bc25..c7c6097e 100644 --- a/Core/Servers/ConfigServer.cs +++ b/Core/Servers/ConfigServer.cs @@ -14,16 +14,19 @@ public class ConfigServer { protected ILogger _logger; protected JsonUtil _jsonUtil; + protected FileUtil _fileUtil; protected Dictionary configs = new(); - protected readonly string[] acceptableFileExtensions = [".json", ".jsonc"]; + protected readonly string[] acceptableFileExtensions = ["json", "jsonc"]; public ConfigServer( ILogger logger, - JsonUtil jsonUtil + JsonUtil jsonUtil, + FileUtil fileUtil ) { _logger = logger; _jsonUtil = jsonUtil; + _fileUtil = fileUtil; Initialize(); } @@ -45,13 +48,13 @@ public class ConfigServer // Get all filepaths var filepath = "./assets/configs/"; - var files = Directory.GetFiles(filepath); + var files = _fileUtil.GetFiles(filepath); // Add file content to result foreach (var file in files) - if (acceptableFileExtensions.Contains(Path.GetExtension(file))) + if (acceptableFileExtensions.Contains(_fileUtil.GetFileExtension(file))) { - var fileContent = File.ReadAllText(file); + var fileContent = _fileUtil.ReadFile(file); var type = GetConfigTypeByFilename(file); var deserializedContent = _jsonUtil.Deserialize(fileContent, type); @@ -61,7 +64,7 @@ public class ConfigServer throw new Exception($"Server will not run until the: {file} config error mentioned above is fixed"); } - configs[$"spt-{Path.GetFileNameWithoutExtension(file)}"] = deserializedContent; + configs[$"spt-{_fileUtil.StripExtension(file)}"] = deserializedContent; } /** TODO: deal with this: @@ -77,7 +80,7 @@ public class ConfigServer private Type GetConfigTypeByFilename(string filename) { var type = Enum.GetValues() - .First(en => en.GetValue().Contains(Path.GetFileNameWithoutExtension(filename))); + .First(en => en.GetValue().Contains(_fileUtil.StripExtension(filename))); return type.GetConfigType(); } } diff --git a/Core/Services/I18nService.cs b/Core/Services/I18nService.cs index f656d50f..dc3b96ef 100644 --- a/Core/Services/I18nService.cs +++ b/Core/Services/I18nService.cs @@ -1,10 +1,8 @@ -using System.Text.Json; -using Core.Annotations; -using Core.Utils; +using Core.Utils; +using Core.Utils.Extensions; namespace Core.Services; -[Injectable(InjectionType.Singleton)] public class I18nService { private List _locales; @@ -12,29 +10,39 @@ public class I18nService private string _defaultLocale; private string _directory; private JsonUtil _jsonUtil; + private FileUtil _fileUtil; private string _setLocale; private Dictionary> _loadedLocales = new(); - public I18nService(JsonUtil jsonUtil, List locales, Dictionary fallbacks, string defaultLocale, string directory) + public I18nService( + FileUtil fileUtil, + JsonUtil jsonUtil, + List locales, + Dictionary fallbacks, + string defaultLocale, + string directory + ) { _locales = locales; _fallbacks = fallbacks; _defaultLocale = defaultLocale; _directory = directory; _jsonUtil = jsonUtil; + _fileUtil = fileUtil; Initialize(); } private void Initialize() { - var files = Directory.GetFiles(_directory, "*.json"); - if (files.Length == 0) + var files = _fileUtil.GetFiles(_directory, true).Where(f => _fileUtil.GetFileExtension(f) == "json").ToList(); + if (files.Count == 0) throw new Exception($"Localisation files in directory {_directory} not found."); foreach (var file in files) - _loadedLocales.Add(Path.GetFileNameWithoutExtension(file), - _jsonUtil.Deserialize>(File.ReadAllText(file)) ?? new Dictionary()); + _loadedLocales.Add(_fileUtil.StripExtension(file), + _jsonUtil.Deserialize>(_fileUtil.ReadFile(file)) ?? + new Dictionary()); if (!_loadedLocales.ContainsKey(_defaultLocale)) throw new Exception($"The default locale '{_defaultLocale}' does not exist on the loaded locales."); @@ -53,7 +61,8 @@ public class I18nService { var foundFallbackLocale = fallback.First().Value; if (!_loadedLocales.ContainsKey(foundFallbackLocale)) - throw new Exception($"Locale '{locale}' was not defined, and the found fallback locale did not match any of the loaded locales."); + throw new Exception( + $"Locale '{locale}' was not defined, and the found fallback locale did not match any of the loaded locales."); _setLocale = foundFallbackLocale; } @@ -75,9 +84,26 @@ public class I18nService return value; } - public string GetLocalised(string key, params object[] args) + public string GetLocalised(string key, object? args) { - // TODO: Deal with arguments - return GetLocalised(key); + var rawLocalizedString = GetLocalised(key); + if (args == null) + return rawLocalizedString; + if (args is string value) + { + return rawLocalizedString.Replace("%s", value); + } + else + { + foreach (var propertyInfo in args.GetType().GetProperties()) + { + var localizedName = $"{{{{{propertyInfo.GetJsonName()}}}}}"; + if (rawLocalizedString.Contains(localizedName)) + { + rawLocalizedString.Replace(localizedName, propertyInfo.GetValue(args, null)?.ToString() ?? string.Empty); + } + } + return rawLocalizedString; + } } } diff --git a/Core/Services/LocalisationService.cs b/Core/Services/LocalisationService.cs index 98c45e73..bb664fb3 100644 --- a/Core/Services/LocalisationService.cs +++ b/Core/Services/LocalisationService.cs @@ -19,7 +19,8 @@ public class LocalisationService RandomUtil randomUtil, DatabaseServer databaseServer, LocaleService localeService, - JsonUtil jsonUtil + JsonUtil jsonUtil, + FileUtil fileUtil ) { _logger = logger; @@ -27,6 +28,7 @@ public class LocalisationService _databaseServer = databaseServer; _localeService = localeService; _i18nService = new I18nService( + fileUtil, jsonUtil, localeService.GetServerSupportedLocales(), localeService.GetLocaleFallbacks(), diff --git a/Core/Utils/FileUtil.cs b/Core/Utils/FileUtil.cs index a8242d4d..99df8e35 100644 --- a/Core/Utils/FileUtil.cs +++ b/Core/Utils/FileUtil.cs @@ -25,6 +25,11 @@ public class FileUtil return Path.GetExtension(path).Replace(".", ""); } + public string GetFileName(string path) + { + return Path.GetFileName(path); + } + public string StripExtension(string path, bool keepPath = false) { return keepPath ? path.Split('.').First() : Path.GetFileNameWithoutExtension(path); diff --git a/Core/Utils/ImporterUtil.cs b/Core/Utils/ImporterUtil.cs index b16afbd6..953253be 100644 --- a/Core/Utils/ImporterUtil.cs +++ b/Core/Utils/ImporterUtil.cs @@ -43,18 +43,16 @@ public class ImporterUtil foreach (var file in files) { if (_fileUtil.GetFileExtension(file) != "json") continue; - if (filesToIgnore.Contains(Path.GetFileName(file).ToLower())) continue; + if (filesToIgnore.Contains(_fileUtil.GetFileName(file).ToLower())) continue; tasks.Add( Task.Factory.StartNew(() => { - // const filename = this.vfs.stripExtension(file); - // const filePathAndName = `${filepath}${file}`; - var fileData = File.ReadAllText(file); + var fileData = _fileUtil.ReadFile(file); if (onReadCallback != null) onReadCallback(file, fileData); var setMethod = GetSetMethod( - Path.GetFileNameWithoutExtension(file).ToLower(), + _fileUtil.StripExtension(file).ToLower(), loadedType, out var propertyType, out var isDictionary @@ -66,7 +64,7 @@ public class ImporterUtil onObjectDeserialized(file, fileDeserialized); setMethod.Invoke(result, - isDictionary ? [Path.GetFileNameWithoutExtension(file), fileDeserialized] : [fileDeserialized]); + isDictionary ? [_fileUtil.StripExtension(file), fileDeserialized] : [fileDeserialized]); } catch (Exception e) { @@ -116,124 +114,13 @@ public class ImporterUtil { var matchedProperty = type.GetProperties() .FirstOrDefault(prop => - prop.Name.ToLower() == Path.GetFileNameWithoutExtension(propertyName).ToLower()); + prop.Name.ToLower() == _fileUtil.StripExtension(propertyName).ToLower()); if (matchedProperty == null) throw new Exception( - $"Unable to find property '{Path.GetFileNameWithoutExtension(propertyName)}' for type '{type.Name}'"); + $"Unable to find property '{_fileUtil.StripExtension(propertyName)}' for type '{type.Name}'"); propertyType = matchedProperty.PropertyType; setMethod = matchedProperty.GetSetMethod(); } return setMethod; } - - /** - * Load files into js objects recursively (synchronous) - * @param filepath Path to folder with files - * @returns - */ - public object LoadRecursive( - string filepath, - Type loadedType, - Action? onReadCallback = null, - Action? onObjectDeserialized = null - ) - { - var result = Activator.CreateInstance(loadedType); - - // get all filepaths - var files = Directory.GetFiles(filepath); - var directories = Directory.GetDirectories(filepath); - - foreach (var file in files) - if (Path.GetExtension(file) == "json") - { - // const filename = this.vfs.stripExtension(file); - // const filePathAndName = `${filepath}${file}`; - var fileData = File.ReadAllText(file); - onReadCallback(file, fileData); - var matchedProperty = loadedType.GetProperties() - .FirstOrDefault(prop => prop.Name.ToLower() == Path.GetFileNameWithoutExtension(file).ToLower()); - if (matchedProperty == null) - throw new Exception($"Unable to find property '{Path.GetFileNameWithoutExtension(file)}' for type '{loadedType.Name}'"); - var propertyType = matchedProperty.PropertyType; - var fileDeserialized = _jsonUtil.Deserialize(fileData, propertyType); - onObjectDeserialized(file, fileDeserialized); - - matchedProperty.GetSetMethod().Invoke(result, [fileDeserialized]); - } - - // deep tree search - foreach (var directory in directories) - { - var matchedProperty = loadedType.GetProperties().FirstOrDefault(prop => prop.Name.ToLower() == directory.ToLower()); - if (matchedProperty == null) - throw new Exception($"Unable to find property '{directory}' for type '{loadedType.Name}'"); - matchedProperty.GetSetMethod().Invoke(result, [LoadRecursive($"{filepath}{directory}/", matchedProperty.PropertyType)]); - } - - // return the result of all async fetch - return result; - } - - public async Task LoadAsync( - string filepath, - Type loadedType, - string strippablePath = "", - Action? onReadCallback = null, - Action? onObjectDeserialized = null - ) - { - var result = Activator.CreateInstance(loadedType); - var promises = new List>(); - var filesToProcess = new Queue(_fileUtil.GetFiles(filepath, true)); - - while (filesToProcess.Count != 0) - { - var fileNode = filesToProcess.Dequeue(); - if (fileNode == null || _fileUtil.GetFileExtension(fileNode) != "json") continue; - - promises.Add(File.ReadAllTextAsync(fileNode).ContinueWith(fd => - { - onReadCallback(fileNode, fd.Result); - return _jsonUtil.Deserialize(fd.Result, typeof(object)); - })); - /* - this.vfs - .readFileAsync(filePathAndName) - .then(async (fileData) => { - onReadCallback(filePathAndName, fileData); - return this.jsonUtil.deserializeWithCacheCheckAsync(fileData, filePathAndName); - }) - .then(async (fileDeserialized) => { - onObjectDeserialized(filePathAndName, fileDeserialized); - const strippedFilePath = this.vfs.stripExtension(filePathAndName).replace(filepath, ""); - this.placeObject(fileDeserialized, strippedFilePath, result, strippablePath); - }) - .then(() => progressWriter.increment()), - );*/ - } - - //await JSType.Promise<>.all(promises).catch((e) => console.error(e)); - - return result; - } - - /* - protected placeObject(fileDeserialized: any, strippedFilePath: string, result: T, strippablePath: string): void { - const strippedFinalPath = strippedFilePath.replace(strippablePath, ""); - let temp = result; - const propertiesToVisit = strippedFinalPath.split("/"); - for (let i = 0; i < propertiesToVisit.length; i++) { - const property = propertiesToVisit[i]; - - if (i === propertiesToVisit.length - 1) { - temp[property] = fileDeserialized; - } else { - if (!temp[property]) { - temp[property] = {}; - } - temp = temp[property]; - } - } - }*/ } diff --git a/Server/Logger/AbstractFormatter.cs b/Server/Logger/AbstractFormatter.cs index e9cbf739..c231bf5d 100644 --- a/Server/Logger/AbstractFormatter.cs +++ b/Server/Logger/AbstractFormatter.cs @@ -14,7 +14,8 @@ public abstract class AbstractFormatter : ITextFormatter var logLevel = logEvent.Level.ToString().ToUpper().Substring(0, 4); var message = logEvent.RenderMessage(); var exception = logEvent.Exception != null ? $"{newLine}{logEvent.Exception}{newLine}{logEvent.Exception.StackTrace}" : ""; - var logMessage = ProcessText($"[{timestamp} {logLevel}] {message}{exception}"); + var sourceContext = logEvent.Properties["SourceContext"].ToString().Replace("\"", ""); + var logMessage = ProcessText($"[{timestamp} {logLevel}][{sourceContext}] {message}{exception}"); output.WriteLine(logMessage); } } diff --git a/Server/Program.cs b/Server/Program.cs index b0bbb337..db0e6279 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -8,6 +8,7 @@ using Core.Models.Spt.Config; using Core.Servers; using Core.Utils; using Serilog; +using Serilog.Events; namespace Server; @@ -18,7 +19,7 @@ public static class Program var assemblies = ModDllLoader.LoadAllMods(); HarmonyBootstrapper.LoadAllPatches(assemblies); var builder = WebApplication.CreateBuilder(args); - + builder.Configuration.AddJsonFile("appsettings.json", true, true); CreateAndRegisterLogger(builder); @@ -64,6 +65,7 @@ public static class Program builder.Logging.ClearProviders(); var logger = new LoggerConfiguration() .ReadFrom.Configuration(builder.Configuration) + .MinimumLevel.Override("Microsoft.AspNetCore.Hosting.Diagnostics", LogEventLevel.Warning) .CreateLogger(); builder.Logging.AddSerilog(logger); } diff --git a/Server/Server.csproj b/Server/Server.csproj index 59553677..c73311b6 100644 --- a/Server/Server.csproj +++ b/Server/Server.csproj @@ -19,6 +19,7 @@ + diff --git a/Server/appsettings.json b/Server/appsettings.json index e5a6eb10..c6b43de4 100644 --- a/Server/appsettings.json +++ b/Server/appsettings.json @@ -1,9 +1,10 @@ { "Logging": { "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" + "Default": "Trace", + "System": "Information", + "Microsoft": "Information", + "Microsoft.AspNetCore.Hosting.Diagnostics": "Warning" } }, "Serilog": { @@ -31,6 +32,14 @@ ] } } + ], + "Filter": [ + { + "Name": "ByExcluding", + "Args": { + "expression": "StartsWith(SourceContext, 'TADAADA')" + } + } ] } }