AppleTrailerListingDownloader.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. using MediaBrowser.Common.Extensions;
  2. using MediaBrowser.Controller;
  3. using MediaBrowser.Controller.Entities;
  4. using MediaBrowser.Model.Entities;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Globalization;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using System.Xml;
  11. namespace MediaBrowser.Plugins.Trailers
  12. {
  13. /// <summary>
  14. /// Fetches Apple's list of current movie trailers
  15. /// </summary>
  16. public static class AppleTrailerListingDownloader
  17. {
  18. /// <summary>
  19. /// The trailer feed URL
  20. /// </summary>
  21. private const string TrailerFeedUrl = "http://trailers.apple.com/trailers/home/xml/current_720p.xml";
  22. /// <summary>
  23. /// Downloads a list of trailer info's from the apple url
  24. /// </summary>
  25. /// <returns>Task{List{TrailerInfo}}.</returns>
  26. public static async Task<List<TrailerInfo>> GetTrailerList(CancellationToken cancellationToken)
  27. {
  28. var stream = await Kernel.Instance.HttpManager.Get(TrailerFeedUrl, Kernel.Instance.ResourcePools.AppleTrailerVideos, cancellationToken).ConfigureAwait(false);
  29. var list = new List<TrailerInfo>();
  30. using (var reader = XmlReader.Create(stream, new XmlReaderSettings { Async = true }))
  31. {
  32. await reader.MoveToContentAsync().ConfigureAwait(false);
  33. while (await reader.ReadAsync().ConfigureAwait(false))
  34. {
  35. cancellationToken.ThrowIfCancellationRequested();
  36. if (reader.NodeType == XmlNodeType.Element)
  37. {
  38. switch (reader.Name)
  39. {
  40. case "movieinfo":
  41. var trailer = FetchTrailerInfo(reader.ReadSubtree());
  42. list.Add(trailer);
  43. break;
  44. }
  45. }
  46. }
  47. }
  48. return list;
  49. }
  50. /// <summary>
  51. /// Fetches trailer info from an xml node
  52. /// </summary>
  53. /// <param name="reader">The reader.</param>
  54. /// <returns>TrailerInfo.</returns>
  55. private static TrailerInfo FetchTrailerInfo(XmlReader reader)
  56. {
  57. var trailerInfo = new TrailerInfo { };
  58. reader.MoveToContent();
  59. while (reader.Read())
  60. {
  61. if (reader.NodeType == XmlNodeType.Element)
  62. {
  63. switch (reader.Name)
  64. {
  65. case "info":
  66. FetchInfo(reader.ReadSubtree(), trailerInfo);
  67. break;
  68. case "cast":
  69. FetchCast(reader.ReadSubtree(), trailerInfo);
  70. break;
  71. case "genre":
  72. FetchGenres(reader.ReadSubtree(), trailerInfo);
  73. break;
  74. case "poster":
  75. FetchPosterUrl(reader.ReadSubtree(), trailerInfo);
  76. break;
  77. case "preview":
  78. FetchTrailerUrl(reader.ReadSubtree(), trailerInfo);
  79. break;
  80. default:
  81. reader.Skip();
  82. break;
  83. }
  84. }
  85. }
  86. return trailerInfo;
  87. }
  88. private static readonly CultureInfo USCulture = new CultureInfo("en-US");
  89. /// <summary>
  90. /// Fetches from the info node
  91. /// </summary>
  92. /// <param name="reader">The reader.</param>
  93. /// <param name="info">The info.</param>
  94. private static void FetchInfo(XmlReader reader, TrailerInfo info)
  95. {
  96. reader.MoveToContent();
  97. reader.Read();
  98. while (reader.NodeType == XmlNodeType.Element)
  99. {
  100. switch (reader.Name)
  101. {
  102. case "title":
  103. info.Video.Name = reader.ReadStringSafe();
  104. break;
  105. case "runtime":
  106. {
  107. var runtime = reader.ReadStringSafe();
  108. if (!string.IsNullOrWhiteSpace(runtime))
  109. {
  110. if (runtime.StartsWith(":", StringComparison.OrdinalIgnoreCase))
  111. {
  112. runtime = "0" + runtime;
  113. }
  114. TimeSpan runtimeTimeSpan;
  115. if (TimeSpan.TryParse(runtime, USCulture, out runtimeTimeSpan))
  116. {
  117. info.Video.RunTimeTicks = runtimeTimeSpan.Ticks;
  118. }
  119. }
  120. break;
  121. }
  122. case "rating":
  123. info.Video.OfficialRating = reader.ReadStringSafe();
  124. break;
  125. case "studio":
  126. {
  127. var studio = reader.ReadStringSafe();
  128. if (!string.IsNullOrWhiteSpace(studio))
  129. {
  130. info.Video.AddStudio(studio);
  131. }
  132. break;
  133. }
  134. case "postdate":
  135. {
  136. DateTime date;
  137. if (DateTime.TryParse(reader.ReadStringSafe(), USCulture, DateTimeStyles.None, out date))
  138. {
  139. info.PostDate = date;
  140. }
  141. break;
  142. }
  143. case "releasedate":
  144. {
  145. var val = reader.ReadStringSafe();
  146. if (!string.IsNullOrWhiteSpace(val))
  147. {
  148. DateTime date;
  149. if (DateTime.TryParse(val, USCulture, DateTimeStyles.None, out date))
  150. {
  151. info.Video.PremiereDate = date;
  152. info.Video.ProductionYear = date.Year;
  153. }
  154. }
  155. break;
  156. }
  157. case "director":
  158. {
  159. var directors = reader.ReadStringSafe() ?? string.Empty;
  160. foreach (var director in directors.Split(',', StringSplitOptions.RemoveEmptyEntries))
  161. {
  162. var name = director.Trim();
  163. if (!string.IsNullOrWhiteSpace(name))
  164. {
  165. info.Video.AddPerson(new PersonInfo { Name = name, Type = PersonType.Director });
  166. }
  167. }
  168. break;
  169. }
  170. case "description":
  171. info.Video.Overview = reader.ReadStringSafe();
  172. break;
  173. default:
  174. reader.Skip();
  175. break;
  176. }
  177. }
  178. }
  179. /// <summary>
  180. /// Fetches from the genre node
  181. /// </summary>
  182. /// <param name="reader">The reader.</param>
  183. /// <param name="info">The info.</param>
  184. private static void FetchGenres(XmlReader reader, TrailerInfo info)
  185. {
  186. reader.MoveToContent();
  187. reader.Read();
  188. while (reader.IsStartElement())
  189. {
  190. if (reader.NodeType == XmlNodeType.Element)
  191. {
  192. switch (reader.Name)
  193. {
  194. case "name":
  195. info.Video.AddGenre(reader.ReadStringSafe());
  196. break;
  197. default:
  198. reader.Skip();
  199. break;
  200. }
  201. }
  202. }
  203. }
  204. /// <summary>
  205. /// Fetches from the cast node
  206. /// </summary>
  207. /// <param name="reader">The reader.</param>
  208. /// <param name="info">The info.</param>
  209. private static void FetchCast(XmlReader reader, TrailerInfo info)
  210. {
  211. reader.MoveToContent();
  212. reader.Read();
  213. while (reader.IsStartElement())
  214. {
  215. if (reader.NodeType == XmlNodeType.Element)
  216. {
  217. switch (reader.Name)
  218. {
  219. case "name":
  220. info.Video.AddPerson(new PersonInfo { Name = reader.ReadStringSafe(), Type = PersonType.Actor });
  221. break;
  222. default:
  223. reader.Skip();
  224. break;
  225. }
  226. }
  227. }
  228. }
  229. /// <summary>
  230. /// Fetches from the preview node
  231. /// </summary>
  232. /// <param name="reader">The reader.</param>
  233. /// <param name="info">The info.</param>
  234. private static void FetchTrailerUrl(XmlReader reader, TrailerInfo info)
  235. {
  236. reader.MoveToContent();
  237. reader.Read();
  238. while (reader.NodeType == XmlNodeType.Element)
  239. {
  240. switch (reader.Name)
  241. {
  242. case "large":
  243. info.TrailerUrl = reader.ReadStringSafe();
  244. break;
  245. default:
  246. reader.Skip();
  247. break;
  248. }
  249. }
  250. }
  251. /// <summary>
  252. /// Fetches from the poster node
  253. /// </summary>
  254. /// <param name="reader">The reader.</param>
  255. /// <param name="info">The info.</param>
  256. private static void FetchPosterUrl(XmlReader reader, TrailerInfo info)
  257. {
  258. reader.MoveToContent();
  259. reader.Read();
  260. while (reader.NodeType == XmlNodeType.Element)
  261. {
  262. switch (reader.Name)
  263. {
  264. case "location":
  265. info.ImageUrl = reader.ReadStringSafe();
  266. break;
  267. case "xlarge":
  268. info.HdImageUrl = reader.ReadStringSafe();
  269. break;
  270. default:
  271. reader.Skip();
  272. break;
  273. }
  274. }
  275. }
  276. }
  277. }