diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index bdf464bbff..018b3960d7 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -108,6 +108,8 @@ + + diff --git a/MediaBrowser.Controller/Providers/FanartBaseProvider.cs b/MediaBrowser.Controller/Providers/FanartBaseProvider.cs index 8ea7532f38..fdac03c9a8 100644 --- a/MediaBrowser.Controller/Providers/FanartBaseProvider.cs +++ b/MediaBrowser.Controller/Providers/FanartBaseProvider.cs @@ -7,6 +7,14 @@ using MediaBrowser.Model.Logging; namespace MediaBrowser.Controller.Providers { + class FanArtProviderException : ApplicationException + { + public FanArtProviderException(string msg) + : base(msg) + { + } + + } /// /// Class FanartBaseProvider /// diff --git a/MediaBrowser.Controller/Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Controller/Providers/Music/FanArtAlbumProvider.cs new file mode 100644 index 0000000000..2d7284c80e --- /dev/null +++ b/MediaBrowser.Controller/Providers/Music/FanArtAlbumProvider.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Common.Extensions; + +namespace MediaBrowser.Controller.Providers.Music +{ + public class FanArtAlbumProvider : FanartBaseProvider + { + public FanArtAlbumProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager) + { + } + + public override bool Supports(BaseItem item) + { + return item is MusicAlbum && item.Parent is MusicArtist; + } + + /// + /// Needses the refresh internal. + /// + /// The item. + /// The provider info. + /// true if we need refreshing, false otherwise + protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo) + { + //we fetch if image needed and haven't already tried recently + return string.IsNullOrEmpty(item.PrimaryImagePath) && + DateTime.Today.Subtract(providerInfo.LastRefreshed).TotalDays > ConfigurationManager.Configuration.MetadataRefreshDays; + } + + protected override async Task FetchAsyncInternal(BaseItem item, bool force, CancellationToken cancellationToken) + { + var mbid = item.GetProviderId(MetadataProviders.Musicbrainz); + if (mbid == null) + { + Logger.Warn("No Musicbrainz id associated with album {0}", item.Name); + SetLastRefreshed(item, DateTime.UtcNow, ProviderRefreshStatus.CompletedWithErrors); + return false; + } + + cancellationToken.ThrowIfCancellationRequested(); + + //Look at our parent for our album cover + var artist = (MusicArtist)item.Parent; + var cover = artist.AlbumCovers != null ? artist.AlbumCovers.GetValueOrDefault(mbid, null) : null; + if (cover == null) + { + // Not there - maybe it is new since artist last refreshed so refresh it and try again + await artist.RefreshMetadata(cancellationToken).ConfigureAwait(false); + cancellationToken.ThrowIfCancellationRequested(); + + cover = artist.AlbumCovers != null ? artist.AlbumCovers.GetValueOrDefault(mbid, null) : null; + } + if (cover == null) + { + Logger.Warn("Unable to find cover art for {0}", item.Name); + SetLastRefreshed(item, DateTime.UtcNow, ProviderRefreshStatus.CompletedWithErrors); + return false; + } + + item.SetImage(ImageType.Primary, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(item, cover, "folder.jpg", FanArtResourcePool, cancellationToken).ConfigureAwait(false)); + return true; + } + } +} diff --git a/MediaBrowser.Controller/Providers/Music/LastfmAlbumProvider.cs b/MediaBrowser.Controller/Providers/Music/LastfmAlbumProvider.cs new file mode 100644 index 0000000000..70de42f4d4 --- /dev/null +++ b/MediaBrowser.Controller/Providers/Music/LastfmAlbumProvider.cs @@ -0,0 +1,76 @@ +using System.IO; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.Serialization; + +namespace MediaBrowser.Controller.Providers.Music +{ + public class LastfmAlbumProvider : LastfmBaseProvider + { + private static readonly Task BlankId = Task.FromResult("0000"); + + public LastfmAlbumProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager) + : base(jsonSerializer, httpClient, logManager, configurationManager) + { + LocalMetaFileName = LastfmHelper.LocalAlbumMetaFileName; + } + + protected override Task FindId(BaseItem item, CancellationToken cancellationToken) + { + // We don't fetch by id + return BlankId; + } + + protected override async Task FetchLastfmData(BaseItem item, string id, CancellationToken cancellationToken) + { + // Get albu info using artist and album name + var url = RootUrl + string.Format("method=album.getInfo&artist={0}&album={1}&api_key={2}&format=json", UrlEncode(item.Parent.Name), UrlEncode(item.Name), ApiKey); + + LastfmGetAlbumResult result = null; + + try + { + using (var json = await HttpClient.Get(url, LastfmResourcePool, cancellationToken).ConfigureAwait(false)) + { + result = JsonSerializer.DeserializeFromStream(json); + } + } + catch (HttpException e) + { + if (e.StatusCode == HttpStatusCode.NotFound) + { + throw new LastfmProviderException(string.Format("Unable to retrieve album info for {0} with artist {1}", item.Name, item.Parent.Name)); + } + throw; + } + + if (result != null && result.album != null) + { + LastfmHelper.ProcessAlbumData(item, result.album); + //And save locally if indicated + if (ConfigurationManager.Configuration.SaveLocalMeta) + { + var ms = new MemoryStream(); + JsonSerializer.SerializeToStream(result.album, ms); + + cancellationToken.ThrowIfCancellationRequested(); + + await Kernel.Instance.FileSystemManager.SaveToLibraryFilesystem(item, Path.Combine(item.MetaLocation, LocalMetaFileName), ms, cancellationToken).ConfigureAwait(false); + + } + } + } + + public override bool Supports(BaseItem item) + { + return item is MusicAlbum; + } + } +} diff --git a/MediaBrowser.Controller/Providers/Music/LastfmArtistProvider.cs b/MediaBrowser.Controller/Providers/Music/LastfmArtistProvider.cs index 8aca8b9a04..29cb35cdc9 100644 --- a/MediaBrowser.Controller/Providers/Music/LastfmArtistProvider.cs +++ b/MediaBrowser.Controller/Providers/Music/LastfmArtistProvider.cs @@ -75,7 +75,7 @@ namespace MediaBrowser.Controller.Providers.Music { if (e.StatusCode == HttpStatusCode.NotFound) { - throw new LastfmProviderException(string.Format("Unable to retrieve artist info for {0} with id {0}", item.Name, id)); + throw new LastfmProviderException(string.Format("Unable to retrieve artist info for {0} with id {1}", item.Name, id)); } throw; } diff --git a/MediaBrowser.Controller/Providers/Music/LastfmBaseProvider.cs b/MediaBrowser.Controller/Providers/Music/LastfmBaseProvider.cs index f18a9cb653..d8b4c387f5 100644 --- a/MediaBrowser.Controller/Providers/Music/LastfmBaseProvider.cs +++ b/MediaBrowser.Controller/Providers/Music/LastfmBaseProvider.cs @@ -123,7 +123,7 @@ namespace MediaBrowser.Controller.Providers.Music var id = item.GetProviderId(MetadataProviders.Musicbrainz) ?? await FindId(item, cancellationToken).ConfigureAwait(false); if (id != null) { - Logger.Debug("LastfmProvider - getting info with id: " + id); + Logger.Debug("LastfmProvider - getting info for {0}", item.Name); cancellationToken.ThrowIfCancellationRequested(); @@ -275,6 +275,25 @@ namespace MediaBrowser.Controller.Providers.Music public LastFmBio bio { get; set; } } + + public class LastfmAlbum + { + public string name { get; set; } + public string artist { get; set; } + public string id { get; set; } + public string mbid { get; set; } + public string releasedate { get; set; } + public int listeners { get; set; } + public int playcount { get; set; } + public LastfmTags toptags { get; set; } + public LastFmBio wiki { get; set; } + } + + public class LastfmGetAlbumResult + { + public LastfmAlbum album { get; set; } + } + public class LastfmGetArtistResult { public LastfmArtist artist { get; set; } diff --git a/MediaBrowser.Controller/Providers/Music/LastfmHelper.cs b/MediaBrowser.Controller/Providers/Music/LastfmHelper.cs index d4559b94a1..101422f01b 100644 --- a/MediaBrowser.Controller/Providers/Music/LastfmHelper.cs +++ b/MediaBrowser.Controller/Providers/Music/LastfmHelper.cs @@ -4,25 +4,59 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Providers.Music { public static class LastfmHelper { public static string LocalArtistMetaFileName = "MBArtist.json"; + public static string LocalAlbumMetaFileName = "MBAlbum.json"; public static void ProcessArtistData(BaseItem artist, LastfmArtist data) { artist.Overview = data.bio != null ? data.bio.content : null; + var yearFormed = 0; + try + { + yearFormed = Convert.ToInt32(data.bio.yearformed); + } + catch (FormatException) + { + } + catch (NullReferenceException) + { + } + catch (OverflowException) + { + } + artist.PremiereDate = new DateTime(yearFormed, 1,1); if (data.tags != null) { - foreach (var tag in data.tags.tag) - { - artist.AddGenre(tag.name); - } - + AddGenres(artist, data.tags); } } + public static void ProcessAlbumData(BaseItem item, LastfmAlbum data) + { + if (!string.IsNullOrWhiteSpace(data.mbid)) item.SetProviderId(MetadataProviders.Musicbrainz, data.mbid); + + item.Overview = data.wiki != null ? data.wiki.content : null; + var release = DateTime.MinValue; + DateTime.TryParse(data.releasedate, out release); + item.PremiereDate = release; + if (data.toptags != null) + { + AddGenres(item, data.toptags); + } + } + + private static void AddGenres(BaseItem item, LastfmTags tags) + { + foreach (var tag in tags.tag) + { + item.AddGenre(tag.name); + } + } } } diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 14e0076dda..6422315489 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -402,4 +402,10 @@ del "$(SolutionDir)..\Deploy\MBServer.zip" --> + + + + + + \ No newline at end of file