TvdbSeriesImageProvider.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. using MediaBrowser.Common.Extensions;
  2. using MediaBrowser.Common.Net;
  3. using MediaBrowser.Controller.Configuration;
  4. using MediaBrowser.Controller.Entities;
  5. using MediaBrowser.Controller.Entities.TV;
  6. using MediaBrowser.Controller.Library;
  7. using MediaBrowser.Controller.Providers;
  8. using MediaBrowser.Model.Entities;
  9. using MediaBrowser.Model.Logging;
  10. using System;
  11. using System.Globalization;
  12. using System.IO;
  13. using System.Threading;
  14. using System.Threading.Tasks;
  15. using System.Xml;
  16. namespace MediaBrowser.Providers.TV
  17. {
  18. public class TvdbSeriesImageProvider : BaseMetadataProvider
  19. {
  20. /// <summary>
  21. /// Gets the HTTP client.
  22. /// </summary>
  23. /// <value>The HTTP client.</value>
  24. protected IHttpClient HttpClient { get; private set; }
  25. /// <summary>
  26. /// The _provider manager
  27. /// </summary>
  28. private readonly IProviderManager _providerManager;
  29. /// <summary>
  30. /// Initializes a new instance of the <see cref="TvdbSeriesImageProvider"/> class.
  31. /// </summary>
  32. /// <param name="httpClient">The HTTP client.</param>
  33. /// <param name="logManager">The log manager.</param>
  34. /// <param name="configurationManager">The configuration manager.</param>
  35. /// <param name="providerManager">The provider manager.</param>
  36. /// <exception cref="System.ArgumentNullException">httpClient</exception>
  37. public TvdbSeriesImageProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager)
  38. : base(logManager, configurationManager)
  39. {
  40. if (httpClient == null)
  41. {
  42. throw new ArgumentNullException("httpClient");
  43. }
  44. HttpClient = httpClient;
  45. _providerManager = providerManager;
  46. }
  47. /// <summary>
  48. /// Supportses the specified item.
  49. /// </summary>
  50. /// <param name="item">The item.</param>
  51. /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
  52. public override bool Supports(BaseItem item)
  53. {
  54. return item is Series;
  55. }
  56. /// <summary>
  57. /// Gets the priority.
  58. /// </summary>
  59. /// <value>The priority.</value>
  60. public override MetadataProviderPriority Priority
  61. {
  62. // Run after fanart
  63. get { return MetadataProviderPriority.Fourth; }
  64. }
  65. /// <summary>
  66. /// Gets a value indicating whether [requires internet].
  67. /// </summary>
  68. /// <value><c>true</c> if [requires internet]; otherwise, <c>false</c>.</value>
  69. public override bool RequiresInternet
  70. {
  71. get
  72. {
  73. return true;
  74. }
  75. }
  76. /// <summary>
  77. /// Returns true or false indicating if the provider should refresh when the contents of it's directory changes
  78. /// </summary>
  79. /// <value><c>true</c> if [refresh on file system stamp change]; otherwise, <c>false</c>.</value>
  80. protected override bool RefreshOnFileSystemStampChange
  81. {
  82. get
  83. {
  84. return ConfigurationManager.Configuration.SaveLocalMeta;
  85. }
  86. }
  87. /// <summary>
  88. /// Gets a value indicating whether [refresh on version change].
  89. /// </summary>
  90. /// <value><c>true</c> if [refresh on version change]; otherwise, <c>false</c>.</value>
  91. protected override bool RefreshOnVersionChange
  92. {
  93. get
  94. {
  95. return true;
  96. }
  97. }
  98. /// <summary>
  99. /// Gets the provider version.
  100. /// </summary>
  101. /// <value>The provider version.</value>
  102. protected override string ProviderVersion
  103. {
  104. get
  105. {
  106. return "1";
  107. }
  108. }
  109. /// <summary>
  110. /// Needses the refresh internal.
  111. /// </summary>
  112. /// <param name="item">The item.</param>
  113. /// <param name="providerInfo">The provider info.</param>
  114. /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
  115. protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
  116. {
  117. if (GetComparisonData(item) != providerInfo.Data)
  118. {
  119. return true;
  120. }
  121. return base.NeedsRefreshInternal(item, providerInfo);
  122. }
  123. /// <summary>
  124. /// Gets the comparison data.
  125. /// </summary>
  126. /// <param name="item">The item.</param>
  127. /// <returns>Guid.</returns>
  128. private Guid GetComparisonData(BaseItem item)
  129. {
  130. var seriesId = item.GetProviderId(MetadataProviders.Tvdb);
  131. if (!string.IsNullOrEmpty(seriesId))
  132. {
  133. // Process images
  134. var imagesXmlPath = Path.Combine(RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId), "banners.xml");
  135. var imagesFileInfo = new FileInfo(imagesXmlPath);
  136. return GetComparisonData(imagesFileInfo);
  137. }
  138. return Guid.Empty;
  139. }
  140. /// <summary>
  141. /// Gets the comparison data.
  142. /// </summary>
  143. /// <param name="imagesFileInfo">The images file info.</param>
  144. /// <returns>Guid.</returns>
  145. private Guid GetComparisonData(FileInfo imagesFileInfo)
  146. {
  147. var date = imagesFileInfo.Exists ? imagesFileInfo.LastWriteTimeUtc : DateTime.MinValue;
  148. var key = date.Ticks + imagesFileInfo.FullName;
  149. return key.GetMD5();
  150. }
  151. /// <summary>
  152. /// Fetches metadata and returns true or false indicating if any work that requires persistence was done
  153. /// </summary>
  154. /// <param name="item">The item.</param>
  155. /// <param name="force">if set to <c>true</c> [force].</param>
  156. /// <param name="cancellationToken">The cancellation token.</param>
  157. /// <returns>Task{System.Boolean}.</returns>
  158. public override async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
  159. {
  160. cancellationToken.ThrowIfCancellationRequested();
  161. var series = (Series)item;
  162. var seriesId = series.GetProviderId(MetadataProviders.Tvdb);
  163. if (!string.IsNullOrEmpty(seriesId))
  164. {
  165. // Process images
  166. var imagesXmlPath = Path.Combine(RemoteSeriesProvider.GetSeriesDataPath(ConfigurationManager.ApplicationPaths, seriesId), "banners.xml");
  167. var imagesFileInfo = new FileInfo(imagesXmlPath);
  168. if (imagesFileInfo.Exists)
  169. {
  170. if (!series.HasImage(ImageType.Primary) || !series.HasImage(ImageType.Banner) || series.BackdropImagePaths.Count == 0)
  171. {
  172. var xmlDoc = new XmlDocument();
  173. xmlDoc.Load(imagesXmlPath);
  174. await FetchImages(series, xmlDoc, cancellationToken).ConfigureAwait(false);
  175. }
  176. }
  177. BaseProviderInfo data;
  178. if (!item.ProviderData.TryGetValue(Id, out data))
  179. {
  180. data = new BaseProviderInfo();
  181. item.ProviderData[Id] = data;
  182. }
  183. data.Data = GetComparisonData(imagesFileInfo);
  184. SetLastRefreshed(item, DateTime.UtcNow);
  185. return true;
  186. }
  187. return false;
  188. }
  189. protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
  190. /// <summary>
  191. /// Fetches the images.
  192. /// </summary>
  193. /// <param name="series">The series.</param>
  194. /// <param name="images">The images.</param>
  195. /// <param name="cancellationToken">The cancellation token.</param>
  196. /// <returns>Task.</returns>
  197. private async Task FetchImages(Series series, XmlDocument images, CancellationToken cancellationToken)
  198. {
  199. if (!series.HasImage(ImageType.Primary) && !series.LockedImages.Contains(ImageType.Primary))
  200. {
  201. var n = images.SelectSingleNode("//Banner[BannerType='poster']");
  202. if (n != null)
  203. {
  204. n = n.SelectSingleNode("./BannerPath");
  205. if (n != null)
  206. {
  207. var path = await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "folder" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false);
  208. series.SetImage(ImageType.Primary, path);
  209. }
  210. }
  211. }
  212. if (ConfigurationManager.Configuration.DownloadSeriesImages.Banner && !series.HasImage(ImageType.Banner) && !series.LockedImages.Contains(ImageType.Banner))
  213. {
  214. var n = images.SelectSingleNode("//Banner[BannerType='series']");
  215. if (n != null)
  216. {
  217. n = n.SelectSingleNode("./BannerPath");
  218. if (n != null)
  219. {
  220. var bannerImagePath = await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "banner" + Path.GetExtension(n.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken);
  221. series.SetImage(ImageType.Banner, bannerImagePath);
  222. }
  223. }
  224. }
  225. if (series.BackdropImagePaths.Count == 0 && !series.LockedImages.Contains(ImageType.Backdrop))
  226. {
  227. var bdNo = series.BackdropImagePaths.Count;
  228. var xmlNodeList = images.SelectNodes("//Banner[BannerType='fanart']");
  229. if (xmlNodeList != null)
  230. {
  231. foreach (XmlNode b in xmlNodeList)
  232. {
  233. var p = b.SelectSingleNode("./BannerPath");
  234. if (p != null)
  235. {
  236. var bdName = "backdrop" + (bdNo > 0 ? bdNo.ToString(UsCulture) : "");
  237. series.BackdropImagePaths.Add(await _providerManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + p.InnerText, bdName + Path.GetExtension(p.InnerText), ConfigurationManager.Configuration.SaveLocalMeta, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false));
  238. bdNo++;
  239. }
  240. if (series.BackdropImagePaths.Count >= ConfigurationManager.Configuration.MaxBackdrops) break;
  241. }
  242. }
  243. }
  244. }
  245. }
  246. }