using SptCommon.Annotations; using Core.DI; using Core.Models.Eft.Common.Tables; using Core.Models.Spt.Config; using Core.Models.Spt.Server; using Core.Models.Utils; using Core.Routers; using Core.Servers; using Core.Services; using LogLevel = Core.Models.Spt.Logging.LogLevel; namespace Core.Utils; [Injectable(InjectionType.Singleton, InjectableTypeOverride = typeof(OnLoad), TypePriority = OnLoadOrder.Database)] public class DatabaseImporter : OnLoad { private object hashedFile; private ValidationResult valid = ValidationResult.UNDEFINED; private string filepath; private HttpConfig httpConfig; protected ISptLogger _logger; protected LocalisationService _localisationService; protected DatabaseServer _databaseServer; protected ImageRouter _imageRouter; protected EncodingUtil _encodingUtil; protected HashUtil _hashUtil; protected ImporterUtil _importerUtil; protected ConfigServer _configServer; protected FileUtil _fileUtil; public DatabaseImporter( ISptLogger logger, // TODO: are we gonna use this? @inject("JsonUtil") protected jsonUtil: JsonUtil, FileUtil fileUtil, LocalisationService localisationService, DatabaseServer databaseServer, ImageRouter imageRouter, EncodingUtil encodingUtil, HashUtil hashUtil, ImporterUtil importerUtil, ConfigServer configServer ) { _logger = logger; _localisationService = localisationService; _databaseServer = databaseServer; _encodingUtil = encodingUtil; _hashUtil = hashUtil; _importerUtil = importerUtil; _configServer = configServer; _fileUtil = fileUtil; _imageRouter = imageRouter; httpConfig = _configServer.GetConfig(); } /** * Get path to spt data * @returns path to data */ public string GetSptDataPath() { return "./Assets/"; } public async Task OnLoad() { filepath = GetSptDataPath(); /* if (ProgramStatics.COMPILED) { try { // Reading the dynamic SHA1 file const file = "checks.dat"; const fileWithPath = `${this.filepath}${file}`; if (this.vfs.exists(fileWithPath)) { this.hashedFile = this.jsonUtil.deserialize( this.encodingUtil.fromBase64(this.vfs.readFile(fileWithPath)), file, ); } else { this.valid = ValidationResult.NOT_FOUND; this.logger.debug(this.localisationService.getText("validation_not_found")); } } catch (e) { this.valid = ValidationResult.FAILED; this.logger.warning(this.localisationService.getText("validation_error_decode")); } } */ await HydrateDatabase(filepath); var imageFilePath = $"{filepath}images/"; CreateRouteMapping(imageFilePath, "files"); } private void CreateRouteMapping(string directory, string newBasePath) { var directoryContent = GetAllFilesInDirectory(directory); foreach (var fileNameWithPath in directoryContent) { var fileNameWithNoSPTPath = fileNameWithPath.Replace(directory, ""); var filePathNoExtension = _fileUtil.StripExtension(fileNameWithNoSPTPath, true); if (filePathNoExtension.StartsWith("/") || fileNameWithPath.StartsWith("\\")) filePathNoExtension = $"{filePathNoExtension.Substring(1)}"; var bsgPath = $"/{newBasePath}/{filePathNoExtension}".Replace("\\", "/"); _imageRouter.AddRoute(bsgPath, fileNameWithPath); } } private List GetAllFilesInDirectory(string directoryPath) { List result = []; result.AddRange(Directory.GetFiles(directoryPath)); foreach (var subdirectory in Directory.GetDirectories(directoryPath)) { result.AddRange(GetAllFilesInDirectory(subdirectory)); } return result; } /** * Read all json files in database folder and map into a json object * @param filepath path to database folder */ protected async Task HydrateDatabase(string filePath) { _logger.Info(_localisationService.GetText("importing_database")); var dataToImport = await _importerUtil.LoadRecursiveAsync( $"{filePath}database/", OnReadValidate ); // TODO: Fix loading of traders, so their full path is not included as the key var tempTraders = new Dictionary(); // temp fix for trader keys foreach (var trader in dataToImport.Traders) { // fix string for key var tempKey = trader.Key.Split("/").Last(); tempTraders.Add(tempKey, trader.Value); } dataToImport.Traders = tempTraders; var validation = valid == ValidationResult.FAILED || valid == ValidationResult.NOT_FOUND ? "." : ""; _logger.Info($"{_localisationService.GetText("importing_database_finish")}{validation}"); _databaseServer.SetTables(dataToImport); } protected void OnReadValidate(string fileWithPath, string data) { // Validate files //if (ProgramStatics.COMPILED && hashedFile && !ValidateFile(fileWithPath, data)) { // this.valid = ValidationResult.FAILED; //} } public string GetRoute() { return "spt-database"; } protected bool ValidateFile(string filePathAndName, object fileData) { /* try { const finalPath = filePathAndName.replace(this.filepath, "").replace(".json", ""); let tempObject: any; for (const prop of finalPath.split("/")) { if (!tempObject) { tempObject = this.hashedFile[prop]; } else { tempObject = tempObject[prop]; } } if (tempObject !== this.hashUtil.generateSha1ForData(fileData)) { this.logger.debug(this.localisationService.getText("validation_error_file", filePathAndName)); return false; } } catch (e) { this.logger.warning(this.localisationService.getText("validation_error_exception", filePathAndName)); this.logger.warning(e); return false; } return true; */ return true; } /** * absolute dogshit, do not use * Find and map files with image router inside a designated path * @param filepath Path to find files in */ [Obsolete] public void LoadImages(string filepath, string[] directories, List routes) { for (var i = 0; i < directories.Length; i++) { // Get all files in directory var filesInDirectory = _fileUtil.GetFiles(directories[i]); foreach (var file in filesInDirectory) { var imagePath = file; // Register each file in image router var filename = _fileUtil.StripExtension(file); var routeKey = $"{routes[i]}{filename}"; //var imagePath = $"{filepath}{directories[i]}/{file}"; var pathOverride = GetImagePathOverride(imagePath); if (!string.IsNullOrEmpty(pathOverride)) { if (_logger.IsLogEnabled(LogLevel.Debug)) { _logger.Debug($"overrode route: {routeKey} endpoint: {imagePath} with {pathOverride}"); } imagePath = pathOverride; } _imageRouter.AddRoute(routeKey, imagePath); } } // Map icon file separately _imageRouter.AddRoute("/favicon.ico", $"{filepath}icon.ico"); } /** * Check for a path override in the http json config file * @param imagePath Key * @returns override for key */ protected string? GetImagePathOverride(string imagePath) { if (httpConfig.ServerImagePathOverride.TryGetValue(imagePath, out var value)) return value; return null; } } internal enum ValidationResult { SUCCESS = 0, FAILED = 1, NOT_FOUND = 2, UNDEFINED = 3 }