@ -12,6 +12,7 @@ using NzbDrone.Core.Extras.Files;
using NzbDrone.Core.Extras.Metadata.Files ;
using NzbDrone.Core.Extras.Metadata.Files ;
using NzbDrone.Core.MediaFiles ;
using NzbDrone.Core.MediaFiles ;
using NzbDrone.Core.Music ;
using NzbDrone.Core.Music ;
using NzbDrone.Core.Organizer ;
namespace NzbDrone.Core.Extras.Metadata
namespace NzbDrone.Core.Extras.Metadata
{
{
@ -52,7 +53,7 @@ namespace NzbDrone.Core.Extras.Metadata
public override int Order = > 0 ;
public override int Order = > 0 ;
public override IEnumerable < ExtraFile > CreateAfterArtistScan ( Artist artist , List < Album> albums , List < TrackFile> trackFiles )
public override IEnumerable < ExtraFile > CreateAfterArtistScan ( Artist artist , List < TrackFile> trackFiles )
{
{
var metadataFiles = _metadataFileService . GetFilesByArtist ( artist . Id ) ;
var metadataFiles = _metadataFileService . GetFilesByArtist ( artist . Id ) ;
_cleanMetadataService . Clean ( artist ) ;
_cleanMetadataService . Clean ( artist ) ;
@ -71,18 +72,20 @@ namespace NzbDrone.Core.Extras.Metadata
files . AddIfNotNull ( ProcessArtistMetadata ( consumer , artist , consumerFiles ) ) ;
files . AddIfNotNull ( ProcessArtistMetadata ( consumer , artist , consumerFiles ) ) ;
files . AddRange ( ProcessArtistImages ( consumer , artist , consumerFiles ) ) ;
files . AddRange ( ProcessArtistImages ( consumer , artist , consumerFiles ) ) ;
files . AddRange ( ProcessAlbumImages ( consumer , artist , consumerFiles ) ) ;
foreach ( var album in albums )
var albumGroups = trackFiles . GroupBy ( s = > Path . GetDirectoryName ( s . RelativePath ) ) . ToList ( ) ;
{
album . Artist = artist ;
files . AddIfNotNull ( ProcessAlbumMetadata ( consumer , album , consumerFiles ) ) ;
}
foreach ( var trackFile in trackFile s)
foreach ( var group in albumGroups )
{
{
files . AddIfNotNull ( ProcessEpisodeMetadata ( consumer , artist , trackFile , consumerFiles ) ) ;
var album = _albumService . GetAlbum ( group . First ( ) . AlbumId ) ;
files . AddRange ( ProcessEpisodeImages ( consumer , artist , trackFile , consumerFiles ) ) ;
var albumFolder = group . Key ;
files . AddIfNotNull ( ProcessAlbumMetadata ( consumer , artist , album , albumFolder , consumerFiles ) ) ;
files . AddRange ( ProcessAlbumImages ( consumer , artist , album , albumFolder , consumerFiles ) ) ;
foreach ( var trackFile in group )
{
files . AddIfNotNull ( ProcessTrackMetadata ( consumer , artist , trackFile , consumerFiles ) ) ;
}
}
}
}
}
@ -97,9 +100,7 @@ namespace NzbDrone.Core.Extras.Metadata
foreach ( var consumer in _metadataFactory . Enabled ( ) )
foreach ( var consumer in _metadataFactory . Enabled ( ) )
{
{
files . AddIfNotNull ( ProcessTrackMetadata ( consumer , artist , trackFile , new List < MetadataFile > ( ) ) ) ;
files . AddIfNotNull ( ProcessEpisodeMetadata ( consumer , artist , trackFile , new List < MetadataFile > ( ) ) ) ;
files . AddRange ( ProcessEpisodeImages ( consumer , artist , trackFile , new List < MetadataFile > ( ) ) ) ;
}
}
_metadataFileService . Upsert ( files ) ;
_metadataFileService . Upsert ( files ) ;
@ -107,7 +108,7 @@ namespace NzbDrone.Core.Extras.Metadata
return files ;
return files ;
}
}
public override IEnumerable < ExtraFile > CreateAfterTrackImport ( Artist artist , string artistFolder , string albumFolder )
public override IEnumerable < ExtraFile > CreateAfterTrackImport ( Artist artist , Album album , string artistFolder , string albumFolder )
{
{
var metadataFiles = _metadataFileService . GetFilesByArtist ( artist . Id ) ;
var metadataFiles = _metadataFileService . GetFilesByArtist ( artist . Id ) ;
@ -127,11 +128,6 @@ namespace NzbDrone.Core.Extras.Metadata
files . AddIfNotNull ( ProcessArtistMetadata ( consumer , artist , consumerFiles ) ) ;
files . AddIfNotNull ( ProcessArtistMetadata ( consumer , artist , consumerFiles ) ) ;
files . AddRange ( ProcessArtistImages ( consumer , artist , consumerFiles ) ) ;
files . AddRange ( ProcessArtistImages ( consumer , artist , consumerFiles ) ) ;
}
}
if ( albumFolder . IsNotNullOrWhiteSpace ( ) )
{
files . AddRange ( ProcessAlbumImages ( consumer , artist , consumerFiles ) ) ;
}
}
}
_metadataFileService . Upsert ( files ) ;
_metadataFileService . Upsert ( files ) ;
@ -143,12 +139,42 @@ namespace NzbDrone.Core.Extras.Metadata
{
{
var metadataFiles = _metadataFileService . GetFilesByArtist ( artist . Id ) ;
var metadataFiles = _metadataFileService . GetFilesByArtist ( artist . Id ) ;
var movedFiles = new List < MetadataFile > ( ) ;
var movedFiles = new List < MetadataFile > ( ) ;
var distinctTrackFilePaths = trackFiles . DistinctBy ( s = > Path . GetDirectoryName ( s . RelativePath ) ) . ToList ( ) ;
// TODO: Move EpisodeImage and EpisodeMetadata metadata files, instead of relying on consumers to do it
// TODO: Move EpisodeImage and EpisodeMetadata metadata files, instead of relying on consumers to do it
// (Xbmc's EpisodeImage is more than just the extension)
// (Xbmc's EpisodeImage is more than just the extension)
foreach ( var consumer in _metadataFactory . GetAvailableProviders ( ) )
foreach ( var consumer in _metadataFactory . GetAvailableProviders ( ) )
{
{
foreach ( var filePath in distinctTrackFilePaths )
{
var metadataFilesForConsumer = GetMetadataFilesForConsumer ( consumer , metadataFiles )
. Where ( m = > m . AlbumId = = filePath . AlbumId )
. Where ( m = > m . Type = = MetadataType . AlbumImage | | m . Type = = MetadataType . AlbumMetadata )
. ToList ( ) ;
foreach ( var metadataFile in metadataFilesForConsumer )
{
var newFileName = consumer . GetFilenameAfterMove ( artist , Path . GetDirectoryName ( filePath . RelativePath ) , metadataFile ) ;
var existingFileName = Path . Combine ( artist . Path , metadataFile . RelativePath ) ;
if ( newFileName . PathNotEquals ( existingFileName ) )
{
try
{
_diskProvider . MoveFile ( existingFileName , newFileName ) ;
metadataFile . RelativePath = artist . Path . GetRelativePath ( newFileName ) ;
movedFiles . Add ( metadataFile ) ;
}
catch ( Exception ex )
{
_logger . Warn ( ex , "Unable to move metadata file after rename: {0}" , existingFileName ) ;
}
}
}
}
foreach ( var trackFile in trackFiles )
foreach ( var trackFile in trackFiles )
{
{
var metadataFilesForConsumer = GetMetadataFilesForConsumer ( consumer , metadataFiles ) . Where ( m = > m . TrackFileId = = trackFile . Id ) . ToList ( ) ;
var metadataFilesForConsumer = GetMetadataFilesForConsumer ( consumer , metadataFiles ) . Where ( m = > m . TrackFileId = = trackFile . Id ) . ToList ( ) ;
@ -233,9 +259,9 @@ namespace NzbDrone.Core.Extras.Metadata
return metadata ;
return metadata ;
}
}
private MetadataFile ProcessAlbumMetadata ( IMetadata consumer , A lbum album , List < MetadataFile > existingMetadataFiles )
private MetadataFile ProcessAlbumMetadata ( IMetadata consumer , A rtist artist , A lbum album , string albumPath , List < MetadataFile > existingMetadataFiles )
{
{
var albumMetadata = consumer . AlbumMetadata ( a lbum. A rtist, album ) ;
var albumMetadata = consumer . AlbumMetadata ( a rtist, album , albumPath ) ;
if ( albumMetadata = = null )
if ( albumMetadata = = null )
{
{
@ -244,10 +270,10 @@ namespace NzbDrone.Core.Extras.Metadata
var hash = albumMetadata . Contents . SHA256Hash ( ) ;
var hash = albumMetadata . Contents . SHA256Hash ( ) ;
var metadata = GetMetadataFile ( a lbum. A rtist, existingMetadataFiles , e = > e . Type = = MetadataType . AlbumMetadata & & e . AlbumId = = album . Id ) ? ?
var metadata = GetMetadataFile ( a rtist, existingMetadataFiles , e = > e . Type = = MetadataType . AlbumMetadata & & e . AlbumId = = album . Id ) ? ?
new MetadataFile
new MetadataFile
{
{
ArtistId = a lbum. Artist Id,
ArtistId = a rtist. Id,
AlbumId = album . Id ,
AlbumId = album . Id ,
Consumer = consumer . GetType ( ) . Name ,
Consumer = consumer . GetType ( ) . Name ,
Type = MetadataType . AlbumMetadata
Type = MetadataType . AlbumMetadata
@ -265,7 +291,7 @@ namespace NzbDrone.Core.Extras.Metadata
return null ;
return null ;
}
}
var fullPath = Path . Combine ( a lbum . Path , albumMetadata . RelativePath ) ;
var fullPath = Path . Combine ( a rtist . Path , albumMetadata . RelativePath ) ;
_logger . Debug ( "Writing Album Metadata to: {0}" , fullPath ) ;
_logger . Debug ( "Writing Album Metadata to: {0}" , fullPath ) ;
SaveMetadataFile ( fullPath , albumMetadata . Contents ) ;
SaveMetadataFile ( fullPath , albumMetadata . Contents ) ;
@ -277,16 +303,16 @@ namespace NzbDrone.Core.Extras.Metadata
return metadata ;
return metadata ;
}
}
private MetadataFile Process Episode Metadata( IMetadata consumer , Artist artist , TrackFile trackFile , List < MetadataFile > existingMetadataFiles )
private MetadataFile Process Track Metadata( IMetadata consumer , Artist artist , TrackFile trackFile , List < MetadataFile > existingMetadataFiles )
{
{
var episode Metadata = consumer . TrackMetadata ( artist , trackFile ) ;
var track Metadata = consumer . TrackMetadata ( artist , trackFile ) ;
if ( episode Metadata = = null )
if ( track Metadata = = null )
{
{
return null ;
return null ;
}
}
var fullPath = Path . Combine ( artist . Path , episode Metadata. RelativePath ) ;
var fullPath = Path . Combine ( artist . Path , track Metadata. RelativePath ) ;
var existingMetadata = GetMetadataFile ( artist , existingMetadataFiles , c = > c . Type = = MetadataType . TrackMetadata & &
var existingMetadata = GetMetadataFile ( artist , existingMetadataFiles , c = > c . Type = = MetadataType . TrackMetadata & &
c . TrackFileId = = trackFile . Id ) ;
c . TrackFileId = = trackFile . Id ) ;
@ -297,11 +323,11 @@ namespace NzbDrone.Core.Extras.Metadata
if ( fullPath . PathNotEquals ( existingFullPath ) )
if ( fullPath . PathNotEquals ( existingFullPath ) )
{
{
_diskTransferService . TransferFile ( existingFullPath , fullPath , TransferMode . Move ) ;
_diskTransferService . TransferFile ( existingFullPath , fullPath , TransferMode . Move ) ;
existingMetadata . RelativePath = episode Metadata. RelativePath ;
existingMetadata . RelativePath = track Metadata. RelativePath ;
}
}
}
}
var hash = episode Metadata. Contents . SHA256Hash ( ) ;
var hash = track Metadata. Contents . SHA256Hash ( ) ;
var metadata = existingMetadata ? ?
var metadata = existingMetadata ? ?
new MetadataFile
new MetadataFile
@ -311,7 +337,7 @@ namespace NzbDrone.Core.Extras.Metadata
TrackFileId = trackFile . Id ,
TrackFileId = trackFile . Id ,
Consumer = consumer . GetType ( ) . Name ,
Consumer = consumer . GetType ( ) . Name ,
Type = MetadataType . TrackMetadata ,
Type = MetadataType . TrackMetadata ,
RelativePath = episode Metadata. RelativePath ,
RelativePath = track Metadata. RelativePath ,
Extension = Path . GetExtension ( fullPath )
Extension = Path . GetExtension ( fullPath )
} ;
} ;
@ -321,7 +347,7 @@ namespace NzbDrone.Core.Extras.Metadata
}
}
_logger . Debug ( "Writing Track Metadata to: {0}" , fullPath ) ;
_logger . Debug ( "Writing Track Metadata to: {0}" , fullPath ) ;
SaveMetadataFile ( fullPath , episode Metadata. Contents ) ;
SaveMetadataFile ( fullPath , track Metadata. Contents ) ;
metadata . Hash = hash ;
metadata . Hash = hash ;
@ -361,92 +387,39 @@ namespace NzbDrone.Core.Extras.Metadata
return result ;
return result ;
}
}
private List < MetadataFile > ProcessAlbumImages ( IMetadata consumer , Artist artist , List < MetadataFile > existingMetadataFiles )
private List < MetadataFile > ProcessAlbumImages ( IMetadata consumer , Artist artist , Album album , string albumFolder , List < MetadataFile > existingMetadataFiles )
{
var result = new List < MetadataFile > ( ) ;
var albums = _albumService . GetAlbumsByArtist ( artist . Id ) ;
foreach ( var album in albums )
{
foreach ( var image in consumer . AlbumImages ( artist , album ) )
{
var fullPath = Path . Combine ( artist . Path , image . RelativePath ) ;
if ( _diskProvider . FileExists ( fullPath ) )
{
_logger . Debug ( "Album image already exists: {0}" , fullPath ) ;
continue ;
}
var metadata = GetMetadataFile ( artist , existingMetadataFiles , c = > c . Type = = MetadataType . AlbumImage & &
c . AlbumId = = album . Id & &
c . RelativePath = = image . RelativePath ) ? ?
new MetadataFile
{
ArtistId = artist . Id ,
AlbumId = album . Id ,
Consumer = consumer . GetType ( ) . Name ,
Type = MetadataType . AlbumImage ,
RelativePath = image . RelativePath ,
Extension = Path . GetExtension ( fullPath )
} ;
DownloadImage ( album , image ) ;
result . Add ( metadata ) ;
}
}
return result ;
}
private List < MetadataFile > ProcessEpisodeImages ( IMetadata consumer , Artist artist , TrackFile trackFile , List < MetadataFile > existingMetadataFiles )
{
{
var result = new List < MetadataFile > ( ) ;
var result = new List < MetadataFile > ( ) ;
foreach ( var image in consumer . TrackImages( artist , trackFile ) )
foreach ( var image in consumer . AlbumImages ( artist , album , albumFolder ) )
{
{
var fullPath = Path . Combine ( artist . Path , image . RelativePath ) ;
var fullPath = Path . Combine ( artist . Path , image . RelativePath ) ;
if ( _diskProvider . FileExists ( fullPath ) )
if ( _diskProvider . FileExists ( fullPath ) )
{
{
_logger . Debug ( " Track image already exists: {0}", fullPath ) ;
_logger . Debug ( "Album image already exists: {0}" , fullPath ) ;
continue ;
continue ;
}
}
var existingMetadata = GetMetadataFile ( artist , existingMetadataFiles , c = > c . Type = = MetadataType . TrackImage & &
var metadata = GetMetadataFile ( artist , existingMetadataFiles , c = > c . Type = = MetadataType . AlbumImage & &
c . TrackFileId = = trackFile . Id ) ;
c . AlbumId = = album . Id & &
c . RelativePath = = image . RelativePath ) ? ?
if ( existingMetadata ! = null )
new MetadataFile
{
{
var existingFullPath = Path . Combine ( artist . Path , existingMetadata . RelativePath ) ;
ArtistId = artist . Id ,
if ( fullPath . PathNotEquals ( existingFullPath ) )
AlbumId = album . Id ,
{
Consumer = consumer . GetType ( ) . Name ,
_diskTransferService . TransferFile ( existingFullPath , fullPath , TransferMode . Move ) ;
Type = MetadataType . AlbumImage ,
existingMetadata . RelativePath = image . RelativePath ;
RelativePath = image . RelativePath ,
Extension = Path . GetExtension ( fullPath )
return new List < MetadataFile > { existingMetadata } ;
} ;
}
}
var metadata = existingMetadata ? ?
new MetadataFile
{
ArtistId = artist . Id ,
AlbumId = trackFile . AlbumId ,
TrackFileId = trackFile . Id ,
Consumer = consumer . GetType ( ) . Name ,
Type = MetadataType . TrackImage ,
RelativePath = image . RelativePath ,
Extension = Path . GetExtension ( fullPath )
} ;
DownloadImage ( artist , image ) ;
DownloadImage ( artist , image ) ;
result . Add ( metadata ) ;
result . Add ( metadata ) ;
}
}
return result ;
return result ;
}
}
@ -476,32 +449,6 @@ namespace NzbDrone.Core.Extras.Metadata
}
}
}
}
private void DownloadImage ( Album album , ImageFileResult image )
{
var fullPath = Path . Combine ( album . Path , image . RelativePath ) ;
try
{
if ( image . Url . StartsWith ( "http" ) )
{
_httpClient . DownloadFile ( image . Url , fullPath ) ;
}
else
{
_diskProvider . CopyFile ( image . Url , fullPath ) ;
}
_mediaFileAttributeService . SetFilePermissions ( fullPath ) ;
}
catch ( WebException ex )
{
_logger . Warn ( ex , "Couldn't download image {0} for {1}. {2}" , image . Url , album , ex . Message ) ;
}
catch ( Exception ex )
{
_logger . Error ( ex , "Couldn't download image {0} for {1}. {2}" , image . Url , album , ex . Message ) ;
}
}
private void SaveMetadataFile ( string path , string contents )
private void SaveMetadataFile ( string path , string contents )
{
{
_diskProvider . WriteAllText ( path , contents ) ;
_diskProvider . WriteAllText ( path , contents ) ;