TVUtils.cs 4.8 KB

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