TVUtils.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. using System.Collections.Generic;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Text.RegularExpressions;
  5. using MediaBrowser.Controller.IO;
  6. namespace MediaBrowser.TV
  7. {
  8. public static class TVUtils
  9. {
  10. private static readonly Regex[] seasonPathExpressions = new Regex[] {
  11. new Regex(@".+\\[s|S]eason\s?(?<seasonnumber>\d{1,2})$"),
  12. new Regex(@".+\\[s|S]æson\s?(?<seasonnumber>\d{1,2})$"),
  13. new Regex(@".+\\[t|T]emporada\s?(?<seasonnumber>\d{1,2})$"),
  14. new Regex(@".+\\[s|S]aison\s?(?<seasonnumber>\d{1,2})$"),
  15. new Regex(@".+\\[s|S]taffel\s?(?<seasonnumber>\d{1,2})$"),
  16. new Regex(@".+\\[s|S](?<seasonnumber>\d{1,2})$"),
  17. new Regex(@".+\\[s|S]eason\s?(?<seasonnumber>\d{1,2})[^\\]*$")
  18. };
  19. /// <summary>
  20. /// Used to detect paths that represent episodes, need to make sure they don't also
  21. /// match movie titles like "2001 A Space..."
  22. /// Currently we limit the numbers here to 2 digits to try and avoid this
  23. /// </summary>
  24. /// <remarks>
  25. /// The order here is important, if the order is changed some of the later
  26. /// ones might incorrectly match things that higher ones would have caught.
  27. /// The most restrictive expressions should appear first
  28. /// </remarks>
  29. private static readonly Regex[] episodeExpressions = new Regex[] {
  30. new Regex(@".*\\[s|S]?(?<seasonnumber>\d{1,2})[x|X](?<epnumber>\d{1,3})[^\\]*$"), // 01x02 blah.avi S01x01 balh.avi
  31. new Regex(@".*\\[s|S](?<seasonnumber>\d{1,2})x?[e|E](?<epnumber>\d{1,3})[^\\]*$"), // S01E02 blah.avi, S01xE01 blah.avi
  32. new Regex(@".*\\(?<seriesname>[^\\]*)[s|S]?(?<seasonnumber>\d{1,2})[x|X](?<epnumber>\d{1,3})[^\\]*$"), // 01x02 blah.avi S01x01 balh.avi
  33. new Regex(@".*\\(?<seriesname>[^\\]*)[s|S](?<seasonnumber>\d{1,2})[x|X|\.]?[e|E](?<epnumber>\d{1,3})[^\\]*$") // S01E02 blah.avi, S01xE01 blah.avi
  34. };
  35. /// <summary>
  36. /// To avoid the following matching movies they are only valid when contained in a folder which has been matched as a being season
  37. /// </summary>
  38. private static readonly Regex[] episodeExpressionsInASeasonFolder = new Regex[] {
  39. new Regex(@".*\\(?<epnumber>\d{1,2})\s?-\s?[^\\]*$"), // 01 - blah.avi, 01-blah.avi
  40. new Regex(@".*\\(?<epnumber>\d{1,2})[^\d\\]*[^\\]*$"), // 01.avi, 01.blah.avi "01 - 22 blah.avi"
  41. new Regex(@".*\\(?<seasonnumber>\d)(?<epnumber>\d{1,2})[^\d\\]+[^\\]*$"), // 01.avi, 01.blah.avi
  42. new Regex(@".*\\\D*\d+(?<epnumber>\d{2})") // hell0 - 101 - hello.avi
  43. };
  44. public static bool IsSeasonFolder(string path)
  45. {
  46. path = path.ToLower();
  47. return seasonPathExpressions.Any(r => r.IsMatch(path));
  48. }
  49. public static bool IsSeriesFolder(string path, KeyValuePair<string, WIN32_FIND_DATA>[] fileSystemChildren)
  50. {
  51. for (int i = 0; i < fileSystemChildren.Length; i++)
  52. {
  53. var child = fileSystemChildren[i];
  54. if (child.Value.IsDirectory)
  55. {
  56. if (IsSeasonFolder(child.Key))
  57. {
  58. return true;
  59. }
  60. }
  61. else
  62. {
  63. if (!string.IsNullOrEmpty(EpisodeNumberFromFile(child.Key, false)))
  64. {
  65. return true;
  66. }
  67. }
  68. }
  69. return false;
  70. }
  71. public static string EpisodeNumberFromFile(string fullPath, bool isInSeason)
  72. {
  73. string fl = fullPath.ToLower();
  74. foreach (Regex r in episodeExpressions)
  75. {
  76. Match m = r.Match(fl);
  77. if (m.Success)
  78. return m.Groups["epnumber"].Value;
  79. }
  80. if (isInSeason)
  81. {
  82. foreach (Regex r in episodeExpressionsInASeasonFolder)
  83. {
  84. Match m = r.Match(fl);
  85. if (m.Success)
  86. return m.Groups["epnumber"].Value;
  87. }
  88. }
  89. return null;
  90. }
  91. }
  92. }