public void TestEpisodeNumberFromFile()
        {
            Assert.AreEqual("02", TVUtils.EpisodeNumberFromFile(@"c:\somefolder\Season 1\1x02 BFOD.avi"));
            Assert.AreEqual("02", TVUtils.EpisodeNumberFromFile(@"c:\somefolder\1x02 BFOD.avi"));
            Assert.AreEqual("02", TVUtils.EpisodeNumberFromFile(@"c:\somefolder\South.Park.s01e02 BFOD.avi"));
            Assert.AreEqual("02", TVUtils.EpisodeNumberFromFile(@"c:\somefolder\South.Park.s01.e02 BFOD.avi"));
            Assert.AreEqual("05", TVUtils.EpisodeNumberFromFile(@"c:\somefolder\South.Park.01x05 BFOD.avi"));
            Assert.AreEqual("02", TVUtils.EpisodeNumberFromFile(@"c:\seriesname\season1\South.Park.s01e02 BFOD.avi"));
            Assert.AreEqual("02", TVUtils.EpisodeNumberFromFile(@"c:\seriesname\season1\South.Park.S01E02 BFOD.avi"));
            Assert.AreEqual("05", TVUtils.EpisodeNumberFromFile(@"c:\seriesname\season 1\South.Park.01x05 BFOD.avi"));
            Assert.AreEqual("2", TVUtils.EpisodeNumberFromFile(@"c:\someseries\Season 1\2 - 22 Balloon.avi"));
            Assert.AreEqual("2", TVUtils.EpisodeNumberFromFile(@"c:\someseries\Saison 1\2 - 22 Balloon.avi"));
            Assert.AreEqual("2", TVUtils.EpisodeNumberFromFile(@"c:\someseries\Temporada 1\2 - 22 Balloon.avi"));
            Assert.AreEqual("2", TVUtils.EpisodeNumberFromFile(@"c:\someseries\Sæson 1\2 - 22 Balloon.avi"));
            Assert.AreEqual("03", TVUtils.EpisodeNumberFromFile(@"c:\someseries\Season1\103 BFOD.avi"));
            Assert.AreEqual("01", TVUtils.EpisodeNumberFromFile(@"c:\Flight.of.the.Conchords.S01E01....dfdfdf..avi"));
            Assert.AreEqual("02", TVUtils.EpisodeNumberFromFile(@"c:\Flight.of.the.Conchords.S01E02.avi"));
            Assert.AreEqual("03", TVUtils.EpisodeNumberFromFile(@"c:\Flight.of.the.Conchords.S01E03.sdad.avi"));
            Assert.AreEqual("04", TVUtils.EpisodeNumberFromFile(@"c:\Flight.of.the.Conchords.S01E04.dfg.avi"));
            Assert.AreEqual("05", TVUtils.EpisodeNumberFromFile(@"c:\Flight.of.the.Conchords.S01E05.dfgfd.avi"));
            Assert.AreEqual("06", TVUtils.EpisodeNumberFromFile(@"c:\Flight.of.the.Conchords.S01E06.dsfdsf 119223 sdfd.avi"));
            Assert.AreEqual("07", TVUtils.EpisodeNumberFromFile(@"c:\Flight.of.the.Conchords.S01E07.sfddsfsf2.avi"));
            Assert.AreEqual("08", TVUtils.EpisodeNumberFromFile(@"c:\Flight.of.the.Conchords.S01E08.dsfsdf.avi"));
            Assert.AreEqual("09", TVUtils.EpisodeNumberFromFile(@"c:\Flight.of.the.Conchords.S01E09.sdfsdfdff.avi"));
            Assert.AreEqual("10", TVUtils.EpisodeNumberFromFile(@"c:\Flight.of.the.Conchords.S01E10.sdfsdfs.avi"));
            Assert.AreEqual("11", TVUtils.EpisodeNumberFromFile(@"c:\Flight.of.the.Conchords.S01E11.sfdsdf.avi"));
            Assert.AreEqual("12", TVUtils.EpisodeNumberFromFile(@"c:\Flight.of.the.Conchords.S01E12.sdfsdf.avi"));

            // Test network share
            Assert.AreEqual("11", TVUtils.EpisodeNumberFromFile(@"\\10.0.0.4\videos\TV\Mister TV\Season 12\Mister.Tv.S12E11.NONSE.avi"));
        }
        public static bool IsSeriesFolder(this IMediaLocation location)
        {
            IFolderMediaLocation folder = location as IFolderMediaLocation;

            if (folder != null)
            {
                if (TVUtils.IsSeasonFolder(folder.Path))
                {
                    return(false);
                }

                int i = 0;

                foreach (IMediaLocation child in folder.Children)
                {
                    if (child is IFolderMediaLocation &&
                        TVUtils.IsSeasonFolder(child.Path))
                    {
                        return(true); // we have found at least one season folder
                    }
                    else
                    {
                        i++;
                    }
                    if (i >= 3)
                    {
                        return(false); // a folder with more than 3 non-season folders in will not be counted as a series
                    }
                }

                foreach (IMediaLocation child in folder.Children)
                {
                    if (!(child is IFolderMediaLocation) &&
                        child.IsVideo() &&
                        TVUtils.EpisodeNumberFromFile(child.Path, false) != null)
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
        /// <summary>
        /// Fetches the episode data.
        /// </summary>
        /// <param name="episode">The episode.</param>
        /// <param name="seriesId">The series id.</param>
        /// <returns>Task{System.Boolean}.</returns>
        private async Task <bool> FetchEpisodeData(Episode episode, string seriesId, CancellationToken cancellationToken)
        {
            string name     = episode.Name;
            string location = episode.Path;

            Logger.Debug("TvDbProvider: Fetching episode data for: " + name);
            string epNum = TVUtils.EpisodeNumberFromFile(location, episode.Season != null);

            if (epNum == null)
            {
                Logger.Warn("TvDbProvider: Could not determine episode number for: " + episode.Path);
                return(false);
            }

            var episodeNumber = Int32.Parse(epNum);

            episode.IndexNumber = episodeNumber;
            var usingAbsoluteData = false;

            if (string.IsNullOrEmpty(seriesId))
            {
                return(false);
            }

            var seasonNumber = "";

            if (episode.Parent is Season)
            {
                seasonNumber = episode.Parent.IndexNumber.ToString();
            }

            if (string.IsNullOrEmpty(seasonNumber))
            {
                seasonNumber = TVUtils.SeasonNumberFromEpisodeFile(location); // try and extract the season number from the file name for S1E1, 1x04 etc.
            }
            if (!string.IsNullOrEmpty(seasonNumber))
            {
                seasonNumber = seasonNumber.TrimStart('0');

                if (string.IsNullOrEmpty(seasonNumber))
                {
                    seasonNumber = "0"; // Specials
                }

                var url = string.Format(episodeQuery, TVUtils.TVDBApiKey, seriesId, seasonNumber, episodeNumber, ConfigurationManager.Configuration.PreferredMetadataLanguage);
                var doc = new XmlDocument();

                try
                {
                    using (var result = await HttpClient.Get(url, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false))
                    {
                        doc.Load(result);
                    }
                }
                catch (HttpException)
                {
                }

                //episode does not exist under this season, try absolute numbering.
                //still assuming it's numbered as 1x01
                //this is basicly just for anime.
                if (!doc.HasChildNodes && Int32.Parse(seasonNumber) == 1)
                {
                    url = string.Format(absEpisodeQuery, TVUtils.TVDBApiKey, seriesId, episodeNumber, ConfigurationManager.Configuration.PreferredMetadataLanguage);

                    try
                    {
                        using (var result = await HttpClient.Get(url, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false))
                        {
                            if (result != null)
                            {
                                doc.Load(result);
                            }
                            usingAbsoluteData = true;
                        }
                    }
                    catch (HttpException)
                    {
                    }
                }

                if (doc.HasChildNodes)
                {
                    var p = doc.SafeGetString("//filename");
                    if (p != null)
                    {
                        if (!Directory.Exists(episode.MetaLocation))
                        {
                            Directory.CreateDirectory(episode.MetaLocation);
                        }

                        try
                        {
                            episode.PrimaryImagePath = await _providerManager.DownloadAndSaveImage(episode, TVUtils.BannerUrl + p, Path.GetFileName(p), RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken);
                        }
                        catch (HttpException)
                        {
                        }
                        catch (IOException)
                        {
                        }
                    }

                    episode.Overview = doc.SafeGetString("//Overview");
                    if (usingAbsoluteData)
                    {
                        episode.IndexNumber = doc.SafeGetInt32("//absolute_number", -1);
                    }
                    if (episode.IndexNumber < 0)
                    {
                        episode.IndexNumber = doc.SafeGetInt32("//EpisodeNumber");
                    }

                    episode.Name            = episode.IndexNumber.Value.ToString("000") + " - " + doc.SafeGetString("//EpisodeName");
                    episode.CommunityRating = doc.SafeGetSingle("//Rating", -1, 10);
                    var      firstAired = doc.SafeGetString("//FirstAired");
                    DateTime airDate;
                    if (DateTime.TryParse(firstAired, out airDate) && airDate.Year > 1850)
                    {
                        episode.PremiereDate   = airDate.ToUniversalTime();
                        episode.ProductionYear = airDate.Year;
                    }

                    var actors = doc.SafeGetString("//GuestStars");
                    if (actors != null)
                    {
                        episode.AddPeople(actors.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries).Select(str => new PersonInfo {
                            Type = "Actor", Name = str
                        }));
                    }


                    var directors = doc.SafeGetString("//Director");
                    if (directors != null)
                    {
                        episode.AddPeople(directors.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries).Select(str => new PersonInfo {
                            Type = "Director", Name = str
                        }));
                    }


                    var writers = doc.SafeGetString("//Writer");
                    if (writers != null)
                    {
                        episode.AddPeople(writers.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries).Select(str => new PersonInfo {
                            Type = "Writer", Name = str
                        }));
                    }

                    if (ConfigurationManager.Configuration.SaveLocalMeta)
                    {
                        if (!Directory.Exists(episode.MetaLocation))
                        {
                            Directory.CreateDirectory(episode.MetaLocation);
                        }
                        var ms = new MemoryStream();
                        doc.Save(ms);

                        await _providerManager.SaveToLibraryFilesystem(episode, Path.Combine(episode.MetaLocation, Path.GetFileNameWithoutExtension(episode.Path) + ".xml"), ms, cancellationToken).ConfigureAwait(false);
                    }

                    return(true);
                }
            }

            return(false);
        }
 public void TestEpisodeNumberThatContainsSeasonNumber()
 {
     Assert.AreEqual("05", TVUtils.EpisodeNumberFromFile(@"c:\weeds\season 1\Weeds - 105 - 100 things happend.avi"));
 }