Fixed some Inspector related bugs. Fixed typo ('FileExtensionsToDelete') in configuration.

This commit is contained in:
Steven Hildreth 2019-06-15 17:33:24 -05:00
parent bb4b98f232
commit 308f80669e
26 changed files with 180 additions and 49 deletions

View file

@ -1,40 +1,35 @@
using System;
using McMaster.Extensions.CommandLineUtils;
using System.ComponentModel.DataAnnotations;
using System.IO;
using McMaster.Extensions.CommandLineUtils;
namespace Inspector
{
public class Program
{
public static int Main(string[] args)
=> CommandLineApplication.Execute<Program>(args);
[Option(ShortName = "f", Description = "Folder To Inspect")]
[Required]
public string Folder { get; }
[Option(ShortName = "d", Description = "Destination Folder")]
public string Destination { get; }
[Option("-c", "Copy Dont Move Originals", CommandOptionType.NoValue)]
public bool DoCopy { get; }
[Option("-r", "Only show what would be done, don't modify any files", CommandOptionType.NoValue)]
public bool IsReadOnly { get; }
[Option("-s", "Don't append a subfolder to the Destination folder", CommandOptionType.NoValue)]
public bool DontAppendSubFolder { get; }
[Option("-x", "Don't delete empty folders after inspection, if moving", CommandOptionType.NoValue)]
public bool DontDeleteEmptyFolders { get; }
[Option(ShortName = "f", Description = "Folder To Inspect")]
[Required]
public string Folder { get; }
[Option("-r", "Only show what would be done, don't modify any files", CommandOptionType.NoValue)]
public bool IsReadOnly { get; }
public static int Main(string[] args) => CommandLineApplication.Execute<Program>(args);
private void OnExecute()
{
var inspector = new Roadie.Library.Inspect.Inspector();
inspector.Inspect(DoCopy, IsReadOnly, Folder, Destination ?? Folder, DontAppendSubFolder, IsReadOnly ? true : DontDeleteEmptyFolders);
}
}
}
}

View file

@ -18,7 +18,7 @@
"Width": 320
},
"DontDoMetaDataProvidersSearchArtists": [ "Various Artists", "Sound Tracks" ],
"FileExtenionsToDelete": [ ".cue", ".db", ".gif", ".html", ".ini", ".jpg", ".jpeg", ".log", ".mpg", ".m3u", ".png", ".nfo", ".nzb", ".sfv", ".srr", ".txt", ".url" ],
"FileExtensionsToDelete": [ ".cue", ".db", ".gif", ".html", ".ini", ".jpg", ".jpeg", ".log", ".mpg", ".m3u", ".png", ".nfo", ".nzb", ".sfv", ".srr", ".txt", ".url" ],
"RecordNoResultSearches": true,
"ArtistNameReplace": {
"AC/DC": [ "AC; DC", "AC;DC", "AC/ DC", "AC DC" ],

View file

@ -47,7 +47,7 @@ namespace Roadie.Library.Tests
[InlineData("cover.png")]
[InlineData("Cover.Jpg")]
[InlineData("Cover.JPG")]
[InlineData("Cover.PNG")]
[InlineData("Cover.PNG")]
[InlineData("CvR.Jpg")]
[InlineData("Release.JPG")]
[InlineData("folder.JPG")]
@ -71,6 +71,8 @@ namespace Roadie.Library.Tests
[Theory]
[InlineData("cover.png")]
[InlineData("cover1.jpg")]
[InlineData("cover 1.jpg")]
[InlineData("Cover.jpg")]
[InlineData("batman.txt")]
[InlineData("Song.mp3")]
@ -185,6 +187,7 @@ namespace Roadie.Library.Tests
[InlineData("cover_01.jpg")]
[InlineData("cover 03.jpg")]
[InlineData("cover 1.jpg")]
[InlineData("cover1.jpg")]
[InlineData("Encartes (11).jpg")]
[InlineData("Encartes (1).png")]
[InlineData("Encartes.jpg")]

View file

@ -18,7 +18,7 @@
"Width": 320
},
"DontDoMetaDataProvidersSearchArtists": [ "Various Artists", "Sound Tracks" ],
"FileExtenionsToDelete": [ ".cue", ".db", ".gif", ".html", ".ini", ".jpg", ".jpeg", ".log", ".mpg", ".m3u", ".png", ".nfo", ".nzb", ".sfv", ".srr", ".txt", ".url" ],
"FileExtensionsToDelete": [ ".cue", ".db", ".gif", ".html", ".ini", ".jpg", ".jpeg", ".log", ".mpg", ".m3u", ".png", ".nfo", ".nzb", ".sfv", ".srr", ".txt", ".url" ],
"RecordNoResultSearches": true,
"ArtistNameReplace": {
"AC/DC": [ "AC; DC", "AC;DC", "AC/ DC", "AC DC" ],

View file

@ -102,13 +102,13 @@ namespace Roadie.Library.Data
}
private IEnumerable<PositionAristRelease> _positionAristReleases = null;
private IEnumerable<PositionArtistRelease> _positionArtistReleases = null;
public IEnumerable<PositionAristRelease> PositionArtistReleases()
public IEnumerable<PositionArtistRelease> PositionArtistReleases()
{
if (this._positionAristReleases == null)
if (this._positionArtistReleases == null)
{
var rows = new List<PositionAristRelease>();
var rows = new List<PositionArtistRelease>();
using (var sr = new StringReader(this.ListInCSV))
{
var index = 0;
@ -125,7 +125,7 @@ namespace Roadie.Library.Data
while (csv.Read())
{
index++;
rows.Add(new PositionAristRelease
rows.Add(new PositionArtistRelease
{
Index = index,
Position = csv.GetField<int>(this.PositionColumn),
@ -134,9 +134,9 @@ namespace Roadie.Library.Data
});
}
}
this._positionAristReleases = rows;
this._positionArtistReleases = rows;
}
return this._positionAristReleases;
return this._positionArtistReleases;
}
public Collection()
@ -152,7 +152,7 @@ namespace Roadie.Library.Data
}
[Serializable]
public class PositionAristRelease
public class PositionArtistRelease
{
[JsonIgnore]
public Statuses Status { get; set; }

View file

@ -80,7 +80,7 @@ namespace Roadie.Library.Engines
{
artist.Thumbnail = ImageHelper.ResizeImage(artist.Thumbnail, this.Configuration.ThumbnailImageSize.Width, this.Configuration.ThumbnailImageSize.Height);
artist.Thumbnail = ImageHelper.ConvertToJpegFormat(artist.Thumbnail);
if (artist.Thumbnail.Length >= 65535)
if (artist.Thumbnail.Length >= ImageHelper.MaximumThumbnailByteSize)
{
Logger.LogWarning($"Artist Thumbnail larger than maximum size after resizing to [{ this.Configuration.ThumbnailImageSize.Width }x{ this.Configuration.ThumbnailImageSize.Height}] Thumbnail Size [{ artist.Thumbnail.Length }]");
artist.Thumbnail = null;

View file

@ -62,7 +62,7 @@ namespace Roadie.Library.Engines
public IReleaseSearchEngine WikipediaReleaseSearchEngine { get; }
public ReleaseLookupEngine(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context,
ICacheManager cacheManager, ILogger logger, IArtistLookupEngine aristLookupEngine,
ICacheManager cacheManager, ILogger logger, IArtistLookupEngine artistLookupEngine,
ILabelLookupEngine labelLookupEngine)
: base(configuration, httpEncoder, context, cacheManager, logger)
{
@ -916,7 +916,7 @@ namespace Roadie.Library.Engines
{
result.Thumbnail = ImageHelper.ResizeImage(result.Thumbnail, this.Configuration.ThumbnailImageSize.Width, this.Configuration.ThumbnailImageSize.Height);
result.Thumbnail = ImageHelper.ConvertToJpegFormat(result.Thumbnail);
if(result.Thumbnail.Length >= 65535)
if(result.Thumbnail.Length >= ImageHelper.MaximumThumbnailByteSize)
{
Logger.LogWarning($"Release Thumbnail larger than maximum size after resizing to [{ this.Configuration.ThumbnailImageSize.Width }x{ this.Configuration.ThumbnailImageSize.Height}] Thumbnail Size [{ result.Thumbnail.Length }]");
result.Thumbnail = null;

View file

@ -335,6 +335,11 @@ namespace Roadie.Library.Factories
artist.Thumbnail = File.ReadAllBytes(i.FullName);
artist.Thumbnail = ImageHelper.ResizeImage(artist.Thumbnail, this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height);
artist.Thumbnail = ImageHelper.ConvertToJpegFormat(artist.Thumbnail);
if (artist.Thumbnail.Length >= ImageHelper.MaximumThumbnailByteSize)
{
Logger.LogWarning($"Artist Thumbnail larger than maximum size after resizing to [{ this.Configuration.ThumbnailImageSize.Width }x{ this.Configuration.ThumbnailImageSize.Height}] Thumbnail Size [{ artist.Thumbnail.Length }]");
artist.Thumbnail = null;
}
artist.LastUpdated = DateTime.UtcNow;
await this.DbContext.SaveChangesAsync();
this.CacheManager.ClearRegion(artist.CacheRegion);

View file

@ -798,6 +798,11 @@ namespace Roadie.Library.Factories
release.Thumbnail = File.ReadAllBytes(i.FullName);
release.Thumbnail = ImageHelper.ResizeImage(release.Thumbnail, this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height);
release.Thumbnail = ImageHelper.ConvertToJpegFormat(release.Thumbnail);
if (release.Thumbnail.Length >= ImageHelper.MaximumThumbnailByteSize)
{
Logger.LogWarning($"Release Thumbnail larger than maximum size after resizing to [{ this.Configuration.ThumbnailImageSize.Width }x{ this.Configuration.ThumbnailImageSize.Height}] Thumbnail Size [{ release.Thumbnail.Length }]");
release.Thumbnail = null;
}
release.LastUpdated = now;
await this.DbContext.SaveChangesAsync();
this.CacheManager.ClearRegion(release.Artist.CacheRegion);

View file

@ -122,8 +122,8 @@ namespace Roadie.Library.FilePlugins
if (artistImages.Any())
{
var artistImage = artistImages.First();
var aristImageFilename = Path.Combine(artistFolder, ImageHelper.ArtistImageFilename);
if (aristImageFilename != artistImage.FullName)
var artistImageFilename = Path.Combine(artistFolder, ImageHelper.ArtistImageFilename);
if (artistImageFilename != artistImage.FullName)
{
// Read image and convert to jpeg
var imageBytes = File.ReadAllBytes(artistImage.FullName);
@ -132,7 +132,7 @@ namespace Roadie.Library.FilePlugins
// Move artist image to artist folder
if (!doJustInfo)
{
File.WriteAllBytes(aristImageFilename, imageBytes);
File.WriteAllBytes(artistImageFilename, imageBytes);
artistImage.Delete();
}
this.Logger.LogDebug("Found Artist Image File [{0}], Moved to artist folder.", artistImage.Name);

View file

@ -16,6 +16,8 @@ namespace Roadie.Library.Imaging
{
public static class ImageHelper
{
public static int MaximumThumbnailByteSize = 65535;
public static string ArtistImageFilename = "artist.jpg";
public static string ArtistSecondaryImageFilename = "artist {0}.jpg"; // Replace with counter of image
public static string ReleaseCoverFilename = "cover.jpg";
@ -163,7 +165,7 @@ namespace Roadie.Library.Imaging
{
return false;
}
return Regex.IsMatch(fileinfo.Name, @"((book[let]*[#-_\s(]*[0-9]*-*[0-9]*(\))*)|(encartes[-_\s]*[(]*[0-9]*[)]*)|scan(.)?[0-9]*|matrix(.)?[0-9]*|(cover[\s_-]+[0-9]+)|back|traycard|jewel case|disc|(.*)[in]*side(.*)|in([side|lay|let|site])*[0-9]*|cd(.)?[0-9]*|(release[\s_-]+[0-9]+))\.(jpg|jpeg|png|bmp|gif)", RegexOptions.IgnoreCase);
return Regex.IsMatch(fileinfo.Name, @"((book[let]*[#-_\s(]*[0-9]*-*[0-9]*(\))*)|(encartes[-_\s]*[(]*[0-9]*[)]*)|scan(.)?[0-9]*|matrix(.)?[0-9]*|(cover[\s_-]*[0-9]+)|back|traycard|jewel case|disc|(.*)[in]*side(.*)|in([side|lay|let|site])*[0-9]*|cd(.)?[0-9]*|(release[\s_-]+[0-9]+))\.(jpg|jpeg|png|bmp|gif)", RegexOptions.IgnoreCase);
}
public static bool IsLabelImage(FileInfo fileinfo)

View file

@ -131,7 +131,7 @@ namespace Roadie.Library.Inspect
var settings = new RoadieSettings();
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddJsonFile("appsettings.json");
configurationBuilder.AddJsonFile("appsettings.json", false);
IConfiguration configuration = configurationBuilder.Build();
configuration.GetSection("RoadieSettings").Bind(settings);
settings.ConnectionString = configuration.GetConnectionString("RoadieDatabaseConnection");
@ -208,7 +208,7 @@ namespace Roadie.Library.Inspect
continue;
}
// Run directory plugins against current directory
foreach (var plugin in DirectoryPlugins.OrderBy(x => x.Order))
foreach (var plugin in DirectoryPlugins.Where(x => !x.IsPostProcessingPlugin).OrderBy(x => x.Order))
{
Console.WriteLine($"╠╬═ Running Directory Plugin { plugin.Description }");
var pluginResult = plugin.Process(directoryInfo);
@ -382,6 +382,22 @@ namespace Roadie.Library.Inspect
Console.WriteLine("╠════════════════════════╣");
}
}
// Run post-processing directory plugins against current directory
foreach (var plugin in DirectoryPlugins.Where(x => x.IsPostProcessingPlugin).OrderBy(x => x.Order))
{
Console.WriteLine($"╠╬═ Running Post-Processing Directory Plugin { plugin.Description }");
var pluginResult = plugin.Process(directoryInfo);
if (!pluginResult.IsSuccess)
{
Console.WriteLine($"Plugin Failed: Error [{ JsonConvert.SerializeObject(pluginResult)}]");
return;
}
else if (!string.IsNullOrEmpty(pluginResult.Data))
{
Console.WriteLine($"╠╣ Directory Plugin Message: { pluginResult.Data }");
}
}
Console.WriteLine($"╠╝");
sw.Stop();
Console.WriteLine($"╚═ Elapsed Time { sw.ElapsedMilliseconds.ToString("0000000") }, Artists { artistsFound.Count() }, Releases { releasesFound.Count() }, MP3s { mp3FilesFoundCount } ═╝");
}

View file

@ -0,0 +1,58 @@
using Microsoft.Extensions.Logging;
using Roadie.Library.Caching;
using Roadie.Library.Configuration;
using Roadie.Library.MetaData.ID3Tags;
using Roadie.Library.Utility;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Roadie.Library.Inspect.Plugins.Directory
{
public class DeleteUnwantedFiles : FolderPluginBase
{
public override bool IsEnabled => true;
public override bool IsPostProcessingPlugin => true;
public override string Description
{
get
{
return "Cleanup: Delete unwanted files";
}
}
public override int Order { get; } = 99;
public DeleteUnwantedFiles(IRoadieSettings configuration, ICacheManager cacheManager, ILogger logger, IID3TagsHelper tagsHelper)
: base(configuration, cacheManager, logger, tagsHelper)
{
}
public override OperationResult<string> Process(DirectoryInfo directory)
{
var result = new OperationResult<string>();
var data = string.Empty;
var deletedFiles = new List<string>();
var fileExtensionsToDelete = this.Configuration.FileExtensionsToDelete ?? new string[0];
foreach (var file in directory.GetFiles("*.*", SearchOption.AllDirectories))
{
if (fileExtensionsToDelete.Any(x => x.Equals(file.Extension, StringComparison.OrdinalIgnoreCase)))
{
if (!Configuration.Inspector.IsInReadOnlyMode)
{
file.Delete();
}
deletedFiles.Add(file.Name);
Console.WriteLine($" X Deleted File [{file}], Was foud in in FileExtensionsToDelete");
}
}
result.Data = $"Deleted [{ deletedFiles.Count() }] unwanted files"; ;
result.IsSuccess = true;
return result;
}
}
}

View file

@ -50,7 +50,7 @@ namespace Roadie.Library.Inspect.Plugins.Directory
foreach (var metaData in metaDatasForFilesInFolder.Where(x => x.Artist != artist))
{
modified++;
Console.WriteLine($"╟ Setting Arist to [{ artist }], was [{ metaData.Artist }] on file [{ metaData.FileInfo.Name}");
Console.WriteLine($"╟ Setting Artist to [{ artist }], was [{ metaData.Artist }] on file [{ metaData.FileInfo.Name}");
metaData.Artist = artist;
if (!Configuration.Inspector.IsInReadOnlyMode)
{

View file

@ -10,6 +10,8 @@ namespace Roadie.Library.Inspect.Plugins.Directory
{
public virtual bool IsEnabled => true;
public virtual bool IsPostProcessingPlugin => false;
public FolderPluginBase(IRoadieSettings configuration, ICacheManager cacheManager, ILogger logger, IID3TagsHelper tagsHelper)
: base(configuration, cacheManager, logger, tagsHelper)
{

View file

@ -5,6 +5,7 @@ namespace Roadie.Library.Inspect.Plugins.Directory
public interface IInspectorDirectoryPlugin
{
bool IsEnabled { get; }
bool IsPostProcessingPlugin { get; }
string Description { get; }
int Order { get; }

View file

@ -11,7 +11,7 @@ namespace Roadie.Library.Inspect.Plugins.File
public class CleanUpArtists : FilePluginBase
{
public override string Description => "Clean: Artist (TPE1) and TrackArtist (TOPE)";
public override int Order => 2;
public override int Order => 5;
public CleanUpArtists(IRoadieSettings configuration, ICacheManager cacheManager, ILogger logger, IID3TagsHelper tagsHelper)
: base(configuration, cacheManager, logger, tagsHelper)

View file

@ -9,7 +9,7 @@ namespace Roadie.Library.Inspect.Plugins.File
public class CleanUpComments : FilePluginBase
{
public override string Description => "Clean: Clear Comments (COMM)";
public override int Order => 2;
public override int Order => 5;
public CleanUpComments(IRoadieSettings configuration, ICacheManager cacheManager, ILogger logger, IID3TagsHelper tagsHelper)
: base(configuration, cacheManager, logger, tagsHelper)

View file

@ -10,7 +10,7 @@ namespace Roadie.Library.Inspect.Plugins.File
public class CleanUpReleaseTitle : FilePluginBase
{
public override string Description => "Clean: Release Title (TALB)";
public override int Order => 2;
public override int Order => 5;
public CleanUpReleaseTitle(IRoadieSettings configuration, ICacheManager cacheManager, ILogger logger, IID3TagsHelper tagsHelper)
: base(configuration, cacheManager, logger, tagsHelper)

View file

@ -10,7 +10,7 @@ namespace Roadie.Library.Inspect.Plugins.File
public class CleanUpTrackTitle : FilePluginBase
{
public override string Description => "Clean: Clean Track Title (TIT2) ";
public override int Order => 2;
public override int Order => 5;
public CleanUpTrackTitle(IRoadieSettings configuration, ICacheManager cacheManager, ILogger logger, IID3TagsHelper tagsHelper)
: base(configuration, cacheManager, logger, tagsHelper)

View file

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Extensions.Logging;
using Roadie.Library.Caching;
using Roadie.Library.Configuration;
using Roadie.Library.Extensions;
using Roadie.Library.MetaData.Audio;
using Roadie.Library.MetaData.ID3Tags;
namespace Roadie.Library.Inspect.Plugins.File
{
public class EnsureFileWriteable : FilePluginBase
{
public override string Description => "Ensure: Ensure file is writable ";
public override int Order => 1;
public EnsureFileWriteable(IRoadieSettings configuration, ICacheManager cacheManager, ILogger logger, IID3TagsHelper tagsHelper)
: base(configuration, cacheManager, logger, tagsHelper)
{
}
public override OperationResult<AudioMetaData> Process(AudioMetaData metaData)
{
var result = new OperationResult<AudioMetaData>();
if (this.Configuration.Processing.DoAudioCleanup)
{
if (metaData.FileInfo.IsReadOnly)
{
metaData.FileInfo.Attributes = RemoveAttribute(metaData.FileInfo.Attributes, FileAttributes.ReadOnly);
Console.WriteLine($"╟ Removed read only attribute on file file [{ metaData.FileInfo.Name}");
}
}
result.Data = metaData;
result.IsSuccess = true;
return result;
}
private static FileAttributes RemoveAttribute(FileAttributes attributes, FileAttributes attributesToRemove)
{
return attributes & ~attributesToRemove;
}
}
}

View file

@ -17,7 +17,7 @@ namespace Roadie.Library.Inspect.Plugins.File
}
}
public override int Order { get; } = 1;
public override int Order { get; } = 2;
public Renumber(IRoadieSettings configuration, ICacheManager cacheManager, ILogger logger, IID3TagsHelper tagsHelper)
: base(configuration, cacheManager, logger, tagsHelper)

View file

@ -449,7 +449,7 @@ namespace Roadie.Api.Services
var collectionReleases = (from cr in this.DbContext.CollectionReleases
where cr.CollectionId == collection.Id
select cr);
PositionAristRelease[] pars = null;
PositionArtistRelease[] pars = null;
try
{
@ -567,7 +567,7 @@ namespace Roadie.Api.Services
sw.Start();
CollectionRelease[] crs = new CollectionRelease[0];
var result = new List<PositionAristRelease>();
var result = new List<PositionArtistRelease>();
var errors = new List<Exception>();
var collection = this.DbContext.Collections.FirstOrDefault(x => x.RoadieId == collectionId);
if (collection == null)

View file

@ -523,13 +523,13 @@ namespace Roadie.Api.Services
// Ensure is jpeg first
artistSecondaryImage = ImageHelper.ConvertToJpegFormat(artistSecondaryImage);
var aristImageFilename = Path.Combine(newArtistFolder, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
while (File.Exists(aristImageFilename))
var artistImageFilename = Path.Combine(newArtistFolder, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
while (File.Exists(artistImageFilename))
{
looper++;
aristImageFilename = Path.Combine(newArtistFolder, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
artistImageFilename = Path.Combine(newArtistFolder, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
}
File.WriteAllBytes(aristImageFilename, artistSecondaryImage);
File.WriteAllBytes(artistImageFilename, artistSecondaryImage);
}
looper++;
}

View file

@ -70,7 +70,7 @@
"Width": 320
},
"DontDoMetaDataProvidersSearchArtists": [ "Various Artists", "Sound Tracks" ],
"FileExtenionsToDelete": [ ".cue", ".db", ".gif", ".html", ".ini", ".jpg", ".jpeg", ".log", ".mpg", ".m3u", ".png", ".nfo", ".nzb", ".sfv", ".srr", ".txt", ".url" ],
"FileExtensionsToDelete": [ ".cue", ".db", ".gif", ".html", ".ini", ".jpg", ".jpeg", ".log", ".mpg", ".m3u", ".png", ".nfo", ".nzb", ".sfv", ".srr", ".txt", ".url" ],
"RecordNoResultSearches": true,
"ArtistNameReplace": {
"AC/DC": [ "AC; DC", "AC;DC", "AC/ DC", "AC DC" ],

View file

@ -70,7 +70,7 @@
"Width": 320
},
"DontDoMetaDataProvidersSearchArtists": [ "Various Artists", "Sound Tracks" ],
"FileExtenionsToDelete": [ ".cue", ".db", ".gif", ".html", ".ini", ".jpg", ".jpeg", ".log", ".mpg", ".m3u", ".png", ".nfo", ".nzb", ".sfv", ".srr", ".txt", ".url" ],
"FileExtensionsToDelete": [ ".cue", ".db", ".gif", ".html", ".ini", ".jpg", ".jpeg", ".log", ".mpg", ".m3u", ".png", ".nfo", ".nzb", ".sfv", ".srr", ".txt", ".url" ],
"RecordNoResultSearches": true,
"ArtistNameReplace": {
"AC/DC": [ "AC; DC", "AC;DC", "AC/ DC", "AC DC" ],