mirror of
https://github.com/sphildreth/roadie
synced 2024-11-25 05:30:24 +00:00
resolves #23
This commit is contained in:
parent
45c9a1c97a
commit
36459efa38
14 changed files with 205 additions and 163 deletions
82
Roadie.Api.Library.Tests/HashHelperTests.cs
Normal file
82
Roadie.Api.Library.Tests/HashHelperTests.cs
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 }");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 }");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 }");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue