2
0
Fork 0
mirror of https://github.com/sphildreth/roadie synced 2025-02-17 21:48:27 +00:00

Lots of cleanup, removals of 'this'.

This commit is contained in:
Steven Hildreth 2019-07-03 11:21:29 -05:00
parent 6bb4e8671c
commit 2fcf82db36
272 changed files with 6674 additions and 9496 deletions
Roadie.Api.Library
Caching
Configuration
Data
Encoding
Engines
Enums
EventMessage.cs
Extensions
Factories
FileOperationResult.cs
FilePlugins
Identity

View file

@ -9,15 +9,16 @@ namespace Roadie.Library.Caching
{
public const string SystemCacheRegionUrn = "urn:system";
protected readonly CachePolicy _defaultPolicy = null;
protected readonly CachePolicy _defaultPolicy;
protected readonly JsonSerializerSettings _serializerSettings;
protected ILogger Logger { get; }
protected readonly JsonSerializerSettings _serializerSettings = null;
public CacheManagerBase(ILogger logger, CachePolicy defaultPolicy)
{
this.Logger = logger;
this._defaultPolicy = defaultPolicy;
this._serializerSettings = new JsonSerializerSettings
Logger = logger;
_defaultPolicy = defaultPolicy;
_serializerSettings = new JsonSerializerSettings
{
ContractResolver = new IgnoreJsonAttributesResolver(),
Formatting = Formatting.Indented
@ -56,26 +57,22 @@ namespace Roadie.Library.Caching
protected TOut Deserialize<TOut>(string s)
{
if (string.IsNullOrEmpty(s))
{
return default(TOut);
}
if (string.IsNullOrEmpty(s)) return default(TOut);
try
{
return JsonConvert.DeserializeObject<TOut>(s, this._serializerSettings);
return JsonConvert.DeserializeObject<TOut>(s, _serializerSettings);
}
catch (Exception ex)
{
this.Logger.LogError(ex);
Logger.LogError(ex);
}
return default(TOut);
}
protected string Serialize(object o)
{
return JsonConvert.SerializeObject(o, this._serializerSettings);
return JsonConvert.SerializeObject(o, _serializerSettings);
}
}
}

View file

@ -4,20 +4,17 @@ namespace Roadie.Library.Caching
{
public sealed class CachePolicy
{
private readonly TimeSpan expiresAfter;
private readonly bool renewLeaseOnAccess;
public TimeSpan ExpiresAfter { get { return this.expiresAfter; } }
public TimeSpan ExpiresAfter { get; }
/// <summary>
/// If specified, each read of the item from the cache will reset the expiration time
/// If specified, each read of the item from the cache will reset the expiration time
/// </summary>
public bool RenewLeaseOnAccess { get { return this.renewLeaseOnAccess; } }
public bool RenewLeaseOnAccess { get; }
public CachePolicy(TimeSpan expiresAfter, bool renewLeaseOnAccess = false)
{
this.expiresAfter = expiresAfter;
this.renewLeaseOnAccess = renewLeaseOnAccess;
ExpiresAfter = expiresAfter;
RenewLeaseOnAccess = renewLeaseOnAccess;
}
}
}

View file

@ -1,57 +1,52 @@
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
namespace Roadie.Library.Caching
{
public class DictionaryCacheManager : CacheManagerBase
{
static readonly object padlock = new object();
private static readonly object padlock = new object();
private Dictionary<string, object> Cache { get; }
public DictionaryCacheManager(ILogger logger, CachePolicy defaultPolicy)
: base(logger, defaultPolicy)
: base(logger, defaultPolicy)
{
this.Cache = new Dictionary<string, object>();
Cache = new Dictionary<string, object>();
}
public override bool Add<TCacheValue>(string key, TCacheValue value)
{
lock (padlock)
{
if (this.Cache.ContainsKey(key))
{
this.Cache.Remove(key);
}
this.Cache.Add(key, value);
if (Cache.ContainsKey(key)) Cache.Remove(key);
Cache.Add(key, value);
return true;
}
}
public override bool Add<TCacheValue>(string key, TCacheValue value, string region)
{
return this.Add(key, value);
return Add(key, value);
}
public override bool Add<TCacheValue>(string key, TCacheValue value, CachePolicy policy)
{
return this.Add(key, value);
return Add(key, value);
}
public override bool Add<TCacheValue>(string key, TCacheValue value, string region, CachePolicy policy)
{
return this.Add(key, value);
return Add(key, value);
}
public override void Clear()
{
lock (padlock)
{
this.Cache.Clear();
Cache.Clear();
}
}
@ -59,7 +54,7 @@ namespace Roadie.Library.Caching
{
lock (padlock)
{
this.Clear();
Clear();
}
}
@ -67,7 +62,7 @@ namespace Roadie.Library.Caching
{
lock (padlock)
{
return this.Cache.ContainsKey(key);
return Cache.ContainsKey(key);
}
}
@ -75,7 +70,7 @@ namespace Roadie.Library.Caching
{
lock (padlock)
{
return this.Exists<TOut>(key);
return Exists<TOut>(key);
}
}
@ -83,11 +78,8 @@ namespace Roadie.Library.Caching
{
lock (padlock)
{
if (!this.Cache.ContainsKey(key))
{
return default(TOut);
}
return (TOut)this.Cache[key];
if (!Cache.ContainsKey(key)) return default(TOut);
return (TOut)Cache[key];
}
}
@ -98,55 +90,53 @@ namespace Roadie.Library.Caching
public override TOut Get<TOut>(string key, Func<TOut> getItem, string region)
{
return Get<TOut>(key, getItem, region, this._defaultPolicy);
return Get(key, getItem, region, _defaultPolicy);
}
public override TOut Get<TOut>(string key, Func<TOut> getItem, string region, CachePolicy policy)
{
lock (padlock)
{
var r = this.Get<TOut>(key, region);
var r = Get<TOut>(key, region);
if (r == null)
{
r = getItem();
this.Add(key, r, region, policy);
Add(key, r, region, policy);
}
return r;
}
}
public override async Task<TOut> GetAsync<TOut>(string key, Func<Task<TOut>> getItem, string region)
{
var r = Get<TOut>(key, region);
if (r == null)
{
r = await getItem();
Add(key, r, region);
Logger.LogTrace($"-+> Cache Miss for Key [{key}], Region [{region}]");
}
else
{
Logger.LogTrace($"-!> Cache Hit for Key [{key}], Region [{region}]");
}
return r;
}
public override bool Remove(string key)
{
lock (padlock)
{
if (this.Cache.ContainsKey(key))
{
this.Cache.Remove(key);
}
if (Cache.ContainsKey(key)) Cache.Remove(key);
return true;
}
}
public override bool Remove(string key, string region)
{
return this.Remove(key);
}
public async override Task<TOut> GetAsync<TOut>(string key, Func<Task<TOut>> getItem, string region)
{
var r = this.Get<TOut>(key, region);
if (r == null)
{
r = await getItem();
this.Add(key, r, region);
this.Logger.LogTrace($"-+> Cache Miss for Key [{ key }], Region [{ region }]");
}
else
{
this.Logger.LogTrace($"-!> Cache Hit for Key [{ key }], Region [{ region }]");
}
return r;
return Remove(key);
}
}
}

View file

@ -3,7 +3,7 @@ using System.Threading.Tasks;
namespace Roadie.Library.Caching
{
public interface ICacheManager
public interface ICacheManager
{
bool Add<TCacheValue>(string key, TCacheValue value);
@ -25,12 +25,12 @@ namespace Roadie.Library.Caching
TOut Get<TOut>(string key);
Task<TOut> GetAsync<TOut>(string key, Func<Task<TOut>> getItem, string region);
TOut Get<TOut>(string key, Func<TOut> getItem, string region);
TOut Get<TOut>(string key, Func<TOut> getItem, string region, CachePolicy policy);
Task<TOut> GetAsync<TOut>(string key, Func<Task<TOut>> getItem, string region);
bool Remove(string key);
bool Remove(string key, string region);

View file

@ -1,7 +1,6 @@
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace Roadie.Library.Caching
@ -13,7 +12,7 @@ namespace Roadie.Library.Caching
public MemoryCacheManager(ILogger logger, CachePolicy defaultPolicy)
: base(logger, defaultPolicy)
{
this._cache = new MemoryCache(new MemoryCacheOptions());
_cache = new MemoryCache(new MemoryCacheOptions());
}
public override bool Add<TCacheValue>(string key, TCacheValue value)
@ -24,7 +23,7 @@ namespace Roadie.Library.Caching
public override bool Add<TCacheValue>(string key, TCacheValue value, string region)
{
_cache.Set(key, value, this._defaultPolicy.ExpiresAfter);
_cache.Set(key, value, _defaultPolicy.ExpiresAfter);
return true;
}
@ -32,87 +31,91 @@ namespace Roadie.Library.Caching
{
_cache.Set(key, value, new MemoryCacheEntryOptions
{
AbsoluteExpiration = DateTimeOffset.UtcNow.Add(policy.ExpiresAfter) // new DateTimeOffset(DateTime.UtcNow, policy.ExpiresAfter)
AbsoluteExpiration =
DateTimeOffset.UtcNow.Add(policy
.ExpiresAfter) // new DateTimeOffset(DateTime.UtcNow, policy.ExpiresAfter)
});
return true;
}
public override bool Add<TCacheValue>(string key, TCacheValue value, string region, CachePolicy policy)
{
return this.Add(key, value, policy);
return Add(key, value, policy);
}
public override void Clear()
{
this._cache = new MemoryCache(new MemoryCacheOptions());
_cache = new MemoryCache(new MemoryCacheOptions());
}
public override void ClearRegion(string region)
{
this.Clear();
Clear();
}
public override bool Exists<TOut>(string key)
{
return this.Get<TOut>(key) != null;
return Get<TOut>(key) != null;
}
public override bool Exists<TOut>(string key, string region)
{
return this.Exists<TOut>(key);
return Exists<TOut>(key);
}
public override TOut Get<TOut>(string key)
{
return this._cache.Get<TOut>(key);
return _cache.Get<TOut>(key);
}
public override TOut Get<TOut>(string key, string region)
{
return this.Get<TOut>(key);
return Get<TOut>(key);
}
public override TOut Get<TOut>(string key, Func<TOut> getItem, string region)
{
return this.Get<TOut>(key, getItem, region, this._defaultPolicy);
return Get(key, getItem, region, _defaultPolicy);
}
public override TOut Get<TOut>(string key, Func<TOut> getItem, string region, CachePolicy policy)
{
var r = this.Get<TOut>(key, region);
var r = Get<TOut>(key, region);
if (r == null)
{
r = getItem();
this.Add(key, r, region, policy);
Add(key, r, region, policy);
}
return r;
}
public override async Task<TOut> GetAsync<TOut>(string key, Func<Task<TOut>> getItem, string region)
{
var r = Get<TOut>(key, region);
if (r == null)
{
r = await getItem();
Add(key, r, region);
Logger.LogInformation($"-+> Cache Miss for Key [{key}], Region [{region}]");
}
else
{
Logger.LogInformation($"-!> Cache Hit for Key [{key}], Region [{region}]");
}
return r;
}
public override bool Remove(string key)
{
this._cache.Remove(key);
_cache.Remove(key);
return true;
}
public override bool Remove(string key, string region)
{
return this.Remove(key);
}
public async override Task<TOut> GetAsync<TOut>(string key, Func<Task<TOut>> getItem, string region)
{
var r = this.Get<TOut>(key, region);
if (r == null)
{
r = await getItem();
this.Add(key, r, region);
this.Logger.LogInformation($"-+> Cache Miss for Key [{ key }], Region [{ region }]");
}
else
{
this.Logger.LogInformation($"-!> Cache Hit for Key [{ key }], Region [{ region }]");
}
return r;
return Remove(key);
}
}
}

View file

@ -9,62 +9,47 @@ using System.Threading.Tasks;
namespace Roadie.Library.Caching
{
/// <summary>
/// Redis Cache implemention
/// Redis Cache implemention
/// </summary>
/// <typeparam name="TCacheValue"></typeparam>
public class RedisCacheManager : CacheManagerBase
{
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
private static readonly Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
return ConnectionMultiplexer.Connect("192.168.1.253:6379,allowAdmin=true");
});
private bool _doTraceLogging = true;
private IDatabase _redis = null;
private readonly bool _doTraceLogging = true;
private IDatabase _redis;
public static ConnectionMultiplexer Connection
{
get
{
return lazyConnection.Value;
}
}
public static ConnectionMultiplexer Connection => lazyConnection.Value;
private IDatabase Redis
{
get
{
return this._redis ?? (this._redis = Connection.GetDatabase());
}
}
private IDatabase Redis => _redis ?? (_redis = Connection.GetDatabase());
public RedisCacheManager(ILogger logger, CachePolicy defaultPolicy)
: base(logger, defaultPolicy)
: base(logger, defaultPolicy)
{
}
public override bool Add<TCacheValue>(string key, TCacheValue value)
{
return this.Add(key, value, null, this._defaultPolicy);
return Add(key, value, null, _defaultPolicy);
}
public override bool Add<TCacheValue>(string key, TCacheValue value, string region)
{
return this.Add(key, value, region, null);
return Add(key, value, region, null);
}
public override bool Add<TCacheValue>(string key, TCacheValue value, CachePolicy policy)
{
return this.Add(key, value, null, this._defaultPolicy);
return Add(key, value, null, _defaultPolicy);
}
public override bool Add<TCacheValue>(string key, TCacheValue value, string region, CachePolicy policy)
{
if (this._doTraceLogging)
{
this.Logger.LogTrace("Added [{0}], Region [{1}]", key, region);
}
return this.Redis.StringSet(key, this.Serialize(value));
if (_doTraceLogging) Logger.LogTrace("Added [{0}], Region [{1}]", key, region);
return Redis.StringSet(key, Serialize(value));
}
public override void Clear()
@ -72,71 +57,70 @@ namespace Roadie.Library.Caching
var endpoints = Connection.GetEndPoints();
var server = Connection.GetServer(endpoints[0]);
server.FlushAllDatabases();
if (this._doTraceLogging)
{
this.Logger.LogTrace("Cleared Cache");
}
if (_doTraceLogging) Logger.LogTrace("Cleared Cache");
}
public override void ClearRegion(string region)
{
this.Clear();
Clear();
}
public override bool Exists<TOut>(string key)
{
return this.Exists<TOut>(key, null);
return Exists<TOut>(key, null);
}
public override bool Exists<TOut>(string key, string region)
{
return this.Redis.KeyExists(key);
return Redis.KeyExists(key);
}
public override TOut Get<TOut>(string key)
{
return this.Get<TOut>(key, null);
return Get<TOut>(key, null);
}
public override TOut Get<TOut>(string key, string region)
{
return this.Get<TOut>(key, region, this._defaultPolicy);
return Get<TOut>(key, region, _defaultPolicy);
}
public override TOut Get<TOut>(string key, Func<TOut> getItem, string region)
{
return this.Get<TOut>(key, getItem, region, this._defaultPolicy);
return Get(key, getItem, region, _defaultPolicy);
}
public override TOut Get<TOut>(string key, Func<TOut> getItem, string region, CachePolicy policy)
{
var r = this.Get<TOut>(key, region);
var r = Get<TOut>(key, region);
if (r == null)
{
r = getItem();
this.Add(key, r, region, policy);
Add(key, r, region, policy);
}
return r;
}
public override Task<TOut> GetAsync<TOut>(string key, Func<Task<TOut>> getItem, string region)
{
throw new NotImplementedException();
}
public override bool Remove(string key)
{
return this.Remove(key, null);
return Remove(key, null);
}
public override bool Remove(string key, string region)
{
if (this.Redis.KeyExists(key))
{
this.Redis.KeyDelete(key);
}
if (Redis.KeyExists(key)) Redis.KeyDelete(key);
return false;
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
try
{
Connection.Close();
@ -145,30 +129,23 @@ namespace Roadie.Library.Caching
catch
{
}
}
// free native resources here if there are any
}
private TOut Get<TOut>(string key, string region, CachePolicy policy)
{
var result = this.Deserialize<TOut>(this.Redis.StringGet(key));
var result = Deserialize<TOut>(Redis.StringGet(key));
if (result == null)
{
if (this._doTraceLogging)
{
this.Logger.LogTrace("Get Cache Miss Key [{0}], Region [{1}]", key, region);
}
if (_doTraceLogging) Logger.LogTrace("Get Cache Miss Key [{0}], Region [{1}]", key, region);
}
else if (this._doTraceLogging)
else if (_doTraceLogging)
{
this.Logger.LogTrace("Get Cache Hit Key [{0}], Region [{1}]", key, region);
Logger.LogTrace("Get Cache Hit Key [{0}], Region [{1}]", key, region);
}
return result;
}
public override Task<TOut> GetAsync<TOut>(string key, Func<Task<TOut>> getItem, string region)
{
throw new NotImplementedException();
return result;
}
}
@ -176,13 +153,14 @@ namespace Roadie.Library.Caching
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
var props = base.CreateProperties(type, memberSerialization);
foreach (var prop in props)
{
prop.Ignored = false; // Ignore [JsonIgnore]
prop.Converter = null; // Ignore [JsonConverter]
prop.PropertyName = prop.UnderlyingName; // restore original property name
prop.Ignored = false; // Ignore [JsonIgnore]
prop.Converter = null; // Ignore [JsonConverter]
prop.PropertyName = prop.UnderlyingName; // restore original property name
}
return props;
}
}

View file

@ -3,7 +3,8 @@
namespace Roadie.Library.Configuration
{
/// <summary>
/// This is a Api Key used by Roadie to interact with an API (ie KeyName is "BingImageSearch" and its key is the BingImageSearch Key)
/// This is a Api Key used by Roadie to interact with an API (ie KeyName is "BingImageSearch" and its key is the
/// BingImageSearch Key)
/// </summary>
[Serializable]
public class ApiKey : IApiKey

View file

@ -8,8 +8,8 @@ namespace Roadie.Library.Configuration
public string APEConvertCommand { get; set; }
public bool ConvertingEnabled { get; set; }
public bool DoDeleteAfter { get; set; }
public string FLACConvertCommand { get; set; }
public string M4AConvertCommand { get; set; }
public string OGGConvertCommand { get; set; }
public string FLACConvertCommand { get; set; }
}
}

View file

@ -2,8 +2,8 @@
{
public interface IConverting
{
bool ConvertingEnabled { get; set; }
string APEConvertCommand { get; set; }
bool ConvertingEnabled { get; set; }
bool DoDeleteAfter { get; set; }
string M4AConvertCommand { get; set; }
string OGGConvertCommand { get; set; }

View file

@ -5,6 +5,7 @@ namespace Roadie.Library.Configuration
public interface IRoadieSettings
{
Dictionary<string, List<string>> ArtistNameReplace { get; set; }
string BehindProxyHost { get; set; }
string ConnectionString { get; set; }
string ContentPath { get; set; }
Converting Converting { get; set; }
@ -14,11 +15,12 @@ namespace Roadie.Library.Configuration
IEnumerable<string> FileExtensionsToDelete { get; set; }
FilePlugins FilePlugins { get; set; }
string InboundFolder { get; set; }
Inspector Inspector { get; set; }
Integrations Integrations { get; set; }
ImageSize LargeImageSize { get; set; }
ImageSize MaximumImageSize { get; set; }
string LibraryFolder { get; set; }
string ListenAddress { get; set; }
ImageSize MaximumImageSize { get; set; }
ImageSize MediumImageSize { get; set; }
Processing Processing { get; set; }
bool RecordNoResultSearches { get; set; }
@ -35,8 +37,6 @@ namespace Roadie.Library.Configuration
ImageSize ThumbnailImageSize { get; set; }
Dictionary<string, string> TrackPathReplace { get; set; }
bool UseSSLBehindProxy { get; set; }
string BehindProxyHost { get; set; }
string WebsocketAddress { get; set; }
Inspector Inspector { get; set; }
}
}

View file

@ -1,19 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Configuration
namespace Roadie.Library.Configuration
{
public class Inspector : IInspector
{
/// <summary>
/// When true then make a copy of files to new destination versus moving files to destination.
/// When true then make a copy of files to new destination versus moving files to destination.
/// </summary>
public bool DoCopyFiles { get; set; }
/// <summary>
/// When true then don't modify any files only report what would be done.
/// When true then don't modify any files only report what would be done.
/// </summary>
public bool IsInReadOnlyMode { get; set; }
}
}
}

View file

@ -15,20 +15,15 @@ namespace Roadie.Library.Configuration
public List<ApiKey> ApiKeys { get; set; } = new List<ApiKey>();
public string DiscogsConsumerKey
{
get
{
var keySetting = this.ApiKeys.FirstOrDefault(x => x.ApiName == "DiscogsConsumerKey");
var keySetting = ApiKeys.FirstOrDefault(x => x.ApiName == "DiscogsConsumerKey");
if (keySetting != null)
{
return keySetting.Key;
}
else
{
Trace.WriteLine("Unable To Find Api Key with Key Name of 'DiscogsConsumerKey', Discogs Integration Disabled");
}
Trace.WriteLine(
"Unable To Find Api Key with Key Name of 'DiscogsConsumerKey', Discogs Integration Disabled");
return null;
}
}
@ -37,15 +32,11 @@ namespace Roadie.Library.Configuration
{
get
{
var keySetting = this.ApiKeys.FirstOrDefault(x => x.ApiName == "DiscogsConsumerKey");
var keySetting = ApiKeys.FirstOrDefault(x => x.ApiName == "DiscogsConsumerKey");
if (keySetting != null)
{
return keySetting.KeySecret;
}
else
{
Trace.WriteLine("Unable To Find Api Key with Key Name of 'DiscogsConsumerKey', Discogs Integration Disabled");
}
Trace.WriteLine(
"Unable To Find Api Key with Key Name of 'DiscogsConsumerKey', Discogs Integration Disabled");
return null;
}
}
@ -54,16 +45,11 @@ namespace Roadie.Library.Configuration
{
get
{
if (string.IsNullOrEmpty(this.DiscogsConsumerKey) || string.IsNullOrEmpty(this.DiscogsConsumerSecret))
{
if (string.IsNullOrEmpty(DiscogsConsumerKey) || string.IsNullOrEmpty(DiscogsConsumerSecret))
return false;
}
return this._discogsEnabled;
}
set
{
this._discogsEnabled = value;
return _discogsEnabled;
}
set => _discogsEnabled = value;
}
public short? DiscogsReadWriteTimeout { get; set; }
@ -76,15 +62,10 @@ namespace Roadie.Library.Configuration
{
get
{
var keySetting = this.ApiKeys.FirstOrDefault(x => x.ApiName == "LastFMApiKey");
var keySetting = ApiKeys.FirstOrDefault(x => x.ApiName == "LastFMApiKey");
if (keySetting != null)
{
return keySetting.Key;
}
else
{
Trace.WriteLine("Unable To Find Api Key with Key Name of 'LastFMApiKey', Last FM Integration Disabled");
}
Trace.WriteLine("Unable To Find Api Key with Key Name of 'LastFMApiKey', Last FM Integration Disabled");
return null;
}
}
@ -93,15 +74,10 @@ namespace Roadie.Library.Configuration
{
get
{
var keySetting = this.ApiKeys.FirstOrDefault(x => x.ApiName == "LastFMApiKey");
var keySetting = ApiKeys.FirstOrDefault(x => x.ApiName == "LastFMApiKey");
if (keySetting != null)
{
return keySetting.KeySecret;
}
else
{
Trace.WriteLine("Unable To Find Api Key with Key Name of 'LastFMApiKey', Last FM Integration Disabled");
}
Trace.WriteLine("Unable To Find Api Key with Key Name of 'LastFMApiKey', Last FM Integration Disabled");
return null;
}
}
@ -110,16 +86,10 @@ namespace Roadie.Library.Configuration
{
get
{
if (string.IsNullOrEmpty(this.LastFMApiKey) || string.IsNullOrEmpty(this.LastFmApiSecret))
{
return false;
}
return this._lastFmEnabled;
}
set
{
this._lastFmEnabled = value;
if (string.IsNullOrEmpty(LastFMApiKey) || string.IsNullOrEmpty(LastFmApiSecret)) return false;
return _lastFmEnabled;
}
set => _lastFmEnabled = value;
}
public bool MusicBrainzProviderEnabled { get; set; }

View file

@ -6,34 +6,55 @@ namespace Roadie.Library.Configuration
[Serializable]
public class Processing : IProcessing
{
public bool DoAudioCleanup { get; set; }
public bool DoClearComments { get; set; }
public bool DoDeleteUnknowns { get; set; }
public bool DoFolderArtistNameSet { get; set; }
public bool DoMoveUnknowns { get; set; }
public bool DoParseFromDiscogsDB { get; private set; }
public bool DoParseFromDiscogsDBFindingTrackForArtist { get; private set; }
public bool DoParseFromFileName { get; set; }
public bool DoParseFromLastFM { get; private set; }
public bool DoParseFromMusicBrainz { get; private set; }
public bool DoSaveEditsToTags { get; set; }
public int MaxImageWidth { get; set; }
public int MaximumArtistImagesToAdd { get; set; }
public int MaximumReleaseImagesToAdd { get; set; }
public string RemoveStringsRegex { get; set; }
public string ArtistRemoveStringsRegex { get; set; }
public string ReleaseRemoveStringsRegex { get; set; }
public string TrackRemoveStringsRegex { get; set; }
public string PreInspectScript { get; set; }
public bool DoAudioCleanup { get; set; }
public bool DoClearComments { get; set; }
public bool DoDeleteUnknowns { get; set; }
public bool DoFolderArtistNameSet { get; set; }
public bool DoMoveUnknowns { get; set; }
public bool DoParseFromDiscogsDB { get; private set; }
public bool DoParseFromDiscogsDBFindingTrackForArtist { get; private set; }
public bool DoParseFromFileName { get; set; }
public bool DoParseFromLastFM { get; private set; }
public bool DoParseFromMusicBrainz { get; private set; }
public bool DoSaveEditsToTags { get; set; }
public int MaxImageWidth { get; set; }
public int MaximumArtistImagesToAdd { get; set; }
public int MaximumReleaseImagesToAdd { get; set; }
public string PostInspectScript { get; set; }
public string PreInspectScript { get; set; }
public string ReleaseRemoveStringsRegex { get; set; }
public string RemoveStringsRegex { get; set; }
public List<ReplacementString> ReplaceStrings { get; set; }
public string TrackRemoveStringsRegex { get; set; }
public string UnknownFolder { get; set; }
public Processing()
{
this.ReplaceStrings = new List<ReplacementString>();
this.DoAudioCleanup = true;
this.DoClearComments = true;
ReplaceStrings = new List<ReplacementString>();
DoAudioCleanup = true;
DoClearComments = true;
}
}
}

View file

@ -1,14 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Configuration
{
[Serializable]
public class ReplacementString : IReplacementString
{
public int Order { get; set; }
public string Key { get; set; }
public int Order { get; set; }
public string ReplaceWith { get; set; }
}
}
}

View file

@ -7,53 +7,83 @@ namespace Roadie.Library.Configuration
public sealed class RoadieSettings : IRoadieSettings
{
/// <summary>
/// If the artist name is found in the values then use the key.
/// <remark>This was desgined to handle 'AC/DC' type names as they contain the ID3 v2.3 spec artist seperator</remark>
/// If the artist name is found in the values then use the key.
/// <remark>This was desgined to handle 'AC/DC' type names as they contain the ID3 v2.3 spec artist seperator</remark>
/// </summary>
public Dictionary<string, List<string>> ArtistNameReplace { get; set; }
public string BehindProxyHost { get; set; }
/// <summary>
/// Set to the Roadie Database for DbDataReader operations
/// Set to the Roadie Database for DbDataReader operations
/// </summary>
public string ConnectionString { get; set; }
/// <summary>
/// This is the phsycial path to the content folder (which holds among other things place-holder images)
/// This is the phsycial path to the content folder (which holds among other things place-holder images)
/// </summary>
public string ContentPath { get; set; }
public Converting Converting { get; set; }
public string DefaultTimeZone { get; set; }
public string DiagnosticsPassword { get; set; }
public IEnumerable<string> DontDoMetaDataProvidersSearchArtists { get; set; }
public IEnumerable<string> FileExtensionsToDelete { get; set; }
public FilePlugins FilePlugins { get; set; }
public string InboundFolder { get; set; }
public Integrations Integrations { get; set; }
public ImageSize LargeImageSize { get; set; }
public ImageSize MaximumImageSize { get; set; }
public string LibraryFolder { get; set; }
public string ListenAddress { get; set; }
public ImageSize MediumImageSize { get; set; }
public Processing Processing { get; set; }
public bool RecordNoResultSearches { get; set; }
public RedisCache Redis { get; set; }
public ImageSize SmallImageSize { get; set; }
public string SecretKey { get; set; }
public string SiteName { get; set; }
public string SmtpFromAddress { get; set; }
public string SmtpHost { get; set; }
public string SmtpPassword { get; set; }
public int SmtpPort { get; set; }
public string SmtpUsername { get; set; }
public bool SmtpUseSSl { get; set; }
public ImageSize ThumbnailImageSize { get; set; }
public Dictionary<string, string> TrackPathReplace { get; set; }
public bool UseSSLBehindProxy { get; set; }
public string BehindProxyHost { get; set; }
public string WebsocketAddress { get; set; }
public Inspector Inspector { get; set; }
public Integrations Integrations { get; set; }
public ImageSize LargeImageSize { get; set; }
public string LibraryFolder { get; set; }
public string ListenAddress { get; set; }
public ImageSize MaximumImageSize { get; set; }
public ImageSize MediumImageSize { get; set; }
public Processing Processing { get; set; }
public bool RecordNoResultSearches { get; set; }
public RedisCache Redis { get; set; }
public string SecretKey { get; set; }
public string SiteName { get; set; }
public ImageSize SmallImageSize { get; set; }
public string SmtpFromAddress { get; set; }
public string SmtpHost { get; set; }
public string SmtpPassword { get; set; }
public int SmtpPort { get; set; }
public string SmtpUsername { get; set; }
public bool SmtpUseSSl { get; set; }
public ImageSize ThumbnailImageSize { get; set; }
public Dictionary<string, string> TrackPathReplace { get; set; }
public bool UseSSLBehindProxy { get; set; }
public string WebsocketAddress { get; set; }
public RoadieSettings()
{
ThumbnailImageSize = new ImageSize { Width = 80, Height = 80 };

View file

@ -6,12 +6,13 @@ namespace Roadie.Library.Configuration
public class ImageSize : IImageSize
{
public short Height { get; set; }
public short Width { get; set; }
public ImageSize()
{
this.Height = 80;
this.Width = 80;
Height = 80;
Width = 80;
}
}
}

View file

@ -9,18 +9,12 @@ namespace Roadie.Library.Data
[Table("artist")]
public partial class Artist : BeginAndEndNamedEntityBase
{
[Column("amgId")]
[MaxLength(100)]
public string AmgId { get; set; }
[Column("amgId")] [MaxLength(100)] public string AmgId { get; set; }
[Column("artistType", TypeName = "enum")]
public string ArtistType { get; set; }
[InverseProperty("Artist")]
public ICollection<ArtistAssociation> AssociatedArtists { get; set; }
[InverseProperty("Artist")]
public ICollection<ArtistSimilar> SimilarArtists { get; set; }
[InverseProperty("Artist")] public ICollection<ArtistAssociation> AssociatedArtists { get; set; }
[Column("bandStatus", TypeName = "enum")]
public BandStatus? BandStatus { get; set; }
@ -32,9 +26,9 @@ namespace Roadie.Library.Data
[Column("birthDate", TypeName = "date")]
public DateTime? BirthDate { get; set; }
[Column("discogsId")]
[MaxLength(50)]
public string DiscogsId { get; set; }
public ICollection<Comment> Comments { get; set; }
[Column("discogsId")] [MaxLength(50)] public string DiscogsId { get; set; }
public ICollection<ArtistGenre> Genres { get; set; }
@ -44,59 +38,46 @@ namespace Roadie.Library.Data
[MaxLength(65535)]
public string ISNI { get; set; }
[Column("iTunesId")]
[MaxLength(100)]
public string ITunesId { get; set; }
[Column("iTunesId")] [MaxLength(100)] public string ITunesId { get; set; }
[Column("lastPlayed")]
public DateTime? LastPlayed { get; set; }
[Column("lastPlayed")] public DateTime? LastPlayed { get; set; }
[Column("musicBrainzId")]
[MaxLength(100)]
public string MusicBrainzId { get; set; }
[Column("playedCount")] public int? PlayedCount { get; set; }
[Column("profile", TypeName = "text")]
[MaxLength(65535)]
public string Profile { get; set; }
[Column("playedCount")]
public int? PlayedCount { get; set; }
[Column("rank")] public decimal? Rank { get; set; }
[Column("rating")]
public short? Rating { get; set; }
[Column("rating")] public short? Rating { get; set; }
[Column("rank")]
public decimal? Rank { get; set; }
[Column("realName")] [MaxLength(500)] public string RealName { get; set; }
[Column("realName")]
[MaxLength(500)]
public string RealName { get; set; }
[Column("releaseCount")] public int? ReleaseCount { get; set; }
//public List<Release> Releases { get; set; }
public ICollection<Release> Releases { get; set; }
[Column("spotifyId")]
[MaxLength(100)]
public string SpotifyId { get; set; }
[InverseProperty("Artist")] public ICollection<ArtistSimilar> SimilarArtists { get; set; }
[Column("releaseCount")]
public int? ReleaseCount { get; set; }
[Column("spotifyId")] [MaxLength(100)] public string SpotifyId { get; set; }
[Column("trackCount")]
public int? TrackCount { get; set; }
public ICollection<Comment> Comments { get; set; }
[Column("trackCount")] public int? TrackCount { get; set; }
public Artist()
{
this.Releases = new HashSet<Release>();
this.Genres = new HashSet<ArtistGenre>();
this.AssociatedArtists = new HashSet<ArtistAssociation>();
this.SimilarArtists = new HashSet<ArtistSimilar>();
this.Comments = new HashSet<Comment>();
this.Rating = 0;
this.Status = Statuses.Ok;
Releases = new HashSet<Release>();
Genres = new HashSet<ArtistGenre>();
AssociatedArtists = new HashSet<ArtistAssociation>();
SimilarArtists = new HashSet<ArtistSimilar>();
Comments = new HashSet<Comment>();
Rating = 0;
Status = Statuses.Ok;
}
}
}

View file

@ -4,20 +4,17 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("artistAssociation")]
public partial class ArtistAssociation
public class ArtistAssociation
{
//[ForeignKey("artistId")]
public Artist Artist { get; set; }
[Column("artistId")]
[Required]
public int ArtistId { get; set; }
[Column("artistId")] [Required] public int ArtistId { get; set; }
//[ForeignKey("associatedArtistId")]
public Artist AssociatedArtist { get; set; }
[Column("associatedArtistId")]
public int AssociatedArtistId { get; set; }
[Column("associatedArtistId")] public int AssociatedArtistId { get; set; }
[Key]
[Column("id")]

View file

@ -4,19 +4,15 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("artistGenreTable")]
public partial class ArtistGenre
public class ArtistGenre
{
public Artist Artist { get; set; }
[Column("artistId")]
[Required]
public int ArtistId { get; set; }
[Column("artistId")] [Required] public int ArtistId { get; set; }
public Genre Genre { get; set; }
[Column("genreId")]
[Required]
public int? GenreId { get; set; }
[Column("genreId")] [Required] public int? GenreId { get; set; }
[Column("id")]
[Key]

View file

@ -2,85 +2,60 @@
using Roadie.Library.Utility;
using System;
using System.Linq;
using System.Security.Cryptography;
namespace Roadie.Library.Data
{
public partial class Artist
{
public static string CacheRegionUrn(Guid Id)
{
return $"urn:artist:{ Id}";
}
public string CacheKey => CacheUrn(RoadieId);
public static string CacheUrnByName(string name)
{
return $"urn:artist_by_name:{ name }";
}
public static string CacheUrn(Guid Id)
{
return $"urn:artist_by_id:{ Id }";
}
public string CacheKey
{
get
{
return Artist.CacheUrn(this.RoadieId);
}
}
public string CacheRegion
{
get
{
return Artist.CacheRegionUrn(this.RoadieId);
}
}
public string CacheRegion => CacheRegionUrn(RoadieId);
public string Etag
{
get
{
using (var md5 = System.Security.Cryptography.MD5.Create())
using (var md5 = MD5.Create())
{
return String.Concat(md5.ComputeHash(System.Text.Encoding.Default.GetBytes(string.Format("{0}{1}", this.RoadieId, this.LastUpdated))).Select(x => x.ToString("D2")));
return string.Concat(md5
.ComputeHash(
System.Text.Encoding.Default.GetBytes(string.Format("{0}{1}", RoadieId, LastUpdated)))
.Select(x => x.ToString("D2")));
}
}
}
public bool IsNew
public bool IsNew => Id < 1;
public bool IsValid => !string.IsNullOrEmpty(Name);
public string SortNameValue => string.IsNullOrEmpty(SortName) ? Name : SortName;
public static string CacheRegionUrn(Guid Id)
{
get
{
return this.Id < 1;
}
return $"urn:artist:{Id}";
}
public bool IsValid
public static string CacheUrn(Guid Id)
{
get
{
return !string.IsNullOrEmpty(this.Name);
}
return $"urn:artist_by_id:{Id}";
}
public string SortNameValue
public static string CacheUrnByName(string name)
{
get
{
return string.IsNullOrEmpty(this.SortName) ? this.Name : this.SortName;
}
return $"urn:artist_by_name:{name}";
}
public string ArtistFileFolder(IRoadieSettings configuration, string destinationRoot)
{
return FolderPathHelper.ArtistPath(configuration, this.SortNameValue, destinationRoot);
return FolderPathHelper.ArtistPath(configuration, SortNameValue, destinationRoot);
}
public override string ToString()
{
return string.Format("Id [{0}], Name [{1}], SortName [{2}], RoadieId [{3}]", this.Id, this.Name, this.SortNameValue, this.RoadieId);
return string.Format("Id [{0}], Name [{1}], SortName [{2}], RoadieId [{3}]", Id, Name, SortNameValue,
RoadieId);
}
}
}

View file

@ -4,24 +4,21 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("artistSimilar")]
public partial class ArtistSimilar
public class ArtistSimilar
{
//[ForeignKey("artistId")]
public Artist Artist { get; set; }
[Column("artistId")]
[Required]
public int ArtistId { get; set; }
//[ForeignKey("associatedArtistId")]
public Artist SimilarArtist { get; set; }
[Column("similarArtistId")]
public int SimilarArtistId { get; set; }
[Column("artistId")] [Required] public int ArtistId { get; set; }
[Key]
[Column("id")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
//[ForeignKey("associatedArtistId")]
public Artist SimilarArtist { get; set; }
[Column("similarArtistId")] public int SimilarArtistId { get; set; }
}
}

View file

@ -8,7 +8,6 @@ namespace Roadie.Library.Data
[Column("beginDate", TypeName = "date")]
public DateTime? BeginDate { get; set; }
[Column("endDate", TypeName = "date")]
public DateTime? EndDate { get; set; }
[Column("endDate", TypeName = "date")] public DateTime? EndDate { get; set; }
}
}

View file

@ -5,10 +5,8 @@ namespace Roadie.Library.Data
{
public abstract class BeginAndEndNamedEntityBase : NamedEntityBase
{
[Column("beginDate")]
public DateTime? BeginDate { get; set; }
[Column("beginDate")] public DateTime? BeginDate { get; set; }
[Column("endDate")]
public DateTime? EndDate { get; set; }
[Column("endDate")] public DateTime? EndDate { get; set; }
}
}

View file

@ -8,26 +8,16 @@ namespace Roadie.Library.Data
[Table("bookmark")]
public partial class Bookmark : EntityBase
{
[Column("bookmarkTargetId")]
public int BookmarkTargetId { get; set; }
[Column("bookmarkTargetId")] public int BookmarkTargetId { get; set; }
// public short? Type { get; set; }
// public short? Type { get; set; }
[Column("bookmarkType")]
public BookmarkType? BookmarkType { get; set; }
[Column("bookmarkType")] public BookmarkType? BookmarkType { get; set; }
[Column("Comment")] [MaxLength(4000)] public string Comment { get; set; }
[Column("position")] public int? Position { get; set; }
public ApplicationUser User { get; set; }
[Column("userId")]
[Required]
public int UserId { get; set; }
[Column("position")]
public int? Position { get; set; }
[Column("Comment")]
[MaxLength(4000)]
public string Comment { get; set; }
[Column("userId")] [Required] public int UserId { get; set; }
}
}

View file

@ -1,14 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Data
namespace Roadie.Library.Data
{
public partial class Bookmark
{
public override string ToString()
{
return $"Id [{ this.Id }], BookmarkType [{ this.BookmarkType }], BookmarkTargetId [{ this.BookmarkTargetId }]";
return $"Id [{Id}], BookmarkType [{BookmarkType}], BookmarkTargetId [{BookmarkTargetId}]";
}
}
}
}

View file

@ -1,24 +1,19 @@
using Roadie.Library.Identity;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
namespace Roadie.Library.Data
{
[Table("chatMessage")]
public class ChatMessage : EntityBase
{
public ApplicationUser User { get; set; }
[Column("userId")]
[Required]
public int UserId { get; set; }
[Column("message")]
[Required]
[MaxLength(5000)]
public string Message { get; set; }
public ApplicationUser User { get; set; }
[Column("userId")] [Required] public int UserId { get; set; }
}
}
}

View file

@ -1,5 +1,4 @@
using Roadie.Library.Enums;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
@ -9,19 +8,17 @@ namespace Roadie.Library.Data
[Table("collection")]
public partial class Collection : NamedEntityBase
{
[Column("collectionCount")]
public int CollectionCount { get; set; }
[Column("collectionCount")] public int CollectionCount { get; set; }
[Column("collectionType")]
public CollectionType? CollectionType { get; set; }
[Column("collectionType")] public CollectionType? CollectionType { get; set; }
public ICollection<Comment> Comments { get; set; }
[Column("description")]
[MaxLength(4000)]
public string Description { get; set; }
[Column("edition")]
[MaxLength(200)]
public string Edition { get; set; }
[Column("edition")] [MaxLength(200)] public string Edition { get; set; }
[Column("listInCSV", TypeName = "text")]
[MaxLength(65535)]
@ -31,12 +28,8 @@ namespace Roadie.Library.Data
[MaxLength(200)]
public string ListInCSVFormat { get; set; }
[Column("maintainerId")]
public int MaintainerId { get; set; }
[Column("maintainerId")] public int MaintainerId { get; set; }
public ICollection<CollectionRelease> Releases { get; set; }
public ICollection<Comment> Comments { get; set; }
}
}

View file

@ -1,28 +1,23 @@
using Roadie.Library.Enums;
using Roadie.Library.Identity;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("collectionMissing")]
public partial class CollectionMissing
public class CollectionMissing
{
[Column("artist")] [MaxLength(1000)] public string Artist { get; set; }
[Column("collectionId")] public int CollectionId { get; set; }
[Column("id")]
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("collectionId")]
public int CollectionId { get; set; }
[Column("isArtistFound")]
public bool IsArtistFound { get; set; }
[Column("position")]
public int Position { get; set; }
[Column("artist")]
[MaxLength(1000)]
public string Artist { get; set; }
[Column("release")]
[MaxLength(1000)]
public string Release { get; set; }
[Column("isArtistFound")] public bool IsArtistFound { get; set; }
[Column("position")] public int Position { get; set; }
[Column("release")] [MaxLength(1000)] public string Release { get; set; }
}
}
}

View file

@ -6,12 +6,83 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
namespace Roadie.Library.Data
{
public partial class Collection
{
public int? _artistColumn;
public int? _positionColumn;
public int? _releaseColumn;
private IEnumerable<PositionArtistRelease> _positionArtistReleases;
public int ArtistColumn
{
get
{
if (_artistColumn == null)
{
var looper = -1;
foreach (var pos in ListInCSVFormat.Split(','))
{
looper++;
if (pos.ToLower().Equals("artist")) _artistColumn = looper;
}
}
return _artistColumn.Value;
}
}
public string CacheKey => CacheUrn(RoadieId);
public string CacheRegion => CacheRegionUrn(RoadieId);
public int PositionColumn
{
get
{
if (_positionColumn == null)
{
var looper = -1;
foreach (var pos in ListInCSVFormat.Split(','))
{
looper++;
if (pos.ToLower().Equals("position")) _positionColumn = looper;
}
}
return _positionColumn.Value;
}
}
public int ReleaseColumn
{
get
{
if (_releaseColumn == null)
{
var looper = -1;
foreach (var pos in ListInCSVFormat.Split(','))
{
looper++;
if (pos.ToLower().Equals("release")) _releaseColumn = looper;
}
}
return _releaseColumn.Value;
}
}
public Collection()
{
Releases = new HashSet<CollectionRelease>();
Comments = new HashSet<Comment>();
ListInCSVFormat = "Position,Release,Artist";
CollectionType = Enums.CollectionType.Rank;
}
public static string CacheRegionUrn(Guid Id)
{
return string.Format("urn:collection:{0}", Id);
@ -19,97 +90,15 @@ namespace Roadie.Library.Data
public static string CacheUrn(Guid Id)
{
return $"urn:collection_by_id:{ Id }";
return $"urn:collection_by_id:{Id}";
}
public string CacheKey
{
get
{
return Collection.CacheUrn(this.RoadieId);
}
}
public string CacheRegion
{
get
{
return Collection.CacheRegionUrn(this.RoadieId);
}
}
public int? _positionColumn = null;
public int PositionColumn
{
get
{
if (this._positionColumn == null)
{
var looper = -1;
foreach (var pos in this.ListInCSVFormat.Split(','))
{
looper++;
if (pos.ToLower().Equals("position"))
{
this._positionColumn = looper;
}
}
}
return this._positionColumn.Value;
}
}
public int? _artistColumn = null;
public int ArtistColumn
{
get
{
if (this._artistColumn == null)
{
var looper = -1;
foreach (var pos in this.ListInCSVFormat.Split(','))
{
looper++;
if (pos.ToLower().Equals("artist"))
{
this._artistColumn = looper;
}
}
}
return this._artistColumn.Value;
}
}
public int? _releaseColumn = null;
public int ReleaseColumn
{
get
{
if (this._releaseColumn == null)
{
var looper = -1;
foreach (var pos in this.ListInCSVFormat.Split(','))
{
looper++;
if (pos.ToLower().Equals("release"))
{
this._releaseColumn = looper;
}
}
}
return this._releaseColumn.Value;
}
}
private IEnumerable<PositionArtistRelease> _positionArtistReleases = null;
public IEnumerable<PositionArtistRelease> PositionArtistReleases()
{
if (this._positionArtistReleases == null)
if (_positionArtistReleases == null)
{
var rows = new List<PositionArtistRelease>();
using (var sr = new StringReader(this.ListInCSV))
using (var sr = new StringReader(ListInCSV))
{
var index = 0;
var configuration = new CsvHelper.Configuration.Configuration
@ -128,60 +117,49 @@ namespace Roadie.Library.Data
rows.Add(new PositionArtistRelease
{
Index = index,
Position = csv.GetField<int>(this.PositionColumn),
Artist = SafeParser.ToString(csv.GetField<string>(this.ArtistColumn)),
Release = SafeParser.ToString(csv.GetField<string>(this.ReleaseColumn)),
Position = csv.GetField<int>(PositionColumn),
Artist = SafeParser.ToString(csv.GetField<string>(ArtistColumn)),
Release = SafeParser.ToString(csv.GetField<string>(ReleaseColumn))
});
}
}
this._positionArtistReleases = rows;
}
return this._positionArtistReleases;
}
public Collection()
{
this.Releases = new HashSet<CollectionRelease>();
this.Comments = new HashSet<Comment>();
ListInCSVFormat = "Position,Release,Artist";
CollectionType = Enums.CollectionType.Rank;
_positionArtistReleases = rows;
}
return _positionArtistReleases;
}
public override string ToString()
{
return $"Id [{ this.Id }], Name [{ this.Name }]";
return $"Id [{Id}], Name [{Name}]";
}
}
[Serializable]
public class PositionArtistRelease
{
[JsonIgnore]
public Statuses Status { get; set; }
public string Artist { get; set; }
[JsonProperty("Status")]
public string StatusVerbose
{
get
{
return this.Status.ToString();
}
}
/// <summary>
/// This is the index (position in the list regardless of the position number)
/// This is the index (position in the list regardless of the position number)
/// </summary>
[JsonIgnore]
public int Index { get; set; }
/// <summary>
/// This is the position number for the list (can be a year "1984" can be a number "14")
/// This is the position number for the list (can be a year "1984" can be a number "14")
/// </summary>
public int Position { get; set; }
public string Artist { get; set; }
public string Release { get; set; }
[JsonIgnore] public Statuses Status { get; set; }
[JsonProperty("Status")] public string StatusVerbose => Status.ToString();
public override string ToString()
{
return string.Format("Position [{0}], Artist [{1}], Release [{2}]", this.Position, this.Artist, this.Release);
return string.Format("Position [{0}], Artist [{1}], Release [{2}]", Position, Artist, Release);
}
}
}
}

View file

@ -4,21 +4,16 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("collectionrelease")]
public partial class CollectionRelease : EntityBase
public class CollectionRelease : EntityBase
{
public Collection Collection { get; set; }
[Column("collectionId")]
[Required]
public int CollectionId { get; set; }
[Column("collectionId")] [Required] public int CollectionId { get; set; }
[Column("listNumber")]
public int ListNumber { get; set; }
[Column("listNumber")] public int ListNumber { get; set; }
public Release Release { get; set; }
[Column("releaseId")]
[Required]
public int ReleaseId { get; set; }
[Column("releaseId")] [Required] public int ReleaseId { get; set; }
}
}

View file

@ -9,50 +9,39 @@ namespace Roadie.Library.Data
[Table("comment")]
public partial class Comment : EntityBase
{
[Column("artistId")] public int? ArtistId { get; set; }
[Column("comment")]
[MaxLength(25500)]
[Required]
public string Cmt { get; set; }
public ApplicationUser User { get; set; }
[Column("collectionId")] public int? CollectionId { get; set; }
[Column("userId")]
[Required]
public int UserId { get; set; }
[Column("genreId")] public int? GenreId { get; set; }
[Column("replyToCommentId")]
public int? ReplyToCommentId { get; set; }
[NotMapped] public new bool? IsLocked { get; set; }
[Column("artistId")]
public int? ArtistId { get; set; }
[Column("labelId")] public int? LabelId { get; set; }
[Column("collectionId")]
public int? CollectionId { get; set; }
[Column("genreId")]
public int? GenreId { get; set; }
[Column("labelId")]
public int? LabelId { get; set; }
[Column("playlistId")]
public int? PlaylistId { get; set; }
[Column("releaseId")]
public int? ReleaseId { get; set; }
[Column("trackId")]
public int? TrackId { get; set; }
[NotMapped]
public new bool? IsLocked { get; set; }
[Column("playlistId")] public int? PlaylistId { get; set; }
public ICollection<CommentReaction> Reactions { get; set; }
[Column("releaseId")] public int? ReleaseId { get; set; }
[Column("replyToCommentId")] public int? ReplyToCommentId { get; set; }
[Column("trackId")] public int? TrackId { get; set; }
public ApplicationUser User { get; set; }
[Column("userId")] [Required] public int UserId { get; set; }
public Comment()
{
this.Reactions = new HashSet<CommentReaction>();
this.Status = Statuses.Ok;
Reactions = new HashSet<CommentReaction>();
Status = Statuses.Ok;
}
}
}

View file

@ -1,8 +1,5 @@
using Roadie.Library.Enums;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
namespace Roadie.Library.Data
{
@ -13,36 +10,15 @@ namespace Roadie.Library.Data
{
get
{
if(this.ArtistId.HasValue)
{
return CommentType.Artist;
}
if(this.CollectionId.HasValue)
{
return CommentType.Collection;
}
if(this.GenreId.HasValue)
{
return CommentType.Genre;
}
if(this.LabelId.HasValue)
{
return CommentType.Label;
}
if(this.PlaylistId.HasValue)
{
return CommentType.Playlist;
}
if(this.ReleaseId.HasValue)
{
return CommentType.Release;
}
if(this.TrackId.HasValue)
{
return CommentType.Track;
}
if (ArtistId.HasValue) return CommentType.Artist;
if (CollectionId.HasValue) return CommentType.Collection;
if (GenreId.HasValue) return CommentType.Genre;
if (LabelId.HasValue) return CommentType.Label;
if (PlaylistId.HasValue) return CommentType.Playlist;
if (ReleaseId.HasValue) return CommentType.Release;
if (TrackId.HasValue) return CommentType.Track;
return CommentType.Unknown;
}
}
}
}
}

View file

@ -1,5 +1,4 @@
using Roadie.Library.Enums;
using Roadie.Library.Identity;
using Roadie.Library.Identity;
using Roadie.Library.Utility;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
@ -7,33 +6,18 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("commentReaction")]
public partial class CommentReaction : EntityBase
public class CommentReaction : EntityBase
{
public Comment Comment { get; set; }
[Column("commentId")] [Required] public int CommentId { get; set; }
[NotMapped] public new bool? IsLocked { get; set; }
[Column("reaction")] public string Reaction { get; set; }
[NotMapped]
public Enums.CommentReaction ReactionValue => SafeParser.ToEnum<Enums.CommentReaction>(Reaction ?? "Unknown");
public ApplicationUser User { get; set; }
[Column("commentId")]
[Required]
public int CommentId { get; set; }
[Column("userId")]
[Required]
public int UserId { get; set; }
[NotMapped]
public new bool? IsLocked { get; set; }
[Column("reaction")]
public string Reaction { get; set; }
[NotMapped]
public Enums.CommentReaction ReactionValue
{
get
{
return SafeParser.ToEnum<Enums.CommentReaction>(this.Reaction ?? "Unknown");
}
}
[Column("userId")] [Required] public int UserId { get; set; }
}
}

View file

@ -1,5 +1,4 @@
using Mapster;
using Roadie.Library.Enums;
using Roadie.Library.Enums;
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
@ -8,9 +7,7 @@ namespace Roadie.Library.Data
{
public abstract class EntityBase
{
[Column("createdDate")]
[Required]
public DateTime CreatedDate { get; set; }
[Column("createdDate")] [Required] public DateTime CreatedDate { get; set; }
[Column("id")]
[Key]
@ -19,23 +16,18 @@ namespace Roadie.Library.Data
public bool? IsLocked { get; set; }
[Column("lastUpdated")]
public DateTime? LastUpdated { get; set; }
[Column("lastUpdated")] public DateTime? LastUpdated { get; set; }
[Column("RoadieId")]
[Required]
public Guid RoadieId { get; set; }
[Column("RoadieId")] [Required] public Guid RoadieId { get; set; }
[Column("status")]
public Statuses? Status { get; set; }
[Column("status")] public Statuses? Status { get; set; }
public EntityBase()
{
this.RoadieId = Guid.NewGuid();
this.Status = Statuses.Incomplete;
this.CreatedDate = DateTime.UtcNow;
this.IsLocked = false;
RoadieId = Guid.NewGuid();
Status = Statuses.Incomplete;
CreatedDate = DateTime.UtcNow;
IsLocked = false;
}
}
}

View file

@ -7,20 +7,19 @@ namespace Roadie.Library.Data
[Table("genre")]
public partial class Genre : EntityBase
{
[Column("name")]
[MaxLength(100)]
public string Name { get; set; }
public ICollection<ReleaseGenre> Releases { get; set; }
public ICollection<ArtistGenre> Artists { get; set; }
public ICollection<Comment> Comments { get; set; }
[Column("name")] [MaxLength(100)] public string Name { get; set; }
public ICollection<ReleaseGenre> Releases { get; set; }
public Genre()
{
this.Releases = new HashSet<ReleaseGenre>();
this.Artists = new HashSet<ArtistGenre>();
this.Comments = new HashSet<Comment>();
Releases = new HashSet<ReleaseGenre>();
Artists = new HashSet<ArtistGenre>();
Comments = new HashSet<Comment>();
}
}
}

View file

@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Data
{
public partial class Genre
{
public string CacheKey => CacheUrn(RoadieId);
public string CacheRegion => CacheRegionUrn(RoadieId);
public static string CacheRegionUrn(Guid Id)
{
return string.Format("urn:genre:{0}", Id);
@ -13,23 +15,7 @@ namespace Roadie.Library.Data
public static string CacheUrn(Guid Id)
{
return $"urn:genre_by_id:{ Id }";
}
public string CacheKey
{
get
{
return Genre.CacheUrn(this.RoadieId);
}
}
public string CacheRegion
{
get
{
return Genre.CacheRegionUrn(this.RoadieId);
}
return $"urn:genre_by_id:{Id}";
}
}
}
}

View file

@ -10,20 +10,21 @@ using System.Threading.Tasks;
namespace Roadie.Library.Data
{
public interface IRoadieDbContext : IDisposable, IInfrastructure<IServiceProvider>, IDbContextDependencies, IDbSetCache, IDbQueryCache, IDbContextPoolable
public interface IRoadieDbContext : IDisposable, IInfrastructure<IServiceProvider>, IDbContextDependencies,
IDbSetCache, IDbQueryCache, IDbContextPoolable
{
DbSet<ArtistAssociation> ArtistAssociations { get; set; }
DbSet<ArtistSimilar> ArtistSimilar { get; set; }
DbSet<ArtistGenre> ArtistGenres { get; set; }
DbSet<Artist> Artists { get; set; }
DbSet<ArtistSimilar> ArtistSimilar { get; set; }
DbSet<Bookmark> Bookmarks { get; set; }
ChangeTracker ChangeTracker { get; }
DbSet<ChatMessage> ChatMessages { get; set; }
DbSet<CollectionMissing> CollectionMissings { get; set; }
DbSet<CollectionRelease> CollectionReleases { get; set; }
DbSet<Collection> Collections { get; set; }
DbSet<Comment> Comments { get; set; }
DbSet<CommentReaction> CommentReactions { get; set; }
DbSet<Comment> Comments { get; set; }
DatabaseFacade Database { get; }
DbSet<Genre> Genres { get; set; }
DbSet<Image> Images { get; set; }
@ -51,13 +52,15 @@ namespace Roadie.Library.Data
Task<EntityEntry> AddAsync(object entity, CancellationToken cancellationToken = default(CancellationToken));
Task<EntityEntry<TEntity>> AddAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = default(CancellationToken)) where TEntity : class;
Task<EntityEntry<TEntity>> AddAsync<TEntity>(TEntity entity,
CancellationToken cancellationToken = default(CancellationToken)) where TEntity : class;
void AddRange(IEnumerable<object> entities);
void AddRange(params object[] entities);
Task AddRangeAsync(IEnumerable<object> entities, CancellationToken cancellationToken = default(CancellationToken));
Task AddRangeAsync(IEnumerable<object> entities,
CancellationToken cancellationToken = default(CancellationToken));
Task AddRangeAsync(params object[] entities);
@ -103,7 +106,8 @@ namespace Roadie.Library.Data
int SaveChanges();
Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken));
Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess,
CancellationToken cancellationToken = default(CancellationToken));
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
@ -118,7 +122,5 @@ namespace Roadie.Library.Data
void UpdateRange(params object[] entities);
void UpdateRange(IEnumerable<object> entities);
}
}

View file

@ -6,28 +6,19 @@ namespace Roadie.Library.Data
[Table("image")]
public partial class Image : EntityBase
{
[Column("artistId")]
public int? ArtistId { get; set; }
public Artist Artist { get; set; }
[Column("artistId")] public int? ArtistId { get; set; }
[Column("image", TypeName = "mediumblob")]
public byte[] Bytes { get; set; }
[Column("caption")]
[MaxLength(100)]
public string Caption { get; set; }
[Column("caption")] [MaxLength(100)] public string Caption { get; set; }
[Column("releaseId")]
public int? ReleaseId { get; set; }
[Column("signature")]
[MaxLength(50)]
public string Signature { get; set; }
[Column("url")]
[MaxLength(500)]
public string Url { get; set; }
public Artist Artist { get; set; }
public Release Release { get; set; }
[Column("releaseId")] public int? ReleaseId { get; set; }
[Column("signature")] [MaxLength(50)] public string Signature { get; set; }
[Column("url")] [MaxLength(500)] public string Url { get; set; }
}
}

View file

@ -1,6 +1,4 @@
using Microsoft.Net.Http.Headers;
using Roadie.Library.Imaging;
using Roadie.Library.Utility;
using Roadie.Library.Imaging;
using System;
using System.Linq;
@ -8,6 +6,10 @@ namespace Roadie.Library.Data
{
public partial class Image
{
public string CacheKey => Artist.CacheUrn(RoadieId);
public string CacheRegion => CacheRegionUrn(RoadieId);
public static string CacheRegionUrn(Guid Id)
{
return string.Format("urn:image:{0}", Id);
@ -15,34 +17,13 @@ namespace Roadie.Library.Data
public static string CacheUrn(Guid Id)
{
return $"urn:image_by_id:{ Id }";
}
public string CacheKey
{
get
{
return Artist.CacheUrn(this.RoadieId);
}
}
public string CacheRegion
{
get
{
return Image.CacheRegionUrn(this.RoadieId);
}
return $"urn:image_by_id:{Id}";
}
public string GenerateSignature()
{
if (this.Bytes == null || !this.Bytes.Any())
{
return null;
}
return ImageHasher.AverageHash(this.Bytes).ToString();
if (Bytes == null || !Bytes.Any()) return null;
return ImageHasher.AverageHash(Bytes).ToString();
}
}
}

View file

@ -8,13 +8,13 @@ namespace Roadie.Library.Data
[Table("label")]
public partial class Label : BeginAndEndNamedEntityBase
{
[Column("discogsId")]
[MaxLength(50)]
public string DiscogsId { get; set; }
[Column("artistCount")] public int? ArtistCount { get; set; }
[Column("imageUrl")]
[MaxLength(500)]
public string ImageUrl { get; set; }
public ICollection<Comment> Comments { get; set; }
[Column("discogsId")] [MaxLength(50)] public string DiscogsId { get; set; }
[Column("imageUrl")] [MaxLength(500)] public string ImageUrl { get; set; }
[Column("musicBrainzId")]
[MaxLength(100)]
@ -24,24 +24,17 @@ namespace Roadie.Library.Data
[MaxLength(65535)]
public string Profile { get; set; }
[Column("artistCount")]
public int? ArtistCount { get; set; }
[Column("releaseCount")]
public int? ReleaseCount { get; set; }
[Column("trackCount")]
public int? TrackCount { get; set; }
[Column("releaseCount")] public int? ReleaseCount { get; set; }
public ICollection<ReleaseLabel> ReleaseLabels { get; set; }
public ICollection<Comment> Comments { get; set; }
[Column("trackCount")] public int? TrackCount { get; set; }
public Label()
{
this.ReleaseLabels = new HashSet<ReleaseLabel>();
this.Comments = new HashSet<Comment>();
this.Status = Statuses.Ok;
ReleaseLabels = new HashSet<ReleaseLabel>();
Comments = new HashSet<Comment>();
Status = Statuses.Ok;
}
}
}

View file

@ -1,10 +1,31 @@
using System;
using System.Linq;
using System.Security.Cryptography;
namespace Roadie.Library.Data
{
public partial class Label
{
public string CacheKey => CacheUrn(RoadieId);
public string CacheRegion => CacheRegionUrn(RoadieId);
public string Etag
{
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")));
}
}
}
public bool IsValid => !string.IsNullOrEmpty(Name);
public static string CacheRegionUrn(Guid Id)
{
return string.Format("urn:label:{0}", Id);
@ -12,42 +33,7 @@ namespace Roadie.Library.Data
public static string CacheUrn(Guid Id)
{
return $"urn:label_by_id:{ Id }";
}
public string CacheKey
{
get
{
return Label.CacheUrn(this.RoadieId);
}
}
public string CacheRegion
{
get
{
return Label.CacheRegionUrn(this.RoadieId);
}
}
public string Etag
{
get
{
using (var md5 = System.Security.Cryptography.MD5.Create())
{
return String.Concat(md5.ComputeHash(System.Text.Encoding.Default.GetBytes(string.Format("{0}{1}", this.RoadieId, this.LastUpdated))).Select(x => x.ToString("D2")));
}
}
}
public bool IsValid
{
get
{
return !string.IsNullOrEmpty(this.Name);
}
return $"urn:label_by_id:{Id}";
}
}
}

View file

@ -9,13 +9,9 @@ namespace Roadie.Library.Data
[MaxLength(65535)]
public string AlternateNames { get; set; }
[MaxLength(250)]
[Column("name")]
public string Name { get; set; }
[MaxLength(250)] [Column("name")] public string Name { get; set; }
[Column("sortName")]
[MaxLength(250)]
public string SortName { get; set; }
[Column("sortName")] [MaxLength(250)] public string SortName { get; set; }
[Column("tags", TypeName = "text")]
[MaxLength(65535)]

View file

@ -8,37 +8,31 @@ namespace Roadie.Library.Data
[Table("playlist")]
public partial class Playlist : NamedEntityBase
{
[NotMapped]
public new string SortName { get; set; }
public ICollection<Comment> Comments { get; set; }
[Column("Description")]
[MaxLength(1000)]
public string Description { get; set; }
[Column("isPublic")]
public bool IsPublic { get; set; }
[Column("duration")] public int? Duration { get; set; }
[Column("isPublic")] public bool IsPublic { get; set; }
[Column("releaseCount")] public short ReleaseCount { get; set; }
[NotMapped] public new string SortName { get; set; }
[Column("trackCount")] public short TrackCount { get; set; }
public ICollection<PlaylistTrack> Tracks { get; set; }
public ApplicationUser User { get; set; }
[Column("userId")]
public int? UserId { get; set; }
[Column("duration")]
public int? Duration { get; set; }
[Column("trackCount")]
public short TrackCount { get; set; }
[Column("releaseCount")]
public short ReleaseCount { get; set; }
public ICollection<Comment> Comments { get; set; }
[Column("userId")] public int? UserId { get; set; }
public Playlist()
{
this.Comments = new HashSet<Comment>();
Comments = new HashSet<Comment>();
}
}
}

View file

@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Data
{
public partial class Playlist
{
public string CacheKey => CacheUrn(RoadieId);
public string CacheRegion => CacheRegionUrn(RoadieId);
public static string CacheRegionUrn(Guid Id)
{
return string.Format("urn:playlist:{0}", Id);
@ -13,28 +15,12 @@ namespace Roadie.Library.Data
public static string CacheUrn(Guid Id)
{
return $"urn:playlist_by_id:{ Id }";
}
public string CacheKey
{
get
{
return Playlist.CacheUrn(this.RoadieId);
}
}
public string CacheRegion
{
get
{
return Playlist.CacheRegionUrn(this.RoadieId);
}
return $"urn:playlist_by_id:{Id}";
}
public override string ToString()
{
return $"Id [{this.Id}], Name [{this.Name}], RoadieId [{ this.RoadieId}]";
return $"Id [{Id}], Name [{Name}], RoadieId [{RoadieId}]";
}
}
}
}

View file

@ -4,20 +4,16 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("playlisttrack")]
public partial class PlaylistTrack : EntityBase
public class PlaylistTrack : EntityBase
{
[Column("listNumber")]
[Required]
public int ListNumber { get; set; }
[Column("listNumber")] [Required] public int ListNumber { get; set; }
public Playlist Playlist { get; set; }
[Column("playListId")]
public int PlayListId { get; set; }
[Column("playListId")] public int PlayListId { get; set; }
public Track Track { get; set; }
[Column("trackId")]
public int TrackId { get; set; }
[Column("trackId")] public int TrackId { get; set; }
}
}

View file

@ -13,54 +13,41 @@ namespace Roadie.Library.Data
[MaxLength(65535)]
public string AlternateNames { get; set; }
[Column("amgId")]
[MaxLength(50)]
public string AmgId { get; set; }
[Column("amgId")] [MaxLength(50)] public string AmgId { get; set; }
public Artist Artist { get; set; }
[Column("artistId")]
[Required]
public int ArtistId { get; set; }
[Column("artistId")] [Required] public int ArtistId { get; set; }
public ICollection<CollectionRelease> Collections { get; set; }
[Column("duration")]
public int? Duration { get; set; }
public ICollection<Comment> Comments { get; set; }
[Column("discogsId")]
[MaxLength(50)]
public string DiscogsId { get; set; }
[Column("discogsId")] [MaxLength(50)] public string DiscogsId { get; set; }
[Column("duration")] public int? Duration { get; set; }
public ICollection<ReleaseGenre> Genres { get; set; }
public ICollection<Image> Images { get; set; }
[Column("isVirtual")]
public bool? IsVirtual { get; set; }
[Column("isVirtual")] public bool? IsVirtual { get; set; }
[Column("itunesId")]
[MaxLength(100)]
public string ITunesId { get; set; }
[Column("itunesId")] [MaxLength(100)] public string ITunesId { get; set; }
public ICollection<ReleaseLabel> Labels { get; set; }
[Column("lastFMId")]
[MaxLength(50)]
public string LastFMId { get; set; }
[Column("lastFMId")] [MaxLength(50)] public string LastFMId { get; set; }
[Column("lastFMSummary", TypeName = "text")]
[MaxLength(65535)]
public string LastFMSummary { get; set; }
[Column("lastPlayed")]
public DateTime? LastPlayed { get; set; }
[Column("lastPlayed")] public DateTime? LastPlayed { get; set; }
[Column("libraryStatus")]
public LibraryStatus? LibraryStatus { get; set; }
[Column("libraryStatus")] public LibraryStatus? LibraryStatus { get; set; }
[Column("mediaCount")]
public short? MediaCount { get; set; }
[Column("mediaCount")] public short? MediaCount { get; set; }
public ICollection<ReleaseMedia> Medias { get; set; }
@ -68,28 +55,23 @@ namespace Roadie.Library.Data
[MaxLength(100)]
public string MusicBrainzId { get; set; }
[Column("playedCount")]
public int? PlayedCount { get; set; }
[Column("playedCount")] public int? PlayedCount { get; set; }
[Column("profile", TypeName = "text")]
[MaxLength(65535)]
public string Profile { get; set; }
[Column("rating")]
public short? Rating { get; set; }
[Column("rank")] public decimal? Rank { get; set; }
[Column("releaseDate")]
public DateTime? ReleaseDate { get; set; }
[Column("rating")] public short? Rating { get; set; }
[Column("releaseType")]
public ReleaseType? ReleaseType { get; set; }
[Column("releaseDate")] public DateTime? ReleaseDate { get; set; }
[Column("spotifyId")]
[MaxLength(100)]
public string SpotifyId { get; set; }
[Column("releaseType")] public ReleaseType? ReleaseType { get; set; }
[Column("submissionId")]
public int? SubmissionId { get; set; }
[Column("spotifyId")] [MaxLength(100)] public string SpotifyId { get; set; }
[Column("submissionId")] public int? SubmissionId { get; set; }
[Column("tags", TypeName = "text")]
[MaxLength(65535)]
@ -104,28 +86,22 @@ namespace Roadie.Library.Data
[Required]
public string Title { get; set; }
[Column("trackCount")]
public short TrackCount { get; set; }
[Column("trackCount")] public short TrackCount { get; set; }
[Column("urls", TypeName = "text")]
[MaxLength(65535)]
public string URLs { get; set; }
[Column("rank")]
public decimal? Rank { get; set; }
public ICollection<Comment> Comments { get; set; }
public Release()
{
this.Rating = 0;
this.ReleaseType = Enums.ReleaseType.Release;
this.Images = new HashSet<Image>();
this.Medias = new HashSet<ReleaseMedia>();
this.Labels = new HashSet<ReleaseLabel>();
this.Collections = new HashSet<CollectionRelease>();
this.Genres = new HashSet<ReleaseGenre>();
this.Comments = new HashSet<Comment>();
Rating = 0;
ReleaseType = Enums.ReleaseType.Release;
Images = new HashSet<Image>();
Medias = new HashSet<ReleaseMedia>();
Labels = new HashSet<ReleaseLabel>();
Collections = new HashSet<CollectionRelease>();
Genres = new HashSet<ReleaseGenre>();
Comments = new HashSet<Comment>();
}
}
}

View file

@ -4,13 +4,11 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("releaseGenreTable")]
public partial class ReleaseGenre
public class ReleaseGenre
{
public Genre Genre { get; set; }
[Column("genreId")]
[Required]
public int? GenreId { get; set; }
[Column("genreId")] [Required] public int? GenreId { get; set; }
[Column("id")]
[Key]
@ -19,8 +17,6 @@ namespace Roadie.Library.Data
public Release Release { get; set; }
[Column("releaseId")]
[Required]
public int ReleaseId { get; set; }
[Column("releaseId")] [Required] public int ReleaseId { get; set; }
}
}

View file

@ -5,17 +5,14 @@ namespace Roadie.Library.Data
[Table("releaselabel")]
public class ReleaseLabel : BeginAndEndEntityBase
{
[Column("catalogNumber")]
public string CatalogNumber { get; set; }
[Column("catalogNumber")] public string CatalogNumber { get; set; }
public Label Label { get; set; }
[Column("labelId")]
public int LabelId { get; set; }
[Column("labelId")] public int LabelId { get; set; }
public Release Release { get; set; }
[Column("releaseId")]
public int ReleaseId { get; set; }
[Column("releaseId")] public int ReleaseId { get; set; }
}
}

View file

@ -7,27 +7,23 @@ namespace Roadie.Library.Data
[Table("releasemedia")]
public class ReleaseMedia : EntityBase
{
[Column("releaseMediaNumber")]
public short MediaNumber { get; set; }
[Column("releaseMediaNumber")] public short MediaNumber { get; set; }
public Release Release { get; set; }
[Column("releaseId")]
public int ReleaseId { get; set; }
[Column("releaseId")] public int ReleaseId { get; set; }
[Column("releaseSubTitle")]
[MaxLength(500)]
public string SubTitle { get; set; }
[Column("trackCount")]
[Required]
public short TrackCount { get; set; }
[Column("trackCount")] [Required] public short TrackCount { get; set; }
public ICollection<Track> Tracks { get; set; }
public ReleaseMedia()
{
this.Tracks = new HashSet<Track>();
Tracks = new HashSet<Track>();
}
}
}

View file

@ -3,44 +3,26 @@ using Roadie.Library.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
namespace Roadie.Library.Data
{
public partial class Release
{
public static string CacheRegionUrn(Guid Id)
{
return string.Format("urn:release:{0}", Id);
}
public string CacheKey => Artist.CacheUrn(RoadieId);
public static string CacheUrn(Guid Id)
{
return $"urn:release_by_id:{ Id }";
}
public string CacheKey
{
get
{
return Artist.CacheUrn(this.RoadieId);
}
}
public string CacheRegion
{
get
{
return Release.CacheRegionUrn(this.RoadieId);
}
}
public string CacheRegion => CacheRegionUrn(RoadieId);
public string Etag
{
get
{
using (var md5 = System.Security.Cryptography.MD5.Create())
using (var md5 = MD5.Create())
{
return String.Concat(md5.ComputeHash(System.Text.Encoding.Default.GetBytes(string.Format("{0}{1}", this.RoadieId, this.LastUpdated))).Select(x => x.ToString("D2")));
return string.Concat(md5
.ComputeHash(
System.Text.Encoding.Default.GetBytes(string.Format("{0}{1}", RoadieId, LastUpdated)))
.Select(x => x.ToString("D2")));
}
}
}
@ -49,11 +31,8 @@ namespace Roadie.Library.Data
{
get
{
if (string.IsNullOrEmpty(this.Title))
{
return false;
}
return this.IsReleaseTypeOf("Original Broadway Cast") || this.IsReleaseTypeOf("Original Cast");
if (string.IsNullOrEmpty(Title)) return false;
return IsReleaseTypeOf("Original Broadway Cast") || IsReleaseTypeOf("Original Cast");
}
}
@ -61,107 +40,80 @@ namespace Roadie.Library.Data
{
get
{
if (string.IsNullOrEmpty(this.Title))
{
return false;
}
if (string.IsNullOrEmpty(Title)) return false;
foreach (var soundTrackTrigger in new List<string> { "soundtrack", " ost", "(ost)" })
{
if (this.IsReleaseTypeOf(soundTrackTrigger))
{
if (IsReleaseTypeOf(soundTrackTrigger))
return true;
}
}
return false;
}
}
public bool IsValid
{
get
{
return !string.IsNullOrEmpty(this.Title) && this.ReleaseDate > DateTime.MinValue;
}
}
public bool IsReleaseTypeOf(string type, bool doCheckTitles = false)
{
if (string.IsNullOrEmpty(type))
{
return false;
}
try
{
if (doCheckTitles)
{
if (this.Artist != null && !string.IsNullOrEmpty(this.Artist.Name))
{
if (this.Artist.Name.IndexOf(type, 0, StringComparison.OrdinalIgnoreCase) > -1)
{
return true;
}
}
if (!string.IsNullOrEmpty(this.Title))
{
if (this.Title.IndexOf(type, 0, StringComparison.OrdinalIgnoreCase) > -1)
{
return true;
}
}
if (this.AlternateNames != null)
{
if (this.AlternateNames.IsValueInDelimitedList(type))
{
return true;
}
}
}
if (this.Tags != null)
{
if (this.Tags.IsValueInDelimitedList(type))
{
return true;
}
}
if (this.Genres != null)
{
if (this.Genres.Any(x => x.Genre.Name.ToLower().Equals(type)))
{
return true;
}
}
}
catch
{
}
return false;
}
public bool IsValid => !string.IsNullOrEmpty(Title) && ReleaseDate > DateTime.MinValue;
public int? ReleaseYear
{
get
{
if(this.ReleaseDate.HasValue)
{
return this.ReleaseDate.Value.Year;
}
if (ReleaseDate.HasValue) return ReleaseDate.Value.Year;
return null;
}
}
public static string CacheRegionUrn(Guid Id)
{
return string.Format("urn:release:{0}", Id);
}
public static string CacheUrn(Guid Id)
{
return $"urn:release_by_id:{Id}";
}
public bool IsReleaseTypeOf(string type, bool doCheckTitles = false)
{
if (string.IsNullOrEmpty(type)) return false;
try
{
if (doCheckTitles)
{
if (Artist != null && !string.IsNullOrEmpty(Artist.Name))
if (Artist.Name.IndexOf(type, 0, StringComparison.OrdinalIgnoreCase) > -1)
return true;
if (!string.IsNullOrEmpty(Title))
if (Title.IndexOf(type, 0, StringComparison.OrdinalIgnoreCase) > -1)
return true;
if (AlternateNames != null)
if (AlternateNames.IsValueInDelimitedList(type))
return true;
}
if (Tags != null)
if (Tags.IsValueInDelimitedList(type))
return true;
if (Genres != null)
if (Genres.Any(x => x.Genre.Name.ToLower().Equals(type)))
return true;
}
catch
{
}
return false;
}
/// <summary>
/// Return this releases file folder for the given artist folder
/// Return this releases file folder for the given artist folder
/// </summary>
/// <param name="artistFolder"></param>
/// <returns></returns>
public string ReleaseFileFolder(string artistFolder)
{
return FolderPathHelper.ReleasePath(artistFolder, this.Title, this.ReleaseDate.Value);
return FolderPathHelper.ReleasePath(artistFolder, Title, ReleaseDate.Value);
}
public override string ToString()
{
return $"Id [{ this.Id }], Title [{ this.Title }], Release Date [{this.ReleaseYear}]";
return $"Id [{Id}], Title [{Title}], Release Date [{ReleaseYear}]";
}
}
}

View file

@ -5,20 +5,16 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("request")]
public partial class Request : EntityBase
public class Request : EntityBase
{
[Column("description")]
[MaxLength(500)]
[Required]
public string Description { get; set; }
[NotMapped] public new bool? IsLocked { get; set; }
public ApplicationUser User { get; set; }
[Column("userId")]
public int? UserId { get; set; }
[NotMapped]
public new bool? IsLocked { get; set; }
[Column("userId")] public int? UserId { get; set; }
}
}

View file

@ -8,40 +8,68 @@ namespace Roadie.Library.Data
public class RoadieDbContext : DbContext, IRoadieDbContext
{
public DbSet<ArtistAssociation> ArtistAssociations { get; set; }
public DbSet<ArtistSimilar> ArtistSimilar { get; set; }
public DbSet<ArtistGenre> ArtistGenres { get; set; }
public DbSet<Artist> Artists { get; set; }
public DbSet<ArtistSimilar> ArtistSimilar { get; set; }
public DbSet<Bookmark> Bookmarks { get; set; }
public DbSet<ChatMessage> ChatMessages { get; set; }
public DbSet<Comment> Comments { get; set; }
public DbSet<CollectionMissing> CollectionMissings { get; set; }
public DbSet<CommentReaction> CommentReactions { get; set; }
public DbSet<CollectionRelease> CollectionReleases { get; set; }
public DbSet<Collection> Collections { get; set; }
public DbSet<CommentReaction> CommentReactions { get; set; }
public DbSet<Comment> Comments { get; set; }
public DbSet<Genre> Genres { get; set; }
public DbSet<Image> Images { get; set; }
public DbSet<Label> Labels { get; set; }
public DbSet<Playlist> Playlists { get; set; }
public DbSet<PlaylistTrack> PlaylistTracks { get; set; }
public DbSet<ReleaseGenre> ReleaseGenres { get; set; }
public DbSet<ReleaseLabel> ReleaseLabels { get; set; }
public DbSet<ReleaseMedia> ReleaseMedias { get; set; }
public DbSet<Release> Releases { get; set; }
public DbSet<Request> Requests { get; set; }
public DbSet<ScanHistory> ScanHistories { get; set; }
public DbSet<Submission> Submissions { get; set; }
public DbSet<Track> Tracks { get; set; }
public DbSet<UserArtist> UserArtists { get; set; }
public DbSet<UserQue> UserQues { get; set; }
public DbSet<UserRelease> UserReleases { get; set; }
public DbSet<ApplicationRole> UserRoles { get; set; }
public DbSet<ApplicationUser> Users { get; set; }
public DbSet<UserTrack> UserTracks { get; set; }
public RoadieDbContext(DbContextOptions<RoadieDbContext> options)
: base(options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
@ -56,7 +84,6 @@ namespace Roadie.Library.Data
// v => string.IsNullOrEmpty(v) ? Statuses.Ok : (Statuses)Enum.Parse(typeof(Statuses), v))
// .HasDefaultValue(Statuses.Ok);
//builder
// .Entity<Artist>()
// .Property(e => e.Status)
@ -70,7 +97,9 @@ namespace Roadie.Library.Data
.Property(e => e.ReleaseType)
.HasConversion(
v => v.ToString(),
v => string.IsNullOrEmpty(v) ? ReleaseType.Unknown : (ReleaseType)Enum.Parse(typeof(ReleaseType), v))
v => string.IsNullOrEmpty(v)
? ReleaseType.Unknown
: (ReleaseType)Enum.Parse(typeof(ReleaseType), v))
.HasDefaultValue(ReleaseType.Release);
builder
@ -78,7 +107,9 @@ namespace Roadie.Library.Data
.Property(e => e.LibraryStatus)
.HasConversion(
v => v.ToString(),
v => string.IsNullOrEmpty(v) ? LibraryStatus.Incomplete : (LibraryStatus)Enum.Parse(typeof(LibraryStatus), v))
v => string.IsNullOrEmpty(v)
? LibraryStatus.Incomplete
: (LibraryStatus)Enum.Parse(typeof(LibraryStatus), v))
.HasDefaultValue(LibraryStatus.Incomplete);
builder
@ -86,7 +117,9 @@ namespace Roadie.Library.Data
.Property(e => e.CollectionType)
.HasConversion(
v => v.ToString(),
v => string.IsNullOrEmpty(v) ? CollectionType.Unknown : (CollectionType)Enum.Parse(typeof(CollectionType), v))
v => string.IsNullOrEmpty(v)
? CollectionType.Unknown
: (CollectionType)Enum.Parse(typeof(CollectionType), v))
.HasDefaultValue(CollectionType.Unknown);
builder

View file

@ -1,35 +1,33 @@
using Roadie.Library.Identity;
using System;
using System.Collections.Generic;
using Roadie.Library.Enums;
using Roadie.Library.Identity;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
namespace Roadie.Library.Data
{
[Table("scanHistory")]
public class ScanHistory : EntityBase
{
[Column("userId")]
public int UserId { get; set; }
[Column("forArtistId")] public int? ForArtistId { get; set; }
[Column("forReleaseId")] public int? ForReleaseId { get; set; }
[NotMapped] public new bool? IsLocked { get; set; }
[Column("newArtists")] public int? NewArtists { get; set; }
[Column("newReleases")] public int? NewReleases { get; set; }
[Column("newTracks")] public int? NewTracks { get; set; }
[Column("timeSpanInSeconds")] public int TimeSpanInSeconds { get; set; }
public ApplicationUser User { get; set; }
[Column("forArtistId")]
public int? ForArtistId { get; set; }
[Column("forReleaseId")]
public int? ForReleaseId { get; set; }
[Column("newArtists")]
public int? NewArtists { get; set; }
[Column("newReleases")]
public int? NewReleases { get; set; }
[Column("newTracks")]
public int? NewTracks { get; set; }
[Column("timeSpanInSeconds")]
public int TimeSpanInSeconds { get; set; }
[NotMapped]
public new bool? IsLocked { get; set; }
[Column("userId")] public int UserId { get; set; }
public ScanHistory()
{
this.Status = Enums.Statuses.Complete;
Status = Statuses.Complete;
}
}
}
}

View file

@ -4,11 +4,10 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("submission")]
public partial class Submission : EntityBase
public class Submission : EntityBase
{
public ApplicationUser User { get; set; }
[Column("userId")]
public int UserId { get; set; }
[Column("userId")] public int UserId { get; set; }
}
}

View file

@ -12,41 +12,27 @@ namespace Roadie.Library.Data
[MaxLength(65535)]
public string AlternateNames { get; set; }
[Column("amgId")]
[MaxLength(50)]
public string AmgId { get; set; }
[Column("amgId")] [MaxLength(50)] public string AmgId { get; set; }
[Column("artistId")]
public int? ArtistId { get; set; }
[Column("artistId")] public int? ArtistId { get; set; }
[Column("duration")]
public int? Duration { get; set; }
public ICollection<Comment> Comments { get; set; }
[Column("fileName")]
[MaxLength(500)]
public string FileName { get; set; }
[Column("duration")] public int? Duration { get; set; }
[Column("filePath")]
[MaxLength(1000)]
public string FilePath { get; set; }
[Column("fileName")] [MaxLength(500)] public string FileName { get; set; }
[Column("fileSize")]
public int? FileSize { get; set; }
[Column("filePath")] [MaxLength(1000)] public string FilePath { get; set; }
[Column("hash")]
[MaxLength(32)]
public string Hash { get; set; }
[Column("fileSize")] public int? FileSize { get; set; }
[Column("isrc")]
[MaxLength(15)]
public string ISRC { get; set; }
[Column("hash")] [MaxLength(32)] public string Hash { get; set; }
[Column("lastFMId")]
[MaxLength(50)]
public string LastFMId { get; set; }
[Column("isrc")] [MaxLength(15)] public string ISRC { get; set; }
[Column("lastPlayed")]
public DateTime? LastPlayed { get; set; }
[Column("lastFMId")] [MaxLength(50)] public string LastFMId { get; set; }
[Column("lastPlayed")] public DateTime? LastPlayed { get; set; }
[Column("musicBrainzId")]
[MaxLength(100)]
@ -56,20 +42,15 @@ namespace Roadie.Library.Data
[MaxLength(65535)]
public string PartTitles { get; set; }
[Column("playedCount")]
public int? PlayedCount { get; set; }
[Column("playedCount")] public int? PlayedCount { get; set; }
[Column("rating")]
public short Rating { get; set; }
[Column("rating")] public short Rating { get; set; }
public ReleaseMedia ReleaseMedia { get; set; }
[Column("releaseMediaId")]
public int ReleaseMediaId { get; set; }
[Column("releaseMediaId")] public int ReleaseMediaId { get; set; }
[Column("spotifyId")]
[MaxLength(100)]
public string SpotifyId { get; set; }
[Column("spotifyId")] [MaxLength(100)] public string SpotifyId { get; set; }
[Column("tags", TypeName = "text")]
[MaxLength(65535)]
@ -83,16 +64,12 @@ namespace Roadie.Library.Data
[Required]
public string Title { get; set; }
[Column("trackNumber")]
[Required]
public short TrackNumber { get; set; }
public ICollection<Comment> Comments { get; set; }
[Column("trackNumber")] [Required] public short TrackNumber { get; set; }
public Track()
{
this.Comments = new HashSet<Comment>();
this.Rating = 0;
Comments = new HashSet<Comment>();
Rating = 0;
}
}
}

View file

@ -5,11 +5,36 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Security.Cryptography;
namespace Roadie.Library.Data
{
public partial class Track
{
public string CacheKey => CacheUrn(RoadieId);
public string CacheRegion => CacheRegionUrn(RoadieId);
public string Etag
{
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")));
}
}
}
public bool IsValid => !string.IsNullOrEmpty(Hash);
public Artist TrackArtist { get; set; }
[NotMapped] public IEnumerable<string> TrackArtists { get; set; }
public static string CacheRegionUrn(Guid Id)
{
return string.Format("urn:track:{0}", Id);
@ -17,51 +42,11 @@ namespace Roadie.Library.Data
public static string CacheUrn(Guid Id)
{
return $"urn:track_by_id:{ Id }";
return $"urn:track_by_id:{Id}";
}
public string CacheKey
{
get
{
return Track.CacheUrn(this.RoadieId);
}
}
public string CacheRegion
{
get
{
return Track.CacheRegionUrn(this.RoadieId);
}
}
public string Etag
{
get
{
using (var md5 = System.Security.Cryptography.MD5.Create())
{
return String.Concat(md5.ComputeHash(System.Text.Encoding.Default.GetBytes(string.Format("{0}{1}", this.RoadieId, this.LastUpdated))).Select(x => x.ToString("D2")));
}
}
}
public bool IsValid
{
get
{
return !string.IsNullOrEmpty(this.Hash);
}
}
public Artist TrackArtist { get; set; }
[NotMapped]
public IEnumerable<string> TrackArtists { get; set; }
/// <summary>
/// Returns a full file path to the current track
/// Returns a full file path to the current track
/// </summary>
public string PathToTrack(IRoadieSettings configuration, string libraryFolder)
{
@ -69,31 +54,30 @@ namespace Roadie.Library.Data
}
/// <summary>
/// Returns a full file path to the current track thumbnail (if any)
/// Returns a full file path to the current track thumbnail (if any)
/// </summary>
public string PathToTrackThumbnail(IRoadieSettings configuration, string libraryFolder)
{
return FolderPathHelper.PathForTrackThumbnail(configuration, this, libraryFolder);
}
public override string ToString()
{
return string.Format("Id [{0}], TrackNumber [{1}], Title [{2}]", this.Id, this.TrackNumber, this.Title);
return string.Format("Id [{0}], TrackNumber [{1}], Title [{2}]", Id, TrackNumber, Title);
}
/// <summary>
/// Update any file related columns to indicate this track file is missing
/// Update any file related columns to indicate this track file is missing
/// </summary>
/// <param name="now">Optional datetime to mark for Updated, if missing defaults to UtcNow</param>
public void UpdateTrackMissingFile(DateTime? now = null)
{
this.Hash = null;
this.Status = Statuses.Missing;
this.FileName = null;
this.FileSize = null;
this.FilePath = null;
this.LastUpdated = now ?? DateTime.UtcNow;
Hash = null;
Status = Statuses.Missing;
FileName = null;
FileSize = null;
FilePath = null;
LastUpdated = now ?? DateTime.UtcNow;
}
}
}

View file

@ -5,32 +5,25 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("userartist")]
public partial class UserArtist : EntityBase
public class UserArtist : EntityBase
{
public Artist Artist { get; set; }
[Column("artistId")]
[Required]
public int ArtistId { get; set; }
[Column("artistId")] [Required] public int ArtistId { get; set; }
[Column("isDisliked")]
public bool? IsDisliked { get; set; }
[Column("isDisliked")] public bool? IsDisliked { get; set; }
[Column("isFavorite")]
public bool? IsFavorite { get; set; }
[Column("isFavorite")] public bool? IsFavorite { get; set; }
[Column("rating")]
public short Rating { get; set; }
[Column("rating")] public short Rating { get; set; }
public ApplicationUser User { get; set; }
[Column("userId")]
[Required]
public int UserId { get; set; }
[Column("userId")] [Required] public int UserId { get; set; }
public UserArtist()
{
this.Rating = 0;
Rating = 0;
}
}
}

View file

@ -1,36 +1,19 @@
using Roadie.Library.Identity;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
namespace Roadie.Library.Data
{
[Table("userQue")]
public class UserQue : EntityBase
{
[Column("isCurrent")] public bool? IsCurrent { get; set; }
[Column("position")] public long? Position { get; set; }
[Column("queSortOrder")] [Required] public short QueSortOrder { get; set; }
public Track Track { get; set; }
[Column("trackId")] [Required] public int TrackId { get; set; }
public ApplicationUser User { get; set; }
[Column("userId")]
[Required]
public int UserId { get; set; }
public Track Track { get; set; }
[Column("trackId")]
[Required]
public int TrackId { get; set; }
[Column("queSortOrder")]
[Required]
public short QueSortOrder { get; set; }
[Column("position")]
public long? Position { get; set; }
[Column("isCurrent")]
public bool? IsCurrent { get; set; }
[Column("userId")] [Required] public int UserId { get; set; }
}
}
}

View file

@ -5,32 +5,25 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("userrelease")]
public partial class UserRelease : EntityBase
public class UserRelease : EntityBase
{
[Column("isDisliked")]
public bool? IsDisliked { get; set; }
[Column("isDisliked")] public bool? IsDisliked { get; set; }
[Column("isFavorite")]
public bool? IsFavorite { get; set; }
[Column("isFavorite")] public bool? IsFavorite { get; set; }
[Column("rating")]
public short Rating { get; set; }
[Column("rating")] public short Rating { get; set; }
public Release Release { get; set; }
[Column("releaseId")]
[Required]
public int ReleaseId { get; set; }
[Column("releaseId")] [Required] public int ReleaseId { get; set; }
public ApplicationUser User { get; set; }
[Column("userId")]
[Required]
public int UserId { get; set; }
[Column("userId")] [Required] public int UserId { get; set; }
public UserRelease()
{
this.Rating = 0;
Rating = 0;
}
}
}

View file

@ -6,37 +6,29 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Data
{
[Table("usertrack")]
public partial class UserTrack : EntityBase
public class UserTrack : EntityBase
{
[Column("isDisliked")]
public bool? IsDisliked { get; set; }
[Column("isDisliked")] public bool? IsDisliked { get; set; }
[Column("isFavorite")]
public bool? IsFavorite { get; set; }
[Column("isFavorite")] public bool? IsFavorite { get; set; }
[Column("lastPlayed")]
public DateTime? LastPlayed { get; set; }
[Column("lastPlayed")] public DateTime? LastPlayed { get; set; }
[Column("playedCount")]
public int? PlayedCount { get; set; }
[Column("playedCount")] public int? PlayedCount { get; set; }
[Column("rating")]
public short Rating { get; set; }
[Column("rating")] public short Rating { get; set; }
public Track Track { get; set; }
[Column("trackId")]
[Required]
public int TrackId { get; set; }
[Column("trackId")] [Required] public int TrackId { get; set; }
public ApplicationUser User { get; set; }
[Column("userId")]
[Required]
public int UserId { get; set; }
[Column("userId")] [Required] public int UserId { get; set; }
public UserTrack()
{ }
{
}
public UserTrack(DateTime? now = null)
{

View file

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Encoding
{
@ -31,4 +29,4 @@ namespace Roadie.Library.Encoding
throw new NotImplementedException();
}
}
}
}

View file

@ -29,32 +29,34 @@ namespace Roadie.Library.Engines
{
public class ArtistLookupEngine : LookupEngineBase, IArtistLookupEngine
{
private List<int> _addedArtistIds = new List<int>();
private readonly List<int> _addedArtistIds = new List<int>();
public IEnumerable<int> AddedArtistIds
{
get
{
return this._addedArtistIds;
}
}
public IEnumerable<int> AddedArtistIds => _addedArtistIds;
public IArtistSearchEngine DiscogsArtistSearchEngine { get; }
public IArtistSearchEngine ITunesArtistSearchEngine { get; }
public IArtistSearchEngine LastFmArtistSearchEngine { get; }
public IArtistSearchEngine MusicBrainzArtistSearchEngine { get; }
public IArtistSearchEngine SpotifyArtistSearchEngine { get; }
public IArtistSearchEngine WikipediaArtistSearchEngine { get; }
public ArtistLookupEngine(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context, ICacheManager cacheManager, ILogger logger)
public ArtistLookupEngine(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context,
ICacheManager cacheManager, ILogger logger)
: base(configuration, httpEncoder, context, cacheManager, logger)
{
this.ITunesArtistSearchEngine = new ITunesSearchEngine(this.Configuration, this.CacheManager, this.Logger);
this.MusicBrainzArtistSearchEngine = new musicbrainz.MusicBrainzProvider(this.Configuration, this.CacheManager, this.Logger);
this.LastFmArtistSearchEngine = new lastfm.LastFmHelper(this.Configuration, this.CacheManager, this.Logger, context, httpEncoder);
this.SpotifyArtistSearchEngine = new spotify.SpotifyHelper(this.Configuration, this.CacheManager, this.Logger);
this.WikipediaArtistSearchEngine = new wikipedia.WikipediaHelper(this.Configuration, this.CacheManager, this.Logger, this.HttpEncoder);
this.DiscogsArtistSearchEngine = new discogs.DiscogsHelper(this.Configuration, this.CacheManager, this.Logger);
ITunesArtistSearchEngine = new ITunesSearchEngine(Configuration, CacheManager, Logger);
MusicBrainzArtistSearchEngine = new musicbrainz.MusicBrainzProvider(Configuration, CacheManager, Logger);
LastFmArtistSearchEngine =
new lastfm.LastFmHelper(Configuration, CacheManager, Logger, context, httpEncoder);
SpotifyArtistSearchEngine = new spotify.SpotifyHelper(Configuration, CacheManager, Logger);
WikipediaArtistSearchEngine =
new wikipedia.WikipediaHelper(Configuration, CacheManager, Logger, HttpEncoder);
DiscogsArtistSearchEngine = new discogs.DiscogsHelper(Configuration, CacheManager, Logger);
}
public async Task<OperationResult<Artist>> Add(Artist artist)
@ -66,7 +68,8 @@ namespace Roadie.Library.Engines
var ArtistGenreTables = artist.Genres;
var ArtistImages = artist.Images;
var now = DateTime.UtcNow;
artist.AlternateNames = artist.AlternateNames.AddToDelimitedList(new string[] { artist.Name.ToAlphanumericName() });
artist.AlternateNames =
artist.AlternateNames.AddToDelimitedList(new[] { artist.Name.ToAlphanumericName() });
artist.Genres = null;
artist.Images = null;
if (artist.Thumbnail == null && ArtistImages != null)
@ -78,31 +81,29 @@ namespace Roadie.Library.Engines
artist.Thumbnail = firstImageWithNotNullBytes.Bytes;
if (artist.Thumbnail != null)
{
artist.Thumbnail = ImageHelper.ResizeImage(artist.Thumbnail, this.Configuration.ThumbnailImageSize.Width, this.Configuration.ThumbnailImageSize.Height);
artist.Thumbnail = ImageHelper.ResizeImage(artist.Thumbnail,
Configuration.ThumbnailImageSize.Width, Configuration.ThumbnailImageSize.Height);
artist.Thumbnail = ImageHelper.ConvertToJpegFormat(artist.Thumbnail);
if (artist.Thumbnail.Length >= ImageHelper.MaximumThumbnailByteSize)
{
Logger.LogWarning($"Artist Thumbnail larger than maximum size after resizing to [{ this.Configuration.ThumbnailImageSize.Width }x{ this.Configuration.ThumbnailImageSize.Height}] Thumbnail Size [{ artist.Thumbnail.Length }]");
Logger.LogWarning(
$"Artist Thumbnail larger than maximum size after resizing to [{Configuration.ThumbnailImageSize.Width}x{Configuration.ThumbnailImageSize.Height}] Thumbnail Size [{artist.Thumbnail.Length}]");
artist.Thumbnail = null;
}
}
}
}
if (!artist.IsValid)
{
return new OperationResult<Artist>
{
Errors = new Exception[1] { new Exception("Artist is Invalid") }
};
}
var addArtistResult = this.DbContext.Artists.Add(artist);
int inserted = 0;
inserted = await this.DbContext.SaveChangesAsync();
this._addedArtistIds.Add(artist.Id);
if (artist.Id < 1 && addArtistResult.Entity.Id > 0)
{
artist.Id = addArtistResult.Entity.Id;
}
var addArtistResult = DbContext.Artists.Add(artist);
var inserted = 0;
inserted = await DbContext.SaveChangesAsync();
_addedArtistIds.Add(artist.Id);
if (artist.Id < 1 && addArtistResult.Entity.Id > 0) artist.Id = addArtistResult.Entity.Id;
if (inserted > 0 && artist.Id > 0)
{
if (ArtistGenreTables != null && ArtistGenreTables.Any(x => x.GenreId == null))
@ -112,48 +113,51 @@ namespace Roadie.Library.Engines
{
foreach (var ArtistGenreTable in ArtistGenreTables)
{
var genre = this.DbContext.Genres.FirstOrDefault(x => x.Name.ToLower().Trim() == ArtistGenreTable.Genre.Name.ToLower().Trim());
var genre = DbContext.Genres.FirstOrDefault(x =>
x.Name.ToLower().Trim() == ArtistGenreTable.Genre.Name.ToLower().Trim());
if (genre == null)
{
genre = new Genre
{
Name = ArtistGenreTable.Genre.Name
};
this.DbContext.Genres.Add(genre);
await this.DbContext.SaveChangesAsync();
DbContext.Genres.Add(genre);
await DbContext.SaveChangesAsync();
}
if (genre != null && genre.Id > 0)
{
await this.DbContext.Database.ExecuteSqlCommandAsync("INSERT INTO `artistGenreTable` (artistId, genreId) VALUES ({0}, {1});", artist.Id, genre.Id);
}
await DbContext.Database.ExecuteSqlCommandAsync(
"INSERT INTO `artistGenreTable` (artistId, genreId) VALUES ({0}, {1});",
artist.Id, genre.Id);
}
}
catch (Exception ex)
{
this.Logger.LogError(ex, "Sql [" + sql + "] Exception [" + ex.Serialize() + "]");
Logger.LogError(ex, "Sql [" + sql + "] Exception [" + ex.Serialize() + "]");
}
}
if (ArtistImages != null && ArtistImages.Any(x => x.Status == Statuses.New))
{
foreach (var ArtistImage in ArtistImages)
{
this.DbContext.Images.Add(new Image
DbContext.Images.Add(new Image
{
ArtistId = artist.Id,
Url = ArtistImage.Url,
Signature = ArtistImage.Signature,
Bytes = ArtistImage.Bytes
});
}
inserted = await this.DbContext.SaveChangesAsync();
inserted = await DbContext.SaveChangesAsync();
}
this.Logger.LogInformation("Added New Artist: [{0}]", artist.ToString());
Logger.LogInformation("Added New Artist: [{0}]", artist.ToString());
}
}
catch (Exception ex)
{
this.Logger.LogError(ex, ex.Serialize());
Logger.LogError(ex, ex.Serialize());
}
return new OperationResult<Artist>
{
IsSuccess = artist.Id > 0,
@ -163,43 +167,41 @@ namespace Roadie.Library.Engines
public Artist DatabaseQueryForArtistName(string name, string sortName = null)
{
if (string.IsNullOrEmpty(name))
{
return null;
}
if (string.IsNullOrEmpty(name)) return null;
try
{
var searchName = name.NormalizeName();
var searchSortName = !string.IsNullOrEmpty(sortName) ? sortName.NormalizeName().ToLower() : searchName;
var specialSearchName = name.ToAlphanumericName();
var searchNameStart = $"{ searchName }|";
var searchNameIn = $"|{ searchName }|";
var searchNameEnd = $"|{ searchName }";
var searchNameStart = $"{searchName}|";
var searchNameIn = $"|{searchName}|";
var searchNameEnd = $"|{searchName}";
var specialSearchNameStart = $"{ specialSearchName }|";
var specialSearchNameIn = $"|{ specialSearchName }|";
var specialSearchNameEnd = $"|{ specialSearchName }";
var specialSearchNameStart = $"{specialSearchName}|";
var specialSearchNameIn = $"|{specialSearchName}|";
var specialSearchNameEnd = $"|{specialSearchName}";
return (from a in this.DbContext.Artists
where (a.Name == searchName ||
a.Name == specialSearchName ||
a.SortName == searchName ||
a.SortName == searchSortName ||
a.SortName == specialSearchName ||
a.AlternateNames.StartsWith(searchNameStart) ||
a.AlternateNames.Contains(searchNameIn) ||
a.AlternateNames.EndsWith(searchNameEnd) ||
a.AlternateNames.StartsWith(specialSearchNameStart) ||
a.AlternateNames.Contains(specialSearchNameIn) ||
a.AlternateNames.EndsWith(specialSearchNameEnd))
return (from a in DbContext.Artists
where a.Name == searchName ||
a.Name == specialSearchName ||
a.SortName == searchName ||
a.SortName == searchSortName ||
a.SortName == specialSearchName ||
a.AlternateNames.StartsWith(searchNameStart) ||
a.AlternateNames.Contains(searchNameIn) ||
a.AlternateNames.EndsWith(searchNameEnd) ||
a.AlternateNames.StartsWith(specialSearchNameStart) ||
a.AlternateNames.Contains(specialSearchNameIn) ||
a.AlternateNames.EndsWith(specialSearchNameEnd)
select a
).FirstOrDefault();
).FirstOrDefault();
}
catch (Exception ex)
{
this.Logger.LogError(ex, ex.Serialize());
Logger.LogError(ex, ex.Serialize());
}
return null;
}
@ -210,9 +212,9 @@ namespace Roadie.Library.Engines
var sw = new Stopwatch();
sw.Start();
var artistName = metaData.Artist ?? metaData.TrackArtist;
var cacheRegion = (new Artist { Name = artistName }).CacheRegion;
var cacheRegion = new Artist { Name = artistName }.CacheRegion;
var cacheKey = string.Format("urn:artist_by_name:{0}", artistName);
var resultInCache = this.CacheManager.Get<Artist>(cacheKey, cacheRegion);
var resultInCache = CacheManager.Get<Artist>(cacheKey, cacheRegion);
if (resultInCache != null)
{
sw.Stop();
@ -223,56 +225,63 @@ namespace Roadie.Library.Engines
Data = resultInCache
};
}
var artist = this.DatabaseQueryForArtistName(artistName);
var artist = DatabaseQueryForArtistName(artistName);
sw.Stop();
if (artist == null || !artist.IsValid)
{
this.Logger.LogInformation("ArtistLookupEngine: Artist Not Found By Name [{0}]", artistName);
Logger.LogInformation("ArtistLookupEngine: Artist Not Found By Name [{0}]", artistName);
if (doFindIfNotInDatabase)
{
OperationResult<Artist> artistSearch = null;
// See if roadie.json file exists in the metadata files folder, if so then use artist data from that
var releaseRoadieDataFilename = Path.Combine(Path.GetDirectoryName(metaData.Filename), "roadie.artist.json");
var releaseRoadieDataFilename = Path.Combine(Path.GetDirectoryName(metaData.Filename),
"roadie.artist.json");
if (File.Exists(releaseRoadieDataFilename))
{
artist = JsonConvert.DeserializeObject<Artist>(File.ReadAllText(releaseRoadieDataFilename));
var addResult = await this.Add(artist);
var addResult = await Add(artist);
if (!addResult.IsSuccess)
{
sw.Stop();
this.Logger.LogWarning("Unable To Add Artist For Roadie Data File [{0}]", releaseRoadieDataFilename);
Logger.LogWarning("Unable To Add Artist For Roadie Data File [{0}]",
releaseRoadieDataFilename);
return new OperationResult<Artist>
{
OperationTime = sw.ElapsedMilliseconds,
Errors = addResult.Errors
};
}
artist = addResult.Data;
}
else
{
try
{
artistSearch = await this.PerformMetaDataProvidersArtistSearch(metaData);
artistSearch = await PerformMetaDataProvidersArtistSearch(metaData);
if (artistSearch.IsSuccess)
{
artist = artistSearch.Data;
// See if Artist already exist with either Name or Sort Name
var alreadyExists = this.DatabaseQueryForArtistName(artistSearch.Data.Name, artistSearch.Data.SortNameValue);
var alreadyExists = DatabaseQueryForArtistName(artistSearch.Data.Name,
artistSearch.Data.SortNameValue);
if (alreadyExists == null || !alreadyExists.IsValid)
{
var addResult = await this.Add(artist);
var addResult = await Add(artist);
if (!addResult.IsSuccess)
{
sw.Stop();
this.Logger.LogWarning("Unable To Add Artist For MetaData [{0}]", metaData.ToString());
Logger.LogWarning("Unable To Add Artist For MetaData [{0}]",
metaData.ToString());
return new OperationResult<Artist>
{
OperationTime = sw.ElapsedMilliseconds,
Errors = addResult.Errors
};
}
artist = addResult.Data;
}
else
@ -283,15 +292,13 @@ namespace Roadie.Library.Engines
}
catch (Exception ex)
{
this.Logger.LogError(ex, ex.Serialize());
Logger.LogError(ex, ex.Serialize());
}
}
}
}
if (artist != null && artist.IsValid)
{
this.CacheManager.Add(cacheKey, artist);
}
if (artist != null && artist.IsValid) CacheManager.Add(cacheKey, artist);
return new OperationResult<Artist>
{
IsSuccess = artist != null,
@ -301,15 +308,17 @@ namespace Roadie.Library.Engines
}
catch (Exception ex)
{
this.Logger.LogError(ex, ex.Serialize());
Logger.LogError(ex, ex.Serialize());
}
return new OperationResult<Artist>();
}
public async Task<OperationResult<Artist>> PerformMetaDataProvidersArtistSearch(AudioMetaData metaData)
{
SimpleContract.Requires<ArgumentNullException>(metaData != null, "Invalid MetaData");
SimpleContract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(metaData.Artist), "Invalid MetaData, Missing Artist");
SimpleContract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(metaData.Artist),
"Invalid MetaData, Missing Artist");
var sw = new Stopwatch();
sw.Start();
@ -324,36 +333,19 @@ namespace Roadie.Library.Engines
try
{
if (this.ITunesArtistSearchEngine.IsEnabled)
if (ITunesArtistSearchEngine.IsEnabled)
{
var iTunesResult = await this.ITunesArtistSearchEngine.PerformArtistSearch(artistName, 1);
var iTunesResult = await ITunesArtistSearchEngine.PerformArtistSearch(artistName, 1);
if (iTunesResult.IsSuccess)
{
var i = iTunesResult.Data.First();
if (i.AlternateNames != null)
{
result.AlternateNames = result.AlternateNames.AddToDelimitedList(i.AlternateNames);
}
if (i.Tags != null)
{
result.Tags = result.Tags.AddToDelimitedList(i.Tags);
}
if (i.Urls != null)
{
result.URLs = result.URLs.AddToDelimitedList(i.Urls);
}
if (i.ISNIs != null)
{
result.ISNI = result.ISNI.AddToDelimitedList(i.ISNIs);
}
if (i.ImageUrls != null)
{
artistImageUrls.AddRange(i.ImageUrls);
}
if (i.ArtistGenres != null)
{
artistGenres.AddRange(i.ArtistGenres);
}
if (i.Tags != null) result.Tags = result.Tags.AddToDelimitedList(i.Tags);
if (i.Urls != null) result.URLs = result.URLs.AddToDelimitedList(i.Urls);
if (i.ISNIs != null) result.ISNI = result.ISNI.AddToDelimitedList(i.ISNIs);
if (i.ImageUrls != null) artistImageUrls.AddRange(i.ImageUrls);
if (i.ArtistGenres != null) artistGenres.AddRange(i.ArtistGenres);
result.CopyTo(new Artist
{
EndDate = i.EndDate,
@ -363,56 +355,39 @@ namespace Roadie.Library.Engines
BeginDate = i.BeginDate,
Name = result.Name ?? i.ArtistName,
SortName = result.SortName ?? i.ArtistSortName,
Thumbnail = i.ArtistThumbnailUrl != null ? WebHelper.BytesForImageUrl(i.ArtistThumbnailUrl) : null,
Thumbnail = i.ArtistThumbnailUrl != null
? WebHelper.BytesForImageUrl(i.ArtistThumbnailUrl)
: null,
ArtistType = result.ArtistType ?? i.ArtistType
});
}
if (iTunesResult.Errors != null)
{
resultsExceptions.AddRange(iTunesResult.Errors);
}
if (iTunesResult.Errors != null) resultsExceptions.AddRange(iTunesResult.Errors);
}
}
catch (Exception ex)
{
this.Logger.LogError(ex, "iTunesArtistSearch: " + ex.Serialize());
Logger.LogError(ex, "iTunesArtistSearch: " + ex.Serialize());
}
try
{
if (this.MusicBrainzArtistSearchEngine.IsEnabled)
if (MusicBrainzArtistSearchEngine.IsEnabled)
{
var mbResult = await this.MusicBrainzArtistSearchEngine.PerformArtistSearch(result.Name, 1);
var mbResult = await MusicBrainzArtistSearchEngine.PerformArtistSearch(result.Name, 1);
if (mbResult.IsSuccess)
{
var mb = mbResult.Data.First();
if (mb.AlternateNames != null)
{
result.AlternateNames = result.AlternateNames.AddToDelimitedList(mb.AlternateNames);
}
if (mb.Tags != null)
{
result.Tags = result.Tags.AddToDelimitedList(mb.Tags);
}
if (mb.Urls != null)
{
result.URLs = result.URLs.AddToDelimitedList(mb.Urls);
}
if (mb.ISNIs != null)
{
result.ISNI = result.ISNI.AddToDelimitedList(mb.ISNIs);
}
if (mb.ImageUrls != null)
{
artistImageUrls.AddRange(mb.ImageUrls);
}
if (mb.ArtistGenres != null)
{
artistGenres.AddRange(mb.ArtistGenres);
}
if (!string.IsNullOrEmpty(mb.ArtistName) && !mb.ArtistName.Equals(result.Name, StringComparison.OrdinalIgnoreCase))
{
result.AlternateNames.AddToDelimitedList(new string[] { mb.ArtistName });
}
if (mb.Tags != null) result.Tags = result.Tags.AddToDelimitedList(mb.Tags);
if (mb.Urls != null) result.URLs = result.URLs.AddToDelimitedList(mb.Urls);
if (mb.ISNIs != null) result.ISNI = result.ISNI.AddToDelimitedList(mb.ISNIs);
if (mb.ImageUrls != null) artistImageUrls.AddRange(mb.ImageUrls);
if (mb.ArtistGenres != null) artistGenres.AddRange(mb.ArtistGenres);
if (!string.IsNullOrEmpty(mb.ArtistName) &&
!mb.ArtistName.Equals(result.Name, StringComparison.OrdinalIgnoreCase))
result.AlternateNames.AddToDelimitedList(new[] { mb.ArtistName });
result.CopyTo(new Artist
{
EndDate = mb.EndDate,
@ -422,185 +397,147 @@ namespace Roadie.Library.Engines
BeginDate = mb.BeginDate,
Name = result.Name ?? mb.ArtistName,
SortName = result.SortName ?? mb.ArtistSortName,
Thumbnail = mb.ArtistThumbnailUrl != null ? WebHelper.BytesForImageUrl(mb.ArtistThumbnailUrl) : null,
Thumbnail = mb.ArtistThumbnailUrl != null
? WebHelper.BytesForImageUrl(mb.ArtistThumbnailUrl)
: null,
ArtistType = mb.ArtistType
});
}
if (mbResult.Errors != null)
{
resultsExceptions.AddRange(mbResult.Errors);
}
if (mbResult.Errors != null) resultsExceptions.AddRange(mbResult.Errors);
}
}
catch (Exception ex)
{
this.Logger.LogError(ex, "MusicBrainzArtistSearch: " + ex.Serialize());
Logger.LogError(ex, "MusicBrainzArtistSearch: " + ex.Serialize());
}
try
{
if (this.LastFmArtistSearchEngine.IsEnabled)
if (LastFmArtistSearchEngine.IsEnabled)
{
var lastFmResult = await this.LastFmArtistSearchEngine.PerformArtistSearch(result.Name, 1);
var lastFmResult = await LastFmArtistSearchEngine.PerformArtistSearch(result.Name, 1);
if (lastFmResult.IsSuccess)
{
var l = lastFmResult.Data.First();
if (l.AlternateNames != null)
{
result.AlternateNames = result.AlternateNames.AddToDelimitedList(l.AlternateNames);
}
if (l.Tags != null)
{
result.Tags = result.Tags.AddToDelimitedList(l.Tags);
}
if (l.Urls != null)
{
result.URLs = result.URLs.AddToDelimitedList(l.Urls);
}
if (l.ISNIs != null)
{
result.ISNI = result.ISNI.AddToDelimitedList(l.ISNIs);
}
if (l.ImageUrls != null)
{
artistImageUrls.AddRange(l.ImageUrls);
}
if (l.ArtistGenres != null)
{
artistGenres.AddRange(l.ArtistGenres);
}
if (!string.IsNullOrEmpty(l.ArtistName) && !l.ArtistName.Equals(result.Name, StringComparison.OrdinalIgnoreCase))
{
result.AlternateNames.AddToDelimitedList(new string[] { l.ArtistName });
}
if (l.Tags != null) result.Tags = result.Tags.AddToDelimitedList(l.Tags);
if (l.Urls != null) result.URLs = result.URLs.AddToDelimitedList(l.Urls);
if (l.ISNIs != null) result.ISNI = result.ISNI.AddToDelimitedList(l.ISNIs);
if (l.ImageUrls != null) artistImageUrls.AddRange(l.ImageUrls);
if (l.ArtistGenres != null) artistGenres.AddRange(l.ArtistGenres);
if (!string.IsNullOrEmpty(l.ArtistName) &&
!l.ArtistName.Equals(result.Name, StringComparison.OrdinalIgnoreCase))
result.AlternateNames.AddToDelimitedList(new[] { l.ArtistName });
result.CopyTo(new Artist
{
EndDate = l.EndDate,
BioContext = this.HttpEncoder.HtmlEncode(l.Bio),
Profile = this.HttpEncoder.HtmlEncode(l.Profile),
BioContext = HttpEncoder.HtmlEncode(l.Bio),
Profile = HttpEncoder.HtmlEncode(l.Profile),
MusicBrainzId = l.MusicBrainzId,
BeginDate = l.BeginDate,
Name = result.Name ?? l.ArtistName,
SortName = result.SortName ?? l.ArtistSortName,
Thumbnail = l.ArtistThumbnailUrl != null ? WebHelper.BytesForImageUrl(l.ArtistThumbnailUrl) : null,
Thumbnail = l.ArtistThumbnailUrl != null
? WebHelper.BytesForImageUrl(l.ArtistThumbnailUrl)
: null,
ArtistType = result.ArtistType ?? l.ArtistType
});
}
if (lastFmResult.Errors != null)
{
resultsExceptions.AddRange(lastFmResult.Errors);
}
if (lastFmResult.Errors != null) resultsExceptions.AddRange(lastFmResult.Errors);
}
}
catch (Exception ex)
{
this.Logger.LogError(ex, "LastFMArtistSearch: " + ex.Serialize());
Logger.LogError(ex, "LastFMArtistSearch: " + ex.Serialize());
}
try
{
if (this.SpotifyArtistSearchEngine.IsEnabled)
if (SpotifyArtistSearchEngine.IsEnabled)
{
var spotifyResult = await this.SpotifyArtistSearchEngine.PerformArtistSearch(result.Name, 1);
var spotifyResult = await SpotifyArtistSearchEngine.PerformArtistSearch(result.Name, 1);
if (spotifyResult.IsSuccess)
{
var s = spotifyResult.Data.First();
if (s.Tags != null)
{
result.Tags = result.Tags.AddToDelimitedList(s.Tags);
}
if (s.Urls != null)
{
result.URLs = result.URLs.AddToDelimitedList(s.Urls);
}
if (s.ImageUrls != null)
{
artistImageUrls.AddRange(s.ImageUrls);
}
if (s.ArtistGenres != null)
{
artistGenres.AddRange(s.ArtistGenres);
}
if (!string.IsNullOrEmpty(s.ArtistName) && !s.ArtistName.Equals(result.Name, StringComparison.OrdinalIgnoreCase))
{
result.AlternateNames.AddToDelimitedList(new string[] { s.ArtistName });
}
if (s.Tags != null) result.Tags = result.Tags.AddToDelimitedList(s.Tags);
if (s.Urls != null) result.URLs = result.URLs.AddToDelimitedList(s.Urls);
if (s.ImageUrls != null) artistImageUrls.AddRange(s.ImageUrls);
if (s.ArtistGenres != null) artistGenres.AddRange(s.ArtistGenres);
if (!string.IsNullOrEmpty(s.ArtistName) &&
!s.ArtistName.Equals(result.Name, StringComparison.OrdinalIgnoreCase))
result.AlternateNames.AddToDelimitedList(new[] { s.ArtistName });
result.CopyTo(new Artist
{
EndDate = s.EndDate,
BioContext = s.Bio,
Profile = this.HttpEncoder.HtmlEncode(s.Profile),
Profile = HttpEncoder.HtmlEncode(s.Profile),
MusicBrainzId = s.MusicBrainzId,
BeginDate = s.BeginDate,
Name = result.Name ?? s.ArtistName,
SortName = result.SortName ?? s.ArtistSortName,
Thumbnail = s.ArtistThumbnailUrl != null ? WebHelper.BytesForImageUrl(s.ArtistThumbnailUrl) : null,
Thumbnail = s.ArtistThumbnailUrl != null
? WebHelper.BytesForImageUrl(s.ArtistThumbnailUrl)
: null,
ArtistType = result.ArtistType ?? s.ArtistType
});
}
if (spotifyResult.Errors != null)
{
resultsExceptions.AddRange(spotifyResult.Errors);
}
if (spotifyResult.Errors != null) resultsExceptions.AddRange(spotifyResult.Errors);
}
}
catch (Exception ex)
{
this.Logger.LogError(ex, "SpotifyArtistSearch: " + ex.Serialize());
Logger.LogError(ex, "SpotifyArtistSearch: " + ex.Serialize());
}
try
{
if (this.DiscogsArtistSearchEngine.IsEnabled)
if (DiscogsArtistSearchEngine.IsEnabled)
{
var discogsResult = await this.DiscogsArtistSearchEngine.PerformArtistSearch(result.Name, 1);
var discogsResult = await DiscogsArtistSearchEngine.PerformArtistSearch(result.Name, 1);
if (discogsResult.IsSuccess)
{
var d = discogsResult.Data.First();
if (d.Urls != null)
{
result.URLs = result.URLs.AddToDelimitedList(d.Urls);
}
if (d.ImageUrls != null)
{
artistImageUrls.AddRange(d.ImageUrls);
}
if (d.Urls != null) result.URLs = result.URLs.AddToDelimitedList(d.Urls);
if (d.ImageUrls != null) artistImageUrls.AddRange(d.ImageUrls);
if (d.AlternateNames != null)
{
result.AlternateNames = result.AlternateNames.AddToDelimitedList(d.AlternateNames);
}
if (!string.IsNullOrEmpty(d.ArtistName) && !d.ArtistName.Equals(result.Name, StringComparison.OrdinalIgnoreCase))
{
result.AlternateNames.AddToDelimitedList(new string[] { d.ArtistName });
}
if (!string.IsNullOrEmpty(d.ArtistName) &&
!d.ArtistName.Equals(result.Name, StringComparison.OrdinalIgnoreCase))
result.AlternateNames.AddToDelimitedList(new[] { d.ArtistName });
result.CopyTo(new Artist
{
Profile = this.HttpEncoder.HtmlEncode(d.Profile),
Profile = HttpEncoder.HtmlEncode(d.Profile),
DiscogsId = d.DiscogsId,
Name = result.Name ?? d.ArtistName,
RealName = result.RealName ?? d.ArtistRealName,
Thumbnail = d.ArtistThumbnailUrl != null ? WebHelper.BytesForImageUrl(d.ArtistThumbnailUrl) : null,
Thumbnail = d.ArtistThumbnailUrl != null
? WebHelper.BytesForImageUrl(d.ArtistThumbnailUrl)
: null,
ArtistType = result.ArtistType ?? d.ArtistType
});
}
if (discogsResult.Errors != null)
{
resultsExceptions.AddRange(discogsResult.Errors);
}
if (discogsResult.Errors != null) resultsExceptions.AddRange(discogsResult.Errors);
}
}
catch (Exception ex)
{
this.Logger.LogError(ex, "DiscogsArtistSearch: " + ex.Serialize());
Logger.LogError(ex, "DiscogsArtistSearch: " + ex.Serialize());
}
try
{
if (this.WikipediaArtistSearchEngine.IsEnabled)
if (WikipediaArtistSearchEngine.IsEnabled)
{
var wikiName = result.Name;
// Help get better results for bands with proper nouns (e.g. "Poison")
if (!result.ArtistType.Equals("Person", StringComparison.OrdinalIgnoreCase))
{
wikiName = wikiName + " band";
}
var wikipediaResult = await this.WikipediaArtistSearchEngine.PerformArtistSearch(wikiName, 1);
var wikipediaResult = await WikipediaArtistSearchEngine.PerformArtistSearch(wikiName, 1);
if (wikipediaResult != null)
{
if (wikipediaResult.IsSuccess)
@ -608,56 +545,51 @@ namespace Roadie.Library.Engines
var w = wikipediaResult.Data.First();
result.CopyTo(new Artist
{
BioContext = this.HttpEncoder.HtmlEncode(w.Bio)
BioContext = HttpEncoder.HtmlEncode(w.Bio)
});
}
if (wikipediaResult.Errors != null)
{
resultsExceptions.AddRange(wikipediaResult.Errors);
}
if (wikipediaResult.Errors != null) resultsExceptions.AddRange(wikipediaResult.Errors);
}
}
}
catch (Exception ex)
{
this.Logger.LogError(ex, "WikipediaArtistSearch: " + ex.Serialize());
Logger.LogError(ex, "WikipediaArtistSearch: " + ex.Serialize());
}
try
{
if (result.AlternateNames != null)
{
result.AlternateNames = string.Join("|", result.AlternateNames.ToListFromDelimited().Distinct().OrderBy(x => x));
}
result.AlternateNames = string.Join("|",
result.AlternateNames.ToListFromDelimited().Distinct().OrderBy(x => x));
if (result.URLs != null)
{
result.URLs = string.Join("|", result.URLs.ToListFromDelimited().Distinct().OrderBy(x => x));
}
if (result.Tags != null)
{
result.Tags = string.Join("|", result.Tags.ToListFromDelimited().Distinct().OrderBy(x => x));
}
if (artistGenres.Any())
{
var genreInfos = (from ag in artistGenres
join g in this.DbContext.Genres on ag equals g.Name into gg
from g in gg.DefaultIfEmpty()
select new
{
newGenre = ag.ToTitleCase(),
existingGenre = g
});
var genreInfos = from ag in artistGenres
join g in DbContext.Genres on ag equals g.Name into gg
from g in gg.DefaultIfEmpty()
select new
{
newGenre = ag.ToTitleCase(),
existingGenre = g
};
result.Genres = new List<ArtistGenre>();
foreach (var genreInfo in genreInfos)
{
result.Genres.Add(new ArtistGenre
{
Genre = genreInfo.existingGenre != null ? genreInfo.existingGenre : new Genre
{
Name = genreInfo.newGenre
}
Genre = genreInfo.existingGenre != null
? genreInfo.existingGenre
: new Genre
{
Name = genreInfo.newGenre
}
});
}
}
if (artistImageUrls.Any())
{
var imageBag = new ConcurrentBag<Image>();
@ -666,25 +598,26 @@ namespace Roadie.Library.Engines
imageBag.Add(await WebHelper.GetImageFromUrlAsync(url));
});
await Task.WhenAll(i);
result.Images = imageBag.Where(x => x != null && x.Bytes != null).GroupBy(x => x.Signature).Select(x => x.First()).Take(this.Configuration.Processing.MaximumArtistImagesToAdd).ToList();
result.Images = imageBag.Where(x => x != null && x.Bytes != null).GroupBy(x => x.Signature)
.Select(x => x.First()).Take(Configuration.Processing.MaximumArtistImagesToAdd).ToList();
if (result.Thumbnail == null && result.Images != null)
{
result.Thumbnail = result.Images.First().Bytes;
}
}
if (result.Thumbnail != null)
{
result.Thumbnail = ImageHelper.ResizeImage(result.Thumbnail, this.Configuration.ThumbnailImageSize.Width, this.Configuration.ThumbnailImageSize.Height);
result.Thumbnail = ImageHelper.ResizeImage(result.Thumbnail, Configuration.ThumbnailImageSize.Width,
Configuration.ThumbnailImageSize.Height);
result.Thumbnail = ImageHelper.ConvertToJpegFormat(result.Thumbnail);
}
}
catch (Exception ex)
{
this.Logger.LogError(ex, "CombiningResults: " + ex.Serialize());
Logger.LogError(ex, "CombiningResults: " + ex.Serialize());
}
result.SortName = result.SortName.ToTitleCase();
if (!string.IsNullOrEmpty(result.ArtistType))
{
switch (result.ArtistType.ToLower().Replace('-', ' '))
{
case "artist":
@ -725,11 +658,11 @@ namespace Roadie.Library.Engines
break;
default:
this.Logger.LogWarning(string.Format("Unknown Artist Type [{0}]", result.ArtistType));
Logger.LogWarning(string.Format("Unknown Artist Type [{0}]", result.ArtistType));
result.ArtistType = "Other";
break;
}
}
sw.Stop();
return new OperationResult<Artist>
{

View file

@ -1,9 +1,8 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Roadie.Library.Data;
using Roadie.Library.Data;
using Roadie.Library.MetaData.Audio;
using Roadie.Library.SearchEngines.Imaging;
using Roadie.Library.SearchEngines.MetaData;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Roadie.Library.Engines
{
@ -18,8 +17,11 @@ namespace Roadie.Library.Engines
IArtistSearchEngine WikipediaArtistSearchEngine { get; }
Task<OperationResult<Artist>> Add(Artist artist);
Task<OperationResult<Artist>> GetByName(AudioMetaData metaData, bool doFindIfNotInDatabase = false);
Task<OperationResult<Artist>> PerformMetaDataProvidersArtistSearch(AudioMetaData metaData);
Artist DatabaseQueryForArtistName(string name, string sortName = null);
Task<OperationResult<Artist>> GetByName(AudioMetaData metaData, bool doFindIfNotInDatabase = false);
Task<OperationResult<Artist>> PerformMetaDataProvidersArtistSearch(AudioMetaData metaData);
}
}

View file

@ -1,12 +1,14 @@
using System.Threading.Tasks;
using Roadie.Library.Data;
using Roadie.Library.Data;
using System.Threading.Tasks;
namespace Roadie.Library.Engines
{
public interface ILabelLookupEngine
{
Task<OperationResult<Label>> Add(Label label);
Task<OperationResult<Label>> GetByName(string LabelName, bool doFindIfNotInDatabase = false);
Task<OperationResult<Label>> PerformMetaDataProvidersLabelSearch(string LabelName);
}
}

View file

@ -1,4 +1,5 @@
using Roadie.Library.MetaData.Audio;
using Roadie.Library.Data;
using Roadie.Library.MetaData.Audio;
using Roadie.Library.SearchEngines.MetaData;
using System.Collections.Generic;
using System.Threading.Tasks;
@ -17,8 +18,12 @@ namespace Roadie.Library.Engines
IReleaseSearchEngine SpotifyReleaseSearchEngine { get; }
IReleaseSearchEngine WikipediaReleaseSearchEngine { get; }
Task<OperationResult<Data.Release>> GetByName(Data.Artist artist, AudioMetaData metaData, bool doFindIfNotInDatabase = false, bool doAddTracksInDatabase = false, int? submissionId = null);
Task<OperationResult<Data.Release>> Add(Data.Release release, bool doAddTracksInDatabase = false);
Task<OperationResult<Data.Release>> PerformMetaDataProvidersReleaseSearch(AudioMetaData metaData, string artistFolder = null, int? submissionId = null);
Task<OperationResult<Release>> Add(Release release, bool doAddTracksInDatabase = false);
Task<OperationResult<Release>> GetByName(Artist artist, AudioMetaData metaData,
bool doFindIfNotInDatabase = false, bool doAddTracksInDatabase = false, int? submissionId = null);
Task<OperationResult<Release>> PerformMetaDataProvidersReleaseSearch(AudioMetaData metaData,
string artistFolder = null, int? submissionId = null);
}
}

View file

@ -1,6 +1,4 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using MySql.Data.MySqlClient;
using Microsoft.Extensions.Logging;
using Roadie.Library.Caching;
using Roadie.Library.Configuration;
using Roadie.Library.Data;
@ -21,10 +19,11 @@ namespace Roadie.Library.Engines
{
private ILabelSearchEngine DiscogsLabelSearchEngine { get; }
public LabelLookupEngine(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context, ICacheManager cacheManager, ILogger logger)
public LabelLookupEngine(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context,
ICacheManager cacheManager, ILogger logger)
: base(configuration, httpEncoder, context, cacheManager, logger)
{
this.DiscogsLabelSearchEngine = new discogs.DiscogsHelper(this.Configuration, this.CacheManager, this.Logger);
DiscogsLabelSearchEngine = new discogs.DiscogsHelper(Configuration, CacheManager, Logger);
}
public async Task<OperationResult<Label>> Add(Label label)
@ -34,29 +33,28 @@ namespace Roadie.Library.Engines
try
{
var now = DateTime.UtcNow;
label.AlternateNames = label.AlternateNames.AddToDelimitedList(new string[] { label.Name.ToAlphanumericName() });
label.AlternateNames = label.AlternateNames.AddToDelimitedList(new[] { label.Name.ToAlphanumericName() });
if (!label.IsValid)
{
return new OperationResult<Label>
{
Errors = new Exception[1] { new Exception("Label is Invalid") }
};
}
this.DbContext.Labels.Add(label);
int inserted = 0;
DbContext.Labels.Add(label);
var inserted = 0;
try
{
inserted = await this.DbContext.SaveChangesAsync();
inserted = await DbContext.SaveChangesAsync();
}
catch (Exception ex)
{
this.Logger.LogError(ex);
Logger.LogError(ex);
}
}
catch (Exception ex)
{
this.Logger.LogError(ex);
Logger.LogError(ex);
}
return new OperationResult<Label>
{
IsSuccess = label.Id > 0,
@ -70,9 +68,9 @@ namespace Roadie.Library.Engines
{
var sw = new Stopwatch();
sw.Start();
var cacheRegion = (new Label { Name = labelName }).CacheRegion;
var cacheRegion = new Label { Name = labelName }.CacheRegion;
var cacheKey = string.Format("urn:Label_by_name:{0}", labelName);
var resultInCache = this.CacheManager.Get<Label>(cacheKey, cacheRegion);
var resultInCache = CacheManager.Get<Label>(cacheKey, cacheRegion);
if (resultInCache != null)
{
sw.Stop();
@ -83,34 +81,36 @@ namespace Roadie.Library.Engines
Data = resultInCache
};
}
var searchName = labelName.NormalizeName();
var specialSearchName = labelName.ToAlphanumericName();
var label = (from l in this.DbContext.Labels
where (l.Name.Contains(searchName) ||
var label = (from l in DbContext.Labels
where l.Name.Contains(searchName) ||
l.SortName.Contains(searchName) ||
l.AlternateNames.Contains(searchName) ||
l.AlternateNames.Contains(specialSearchName))
select l
).FirstOrDefault();
l.AlternateNames.Contains(specialSearchName)
select l
).FirstOrDefault();
sw.Stop();
if (label == null || !label.IsValid)
{
this.Logger.LogInformation("LabelFactory: Label Not Found By Name [{0}]", labelName);
Logger.LogInformation("LabelFactory: Label Not Found By Name [{0}]", labelName);
if (doFindIfNotInDatabase)
{
OperationResult<Label> LabelSearch = null;
try
{
LabelSearch = await this.PerformMetaDataProvidersLabelSearch(labelName);
LabelSearch = await PerformMetaDataProvidersLabelSearch(labelName);
}
catch (Exception ex)
{
this.Logger.LogError(ex);
Logger.LogError(ex);
}
if (LabelSearch.IsSuccess)
{
label = LabelSearch.Data;
var addResult = await this.Add(label);
var addResult = await Add(label);
if (!addResult.IsSuccess)
{
sw.Stop();
@ -125,8 +125,9 @@ namespace Roadie.Library.Engines
}
else
{
this.CacheManager.Add(cacheKey, label);
CacheManager.Add(cacheKey, label);
}
return new OperationResult<Label>
{
IsSuccess = label != null,
@ -136,8 +137,9 @@ namespace Roadie.Library.Engines
}
catch (Exception ex)
{
this.Logger.LogError(ex);
Logger.LogError(ex);
}
return new OperationResult<Label>();
}
@ -153,36 +155,28 @@ namespace Roadie.Library.Engines
};
var resultsExceptions = new List<Exception>();
if (this.DiscogsLabelSearchEngine.IsEnabled)
if (DiscogsLabelSearchEngine.IsEnabled)
{
var discogsResult = await this.DiscogsLabelSearchEngine.PerformLabelSearch(result.Name, 1);
var discogsResult = await DiscogsLabelSearchEngine.PerformLabelSearch(result.Name, 1);
if (discogsResult.IsSuccess)
{
var d = discogsResult.Data.First();
if (d.Urls != null)
{
result.URLs = result.URLs.AddToDelimitedList(d.Urls);
}
if (d.Urls != null) result.URLs = result.URLs.AddToDelimitedList(d.Urls);
if (d.AlternateNames != null)
{
result.AlternateNames = result.AlternateNames.AddToDelimitedList(d.AlternateNames);
}
if (!string.IsNullOrEmpty(d.LabelName) && !d.LabelName.Equals(result.Name, StringComparison.OrdinalIgnoreCase))
{
result.AlternateNames.AddToDelimitedList(new string[] { d.LabelName });
}
if (!string.IsNullOrEmpty(d.LabelName) &&
!d.LabelName.Equals(result.Name, StringComparison.OrdinalIgnoreCase))
result.AlternateNames.AddToDelimitedList(new[] { d.LabelName });
result.CopyTo(new Label
{
Profile = this.HttpEncoder.HtmlEncode(d.Profile),
Profile = HttpEncoder.HtmlEncode(d.Profile),
DiscogsId = d.DiscogsId,
Name = result.Name ?? d.LabelName.ToTitleCase(),
Thumbnail = d.LabelImageUrl != null ? WebHelper.BytesForImageUrl(d.LabelImageUrl) : null
});
}
if (discogsResult.Errors != null)
{
resultsExceptions.AddRange(discogsResult.Errors);
}
if (discogsResult.Errors != null) resultsExceptions.AddRange(discogsResult.Errors);
}
sw.Stop();

View file

@ -3,27 +3,29 @@ using Roadie.Library.Caching;
using Roadie.Library.Configuration;
using Roadie.Library.Data;
using Roadie.Library.Encoding;
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Engines
{
public abstract class LookupEngineBase
{
protected ICacheManager CacheManager { get; }
protected IRoadieSettings Configuration { get; }
protected IRoadieDbContext DbContext { get; }
protected IHttpEncoder HttpEncoder { get; }
protected ILogger Logger { get; }
public LookupEngineBase(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context, ICacheManager cacheManager, ILogger logger)
public LookupEngineBase(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context,
ICacheManager cacheManager, ILogger logger)
{
this.Configuration = configuration;
this.HttpEncoder = httpEncoder;
this.DbContext = context;
this.CacheManager = cacheManager;
this.Logger = logger;
Configuration = configuration;
HttpEncoder = httpEncoder;
DbContext = context;
CacheManager = cacheManager;
Logger = logger;
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -6,6 +6,6 @@
Active,
OnHold,
SplitUp,
Deceased,
Deceased
}
}

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Enums
namespace Roadie.Library.Enums
{
public enum CommentReaction
{
@ -10,4 +6,4 @@ namespace Roadie.Library.Enums
Dislike,
Like
}
}
}

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Enums
namespace Roadie.Library.Enums
{
public enum CommentType
{
@ -15,4 +11,4 @@ namespace Roadie.Library.Enums
Release,
Track
}
}
}

View file

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Enums
namespace Roadie.Library.Enums
{
public enum ImageType : short
{
@ -14,4 +10,4 @@ namespace Roadie.Library.Enums
Label,
Track
}
}
}

View file

@ -1,14 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.Logging;
using System;
namespace Roadie.Library
{
[Serializable]
public class EventMessage
public class EventMessage
{
public Microsoft.Extensions.Logging.LogLevel Level { get; set; } = Microsoft.Extensions.Logging.LogLevel.Trace;
public LogLevel Level { get; set; } = LogLevel.Trace;
public string Message { get; set; }
}
}
}

View file

@ -4,19 +4,13 @@
{
public static int ComputeHash(this byte[] data)
{
if (data == null || data.Length == 0)
{
return 0;
}
if (data == null || data.Length == 0) return 0;
unchecked
{
const int p = 16777619;
int hash = (int)2166136261;
var hash = (int)2166136261;
for (int i = 0; i < data.Length; i++)
{
hash = (hash ^ data[i]) * p;
}
for (var i = 0; i < data.Length; i++) hash = (hash ^ data[i]) * p;
hash += hash << 13;
hash ^= hash >> 7;
hash += hash << 3;

View file

@ -6,14 +6,8 @@ namespace Roadie.Library.Extensions
{
public static DateTime? FormatDateTime(this DateTime? value)
{
if (!value.HasValue)
{
return null;
}
if (value.Value.Year == 0 || value.Value.Year == 1)
{
return null;
}
if (!value.HasValue) return null;
if (value.Value.Year == 0 || value.Value.Year == 1) return null;
return value;
}
@ -31,10 +25,10 @@ namespace Roadie.Library.Extensions
public static int ToUnixTimeSinceEpoch(this DateTime dateTime)
{
DateTime utcDateTime = dateTime.ToUniversalTime();
var utcDateTime = dateTime.ToUniversalTime();
var jan1St1970 = new DateTime(1970, 1, 1, 0, 0, 0);
TimeSpan timeSinceJan1St1970 = utcDateTime.Subtract(jan1St1970);
var timeSinceJan1St1970 = utcDateTime.Subtract(jan1St1970);
return (int)timeSinceJan1St1970.TotalSeconds;
}
}

View file

@ -1,7 +1,5 @@
using Roadie.Library.Utility;
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Extensions
{
@ -9,20 +7,14 @@ namespace Roadie.Library.Extensions
{
public static int ToSecondsFromMilliseconds(this decimal? value)
{
if (value > 0)
{
return (int)new TimeInfo(value.Value).Seconds;
}
if (value > 0) return (int)new TimeInfo(value.Value).Seconds;
return 0;
}
public static TimeSpan? ToTimeSpan(this decimal? value)
{
if(!value.HasValue)
{
return null;
}
if (!value.HasValue) return null;
return TimeSpan.FromSeconds((double)value);
}
}
}
}

View file

@ -1,4 +1,5 @@
using System;
using Newtonsoft.Json;
using System;
namespace Roadie.Library.Extensions
{
@ -6,15 +7,12 @@ namespace Roadie.Library.Extensions
{
public static string Serialize(this Exception input)
{
if (input == null)
if (input == null) return null;
var settings = new JsonSerializerSettings
{
return null;
}
var settings = new Newtonsoft.Json.JsonSerializerSettings
{
NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore
NullValueHandling = NullValueHandling.Ignore
};
return Newtonsoft.Json.JsonConvert.SerializeObject(input, Newtonsoft.Json.Formatting.Indented, settings);
return JsonConvert.SerializeObject(input, Formatting.Indented, settings);
}
}
}

View file

@ -2,7 +2,6 @@
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
@ -10,40 +9,19 @@ namespace Roadie.Library.Extensions
{
public static class GenericExt
{
public static TEntity CopyTo<TEntity>(this TEntity OriginalEntity, TEntity NewEntity)
{
PropertyInfo[] oProperties = OriginalEntity.GetType().GetProperties();
foreach (PropertyInfo CurrentProperty in oProperties.Where(p => p.CanWrite))
{
if (CurrentProperty.GetValue(NewEntity, null) != null)
{
CurrentProperty.SetValue(OriginalEntity, CurrentProperty.GetValue(NewEntity, null), null);
}
}
return OriginalEntity;
}
/// <summary>
/// Perform a deep Copy of the object using a BinaryFormatter.
/// IMPORTANT: the object class must be marked as [Serializable] and have an parameterless constructor.
/// Perform a deep Copy of the object using a BinaryFormatter.
/// IMPORTANT: the object class must be marked as [Serializable] and have an parameterless constructor.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(this T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
if (!typeof(T).IsSerializable) throw new ArgumentException("The type must be serializable.", "source");
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
if (ReferenceEquals(source, null)) return default(T);
IFormatter formatter = new BinaryFormatter();
using (Stream stream = new MemoryStream())
@ -54,12 +32,23 @@ namespace Roadie.Library.Extensions
}
}
public static TEntity CopyTo<TEntity>(this TEntity OriginalEntity, TEntity NewEntity)
{
var oProperties = OriginalEntity.GetType().GetProperties();
foreach (var CurrentProperty in oProperties.Where(p => p.CanWrite))
if (CurrentProperty.GetValue(NewEntity, null) != null)
CurrentProperty.SetValue(OriginalEntity, CurrentProperty.GetValue(NewEntity, null), null);
return OriginalEntity;
}
public static string DescriptionAttr<T>(this T source)
{
FieldInfo fi = source.GetType().GetField(source.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
var fi = source.GetType().GetField(source.ToString());
var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0) return attributes[0].Description;
else return source.ToString();
return source.ToString();
}
}
}

View file

@ -6,10 +6,7 @@ namespace Roadie.Library.Extensions
{
public static int? Or(this int? value, int? alternative)
{
if (!value.HasValue && !alternative.HasValue)
{
return null;
}
if (!value.HasValue && !alternative.HasValue) return null;
return value.HasValue ? value : alternative;
}
@ -17,9 +14,10 @@ namespace Roadie.Library.Extensions
{
if (value > 0)
{
var contentDurationTimeSpan = TimeSpan.FromMilliseconds((double)(value ?? 0));
var contentDurationTimeSpan = TimeSpan.FromMilliseconds(value ?? 0);
return (int)contentDurationTimeSpan.TotalSeconds;
}
return 0;
}
}

View file

@ -8,19 +8,19 @@ namespace Roadie.Library.Extensions
{
public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source)
{
Random rnd = new Random();
return source.OrderBy<T, int>((item) => rnd.Next());
var rnd = new Random();
return source.OrderBy(item => rnd.Next());
}
public static void Shuffle<T>(this IList<T> list)
{
int n = list.Count;
Random rnd = new Random();
var n = list.Count;
var rnd = new Random();
while (n > 1)
{
int k = (rnd.Next(0, n) % n);
var k = rnd.Next(0, n) % n;
n--;
T value = list[k];
var value = list[k];
list[k] = list[n];
list[n] = value;
}
@ -33,10 +33,7 @@ namespace Roadie.Library.Extensions
public static string ToDelimitedList<T>(this IEnumerable<T> list, char delimiter = '|')
{
if (list == null || !list.Any())
{
return null;
}
if (list == null || !list.Any()) return null;
return string.Join(delimiter.ToString(), list);
}
}

View file

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Microsoft.Extensions.Logging
{
@ -11,4 +9,4 @@ namespace Microsoft.Extensions.Logging
logger.LogError(default(EventId), ex, null, null);
}
}
}
}

View file

@ -1,5 +1,4 @@
using Roadie.Library.Utility;
using System;
namespace Roadie.Library.Extensions
{
@ -7,11 +6,8 @@ namespace Roadie.Library.Extensions
{
public static string ToFileSize(this long? l)
{
if (!l.HasValue)
{
return "0";
}
return String.Format(new FileSizeFormatProvider(), "{0:fs}", l);
if (!l.HasValue) return "0";
return string.Format(new FileSizeFormatProvider(), "{0:fs}", l);
}
}
}

View file

@ -4,23 +4,14 @@
{
public static short? Or(this short? value, short? alternative)
{
if (!value.HasValue && !alternative.HasValue)
{
return null;
}
if (!value.HasValue && !alternative.HasValue) return null;
return value.HasValue ? value : alternative;
}
public static short? TakeLarger(this short? value, short? alternative)
{
if (!value.HasValue && !alternative.HasValue)
{
return null;
}
if (!value.HasValue && alternative.HasValue)
{
return alternative.Value;
}
if (!value.HasValue && !alternative.HasValue) return null;
if (!value.HasValue && alternative.HasValue) return alternative.Value;
return value.Value > alternative.Value ? value.Value : alternative.Value;
}
}

View file

@ -1,9 +1,9 @@
using HtmlAgilityPack;
using Roadie.Library.Configuration;
using Roadie.Library.Configuration;
using Roadie.Library.Utility;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
@ -13,7 +13,8 @@ namespace Roadie.Library.Extensions
{
public static class StringExt
{
private static readonly Dictionary<char, string> UnicodeAccents = new Dictionary<char, string>() {
private static readonly Dictionary<char, string> UnicodeAccents = new Dictionary<char, string>
{
{'À', "A"}, {'Á', "A"}, {'Â', "A"}, {'Ã', "A"}, {'Ä', "Ae"}, {'Å', "A"}, {'Æ', "Ae"},
{'Ç', "C"},
{'È', "E"}, {'É', "E"}, {'Ê', "E"}, {'Ë', "E"},
@ -35,60 +36,34 @@ namespace Roadie.Library.Extensions
{'ý', "y"}, {'ÿ', "y"}
};
public static string AddToDelimitedList(this string input, IEnumerable<string> values, char delimiter = '|')
{
if (string.IsNullOrEmpty(input) && (values == null || !values.Any()))
{
return null;
}
if (string.IsNullOrEmpty(input))
{
return string.Join(delimiter.ToString(), values);
}
if (values == null || !values.Any())
{
return input;
}
if (string.IsNullOrEmpty(input) && (values == null || !values.Any())) return null;
if (string.IsNullOrEmpty(input)) return string.Join(delimiter.ToString(), values);
if (values == null || !values.Any()) return input;
foreach (var value in values)
{
if (string.IsNullOrEmpty(value))
{
continue;
}
if (string.IsNullOrEmpty(value)) continue;
if (!input.IsValueInDelimitedList(value, delimiter))
{
if (!input.EndsWith(delimiter.ToString()))
{
input = input + delimiter;
}
if (!input.EndsWith(delimiter.ToString())) input = input + delimiter;
input = input + value;
}
}
return input;
}
public static string CleanString(this string input, IRoadieSettings settings, string removeStringsRegex = null)
{
if (string.IsNullOrEmpty(input) || settings == null)
{
return input;
}
if (string.IsNullOrEmpty(input) || settings == null) return input;
var result = input;
foreach (var kvp in settings.Processing.ReplaceStrings.OrderBy(x => x.Order).ThenBy(x => x.Key))
{
result = result.Replace(kvp.Key, kvp.ReplaceWith, StringComparison.OrdinalIgnoreCase);
}
result = result.Trim().ToTitleCase(false);
if(string.IsNullOrEmpty(result))
{
return input;
}
if (string.IsNullOrEmpty(result)) return input;
var rs = removeStringsRegex ?? settings.Processing.RemoveStringsRegex;
if (!string.IsNullOrEmpty(rs))
{
result = Regex.Replace(result, rs, "", RegexOptions.IgnoreCase);
}
if (!string.IsNullOrEmpty(rs)) result = Regex.Replace(result, rs, "", RegexOptions.IgnoreCase);
if (result.Length > 5)
{
var extensionStart = result.Substring(result.Length - 5, 2);
@ -100,16 +75,14 @@ namespace Roadie.Library.Extensions
result = inputSb.ToString();
}
}
// Strip out any more than single space and remove any blanks before and after
return Regex.Replace(result, @"\s+", " ").Trim();
}
public static bool DoesStartWithNumber(this string input)
{
if (string.IsNullOrEmpty(input))
{
return false;
}
if (string.IsNullOrEmpty(input)) return false;
var firstPart = input.Split(' ').First().SafeReplace("[").SafeReplace("]");
return SafeParser.ToNumber<long>(firstPart) > 0;
}
@ -117,47 +90,33 @@ namespace Roadie.Library.Extensions
public static string FromHexString(this string hexString)
{
var bytes = new byte[hexString.Length / 2];
for (var i = 0; i < bytes.Length; i++)
{
bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
}
for (var i = 0; i < bytes.Length; i++) bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
return System.Text.Encoding.UTF8.GetString(bytes); // returns: "Hello world" for "48656C6C6F20776F726C64"
}
public static bool IsValidFilename(this string input)
{
Regex containsABadCharacter = new Regex("[" + Regex.Escape(new string(System.IO.Path.GetInvalidPathChars())) + "]");
if (containsABadCharacter.IsMatch(input))
{
return false;
};
var containsABadCharacter = new Regex("[" + Regex.Escape(new string(Path.GetInvalidPathChars())) + "]");
if (containsABadCharacter.IsMatch(input)) return false;
;
return true;
}
public static bool IsValueInDelimitedList(this string input, string value, char delimiter = '|')
{
if (string.IsNullOrEmpty(input))
{
return false;
}
if (string.IsNullOrEmpty(input)) return false;
var p = input.Split(delimiter);
return !p.Any() ? false : p.Any(x => x.Trim().Equals(value, StringComparison.OrdinalIgnoreCase));
}
public static string NormalizeName(this string input)
{
if (string.IsNullOrEmpty(input))
{
return input;
}
if (string.IsNullOrEmpty(input)) return input;
input = input.ToLower();
var removeParts = new List<string> { " ft. ", " ft ", " feat ", " feat. " };
foreach (var removePart in removeParts)
{
input = input.Replace(removePart, "");
}
TextInfo cultInfo = new CultureInfo("en-US", false).TextInfo;
foreach (var removePart in removeParts) input = input.Replace(removePart, "");
var cultInfo = new CultureInfo("en-US", false).TextInfo;
return cultInfo.ToTitleCase(input).Trim();
}
@ -166,125 +125,67 @@ namespace Roadie.Library.Extensions
return string.IsNullOrEmpty(input) ? alternative : input;
}
public static string RemoveDiacritics(this string s)
{
var normalizedString = s.Normalize(NormalizationForm.FormD);
var stringBuilder = new StringBuilder();
for (var i = 0; i < normalizedString.Length; i++)
{
var c = normalizedString[i];
if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) stringBuilder.Append(c);
}
return stringBuilder.ToString();
}
public static string RemoveFirst(this string input, string remove = "")
{
if (string.IsNullOrEmpty(input))
{
return input;
}
int index = input.IndexOf(remove);
return (index < 0)
if (string.IsNullOrEmpty(input)) return input;
var index = input.IndexOf(remove);
return index < 0
? input
: input.Remove(index, remove.Length).Trim();
}
public static string RemoveStartsWith(this string input, string remove = "")
{
if (string.IsNullOrEmpty(input))
{
return input;
}
int index = input.IndexOf(remove);
string result = input;
if (string.IsNullOrEmpty(input)) return input;
var index = input.IndexOf(remove);
var result = input;
while (index == 0)
{
result = result.Remove(index, remove.Length).Trim();
index = result.IndexOf(remove);
}
return result;
}
public static string ReplaceLastOccurrence(this string input, string find, string replace = "")
{
if (string.IsNullOrEmpty(input))
{
return input;
}
int Place = input.LastIndexOf(find);
return input.Remove(Place, find.Length).Insert(Place, replace);
}
public static string SafeReplace(this string input, string replace, string replaceWith = " ")
{
if (string.IsNullOrEmpty(input))
{
return null;
}
return input.Replace(replace, replaceWith);
}
public static string StripStartingNumber(this string input)
{
if (string.IsNullOrEmpty(input))
{
return null;
}
if (input.DoesStartWithNumber())
{
return string.Join(" ", input.Split(' ').Skip(1));
}
return input;
}
public static string RemoveUnicodeAccents(this string text)
{
return text.Aggregate(
new StringBuilder(),
(sb, c) => {
string r;
if (UnicodeAccents.TryGetValue(c, out r))
{
return sb.Append(r);
}
return sb.Append(c);
}).ToString();
}
public static String RemoveDiacritics(this string s)
{
String normalizedString = s.Normalize(NormalizationForm.FormD);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < normalizedString.Length; i++)
{
Char c = normalizedString[i];
if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
new StringBuilder(),
(sb, c) =>
{
stringBuilder.Append(c);
}
}
return stringBuilder.ToString();
string r;
if (UnicodeAccents.TryGetValue(c, out r)) return sb.Append(r);
return sb.Append(c);
}).ToString();
}
public static string Translit(this string str)
public static string ReplaceLastOccurrence(this string input, string find, string replace = "")
{
string[] lat_up = { "A", "B", "V", "G", "D", "E", "Yo", "Zh", "Z", "I", "Y", "K", "L", "M", "N", "O", "P", "R", "S", "T", "U", "F", "Kh", "Ts", "Ch", "Sh", "Shch", "\"", "Y", "'", "E", "Yu", "Ya" };
string[] lat_low = { "a", "b", "v", "g", "d", "e", "yo", "zh", "z", "i", "y", "k", "l", "m", "n", "o", "p", "r", "s", "t", "u", "f", "kh", "ts", "ch", "sh", "shch", "\"", "y", "'", "e", "yu", "ya" };
string[] rus_up = { "А", "Б", "В", "Г", "Д", "Е", "Ё", "Ж", "З", "И", "Й", "К", "Л", "М", "Н", "О", "П", "Р", "С", "Т", "У", "Ф", "Х", "Ц", "Ч", "Ш", "Щ", "Ъ", "Ы", "Ь", "Э", "Ю", "Я" };
string[] rus_low = { "а", "б", "в", "г", "д", "е", "ё", "ж", "з", "и", "й", "к", "л", "м", "н", "о", "п", "р", "с", "т", "у", "ф", "х", "ц", "ч", "ш", "щ", "ъ", "ы", "ь", "э", "ю", "я" };
for (int i = 0; i <= 32; i++)
{
str = str.Replace(rus_up[i], lat_up[i]);
str = str.Replace(rus_low[i], lat_low[i]);
}
return str;
if (string.IsNullOrEmpty(input)) return input;
var Place = input.LastIndexOf(find);
return input.Remove(Place, find.Length).Insert(Place, replace);
}
public static string ToAlphanumericName(this string input)
public static string SafeReplace(this string input, string replace, string replaceWith = " ")
{
if (string.IsNullOrEmpty(input))
{
return input;
}
input = WebUtility.HtmlDecode(input);
input = input.ScrubHtml().ToLower().Trim().Replace("&", "and");
char[] arr = input.ToCharArray();
arr = Array.FindAll<char>(arr, (c => (char.IsLetterOrDigit(c))));
input = new string(arr).RemoveDiacritics().RemoveUnicodeAccents().Translit();
input = Regex.Replace(input, @"[^A-Za-z0-9]+", "");
return input;
if (string.IsNullOrEmpty(input)) return null;
return input.Replace(replace, replaceWith);
}
public static string ScrubHtml(this string value)
{
var step1 = Regex.Replace(value, @"<[^>]+>|&nbsp;", "").Trim();
@ -292,30 +193,40 @@ namespace Roadie.Library.Extensions
return step2;
}
public static string StripStartingNumber(this string input)
{
if (string.IsNullOrEmpty(input)) return null;
if (input.DoesStartWithNumber()) return string.Join(" ", input.Split(' ').Skip(1));
return input;
}
public static string ToAlphanumericName(this string input)
{
if (string.IsNullOrEmpty(input)) return input;
input = WebUtility.HtmlDecode(input);
input = input.ScrubHtml().ToLower().Trim().Replace("&", "and");
var arr = input.ToCharArray();
arr = Array.FindAll(arr, c => char.IsLetterOrDigit(c));
input = new string(arr).RemoveDiacritics().RemoveUnicodeAccents().Translit();
input = Regex.Replace(input, @"[^A-Za-z0-9]+", "");
return input;
}
public static string ToContentDispositionFriendly(this string input)
{
if (string.IsNullOrEmpty(input))
{
return null;
}
if (string.IsNullOrEmpty(input)) return null;
return input.Replace(',', ' ');
}
public static string ToFileNameFriendly(this string input)
{
if (string.IsNullOrEmpty(input))
{
return null;
}
if (string.IsNullOrEmpty(input)) return null;
return Regex.Replace(PathSanitizer.SanitizeFilename(input, ' '), @"\s+", " ").Trim();
}
public static string ToFolderNameFriendly(this string input)
{
if (string.IsNullOrEmpty(input))
{
return null;
}
if (string.IsNullOrEmpty(input)) return null;
return Regex.Replace(PathSanitizer.SanitizeFilename(input, ' '), @"\s+", " ").Trim().TrimEnd('.');
}
@ -324,86 +235,90 @@ namespace Roadie.Library.Extensions
var sb = new StringBuilder();
var bytes = System.Text.Encoding.UTF8.GetBytes(str);
foreach (var t in bytes)
{
sb.Append(t.ToString("X2"));
}
foreach (var t in bytes) sb.Append(t.ToString("X2"));
return sb.ToString(); // returns: "48656C6C6F20776F726C64" for "Hello world"
}
public static IEnumerable<string> ToListFromDelimited(this string input, char delimiter = '|')
{
if (string.IsNullOrEmpty(input))
{
return new string[0];
}
if (string.IsNullOrEmpty(input)) return new string[0];
return input.Split(delimiter);
}
public static string ToTitleCase(this string input, bool doPutTheAtEnd = true)
{
if (string.IsNullOrEmpty(input))
{
return null;
}
TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
if (string.IsNullOrEmpty(input)) return null;
var textInfo = new CultureInfo("en-US", false).TextInfo;
var r = textInfo.ToTitleCase(input.Trim().ToLower());
r = Regex.Replace(r, @"\s+", " ");
if (doPutTheAtEnd)
{
if (r.StartsWith("The "))
{
return r.Replace("The ", "") + ", The";
}
}
return r;
}
public static int? ToTrackDuration(this string input)
{
if (string.IsNullOrEmpty(input) || string.IsNullOrEmpty(input.Replace(":", "")))
{
return null;
}
if (string.IsNullOrEmpty(input) || string.IsNullOrEmpty(input.Replace(":", ""))) return null;
try
{
var parts = input.Contains(":") ? input.Split(':').ToList() : new List<string> { input };
while (parts.Count() < 3)
{
parts.Insert(0, "00:");
}
while (parts.Count() < 3) parts.Insert(0, "00:");
var tsRaw = string.Empty;
foreach (var part in parts)
{
if (tsRaw.Length > 0)
{
tsRaw += ":";
}
if (tsRaw.Length > 0) tsRaw += ":";
tsRaw += part.PadLeft(2, '0').Substring(0, 2);
}
TimeSpan ts = TimeSpan.MinValue;
var ts = TimeSpan.MinValue;
var success = TimeSpan.TryParse(tsRaw, out ts);
if (success)
{
return (int?)ts.TotalMilliseconds;
}
if (success) return (int?)ts.TotalMilliseconds;
}
catch
{
}
return null;
}
public static string Translit(this string str)
{
string[] lat_up =
{
"A", "B", "V", "G", "D", "E", "Yo", "Zh", "Z", "I", "Y", "K", "L", "M", "N", "O", "P", "R", "S", "T",
"U", "F", "Kh", "Ts", "Ch", "Sh", "Shch", "\"", "Y", "'", "E", "Yu", "Ya"
};
string[] lat_low =
{
"a", "b", "v", "g", "d", "e", "yo", "zh", "z", "i", "y", "k", "l", "m", "n", "o", "p", "r", "s", "t",
"u", "f", "kh", "ts", "ch", "sh", "shch", "\"", "y", "'", "e", "yu", "ya"
};
string[] rus_up =
{
"А", "Б", "В", "Г", "Д", "Е", "Ё", "Ж", "З", "И", "Й", "К", "Л", "М", "Н", "О", "П", "Р", "С", "Т", "У",
"Ф", "Х", "Ц", "Ч", "Ш", "Щ", "Ъ", "Ы", "Ь", "Э", "Ю", "Я"
};
string[] rus_low =
{
"а", "б", "в", "г", "д", "е", "ё", "ж", "з", "и", "й", "к", "л", "м", "н", "о", "п", "р", "с", "т", "у",
"ф", "х", "ц", "ч", "ш", "щ", "ъ", "ы", "ь", "э", "ю", "я"
};
for (var i = 0; i <= 32; i++)
{
str = str.Replace(rus_up[i], lat_up[i]);
str = str.Replace(rus_low[i], lat_low[i]);
}
return str;
}
public static string TrimEnd(this string input, string suffixToRemove)
{
if (input != null && suffixToRemove != null && input.EndsWith(suffixToRemove))
{
return input.Substring(0, input.Length - suffixToRemove.Length);
}
return input;
}
}
}

View file

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Roadie.Library.Extensions
{
@ -8,11 +6,8 @@ namespace Roadie.Library.Extensions
{
public static string ToDuration(this TimeSpan input)
{
if(input == null || input.TotalMilliseconds == 0)
{
return "--/--/--";
}
if (input == null || input.TotalMilliseconds == 0) return "--/--/--";
return input.ToString(@"ddd\.hh\:mm\:ss");
}
}
}
}

View file

@ -9,7 +9,6 @@ using Roadie.Library.Enums;
using Roadie.Library.Extensions;
using Roadie.Library.Imaging;
using Roadie.Library.MetaData.Audio;
using Roadie.Library.MetaData.ID3Tags;
using Roadie.Library.Processors;
using Roadie.Library.Utility;
using System;
@ -25,37 +24,30 @@ namespace Roadie.Library.Factories
public sealed class ArtistFactory : FactoryBase, IArtistFactory
{
private List<int> _addedArtistIds = new List<int>();
private readonly List<int> _addedArtistIds = new List<int>();
public IEnumerable<int> AddedArtistIds
public ArtistFactory(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context,
ICacheManager cacheManager, ILogger logger, IArtistLookupEngine artistLookupEngine,
IReleaseFactory releaseFactory, IImageFactory imageFactory, IReleaseLookupEngine releaseLookupEngine,
IAudioMetaDataHelper audioMetaDataHelper)
: base(configuration, context, cacheManager, logger, httpEncoder, artistLookupEngine, releaseLookupEngine)
{
get
{
return this._addedArtistIds;
}
ReleaseFactory = releaseFactory;
ImageFactory = imageFactory;
AudioMetaDataHelper = audioMetaDataHelper;
}
public IEnumerable<int> AddedArtistIds => _addedArtistIds;
private IReleaseFactory ReleaseFactory { get; }
private IImageFactory ImageFactory { get; }
private IAudioMetaDataHelper AudioMetaDataHelper { get; }
public ArtistFactory(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context,
ICacheManager cacheManager, ILogger logger, IArtistLookupEngine artistLookupEngine, IReleaseFactory releaseFactory, IImageFactory imageFactory, IReleaseLookupEngine releaseLookupEngine, IAudioMetaDataHelper audioMetaDataHelper)
: base(configuration, context, cacheManager, logger, httpEncoder, artistLookupEngine, releaseLookupEngine)
{
this.ReleaseFactory = releaseFactory;
this.ImageFactory = imageFactory;
this.AudioMetaDataHelper = audioMetaDataHelper;
}
public async Task<OperationResult<bool>> Delete(Guid RoadieId)
{
var isSuccess = false;
var Artist = this.DbContext.Artists.FirstOrDefault(x => x.RoadieId == RoadieId);
if (Artist != null)
{
return await this.Delete(Artist);
}
var Artist = DbContext.Artists.FirstOrDefault(x => x.RoadieId == RoadieId);
if (Artist != null) return await Delete(Artist);
return new OperationResult<bool>
{
Data = isSuccess
@ -69,21 +61,22 @@ namespace Roadie.Library.Factories
{
if (Artist != null)
{
this.DbContext.Artists.Remove(Artist);
await this.DbContext.SaveChangesAsync();
this.CacheManager.ClearRegion(Artist.CacheRegion);
this.Logger.LogInformation(string.Format("x DeleteArtist [{0}]", Artist.Id));
DbContext.Artists.Remove(Artist);
await DbContext.SaveChangesAsync();
CacheManager.ClearRegion(Artist.CacheRegion);
Logger.LogInformation(string.Format("x DeleteArtist [{0}]", Artist.Id));
isSuccess = true;
}
}
catch (Exception ex)
{
this.Logger.LogError(ex, ex.Serialize());
Logger.LogError(ex, ex.Serialize());
return new OperationResult<bool>
{
Errors = new Exception[1] { ex }
};
}
return new OperationResult<bool>
{
IsSuccess = isSuccess,
@ -91,21 +84,22 @@ namespace Roadie.Library.Factories
};
}
public OperationResult<Artist> GetByExternalIds(string musicBrainzId = null, string iTunesId = null, string amgId = null, string spotifyId = null)
public OperationResult<Artist> GetByExternalIds(string musicBrainzId = null, string iTunesId = null,
string amgId = null, string spotifyId = null)
{
var sw = new Stopwatch();
sw.Start();
var Artist = (from a in this.DbContext.Artists
where ((a.MusicBrainzId != null && (musicBrainzId != null && a.MusicBrainzId == musicBrainzId)) ||
(a.ITunesId != null || (iTunesId != null && a.ITunesId == iTunesId)) ||
(a.AmgId != null || (amgId != null && a.AmgId == amgId)) ||
(a.SpotifyId != null || (spotifyId != null && a.SpotifyId == spotifyId)))
var Artist = (from a in DbContext.Artists
where a.MusicBrainzId != null && musicBrainzId != null && a.MusicBrainzId == musicBrainzId ||
a.ITunesId != null || iTunesId != null && a.ITunesId == iTunesId || a.AmgId != null ||
amgId != null && a.AmgId == amgId || a.SpotifyId != null ||
spotifyId != null && a.SpotifyId == spotifyId
select a).FirstOrDefault();
sw.Stop();
if (Artist == null || !Artist.IsValid)
{
this.Logger.LogTrace("ArtistFactory: Artist Not Found By External Ids: MusicbrainzId [{0}], iTunesIs [{1}], AmgId [{2}], SpotifyId [{3}]", musicBrainzId, iTunesId, amgId, spotifyId);
}
Logger.LogTrace(
"ArtistFactory: Artist Not Found By External Ids: MusicbrainzId [{0}], iTunesIs [{1}], AmgId [{2}], SpotifyId [{3}]",
musicBrainzId, iTunesId, amgId, spotifyId);
return new OperationResult<Artist>
{
IsSuccess = Artist != null,
@ -115,12 +109,13 @@ namespace Roadie.Library.Factories
}
/// <summary>
/// Merge one Artist into another one
/// Merge one Artist into another one
/// </summary>
/// <param name="ArtistToMerge">The Artist to be merged</param>
/// <param name="artistToMergeInto">The Artist to merge into</param>
/// <returns></returns>
public async Task<OperationResult<Artist>> MergeArtists(Artist ArtistToMerge, Artist artistToMergeInto, bool doDbUpdates = false)
public async Task<OperationResult<Artist>> MergeArtists(Artist ArtistToMerge, Artist artistToMergeInto,
bool doDbUpdates = false)
{
SimpleContract.Requires<ArgumentNullException>(ArtistToMerge != null, "Invalid Artist");
SimpleContract.Requires<ArgumentNullException>(artistToMergeInto != null, "Invalid Artist");
@ -141,52 +136,61 @@ namespace Roadie.Library.Factories
artistToMergeInto.BirthDate = ArtistToMerge.BirthDate ?? artistToMergeInto.BirthDate;
artistToMergeInto.BeginDate = ArtistToMerge.BeginDate ?? artistToMergeInto.BeginDate;
artistToMergeInto.EndDate = ArtistToMerge.EndDate ?? artistToMergeInto.EndDate;
if (!string.IsNullOrEmpty(ArtistToMerge.ArtistType) && !ArtistToMerge.ArtistType.Equals("Other", StringComparison.OrdinalIgnoreCase))
{
if (!string.IsNullOrEmpty(ArtistToMerge.ArtistType) &&
!ArtistToMerge.ArtistType.Equals("Other", StringComparison.OrdinalIgnoreCase))
artistToMergeInto.ArtistType = ArtistToMerge.ArtistType;
}
artistToMergeInto.BioContext = ArtistToMerge.BioContext ?? artistToMergeInto.BioContext;
artistToMergeInto.DiscogsId = ArtistToMerge.DiscogsId ?? artistToMergeInto.DiscogsId;
artistToMergeInto.Tags = artistToMergeInto.Tags.AddToDelimitedList(ArtistToMerge.Tags.ToListFromDelimited());
artistToMergeInto.Tags =
artistToMergeInto.Tags.AddToDelimitedList(ArtistToMerge.Tags.ToListFromDelimited());
var altNames = ArtistToMerge.AlternateNames.ToListFromDelimited().ToList();
altNames.Add(ArtistToMerge.Name);
altNames.Add(ArtistToMerge.SortName);
artistToMergeInto.AlternateNames = artistToMergeInto.AlternateNames.AddToDelimitedList(altNames);
artistToMergeInto.URLs = artistToMergeInto.URLs.AddToDelimitedList(ArtistToMerge.URLs.ToListFromDelimited());
artistToMergeInto.ISNI = artistToMergeInto.ISNI.AddToDelimitedList(ArtistToMerge.ISNI.ToListFromDelimited());
artistToMergeInto.URLs =
artistToMergeInto.URLs.AddToDelimitedList(ArtistToMerge.URLs.ToListFromDelimited());
artistToMergeInto.ISNI =
artistToMergeInto.ISNI.AddToDelimitedList(ArtistToMerge.ISNI.ToListFromDelimited());
artistToMergeInto.LastUpdated = now;
if (doDbUpdates)
{
string sql = null;
sql = "UPDATE `artistGenreTable` set artistId = " + artistToMergeInto.Id + " WHERE artistId = " + ArtistToMerge.Id + ";";
await this.DbContext.Database.ExecuteSqlCommandAsync(sql);
sql = "UPDATE `image` set artistId = " + artistToMergeInto.Id + " WHERE artistId = " + ArtistToMerge.Id + ";";
await this.DbContext.Database.ExecuteSqlCommandAsync(sql);
sql = "UPDATE `userartist` set artistId = " + artistToMergeInto.Id + " WHERE artistId = " + ArtistToMerge.Id + ";";
await this.DbContext.Database.ExecuteSqlCommandAsync(sql);
sql = "UPDATE `track` set artistId = " + artistToMergeInto.Id + " WHERE artistId = " + ArtistToMerge.Id + ";";
await this.DbContext.Database.ExecuteSqlCommandAsync(sql);
sql = "UPDATE `artistGenreTable` set artistId = " + artistToMergeInto.Id + " WHERE artistId = " +
ArtistToMerge.Id + ";";
await DbContext.Database.ExecuteSqlCommandAsync(sql);
sql = "UPDATE `image` set artistId = " + artistToMergeInto.Id + " WHERE artistId = " +
ArtistToMerge.Id + ";";
await DbContext.Database.ExecuteSqlCommandAsync(sql);
sql = "UPDATE `userartist` set artistId = " + artistToMergeInto.Id + " WHERE artistId = " +
ArtistToMerge.Id + ";";
await DbContext.Database.ExecuteSqlCommandAsync(sql);
sql = "UPDATE `track` set artistId = " + artistToMergeInto.Id + " WHERE artistId = " +
ArtistToMerge.Id + ";";
await DbContext.Database.ExecuteSqlCommandAsync(sql);
try
{
sql = "UPDATE `release` set artistId = " + artistToMergeInto.Id + " WHERE artistId = " + ArtistToMerge.Id + ";";
await this.DbContext.Database.ExecuteSqlCommandAsync(sql);
sql = "UPDATE `release` set artistId = " + artistToMergeInto.Id + " WHERE artistId = " +
ArtistToMerge.Id + ";";
await DbContext.Database.ExecuteSqlCommandAsync(sql);
}
catch (Exception ex)
{
this.Logger.LogWarning(ex.ToString());
}
var artistFolder = ArtistToMerge.ArtistFileFolder(this.Configuration, this.Configuration.LibraryFolder);
foreach (var release in this.DbContext.Releases.Include("Artist").Where(x => x.ArtistId == ArtistToMerge.Id).ToArray())
{
var originalReleaseFolder = release.ReleaseFileFolder(artistFolder);
await this.ReleaseFactory.Update(release, null, originalReleaseFolder);
Logger.LogWarning(ex.ToString());
}
await this.Delete(ArtistToMerge);
var artistFolder = ArtistToMerge.ArtistFileFolder(Configuration, Configuration.LibraryFolder);
foreach (var release in DbContext.Releases.Include("Artist").Where(x => x.ArtistId == ArtistToMerge.Id)
.ToArray())
{
var originalReleaseFolder = release.ReleaseFileFolder(artistFolder);
await ReleaseFactory.Update(release, null, originalReleaseFolder);
}
await Delete(ArtistToMerge);
}
result = true;
@ -201,7 +205,7 @@ namespace Roadie.Library.Factories
}
/// <summary>
/// Perform a Metadata Provider search and then merge the results into the given Artist
/// Perform a Metadata Provider search and then merge the results into the given Artist
/// </summary>
/// <param name="ArtistId">Given Artist RoadieId</param>
/// <returns>Operation Result</returns>
@ -215,36 +219,38 @@ namespace Roadie.Library.Factories
sw.Start();
try
{
var Artist = this.DbContext.Artists.FirstOrDefault(x => x.RoadieId == ArtistId);
var Artist = DbContext.Artists.FirstOrDefault(x => x.RoadieId == ArtistId);
if (Artist == null)
{
this.Logger.LogWarning("Unable To Find Artist [{0}]", ArtistId);
Logger.LogWarning("Unable To Find Artist [{0}]", ArtistId);
return new OperationResult<bool>();
}
OperationResult<Artist> ArtistSearch = null;
try
{
ArtistSearch = await this.ArtistLookupEngine.PerformMetaDataProvidersArtistSearch(new AudioMetaData
ArtistSearch = await ArtistLookupEngine.PerformMetaDataProvidersArtistSearch(new AudioMetaData
{
Artist = Artist.Name
});
}
catch (Exception ex)
{
this.Logger.LogError(ex, ex.Serialize());
Logger.LogError(ex, ex.Serialize());
}
if (ArtistSearch.IsSuccess)
{
// Do metadata search for Artist like if new Artist then set some overides and merge
var mergeResult = await this.MergeArtists(ArtistSearch.Data, Artist);
var mergeResult = await MergeArtists(ArtistSearch.Data, Artist);
if (mergeResult.IsSuccess)
{
Artist = mergeResult.Data;
await this.DbContext.SaveChangesAsync();
await DbContext.SaveChangesAsync();
sw.Stop();
this.CacheManager.ClearRegion(Artist.CacheRegion);
this.Logger.LogInformation("Scanned RefreshArtistMetadata [{0}], OperationTime [{1}]", Artist.ToString(), sw.ElapsedMilliseconds);
CacheManager.ClearRegion(Artist.CacheRegion);
Logger.LogInformation("Scanned RefreshArtistMetadata [{0}], OperationTime [{1}]",
Artist.ToString(), sw.ElapsedMilliseconds);
}
else
{
@ -254,9 +260,10 @@ namespace Roadie.Library.Factories
}
catch (Exception ex)
{
this.Logger.LogError(ex, ex.Serialize());
Logger.LogError(ex, ex.Serialize());
resultErrors.Add(ex);
}
return new OperationResult<bool>
{
Data = result,
@ -267,7 +274,8 @@ namespace Roadie.Library.Factories
}
[Obsolete]
public async Task<OperationResult<bool>> ScanArtistReleasesFolders(Guid artistId, string destinationFolder, bool doJustInfo)
public async Task<OperationResult<bool>> ScanArtistReleasesFolders(Guid artistId, string destinationFolder,
bool doJustInfo)
{
SimpleContract.Requires<ArgumentOutOfRangeException>(artistId != Guid.Empty, "Invalid ArtistId");
@ -277,49 +285,45 @@ namespace Roadie.Library.Factories
sw.Start();
try
{
var artist = this.DbContext.Artists
.Include("Releases")
.Include("Releases.Labels")
.FirstOrDefault(x => x.RoadieId == artistId);
var artist = DbContext.Artists
.Include("Releases")
.Include("Releases.Labels")
.FirstOrDefault(x => x.RoadieId == artistId);
if (artist == null)
{
this.Logger.LogWarning("Unable To Find Artist [{0}]", artistId);
Logger.LogWarning("Unable To Find Artist [{0}]", artistId);
return new OperationResult<bool>();
}
var releaseScannedCount = 0;
var artistFolder = artist.ArtistFileFolder(this.Configuration, destinationFolder);
var artistFolder = artist.ArtistFileFolder(Configuration, destinationFolder);
var scannedArtistFolders = new List<string>();
// Scan known releases for changes
if (artist.Releases != null)
{
foreach (var release in artist.Releases)
{
try
{
result = result && (await this.ReleaseFactory.ScanReleaseFolder(Guid.Empty, destinationFolder, doJustInfo, release)).Data;
result = result && (await ReleaseFactory.ScanReleaseFolder(Guid.Empty, destinationFolder,
doJustInfo, release)).Data;
releaseScannedCount++;
scannedArtistFolders.Add(release.ReleaseFileFolder(artistFolder));
}
catch (Exception ex)
{
this.Logger.LogError(ex, ex.Serialize());
Logger.LogError(ex, ex.Serialize());
}
}
}
// Any folder found in Artist folder not already scanned scan
var folderProcessor = new FolderProcessor(this.Configuration, this.HttpEncoder, destinationFolder, this.DbContext, this.CacheManager, this.Logger, this.ArtistLookupEngine, this, this.ReleaseFactory, this.ImageFactory, this.ReleaseLookupEngine, this.AudioMetaDataHelper);
var nonReleaseFolders = (from d in Directory.EnumerateDirectories(artistFolder)
where !(from r in scannedArtistFolders select r).Contains(d)
orderby d
select d);
var folderProcessor = new FolderProcessor(Configuration, HttpEncoder, destinationFolder, DbContext,
CacheManager, Logger, ArtistLookupEngine, this, ReleaseFactory, ImageFactory, ReleaseLookupEngine,
AudioMetaDataHelper);
var nonReleaseFolders = from d in Directory.EnumerateDirectories(artistFolder)
where !(from r in scannedArtistFolders select r).Contains(d)
orderby d
select d;
foreach (var folder in nonReleaseFolders)
{
await folderProcessor.Process(new DirectoryInfo(folder), doJustInfo);
}
if (!doJustInfo)
{
FolderProcessor.DeleteEmptyFolders(new DirectoryInfo(artistFolder), this.Logger);
}
if (!doJustInfo) FolderProcessor.DeleteEmptyFolders(new DirectoryInfo(artistFolder), Logger);
// Always update artist image if artist image is found on an artist rescan
var imageFiles = ImageHelper.ImageFilesInFolder(artistFolder, SearchOption.AllDirectories);
@ -333,29 +337,34 @@ namespace Roadie.Library.Factories
{
// Read image and convert to jpeg
artist.Thumbnail = File.ReadAllBytes(i.FullName);
artist.Thumbnail = ImageHelper.ResizeImage(artist.Thumbnail, this.Configuration.MediumImageSize.Width, this.Configuration.MediumImageSize.Height);
artist.Thumbnail = ImageHelper.ResizeImage(artist.Thumbnail,
Configuration.MediumImageSize.Width, Configuration.MediumImageSize.Height);
artist.Thumbnail = ImageHelper.ConvertToJpegFormat(artist.Thumbnail);
if (artist.Thumbnail.Length >= ImageHelper.MaximumThumbnailByteSize)
{
Logger.LogWarning($"Artist Thumbnail larger than maximum size after resizing to [{ this.Configuration.ThumbnailImageSize.Width }x{ this.Configuration.ThumbnailImageSize.Height}] Thumbnail Size [{ artist.Thumbnail.Length }]");
Logger.LogWarning(
$"Artist Thumbnail larger than maximum size after resizing to [{Configuration.ThumbnailImageSize.Width}x{Configuration.ThumbnailImageSize.Height}] Thumbnail Size [{artist.Thumbnail.Length}]");
artist.Thumbnail = null;
}
artist.LastUpdated = DateTime.UtcNow;
await this.DbContext.SaveChangesAsync();
this.CacheManager.ClearRegion(artist.CacheRegion);
this.Logger.LogInformation("Update Thumbnail using Artist File [{0}]", iName);
await DbContext.SaveChangesAsync();
CacheManager.ClearRegion(artist.CacheRegion);
Logger.LogInformation("Update Thumbnail using Artist File [{0}]", iName);
}
}
sw.Stop();
this.CacheManager.ClearRegion(artist.CacheRegion);
this.Logger.LogInformation("Scanned Artist [{0}], Releases Scanned [{1}], OperationTime [{2}]", artist.ToString(), releaseScannedCount, sw.ElapsedMilliseconds);
CacheManager.ClearRegion(artist.CacheRegion);
Logger.LogInformation("Scanned Artist [{0}], Releases Scanned [{1}], OperationTime [{2}]",
artist.ToString(), releaseScannedCount, sw.ElapsedMilliseconds);
}
catch (Exception ex)
{
this.Logger.LogError(ex, ex.Serialize());
Logger.LogError(ex, ex.Serialize());
resultErrors.Add(ex);
}
return new OperationResult<bool>
{
Data = result,
@ -366,69 +375,71 @@ namespace Roadie.Library.Factories
}
[Obsolete]
public async Task<OperationResult<Artist>> Update(Artist Artist, IEnumerable<Image> ArtistImages, string destinationFolder = null)
public async Task<OperationResult<Artist>> Update(Artist Artist, IEnumerable<Image> ArtistImages,
string destinationFolder = null)
{
SimpleContract.Requires<ArgumentNullException>(Artist != null, "Invalid Artist");
var sw = new Stopwatch();
sw.Start();
var artistGenreTables = Artist.Genres.Select(x => new ArtistGenre { ArtistId = Artist.Id, GenreId = x.GenreId }).ToList();
var artistAssociatedWith = Artist.AssociatedArtists.Select(x => new ArtistAssociation { ArtistId = Artist.Id, AssociatedArtistId = x.AssociatedArtistId }).ToList();
var similarArtists = Artist.SimilarArtists.Select(x => new ArtistSimilar { ArtistId = Artist.Id, SimilarArtistId = x.SimilarArtistId }).ToList();
var artistGenreTables = Artist.Genres
.Select(x => new ArtistGenre { ArtistId = Artist.Id, GenreId = x.GenreId }).ToList();
var artistAssociatedWith = Artist.AssociatedArtists.Select(x => new ArtistAssociation
{ ArtistId = Artist.Id, AssociatedArtistId = x.AssociatedArtistId }).ToList();
var similarArtists = Artist.SimilarArtists.Select(x => new ArtistSimilar
{ ArtistId = Artist.Id, SimilarArtistId = x.SimilarArtistId }).ToList();
var result = true;
var now = DateTime.UtcNow;
var originalArtistFolder = Artist.ArtistFileFolder(this.Configuration, destinationFolder ?? this.Configuration.LibraryFolder);
var originalArtistFolder =
Artist.ArtistFileFolder(Configuration, destinationFolder ?? Configuration.LibraryFolder);
var originalName = Artist.Name;
var originalSortName = Artist.SortName;
Artist.LastUpdated = now;
await this.DbContext.SaveChangesAsync();
await DbContext.SaveChangesAsync();
this.DbContext.ArtistGenres.RemoveRange((from at in this.DbContext.ArtistGenres
where at.ArtistId == Artist.Id
select at));
DbContext.ArtistGenres.RemoveRange(from at in DbContext.ArtistGenres
where at.ArtistId == Artist.Id
select at);
Artist.Genres = artistGenreTables;
this.DbContext.ArtistAssociations.RemoveRange((from at in this.DbContext.ArtistAssociations
where at.ArtistId == Artist.Id
select at));
DbContext.ArtistAssociations.RemoveRange(from at in DbContext.ArtistAssociations
where at.ArtistId == Artist.Id
select at);
Artist.AssociatedArtists = artistAssociatedWith;
Artist.SimilarArtists = similarArtists;
await this.DbContext.SaveChangesAsync();
await DbContext.SaveChangesAsync();
var existingImageIds = (from ai in ArtistImages
where ai.Status != Statuses.New
select ai.RoadieId).ToArray();
this.DbContext.Images.RemoveRange((from i in this.DbContext.Images
where i.ArtistId == Artist.Id
where !(from x in existingImageIds select x).Contains(i.RoadieId)
select i));
await this.DbContext.SaveChangesAsync();
DbContext.Images.RemoveRange(from i in DbContext.Images
where i.ArtistId == Artist.Id
where !(from x in existingImageIds select x).Contains(i.RoadieId)
select i);
await DbContext.SaveChangesAsync();
if (ArtistImages != null && ArtistImages.Any(x => x.Status == Statuses.New))
{
foreach (var ArtistImage in ArtistImages.Where(x => x.Status == Statuses.New))
{
this.DbContext.Images.Add(ArtistImage);
}
DbContext.Images.Add(ArtistImage);
try
{
await this.DbContext.SaveChangesAsync();
await DbContext.SaveChangesAsync();
}
catch (Exception ex)
{
this.Logger.LogError(ex, ex.Serialize());
Logger.LogError(ex, ex.Serialize());
}
}
var newArtistFolder = Artist.ArtistFileFolder(this.Configuration, destinationFolder ?? this.Configuration.LibraryFolder);
var newArtistFolder =
Artist.ArtistFileFolder(Configuration, destinationFolder ?? Configuration.LibraryFolder);
if (!originalArtistFolder.Equals(newArtistFolder, StringComparison.OrdinalIgnoreCase))
{
this.Logger.LogTrace("Moving Artist From Folder [{0}] To [{1}]", originalArtistFolder, newArtistFolder);
// Directory.Move(originalArtistFolder, Artist.ArtistFileFolder(destinationFolder ?? SettingsHelper.Instance.LibraryFolder));
// TODO if name changed then update Artist track files to have new Artist name
}
this.CacheManager.ClearRegion(Artist.CacheRegion);
Logger.LogTrace("Moving Artist From Folder [{0}] To [{1}]", originalArtistFolder, newArtistFolder);
// Directory.Move(originalArtistFolder, Artist.ArtistFileFolder(destinationFolder ?? SettingsHelper.Instance.LibraryFolder));
// TODO if name changed then update Artist track files to have new Artist name
CacheManager.ClearRegion(Artist.CacheRegion);
sw.Stop();
return new OperationResult<Artist>

View file

@ -15,107 +15,113 @@ namespace Roadie.Library.Factories
public abstract class FactoryBase
{
protected IArtistLookupEngine ArtistLookupEngine { get; }
protected ICacheManager CacheManager { get; }
protected IRoadieSettings Configuration { get; }
protected IRoadieDbContext DbContext { get; }
protected ILabelSearchEngine DiscogsLabelSearchEngine { get; }
protected IHttpEncoder HttpEncoder { get; }
protected ILogger Logger { get; }
protected IReleaseLookupEngine ReleaseLookupEngine { get; }
public FactoryBase(IRoadieSettings configuration, IRoadieDbContext context, ICacheManager cacheManager, ILogger logger, IHttpEncoder httpEncoder, IArtistLookupEngine artistLookupEngine, IReleaseLookupEngine releaseLookupEngine)
public FactoryBase(IRoadieSettings configuration, IRoadieDbContext context, ICacheManager cacheManager,
ILogger logger, IHttpEncoder httpEncoder, IArtistLookupEngine artistLookupEngine,
IReleaseLookupEngine releaseLookupEngine)
{
this.Configuration = configuration;
this.DbContext = context;
this.CacheManager = cacheManager;
this.Logger = logger;
this.HttpEncoder = httpEncoder;
Configuration = configuration;
DbContext = context;
CacheManager = cacheManager;
Logger = logger;
HttpEncoder = httpEncoder;
this.ArtistLookupEngine = artistLookupEngine;
this.ReleaseLookupEngine = releaseLookupEngine;
ArtistLookupEngine = artistLookupEngine;
ReleaseLookupEngine = releaseLookupEngine;
}
[Obsolete("Use Service Methods")]
protected IEnumerable<int> ArtistIdsForRelease(int releaseId)
{
var trackArtistIds = (from r in this.DbContext.Releases
join rm in this.DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
join tr in this.DbContext.Tracks on rm.Id equals tr.ReleaseMediaId
where r.Id == releaseId
where tr.ArtistId != null
select tr.ArtistId.Value).ToList();
trackArtistIds.Add(this.DbContext.Releases.FirstOrDefault(x => x.Id == releaseId).ArtistId);
var trackArtistIds = (from r in DbContext.Releases
join rm in DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
join tr in DbContext.Tracks on rm.Id equals tr.ReleaseMediaId
where r.Id == releaseId
where tr.ArtistId != null
select tr.ArtistId.Value).ToList();
trackArtistIds.Add(DbContext.Releases.FirstOrDefault(x => x.Id == releaseId).ArtistId);
return trackArtistIds.Distinct().ToArray();
}
[Obsolete("Use Service Methods")]
protected async Task UpdateArtistCounts(int artistId, DateTime now)
{
var artist = DbContext.Artists.FirstOrDefault(x => x.Id == artistId);
if (artist != null)
{
artist.ReleaseCount = DbContext.Releases.Where(x => x.ArtistId == artistId).Count();
artist.TrackCount = (from r in DbContext.Releases
join rm in DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
join tr in DbContext.Tracks on rm.Id equals tr.ReleaseMediaId
where tr.ArtistId == artistId || r.ArtistId == artistId
select tr).Count();
artist.LastUpdated = now;
await DbContext.SaveChangesAsync();
CacheManager.ClearRegion(artist.CacheRegion);
}
}
[Obsolete("Use Service Methods")]
/// <summary>
/// Update the counts for all artists on a release (both track and release artists)
/// </summary>
protected async Task UpdateArtistCountsForRelease(int releaseId, DateTime now)
{
foreach(var artistId in this.ArtistIdsForRelease(releaseId))
{
await this.UpdateArtistCounts(artistId, now);
}
}
[Obsolete("Use Service Methods")]
protected async Task UpdateArtistCounts(int artistId, DateTime now)
{
var artist = this.DbContext.Artists.FirstOrDefault(x => x.Id == artistId);
if (artist != null)
{
artist.ReleaseCount = this.DbContext.Releases.Where(x => x.ArtistId == artistId).Count();
artist.TrackCount = (from r in this.DbContext.Releases
join rm in this.DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
join tr in this.DbContext.Tracks on rm.Id equals tr.ReleaseMediaId
where (tr.ArtistId == artistId || r.ArtistId == artistId)
select tr).Count();
artist.LastUpdated = now;
await this.DbContext.SaveChangesAsync();
this.CacheManager.ClearRegion(artist.CacheRegion);
}
foreach (var artistId in ArtistIdsForRelease(releaseId)) await UpdateArtistCounts(artistId, now);
}
[Obsolete("Use Service Methods")]
protected async Task UpdateLabelCounts(int labelId, DateTime now)
{
var label = this.DbContext.Labels.FirstOrDefault(x => x.Id == labelId);
var label = DbContext.Labels.FirstOrDefault(x => x.Id == labelId);
if (label != null)
{
label.ReleaseCount = this.DbContext.ReleaseLabels.Where(x => x.LabelId == label.Id).Count();
label.ArtistCount = (from r in this.DbContext.Releases
join rl in this.DbContext.ReleaseLabels on r.Id equals rl.ReleaseId
join a in this.DbContext.Artists on r.ArtistId equals a.Id
label.ReleaseCount = DbContext.ReleaseLabels.Where(x => x.LabelId == label.Id).Count();
label.ArtistCount = (from r in DbContext.Releases
join rl in DbContext.ReleaseLabels on r.Id equals rl.ReleaseId
join a in DbContext.Artists on r.ArtistId equals a.Id
where rl.LabelId == label.Id
group a by a.Id into artists
group a by a.Id
into artists
select artists).Select(x => x.Key).Count();
label.TrackCount = (from r in this.DbContext.Releases
join rl in this.DbContext.ReleaseLabels on r.Id equals rl.ReleaseId
join rm in this.DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
join t in this.DbContext.Tracks on rm.Id equals t.ReleaseMediaId
label.TrackCount = (from r in DbContext.Releases
join rl in DbContext.ReleaseLabels on r.Id equals rl.ReleaseId
join rm in DbContext.ReleaseMedias on r.Id equals rm.ReleaseId
join t in DbContext.Tracks on rm.Id equals t.ReleaseMediaId
where rl.LabelId == label.Id
select t).Count();
await this.DbContext.SaveChangesAsync();
this.CacheManager.ClearRegion(label.CacheRegion);
await DbContext.SaveChangesAsync();
CacheManager.ClearRegion(label.CacheRegion);
}
}
[Obsolete("Use Service Methods")]
protected async Task UpdateReleaseCounts(int releaseId, DateTime now)
{
var release = this.DbContext.Releases.FirstOrDefault(x => x.Id == releaseId);
var release = DbContext.Releases.FirstOrDefault(x => x.Id == releaseId);
if (release != null)
{
release.Duration = (from t in this.DbContext.Tracks
join rm in this.DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
release.Duration = (from t in DbContext.Tracks
join rm in DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
where rm.ReleaseId == releaseId
select t).Sum(x => x.Duration);
await this.DbContext.SaveChangesAsync();
this.CacheManager.ClearRegion(release.CacheRegion);
await DbContext.SaveChangesAsync();
CacheManager.ClearRegion(release.CacheRegion);
}
}
}

View file

@ -11,14 +11,17 @@ namespace Roadie.Library.Factories
Task<OperationResult<bool>> Delete(Guid RoadieId);
OperationResult<Artist> GetByExternalIds(string musicBrainzId = null, string iTunesId = null, string amgId = null, string spotifyId = null);
OperationResult<Artist> GetByExternalIds(string musicBrainzId = null, string iTunesId = null,
string amgId = null, string spotifyId = null);
Task<OperationResult<Artist>> MergeArtists(Artist ArtistToMerge, Artist artistToMergeInto, bool doDbUpdates = false);
Task<OperationResult<Artist>> MergeArtists(Artist ArtistToMerge, Artist artistToMergeInto,
bool doDbUpdates = false);
Task<OperationResult<bool>> RefreshArtistMetadata(Guid ArtistId);
Task<OperationResult<bool>> ScanArtistReleasesFolders(Guid artistId, string destinationFolder, bool doJustInfo);
Task<OperationResult<Artist>> Update(Artist Artist, IEnumerable<Image> ArtistImages, string destinationFolder = null);
Task<OperationResult<Artist>> Update(Artist Artist, IEnumerable<Image> ArtistImages,
string destinationFolder = null);
}
}

View file

@ -1,10 +1,6 @@
using Roadie.Library.Data;
using System.Threading.Tasks;
namespace Roadie.Library.Factories
namespace Roadie.Library.Factories
{
public interface ILabelFactory
{
}
}

View file

@ -1,5 +1,4 @@
using Roadie.Library.Data;
using Roadie.Library.MetaData.Audio;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
@ -10,18 +9,22 @@ namespace Roadie.Library.Factories
{
IEnumerable<int> AddedTrackIds { get; }
Task<OperationResult<bool>> CheckAndChangeReleaseTitle(Release release, string oldReleaseFolder, string destinationFolder = null);
Task<OperationResult<bool>> CheckAndChangeReleaseTitle(Release release, string oldReleaseFolder,
string destinationFolder = null);
Task<OperationResult<bool>> Delete(Release release, bool doDeleteFiles = false, bool doUpdateArtistCounts = true);
Task<OperationResult<bool>> Delete(Release release, bool doDeleteFiles = false,
bool doUpdateArtistCounts = true);
Task<OperationResult<bool>> DeleteReleases(IEnumerable<Guid> releaseIds, bool doDeleteFiles = false);
OperationResult<Release> GetAllForArtist(Artist artist, bool forceRefresh = false);
Task<OperationResult<bool>> MergeReleases(Release releaseToMerge, Release releaseToMergeInto, bool addAsMedia);
Task<OperationResult<bool>> MergeReleases(Release releaseToMerge, Release releaseToMergeInto, bool addAsMedia);
Task<OperationResult<bool>> ScanReleaseFolder(Guid releaseId, string destinationFolder, bool doJustInfo, Release releaseToScan = null);
Task<OperationResult<bool>> ScanReleaseFolder(Guid releaseId, string destinationFolder, bool doJustInfo,
Release releaseToScan = null);
Task<OperationResult<Release>> Update(Release release, IEnumerable<Image> releaseImages, string originalReleaseFolder, string destinationFolder = null);
Task<OperationResult<Release>> Update(Release release, IEnumerable<Image> releaseImages,
string originalReleaseFolder, string destinationFolder = null);
}
}

View file

@ -18,13 +18,15 @@ namespace Roadie.Library.Factories
{
public sealed class ImageFactory : FactoryBase, IImageFactory
{
public ImageFactory(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context, ICacheManager cacheManager, ILogger logger, IArtistLookupEngine artistLookupEngine, IReleaseLookupEngine releaseLookupEngine)
public ImageFactory(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context,
ICacheManager cacheManager, ILogger logger, IArtistLookupEngine artistLookupEngine,
IReleaseLookupEngine releaseLookupEngine)
: base(configuration, context, cacheManager, logger, httpEncoder, artistLookupEngine, releaseLookupEngine)
{
}
/// <summary>
/// Get image data from all sources for either fileanme or MetaData
/// Get image data from all sources for either fileanme or MetaData
/// </summary>
/// <param name="filename">Name of the File (ie a CUE file)</param>
/// <param name="metaData">Populated MetaData</param>
@ -34,11 +36,11 @@ namespace Roadie.Library.Factories
SimpleContract.Requires<ArgumentException>(!string.IsNullOrEmpty(filename), "Invalid Filename");
SimpleContract.Requires<ArgumentException>(metaData != null, "Invalid MetaData");
return this.ImageForFilename(filename);
return ImageForFilename(filename);
}
/// <summary>
/// Does image exist with the same filename
/// Does image exist with the same filename
/// </summary>
/// <param name="filename">Name of the File (ie a CUE file)</param>
/// <returns>Null if not found else populated image</returns>
@ -46,17 +48,14 @@ namespace Roadie.Library.Factories
{
AudioMetaDataImage imageMetaData = null;
if (string.IsNullOrEmpty(filename))
{
return imageMetaData;
}
if (string.IsNullOrEmpty(filename)) return imageMetaData;
try
{
var fileInfo = new FileInfo(filename);
var ReleaseCover = Path.ChangeExtension(filename, "jpg");
if (File.Exists(ReleaseCover))
{
using (var processor = new ImageProcessor(this.Configuration))
using (var processor = new ImageProcessor(Configuration))
{
imageMetaData = new AudioMetaDataImage
{
@ -75,18 +74,14 @@ namespace Roadie.Library.Factories
{
FileInfo picture = null;
// See if there is a "cover" or "front" jpg file if so use it
picture = pictures.FirstOrDefault(x => x.Name.Equals("cover", StringComparison.OrdinalIgnoreCase));
picture = pictures.FirstOrDefault(x =>
x.Name.Equals("cover", StringComparison.OrdinalIgnoreCase));
if (picture == null)
{
picture = pictures.FirstOrDefault(x => x.Name.Equals("front", StringComparison.OrdinalIgnoreCase));
}
if (picture == null)
{
picture = pictures.First();
}
picture = pictures.FirstOrDefault(x =>
x.Name.Equals("front", StringComparison.OrdinalIgnoreCase));
if (picture == null) picture = pictures.First();
if (picture != null)
{
using (var processor = new ImageProcessor(this.Configuration))
using (var processor = new ImageProcessor(Configuration))
{
imageMetaData = new AudioMetaDataImage
{
@ -95,17 +90,17 @@ namespace Roadie.Library.Factories
MimeType = FileProcessor.DetermineFileType(picture)
};
}
}
}
}
}
catch (System.IO.FileNotFoundException)
catch (FileNotFoundException)
{
}
catch (Exception ex)
{
this.Logger.LogError(ex, ex.Serialize());
Logger.LogError(ex, ex.Serialize());
}
return imageMetaData;
}
}

View file

@ -1,31 +1,21 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using MySql.Data.MySqlClient;
using Microsoft.Extensions.Logging;
using Roadie.Library.Caching;
using Roadie.Library.Configuration;
using Roadie.Library.Data;
using Roadie.Library.Encoding;
using Roadie.Library.Engines;
using Roadie.Library.Extensions;
using Roadie.Library.Utility;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace Roadie.Library.Factories
{
public sealed class LabelFactory : FactoryBase, ILabelFactory
{
public LabelFactory(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context, ICacheManager cacheManager, ILogger logger, IArtistLookupEngine artistLookupEngine, IReleaseLookupEngine releaseLookupEngine)
public LabelFactory(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context,
ICacheManager cacheManager, ILogger logger, IArtistLookupEngine artistLookupEngine,
IReleaseLookupEngine releaseLookupEngine)
: base(configuration, context, cacheManager, logger, httpEncoder, artistLookupEngine, releaseLookupEngine)
{
}
// TODO Merge
}
}

View file

@ -14,7 +14,9 @@ namespace Roadie.Library.Factories
{
public class PlaylistFactory : FactoryBase, IPlaylistFactory
{
public PlaylistFactory(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context, ICacheManager cacheManager, ILogger logger, IArtistLookupEngine artistLookupEngine, IReleaseLookupEngine releaseLookupEngine)
public PlaylistFactory(IRoadieSettings configuration, IHttpEncoder httpEncoder, IRoadieDbContext context,
ICacheManager cacheManager, ILogger logger, IArtistLookupEngine artistLookupEngine,
IReleaseLookupEngine releaseLookupEngine)
: base(configuration, context, cacheManager, logger, httpEncoder, artistLookupEngine, releaseLookupEngine)
{
}
@ -28,28 +30,26 @@ namespace Roadie.Library.Factories
var result = false;
var now = DateTime.UtcNow;
var existingTracksForPlaylist = (from plt in this.DbContext.PlaylistTracks
join t in this.DbContext.Tracks on plt.TrackId equals t.Id
where plt.PlayListId == playlist.Id
select t);
var newTracksForPlaylist = (from t in this.DbContext.Tracks
var existingTracksForPlaylist = from plt in DbContext.PlaylistTracks
join t in DbContext.Tracks on plt.TrackId equals t.Id
where plt.PlayListId == playlist.Id
select t;
var newTracksForPlaylist = (from t in DbContext.Tracks
where (from x in trackIds select x).Contains(t.RoadieId)
where !(from x in existingTracksForPlaylist select x.RoadieId).Contains(t.RoadieId)
select t).ToArray();
foreach (var newTrackForPlaylist in newTracksForPlaylist)
{
this.DbContext.PlaylistTracks.Add(new PlaylistTrack
DbContext.PlaylistTracks.Add(new PlaylistTrack
{
TrackId = newTrackForPlaylist.Id,
PlayListId = playlist.Id,
CreatedDate = now
});
}
playlist.LastUpdated = now;
await this.DbContext.SaveChangesAsync();
await DbContext.SaveChangesAsync();
result = true;
var r = await this.ReorderPlaylist(playlist);
var r = await ReorderPlaylist(playlist);
result = result && r.IsSuccess;
return new OperationResult<bool>
@ -70,13 +70,15 @@ namespace Roadie.Library.Factories
if (playlist != null)
{
var looper = 0;
foreach (var playlistTrack in this.DbContext.PlaylistTracks.Where(x => x.PlayListId == playlist.Id).OrderBy(x => x.CreatedDate))
foreach (var playlistTrack in DbContext.PlaylistTracks.Where(x => x.PlayListId == playlist.Id)
.OrderBy(x => x.CreatedDate))
{
looper++;
playlistTrack.ListNumber = looper;
playlistTrack.LastUpdated = now;
}
await this.DbContext.SaveChangesAsync();
await DbContext.SaveChangesAsync();
result = true;
}

File diff suppressed because it is too large Load diff

View file

@ -1,50 +1,52 @@
using System;
using Microsoft.Net.Http.Headers;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Net.Http.Headers;
namespace Roadie.Library
{
/// <summary>
/// A OperationResult specific to a File type request.
/// A OperationResult specific to a File type request.
/// </summary>
public class FileOperationResult<T> : OperationResult<T>
{
public EntityTagHeaderValue ETag { get; set; }
public DateTimeOffset? LastModified { get; set; }
public string ContentType { get; set; }
public EntityTagHeaderValue ETag { get; set; }
public DateTimeOffset? LastModified { get; set; }
public FileOperationResult()
{
}
public FileOperationResult(string message)
{
this.AddMessage(message);
AddMessage(message);
}
public FileOperationResult(bool isNotFoundResult, string message)
{
this.IsNotFoundResult = isNotFoundResult;
this.AddMessage(message);
IsNotFoundResult = isNotFoundResult;
AddMessage(message);
}
public FileOperationResult(IEnumerable<string> messages = null)
{
if (messages != null && messages.Any())
{
this.AdditionalData = new Dictionary<string, object>();
messages.ToList().ForEach(x => this.AddMessage(x));
AdditionalData = new Dictionary<string, object>();
messages.ToList().ForEach(x => AddMessage(x));
}
}
public FileOperationResult(bool isNotFoundResult, IEnumerable<string> messages = null)
{
this.IsNotFoundResult = isNotFoundResult;
IsNotFoundResult = isNotFoundResult;
if (messages != null && messages.Any())
{
this.AdditionalData = new Dictionary<string, object>();
messages.ToList().ForEach(x => this.AddMessage(x));
AdditionalData = new Dictionary<string, object>();
messages.ToList().ForEach(x => AddMessage(x));
}
}
}

View file

@ -4,6 +4,7 @@ using Roadie.Library.Caching;
using Roadie.Library.Configuration;
using Roadie.Library.Encoding;
using Roadie.Library.Engines;
using Roadie.Library.Enums;
using Roadie.Library.Extensions;
using Roadie.Library.Factories;
using Roadie.Library.Imaging;
@ -28,7 +29,7 @@ namespace Roadie.Library.FilePlugins
public override string[] HandlesTypes => new string[1] { "audio/mpeg" };
public Audio(IRoadieSettings configuration,
IHttpEncoder httpEncoder,
IHttpEncoder httpEncoder,
IArtistFactory artistFactory,
IReleaseFactory releaseFactory,
IImageFactory imageFactory,
@ -37,14 +38,18 @@ namespace Roadie.Library.FilePlugins
IArtistLookupEngine artistLookupEngine,
IReleaseLookupEngine releaseLookupEngine,
IAudioMetaDataHelper audioMetaDataHelper)
: base(configuration, httpEncoder, artistFactory, releaseFactory, imageFactory, cacheManager, logger, artistLookupEngine, releaseLookupEngine)
: base(configuration, httpEncoder, artistFactory, releaseFactory, imageFactory, cacheManager, logger,
artistLookupEngine, releaseLookupEngine)
{
this.AudioMetaDataHelper = audioMetaDataHelper;
AudioMetaDataHelper = audioMetaDataHelper;
}
public override async Task<OperationResult<bool>> Process(string destinationRoot, FileInfo fileInfo, bool doJustInfo, int? submissionId)
public override async Task<OperationResult<bool>> Process(string destinationRoot, FileInfo fileInfo,
bool doJustInfo, int? submissionId)
{
this.Logger.LogTrace(">> Audio: Process destinationRoot [{0}], FileInfo [{1}], doJustInfo [{2}], submissionId [{3}]", destinationRoot, fileInfo, doJustInfo, submissionId);
Logger.LogTrace(
">> Audio: Process destinationRoot [{0}], FileInfo [{1}], doJustInfo [{2}], submissionId [{3}]",
destinationRoot, fileInfo, doJustInfo, submissionId);
var sw = Stopwatch.StartNew();
var result = new OperationResult<bool>();
@ -54,24 +59,25 @@ namespace Roadie.Library.FilePlugins
string destinationName = null;
var metaData = await this.AudioMetaDataHelper.GetInfo(fileInfo, doJustInfo);
var metaData = await AudioMetaDataHelper.GetInfo(fileInfo, doJustInfo);
if (!metaData.IsValid)
{
var minWeight = this.MinWeightToDelete;
var minWeight = MinWeightToDelete;
if (metaData.ValidWeight < minWeight && minWeight > 0)
{
this.Logger.LogTrace("Invalid File{3}: ValidWeight [{0}], Under MinWeightToDelete [{1}]. Deleting File [{2}]", metaData.ValidWeight, minWeight, fileInfo.FullName, doJustInfo ? " [Read Only Mode] " : string.Empty);
if (!doJustInfo)
{
fileInfo.Delete();
}
Logger.LogTrace(
"Invalid File{3}: ValidWeight [{0}], Under MinWeightToDelete [{1}]. Deleting File [{2}]",
metaData.ValidWeight, minWeight, fileInfo.FullName,
doJustInfo ? " [Read Only Mode] " : string.Empty);
if (!doJustInfo) fileInfo.Delete();
}
return result;
}
var artist = metaData.Artist.CleanString(this.Configuration);
var album = metaData.Release.CleanString(this.Configuration);
var title = metaData.Title.CleanString(this.Configuration).ToTitleCase(false);
var artist = metaData.Artist.CleanString(Configuration);
var album = metaData.Release.CleanString(Configuration);
var title = metaData.Title.CleanString(Configuration).ToTitleCase(false);
var year = metaData.Year;
var trackNumber = metaData.TrackNumber ?? 0;
var discNumber = metaData.Disc ?? 0;
@ -83,20 +89,26 @@ namespace Roadie.Library.FilePlugins
SimpleContract.Requires<ArgumentException>(year > 0, string.Format("Invalid Track Year [{0}]", year));
SimpleContract.Requires<ArgumentException>(trackNumber > 0, "Missing Track Number");
var artistFolder = await this.DetermineArtistFolder(dr, metaData, doJustInfo);
var artistFolder = await DetermineArtistFolder(dr, metaData, doJustInfo);
if (string.IsNullOrEmpty(artistFolder))
{
this.Logger.LogWarning("Unable To Find ArtistFolder [{0}] For MetaData [{1}]", artistFolder, metaData.ToString());
Logger.LogWarning("Unable To Find ArtistFolder [{0}] For MetaData [{1}]", artistFolder,
metaData.ToString());
return new OperationResult<bool>("Unable To Find Artist Folder");
}
var releaseFolder = await this.DetermineReleaseFolder(artistFolder, metaData, doJustInfo, submissionId);
var releaseFolder = await DetermineReleaseFolder(artistFolder, metaData, doJustInfo, submissionId);
if (string.IsNullOrEmpty(releaseFolder))
{
this.Logger.LogWarning("Unable To Find ReleaseFolder For MetaData [{0}]", metaData.ToString());
Logger.LogWarning("Unable To Find ReleaseFolder For MetaData [{0}]", metaData.ToString());
return new OperationResult<bool>("Unable To Find Release Folder");
}
destinationName = FolderPathHelper.TrackFullPath(this.Configuration, metaData, dr, artistFolder, releaseFolder);
this.Logger.LogTrace("Info: FileInfo [{0}], Artist Folder [{1}], Release Folder [{1}], Destination Name [{3}]", fileInfo.FullName, artistFolder, releaseFolder, destinationName);
destinationName =
FolderPathHelper.TrackFullPath(Configuration, metaData, dr, artistFolder, releaseFolder);
Logger.LogTrace(
"Info: FileInfo [{0}], Artist Folder [{1}], Release Folder [{1}], Destination Name [{3}]",
fileInfo.FullName, artistFolder, releaseFolder, destinationName);
if (doJustInfo)
{
@ -104,21 +116,16 @@ namespace Roadie.Library.FilePlugins
return result;
}
if(PluginBase.CheckMakeFolder(artistFolder))
{
this.Logger.LogTrace("Created ArtistFolder [{0}]", artistFolder);
}
if(PluginBase.CheckMakeFolder(releaseFolder))
{
this.Logger.LogTrace("Created ReleaseFolder [{0}]", releaseFolder);
}
if (CheckMakeFolder(artistFolder)) Logger.LogTrace("Created ArtistFolder [{0}]", artistFolder);
if (CheckMakeFolder(releaseFolder)) Logger.LogTrace("Created ReleaseFolder [{0}]", releaseFolder);
try
{
// See if file folder parent folder (likely file is in release folder) has primary artist image if so then move to artist folder
var artistImages = new List<FileInfo>();
artistImages.AddRange(ImageHelper.FindImageTypeInDirectory(fileInfo.Directory, Enums.ImageType.Artist));
artistImages.AddRange(ImageHelper.FindImageTypeInDirectory(fileInfo.Directory.Parent, Enums.ImageType.Artist));
artistImages.AddRange(ImageHelper.FindImageTypeInDirectory(fileInfo.Directory, ImageType.Artist));
artistImages.AddRange(
ImageHelper.FindImageTypeInDirectory(fileInfo.Directory.Parent, ImageType.Artist));
if (artistImages.Any())
{
var artistImage = artistImages.First();
@ -135,21 +142,25 @@ namespace Roadie.Library.FilePlugins
File.WriteAllBytes(artistImageFilename, imageBytes);
artistImage.Delete();
}
this.Logger.LogDebug("Found Artist Image File [{0}], Moved to artist folder.", artistImage.Name);
Logger.LogDebug("Found Artist Image File [{0}], Moved to artist folder.", artistImage.Name);
}
}
// See if any secondary artist images if so then move to artist folder
artistImages.Clear();
artistImages.AddRange(ImageHelper.FindImageTypeInDirectory(fileInfo.Directory, Enums.ImageType.ArtistSecondary));
artistImages.AddRange(ImageHelper.FindImageTypeInDirectory(fileInfo.Directory.Parent, Enums.ImageType.Artist));
artistImages.AddRange(
ImageHelper.FindImageTypeInDirectory(fileInfo.Directory, ImageType.ArtistSecondary));
artistImages.AddRange(
ImageHelper.FindImageTypeInDirectory(fileInfo.Directory.Parent, ImageType.Artist));
if (artistImages.Any())
{
var looper = 0;
foreach (var artistImage in artistImages)
{
looper++;
var artistImageFilename = Path.Combine(artistFolder, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
var artistImageFilename = Path.Combine(artistFolder,
string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
if (artistImageFilename != artistImage.FullName)
{
// Read image and convert to jpeg
@ -162,18 +173,24 @@ namespace Roadie.Library.FilePlugins
while (File.Exists(artistImageFilename))
{
looper++;
artistImageFilename = Path.Combine(artistFolder, string.Format(ImageHelper.ArtistSecondaryImageFilename, looper.ToString("00")));
artistImageFilename = Path.Combine(artistFolder,
string.Format(ImageHelper.ArtistSecondaryImageFilename,
looper.ToString("00")));
}
File.WriteAllBytes(artistImageFilename, imageBytes);
artistImage.Delete();
}
this.Logger.LogDebug("Found Artist Secondary Image File [{0}], Moved to artist folder [{1}].", artistImage.Name, artistImageFilename);
Logger.LogDebug(
"Found Artist Secondary Image File [{0}], Moved to artist folder [{1}].",
artistImage.Name, artistImageFilename);
}
}
}
// See if file folder has release image if so then move to release folder
var releaseImages = ImageHelper.FindImageTypeInDirectory(fileInfo.Directory, Enums.ImageType.Release);
var releaseImages = ImageHelper.FindImageTypeInDirectory(fileInfo.Directory, ImageType.Release);
if (releaseImages.Any())
{
var releaseImage = releaseImages.First();
@ -190,19 +207,23 @@ namespace Roadie.Library.FilePlugins
File.WriteAllBytes(coverFileName, imageBytes);
releaseImage.Delete();
}
this.Logger.LogDebug("Found Release Image File [{0}], Moved to release folder", releaseImage.Name);
Logger.LogDebug("Found Release Image File [{0}], Moved to release folder",
releaseImage.Name);
}
}
// See if folder has secondary release image if so then move to release folder
releaseImages = ImageHelper.FindImageTypeInDirectory(fileInfo.Directory, Enums.ImageType.ReleaseSecondary);
releaseImages =
ImageHelper.FindImageTypeInDirectory(fileInfo.Directory, ImageType.ReleaseSecondary);
if (releaseImages.Any())
{
var looper = 0;
foreach (var releaseImage in releaseImages)
{
looper++;
var releaseImageFilename = Path.Combine(releaseFolder, string.Format(ImageHelper.ReleaseSecondaryImageFilename, looper.ToString("00")));
var releaseImageFilename = Path.Combine(releaseFolder,
string.Format(ImageHelper.ReleaseSecondaryImageFilename, looper.ToString("00")));
if (releaseImageFilename != releaseImage.FullName)
{
// Read image and convert to jpeg
@ -215,15 +236,16 @@ namespace Roadie.Library.FilePlugins
File.WriteAllBytes(releaseImageFilename, imageBytes);
releaseImage.Delete();
}
this.Logger.LogDebug("Found Release Image File [{0}], Moved to release folder [{1}]", releaseImage.Name, releaseImageFilename);
Logger.LogDebug("Found Release Image File [{0}], Moved to release folder [{1}]",
releaseImage.Name, releaseImageFilename);
}
}
}
}
catch (Exception ex)
{
this.Logger.LogError(ex, "Error with Managing Images For [{0}]", fileInfo.FullName);
Logger.LogError(ex, "Error with Managing Images For [{0}]", fileInfo.FullName);
}
var doesFileExistsForTrack = File.Exists(destinationName);
@ -232,17 +254,19 @@ namespace Roadie.Library.FilePlugins
var existing = new FileInfo(destinationName);
// If Exists determine which is better - if same do nothing
var existingMetaData = await this.AudioMetaDataHelper.GetInfo(existing, doJustInfo);
var existingMetaData = await AudioMetaDataHelper.GetInfo(existing, doJustInfo);
var areSameFile = existing.FullName.Replace("\\", "").Replace("/", "").Equals(fileInfo.FullName.Replace("\\", "").Replace("/", ""), StringComparison.OrdinalIgnoreCase);
var areSameFile = existing.FullName.Replace("\\", "").Replace("/", "")
.Equals(fileInfo.FullName.Replace("\\", "").Replace("/", ""),
StringComparison.OrdinalIgnoreCase);
var currentBitRate = metaData.AudioBitrate;
var existingBitRate = existingMetaData.AudioBitrate;
if (!areSameFile)
{
if (!existingMetaData.IsValid || (currentBitRate > existingBitRate))
if (!existingMetaData.IsValid || currentBitRate > existingBitRate)
{
this.Logger.LogTrace("Newer Is Better: Deleting Existing File [{0}]", existing);
Logger.LogTrace("Newer Is Better: Deleting Existing File [{0}]", existing);
if (!doJustInfo)
{
existing.Delete();
@ -251,36 +275,32 @@ namespace Roadie.Library.FilePlugins
}
else
{
this.Logger.LogTrace("Existing [{0}] Is Better or Equal: Deleting Found File [{1}]", existing, fileInfo.FullName);
if (!doJustInfo)
{
fileInfo.Delete();
}
Logger.LogTrace("Existing [{0}] Is Better or Equal: Deleting Found File [{1}]", existing,
fileInfo.FullName);
if (!doJustInfo) fileInfo.Delete();
}
}
}
else
{
this.Logger.LogTrace("Moving File To [{0}]", destinationName);
Logger.LogTrace("Moving File To [{0}]", destinationName);
if (!doJustInfo)
{
try
{
fileInfo.MoveTo(destinationName);
}
catch (Exception ex)
{
this.Logger.LogError(ex, "Error Moving File [{0}}", destinationName);
Logger.LogError(ex, "Error Moving File [{0}}", destinationName);
}
}
}
result.AdditionalData.Add(PluginResultInfo.AdditionalDataKeyPluginResultInfo, new PluginResultInfo
{
ArtistFolder = artistFolder,
ArtistId = this._artistId,
ArtistId = _artistId,
ReleaseFolder = releaseFolder,
ReleaseId = this._releaseId,
ReleaseId = _releaseId,
Filename = fileInfo.FullName,
TrackNumber = metaData.TrackNumber,
TrackTitle = metaData.Title
@ -289,51 +309,46 @@ namespace Roadie.Library.FilePlugins
}
catch (Exception ex)
{
this.Logger.LogError(ex, "Error Processing File [{0}}", fileInfo);
Logger.LogError(ex, "Error Processing File [{0}}", fileInfo);
}
sw.Stop();
this.Logger.LogTrace("<< Audio: Process Complete. Result `{0}`, ElapsedTime [{1}]", JsonConvert.SerializeObject(result), sw.ElapsedMilliseconds);
Logger.LogTrace("<< Audio: Process Complete. Result `{0}`, ElapsedTime [{1}]",
JsonConvert.SerializeObject(result), sw.ElapsedMilliseconds);
return result;
}
private async Task<string> DetermineArtistFolder(string destinationRoot, AudioMetaData metaData, bool doJustInfo)
private async Task<string> DetermineArtistFolder(string destinationRoot, AudioMetaData metaData,
bool doJustInfo)
{
var artist = await this.ArtistLookupEngine.GetByName(metaData, !doJustInfo);
if (!artist.IsSuccess)
{
return null;
}
var artist = await ArtistLookupEngine.GetByName(metaData, !doJustInfo);
if (!artist.IsSuccess) return null;
try
{
return artist.Data.ArtistFileFolder(this.Configuration, destinationRoot);
return artist.Data.ArtistFileFolder(Configuration, destinationRoot);
}
catch (Exception ex)
{
this.Logger.LogError(ex, ex.Serialize());
Logger.LogError(ex, ex.Serialize());
}
return null;
}
private async Task<string> DetermineReleaseFolder(string artistFolder, AudioMetaData metaData, bool doJustInfo, int? submissionId)
private async Task<string> DetermineReleaseFolder(string artistFolder, AudioMetaData metaData, bool doJustInfo,
int? submissionId)
{
var artist = await this.ArtistLookupEngine.GetByName(metaData, !doJustInfo);
if (!artist.IsSuccess)
{
return null;
}
this._artistId = artist.Data.RoadieId;
var release = await this.ReleaseLookupEngine.GetByName(artist.Data, metaData, !doJustInfo, submissionId: submissionId);
if (!release.IsSuccess)
{
return null;
}
this._releaseId = release.Data.RoadieId;
var artist = await ArtistLookupEngine.GetByName(metaData, !doJustInfo);
if (!artist.IsSuccess) return null;
_artistId = artist.Data.RoadieId;
var release =
await ReleaseLookupEngine.GetByName(artist.Data, metaData, !doJustInfo, submissionId: submissionId);
if (!release.IsSuccess) return null;
_releaseId = release.Data.RoadieId;
release.Data.ReleaseDate = SafeParser.ToDateTime(release.Data.ReleaseYear ?? metaData.Year);
if(release.Data.ReleaseYear.HasValue && release.Data.ReleaseYear != metaData.Year)
{
this.Logger.LogWarning($"Found Release `{ release.Data }` has different Release Year than MetaData Year `{ metaData }`");
}
if (release.Data.ReleaseYear.HasValue && release.Data.ReleaseYear != metaData.Year)
Logger.LogWarning(
$"Found Release `{release.Data}` has different Release Year than MetaData Year `{metaData}`");
return release.Data.ReleaseFileFolder(artistFolder);
}
}

View file

@ -4,13 +4,9 @@ using Roadie.Library.Configuration;
using Roadie.Library.Encoding;
using Roadie.Library.Engines;
using Roadie.Library.Factories;
using Roadie.Library.MetaData.ID3Tags;
using Roadie.Library.Utility;
using System;
using System.Diagnostics;
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Threading.Tasks;
namespace Roadie.Library.FilePlugins
@ -19,16 +15,11 @@ namespace Roadie.Library.FilePlugins
{
public abstract string[] HandlesTypes { get; }
public int MinWeightToDelete
{
get
{
return this.Configuration.FilePlugins.MinWeightToDelete;
}
}
public int MinWeightToDelete => Configuration.FilePlugins.MinWeightToDelete;
protected IArtistFactory ArtistFactory { get; }
protected IArtistLookupEngine ArtistLookupEngine { get; }
protected ICacheManager CacheManager { get; }
@ -42,25 +33,25 @@ namespace Roadie.Library.FilePlugins
protected IReleaseFactory ReleaseFactory { get; }
protected IArtistLookupEngine ArtistLookupEngine { get; }
protected IReleaseLookupEngine ReleaseLookupEngine { get; }
public PluginBase(IRoadieSettings configuration, IHttpEncoder httpEncoder, IArtistFactory artistFactory, IReleaseFactory releaseFactory, IImageFactory imageFactory, ICacheManager cacheManager, ILogger logger, IArtistLookupEngine artistLookupEngine, IReleaseLookupEngine releaseLookupEngine)
public PluginBase(IRoadieSettings configuration, IHttpEncoder httpEncoder, IArtistFactory artistFactory,
IReleaseFactory releaseFactory, IImageFactory imageFactory, ICacheManager cacheManager, ILogger logger,
IArtistLookupEngine artistLookupEngine, IReleaseLookupEngine releaseLookupEngine)
{
this.Configuration = configuration;
this.HttpEncoder = httpEncoder;
this.ArtistFactory = artistFactory;
this.ReleaseFactory = releaseFactory;
this.ImageFactory = imageFactory;
this.CacheManager = cacheManager;
this.Logger = logger;
this.ArtistLookupEngine = artistLookupEngine;
this.ReleaseLookupEngine = releaseLookupEngine;
Configuration = configuration;
HttpEncoder = httpEncoder;
ArtistFactory = artistFactory;
ReleaseFactory = releaseFactory;
ImageFactory = imageFactory;
CacheManager = cacheManager;
Logger = logger;
ArtistLookupEngine = artistLookupEngine;
ReleaseLookupEngine = releaseLookupEngine;
}
/// <summary>
/// Check if exists if not make given folder
/// Check if exists if not make given folder
/// </summary>
/// <param name="folder">Folder To Check</param>
/// <returns>False if Exists, True if Made</returns>
@ -73,11 +64,12 @@ namespace Roadie.Library.FilePlugins
Directory.CreateDirectory(folder);
return true;
}
return false;
return false;
}
public abstract Task<OperationResult<bool>> Process(string destinationRoot, FileInfo fileInfo, bool doJustInfo, int? submissionId);
public abstract Task<OperationResult<bool>> Process(string destinationRoot, FileInfo fileInfo, bool doJustInfo,
int? submissionId);
protected virtual bool IsFileLocked(FileInfo file)
{
@ -93,10 +85,7 @@ namespace Roadie.Library.FilePlugins
}
finally
{
if (stream != null)
{
stream.Close();
}
if (stream != null) stream.Close();
}
//file is not locked

View file

@ -10,18 +10,26 @@ namespace Roadie.Library.FilePlugins
public const string AdditionalDataKeyPluginResultInfo = "PluginResultInfo";
public string ArtistFolder { get; set; }
public Guid ArtistId { get; set; }
public IEnumerable<string> ArtistNames { get; set; }
public string Filename { get; set; }
public string ReleaseFolder { get; set; }
public Guid ReleaseId { get; set; }
public Statuses Status { get; set; }
public short? TrackNumber { get; set; }
public string TrackTitle { get; set; }
public PluginResultInfo()
{
this.Status = Statuses.Incomplete;
Status = Statuses.Incomplete;
}
}
}

View file

@ -7,10 +7,9 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Roadie.Library.Identity
{
[Table("userrole")]
public partial class ApplicationRole : IdentityRole<int>
public class ApplicationRole : IdentityRole<int>
{
[Column("createdDate")]
public DateTime? CreatedDate { get; set; }
[Column("createdDate")] public DateTime? CreatedDate { get; set; }
[Column("description")]
[StringLength(200)]
@ -20,11 +19,9 @@ namespace Roadie.Library.Identity
//[Key]
//public override int Id { get; set; }
[Column("isLocked")]
public bool? IsLocked { get; set; }
[Column("isLocked")] public bool? IsLocked { get; set; }
[Column("lastUpdated")]
public DateTime? LastUpdated { get; set; }
[Column("lastUpdated")] public DateTime? LastUpdated { get; set; }
[Column("name")]
[Required]
@ -37,8 +34,7 @@ namespace Roadie.Library.Identity
public virtual ICollection<ApplicationRoleClaim> RoleClaims { get; set; }
[Column("status")]
public short? Status { get; set; }
[Column("status")] public short? Status { get; set; }
public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}

View file

@ -8,7 +8,6 @@ namespace Roadie.Library.Identity
{
public virtual ApplicationRole Role { get; set; }
[Column("userRoleId")]
public override int RoleId { get; set; }
[Column("userRoleId")] public override int RoleId { get; set; }
}
}

Some files were not shown because too many files have changed in this diff Show more