diff --git a/Roadie.Api.Library/Data/CollectionPartial.cs b/Roadie.Api.Library/Data/CollectionPartial.cs index 55d762c..9279208 100644 --- a/Roadie.Api.Library/Data/CollectionPartial.cs +++ b/Roadie.Api.Library/Data/CollectionPartial.cs @@ -13,6 +13,11 @@ namespace Roadie.Library.Data { public partial class Collection { + /// + /// If the given value in either Artist or Release starts with this then the next value is the database Id, example "1,~4,~19" + /// + public static string DatabaseIdKey = "~"; + public int? _artistColumn; public int? _positionColumn; diff --git a/Roadie.Api.Library/Engines/ArtistLookupEngine.cs b/Roadie.Api.Library/Engines/ArtistLookupEngine.cs index 19af09a..41baae8 100644 --- a/Roadie.Api.Library/Engines/ArtistLookupEngine.cs +++ b/Roadie.Api.Library/Engines/ArtistLookupEngine.cs @@ -152,7 +152,10 @@ namespace Roadie.Library.Engines public Artist DatabaseQueryForArtistName(string name, string sortName = null) { - if (string.IsNullOrEmpty(name)) return null; + if (string.IsNullOrEmpty(name)) + { + return null; + } try { var searchName = name.NormalizeName(); @@ -242,6 +245,9 @@ namespace Roadie.Library.Engines OperationTime = sw.ElapsedMilliseconds, Errors = addResult.Errors }; + } else + { + File.Delete(releaseRoadieDataFilename); } artist = addResult.Data; } diff --git a/Roadie.Api.Library/Engines/IReleaseLookupEngine.cs b/Roadie.Api.Library/Engines/IReleaseLookupEngine.cs index b52db37..a508e9c 100644 --- a/Roadie.Api.Library/Engines/IReleaseLookupEngine.cs +++ b/Roadie.Api.Library/Engines/IReleaseLookupEngine.cs @@ -20,10 +20,10 @@ namespace Roadie.Library.Engines Task> Add(Release release, bool doAddTracksInDatabase = false); - Task> GetByName(Artist artist, AudioMetaData metaData, - bool doFindIfNotInDatabase = false, bool doAddTracksInDatabase = false, int? submissionId = null); + Release DatabaseQueryForReleaseTitle(Artist artist, string title, string sortTitle = null); - Task> PerformMetaDataProvidersReleaseSearch(AudioMetaData metaData, - string artistFolder = null, int? submissionId = null); + Task> GetByName(Artist artist, AudioMetaData metaData, bool doFindIfNotInDatabase = false, bool doAddTracksInDatabase = false, int? submissionId = null); + + Task> PerformMetaDataProvidersReleaseSearch(AudioMetaData metaData, string artistFolder = null, int? submissionId = null); } } \ No newline at end of file diff --git a/Roadie.Api.Library/Engines/ReleaseLookupEngine.cs b/Roadie.Api.Library/Engines/ReleaseLookupEngine.cs index 02cf578..2f68bf7 100644 --- a/Roadie.Api.Library/Engines/ReleaseLookupEngine.cs +++ b/Roadie.Api.Library/Engines/ReleaseLookupEngine.cs @@ -287,8 +287,51 @@ namespace Roadie.Library.Engines }; } - public async Task> GetByName(Artist artist, AudioMetaData metaData, - bool doFindIfNotInDatabase = false, bool doAddTracksInDatabase = false, int? submissionId = null) + public Release DatabaseQueryForReleaseTitle(Artist artist, string title, string sortTitle = null) + { + if (string.IsNullOrEmpty(title)) + { + return null; + } + try + { + var searchName = title.NormalizeName(); + var searchSortName = !string.IsNullOrEmpty(sortTitle) ? sortTitle.NormalizeName().ToLower() : searchName; + var specialSearchName = title.ToAlphanumericName(); + + var searchNameStart = $"{searchName}|"; + var searchNameIn = $"|{searchName}|"; + var searchNameEnd = $"|{searchName}"; + + var specialSearchNameStart = $"{specialSearchName}|"; + var specialSearchNameIn = $"|{specialSearchName}|"; + var specialSearchNameEnd = $"|{specialSearchName}"; + + return (from a in DbContext.Releases + where a.ArtistId == artist.Id + where a.Title == searchName || + a.Title == specialSearchName || + a.SortTitle == searchName || + a.SortTitle == searchSortName || + a.SortTitle == specialSearchName || + a.AlternateNames.StartsWith(searchNameStart) || + a.AlternateNames.Contains(searchNameIn) || + a.AlternateNames.EndsWith(searchNameEnd) || + a.AlternateNames.StartsWith(specialSearchNameStart) || + a.AlternateNames.Contains(specialSearchNameIn) || + a.AlternateNames.EndsWith(specialSearchNameEnd) + select a + ).FirstOrDefault(); + } + catch (Exception ex) + { + Logger.LogError(ex, ex.Serialize()); + } + + return null; + } + + public async Task> GetByName(Artist artist, AudioMetaData metaData, bool doFindIfNotInDatabase = false, bool doAddTracksInDatabase = false, int? submissionId = null) { SimpleContract.Requires(artist != null, "Invalid Artist"); SimpleContract.Requires(artist.Id > 0, "Invalid Artist Id"); @@ -310,44 +353,44 @@ namespace Roadie.Library.Engines }; } - var searchName = metaData.Release.NormalizeName().ToLower(); - var specialSearchName = metaData.Release.ToAlphanumericName(); + var release = DatabaseQueryForReleaseTitle(artist, metaData.Release); - var altStart = $"{searchName}|"; - var altIn = $"|{searchName}|"; - var altEnds = $"|{searchName}"; + //var searchName = metaData.Release.NormalizeName().ToLower(); + //var specialSearchName = metaData.Release.ToAlphanumericName(); - var altStartSpecial = $"{specialSearchName}|"; - var altInSpecial = $"|{specialSearchName}|"; - var altEndsSpecial = $"|{specialSearchName}"; + //var altStart = $"{searchName}|"; + //var altIn = $"|{searchName}|"; + //var altEnds = $"|{searchName}"; - var release = (from r in DbContext.Releases - where r.ArtistId == artist.Id - where r.Title == searchName || - r.Title == specialSearchName || - r.AlternateNames == searchName || - r.AlternateNames == specialSearchName || - r.AlternateNames.Contains(altStart) || - r.AlternateNames.Contains(altIn) || - r.AlternateNames.Contains(altEnds) || - r.AlternateNames.Contains(altStartSpecial) || - r.AlternateNames.Contains(altInSpecial) || - r.AlternateNames.Contains(altEndsSpecial) - select r - ).FirstOrDefault(); + //var altStartSpecial = $"{specialSearchName}|"; + //var altInSpecial = $"|{specialSearchName}|"; + //var altEndsSpecial = $"|{specialSearchName}"; + + //var release = (from r in DbContext.Releases + // where r.ArtistId == artist.Id + // where r.Title == searchName || + // r.Title == specialSearchName || + // r.AlternateNames == searchName || + // r.AlternateNames == specialSearchName || + // r.AlternateNames.Contains(altStart) || + // r.AlternateNames.Contains(altIn) || + // r.AlternateNames.Contains(altEnds) || + // r.AlternateNames.Contains(altStartSpecial) || + // r.AlternateNames.Contains(altInSpecial) || + // r.AlternateNames.Contains(altEndsSpecial) + // select r + // ).FirstOrDefault(); sw.Stop(); if (release == null || !release.IsValid) { - Logger.LogTrace("ReleaseFactory: Release Not Found For Artist `{0}` MetaData [{1}]", - artist.ToString(), metaData.ToString()); + Logger.LogTrace("ReleaseFactory: Release Not Found For Artist `{0}` MetaData [{1}]", artist.ToString(), metaData.ToString()); if (doFindIfNotInDatabase) { var releaseSearch = new OperationResult(); try { - releaseSearch = await PerformMetaDataProvidersReleaseSearch(metaData, - artist.ArtistFileFolder(Configuration), submissionId); + releaseSearch = await PerformMetaDataProvidersReleaseSearch(metaData, artist.ArtistFileFolder(Configuration), submissionId); } catch (Exception ex) { diff --git a/Roadie.Api.Services/AdminService.cs b/Roadie.Api.Services/AdminService.cs index d571fac..914594c 100644 --- a/Roadie.Api.Services/AdminService.cs +++ b/Roadie.Api.Services/AdminService.cs @@ -37,6 +37,7 @@ namespace Roadie.Api.Services private IGenreService GenreService { get; } private ILabelService LabelService { get; } + private IArtistLookupEngine ArtistLookupEngine { get; } private IReleaseLookupEngine ReleaseLookupEngine { get; } private IReleaseService ReleaseService { get; } @@ -44,7 +45,8 @@ namespace Roadie.Api.Services public AdminService(IRoadieSettings configuration, IHttpEncoder httpEncoder, IHttpContext httpContext, data.IRoadieDbContext context, ICacheManager cacheManager, ILogger logger, IHubContext scanActivityHub, IFileDirectoryProcessorService fileDirectoryProcessorService, IArtistService artistService, - IReleaseService releaseService, IReleaseLookupEngine releaseLookupEngine, ILabelService labelService, IGenreService genreService + IReleaseService releaseService, IArtistLookupEngine artistLookupEngine, IReleaseLookupEngine releaseLookupEngine, + ILabelService labelService, IGenreService genreService ) : base(configuration, httpEncoder, context, cacheManager, logger, httpContext) { @@ -56,6 +58,7 @@ namespace Roadie.Api.Services ReleaseService = releaseService; LabelService = labelService; GenreService = genreService; + ArtistLookupEngine = artistLookupEngine; ReleaseLookupEngine = releaseLookupEngine; FileDirectoryProcessorService = fileDirectoryProcessorService; } @@ -719,8 +722,7 @@ namespace Roadie.Api.Services }; } - public async Task> ScanCollection(ApplicationUser user, Guid collectionId, - bool isReadOnly = false, bool doPurgeFirst = false, bool doUpdateRanks = true) + public async Task> ScanCollection(ApplicationUser user, Guid collectionId, bool isReadOnly = false, bool doPurgeFirst = false, bool doUpdateRanks = true) { var sw = new Stopwatch(); sw.Start(); @@ -740,7 +742,7 @@ namespace Roadie.Api.Services { if (doPurgeFirst) { - await LogAndPublish($"ScanCollection Purgeing Collection [{collectionId}]", LogLevel.Warning); + await LogAndPublish($"ScanCollection Purging Collection [{collectionId}]", LogLevel.Warning); var crs = DbContext.CollectionReleases.Where(x => x.CollectionId == collection.Id).ToArray(); DbContext.CollectionReleases.RemoveRange(crs); await DbContext.SaveChangesAsync(); @@ -759,55 +761,51 @@ namespace Roadie.Api.Services data.Artist artist = null; data.Release release = null; - var artistSearchName = csvRelease.Artist.NormalizeName(); - var artistSpecialSearchName = csvRelease.Artist.ToAlphanumericName(); - var releaseSearchName = csvRelease.Release.NormalizeName().ToLower(); - var releaseSpecialSearchName = csvRelease.Release.ToAlphanumericName(); - - var artistResults = (from a in DbContext.Artists - where a.Name.Contains(artistSearchName) || - a.SortName.Contains(artistSearchName) || - a.AlternateNames.Contains(artistSearchName) || - a.AlternateNames.Contains(artistSpecialSearchName) - select a).ToArray(); - if (!artistResults.Any()) + var isArtistNameDbKey = csvRelease.Artist.StartsWith(Roadie.Library.Data.Collection.DatabaseIdKey); + int? artistId = isArtistNameDbKey ? SafeParser.ToNumber(csvRelease.Artist.Replace(Roadie.Library.Data.Collection.DatabaseIdKey, "")) : null; + if(artistId.HasValue) { - await LogAndPublish($"Unable To Find Artist [{csvRelease.Artist}], SearchName [{artistSpecialSearchName}]", LogLevel.Warning); + artist = DbContext.Artists.FirstOrDefault(x => x.Id == artistId.Value); + } + else + { + artist = ArtistLookupEngine.DatabaseQueryForArtistName(csvRelease.Artist); + } + if (artist == null) + { + await LogAndPublish($"CSV Position [{ csvRelease.Position }] Unable To Find Artist [{csvRelease.Artist}]", LogLevel.Warning); csvRelease.Status = Statuses.Missing; DbContext.CollectionMissings.Add(new data.CollectionMissing { CollectionId = collection.Id, Position = csvRelease.Position, - Artist = artistSpecialSearchName, - Release = releaseSpecialSearchName + Artist = csvRelease.Artist, + Release = csvRelease.Release }); continue; } - foreach (var artistResult in artistResults) + var isReleaseNameDbKey = csvRelease.Release.StartsWith(Roadie.Library.Data.Collection.DatabaseIdKey); + int? releaseId = isReleaseNameDbKey ? SafeParser.ToNumber(csvRelease.Release.Replace(Roadie.Library.Data.Collection.DatabaseIdKey, "")) : null; + if (releaseId.HasValue) { - artist = artistResult; - release = (from r in DbContext.Releases - where r.ArtistId == artist.Id - where r.Title.Contains(releaseSearchName) || - r.AlternateNames.Contains(releaseSearchName) || - r.AlternateNames.Contains(releaseSpecialSearchName) - select r - ).FirstOrDefault(); - if (release != null) break; + release = DbContext.Releases.FirstOrDefault(x => x.Id == releaseId.Value); + } + else + { + release = ReleaseLookupEngine.DatabaseQueryForReleaseTitle(artist, csvRelease.Release); } - if (release == null) { - await LogAndPublish($"Unable To Find Release [{csvRelease.Release}] for Artist [{csvRelease.Artist}], SearchName [{artistSearchName}]", LogLevel.Warning); + await LogAndPublish($"CSV Position [{ csvRelease.Position }] Unable To Find Release [{csvRelease.Release}], for Artist [{csvRelease.Artist}]", LogLevel.Warning); csvRelease.Status = Statuses.Missing; DbContext.CollectionMissings.Add(new data.CollectionMissing { CollectionId = collection.Id, IsArtistFound = true, Position = csvRelease.Position, - Artist = artistSpecialSearchName, - Release = releaseSpecialSearchName + Artist = csvRelease.Artist, + Release = csvRelease.Release }); continue; } diff --git a/Roadie.Api.Services/ImageService.cs b/Roadie.Api.Services/ImageService.cs index b5bcaec..c57d9d3 100644 --- a/Roadie.Api.Services/ImageService.cs +++ b/Roadie.Api.Services/ImageService.cs @@ -694,10 +694,10 @@ namespace Roadie.Api.Services { CreatedDate = track.CreatedDate }; - var trackThumbnailImages = ImageHelper.FindImageTypeInDirectory( new DirectoryInfo(track.PathToTrackThumbnail(Configuration)), ImageType.Track, SearchOption.TopDirectoryOnly); - if (trackThumbnailImages.Any()) + var trackImageFileName = track.PathToTrackThumbnail(Configuration); + if (File.Exists(trackImageFileName)) { - image.Bytes = File.ReadAllBytes(trackThumbnailImages.First().FullName); + image.Bytes = File.ReadAllBytes(trackImageFileName); } if (image.Bytes == null || !image.Bytes.Any()) { diff --git a/Roadie.Api/Controllers/AdminController.cs b/Roadie.Api/Controllers/AdminController.cs index 92ab30b..3be7445 100644 --- a/Roadie.Api/Controllers/AdminController.cs +++ b/Roadie.Api/Controllers/AdminController.cs @@ -260,9 +260,9 @@ namespace Roadie.Api.Controllers [HttpPost("scan/collection/{id}")] [ProducesResponseType(200)] - public async Task ScanCollection(Guid id) + public async Task ScanCollection(Guid id, bool doPurgeFirst = false) { - var result = await AdminService.ScanCollection(await UserManager.GetUserAsync(User), id); + var result = await AdminService.ScanCollection(await UserManager.GetUserAsync(User), id, doPurgeFirst: doPurgeFirst); if (!result.IsSuccess) { if (result.Messages?.Any() ?? false)