2018-11-06 22:59:48 +00:00
using Mapster ;
2018-12-26 21:18:51 +00:00
using Microsoft.AspNetCore.Http ;
2018-11-06 22:59:48 +00:00
using Microsoft.EntityFrameworkCore ;
using Microsoft.Extensions.Logging ;
2018-12-05 16:04:21 +00:00
using Newtonsoft.Json ;
2018-11-06 04:31:25 +00:00
using Roadie.Library ;
using Roadie.Library.Caching ;
using Roadie.Library.Configuration ;
using Roadie.Library.Encoding ;
2018-12-27 17:37:17 +00:00
using Roadie.Library.Engines ;
2018-11-06 22:59:48 +00:00
using Roadie.Library.Enums ;
using Roadie.Library.Extensions ;
2018-12-27 17:37:17 +00:00
using Roadie.Library.Factories ;
2018-12-26 21:18:51 +00:00
using Roadie.Library.Imaging ;
2018-12-27 17:37:17 +00:00
using Roadie.Library.MetaData.Audio ;
using Roadie.Library.MetaData.FileName ;
using Roadie.Library.MetaData.ID3Tags ;
using Roadie.Library.MetaData.LastFm ;
2018-11-06 04:31:25 +00:00
using Roadie.Library.Models ;
using Roadie.Library.Models.Pagination ;
2018-11-06 22:59:48 +00:00
using Roadie.Library.Models.Releases ;
using Roadie.Library.Models.Statistics ;
using Roadie.Library.Models.Users ;
2019-01-08 22:40:26 +00:00
using Roadie.Library.Processors ;
2018-11-06 22:59:48 +00:00
using Roadie.Library.Utility ;
2018-11-06 04:31:25 +00:00
using System ;
using System.Collections.Generic ;
2018-11-06 21:55:31 +00:00
using System.Diagnostics ;
2018-12-26 21:18:51 +00:00
using System.IO ;
2018-11-06 22:59:48 +00:00
using System.Linq ;
2018-11-14 14:00:08 +00:00
using System.Linq.Dynamic.Core ;
2018-11-06 04:31:25 +00:00
using System.Threading.Tasks ;
using data = Roadie . Library . Data ;
2019-01-08 22:40:26 +00:00
using mb = Roadie . Library . MetaData . MusicBrainz ;
2018-11-06 04:31:25 +00:00
namespace Roadie.Api.Services
{
public class ArtistService : ServiceBase , IArtistService
{
2019-01-08 22:40:26 +00:00
private IArtistFactory ArtistFactory { get ; }
2018-12-27 17:37:17 +00:00
private IArtistLookupEngine ArtistLookupEngine { get ; }
private IAudioMetaDataHelper AudioMetaDataHelper { get ; }
2019-01-08 22:40:26 +00:00
private IBookmarkService BookmarkService { get ; } = null ;
private ICollectionService CollectionService { get ; } = null ;
2018-12-27 17:37:17 +00:00
private IFileNameHelper FileNameHelper { get ; }
private IID3TagsHelper ID3TagsHelper { get ; }
private IImageFactory ImageFactory { get ; }
private ILabelFactory LabelFactory { get ; }
private ILabelLookupEngine LabelLookupEngine { get ; }
private ILastFmHelper LastFmHelper { get ; }
private mb . IMusicBrainzProvider MusicBrainzProvider { get ; }
2019-01-08 22:40:26 +00:00
private IPlaylistService PlaylistService { get ; } = null ;
2018-12-27 17:37:17 +00:00
private IReleaseFactory ReleaseFactory { get ; }
private IReleaseLookupEngine ReleaseLookupEngine { get ; }
2018-11-06 22:59:48 +00:00
public ArtistService ( IRoadieSettings configuration ,
2018-11-06 21:55:31 +00:00
IHttpEncoder httpEncoder ,
IHttpContext httpContext ,
2018-12-27 17:37:17 +00:00
data . IRoadieDbContext dbContext ,
2018-11-06 21:55:31 +00:00
ICacheManager cacheManager ,
2018-11-07 04:33:22 +00:00
ILogger < ArtistService > logger ,
ICollectionService collectionService ,
2018-11-24 17:52:15 +00:00
IPlaylistService playlistService ,
IBookmarkService bookmarkService
)
2018-12-27 17:37:17 +00:00
: base ( configuration , httpEncoder , dbContext , cacheManager , logger , httpContext )
2018-11-06 04:31:25 +00:00
{
2018-11-07 04:33:22 +00:00
this . CollectionService = collectionService ;
this . PlaylistService = playlistService ;
2018-11-24 17:52:15 +00:00
this . BookmarkService = bookmarkService ;
2018-12-27 17:37:17 +00:00
2018-12-27 20:42:51 +00:00
this . MusicBrainzProvider = new mb . MusicBrainzProvider ( configuration , cacheManager , logger ) ;
this . LastFmHelper = new LastFmHelper ( configuration , cacheManager , logger ) ;
this . FileNameHelper = new FileNameHelper ( configuration , cacheManager , logger ) ;
this . ID3TagsHelper = new ID3TagsHelper ( configuration , cacheManager , logger ) ;
2018-12-27 17:37:17 +00:00
this . ArtistLookupEngine = new ArtistLookupEngine ( configuration , httpEncoder , dbContext , cacheManager , logger ) ;
this . LabelLookupEngine = new LabelLookupEngine ( configuration , httpEncoder , dbContext , cacheManager , logger ) ;
this . ReleaseLookupEngine = new ReleaseLookupEngine ( configuration , httpEncoder , dbContext , cacheManager , logger , this . ArtistLookupEngine , this . LabelLookupEngine ) ;
this . ImageFactory = new ImageFactory ( configuration , httpEncoder , dbContext , cacheManager , logger , this . ArtistLookupEngine , this . ReleaseLookupEngine ) ;
this . LabelFactory = new LabelFactory ( configuration , httpEncoder , dbContext , cacheManager , logger , this . ArtistLookupEngine , this . ReleaseLookupEngine ) ;
this . AudioMetaDataHelper = new AudioMetaDataHelper ( configuration , httpEncoder , dbContext , this . MusicBrainzProvider , this . LastFmHelper , cacheManager ,
logger , this . ArtistLookupEngine , this . ImageFactory , this . FileNameHelper , this . ID3TagsHelper ) ;
this . ReleaseFactory = new ReleaseFactory ( configuration , httpEncoder , dbContext , cacheManager , logger , this . ArtistLookupEngine , this . LabelFactory , this . AudioMetaDataHelper , this . ReleaseLookupEngine ) ;
this . ArtistFactory = new ArtistFactory ( configuration , httpEncoder , dbContext , cacheManager , logger , this . ArtistLookupEngine , this . ReleaseFactory , this . ImageFactory , this . ReleaseLookupEngine , this . AudioMetaDataHelper ) ;
2018-11-06 04:31:25 +00:00
}
2018-11-14 03:19:28 +00:00
public async Task < OperationResult < Artist > > ById ( User roadieUser , Guid id , IEnumerable < string > includes )
2018-11-06 04:31:25 +00:00
{
2018-12-05 16:04:21 +00:00
var timings = new Dictionary < string , long > ( ) ;
var tsw = new Stopwatch ( ) ;
2018-11-06 21:55:31 +00:00
var sw = Stopwatch . StartNew ( ) ;
sw . Start ( ) ;
2018-11-10 18:03:54 +00:00
var cacheKey = string . Format ( "urn:artist_by_id_operation:{0}:{1}" , id , includes = = null ? "0" : string . Join ( "|" , includes ) ) ;
2018-11-14 23:18:02 +00:00
var result = await this . CacheManager . GetAsync < OperationResult < Artist > > ( cacheKey , async ( ) = >
{
2018-12-05 16:04:21 +00:00
tsw . Restart ( ) ;
var rr = await this . ArtistByIdAction ( id , includes ) ;
tsw . Stop ( ) ;
timings . Add ( "ArtistByIdAction" , tsw . ElapsedMilliseconds ) ;
return rr ;
2018-11-11 16:20:33 +00:00
} , data . Artist . CacheRegionUrn ( id ) ) ;
2018-11-14 23:18:02 +00:00
if ( result ? . Data ! = null & & roadieUser ! = null )
2018-11-14 03:19:28 +00:00
{
2018-12-05 16:04:21 +00:00
tsw . Restart ( ) ;
2018-11-14 03:19:28 +00:00
var artist = this . GetArtist ( id ) ;
2018-12-05 16:04:21 +00:00
tsw . Stop ( ) ;
timings . Add ( "GetArtist" , tsw . ElapsedMilliseconds ) ;
tsw . Restart ( ) ;
2018-11-24 17:52:15 +00:00
var userBookmarkResult = await this . BookmarkService . List ( roadieUser , new PagedRequest ( ) , false , BookmarkType . Artist ) ;
2018-12-05 16:04:21 +00:00
if ( userBookmarkResult . IsSuccess )
2018-11-24 17:52:15 +00:00
{
2018-12-04 23:26:27 +00:00
result . Data . UserBookmarked = userBookmarkResult ? . Rows ? . FirstOrDefault ( x = > x . Bookmark . Value = = artist . RoadieId . ToString ( ) ) ! = null ;
2018-11-24 17:52:15 +00:00
}
2018-12-05 16:04:21 +00:00
tsw . Stop ( ) ;
timings . Add ( "userBookmarkResult" , tsw . ElapsedMilliseconds ) ;
tsw . Restart ( ) ;
2018-11-14 03:19:28 +00:00
var userArtist = this . DbContext . UserArtists . FirstOrDefault ( x = > x . ArtistId = = artist . Id & & x . UserId = = roadieUser . Id ) ;
if ( userArtist ! = null )
{
2018-11-14 14:00:08 +00:00
result . Data . UserRating = new UserArtist
{
IsDisliked = userArtist . IsDisliked ? ? false ,
IsFavorite = userArtist . IsFavorite ? ? false ,
Rating = userArtist . Rating
} ;
2018-11-14 23:18:02 +00:00
}
2018-12-05 16:04:21 +00:00
tsw . Stop ( ) ;
timings . Add ( "userArtist" , tsw . ElapsedMilliseconds ) ;
2018-11-14 03:19:28 +00:00
}
2018-11-10 18:03:54 +00:00
sw . Stop ( ) ;
2018-12-05 16:04:21 +00:00
timings . Add ( "operation" , sw . ElapsedMilliseconds ) ;
this . Logger . LogDebug ( "ById Timings: id [{0}], includes [{1}], timings [{3}]" , id , includes , JsonConvert . SerializeObject ( timings ) ) ;
2018-11-10 18:03:54 +00:00
return new OperationResult < Artist > ( result . Messages )
2018-11-06 21:55:31 +00:00
{
2018-11-11 01:11:58 +00:00
Data = result ? . Data ,
2018-11-14 23:18:02 +00:00
Errors = result ? . Errors ,
IsNotFoundResult = result ? . IsNotFoundResult ? ? false ,
2018-11-11 01:11:58 +00:00
IsSuccess = result ? . IsSuccess ? ? false ,
2018-11-10 18:03:54 +00:00
OperationTime = sw . ElapsedMilliseconds
} ;
}
2019-01-30 03:16:49 +00:00
public async Task < Library . Models . Pagination . PagedResult < ArtistList > > List ( User roadieUser , PagedRequest request , bool? doRandomize = false , bool? onlyIncludeWithReleases = true )
2018-11-06 04:31:25 +00:00
{
2018-11-14 14:00:08 +00:00
var sw = new Stopwatch ( ) ;
sw . Start ( ) ;
2018-11-21 18:19:38 +00:00
int [ ] favoriteArtistIds = new int [ 0 ] ;
2019-01-08 22:40:26 +00:00
if ( request . FilterFavoriteOnly )
2018-11-21 18:19:38 +00:00
{
favoriteArtistIds = ( from a in this . DbContext . Artists
join ua in this . DbContext . UserArtists on a . Id equals ua . ArtistId
where ua . IsFavorite ? ? false
2018-12-01 18:05:24 +00:00
where ( roadieUser = = null | | ua . UserId = = roadieUser . Id )
2018-11-21 18:19:38 +00:00
select a . Id
) . ToArray ( ) ;
}
2018-12-09 23:30:55 +00:00
int [ ] labelArtistIds = new int [ 0 ] ;
2019-01-08 22:40:26 +00:00
if ( request . FilterToLabelId . HasValue )
2018-12-09 23:30:55 +00:00
{
labelArtistIds = ( from l in this . DbContext . Labels
join rl in this . DbContext . ReleaseLabels on l . Id equals rl . LabelId
join r in this . DbContext . Releases on rl . ReleaseId equals r . Id
where l . RoadieId = = request . FilterToLabelId
select r . ArtistId )
. Distinct ( )
. ToArray ( ) ;
}
2018-12-30 04:34:32 +00:00
int [ ] genreArtistIds = new int [ 0 ] ;
var isFilteredToGenre = false ;
2019-01-08 22:40:26 +00:00
if ( ! string . IsNullOrEmpty ( request . Filter ) & & request . Filter . StartsWith ( ":genre" , StringComparison . OrdinalIgnoreCase ) )
2018-12-30 04:34:32 +00:00
{
var genreFilter = request . Filter . Replace ( ":genre " , "" ) ;
genreArtistIds = ( from ag in this . DbContext . ArtistGenres
join g in this . DbContext . Genres on ag . GenreId equals g . Id
where g . Name . Contains ( genreFilter )
select ag . ArtistId )
. Distinct ( )
. ToArray ( ) ;
isFilteredToGenre = true ;
request . Filter = null ;
}
2018-11-25 16:57:17 +00:00
var onlyWithReleases = onlyIncludeWithReleases ? ? true ;
2019-01-27 22:49:55 +00:00
var normalizedFilterValue = ! string . IsNullOrEmpty ( request . FilterValue ) ? request . FilterValue . ToAlphanumericName ( ) : null ;
2018-11-14 14:00:08 +00:00
var result = ( from a in this . DbContext . Artists
2018-11-25 16:57:17 +00:00
where ( ! onlyWithReleases | | a . ReleaseCount > 0 )
2018-11-22 13:48:32 +00:00
where ( request . FilterToArtistId = = null | | a . RoadieId = = request . FilterToArtistId )
2018-11-14 23:18:02 +00:00
where ( request . FilterMinimumRating = = null | | a . Rating > = request . FilterMinimumRating . Value )
2019-01-27 22:49:55 +00:00
where ( request . FilterValue = = "" | | ( a . Name . Contains ( request . FilterValue ) | | a . SortName . Contains ( request . FilterValue ) | | a . AlternateNames . Contains ( request . FilterValue ) | | a . AlternateNames . Contains ( normalizedFilterValue ) ) )
2018-11-21 18:19:38 +00:00
where ( ! request . FilterFavoriteOnly | | favoriteArtistIds . Contains ( a . Id ) )
2018-12-09 23:30:55 +00:00
where ( request . FilterToLabelId = = null | | labelArtistIds . Contains ( a . Id ) )
2018-12-30 04:34:32 +00:00
where ( ! isFilteredToGenre | | genreArtistIds . Contains ( a . Id ) )
2018-11-14 23:18:02 +00:00
select new ArtistList
{
DatabaseId = a . Id ,
Id = a . RoadieId ,
Artist = new DataToken
{
Text = a . Name ,
Value = a . RoadieId . ToString ( )
} ,
Thumbnail = this . MakeArtistThumbnailImage ( a . RoadieId ) ,
Rating = a . Rating ,
2019-01-23 16:50:36 +00:00
Rank = a . Rank ,
2018-11-14 23:18:02 +00:00
CreatedDate = a . CreatedDate ,
LastUpdated = a . LastUpdated ,
2018-12-01 18:05:24 +00:00
LastPlayed = a . LastPlayed ,
PlayedCount = a . PlayedCount ,
ReleaseCount = a . ReleaseCount ,
TrackCount = a . TrackCount ,
2018-11-14 23:18:02 +00:00
SortName = a . SortName
} ) . Distinct ( ) ;
2018-11-06 04:31:25 +00:00
2018-11-14 14:00:08 +00:00
ArtistList [ ] rows = null ;
var rowCount = result . Count ( ) ;
if ( doRandomize ? ? false )
{
2018-12-01 18:05:24 +00:00
var randomLimit = roadieUser ? . RandomReleaseLimit ? ? 100 ;
request . Limit = request . LimitValue > randomLimit ? randomLimit : request . LimitValue ;
2019-03-06 01:18:21 +00:00
rows = result . OrderBy ( x = > x . RandomSortId ) . Skip ( request . SkipValue ) . Take ( request . LimitValue ) . ToArray ( ) ;
2018-11-14 14:00:08 +00:00
}
else
{
2018-11-22 23:12:57 +00:00
string sortBy = "Id" ;
2018-11-14 14:00:08 +00:00
if ( request . ActionValue = = User . ActionKeyUserRated )
{
sortBy = string . IsNullOrEmpty ( request . Sort ) ? request . OrderValue ( new Dictionary < string , string > { { "Rating" , "DESC" } , { "Artist.Text" , "ASC" } } ) : request . OrderValue ( null ) ;
}
else
{
2018-12-07 04:45:09 +00:00
sortBy = request . OrderValue ( new Dictionary < string , string > { { "SortName" , "ASC" } , { "Artist.Text" , "ASC" } } ) ;
2018-11-14 14:00:08 +00:00
}
rows = result . OrderBy ( sortBy ) . Skip ( request . SkipValue ) . Take ( request . LimitValue ) . ToArray ( ) ;
}
2018-11-14 23:18:02 +00:00
if ( rows . Any ( ) & & roadieUser ! = null )
2018-11-14 14:00:08 +00:00
{
2018-12-08 19:47:19 +00:00
var rowIds = rows . Select ( x = > x . DatabaseId ) . ToArray ( ) ;
var userArtistRatings = ( from ua in this . DbContext . UserArtists
2019-01-08 22:40:26 +00:00
where ua . UserId = = roadieUser . Id
where rowIds . Contains ( ua . ArtistId )
select ua ) . ToArray ( ) ;
2018-12-08 19:47:19 +00:00
foreach ( var userArtistRating in userArtistRatings . Where ( x = > rows . Select ( r = > r . DatabaseId ) . Contains ( x . ArtistId ) ) )
2018-11-14 14:00:08 +00:00
{
var row = rows . FirstOrDefault ( x = > x . DatabaseId = = userArtistRating . ArtistId ) ;
2018-11-14 23:18:02 +00:00
if ( row ! = null )
2018-11-14 14:00:08 +00:00
{
row . UserRating = new UserArtist
{
IsDisliked = userArtistRating . IsDisliked ? ? false ,
IsFavorite = userArtistRating . IsFavorite ? ? false ,
2018-11-25 20:43:52 +00:00
Rating = userArtistRating . Rating ,
RatedDate = userArtistRating . LastUpdated ? ? userArtistRating . CreatedDate
2018-11-14 14:00:08 +00:00
} ;
}
}
}
sw . Stop ( ) ;
2019-01-30 03:16:49 +00:00
if ( ! string . IsNullOrEmpty ( request . Filter ) & & rowCount = = 0 )
{
// Create request for no artist found
var req = new data . Request
{
UserId = roadieUser ? . Id ,
Description = request . Filter
} ;
this . DbContext . Requests . Add ( req ) ;
await this . DbContext . SaveChangesAsync ( ) ;
}
return new Library . Models . Pagination . PagedResult < ArtistList >
2018-11-14 14:00:08 +00:00
{
TotalCount = rowCount ,
CurrentPage = request . PageValue ,
TotalPages = ( int ) Math . Ceiling ( ( double ) rowCount / request . LimitValue ) ,
OperationTime = sw . ElapsedMilliseconds ,
Rows = rows
2019-01-30 03:16:49 +00:00
} ;
2018-11-06 04:31:25 +00:00
}
2018-12-26 21:18:51 +00:00
2019-01-08 22:40:26 +00:00
public async Task < OperationResult < bool > > ScanArtistReleasesFolders ( Guid artistId , string destinationFolder , bool doJustInfo )
2018-12-26 21:18:51 +00:00
{
2019-01-08 22:40:26 +00:00
SimpleContract . Requires < ArgumentOutOfRangeException > ( artistId ! = Guid . Empty , "Invalid ArtistId" ) ;
2018-12-26 21:18:51 +00:00
2019-01-08 22:40:26 +00:00
var result = true ;
var resultErrors = new List < Exception > ( ) ;
var sw = new Stopwatch ( ) ;
sw . Start ( ) ;
try
2018-12-26 21:18:51 +00:00
{
2019-01-08 22:40:26 +00:00
var artist = this . DbContext . Artists
. Include ( "Releases" )
. Include ( "Releases.Labels" )
. FirstOrDefault ( x = > x . RoadieId = = artistId ) ;
if ( artist = = null )
{
this . Logger . LogWarning ( "Unable To Find Artist [{0}]" , artistId ) ;
return new OperationResult < bool > ( ) ;
}
var releaseScannedCount = 0 ;
var artistFolder = artist . ArtistFileFolder ( this . 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 ;
releaseScannedCount + + ;
scannedArtistFolders . Add ( release . ReleaseFileFolder ( artistFolder ) ) ;
}
catch ( Exception ex )
{
this . 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 . ArtistFactory , 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 ) ;
foreach ( var folder in nonReleaseFolders )
{
await folderProcessor . Process ( new DirectoryInfo ( folder ) , doJustInfo ) ;
}
if ( ! doJustInfo )
{
FolderProcessor . DeleteEmptyFolders ( new DirectoryInfo ( artistFolder ) , this . Logger ) ;
}
// Always update artist image if artist image is found on an artist rescan
2019-02-12 02:17:24 +00:00
var imageFiles = ImageHelper . ImageFilesInFolder ( artistFolder , SearchOption . AllDirectories ) ;
2019-01-08 22:40:26 +00:00
if ( imageFiles ! = null & & imageFiles . Any ( ) )
{
var imageFile = imageFiles . First ( ) ;
var i = new FileInfo ( imageFile ) ;
var iName = i . Name . ToLower ( ) . Trim ( ) ;
2019-02-10 00:19:26 +00:00
var isArtistImage = iName . Contains ( "artist" ) ;
2019-01-08 22:40:26 +00:00
if ( isArtistImage )
{
// 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 . ConvertToJpegFormat ( artist . Thumbnail ) ;
artist . LastUpdated = DateTime . UtcNow ;
await this . DbContext . SaveChangesAsync ( ) ;
this . CacheManager . ClearRegion ( artist . CacheRegion ) ;
this . 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 ) ;
}
catch ( Exception ex )
{
this . Logger . LogError ( ex , ex . Serialize ( ) ) ;
resultErrors . Add ( ex ) ;
}
return new OperationResult < bool >
{
Data = result ,
IsSuccess = result ,
Errors = resultErrors ,
OperationTime = sw . ElapsedMilliseconds
} ;
}
public async Task < OperationResult < Library . Models . Image > > SetReleaseImageByUrl ( User user , Guid id , string imageUrl )
{
return await this . SaveImageBytes ( user , id , WebHelper . BytesForImageUrl ( imageUrl ) ) ;
}
public async Task < OperationResult < bool > > UpdateArtist ( User user , Artist model )
2018-12-27 17:37:17 +00:00
{
var didRenameArtist = false ;
var didChangeThumbnail = false ;
var sw = new Stopwatch ( ) ;
sw . Start ( ) ;
var errors = new List < Exception > ( ) ;
var artist = this . DbContext . Artists
. Include ( x = > x . Genres )
. Include ( "Genres.Genre" )
. FirstOrDefault ( x = > x . RoadieId = = model . Id ) ;
if ( artist = = null )
{
return new OperationResult < bool > ( true , string . Format ( "Artist Not Found [{0}]" , model . Id ) ) ;
}
try
{
var now = DateTime . UtcNow ;
var originalArtistFolder = artist . ArtistFileFolder ( this . Configuration , this . Configuration . LibraryFolder ) ;
artist . AlternateNames = model . AlternateNamesList . ToDelimitedList ( ) ;
2019-02-05 03:53:31 +00:00
artist . ArtistType = model . ArtistType ;
2018-12-27 17:37:17 +00:00
artist . AmgId = model . AmgId ;
artist . BeginDate = model . BeginDate ;
artist . BioContext = model . BioContext ;
artist . BirthDate = model . BirthDate ;
artist . DiscogsId = model . DiscogsId ;
artist . EndDate = model . EndDate ;
artist . IsLocked = model . IsLocked ;
2018-12-27 21:56:40 +00:00
artist . ISNI = model . ISNIList . ToDelimitedList ( ) ;
2018-12-27 17:37:17 +00:00
artist . ITunesId = model . ITunesId ;
artist . MusicBrainzId = model . MusicBrainzId ;
artist . Name = model . Name ;
artist . Profile = model . Profile ;
artist . Rating = model . Rating ;
artist . RealName = model . RealName ;
artist . SortName = model . SortName ;
artist . SpotifyId = model . SpotifyId ;
artist . Status = SafeParser . ToEnum < Statuses > ( model . Status ) ;
artist . Tags = model . TagsList . ToDelimitedList ( ) ;
artist . URLs = model . URLsList . ToDelimitedList ( ) ;
var newArtistFolder = artist . ArtistFileFolder ( this . Configuration , this . Configuration . LibraryFolder ) ;
if ( ! newArtistFolder . Equals ( originalArtistFolder , StringComparison . OrdinalIgnoreCase ) )
{
didRenameArtist = true ;
// Rename artist folder to reflect new artist name
this . Logger . LogTrace ( "Moving Artist From Folder [{0}] To [{1}]" , originalArtistFolder , newArtistFolder ) ;
Directory . Move ( originalArtistFolder , newArtistFolder ) ;
}
var artistImage = ImageHelper . ImageDataFromUrl ( model . NewThumbnailData ) ;
if ( artistImage ! = null )
{
// Ensure is jpeg first
artist . Thumbnail = ImageHelper . ConvertToJpegFormat ( artistImage ) ;
// Save unaltered image to cover file
2019-02-10 00:19:26 +00:00
var artistImageName = Path . Combine ( artist . ArtistFileFolder ( this . Configuration , this . Configuration . LibraryFolder ) , ImageHelper . ArtistImageFilename ) ;
2018-12-27 17:37:17 +00:00
File . WriteAllBytes ( artistImageName , artist . Thumbnail ) ;
// Resize to store in database as thumbnail
artist . Thumbnail = ImageHelper . ResizeImage ( artist . Thumbnail , this . Configuration . MediumImageSize . Width , this . Configuration . MediumImageSize . Height ) ;
didChangeThumbnail = true ;
}
if ( model . Genres ! = null & & model . Genres . Any ( ) )
{
// Remove existing Genres not in model list
foreach ( var genre in artist . Genres . ToList ( ) )
{
var doesExistInModel = model . Genres . Any ( x = > SafeParser . ToGuid ( x . Value ) = = genre . Genre . RoadieId ) ;
if ( ! doesExistInModel )
{
artist . Genres . Remove ( genre ) ;
}
}
// Add new Genres in model not in data
foreach ( var genre in model . Genres )
{
var genreId = SafeParser . ToGuid ( genre . Value ) ;
var doesExistInData = artist . Genres . Any ( x = > x . Genre . RoadieId = = genreId ) ;
if ( ! doesExistInData )
{
var g = this . DbContext . Genres . FirstOrDefault ( x = > x . RoadieId = = genreId ) ;
if ( g ! = null )
{
artist . Genres . Add ( new data . ArtistGenre
{
ArtistId = artist . Id ,
GenreId = g . Id ,
Genre = g
} ) ;
}
}
}
}
else if ( model . Genres = = null | | ! model . Genres . Any ( ) )
{
artist . Genres . Clear ( ) ;
}
if ( model . AssociatedArtistsTokens ! = null & & model . AssociatedArtistsTokens . Any ( ) )
{
var associatedArtists = this . DbContext . ArtistAssociations . Include ( x = > x . AssociatedArtist ) . Where ( x = > x . ArtistId = = artist . Id ) . ToList ( ) ;
// Remove existing AssociatedArtists not in model list
foreach ( var associatedArtist in associatedArtists )
{
var doesExistInModel = model . AssociatedArtistsTokens . Any ( x = > SafeParser . ToGuid ( x . Value ) = = associatedArtist . AssociatedArtist . RoadieId ) ;
if ( ! doesExistInModel )
{
this . DbContext . ArtistAssociations . Remove ( associatedArtist ) ;
}
}
// Add new AssociatedArtists in model not in data
foreach ( var associatedArtist in model . AssociatedArtistsTokens )
{
var associatedArtistId = SafeParser . ToGuid ( associatedArtist . Value ) ;
var doesExistInData = associatedArtists . Any ( x = > x . AssociatedArtist . RoadieId = = associatedArtistId ) ;
if ( ! doesExistInData )
{
var a = this . DbContext . Artists . FirstOrDefault ( x = > x . RoadieId = = associatedArtistId ) ;
if ( a ! = null )
{
this . DbContext . ArtistAssociations . Add ( new data . ArtistAssociation
{
ArtistId = artist . Id ,
AssociatedArtistId = a . Id
} ) ;
}
}
}
}
else if ( model . AssociatedArtistsTokens = = null | | ! model . AssociatedArtistsTokens . Any ( ) )
{
artist . AssociatedArtists . Clear ( ) ;
}
if ( model . Images ! = null & & model . Images . Any ( ) )
{
// TODO
}
artist . LastUpdated = now ;
await this . DbContext . SaveChangesAsync ( ) ;
2019-01-08 22:40:26 +00:00
if ( didRenameArtist )
{
2018-12-27 20:42:51 +00:00
// Update artist tracks to have new artist name in ID3 metadata
foreach ( var mp3 in Directory . GetFiles ( newArtistFolder , "*.mp3" , SearchOption . AllDirectories ) )
{
var trackFileInfo = new FileInfo ( mp3 ) ;
var audioMetaData = await this . AudioMetaDataHelper . GetInfo ( trackFileInfo ) ;
if ( audioMetaData ! = null )
{
audioMetaData . Artist = artist . Name ;
this . AudioMetaDataHelper . WriteTags ( audioMetaData , trackFileInfo ) ;
}
}
2018-12-27 17:37:17 +00:00
await this . ScanArtistReleasesFolders ( artist . RoadieId , this . Configuration . LibraryFolder , false ) ;
}
this . CacheManager . ClearRegion ( artist . CacheRegion ) ;
this . Logger . LogInformation ( $"UpdateArtist `{ artist }` By User `{ user }`: Renamed Artist [{ didRenameArtist }], Uploaded new image [{ didChangeThumbnail }]" ) ;
}
catch ( Exception ex )
{
this . Logger . LogError ( ex ) ;
errors . Add ( ex ) ;
}
sw . Stop ( ) ;
return new OperationResult < bool >
{
IsSuccess = ! errors . Any ( ) ,
Data = ! errors . Any ( ) ,
OperationTime = sw . ElapsedMilliseconds ,
Errors = errors
} ;
}
2019-01-12 21:10:00 +00:00
public async Task < OperationResult < bool > > MergeArtists ( User user , Guid artistToMergeId , Guid artistToMergeIntoId )
{
var sw = new Stopwatch ( ) ;
sw . Start ( ) ;
var errors = new List < Exception > ( ) ;
2019-01-12 21:38:31 +00:00
var artistToMerge = this . DbContext . Artists
. Include ( x = > x . Genres )
. Include ( "Genres.Genre" )
. FirstOrDefault ( x = > x . RoadieId = = artistToMergeId ) ;
2019-01-12 21:10:00 +00:00
if ( artistToMerge = = null )
{
this . Logger . LogWarning ( "MergeArtists Unknown Artist [{0}]" , artistToMergeId ) ;
return new OperationResult < bool > ( true , string . Format ( "Artist Not Found [{0}]" , artistToMergeId ) ) ;
}
2019-01-12 21:38:31 +00:00
var mergeIntoArtist = this . DbContext . Artists
. Include ( x = > x . Genres )
. Include ( "Genres.Genre" )
. FirstOrDefault ( x = > x . RoadieId = = artistToMergeIntoId ) ;
2019-01-12 21:10:00 +00:00
if ( mergeIntoArtist = = null )
{
this . Logger . LogWarning ( "MergeArtists Unknown Artist [{0}]" , artistToMergeIntoId ) ;
return new OperationResult < bool > ( true , string . Format ( "Artist Not Found [{0}]" , artistToMergeIntoId ) ) ;
}
try
{
var result = await this . ArtistFactory . MergeArtists ( artistToMerge , mergeIntoArtist , true ) ;
if ( ! result . IsSuccess )
{
this . CacheManager . ClearRegion ( artistToMerge . CacheRegion ) ;
this . CacheManager . ClearRegion ( mergeIntoArtist . CacheRegion ) ;
this . Logger . LogInformation ( "MergeArtists `{0}` => `{1}`, By User `{2}`" , artistToMerge , mergeIntoArtist , user ) ;
}
}
catch ( Exception ex )
{
this . Logger . LogError ( ex ) ;
errors . Add ( ex ) ;
}
sw . Stop ( ) ;
return new OperationResult < bool >
{
IsSuccess = ! errors . Any ( ) ,
Data = ! errors . Any ( ) ,
OperationTime = sw . ElapsedMilliseconds ,
Errors = errors
} ;
}
2019-01-08 22:40:26 +00:00
public async Task < OperationResult < Library . Models . Image > > UploadArtistImage ( User user , Guid id , IFormFile file )
2018-12-27 17:37:17 +00:00
{
2019-01-08 22:40:26 +00:00
var bytes = new byte [ 0 ] ;
using ( var ms = new MemoryStream ( ) )
{
file . CopyTo ( ms ) ;
bytes = ms . ToArray ( ) ;
}
return await this . SaveImageBytes ( user , id , bytes ) ;
}
2018-12-27 17:37:17 +00:00
2019-01-08 22:40:26 +00:00
private async Task < OperationResult < Artist > > ArtistByIdAction ( Guid id , IEnumerable < string > includes )
{
var timings = new Dictionary < string , long > ( ) ;
var tsw = new Stopwatch ( ) ;
var sw = Stopwatch . StartNew ( ) ;
2018-12-27 17:37:17 +00:00
sw . Start ( ) ;
2019-01-08 22:40:26 +00:00
tsw . Restart ( ) ;
var artist = this . GetArtist ( id ) ;
tsw . Stop ( ) ;
timings . Add ( "getArtist" , tsw . ElapsedMilliseconds ) ;
if ( artist = = null )
2018-12-27 17:37:17 +00:00
{
2019-01-08 22:40:26 +00:00
return new OperationResult < Artist > ( true , string . Format ( "Artist Not Found [{0}]" , id ) ) ;
}
tsw . Restart ( ) ;
var result = artist . Adapt < Artist > ( ) ;
2019-01-26 04:44:07 +00:00
result . BandStatus = result . BandStatus ? ? BandStatus . Unknown . ToString ( ) ;
2019-01-08 22:40:26 +00:00
result . BeginDate = result . BeginDate = = null | | result . BeginDate = = DateTime . MinValue ? null : result . BeginDate ;
result . EndDate = result . EndDate = = null | | result . EndDate = = DateTime . MinValue ? null : result . EndDate ;
result . BirthDate = result . BirthDate = = null | | result . BirthDate = = DateTime . MinValue ? null : result . BirthDate ;
tsw . Stop ( ) ;
timings . Add ( "adaptArtist" , tsw . ElapsedMilliseconds ) ;
result . Thumbnail = base . MakeArtistThumbnailImage ( id ) ;
result . MediumThumbnail = base . MakeThumbnailImage ( id , "artist" , this . Configuration . MediumImageSize . Width , this . Configuration . MediumImageSize . Height ) ;
tsw . Restart ( ) ;
result . Genres = artist . Genres . Select ( x = > new DataToken { Text = x . Genre . Name , Value = x . Genre . RoadieId . ToString ( ) } ) ;
tsw . Stop ( ) ;
timings . Add ( "genres" , tsw . ElapsedMilliseconds ) ;
if ( includes ! = null & & includes . Any ( ) )
{
if ( includes . Contains ( "releases" ) )
2018-12-27 17:37:17 +00:00
{
2019-01-08 22:40:26 +00:00
var dtoReleases = new List < ReleaseList > ( ) ;
foreach ( var release in this . DbContext . Releases . Include ( "Medias" ) . Include ( "Medias.Tracks" ) . Include ( "Medias.Tracks" ) . Where ( x = > x . ArtistId = = artist . Id ) . ToArray ( ) )
2018-12-27 17:37:17 +00:00
{
2019-01-08 22:40:26 +00:00
var releaseList = release . Adapt < ReleaseList > ( ) ;
releaseList . Thumbnail = base . MakeReleaseThumbnailImage ( release . RoadieId ) ;
var dtoReleaseMedia = new List < ReleaseMediaList > ( ) ;
if ( includes . Contains ( "tracks" ) )
2018-12-27 17:37:17 +00:00
{
2019-01-08 22:40:26 +00:00
foreach ( var releasemedia in release . Medias . OrderBy ( x = > x . MediaNumber ) . ToArray ( ) )
{
var dtoMedia = releasemedia . Adapt < ReleaseMediaList > ( ) ;
var tracks = new List < TrackList > ( ) ;
foreach ( var t in this . DbContext . Tracks . Where ( x = > x . ReleaseMediaId = = releasemedia . Id ) . OrderBy ( x = > x . TrackNumber ) . ToArray ( ) )
{
var track = t . Adapt < TrackList > ( ) ;
ArtistList trackArtist = null ;
if ( t . ArtistId . HasValue )
{
var ta = this . DbContext . Artists . FirstOrDefault ( x = > x . Id = = t . ArtistId . Value ) ;
if ( ta ! = null )
{
trackArtist = ArtistList . FromDataArtist ( ta , this . MakeArtistThumbnailImage ( ta . RoadieId ) ) ;
}
}
track . TrackArtist = trackArtist ;
tracks . Add ( track ) ;
}
dtoMedia . Tracks = tracks ;
dtoReleaseMedia . Add ( dtoMedia ) ;
}
2018-12-27 17:37:17 +00:00
}
2019-01-08 22:40:26 +00:00
releaseList . Media = dtoReleaseMedia ;
dtoReleases . Add ( releaseList ) ;
2018-12-27 17:37:17 +00:00
}
2019-01-08 22:40:26 +00:00
result . Releases = dtoReleases ;
2018-12-27 17:37:17 +00:00
}
2019-01-08 22:40:26 +00:00
if ( includes . Contains ( "stats" ) )
2018-12-27 17:37:17 +00:00
{
2019-02-25 02:26:54 +00:00
try
2019-01-08 22:40:26 +00:00
{
2019-02-25 02:26:54 +00:00
tsw . Restart ( ) ;
var artistTracks = ( from r in this . DbContext . Releases
join rm in this . DbContext . ReleaseMedias on r . Id equals rm . ReleaseId
join t in this . DbContext . Tracks on rm . Id equals t . ReleaseMediaId
where ( r . ArtistId = = artist . Id | | t . ArtistId = = artist . Id )
select new
{
t . Id ,
size = t . FileSize ,
time = t . Duration ,
isMissing = t . Hash = = null
} ) ;
var validCartistTracks = artistTracks . Where ( x = > ! x . isMissing ) ;
long? trackTime = validCartistTracks . Sum ( x = > ( long? ) x . time ) ;
result . Statistics = new CollectionStatistics
{
FileSize = artistTracks . Sum ( x = > ( long? ) x . size ) . ToFileSize ( ) ,
MissingTrackCount = artistTracks . Where ( x = > x . isMissing ) . Count ( ) ,
ReleaseCount = artist . ReleaseCount ,
ReleaseMediaCount = ( from r in this . DbContext . Releases
join rm in this . DbContext . ReleaseMedias on r . Id equals rm . ReleaseId
where r . ArtistId = = artist . Id
select rm . Id ) . Count ( ) ,
TrackTime = validCartistTracks . Any ( ) ? new TimeInfo ( ( decimal ) trackTime ) . ToFullFormattedString ( ) : "--:--" ,
TrackCount = validCartistTracks . Count ( ) ,
TrackPlayedCount = artist . PlayedCount
} ;
tsw . Stop ( ) ;
timings . Add ( "stats" , tsw . ElapsedMilliseconds ) ;
}
catch ( Exception ex )
{
this . Logger . LogError ( ex , $"Error Getting Statistics for Artist `{ artist }`" ) ;
}
2018-12-27 17:37:17 +00:00
}
2019-01-08 22:40:26 +00:00
if ( includes . Contains ( "images" ) )
2018-12-27 17:37:17 +00:00
{
2019-01-08 22:40:26 +00:00
tsw . Restart ( ) ;
result . Images = this . DbContext . Images . Where ( x = > x . ArtistId = = artist . Id ) . Select ( x = > MakeFullsizeImage ( x . RoadieId , x . Caption ) ) . ToArray ( ) ;
2019-02-10 00:19:26 +00:00
var artistFolder = artist . ArtistFileFolder ( this . Configuration , this . Configuration . LibraryFolder ) ;
2019-02-12 02:17:24 +00:00
var artistImagesInFolder = ImageHelper . FindImageTypeInDirectory ( new DirectoryInfo ( artistFolder ) , ImageType . ArtistSecondary , SearchOption . TopDirectoryOnly ) ;
2019-02-10 00:19:26 +00:00
if ( artistImagesInFolder . Any ( ) )
{
result . Images = result . Images . Concat ( artistImagesInFolder . Select ( ( x , i ) = > MakeFullsizeSecondaryImage ( id , ImageType . ArtistSecondary , i ) ) ) ;
}
2019-01-08 22:40:26 +00:00
tsw . Stop ( ) ;
timings . Add ( "images" , tsw . ElapsedMilliseconds ) ;
2018-12-27 17:37:17 +00:00
}
2019-01-08 22:40:26 +00:00
if ( includes . Contains ( "associatedartists" ) )
{
tsw . Restart ( ) ;
var associatedWithArtists = ( from aa in this . DbContext . ArtistAssociations
join a in this . DbContext . Artists on aa . AssociatedArtistId equals a . Id
where aa . ArtistId = = artist . Id
select new ArtistList
{
DatabaseId = a . Id ,
Id = a . RoadieId ,
Artist = new DataToken
{
Text = a . Name ,
Value = a . RoadieId . ToString ( )
} ,
Thumbnail = this . MakeArtistThumbnailImage ( a . RoadieId ) ,
Rating = a . Rating ,
2019-01-23 16:50:36 +00:00
Rank = a . Rank ,
2019-01-08 22:40:26 +00:00
CreatedDate = a . CreatedDate ,
LastUpdated = a . LastUpdated ,
LastPlayed = a . LastPlayed ,
PlayedCount = a . PlayedCount ,
ReleaseCount = a . ReleaseCount ,
TrackCount = a . TrackCount ,
SortName = a . SortName
} ) . ToArray ( ) ;
2018-12-27 17:37:17 +00:00
2019-01-08 22:40:26 +00:00
var associatedArtists = ( from aa in this . DbContext . ArtistAssociations
join a in this . DbContext . Artists on aa . ArtistId equals a . Id
where aa . AssociatedArtistId = = artist . Id
select new ArtistList
{
DatabaseId = a . Id ,
Id = a . RoadieId ,
Artist = new DataToken
{
Text = a . Name ,
Value = a . RoadieId . ToString ( )
} ,
Thumbnail = this . MakeArtistThumbnailImage ( a . RoadieId ) ,
Rating = a . Rating ,
2019-01-23 16:50:36 +00:00
Rank = a . Rank ,
2019-01-08 22:40:26 +00:00
CreatedDate = a . CreatedDate ,
LastUpdated = a . LastUpdated ,
LastPlayed = a . LastPlayed ,
PlayedCount = a . PlayedCount ,
ReleaseCount = a . ReleaseCount ,
TrackCount = a . TrackCount ,
SortName = a . SortName
} ) . ToArray ( ) ;
2019-02-03 01:01:38 +00:00
result . AssociatedArtists = associatedArtists . Union ( associatedWithArtists , new ArtistListComparer ( ) ) . OrderBy ( x = > x . SortName ) ;
2019-01-08 22:40:26 +00:00
result . AssociatedArtistsTokens = result . AssociatedArtists . Select ( x = > x . Artist ) . ToArray ( ) ;
tsw . Stop ( ) ;
timings . Add ( "associatedartists" , tsw . ElapsedMilliseconds ) ;
}
if ( includes . Contains ( "collections" ) )
2018-12-27 17:37:17 +00:00
{
2019-01-08 22:40:26 +00:00
tsw . Restart ( ) ;
var collectionPagedRequest = new PagedRequest
2018-12-27 17:37:17 +00:00
{
2019-01-08 22:40:26 +00:00
Limit = 100
} ;
var r = await this . CollectionService . List ( roadieUser : null ,
request : collectionPagedRequest , artistId : artist . RoadieId ) ;
if ( r . IsSuccess )
{
result . CollectionsWithArtistReleases = r . Rows . ToArray ( ) ;
2018-12-27 17:37:17 +00:00
}
2019-01-08 22:40:26 +00:00
tsw . Stop ( ) ;
timings . Add ( "collections" , tsw . ElapsedMilliseconds ) ;
}
if ( includes . Contains ( "playlists" ) )
{
tsw . Restart ( ) ;
var pg = new PagedRequest
{
FilterToArtistId = artist . RoadieId
} ;
var r = await this . PlaylistService . List ( pg ) ;
if ( r . IsSuccess )
{
result . PlaylistsWithArtistReleases = r . Rows . ToArray ( ) ;
}
tsw . Stop ( ) ;
timings . Add ( "playlists" , tsw . ElapsedMilliseconds ) ;
}
if ( includes . Contains ( "contributions" ) )
{
tsw . Restart ( ) ;
result . ArtistContributionReleases = ( from t in this . DbContext . Tracks
join rm in this . DbContext . ReleaseMedias on t . ReleaseMediaId equals rm . Id
join r in this . DbContext . Releases . Include ( x = > x . Artist ) on rm . ReleaseId equals r . Id
where t . ArtistId = = artist . Id
group r by r . Id into rr
select rr )
. ToArray ( )
. Select ( rr = > rr . First ( ) )
. Select ( r = > ReleaseList . FromDataRelease ( r , r . Artist , this . HttpContext . BaseUrl , MakeArtistThumbnailImage ( r . Artist . RoadieId ) , MakeReleaseThumbnailImage ( r . RoadieId ) ) )
. ToArray ( ) . OrderBy ( x = > x . Release . Text ) . ToArray ( ) ;
result . ArtistContributionReleases = result . ArtistContributionReleases . Any ( ) ? result . ArtistContributionReleases : null ;
tsw . Stop ( ) ;
timings . Add ( "contributions" , tsw . ElapsedMilliseconds ) ;
}
if ( includes . Contains ( "labels" ) )
{
tsw . Restart ( ) ;
result . ArtistLabels = ( from l in this . DbContext . Labels
join rl in this . DbContext . ReleaseLabels on l . Id equals rl . LabelId
join r in this . DbContext . Releases on rl . ReleaseId equals r . Id
where r . ArtistId = = artist . Id
orderby l . SortName
select LabelList . FromDataLabel ( l , this . MakeLabelThumbnailImage ( l . RoadieId ) ) )
. ToArray ( )
. GroupBy ( x = > x . Label . Value ) . Select ( x = > x . First ( ) ) . OrderBy ( x = > x . SortName ) . ThenBy ( x = > x . Label . Text ) . ToArray ( ) ;
result . ArtistLabels = result . ArtistLabels . Any ( ) ? result . ArtistLabels : null ;
tsw . Stop ( ) ;
timings . Add ( "labels" , tsw . ElapsedMilliseconds ) ;
2018-12-27 17:37:17 +00:00
}
}
2019-01-08 22:40:26 +00:00
sw . Stop ( ) ;
timings . Add ( "operation" , sw . ElapsedMilliseconds ) ;
this . Logger . LogDebug ( "ArtistByIdAction Timings: id [{0}], includes [{1}], timings [{3}]" , id , includes , JsonConvert . SerializeObject ( timings ) ) ;
return new OperationResult < Artist >
2018-12-27 17:37:17 +00:00
{
Data = result ,
2019-01-08 22:40:26 +00:00
IsSuccess = result ! = null ,
2018-12-27 17:37:17 +00:00
OperationTime = sw . ElapsedMilliseconds
} ;
}
2018-12-26 21:18:51 +00:00
private async Task < OperationResult < Library . Models . Image > > SaveImageBytes ( User user , Guid id , byte [ ] imageBytes )
{
var sw = new Stopwatch ( ) ;
sw . Start ( ) ;
var errors = new List < Exception > ( ) ;
var artist = this . DbContext . Artists . FirstOrDefault ( x = > x . RoadieId = = id ) ;
if ( artist = = null )
{
return new OperationResult < Library . Models . Image > ( true , string . Format ( "Artist Not Found [{0}]" , id ) ) ;
}
try
{
var now = DateTime . UtcNow ;
artist . Thumbnail = imageBytes ;
if ( artist . Thumbnail ! = null )
{
// Ensure is jpeg first
artist . Thumbnail = ImageHelper . ConvertToJpegFormat ( artist . Thumbnail ) ;
2018-12-27 21:56:40 +00:00
// Ensure artist folder exists
var artistFolder = artist . ArtistFileFolder ( this . Configuration , this . Configuration . LibraryFolder ) ;
2019-01-08 22:40:26 +00:00
if ( ! Directory . Exists ( artistFolder ) )
2018-12-27 21:56:40 +00:00
{
Directory . CreateDirectory ( artistFolder ) ;
this . Logger . LogInformation ( "Created Artist Folder [0] for `artist`" , artistFolder , artist ) ;
2019-01-08 22:40:26 +00:00
}
2018-12-27 21:56:40 +00:00
2018-12-26 21:18:51 +00:00
// Save unaltered image to artist file
2019-02-10 00:19:26 +00:00
var artistImage = Path . Combine ( artistFolder , ImageHelper . ArtistImageFilename ) ;
File . WriteAllBytes ( artistImage , artist . Thumbnail ) ;
2018-12-26 21:18:51 +00:00
// Resize to store in database as thumbnail
artist . Thumbnail = ImageHelper . ResizeImage ( artist . Thumbnail , this . Configuration . MediumImageSize . Width , this . Configuration . MediumImageSize . Height ) ;
}
artist . LastUpdated = now ;
await this . DbContext . SaveChangesAsync ( ) ;
this . CacheManager . ClearRegion ( artist . CacheRegion ) ;
this . Logger . LogInformation ( $"SaveImageBytes `{ artist }` By User `{ user }`" ) ;
}
catch ( Exception ex )
{
this . Logger . LogError ( ex ) ;
errors . Add ( ex ) ;
}
sw . Stop ( ) ;
return new OperationResult < Library . Models . Image >
{
IsSuccess = ! errors . Any ( ) ,
2018-12-27 21:56:40 +00:00
Data = base . MakeThumbnailImage ( id , "artist" , this . Configuration . MediumImageSize . Width , this . Configuration . MediumImageSize . Height , true ) ,
2018-12-26 21:18:51 +00:00
OperationTime = sw . ElapsedMilliseconds ,
Errors = errors
} ;
}
2018-11-06 04:31:25 +00:00
}
}