TVUtils.cs 4.4 KB

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