Several performance improvements. Updated NuGet packages.

This commit is contained in:
Steven Hildreth 2020-06-05 17:49:12 -05:00
parent 1bf0df6c97
commit 625fdf7266
17 changed files with 235 additions and 180 deletions

View file

@ -26,7 +26,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.4" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1"> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.2">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference> </PackageReference>

View file

@ -20,7 +20,7 @@ namespace Roadie.Library.Engines
Task<OperationResult<Release>> Add(Release release, bool doAddTracksInDatabase = false); Task<OperationResult<Release>> Add(Release release, bool doAddTracksInDatabase = false);
Release DatabaseQueryForReleaseTitle(Artist artist, string title, string sortTitle = null); Task<Release> DatabaseQueryForReleaseTitle(Artist artist, string title, string sortTitle = null);
Task<OperationResult<Release>> GetByName(Artist artist, AudioMetaData metaData, bool doFindIfNotInDatabase = false, bool doAddTracksInDatabase = false, int? submissionId = null); Task<OperationResult<Release>> GetByName(Artist artist, AudioMetaData metaData, bool doFindIfNotInDatabase = false, bool doAddTracksInDatabase = false, int? submissionId = null);

View file

@ -1,4 +1,5 @@
using Microsoft.Extensions.Logging; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Roadie.Library.Caching; using Roadie.Library.Caching;
using Roadie.Library.Configuration; using Roadie.Library.Configuration;
using Roadie.Library.Data; using Roadie.Library.Data;
@ -292,7 +293,7 @@ namespace Roadie.Library.Engines
}; };
} }
public Release DatabaseQueryForReleaseTitle(Artist artist, string title, string sortTitle = null) public async Task<Release> DatabaseQueryForReleaseTitle(Artist artist, string title, string sortTitle = null)
{ {
if (string.IsNullOrEmpty(title)) if (string.IsNullOrEmpty(title))
{ {
@ -312,7 +313,7 @@ namespace Roadie.Library.Engines
var specialSearchNameIn = $"|{specialSearchName}|"; var specialSearchNameIn = $"|{specialSearchName}|";
var specialSearchNameEnd = $"|{specialSearchName}"; var specialSearchNameEnd = $"|{specialSearchName}";
return (from a in DbContext.Releases return await (from a in DbContext.Releases
where a.ArtistId == artist.Id where a.ArtistId == artist.Id
where a.Title.ToLower() == searchName || where a.Title.ToLower() == searchName ||
a.Title.ToLower() == specialSearchName || a.Title.ToLower() == specialSearchName ||
@ -328,7 +329,7 @@ namespace Roadie.Library.Engines
a.AlternateNames.ToLower().Contains(specialSearchNameIn) || a.AlternateNames.ToLower().Contains(specialSearchNameIn) ||
a.AlternateNames.ToLower().EndsWith(specialSearchNameEnd) a.AlternateNames.ToLower().EndsWith(specialSearchNameEnd)
select a select a
).FirstOrDefault(); ).FirstOrDefaultAsync().ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -360,7 +361,7 @@ namespace Roadie.Library.Engines
}; };
} }
var release = DatabaseQueryForReleaseTitle(artist, metaData.Release); var release = await DatabaseQueryForReleaseTitle(artist, metaData.Release).ConfigureAwait(false);
sw.Stop(); sw.Stop();
if (release?.IsValid != true) if (release?.IsValid != true)
@ -741,7 +742,7 @@ namespace Roadie.Library.Engines
{ {
result.Genres.Add(new ReleaseGenre result.Genres.Add(new ReleaseGenre
{ {
Genre = DbContext.Genres.Where(x => x.Name.ToLower() == g.ToLower()).FirstOrDefault() ?? new Genre Genre = DbContext.Genres.Where(x => string.Equals(x.Name, g, StringComparison.OrdinalIgnoreCase)).FirstOrDefault() ?? new Genre
{ {
Name = g, Name = g,
NormalizedName = g.ToAlphanumericName() NormalizedName = g.ToAlphanumericName()

View file

@ -99,6 +99,38 @@ namespace Roadie.Library.Imaging
return result; return result;
} }
public static bool IsImageBetterQuality(string image1, string compareToImage)
{
if(string.IsNullOrEmpty(compareToImage))
{
return true;
}
try
{
if (string.IsNullOrEmpty(image1) || !File.Exists(image1))
{
return File.Exists(compareToImage);
}
using (var imageComparing = SixLabors.ImageSharp.Image.Load(image1))
{
using (var imageToCompare = SixLabors.ImageSharp.Image.Load(compareToImage))
{
// Generally a larger image is the preferred image
var isBigger = imageToCompare.Height > imageComparing.Height && imageToCompare.Width > imageComparing.Width;
if (isBigger)
{
return true;
}
}
}
}
catch (Exception ex)
{
Trace.WriteLine($"Error IsImageBetterQuality Image Comparing [{ image1 }] to [{ compareToImage }], Error [{ ex }]", "Warning");
}
return false;
}
public static IEnumerable<FileInfo> FindImageTypeInDirectory(DirectoryInfo directory, ImageType type, SearchOption folderSearchOptions = SearchOption.AllDirectories) public static IEnumerable<FileInfo> FindImageTypeInDirectory(DirectoryInfo directory, ImageType type, SearchOption folderSearchOptions = SearchOption.AllDirectories)
{ {
var result = new List<FileInfo>(); var result = new List<FileInfo>();

View file

@ -11,14 +11,14 @@
<PackageReference Include="AutoCompare.Core" Version="1.0.0" /> <PackageReference Include="AutoCompare.Core" Version="1.0.0" />
<PackageReference Include="CsvHelper" Version="15.0.5" /> <PackageReference Include="CsvHelper" Version="15.0.5" />
<PackageReference Include="EFCore.BulkExtensions" Version="3.1.1" /> <PackageReference Include="EFCore.BulkExtensions" Version="3.1.1" />
<PackageReference Include="FluentFTP" Version="32.4.1" /> <PackageReference Include="FluentFTP" Version="32.4.3" />
<PackageReference Include="Hashids.net" Version="1.3.0" /> <PackageReference Include="Hashids.net" Version="1.3.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.23" /> <PackageReference Include="HtmlAgilityPack" Version="1.11.24" />
<PackageReference Include="IdSharp.Common" Version="1.0.1" /> <PackageReference Include="IdSharp.Common" Version="1.0.1" />
<PackageReference Include="IdSharp.Tagging" Version="1.0.0-rc3" /> <PackageReference Include="IdSharp.Tagging" Version="1.0.0-rc3" />
<PackageReference Include="Inflatable.Lastfm" Version="1.1.0.339" /> <PackageReference Include="Inflatable.Lastfm" Version="1.1.0.339" />
<PackageReference Include="LiteDB" Version="5.0.8" /> <PackageReference Include="LiteDB" Version="5.0.8" />
<PackageReference Include="Mapster" Version="5.3.1" /> <PackageReference Include="Mapster" Version="5.3.2" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.4" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.4" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.4" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.4" />
@ -39,7 +39,7 @@
<PackageReference Include="System.Drawing.Common" Version="4.7.0" /> <PackageReference Include="System.Drawing.Common" Version="4.7.0" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.7.0" /> <PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.7.0" />
<PackageReference Include="System.Runtime.Caching" Version="4.7.0" /> <PackageReference Include="System.Runtime.Caching" Version="4.7.0" />
<PackageReference Include="z440.atl.core" Version="3.4.1" /> <PackageReference Include="z440.atl.core" Version="3.5.0" />
<PackageReference Include="zlib.net-mutliplatform" Version="1.0.4" /> <PackageReference Include="zlib.net-mutliplatform" Version="1.0.4" />
</ItemGroup> </ItemGroup>

View file

@ -640,19 +640,19 @@ namespace Roadie.Api.Services
Logger.LogInformation($"Administration startup tasks completed, elapsed time [{ sw.ElapsedMilliseconds }]"); Logger.LogInformation($"Administration startup tasks completed, elapsed time [{ sw.ElapsedMilliseconds }]");
} }
public async Task<OperationResult<bool>> ScanAllCollections(User user, bool isReadOnly = false, public async Task<OperationResult<bool>> ScanAllCollections(User user, bool isReadOnly = false, bool doPurgeFirst = false)
bool doPurgeFirst = false)
{ {
var sw = new Stopwatch(); var sw = new Stopwatch();
sw.Start(); sw.Start();
var errors = new List<Exception>(); var errors = new List<Exception>();
var collections = await DbContext.Collections.Where(x => x.IsLocked == false).ToArrayAsync(); var collections = await DbContext.Collections.Where(x => x.IsLocked == false).ToArrayAsync().ConfigureAwait(false);
var updatedReleaseIds = new List<int>(); var updatedReleaseIds = new List<int>();
foreach (var collection in collections) foreach (var collection in collections)
{
try try
{ {
var result = await ScanCollection(user, collection.RoadieId, isReadOnly, doPurgeFirst, false); var result = await ScanCollection(user, collection.RoadieId, isReadOnly, doPurgeFirst, false).ConfigureAwait(false);
if (!result.IsSuccess) if (!result.IsSuccess)
{ {
errors.AddRange(result.Errors); errors.AddRange(result.Errors);
@ -661,19 +661,20 @@ namespace Roadie.Api.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
await LogAndPublish(ex.ToString(), LogLevel.Error); await LogAndPublish(ex.ToString(), LogLevel.Error).ConfigureAwait(false);
errors.Add(ex); errors.Add(ex);
} }
}
foreach (var updatedReleaseId in updatedReleaseIds.Distinct()) foreach (var updatedReleaseId in updatedReleaseIds.Distinct())
{ {
await UpdateReleaseRank(updatedReleaseId); await UpdateReleaseRank(updatedReleaseId).ConfigureAwait(false);
} }
sw.Stop(); sw.Stop();
await LogAndPublish($"ScanAllCollections, By User `{user}`, Updated Release Count [{updatedReleaseIds.Distinct().Count()}], ElapsedTime [{sw.ElapsedMilliseconds}]", LogLevel.Warning); await LogAndPublish($"ScanAllCollections, By User `{user}`, Updated Release Count [{updatedReleaseIds.Distinct().Count()}], ElapsedTime [{sw.ElapsedMilliseconds}]", LogLevel.Warning).ConfigureAwait(false);
return new OperationResult<bool> return new OperationResult<bool>
{ {
IsSuccess = !errors.Any(), IsSuccess = errors.Count == 0,
Data = true, Data = true,
OperationTime = sw.ElapsedMilliseconds, OperationTime = sw.ElapsedMilliseconds,
Errors = errors Errors = errors
@ -758,10 +759,10 @@ namespace Roadie.Api.Services
var updatedReleaseIds = new List<int>(); var updatedReleaseIds = new List<int>();
var result = new List<data.PositionArtistRelease>(); var result = new List<data.PositionArtistRelease>();
var errors = new List<Exception>(); var errors = new List<Exception>();
var collection = DbContext.Collections.FirstOrDefault(x => x.RoadieId == collectionId); var collection = await DbContext.Collections.FirstOrDefaultAsync(x => x.RoadieId == collectionId).ConfigureAwait(false);
if (collection == null) if (collection == null)
{ {
await LogAndPublish($"ScanCollection Unknown Collection [{collectionId}]", LogLevel.Warning); await LogAndPublish($"ScanCollection Unknown Collection [{collectionId}]", LogLevel.Warning).ConfigureAwait(false);
return new OperationResult<bool>(true, $"Collection Not Found [{collectionId}]"); return new OperationResult<bool>(true, $"Collection Not Found [{collectionId}]");
} }
@ -769,15 +770,15 @@ namespace Roadie.Api.Services
{ {
if (doPurgeFirst) if (doPurgeFirst)
{ {
await LogAndPublish($"ScanCollection Purging Collection [{collectionId}]", LogLevel.Warning); await LogAndPublish($"ScanCollection Purging Collection [{collectionId}]", LogLevel.Warning).ConfigureAwait(false);
var crs = await DbContext.CollectionReleases.Where(x => x.CollectionId == collection.Id).ToArrayAsync(); var crs = await DbContext.CollectionReleases.Where(x => x.CollectionId == collection.Id).ToArrayAsync().ConfigureAwait(false);
DbContext.CollectionReleases.RemoveRange(crs); DbContext.CollectionReleases.RemoveRange(crs);
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync().ConfigureAwait(false);
} }
var collectionMissingRecords = DbContext.CollectionMissings.Where(x => x.CollectionId == collection.Id); var collectionMissingRecords = DbContext.CollectionMissings.Where(x => x.CollectionId == collection.Id);
DbContext.CollectionMissings.RemoveRange(collectionMissingRecords); DbContext.CollectionMissings.RemoveRange(collectionMissingRecords);
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync().ConfigureAwait(false);
var par = collection.PositionArtistReleases(); var par = collection.PositionArtistReleases();
if (par != null) if (par != null)
@ -800,23 +801,23 @@ namespace Roadie.Api.Services
} }
else else
{ {
artistsMatchingName = await ArtistLookupEngine.DatabaseQueryForArtistName(csvRelease.Artist); artistsMatchingName = await ArtistLookupEngine.DatabaseQueryForArtistName(csvRelease.Artist).ConfigureAwait(false);
if (artistsMatchingName == null || !artistsMatchingName.Any()) if (artistsMatchingName == null || !artistsMatchingName.Any())
{ {
await LogAndPublish($"CSV Position [{ csvRelease.Position }] Unable To Find Artist [{csvRelease.Artist}]", LogLevel.Warning); await LogAndPublish($"CSV Position [{ csvRelease.Position }] Unable To Find Artist [{csvRelease.Artist}]", LogLevel.Warning).ConfigureAwait(false);
csvRelease.Status = Statuses.Missing; csvRelease.Status = Statuses.Missing;
DbContext.CollectionMissings.Add(new data.CollectionMissing await DbContext.CollectionMissings.AddAsync(new data.CollectionMissing
{ {
CollectionId = collection.Id, CollectionId = collection.Id,
Position = csvRelease.Position, Position = csvRelease.Position,
Artist = csvRelease.Artist, Artist = csvRelease.Artist,
Release = csvRelease.Release Release = csvRelease.Release
}); }).ConfigureAwait(false);
continue; continue;
} }
else if (artistsMatchingName.Count() > 1) else if (artistsMatchingName.Count() > 1)
{ {
await LogAndPublish($"CSV Position [{ csvRelease.Position }] Found [{ artistsMatchingName.Count() }] Artists by [{csvRelease.Artist}]", LogLevel.Information); await LogAndPublish($"CSV Position [{ csvRelease.Position }] Found [{ artistsMatchingName.Count() }] Artists by [{csvRelease.Artist}]", LogLevel.Information).ConfigureAwait(false);
} }
} }
foreach (var artist in artistsMatchingName) foreach (var artist in artistsMatchingName)
@ -825,11 +826,11 @@ namespace Roadie.Api.Services
int? releaseId = isReleaseNameDbKey ? SafeParser.ToNumber<int?>(csvRelease.Release.Replace(Roadie.Library.Data.Collection.DatabaseIdKey, "")) : null; int? releaseId = isReleaseNameDbKey ? SafeParser.ToNumber<int?>(csvRelease.Release.Replace(Roadie.Library.Data.Collection.DatabaseIdKey, "")) : null;
if (releaseId.HasValue) if (releaseId.HasValue)
{ {
release = DbContext.Releases.FirstOrDefault(x => x.Id == releaseId.Value); release = await DbContext.Releases.FirstOrDefaultAsync(x => x.Id == releaseId.Value).ConfigureAwait(false);
} }
else else
{ {
release = ReleaseLookupEngine.DatabaseQueryForReleaseTitle(artist, csvRelease.Release); release = await ReleaseLookupEngine.DatabaseQueryForReleaseTitle(artist, csvRelease.Release).ConfigureAwait(false);
} }
if (release != null) if (release != null)
{ {
@ -839,28 +840,29 @@ namespace Roadie.Api.Services
if (release == null) if (release == null)
{ {
await LogAndPublish($"CSV Position [{ csvRelease.Position }] Unable To Find Release [{csvRelease.Release}], for Artist [{csvRelease.Artist}]", LogLevel.Warning); await LogAndPublish($"CSV Position [{ csvRelease.Position }] Unable To Find Release [{csvRelease.Release}], for Artist [{csvRelease.Artist}]", LogLevel.Warning).ConfigureAwait(false);
csvRelease.Status = Statuses.Missing; csvRelease.Status = Statuses.Missing;
DbContext.CollectionMissings.Add(new data.CollectionMissing await DbContext.CollectionMissings.AddAsync(new data.CollectionMissing
{ {
CollectionId = collection.Id, CollectionId = collection.Id,
IsArtistFound = true, IsArtistFound = true,
Position = csvRelease.Position, Position = csvRelease.Position,
Artist = csvRelease.Artist, Artist = csvRelease.Artist,
Release = csvRelease.Release Release = csvRelease.Release
}); }).ConfigureAwait(false);
continue; continue;
} }
var isInCollection = DbContext.CollectionReleases.FirstOrDefault(x => var isInCollection = await DbContext.CollectionReleases.FirstOrDefaultAsync(x =>
x.CollectionId == collection.Id && x.CollectionId == collection.Id &&
x.ListNumber == csvRelease.Position && x.ListNumber == csvRelease.Position &&
x.ReleaseId == release.Id); x.ReleaseId == release.Id)
.ConfigureAwait(false);
var updated = false; var updated = false;
// Found in Database but not in collection add to Collection // Found in Database but not in collection add to Collection
if (isInCollection == null) if (isInCollection == null)
{ {
DbContext.CollectionReleases.Add(new data.CollectionRelease await DbContext.CollectionReleases.AddAsync(new data.CollectionRelease
{ {
CollectionId = collection.Id, CollectionId = collection.Id,
ReleaseId = release.Id, ReleaseId = release.Id,
@ -884,7 +886,7 @@ namespace Roadie.Api.Services
} }
collection.LastUpdated = now; collection.LastUpdated = now;
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync().ConfigureAwait(false);
var dto = new CollectionList var dto = new CollectionList
{ {
CollectionCount = collection.CollectionCount, CollectionCount = collection.CollectionCount,
@ -903,10 +905,10 @@ namespace Roadie.Api.Services
collection.Status = Statuses.Incomplete; collection.Status = Statuses.Incomplete;
} }
var collectionReleasesToRemove = (from cr in DbContext.CollectionReleases var collectionReleasesToRemove = await (from cr in DbContext.CollectionReleases
where cr.CollectionId == collection.Id where cr.CollectionId == collection.Id
where !releaseIdsInCollection.Contains(cr.ReleaseId) where !releaseIdsInCollection.Contains(cr.ReleaseId)
select cr).ToArray(); select cr).ToArrayAsync().ConfigureAwait(false);
if (collectionReleasesToRemove.Any()) if (collectionReleasesToRemove.Any())
{ {
await LogAndPublish($"Removing [{collectionReleasesToRemove.Count()}] Stale Release Records from Collection.", LogLevel.Information); await LogAndPublish($"Removing [{collectionReleasesToRemove.Count()}] Stale Release Records from Collection.", LogLevel.Information);
@ -918,7 +920,7 @@ namespace Roadie.Api.Services
{ {
foreach (var updatedReleaseId in updatedReleaseIds) foreach (var updatedReleaseId in updatedReleaseIds)
{ {
await UpdateReleaseRank(updatedReleaseId); await UpdateReleaseRank(updatedReleaseId).ConfigureAwait(false);
} }
} }
CacheManager.ClearRegion(collection.CacheRegion); CacheManager.ClearRegion(collection.CacheRegion);
@ -1113,7 +1115,7 @@ namespace Roadie.Api.Services
break; break;
} }
await ScanActivityHub.Clients.All.SendAsync("SendSystemActivity", message); await ScanActivityHub.Clients.All.SendAsync("SendSystemActivity", message).ConfigureAwait(false);
} }
private async Task<OperationResult<bool>> ScanFolder(User user, DirectoryInfo d, bool isReadOnly, bool doDeleteFiles = true) private async Task<OperationResult<bool>> ScanFolder(User user, DirectoryInfo d, bool isReadOnly, bool doDeleteFiles = true)

View file

@ -277,18 +277,16 @@ namespace Roadie.Api.Services
where randomArtistIds == null || randomArtistIds.Contains(a.Id) where randomArtistIds == null || randomArtistIds.Contains(a.Id)
where request.FilterToArtistId == null || a.RoadieId == request.FilterToArtistId where request.FilterToArtistId == null || a.RoadieId == request.FilterToArtistId
where request.FilterMinimumRating == null || a.Rating >= request.FilterMinimumRating.Value where request.FilterMinimumRating == null || a.Rating >= request.FilterMinimumRating.Value
where string.IsNullOrEmpty(request.FilterValue) || where string.IsNullOrEmpty(normalizedFilterValue) ||
a.Name.Contains(request.FilterValue) || a.Name.ToLower().Contains(normalizedFilterValue) ||
a.SortName.Contains(request.FilterValue) || a.SortName.ToLower().Contains(normalizedFilterValue) ||
a.RealName.Contains(request.FilterValue) || a.RealName.ToLower().Contains(normalizedFilterValue) ||
a.AlternateNames.Contains(request.FilterValue) ||
a.AlternateNames.Contains(normalizedFilterValue) a.AlternateNames.Contains(normalizedFilterValue)
where !isEqualFilter || where !isEqualFilter ||
a.Name.Equals(request.FilterValue) || a.Name.ToLower().Equals(normalizedFilterValue) ||
a.SortName.Equals(request.FilterValue) || a.SortName.ToLower().Equals(normalizedFilterValue) ||
a.RealName.Equals(request.FilterValue) || a.RealName.ToLower().Equals(normalizedFilterValue) ||
a.AlternateNames.Equals(request.FilterValue) || a.AlternateNames.ToLower().Equals(normalizedFilterValue)
a.AlternateNames.Equals(normalizedFilterValue)
where !request.FilterFavoriteOnly || favoriteArtistIds.Contains(a.Id) where !request.FilterFavoriteOnly || favoriteArtistIds.Contains(a.Id)
where request.FilterToLabelId == null || labelArtistIds.Contains(a.Id) where request.FilterToLabelId == null || labelArtistIds.Contains(a.Id)
where !isFilteredToGenre || genreArtistIds.Contains(a.Id) where !isFilteredToGenre || genreArtistIds.Contains(a.Id)

View file

@ -193,12 +193,19 @@ namespace Roadie.Api.Services
collections = DbContext.Collections; collections = DbContext.Collections;
} }
var normalizedFilterValue = !string.IsNullOrEmpty(request.FilterValue)
? request.FilterValue.ToAlphanumericName()
: null;
var result = from c in collections var result = from c in collections
let collectionCount = (from crc in DbContext.CollectionReleases let collectionCount = (from crc in DbContext.CollectionReleases
where crc.CollectionId == c.Id where crc.CollectionId == c.Id
select crc.Id).Count() select crc.Id).Count()
where request.FilterValue.Length == 0 || where string.IsNullOrEmpty(normalizedFilterValue) || (
request.FilterValue.Length > 0 && c.Name.Contains(request.Filter) c.Name.ToLower().Contains(normalizedFilterValue) ||
c.SortName.ToLower().Contains(normalizedFilterValue) ||
c.AlternateNames.ToLower().Contains(normalizedFilterValue)
)
where request.FilterToStatusValue == Statuses.Ok || c.Status == request.FilterToStatusValue where request.FilterToStatusValue == Statuses.Ok || c.Status == request.FilterToStatusValue
select new CollectionList select new CollectionList
{ {

View file

@ -107,6 +107,10 @@ namespace Roadie.Api.Services
rowCount = DbContext.Genres.Count(); rowCount = DbContext.Genres.Count();
} }
var normalizedFilterValue = !string.IsNullOrEmpty(request.FilterValue)
? request.FilterValue.ToAlphanumericName()
: null;
var result = from g in DbContext.Genres var result = from g in DbContext.Genres
where randomGenreIds == null || randomGenreIds.Contains(g.Id) where randomGenreIds == null || randomGenreIds.Contains(g.Id)
let releaseCount = (from rg in DbContext.ReleaseGenres let releaseCount = (from rg in DbContext.ReleaseGenres
@ -115,7 +119,11 @@ namespace Roadie.Api.Services
let artistCount = (from rg in DbContext.ArtistGenres let artistCount = (from rg in DbContext.ArtistGenres
where rg.GenreId == g.Id where rg.GenreId == g.Id
select rg.Id).Count() select rg.Id).Count()
where request.FilterValue.Length == 0 || g.Name.Contains(request.FilterValue) where string.IsNullOrEmpty(normalizedFilterValue) || (
g.Name.ToLower().Contains(normalizedFilterValue) ||
g.SortName.ToLower().Contains(normalizedFilterValue) ||
g.AlternateNames.ToLower().Contains(normalizedFilterValue)
)
select new GenreList select new GenreList
{ {
DatabaseId = g.Id, DatabaseId = g.Id,

View file

@ -141,11 +141,10 @@ namespace Roadie.Api.Services
var result = from l in DbContext.Labels var result = from l in DbContext.Labels
where randomLabelIds == null || randomLabelIds.Contains(l.Id) where randomLabelIds == null || randomLabelIds.Contains(l.Id)
where request.FilterValue == "" || ( where string.IsNullOrEmpty(normalizedFilterValue) || (
l.Name.Contains(request.FilterValue) || l.Name.ToLower().Contains(normalizedFilterValue) ||
l.SortName.Contains(request.FilterValue) || l.SortName.ToLower().Contains(normalizedFilterValue) ||
l.AlternateNames.Contains(request.FilterValue) || l.AlternateNames.ToLower().Contains(normalizedFilterValue)
l.AlternateNames.Contains(normalizedFilterValue)
) )
select new LabelList select new LabelList
{ {

View file

@ -231,13 +231,19 @@ namespace Roadie.Api.Services
select pl.Id select pl.Id
).ToArray(); ).ToArray();
} }
var normalizedFilterValue = !string.IsNullOrEmpty(request.FilterValue)
? request.FilterValue.ToAlphanumericName()
: null;
var result = from pl in DbContext.Playlists var result = from pl in DbContext.Playlists
join u in DbContext.Users on pl.UserId equals u.Id join u in DbContext.Users on pl.UserId equals u.Id
where request.FilterToPlaylistId == null || pl.RoadieId == request.FilterToPlaylistId where request.FilterToPlaylistId == null || pl.RoadieId == request.FilterToPlaylistId
where request.FilterToArtistId == null || playlistWithArtistTrackIds.Contains(pl.Id) where request.FilterToArtistId == null || playlistWithArtistTrackIds.Contains(pl.Id)
where request.FilterToReleaseId == null || playlistReleaseTrackIds.Contains(pl.Id) where request.FilterToReleaseId == null || playlistReleaseTrackIds.Contains(pl.Id)
where roadieUser == null && pl.IsPublic || roadieUser != null && u.RoadieId == roadieUser.UserId || pl.IsPublic where roadieUser == null && pl.IsPublic || roadieUser != null && u.RoadieId == roadieUser.UserId || pl.IsPublic
where request.FilterValue.Length == 0 || request.FilterValue.Length > 0 && pl.Name != null && pl.Name.Contains(request.FilterValue) where string.IsNullOrEmpty(normalizedFilterValue) || (
pl.Name.ToLower().Contains(normalizedFilterValue) ||
pl.AlternateNames.ToLower().Contains(normalizedFilterValue)
)
select new PlaylistList select new PlaylistList
{ {
Playlist = new DataToken Playlist = new DataToken

View file

@ -291,41 +291,9 @@ namespace Roadie.Api.Services
select plt.PlayListId).ToListAsync().ConfigureAwait(false); select plt.PlayListId).ToListAsync().ConfigureAwait(false);
if (doDeleteFiles) if (doDeleteFiles)
{ {
foreach (var track in releaseTracks)
{
string trackPath = null;
try
{
trackPath = track.PathToTrack(Configuration);
if (File.Exists(trackPath))
{
File.Delete(trackPath);
Logger.LogWarning("For Release [{0}], Deleted File [{1}]", release.Id, trackPath);
}
}
catch (Exception ex)
{
Logger.LogError(ex, $"Error Deleting File [{trackPath}] For Track `{track}` Exception [{ex}]");
}
}
// Delete all image files for Release
foreach (var file in ImageHelper.ImageFilesInFolder(release.ReleaseFileFolder(release.Artist.ArtistFileFolder(Configuration)), SearchOption.AllDirectories))
{
try
{
File.Delete(file);
Logger.LogWarning("For Release [{0}], Deleted File [{1}]", release.Id, file);
}
catch (Exception ex)
{
Logger.LogError(ex, $"Error Deleting File [{file}] Exception [{ex}]");
}
}
try try
{ {
FolderPathHelper.DeleteEmptyFoldersForArtist(Configuration, release.Artist); Directory.Delete(release.ReleaseFileFolder(release.Artist.ArtistFileFolder(Configuration)), true);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -522,15 +490,13 @@ namespace Roadie.Api.Services
(r.ReleaseDate != null && r.ReleaseDate.Value.Year <= request.FilterFromYear) (r.ReleaseDate != null && r.ReleaseDate.Value.Year <= request.FilterFromYear)
where request.FilterToYear == null || where request.FilterToYear == null ||
(r.ReleaseDate != null && r.ReleaseDate.Value.Year >= request.FilterToYear) (r.ReleaseDate != null && r.ReleaseDate.Value.Year >= request.FilterToYear)
where string.IsNullOrEmpty(request.FilterValue) || where string.IsNullOrEmpty(normalizedFilterValue) ||
r.Title.Contains(request.FilterValue) || r.Title.ToLower().Contains(normalizedFilterValue) ||
r.AlternateNames.Contains(request.FilterValue) || r.AlternateNames.ToLower().Contains(normalizedFilterValue)
r.AlternateNames.Contains(normalizedFilterValue)
where !isEqualFilter || where !isEqualFilter ||
r.Title.Equals(request.FilterValue) || r.Title.ToLower().Equals(normalizedFilterValue) ||
r.AlternateNames.Equals(request.FilterValue) || r.AlternateNames.ToLower().Contains(normalizedFilterValue)
r.AlternateNames.Equals(normalizedFilterValue) select new ReleaseList
select new ReleaseList
{ {
DatabaseId = r.Id, DatabaseId = r.Id,
Id = r.RoadieId, Id = r.RoadieId,
@ -858,7 +824,6 @@ namespace Roadie.Api.Services
try try
{ {
var mergedFilesToDelete = new List<string>();
var mergedTracksToMove = new List<data.Track>(); var mergedTracksToMove = new List<data.Track>();
releaseToMergeInto.MediaCount ??= 0; releaseToMergeInto.MediaCount ??= 0;
@ -947,13 +912,6 @@ namespace Roadie.Api.Services
existingTrack.AlternateNames = existingTrack.AlternateNames.AddToDelimitedList(mergeTrack.AlternateNames.ToListFromDelimited()); existingTrack.AlternateNames = existingTrack.AlternateNames.AddToDelimitedList(mergeTrack.AlternateNames.ToListFromDelimited());
existingTrack.LastUpdated = now; existingTrack.LastUpdated = now;
var mergedTrackFileName = mergeTrack.PathToTrack(Configuration);
var trackFileName = existingTrack.PathToTrack(Configuration);
if (!trackFileName.Equals(mergedTrackFileName, StringComparison.Ordinal) &&
File.Exists(trackFileName))
{
mergedFilesToDelete.Add(mergedTrackFileName);
}
} }
} }
} }
@ -979,6 +937,13 @@ namespace Roadie.Api.Services
track.Hash = HashHelper.CreateMD5(releaseToMergeInto.ArtistId + trackFile.LastWriteTimeUtc.GetHashCode().ToString() + audioMetaData.GetHashCode()); track.Hash = HashHelper.CreateMD5(releaseToMergeInto.ArtistId + trackFile.LastWriteTimeUtc.GetHashCode().ToString() + audioMetaData.GetHashCode());
track.LastUpdated = now; track.LastUpdated = now;
File.Move(oldTrackPath, newTrackPath); File.Move(oldTrackPath, newTrackPath);
// If track has track image move into new folder
var trackImageFileName = track.PathToTrackThumbnail(Configuration);
if (File.Exists(trackImageFileName))
{
File.Move(trackImageFileName, newTrackPath);
}
} }
} }
} }
@ -1060,30 +1025,61 @@ namespace Roadie.Api.Services
await Delete(user, releaseToMerge).ConfigureAwait(false); await Delete(user, releaseToMerge).ConfigureAwait(false);
// Delete any files flagged to be deleted (duplicate as track already exists on merged to release) // Merge all release images
if (mergedFilesToDelete.Count > 0) var releaseCoverFiles = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releaseToMergeFolder), ImageType.Release);
if (releaseCoverFiles.Any())
{ {
foreach (var mergedFileToDelete in mergedFilesToDelete) foreach(var releaseCoverFile in releaseCoverFiles)
{ {
try var imagePath = Path.Combine(releaseToMergeIntoDirectory.FullName, releaseCoverFile.Name);
if(File.Exists(imagePath))
{ {
if (File.Exists(mergedFileToDelete)) if(ImageHelper.IsImageBetterQuality(releaseCoverFile.FullName, imagePath))
{ {
File.Delete(mergedFileToDelete); releaseCoverFile.MoveTo(imagePath, true);
Logger.LogWarning("x Deleted Merged File [{0}]", mergedFileToDelete);
} }
} }
catch else
{ {
releaseCoverFile.MoveTo(imagePath);
}
}
}
var secondaryReleaseCoverFiles = ImageHelper.FindImageTypeInDirectory(new DirectoryInfo(releaseToMergeFolder), ImageType.ReleaseSecondary);
if (secondaryReleaseCoverFiles.Any())
{
foreach (var secondaryReleaseCoverFile in secondaryReleaseCoverFiles)
{
var imagePath = Path.Combine(releaseToMergeIntoDirectory.FullName, secondaryReleaseCoverFile.Name);
if (File.Exists(imagePath))
{
if (ImageHelper.IsImageBetterQuality(secondaryReleaseCoverFile.FullName, imagePath))
{
secondaryReleaseCoverFile.MoveTo(imagePath, true);
}
}
else
{
secondaryReleaseCoverFile.MoveTo(imagePath, true);
} }
} }
} }
var releaseToMergeInfoDirectory = new DirectoryInfo(releaseToMergeFolder);
if(releaseToMergeInfoDirectory.Exists)
{
releaseToMergeInfoDirectory.Delete(true);
Logger.LogWarning("x Deleted Folder [{0}]", releaseToMergeInfoDirectory);
}
// Clear cache regions for manipulated records // Clear cache regions for manipulated records
CacheManager.ClearRegion(releaseToMergeInto.CacheRegion); CacheManager.ClearRegion(releaseToMergeInto.CacheRegion);
if (releaseToMergeInto.Artist != null) CacheManager.ClearRegion(releaseToMergeInto.Artist.CacheRegion); if (releaseToMergeInto.Artist != null) CacheManager.ClearRegion(releaseToMergeInto.Artist.CacheRegion);
if (releaseToMerge.Artist != null) CacheManager.ClearRegion(releaseToMerge.Artist.CacheRegion); if (releaseToMerge.Artist != null) CacheManager.ClearRegion(releaseToMerge.Artist.CacheRegion);
// Rescan release
await ScanReleaseFolder(user, releaseToMergeInto.RoadieId, false, releaseToMergeInto).ConfigureAwait(false);
sw.Stop(); sw.Stop();
result = true; result = true;
} }

View file

@ -9,8 +9,8 @@
<PackageReference Include="Hashids.net" Version="1.3.0" /> <PackageReference Include="Hashids.net" Version="1.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.1.4" /> <PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.1.4" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.5.1" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.6.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.1.1" /> <PackageReference Include="System.Linq.Dynamic.Core" Version="1.1.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -93,9 +93,8 @@ namespace Roadie.Api.Services
} }
var artistByName = await CacheManager.GetAsync(data.Artist.CacheUrnByName(artistName), async () => var artistByName = await CacheManager.GetAsync(data.Artist.CacheUrnByName(artistName), async () =>
{ {
return await DbContext.Artists return await DbContext.Artists.FirstOrDefaultAsync(x => x.Name == artistName).ConfigureAwait(false);
.FirstOrDefaultAsync(x => x.Name == artistName); }, null).ConfigureAwait(false);
}, null);
if (artistByName == null) if (artistByName == null)
{ {
return null; return null;
@ -103,83 +102,80 @@ namespace Roadie.Api.Services
return await GetArtist(artistByName.RoadieId); return await GetArtist(artistByName.RoadieId);
} }
protected async Task<data.Artist> GetArtist(Guid id) protected Task<data.Artist> GetArtist(Guid id)
{ {
if (id == Guid.Empty) if (id == Guid.Empty)
{ {
return null; return Task.FromResult<data.Artist>(null);
} }
return await CacheManager.GetAsync(data.Artist.CacheUrn(id), async () => return CacheManager.GetAsync(data.Artist.CacheUrn(id), () =>
{ {
return await DbContext.Artists return DbContext.Artists
.Include(x => x.Genres) .Include(x => x.Genres)
.Include("Genres.Genre") .Include("Genres.Genre")
.FirstOrDefaultAsync(x => x.RoadieId == id); .FirstOrDefaultAsync(x => x.RoadieId == id);
}, data.Artist.CacheRegionUrn(id)); }, data.Artist.CacheRegionUrn(id));
} }
protected async Task<data.Collection> GetCollection(Guid id) protected Task<data.Collection> GetCollection(Guid id)
{ {
if (id == Guid.Empty) if (id == Guid.Empty)
{ {
return null; return Task.FromResult<data.Collection>(null);
} }
return await CacheManager.GetAsync(data.Collection.CacheUrn(id), async () => return CacheManager.GetAsync(data.Collection.CacheUrn(id), () =>
{ {
return await DbContext.Collections return DbContext.Collections.FirstOrDefaultAsync(x => x.RoadieId == id);
.FirstOrDefaultAsync(x => x.RoadieId == id);
}, data.Collection.CacheRegionUrn(id)); }, data.Collection.CacheRegionUrn(id));
} }
protected async Task<data.Genre> GetGenre(Guid id) protected Task<data.Genre> GetGenre(Guid id)
{ {
if (id == Guid.Empty) if (id == Guid.Empty)
{ {
return null; return Task.FromResult<data.Genre>(null);
} }
return await CacheManager.GetAsync(data.Genre.CacheUrn(id), async () => return CacheManager.GetAsync(data.Genre.CacheUrn(id), () =>
{ {
return await DbContext.Genres return DbContext.Genres.FirstOrDefaultAsync(x => x.RoadieId == id);
.FirstOrDefaultAsync(x => x.RoadieId == id);
}, data.Genre.CacheRegionUrn(id)); }, data.Genre.CacheRegionUrn(id));
} }
protected async Task<data.Label> GetLabel(Guid id) protected Task<data.Label> GetLabel(Guid id)
{ {
if (id == Guid.Empty) if (id == Guid.Empty)
{ {
return null; return Task.FromResult<data.Label>(null);
} }
return await CacheManager.GetAsync(data.Label.CacheUrn(id), async () => return CacheManager.GetAsync(data.Label.CacheUrn(id), () =>
{ {
return await DbContext.Labels return DbContext.Labels.FirstOrDefaultAsync(x => x.RoadieId == id);
.FirstOrDefaultAsync(x => x.RoadieId == id);
}, data.Label.CacheRegionUrn(id)); }, data.Label.CacheRegionUrn(id));
} }
protected async Task<data.Playlist> GetPlaylist(Guid id) protected Task<data.Playlist> GetPlaylist(Guid id)
{ {
if (id == Guid.Empty) if (id == Guid.Empty)
{ {
return null; return Task.FromResult<data.Playlist>(null);
} }
return await CacheManager.Get(data.Playlist.CacheUrn(id), async () => return CacheManager.GetAsync(data.Playlist.CacheUrn(id), () =>
{ {
return await DbContext.Playlists return DbContext.Playlists
.Include(x => x.User) .Include(x => x.User)
.FirstOrDefaultAsync(x => x.RoadieId == id); .FirstOrDefaultAsync(x => x.RoadieId == id);
}, data.Playlist.CacheRegionUrn(id)); }, data.Playlist.CacheRegionUrn(id));
} }
protected async Task<data.Release> GetRelease(Guid id) protected Task<data.Release> GetRelease(Guid id)
{ {
if (id == Guid.Empty) if (id == Guid.Empty)
{ {
return null; return Task.FromResult<data.Release>(null);
} }
return await CacheManager.Get(data.Release.CacheUrn(id), async () => return CacheManager.GetAsync(data.Release.CacheUrn(id), () =>
{ {
return await DbContext.Releases return DbContext.Releases
.Include(x => x.Artist) .Include(x => x.Artist)
.Include(x => x.Genres) .Include(x => x.Genres)
.Include("Genres.Genre") .Include("Genres.Genre")
@ -203,15 +199,15 @@ namespace Roadie.Api.Services
} }
// Only read operations // Only read operations
protected async Task<data.Track> GetTrack(Guid id) protected Task<data.Track> GetTrack(Guid id)
{ {
if(id == Guid.Empty) if(id == Guid.Empty)
{ {
return null; return Task.FromResult<data.Track>(null);
} }
return await CacheManager.GetAsync(data.Track.CacheUrn(id), async () => return CacheManager.GetAsync(data.Track.CacheUrn(id), () =>
{ {
return await DbContext.Tracks return DbContext.Tracks
.Include(x => x.ReleaseMedia) .Include(x => x.ReleaseMedia)
.Include(x => x.ReleaseMedia.Release) .Include(x => x.ReleaseMedia.Release)
.Include(x => x.ReleaseMedia.Release.Artist) .Include(x => x.ReleaseMedia.Release.Artist)
@ -226,19 +222,22 @@ namespace Roadie.Api.Services
{ {
return null; return null;
} }
var userByUsername = await CacheManager.GetAsync(User.CacheUrnByUsername(username), async () => var userByUsername = await CacheManager.GetAsync(User.CacheUrnByUsername(username), () =>
{ {
return await DbContext.Users.FirstOrDefaultAsync(x => x.UserName == username); return DbContext.Users.FirstOrDefaultAsync(x => x.UserName == username);
}, null); }, null);
return await GetUser(userByUsername?.RoadieId); return await GetUser(userByUsername?.RoadieId).ConfigureAwait(false);
} }
protected async Task<User> GetUser(Guid? id) protected Task<User> GetUser(Guid? id)
{ {
if (!id.HasValue) return null; if (!id.HasValue)
return await CacheManager.GetAsync(User.CacheUrn(id.Value), async () => {
return Task.FromResult<User>(null);
}
return CacheManager.GetAsync(User.CacheUrn(id.Value), () =>
{ {
return await DbContext.Users return DbContext.Users
.Include(x => x.UserRoles) .Include(x => x.UserRoles)
.Include("UserRoles.Role") .Include("UserRoles.Role")
.Include("UserRoles.Role.RoleClaims") .Include("UserRoles.Role.RoleClaims")
@ -276,9 +275,9 @@ namespace Roadie.Api.Services
userArtist.LastUpdated = now; userArtist.LastUpdated = now;
} }
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync().ConfigureAwait(false);
var ratings = await DbContext.UserArtists.Where(x => x.ArtistId == artist.Id && x.Rating > 0).Select(x => x.Rating).ToListAsync(); var ratings = await DbContext.UserArtists.Where(x => x.ArtistId == artist.Id && x.Rating > 0).Select(x => x.Rating).ToListAsync().ConfigureAwait(false);
if (ratings != null && ratings.Any()) if (ratings != null && ratings.Any())
{ {
artist.Rating = (short)ratings.Average(x => (decimal)x); artist.Rating = (short)ratings.Average(x => (decimal)x);
@ -288,12 +287,12 @@ namespace Roadie.Api.Services
artist.Rating = 0; artist.Rating = 0;
} }
artist.LastUpdated = now; artist.LastUpdated = now;
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync().ConfigureAwait(false);
await UpdateArtistRank(artist.Id); await UpdateArtistRank(artist.Id);
CacheManager.ClearRegion(user.CacheRegion); CacheManager.ClearRegion(user.CacheRegion);
CacheManager.ClearRegion(artist.CacheRegion); CacheManager.ClearRegion(artist.CacheRegion);
artist = await GetArtist(artistId); artist = await GetArtist(artistId).ConfigureAwait(false);
return new OperationResult<short> return new OperationResult<short>
{ {
@ -947,7 +946,7 @@ namespace Roadie.Api.Services
join t in DbContext.Tracks on ut.TrackId equals t.Id join t in DbContext.Tracks on ut.TrackId equals t.Id
join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
where rm.ReleaseId == releaseId where rm.ReleaseId == releaseId
select ut.Rating).Select(x => (decimal?)x).ToArrayAsync()).Average(); select ut.Rating).Select(x => (decimal?)x).ToArrayAsync().ConfigureAwait(false)).Average();
var releaseUserRatingRank = release.Rating > 0 ? release.Rating / (decimal?)release.TrackCount : 0; var releaseUserRatingRank = release.Rating > 0 ? release.Rating / (decimal?)release.TrackCount : 0;
@ -970,12 +969,12 @@ namespace Roadie.Api.Services
release.Rank = SafeParser.ToNumber<decimal>(releaseTrackAverage) + releaseUserRatingRank + releaseCollectionRank; release.Rank = SafeParser.ToNumber<decimal>(releaseTrackAverage) + releaseUserRatingRank + releaseCollectionRank;
await DbContext.SaveChangesAsync(); await DbContext.SaveChangesAsync().ConfigureAwait(false);
CacheManager.ClearRegion(release.CacheRegion); CacheManager.ClearRegion(release.CacheRegion);
Logger.LogTrace("UpdateReleaseRank For Release `{0}`", release); Logger.LogTrace("UpdateReleaseRank For Release `{0}`", release);
if (updateArtistRank) if (updateArtistRank)
{ {
await UpdateArtistsRankForRelease(release); await UpdateArtistsRankForRelease(release).ConfigureAwait(false);
} }
} }
} }

View file

@ -341,8 +341,15 @@ namespace Roadie.Api.Services
where filterToTrackIds == null || filterToTrackIds.Contains(t.RoadieId) where filterToTrackIds == null || filterToTrackIds.Contains(t.RoadieId)
where releaseId == null || r.RoadieId == releaseId where releaseId == null || r.RoadieId == releaseId
where request.FilterMinimumRating == null || t.Rating >= request.FilterMinimumRating.Value where request.FilterMinimumRating == null || t.Rating >= request.FilterMinimumRating.Value
where string.IsNullOrEmpty(request.FilterValue) || (trackArtist != null && trackArtist.Name.Contains(request.FilterValue)) || t.Title.Contains(request.FilterValue) || t.AlternateNames.Contains(request.FilterValue) || t.AlternateNames.Contains(normalizedFilterValue) || t.PartTitles.Contains(request.FilterValue) where string.IsNullOrEmpty(normalizedFilterValue) ||
where !isEqualFilter || t.Title.Equals(request.FilterValue) || t.AlternateNames.Equals(request.FilterValue) || t.AlternateNames.Equals(normalizedFilterValue) || t.PartTitles.Equals(request.FilterValue) (trackArtist != null && trackArtist.Name.ToLower().Contains(normalizedFilterValue)) ||
t.Title.ToLower().Contains(normalizedFilterValue) ||
t.AlternateNames.Contains(normalizedFilterValue) ||
t.PartTitles.ToLower().Contains(normalizedFilterValue)
where !isEqualFilter ||
t.Title.ToLower().Equals(normalizedFilterValue) ||
t.AlternateNames.ToLower().Equals(normalizedFilterValue) ||
t.PartTitles.ToLower().Equals(request.FilterValue)
where !request.FilterFavoriteOnly || favoriteTrackIds.Contains(t.Id) where !request.FilterFavoriteOnly || favoriteTrackIds.Contains(t.Id)
where request.FilterToPlaylistId == null || playlistTrackIds.Contains(t.Id) where request.FilterToPlaylistId == null || playlistTrackIds.Contains(t.Id)
where !request.FilterTopPlayedOnly || topTrackids.Contains(t.Id) where !request.FilterTopPlayedOnly || topTrackids.Contains(t.Id)

View file

@ -212,7 +212,7 @@ namespace Roadie.Api.Controllers
[ProducesResponseType(200)] [ProducesResponseType(200)]
public async Task<IActionResult> ScanAllCollections() public async Task<IActionResult> ScanAllCollections()
{ {
var result = await AdminService.ScanAllCollections(await UserManager.GetUserAsync(User)); var result = await AdminService.ScanAllCollections(await UserManager.GetUserAsync(User).ConfigureAwait(false)).ConfigureAwait(false);
if (!result.IsSuccess) if (!result.IsSuccess)
{ {
if (result.Messages?.Any() ?? false) if (result.Messages?.Any() ?? false)
@ -260,7 +260,7 @@ namespace Roadie.Api.Controllers
[ProducesResponseType(200)] [ProducesResponseType(200)]
public async Task<IActionResult> ScanCollection(Guid id, bool doPurgeFirst = false) public async Task<IActionResult> ScanCollection(Guid id, bool doPurgeFirst = false)
{ {
var result = await AdminService.ScanCollection(await UserManager.GetUserAsync(User), id, doPurgeFirst: doPurgeFirst); var result = await AdminService.ScanCollection(await UserManager.GetUserAsync(User).ConfigureAwait(false), id, doPurgeFirst: doPurgeFirst).ConfigureAwait(false);
if (!result.IsSuccess) if (!result.IsSuccess)
{ {
if (result.Messages?.Any() ?? false) if (result.Messages?.Any() ?? false)

View file

@ -29,7 +29,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="BCrypt-Core" Version="2.0.0" /> <PackageReference Include="BCrypt-Core" Version="2.0.0" />
<PackageReference Include="Mapster" Version="5.3.1" /> <PackageReference Include="Mapster" Version="5.3.2" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.14.0" /> <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.14.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.4" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.4" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.4" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.4" />
@ -43,13 +43,13 @@
<PackageReference Include="Serilog.AspNetCore" Version="3.2.0" /> <PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.1.3" /> <PackageReference Include="Serilog.Enrichers.Environment" Version="2.1.3" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" /> <PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
<PackageReference Include="Serilog.Exceptions" Version="5.4.0" /> <PackageReference Include="Serilog.Exceptions" Version="5.5.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" /> <PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" /> <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.LiteDB.NetStandard" Version="1.0.14" /> <PackageReference Include="Serilog.Sinks.LiteDB.NetStandard" Version="1.0.14" />
<PackageReference Include="Serilog.Sinks.RollingFileAlternate" Version="2.0.9" /> <PackageReference Include="Serilog.Sinks.RollingFileAlternate" Version="2.0.9" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.5.1" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.6.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.1.1" /> <PackageReference Include="System.Linq.Dynamic.Core" Version="1.1.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>