This commit is contained in:
Steven Hildreth 2019-07-31 17:42:49 -05:00
parent 45c9a1c97a
commit 36459efa38
14 changed files with 205 additions and 163 deletions

View file

@ -0,0 +1,82 @@
using Roadie.Library.Utility;
using System;
using Xunit;
namespace Roadie.Library.Tests
{
public class HashHelperTests
{
[Fact]
public void MD5HandleNullString()
{
string s = null;
Assert.Null(HashHelper.CreateMD5(s));
}
[Fact]
public void MD5HandleNullArray()
{
byte[] b = null;
Assert.Null(HashHelper.CreateMD5(b));
}
[Fact]
public void CreateAndCompareMd5BlankString()
{
var s = "";
var md51 = HashHelper.CreateMD5(s);
var md52 = HashHelper.CreateMD5(s);
Assert.Equal(md51, md52);
}
[Fact]
public void CreateAndCompareMd5String()
{
var s = "This is a test";
var md51 = HashHelper.CreateMD5(s);
var md52 = HashHelper.CreateMD5(s);
Assert.Equal(md51, md52);
}
[Fact]
public void CreateAndCompareMd5Bytes()
{
var sb = System.Text.Encoding.UTF8.GetBytes("This is a test");
var md51 = HashHelper.CreateMD5(sb);
var md52 = HashHelper.CreateMD5(sb);
Assert.Equal(md51, md52);
}
[Fact]
public void CreateAndCompareMd5BytesToString()
{
var s = "This is a test";
var sb = System.Text.Encoding.UTF8.GetBytes("This is a test");
var md51 = HashHelper.CreateMD5(sb);
var md52 = HashHelper.CreateMD5(s);
Assert.Equal(md51, md52);
}
[Fact]
public void CreateAndCompareMd5LongString()
{
var s = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
var md51 = HashHelper.CreateMD5(s);
var md52 = HashHelper.CreateMD5(s);
Assert.Equal(md51, md52);
Assert.Equal("01aad0e51fcd5582b307613842e4ffe5", md51.ToLower());
}
[Fact]
public void CreateAndEnsureStandardMd5()
{
var s = "This is a test";
var md5 = HashHelper.CreateMD5(s);
// From https://www.md5hashgenerator.com/
// From http://onlinemd5.com/
// From https://md5.online/
Assert.Equal("ce114e4501d2f4e2dcea3e17b546f339", md5.ToLower());
}
}
}

View file

@ -16,13 +16,7 @@ namespace Roadie.Library.Data
{
get
{
using (var md5 = MD5.Create())
{
return string.Concat(md5
.ComputeHash(
System.Text.Encoding.Default.GetBytes(string.Format("{0}{1}", RoadieId, LastUpdated)))
.Select(x => x.ToString("D2")));
}
return HashHelper.CreateMD5($"{ RoadieId }{ LastUpdated }");
}
}

View file

@ -1,5 +1,6 @@
using Roadie.Library.Configuration;
using Roadie.Library.Extensions;
using Roadie.Library.Utility;
using System;
using System.Diagnostics;
using System.IO;
@ -18,13 +19,7 @@ namespace Roadie.Library.Data
{
get
{
using (var md5 = MD5.Create())
{
return string.Concat(md5
.ComputeHash(
System.Text.Encoding.Default.GetBytes(string.Format("{0}{1}", RoadieId, LastUpdated)))
.Select(x => x.ToString("D2")));
}
return HashHelper.CreateMD5($"{ RoadieId }{ LastUpdated }");
}
}

View file

@ -17,13 +17,7 @@ namespace Roadie.Library.Data
{
get
{
using (var md5 = MD5.Create())
{
return string.Concat(md5
.ComputeHash(
System.Text.Encoding.Default.GetBytes(string.Format("{0}{1}", RoadieId, LastUpdated)))
.Select(x => x.ToString("D2")));
}
return HashHelper.CreateMD5($"{ RoadieId }{ LastUpdated }");
}
}

View file

@ -19,17 +19,23 @@ namespace Roadie.Library.Data
{
get
{
using (var md5 = MD5.Create())
{
return string.Concat(md5
.ComputeHash(
System.Text.Encoding.Default.GetBytes(string.Format("{0}{1}", RoadieId, LastUpdated)))
.Select(x => x.ToString("D2")));
}
return HashHelper.CreateMD5($"{ RoadieId}{ LastUpdated}");
}
}
public bool IsValid => !string.IsNullOrEmpty(Hash);
/// <summary>
/// Are the track details valid so the track can play.
/// </summary>
public bool IsValid
{
get
{
return !string.IsNullOrEmpty(Hash) &&
!string.IsNullOrEmpty(FileName) &&
FileSize.HasValue &&
!string.IsNullOrEmpty(FilePath);
}
}
public Artist TrackArtist { get; set; }

View file

@ -1,23 +0,0 @@
namespace Roadie.Library.Extensions
{
public static class ByteExt
{
//public static int ComputeHash(this byte[] data)
//{
// if (data == null || data.Length == 0) return 0;
// unchecked
// {
// const int p = 16777619;
// var hash = (int)2166136261;
// for (var i = 0; i < data.Length; i++) hash = (hash ^ data[i]) * p;
// hash += hash << 13;
// hash ^= hash >> 7;
// hash += hash << 3;
// hash ^= hash >> 17;
// hash += hash << 5;
// return hash;
// }
//}
}
}

View file

@ -68,21 +68,6 @@ namespace Roadie.Library.MetaData.LastFm
SelectSingleNode(navigator, LastFmErrorXPath)), webException);
}
// http://msdn.microsoft.com/en-us/library/system.security.cryptography.md5.aspx
// Hash an input string and return the hash as
// a 32 character hexadecimal string.
public static string Hash(string input)
{
// Create a new instance of the MD5CryptoServiceProvider object.
using (var md5Hasher = MD5.Create())
{
var data = md5Hasher.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input));
var sb = new StringBuilder();
foreach (var b in data) sb.Append(b.ToString("X2"));
return sb.ToString();
}
}
public static XPathNavigator SelectSingleNode(XPathNavigator navigator, string xpath)
{
var node = navigator.SelectSingleNode(xpath);
@ -474,8 +459,7 @@ namespace Roadie.Library.MetaData.LastFm
return builder.ToString();
}
private string GenerateMethodSignature(string method, IDictionary<string, string> parameters = null,
string sk = null)
private string GenerateMethodSignature(string method, IDictionary<string, string> parameters = null, string sk = null)
{
if (parameters == null) parameters = new Dictionary<string, string>();
if (!parameters.ContainsKey("method")) parameters.Add("method", method);
@ -483,9 +467,11 @@ namespace Roadie.Library.MetaData.LastFm
if (!string.IsNullOrEmpty(sk) && !parameters.ContainsKey("sk")) parameters.Add("sk", sk);
var builder = new StringBuilder();
foreach (var kv in parameters.OrderBy(kv => kv.Key, StringComparer.Ordinal))
{
builder.Append($"{kv.Key}{kv.Value}");
}
builder.Append(_apiKey.KeySecret);
return Hash(builder.ToString());
return HashHelper.CreateMD5(builder.ToString());
}
}
}

View file

@ -118,7 +118,10 @@ namespace Roadie.Library.Utility
/// <param name="destinationFolder">Optional Root folder defaults to Library Folder from Settings</param>
public static string PathForTrack(IRoadieSettings configuration, Track track)
{
if (string.IsNullOrEmpty(track.FilePath) || string.IsNullOrEmpty(track.FileName)) return null;
if (string.IsNullOrEmpty(track.FilePath) || string.IsNullOrEmpty(track.FileName))
{
return null;
}
var directoryInfo = new DirectoryInfo(Path.Combine(configuration.LibraryFolder, track.FilePath, track.FileName));
return directoryInfo.FullName;
}

View file

@ -8,27 +8,34 @@ namespace Roadie.Library.Utility
{
public static string CreateMD5(string input)
{
if (string.IsNullOrEmpty(input)) return null;
return CreateMD5(System.Text.Encoding.ASCII.GetBytes(input));
if (string.IsNullOrEmpty(input))
{
return null;
}
return CreateMD5(System.Text.Encoding.UTF8.GetBytes(input));
}
public static string CreateMD5(byte[] bytes)
{
if (bytes == null || !bytes.Any()) return null;
if (bytes == null || !bytes.Any())
{
return null;
}
using (var md5 = MD5.Create())
{
return System.Text.Encoding.ASCII.GetString(md5.ComputeHash(bytes));
byte[] data = md5.ComputeHash(bytes);
// Create a new Stringbuilder to collect the bytes and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
}
public static string MD5Hash(string input)
{
var hash = new StringBuilder();
var md5provider = new MD5CryptoServiceProvider();
var bytes = md5provider.ComputeHash(new UTF8Encoding().GetBytes(input));
for (var i = 0; i < bytes.Length; i++) hash.Append(bytes[i].ToString("x2"));
return hash.ToString();
}
}
}

View file

@ -934,8 +934,7 @@ namespace Roadie.Api.Services
return await ScanFolder(user, d, dest, isReadOnly);
}
public async Task<OperationResult<bool>> ScanRelease(ApplicationUser user, Guid releaseId,
bool isReadOnly = false, bool wasDoneForInvalidTrackPlay = false)
public async Task<OperationResult<bool>> ScanRelease(ApplicationUser user, Guid releaseId, bool isReadOnly = false, bool wasDoneForInvalidTrackPlay = false)
{
var sw = new Stopwatch();
sw.Start();
@ -954,8 +953,6 @@ namespace Roadie.Api.Services
try
{
var result = await ReleaseService.ScanReleaseFolder(user, release.RoadieId, isReadOnly, release);
await UpdateReleaseRank(release.Id);
CacheManager.ClearRegion(release.CacheRegion);
}
catch (Exception ex)
{

View file

@ -13,8 +13,7 @@ namespace Roadie.Api.Services
Task<OperationResult<bool>> DeleteArtist(ApplicationUser user, Guid artistId);
Task<OperationResult<bool>> DeleteArtistReleases(ApplicationUser user, Guid artistId,
bool doDeleteFiles = false);
Task<OperationResult<bool>> DeleteArtistReleases(ApplicationUser user, Guid artistId, bool doDeleteFiles = false);
Task<OperationResult<bool>> DeleteArtistSecondaryImage(ApplicationUser user, Guid artistId, int index);
@ -32,22 +31,19 @@ namespace Roadie.Api.Services
Task<OperationResult<Dictionary<string, List<string>>>> MissingCollectionReleases(ApplicationUser user);
Task<OperationResult<bool>> ScanAllCollections(ApplicationUser user, bool isReadOnly = false,
bool doPurgeFirst = false);
Task<OperationResult<bool>> ScanAllCollections(ApplicationUser user, bool isReadOnly = false, bool doPurgeFirst = false);
Task<OperationResult<bool>> ScanArtist(ApplicationUser user, Guid artistId, bool isReadOnly = false);
Task<OperationResult<bool>> ScanArtists(ApplicationUser user, IEnumerable<Guid> artistIds, bool isReadOnly = false);
Task<OperationResult<bool>> ScanCollection(ApplicationUser user, Guid collectionId, bool isReadOnly = false,
bool doPurgeFirst = false, bool doUpdateRanks = true);
Task<OperationResult<bool>> ScanCollection(ApplicationUser user, Guid collectionId, bool isReadOnly = false, bool doPurgeFirst = false, bool doUpdateRanks = true);
Task<OperationResult<bool>> ScanInboundFolder(ApplicationUser user, bool isReadOnly = false);
Task<OperationResult<bool>> ScanLibraryFolder(ApplicationUser user, bool isReadOnly = false);
Task<OperationResult<bool>> ScanRelease(ApplicationUser user, Guid releaseId, bool isReadOnly = false,
bool wasDoneForInvalidTrackPlay = false);
Task<OperationResult<bool>> ScanRelease(ApplicationUser user, Guid releaseId, bool isReadOnly = false, bool wasDoneForInvalidTrackPlay = false);
Task<OperationResult<bool>> ValidateInviteToken(Guid? tokenId);

View file

@ -983,8 +983,7 @@ namespace Roadie.Api.Services
/// </summary>
public async Task<OperationResult<bool>> ScanReleaseFolder(ApplicationUser user, Guid releaseId, bool doJustInfo, data.Release releaseToScan = null)
{
SimpleContract.Requires<ArgumentOutOfRangeException>(
releaseId != Guid.Empty && releaseToScan == null || releaseToScan != null, "Invalid ReleaseId");
SimpleContract.Requires<ArgumentOutOfRangeException>(releaseId != Guid.Empty && releaseToScan == null || releaseToScan != null, "Invalid ReleaseId");
_addedTrackIds.Clear();
@ -1012,8 +1011,9 @@ namespace Roadie.Api.Services
releasePath = release.ReleaseFileFolder(release.Artist.ArtistFileFolder(Configuration));
var releaseDirectory = new DirectoryInfo(releasePath);
if (!Directory.Exists(releasePath))
Logger.LogWarning("Unable To Find Release Folder [{0}] For Release `{1}`", releasePath,
release.ToString());
{
Logger.LogWarning("Unable To Find Release Folder [{0}] For Release `{1}`", releasePath, release.ToString());
}
var now = DateTime.UtcNow;
#region Get Tracks for Release from DB and set as missing any not found in Folder
@ -1021,15 +1021,13 @@ namespace Roadie.Api.Services
foreach (var releaseMedia in DbContext.ReleaseMedias.Where(x => x.ReleaseId == release.Id).ToArray())
{
var foundMissingTracks = false;
foreach (var existingTrack in DbContext.Tracks.Where(x => x.ReleaseMediaId == releaseMedia.Id)
.ToArray())
foreach (var existingTrack in DbContext.Tracks.Where(x => x.ReleaseMediaId == releaseMedia.Id).ToArray())
{
var trackPath = existingTrack.PathToTrack(Configuration);
if (!File.Exists(trackPath))
{
Logger.LogWarning("Track `{0}`, File [{1}] Not Found.", existingTrack.ToString(),
trackPath);
Logger.LogWarning("Track `{0}`, File [{1}] Not Found.", existingTrack.ToString(), trackPath);
if (!doJustInfo)
{
existingTrack.UpdateTrackMissingFile(now);
@ -1040,21 +1038,24 @@ namespace Roadie.Api.Services
}
}
if (foundMissingTracks) await DbContext.SaveChangesAsync();
if (foundMissingTracks)
{
await DbContext.SaveChangesAsync();
}
}
#endregion Get Tracks for Release from DB and set as missing any not found in Folder
#region Scan Folder and Add or Update Existing Tracks from Files
var existingReleaseMedia = DbContext.ReleaseMedias.Include(x => x.Tracks)
.Where(x => x.ReleaseId == release.Id).ToList();
var existingReleaseMedia = DbContext.ReleaseMedias.Include(x => x.Tracks).Where(x => x.ReleaseId == release.Id).ToList();
var foundInFolderTracks = new List<data.Track>();
short totalNumberOfTracksFound = 0;
// This is the number of tracks metadata says the release should have (releaseMediaNumber, TotalNumberOfTracks)
var releaseMediaTotalNumberOfTracks = new Dictionary<short, short?>();
var releaseMediaTracksFound = new Dictionary<int, short>();
if (Directory.Exists(releasePath))
{
foreach (var file in releaseDirectory.GetFiles("*.mp3", SearchOption.AllDirectories))
{
int? trackArtistId = null;
@ -1065,21 +1066,19 @@ namespace Roadie.Api.Services
if (audioMetaData.IsValid)
{
var trackHash = HashHelper.CreateMD5(
release.ArtistId + file.LastWriteTimeUtc.GetHashCode().ToString() +
audioMetaData.GetHashCode());
var trackHash = HashHelper.CreateMD5(release.ArtistId + file.LastWriteTimeUtc.GetHashCode().ToString() + audioMetaData.GetHashCode());
totalNumberOfTracksFound++;
totalTrackCount = totalTrackCount ?? (short)(audioMetaData.TotalTrackNumbers ?? 0);
var releaseMediaNumber = (short)(audioMetaData.Disc ?? 1);
if (!releaseMediaTotalNumberOfTracks.ContainsKey(releaseMediaNumber))
releaseMediaTotalNumberOfTracks.Add(releaseMediaNumber,
(short)(audioMetaData.TotalTrackNumbers ?? 0));
{
releaseMediaTotalNumberOfTracks.Add(releaseMediaNumber, (short)(audioMetaData.TotalTrackNumbers ?? 0));
}
else
releaseMediaTotalNumberOfTracks[releaseMediaNumber] =
releaseMediaTotalNumberOfTracks[releaseMediaNumber]
.TakeLarger((short)(audioMetaData.TotalTrackNumbers ?? 0));
var releaseMedia =
existingReleaseMedia.FirstOrDefault(x => x.MediaNumber == releaseMediaNumber);
{
releaseMediaTotalNumberOfTracks[releaseMediaNumber] = releaseMediaTotalNumberOfTracks[releaseMediaNumber].TakeLarger((short)(audioMetaData.TotalTrackNumbers ?? 0));
}
var releaseMedia = existingReleaseMedia.FirstOrDefault(x => x.MediaNumber == releaseMediaNumber);
if (releaseMedia == null)
{
// New ReleaseMedia - Not Found In Database
@ -1100,8 +1099,7 @@ namespace Roadie.Api.Services
releaseMedia.LastUpdated = now;
}
var track = releaseMedia.Tracks.FirstOrDefault(x =>
x.TrackNumber == audioMetaData.TrackNumber);
var track = releaseMedia.Tracks.FirstOrDefault(x => x.TrackNumber == audioMetaData.TrackNumber);
if (track == null)
{
// New Track - Not Found In Database
@ -1129,16 +1127,15 @@ namespace Roadie.Api.Services
{
if (audioMetaData.TrackArtists.Count() == 1)
{
var trackArtistData =
await ArtistLookupEngine.GetByName(
new AudioMetaData { Artist = audioMetaData.TrackArtist }, true);
var trackArtistData = await ArtistLookupEngine.GetByName(new AudioMetaData { Artist = audioMetaData.TrackArtist }, true);
if (trackArtistData.IsSuccess && release.ArtistId != trackArtistData.Data.Id)
{
trackArtistId = trackArtistData.Data.Id;
}
}
else if (audioMetaData.TrackArtists.Any())
{
partTitles = string.Join(AudioMetaData.ArtistSplitCharacter.ToString(),
audioMetaData.TrackArtists);
partTitles = string.Join(AudioMetaData.ArtistSplitCharacter.ToString(), audioMetaData.TrackArtists);
}
else
{
@ -1147,8 +1144,7 @@ namespace Roadie.Api.Services
}
var alt = track.Title.ToAlphanumericName();
track.AlternateNames =
!alt.Equals(audioMetaData.Title, StringComparison.OrdinalIgnoreCase)
track.AlternateNames = !alt.Equals(audioMetaData.Title, StringComparison.OrdinalIgnoreCase)
? track.AlternateNames.AddToDelimitedList(new[] { alt })
: null;
track.ArtistId = trackArtistId;
@ -1164,16 +1160,15 @@ namespace Roadie.Api.Services
{
if (audioMetaData.TrackArtists.Count() == 1)
{
var trackArtistData =
await ArtistLookupEngine.GetByName(
new AudioMetaData { Artist = audioMetaData.TrackArtist }, true);
var trackArtistData = await ArtistLookupEngine.GetByName( new AudioMetaData { Artist = audioMetaData.TrackArtist }, true);
if (trackArtistData.IsSuccess && release.ArtistId != trackArtistData.Data.Id)
{
trackArtistId = trackArtistData.Data.Id;
}
}
else if (audioMetaData.TrackArtists.Any())
{
partTitles = string.Join(AudioMetaData.ArtistSplitCharacter.ToString(),
audioMetaData.TrackArtists);
partTitles = string.Join(AudioMetaData.ArtistSplitCharacter.ToString(), audioMetaData.TrackArtists);
}
else
{
@ -1196,7 +1191,9 @@ namespace Roadie.Api.Services
track.LastUpdated = now;
var alt = track.Title.ToAlphanumericName();
if (!alt.Equals(track.Title, StringComparison.OrdinalIgnoreCase))
{
track.AlternateNames = track.AlternateNames.AddToDelimitedList(new[] { alt });
}
track.TrackNumber = audioMetaData.TrackNumber ?? -1;
track.LastUpdated = now;
modifiedRelease = true;
@ -1210,20 +1207,24 @@ namespace Roadie.Api.Services
foundInFolderTracks.Add(track);
if (releaseMediaTracksFound.ContainsKey(releaseMedia.Id))
{
releaseMediaTracksFound[releaseMedia.Id]++;
}
else
{
releaseMediaTracksFound[releaseMedia.Id] = 1;
}
}
else
{
Logger.LogWarning("Release Track File Has Invalid MetaData `{0}`",
audioMetaData.ToString());
Logger.LogWarning("Release Track File Has Invalid MetaData `{0}`", audioMetaData.ToString());
}
}
}
else
Logger.LogWarning("Unable To Find Releaes Path [{0}] For Release `{1}`", releasePath,
release.ToString());
{
Logger.LogWarning("Unable To Find Releaes Path [{0}] For Release `{1}`", releasePath, release.ToString());
}
var releaseMediaNumbersFound = new List<short?>();
foreach (var kp in releaseMediaTracksFound)
{
@ -1231,38 +1232,38 @@ namespace Roadie.Api.Services
if (releaseMedia != null)
{
if (!releaseMediaNumbersFound.Any(x => x == releaseMedia.MediaNumber))
{
releaseMediaNumbersFound.Add(releaseMedia.MediaNumber);
}
var releaseMediaFoundInFolderTrackNumbers = foundInFolderTracks
.Where(x => x.ReleaseMediaId == releaseMedia.Id).Select(x => x.TrackNumber).OrderBy(x => x)
.ToArray();
var areTracksForRelaseMediaSequential = releaseMediaFoundInFolderTrackNumbers
.Zip(releaseMediaFoundInFolderTrackNumbers.Skip(1), (a, b) => a + 1 == b).All(x => x);
var areTracksForRelaseMediaSequential = releaseMediaFoundInFolderTrackNumbers.Zip(releaseMediaFoundInFolderTrackNumbers.Skip(1), (a, b) => a + 1 == b).All(x => x);
if (!areTracksForRelaseMediaSequential)
{
Logger.LogDebug("ReleaseMedia [{0}] Track Numbers Are Not Sequential", releaseMedia.Id);
}
releaseMedia.TrackCount = kp.Value;
releaseMedia.LastUpdated = now;
releaseMedia.Status = areTracksForRelaseMediaSequential ? Statuses.Ok : Statuses.Incomplete;
await DbContext.SaveChangesAsync();
modifiedRelease = true;
}
;
}
var foundInFolderTrackNumbers =
foundInFolderTracks.Select(x => x.TrackNumber).OrderBy(x => x).ToArray();
var foundInFolderTrackNumbers = foundInFolderTracks.Select(x => x.TrackNumber).OrderBy(x => x).ToArray();
if (modifiedRelease || !foundInFolderTrackNumbers.Count().Equals(release.TrackCount) ||
releaseMediaNumbersFound.Count() != (release.MediaCount ?? 0))
{
var areTracksForRelaseSequential = foundInFolderTrackNumbers
.Zip(foundInFolderTrackNumbers.Skip(1), (a, b) => a + 1 == b).All(x => x);
var maxFoundInFolderTrackNumbers =
foundInFolderTrackNumbers.Any() ? foundInFolderTrackNumbers.Max() : (short)0;
var areTracksForRelaseSequential = foundInFolderTrackNumbers.Zip(foundInFolderTrackNumbers.Skip(1), (a, b) => a + 1 == b).All(x => x);
var maxFoundInFolderTrackNumbers = foundInFolderTrackNumbers.Any() ? foundInFolderTrackNumbers.Max() : (short)0;
release.Status = areTracksForRelaseSequential ? Statuses.Ok : Statuses.Incomplete;
release.TrackCount = (short)foundInFolderTrackNumbers.Count();
release.MediaCount = (short)releaseMediaNumbersFound.Count();
if (release.TrackCount < maxFoundInFolderTrackNumbers)
{
release.TrackCount = maxFoundInFolderTrackNumbers;
}
release.LibraryStatus = release.TrackCount > 0 && release.TrackCount == totalNumberOfTracksFound
? LibraryStatus.Complete
: LibraryStatus.Incomplete;
@ -1299,12 +1300,16 @@ namespace Roadie.Api.Services
await UpdateReleaseCounts(release.Id, now);
await UpdateArtistCountsForRelease(release.Id, now);
if (release.Labels != null && release.Labels.Any())
foreach (var label in release.Labels)
await UpdateLabelCounts(label.Id, now);
await UpdateReleaseRank(release.Id);
Logger.LogInformation("Scanned Release `{0}` Folder [{1}], Modified Release [{2}], OperationTime [{3}]",
release.ToString(), releasePath, modifiedRelease, sw.ElapsedMilliseconds);
if (release.Labels != null && release.Labels.Any())
{
foreach (var label in release.Labels)
{
await UpdateLabelCounts(label.Id, now);
}
}
Logger.LogInformation("Scanned Release `{0}` Folder [{1}], Modified Release [{2}], OperationTime [{3}]", release.ToString(), releasePath, modifiedRelease, sw.ElapsedMilliseconds);
result = true;
}
catch (Exception ex)

View file

@ -135,7 +135,7 @@ namespace Roadie.Api.Services
if (!string.IsNullOrEmpty(request.s))
try
{
var token = HashHelper.MD5Hash((user.ApiToken ?? user.Email) + request.s);
var token = HashHelper.CreateMD5((user.ApiToken ?? user.Email) + request.s);
if (!token.Equals(request.t, StringComparison.OrdinalIgnoreCase)) user = null;
}
catch

View file

@ -657,7 +657,7 @@ namespace Roadie.Api.Services
long endBytes, User roadieUser)
{
var track = DbContext.Tracks.FirstOrDefault(x => x.RoadieId == trackId);
if (track == null)
if (!(track?.IsValid ?? true))
{
// Not Found try recanning release
var release = (from r in DbContext.Releases
@ -670,21 +670,21 @@ namespace Roadie.Api.Services
{
Id = roadieUser.Id.Value
}, release.RoadieId, false, true);
track = DbContext.Tracks.FirstOrDefault(x => x.RoadieId == trackId);
}
else
{
Logger.LogWarning($"TrackStreamInfo: Track [{ trackId }] was invalid but release [{ release.RoadieId }] is locked, did not rescan.");
}
track = DbContext.Tracks.FirstOrDefault(x => x.RoadieId == trackId);
if (track == null)
{
return new OperationResult<TrackStreamInfo>($"TrackStreamInfo: Unable To Find Track [{trackId}]");
}
if (!track.IsValid)
{
return new OperationResult<TrackStreamInfo>($"TrackStreamInfo: Invalid Track. Track Id [{trackId}], FilePath [{track.FilePath}], Filename [{track.FileName}]");
}
}
if (!track.IsValid)
{
return new OperationResult<TrackStreamInfo>(
$"TrackStreamInfo: Invalid Track. Track Id [{trackId}], FilePath [{track.FilePath}], Filename [{track.FileName}]");
}
string trackPath = null;
try
{