/// <summary> /// Gets the definitions asynchronous. /// </summary> /// <param name="storagePath">The storage path.</param> /// <param name="game">The game.</param> /// <param name="path">The path.</param> /// <returns>Task<IEnumerable<IDefinition>>.</returns> public virtual async Task <IEnumerable <IDefinition> > GetDefinitionsAsync(string storagePath, IGame game, string path) { storagePath = ResolveStoragePath(storagePath); path = SanitizePath(path); var fullPath = Path.Combine(storagePath, game.Type, path); if (File.Exists(fullPath)) { var bytes = await File.ReadAllBytesAsync(fullPath); if (bytes.Any()) { using var source = new MemoryStream(bytes); using var destination = new MemoryStream(); using var compress = new DeflateStream(source, CompressionMode.Decompress); await compress.CopyToAsync(destination); var text = Encoding.UTF8.GetString(destination.ToArray()); if (!string.IsNullOrWhiteSpace(text)) { var result = JsonDISerializer.Deserialize <List <IDefinition> >(text); return(result); } } } return(null); }
/// <summary> /// Exports the asynchronous. /// </summary> /// <param name="modHashes">The mod hashes.</param> /// <param name="path">The path.</param> /// <returns>Task<System.Boolean>.</returns> public Task <bool> ExportAsync(IEnumerable <IHashReport> modHashes, string path) { var retryStrategy = new RetryStrategy(); if (modHashes?.Count() > 0) { var json = JsonDISerializer.Serialize(modHashes); return(retryStrategy.RetryActionAsync(async() => { await File.WriteAllTextAsync(path, json); return true; })); } return(Task.FromResult(false)); }
/// <summary> /// import as an asynchronous operation. /// </summary> /// <param name="path">The path.</param> /// <returns>Task<IEnumerable<IModHashFileReport>>.</returns> public async Task <IEnumerable <IHashReport> > ImportAsync(string path) { if (File.Exists(path)) { var json = await File.ReadAllTextAsync(path); if (!string.IsNullOrWhiteSpace(json)) { try { var result = JsonDISerializer.Deserialize <IEnumerable <IHashReport> >(json); return(result); } catch (Exception ex) { logger.Error(ex); } } } return(null); }
/// <summary> /// Export as an asynchronous operation. /// </summary> /// <param name="params">The parameters.</param> /// <returns>A Task<System.Boolean> representing the asynchronous operation.</returns> public async Task <bool> ExportAsync(ModCollectionExporterParams @params) { // Paradox launcher only exports pdx or steam mods, local mods are not exported var validMods = @params.ExportMods.Where(p => p.Source != ModSource.Local).ToList(); var modInfo = new ModInfo() { Game = @params.Game.ParadoxGameId, Name = @params.Mod.Name, Mods = validMods.Select(p => new Models.Paradox.Json.v3.Mods() { DisplayName = p.Name, Enabled = true, Position = validMods.IndexOf(p), SteamId = p.Source == ModSource.Steam ? p.RemoteId.ToString() : null, PdxId = p.Source == ModSource.Paradox ? p.RemoteId.ToString() : null }).ToList() }; var json = JsonDISerializer.Serialize(modInfo); await File.WriteAllTextAsync(@params.File, json); return(true); }
/// <summary> /// Saves the definitions asynchronous. /// </summary> /// <param name="storagePath">The storage path.</param> /// <param name="game">The game.</param> /// <param name="definitions">The definitions.</param> /// <returns>Task<System.Boolean>.</returns> /// <exception cref="ArgumentException">Definitions types differ.</exception> public virtual async Task <bool> SaveDefinitionsAsync(string storagePath, IGame game, IEnumerable <IDefinition> definitions) { storagePath = ResolveStoragePath(storagePath); if (definitions.GroupBy(p => p.ParentDirectory).Count() > 1) { throw new ArgumentException("Definitions types differ."); } if (definitions == null || !definitions.Any()) { return(false); } var path = SanitizePath(definitions.FirstOrDefault().ParentDirectory); var fullPath = Path.Combine(storagePath, game.Type, path); if (File.Exists(fullPath)) { DiskOperations.DeleteFile(fullPath); } var json = JsonDISerializer.Serialize(definitions.ToList()); var bytes = Encoding.UTF8.GetBytes(json); using var source = new MemoryStream(bytes); using var destination = new MemoryStream(); using var compress = new DeflateStream(destination, CompressionLevel.Fastest, true); await source.CopyToAsync(compress); await compress.FlushAsync(); if (!Directory.Exists(Path.GetDirectoryName(fullPath))) { Directory.CreateDirectory(Path.GetDirectoryName(fullPath)); } await File.WriteAllBytesAsync(fullPath, destination.ToArray()); return(true); }
/// <summary> /// json import as an asynchronous operation. /// </summary> /// <param name="parameters">The parameters.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> /// <exception cref="System.AggregateException"></exception> public virtual async Task <ICollectionImportResult> JsonImportAsync(ModCollectionExporterParams parameters) { async Task <(Exception, ICollectionImportResult)> parseV2() { var content = await File.ReadAllTextAsync(parameters.File); if (!string.IsNullOrWhiteSpace(content)) { Models.Paradox.Json.v2.ModInfo model = null; try { model = JsonDISerializer.Deserialize <Models.Paradox.Json.v2.ModInfo>(content); } catch (Exception ex) { return(ex, null); } if (!string.IsNullOrWhiteSpace(model.Game) && !string.IsNullOrWhiteSpace(model.Name)) { // Validate whether this really is v2 (execting length larger than 4 as a dumb best guess) if (model.Mods.Any(p => p.Position.Length >= 4)) { var result = DIResolver.Get <ICollectionImportResult>(); result.Name = model.Name; // Will need to lookup the game and mod ids in the mod service result.Game = model.Game; var mods = model.Mods.Where(p => p.Enabled).OrderBy(p => p.Position); result.ModIds = mods.Select(p => !string.IsNullOrWhiteSpace(p.PdxId) ? p.PdxId : p.SteamId).ToList(); return(null, result); } } } return(null, null); } async Task <(Exception, ICollectionImportResult)> parseV3() { var content = await File.ReadAllTextAsync(parameters.File); if (!string.IsNullOrWhiteSpace(content)) { Models.Paradox.Json.v3.ModInfo model = null; try { model = JsonDISerializer.Deserialize <Models.Paradox.Json.v3.ModInfo>(content); } catch (Exception ex) { return(ex, null); } if (!string.IsNullOrWhiteSpace(model.Game) && !string.IsNullOrWhiteSpace(model.Name)) { var result = DIResolver.Get <ICollectionImportResult>(); result.Name = model.Name; // Will need to lookup the game and mod ids in the mod service result.Game = model.Game; var mods = model.Mods.Where(p => p.Enabled).OrderBy(p => p.Position); result.ModIds = mods.Select(p => !string.IsNullOrWhiteSpace(p.PdxId) ? p.PdxId : p.SteamId).ToList(); return(null, result); } } return(null, null); } if (File.Exists(parameters.File)) { var exceptions = new List <Exception>(); var result = await parseV2(); if (result.Item2 != null) { return(result.Item2); } if (result.Item1 != null) { exceptions.Add(result.Item1); } result = await parseV3(); if (result.Item2 != null) { return(result.Item2); } if (result.Item1 != null) { exceptions.Add(result.Item1); } if (exceptions.Any()) { throw new AggregateException(exceptions); } } return(null); }
/// <summary> /// Parses the paradoxos as json. /// </summary> /// <param name="content">The content.</param> /// <returns>ParadoxosExportedList.</returns> private ParadoxosExportedList ParseParadoxosAsJSON(string content) { return(JsonDISerializer.Deserialize <ParadoxosExportedList>(content)); }
/// <summary> /// Imports the internal. /// </summary> /// <param name="parameters">The parameters.</param> /// <param name="importInstance">if set to <c>true</c> [import instance].</param> /// <param name="collectionImportResult">The collection import result.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> private bool ImportInternal(ModCollectionExporterParams parameters, bool importInstance, out ICollectionImportResult collectionImportResult) { ICollectionImportResult importResult = null; if (importInstance) { importResult = DIResolver.Get <ICollectionImportResult>(); } if (!importInstance) { if (Directory.Exists(parameters.ModDirectory)) { DiskOperations.DeleteDirectory(parameters.ModDirectory, true); } } var result = false; int getTotalFileCount() { var count = 0; using var fileStream = File.OpenRead(parameters.File); using var reader = ReaderFactory.Open(fileStream); while (reader.MoveToNextEntry()) { if (!reader.Entry.IsDirectory) { count++; } } fileStream.Close(); fileStream.Dispose(); return(count); } void parseUsingReaderFactory() { double total = getTotalFileCount(); using var fileStream = File.OpenRead(parameters.File); using var reader = ReaderFactory.Open(fileStream); double processed = 0; double previousProgress = 0; while (reader.MoveToNextEntry()) { if (!reader.Entry.IsDirectory) { var relativePath = reader.Entry.Key.StandardizeDirectorySeparator().Trim(Path.DirectorySeparatorChar); if (reader.Entry.Key.Equals(Common.Constants.ExportedModContentId, StringComparison.OrdinalIgnoreCase)) { if (importInstance) { using var entryStream = reader.OpenEntryStream(); using var memoryStream = new MemoryStream(); entryStream.CopyTo(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); using var streamReader = new StreamReader(memoryStream, true); var text = streamReader.ReadToEnd(); streamReader.Close(); streamReader.Dispose(); var model = JsonDISerializer.Deserialize <IModCollection>(text); mapper.Map(model, importResult); importResult.ModNames = model.ModNames; importResult.Descriptors = model.Mods; result = true; break; } } else { if (!importInstance) { var exportFileName = Path.Combine(relativePath.StartsWith(Common.Constants.ModExportPath + Path.DirectorySeparatorChar) ? parameters.ExportModDirectory : parameters.ModDirectory, relativePath.Replace(Common.Constants.ModExportPath + Path.DirectorySeparatorChar, string.Empty)); if (!Directory.Exists(Path.GetDirectoryName(exportFileName))) { Directory.CreateDirectory(Path.GetDirectoryName(exportFileName)); } reader.WriteEntryToFile(exportFileName, ZipExtractionOpts.GetExtractionOptions()); } } processed++; var perc = GetProgressPercentage(total, processed, 100); if (perc != previousProgress) { messageBus.Publish(new ModExportProgressEvent(perc)); previousProgress = perc; } } } } void parseUsingArchiveFactory() { using var fileStream = File.OpenRead(parameters.File); using var reader = ArchiveFactory.Open(fileStream); var entries = reader.Entries.Where(entry => !entry.IsDirectory); double total = !importInstance?entries.Count() : 1; double processed = 0; double previousProgress = 0; foreach (var entry in entries) { var relativePath = entry.Key.StandardizeDirectorySeparator().Trim(Path.DirectorySeparatorChar); if (entry.Key.Equals(Common.Constants.ExportedModContentId, StringComparison.OrdinalIgnoreCase)) { if (importInstance) { using var entryStream = entry.OpenEntryStream(); using var memoryStream = new MemoryStream(); entryStream.CopyTo(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); using var streamReader = new StreamReader(memoryStream, true); var text = streamReader.ReadToEnd(); streamReader.Close(); streamReader.Dispose(); var model = JsonDISerializer.Deserialize <IModCollection>(text); mapper.Map(model, importResult); importResult.ModNames = model.ModNames; importResult.Descriptors = model.Mods; result = true; break; } } else { if (!importInstance) { var exportFileName = Path.Combine(relativePath.StartsWith(Common.Constants.ModExportPath + Path.DirectorySeparatorChar) ? parameters.ExportModDirectory : parameters.ModDirectory, relativePath.Replace(Common.Constants.ModExportPath + Path.DirectorySeparatorChar, string.Empty)); if (!Directory.Exists(Path.GetDirectoryName(exportFileName))) { Directory.CreateDirectory(Path.GetDirectoryName(exportFileName)); } entry.WriteToFile(exportFileName, ZipExtractionOpts.GetExtractionOptions()); } } processed++; var perc = GetProgressPercentage(total, processed, 100); if (perc != previousProgress) { messageBus.Publish(new ModExportProgressEvent(perc)); previousProgress = perc; } } } try { parseUsingArchiveFactory(); } catch (Exception ex) { logger.Error(ex); result = false; parseUsingReaderFactory(); } collectionImportResult = importResult; return(!importInstance || result); }