public void ExportAndDisplayTerms(XRay xray, ISecondarySource dataSource, bool overwriteAliases, bool splitAliases) { //Export available terms to a file to make it easier to create aliases or import the modified aliases if they exist //Could potentially just attempt to automate the creation of aliases, but in some cases it is very subjective... //For example, Shelfari shows the character "Artemis Fowl II", but in the book he is either referred to as "Artemis Fowl", "Artemis", or even "Arty" //Other characters have one name on Shelfari but can have completely different names within the book var aliasesDownloaded = false; // TODO: Review this download process //if ((!File.Exists(AliasPath) || Properties.Settings.Default.overwriteAliases) && Properties.Settings.Default.downloadAliases) //{ // aliasesDownloaded = await AttemptAliasDownload(); //} var aliasPath = _directoryService.GetAliasPath(xray.Asin); if (!aliasesDownloaded && (!File.Exists(aliasPath) || overwriteAliases)) { // overwrite path in case it waas changed within the service aliasPath = _aliasesRepository.SaveCharactersToFile(xray.Terms, xray.Asin, splitAliases); if (aliasPath != null) { _logger.Log($"Characters exported to {aliasPath} for adding aliases."); } } var termsFound = $"{xray.Terms.Count} {(xray.Terms.Count > 1 ? "terms" : "term")} found"; _logger.Log($"{termsFound} on {dataSource.Name}:"); var str = new StringBuilder(xray.Terms.Count * 32); // Assume that most names will be less than 32 chars var termId = 1; foreach (var t in xray.Terms) { str.Append(t.TermName).Append(", "); // todo don't set the IDs here... t.Id = termId++; } _logger.Log(str.ToString()); }
/// <summary> /// Builds an X-Ray file from the parameters given and returns the path at which the file has been saved (or null if something failed) /// </summary> public async Task <string> BuildAsync([NotNull] Request request, CancellationToken cancellationToken) { using var metadata = await GetAndValidateMetadataAsync(request.BookPath, cancellationToken); if (metadata == null) { return(null); } var dataSource = string.IsNullOrEmpty(request.DataUrl) || request.DataUrl == SecondarySourceRoentgen.FakeUrl ? _secondaryDataSourceFactory.Get(SecondaryDataSourceFactory.Enum.Roentgen) : _secondaryDataSourceFactory.GetInferredSource(request.DataUrl); if (dataSource == null) { _logger.Log("Data source could not be determined from the given path."); return(null); } Core.XRay.XRay xray; try { xray = await _xrayService.CreateXRayAsync(request.DataUrl, metadata.DbName, metadata.UniqueId, metadata.Asin, request.AmazonTld ?? "com", request.IncludeTopics, dataSource, _progress, cancellationToken); if (xray.Terms.Count == 0) { _logger.Log($"No terms were available on {dataSource.Name}, cancelling the build..."); return(null); } var aliasPath = _directoryService.GetAliasPath(xray.Asin); _xrayService.ExportAndDisplayTerms(xray, dataSource, false, request.SplitAliases); if (xray.Terms.Any(term => term.Aliases?.Count > 0)) { _logger.Log("Character aliases read from the XML file."); } else if (!File.Exists(aliasPath)) { _logger.Log("Aliases file not found."); } else { _aliasesRepository.LoadAliasesForXRay(xray); _logger.Log($"Character aliases read from {aliasPath}."); } _logger.Log("Initial X-Ray built, adding locations and chapters..."); //Expand the X-Ray file from the unpacked mobi Task buildTask = metadata switch { // ReSharper disable AccessToDisposedClosure MobiMetadata _ => Task.Run(() => _xrayService.ExpandFromRawMl(xray, metadata, metadata.GetRawMlStream(), true, true, 25, true, null, _progress, cancellationToken, true, false), cancellationToken), KfxContainer kfx => Task.Run(() => _kfxXrayService.AddLocations(xray, kfx, true, 25, _progress, cancellationToken), cancellationToken), _ => throw new NotSupportedException() }; await buildTask.ConfigureAwait(false); } catch (OperationCanceledException) { _logger.Log("Build canceled."); return(null); } catch (Exception ex) { _logger.Log($"An error occurred while building the X-Ray:\r\n{ex.Message}\r\n{ex.StackTrace}"); return(null); } _logger.Log("Saving X-Ray to file..."); var xrayPath = _directoryService.GetArtifactPath(ArtifactType.XRay, metadata, Path.GetFileNameWithoutExtension(request.BookPath), true); try { var xrayExporter = _xrayExporterFactory.Get(XRayExporterFactory.Enum.Sqlite); xrayExporter.Export(xray, xrayPath, _progress, cancellationToken); } catch (OperationCanceledException) { _logger.Log("Building canceled."); return(null); } catch (Exception ex) { // TODO: Add option to retry maybe? _logger.Log($"An error occurred while creating the X-Ray file. Is it opened in another program?\r\n{ex.Message}"); return(null); } _logger.Log($"X-Ray file created successfully!\r\nSaved to {xrayPath}"); return(xrayPath); }
// todo make this better public void LoadAliasesForXRay(XRay xray) { var aliasesByTermName = LoadAliasesFromFile(_directoryService.GetAliasPath(xray.Asin)); if (aliasesByTermName == null) { return; } for (var i = 0; i < xray.Terms.Count; i++) { var t = xray.Terms[i]; if (aliasesByTermName.ContainsKey(t.TermName)) { if (t.Aliases.Count > 0) { // If aliases exist (loaded from Goodreads), remove any duplicates and add them in the order from the aliases file // Otherwise, the website would take precedence and that could be bad? foreach (var alias in aliasesByTermName[t.TermName]) { if (t.Aliases.Contains(alias)) { t.Aliases.Remove(alias); t.Aliases.Add(alias); } else { t.Aliases.Add(alias); } } } else { t.Aliases = new List <string>(aliasesByTermName[t.TermName]); } // If first alias is "/c", character searches will be case-sensitive // If it is /d, delete this character // If /n, will not match excerpts but will leave character in X-Ray // If /r, character's aliases (and ONLY the aliases) will be processed as Regular Expressions (case-sensitive unless specified in regex) if (t.Aliases[0] == "/c") { t.MatchCase = true; t.Aliases.Remove("/c"); } else if (t.Aliases[0] == "/d") { xray.Terms.Remove(t); i--; } else if (t.Aliases[0] == "/n") { t.Match = false; t.Aliases.Remove("/n"); } else if (t.Aliases[0] == "/r") { t.RegexAliases = true; t.Aliases.Remove("/r"); } } } }