public static ArchivedAlbumContract GetAllProperties(ArchivedAlbumVersion version) { var data = new ArchivedAlbumContract(); var xmlCache = new XmlCache <ArchivedAlbumContract>(); var thisVersion = xmlCache.Deserialize(version.Version, version.Data); data.DiscType = thisVersion.DiscType; data.Id = thisVersion.Id; data.MainPictureMime = thisVersion.MainPictureMime; data.TranslatedName = thisVersion.TranslatedName; DoIfExists(version, AlbumEditableFields.Artists, xmlCache, (v, doc) => SetArtists(data, v, doc)); DoIfExists(version, AlbumEditableFields.Description, xmlCache, v => { data.Description = v.Description; data.DescriptionEng = v.DescriptionEng; }); DoIfExists(version, AlbumEditableFields.Identifiers, xmlCache, v => data.Identifiers = v.Identifiers); DoIfExists(version, AlbumEditableFields.OriginalRelease, xmlCache, v => data.OriginalRelease = v.OriginalRelease); DoIfExists(version, AlbumEditableFields.Names, xmlCache, v => data.Names = v.Names); DoIfExists(version, AlbumEditableFields.Pictures, xmlCache, v => data.Pictures = v.Pictures); DoIfExists(version, AlbumEditableFields.PVs, xmlCache, v => data.PVs = v.PVs); DoIfExists(version, AlbumEditableFields.Tracks, xmlCache, v => data.Songs = v.Songs); DoIfExists(version, AlbumEditableFields.WebLinks, xmlCache, v => data.WebLinks = v.WebLinks); return(data); }
public static ArchivedEventContract GetAllProperties(ArchivedReleaseEventVersion version) { var data = new ArchivedEventContract(); var xmlCache = new XmlCache <ArchivedEventContract>(); var thisVersion = version.Data != null?xmlCache.Deserialize(version.Version, version.Data) : new ArchivedEventContract(); data.Category = thisVersion.Category; data.Date = thisVersion.Date; data.Description = thisVersion.Description; data.Id = thisVersion.Id; data.MainPictureMime = thisVersion.MainPictureMime; data.Series = thisVersion.Series; data.SeriesNumber = thisVersion.SeriesNumber; data.SongList = thisVersion.SongList; data.TranslatedName = thisVersion.TranslatedName; data.Venue = thisVersion.Venue; data.VenueName = thisVersion.VenueName; DoIfExists(version, ReleaseEventEditableFields.Artists, xmlCache, v => data.Artists = v.Artists); DoIfExists(version, ReleaseEventEditableFields.Names, xmlCache, v => data.Names = v.Names); DoIfExists(version, ReleaseEventEditableFields.PVs, xmlCache, v => data.PVs = v.PVs); DoIfExists(version, ReleaseEventEditableFields.WebLinks, xmlCache, v => data.WebLinks = v.WebLinks); return(data); }
public static ArchivedArtistContract GetAllProperties(ArchivedArtistVersion version) { var data = new ArchivedArtistContract(); var xmlCache = new XmlCache <ArchivedArtistContract>(); var thisVersion = xmlCache.Deserialize(version.Version, version.Data); data.ArtistType = thisVersion.ArtistType; data.BaseVoicebank = thisVersion.BaseVoicebank; data.Groups = thisVersion.Groups; data.Id = thisVersion.Id; data.MainPictureMime = thisVersion.MainPictureMime; data.Members = thisVersion.Members; data.ReleaseDate = thisVersion.ReleaseDate; data.TranslatedName = thisVersion.TranslatedName; DoIfExists(version, ArtistEditableFields.Description, xmlCache, v => { data.Description = v.Description; data.DescriptionEng = v.DescriptionEng; }); DoIfExists(version, ArtistEditableFields.Names, xmlCache, v => data.Names = v.Names); DoIfExists(version, ArtistEditableFields.Pictures, xmlCache, v => data.Pictures = v.Pictures); DoIfExists(version, ArtistEditableFields.WebLinks, xmlCache, v => data.WebLinks = v.WebLinks); return(data); }
public static ArchivedSongContract GetAllProperties(ArchivedSongVersion version) { var data = new ArchivedSongContract(); var xmlCache = new XmlCache <ArchivedSongContract>(); var thisVersion = xmlCache.Deserialize(version.Version, version.Data); data.Id = thisVersion.Id; data.LengthSeconds = thisVersion.LengthSeconds; data.NicoId = thisVersion.NicoId; data.Notes = thisVersion.Notes; data.NotesEng = thisVersion.NotesEng; data.OriginalVersion = thisVersion.OriginalVersion; data.PublishDate = thisVersion.PublishDate; data.ReleaseEvent = thisVersion.ReleaseEvent; data.SongType = thisVersion.SongType; data.TranslatedName = thisVersion.TranslatedName; DoIfExists(version, SongEditableFields.Albums, xmlCache, v => data.Albums = v.Albums); DoIfExists(version, SongEditableFields.Artists, xmlCache, (v, doc) => SetArtists(data, v, doc)); DoIfExists(version, SongEditableFields.Lyrics, xmlCache, v => data.Lyrics = v.Lyrics); DoIfExists(version, SongEditableFields.Names, xmlCache, v => data.Names = v.Names); DoIfExists(version, SongEditableFields.PVs, xmlCache, v => data.PVs = v.PVs); DoIfExists(version, SongEditableFields.WebLinks, xmlCache, v => data.WebLinks = v.WebLinks); return(data); }
private static void DoIfExists(ArchivedAlbumVersion version, AlbumEditableFields field, XmlCache<ArchivedAlbumContract> xmlCache, Action<ArchivedAlbumContract, XDocument> func) { var versionWithField = version.GetLatestVersionWithField(field); if (versionWithField != null && versionWithField.Data != null) { var data = xmlCache.Deserialize(versionWithField.Version, versionWithField.Data); func(data, versionWithField.Data); } }
public void CachesOnRead() { var reads = 0; var cache = new XmlCache(); cache.Content("test", () => { reads++; return(new XDocument(new XElement("splashy"))); }); cache.Content("test", () => { reads++; return(new XDocument(new XElement("splashy"))); }); Assert.Equal(1, reads); }
private static void DoIfExists(ArchivedTagVersion version, TagEditableFields field, XmlCache <ArchivedTagContract> xmlCache, Action <ArchivedTagContract> func) { var versionWithField = version.GetLatestVersionWithField(field); if (versionWithField?.Data != null) { var data = xmlCache.Deserialize(versionWithField.Version, versionWithField.Data); func(data); } }
public void Removes() { var reads = 0; var cache = new XmlCache(); cache.Content("test", () => { reads++; return(new XDocument(new XElement("splashy"))); }); cache.Remove("test"); cache.Content("test", () => { reads++; return(new XDocument(new XElement("splashy"))); }); Assert.Equal(2, reads); }
private XmlDocument LoadXml() { var xml = new XmlDocument(); try { var filePath = Path.Combine(ConfigFilePath, BuiltInUserConfigFile); var xmlCache = new XmlCache(filePath); xml = xmlCache.Read(); } catch (Exception ex) { Utility.ErrorLog(ex.Message, ex); } return(xml); }
public void IsThreadSafe() { var reads = 0; var cache = new XmlCache(); Parallel.For(0, 64, (idx) => { cache.Content("test", () => new XDocument(new XElement("splashy"))); cache.Update("test", () => { reads++; return(new XDocument(new XElement("splashy"))); }, () => { reads++; return(new XDocument(new XElement("splashy"))); } ); cache.Content("test", () => { reads++; return(new XDocument(new XElement("splashy"))); }); }); Assert.Equal(64, reads); }
public static ArchivedVenueContract GetAllProperties(ArchivedVenueVersion version) { var data = new ArchivedVenueContract(); var xmlCache = new XmlCache <ArchivedVenueContract>(); var thisVersion = version.Data != null?xmlCache.Deserialize(version.Version, version.Data) : new ArchivedVenueContract(); data.Address = thisVersion.Address; data.AddressCountryCode = thisVersion.AddressCountryCode; data.Coordinates = thisVersion.Coordinates; data.Description = thisVersion.Description; data.Id = thisVersion.Id; data.TranslatedName = thisVersion.TranslatedName; DoIfExists(version, VenueEditableFields.Names, xmlCache, v => data.Names = v.Names); DoIfExists(version, VenueEditableFields.WebLinks, xmlCache, v => data.WebLinks = v.WebLinks); return(data); }
public static ArchivedTagContract GetAllProperties(ArchivedTagVersion version) { var data = new ArchivedTagContract(); var xmlCache = new XmlCache <ArchivedTagContract>(); var thisVersion = version.Data != null?xmlCache.Deserialize(version.Version, version.Data) : new ArchivedTagContract(); data.CategoryName = thisVersion.CategoryName; data.HideFromSuggestions = thisVersion.HideFromSuggestions; data.Id = thisVersion.Id; data.TranslatedName = thisVersion.TranslatedName; DoIfExists(version, TagEditableFields.Description, xmlCache, v => { data.Description = v.Description; data.DescriptionEng = v.DescriptionEng; }); DoIfExists(version, TagEditableFields.Names, xmlCache, v => data.Names = v.Names); DoIfExists(version, TagEditableFields.Parent, xmlCache, v => data.Parent = v.Parent); DoIfExists(version, TagEditableFields.RelatedTags, xmlCache, v => data.RelatedTags = v.RelatedTags); DoIfExists(version, TagEditableFields.WebLinks, xmlCache, v => data.WebLinks = v.WebLinks); return(data); }
public static ArchivedSongContract GetAllProperties(ArchivedSongVersion version) { var data = new ArchivedSongContract(); var xmlCache = new XmlCache<ArchivedSongContract>(); var thisVersion = xmlCache.Deserialize(version.Version, version.Data); data.Id = thisVersion.Id; data.LengthSeconds = thisVersion.LengthSeconds; data.NicoId = thisVersion.NicoId; data.Notes = thisVersion.Notes; data.OriginalVersion = thisVersion.OriginalVersion; data.SongType = thisVersion.SongType; data.TranslatedName = thisVersion.TranslatedName; DoIfExists(version, SongEditableFields.Artists, xmlCache, (v, doc) => SetArtists(data, v, doc)); DoIfExists(version, SongEditableFields.Lyrics, xmlCache, v => data.Lyrics = v.Lyrics); DoIfExists(version, SongEditableFields.Names, xmlCache, v => data.Names = v.Names); DoIfExists(version, SongEditableFields.PVs, xmlCache, v => data.PVs = v.PVs); DoIfExists(version, SongEditableFields.WebLinks, xmlCache, v => data.WebLinks = v.WebLinks); return data; }
public static ArchivedArtistContract GetAllProperties(ArchivedArtistVersion version) { var data = new ArchivedArtistContract(); var xmlCache = new XmlCache<ArchivedArtistContract>(); var thisVersion = xmlCache.Deserialize(version.Version, version.Data); data.ArtistType = thisVersion.ArtistType; data.BaseVoicebank = thisVersion.BaseVoicebank; data.Groups = thisVersion.Groups; data.Id = thisVersion.Id; data.MainPictureMime = thisVersion.MainPictureMime; data.Members = thisVersion.Members; data.TranslatedName = thisVersion.TranslatedName; DoIfExists(version, ArtistEditableFields.Albums, xmlCache, v => data.Albums = v.Albums); DoIfExists(version, ArtistEditableFields.Description, xmlCache, v => data.Description = v.Description); DoIfExists(version, ArtistEditableFields.Names, xmlCache, v => data.Names = v.Names); DoIfExists(version, ArtistEditableFields.Pictures, xmlCache, v => data.Pictures = v.Pictures); DoIfExists(version, ArtistEditableFields.WebLinks, xmlCache, v => data.WebLinks = v.WebLinks); return data; }
public static ArchivedAlbumContract GetAllProperties(ArchivedAlbumVersion version) { var data = new ArchivedAlbumContract(); var xmlCache = new XmlCache<ArchivedAlbumContract>(); var thisVersion = xmlCache.Deserialize(version.Version, version.Data); data.DiscType = thisVersion.DiscType; data.Id = thisVersion.Id; data.MainPictureMime = thisVersion.MainPictureMime; data.TranslatedName = thisVersion.TranslatedName; DoIfExists(version, AlbumEditableFields.Artists, xmlCache, (v, doc) => SetArtists(data, v, doc)); DoIfExists(version, AlbumEditableFields.Description, xmlCache, v => data.Description = v.Description); DoIfExists(version, AlbumEditableFields.Identifiers, xmlCache, v => data.Identifiers = v.Identifiers); DoIfExists(version, AlbumEditableFields.OriginalRelease, xmlCache, v => data.OriginalRelease = v.OriginalRelease); DoIfExists(version, AlbumEditableFields.Names, xmlCache, v => data.Names = v.Names); DoIfExists(version, AlbumEditableFields.Pictures, xmlCache, v => data.Pictures = v.Pictures); DoIfExists(version, AlbumEditableFields.PVs, xmlCache, v => data.PVs = v.PVs); DoIfExists(version, AlbumEditableFields.Tracks, xmlCache, v => data.Songs = v.Songs); DoIfExists(version, AlbumEditableFields.WebLinks, xmlCache, v => data.WebLinks = v.WebLinks); return data; }
private static void DoIfExists(ArchivedAlbumVersion version, AlbumEditableFields field, XmlCache <ArchivedAlbumContract> xmlCache, Action <ArchivedAlbumContract, XDocument> func) { var versionWithField = version.GetLatestVersionWithField(field); if (versionWithField != null && versionWithField.Data != null) { var data = xmlCache.Deserialize(versionWithField.Version, versionWithField.Data); func(data, versionWithField.Data); } }
public override void Uninstall(IDictionary savedState) { base.Uninstall(savedState); XmlCache.RemoveCache(); }
public IEnumerable<AtomEntry> GetEntries(EntryCriteria criteria, int pageIndex, int pageSize, out int totalRecords) { string[] paths = criteria.EntryId != null ? pathResolver.GetEntryFilePaths(criteria.EntryId, criteria.Annotations, criteria.Deep) : pathResolver.GetEntryFilePaths(criteria.WorkspaceName, criteria.CollectionName, criteria.Annotations, criteria.Deep); Func<AtomEntry, bool> where = (entry) => whereAuth(entry, criteria) && (criteria.StartDate.HasValue && criteria.EndDate.HasValue ? whereDate(entry, criteria) : true) && (criteria.CategoryTerm != null ? whereCategory(entry, criteria) : true) && (criteria.PersonName != null ? wherePerson(entry, criteria) : true) && (criteria.SearchTerm != null ? whereSearch(entry, criteria) : true) && (criteria.Approved != null ? whereApproved(entry, criteria) : true) && (criteria.Draft != null ? whereDraft(entry, criteria) : true) && (criteria.Pending != null ? wherePending(entry, criteria) : true) && (criteria.Published != null ? wherePublished(entry, criteria) : true) && (criteria.Spam != null ? whereSpam(entry, criteria) : true); IEnumerable<AtomEntry> entries = GetEntries(paths, where); totalRecords = entries.Count(); if (criteria.SortMethod == SortMethod.EditDesc) entries = entries.OrderByDescending(e => e.Edited); else if (criteria.SortMethod == SortMethod.DateAsc) entries = entries.OrderBy(e => e.Date); else if (criteria.SortMethod == SortMethod.DateDesc) entries = entries.OrderByDescending(e => e.Date); else if (criteria.SortMethod == SortMethod.Default && criteria.Annotations) entries = entries.OrderBy(e => e.Date); else if (criteria.SortMethod == SortMethod.Default && criteria.SearchTerm != null) entries = entries.OrderByDescending(e => Regex.Matches(e.Xml.Value, criteria.SearchTerm, RegexOptions.IgnoreCase).Count); return entries.Skip(pageIndex * pageSize).Take(pageSize); }
static void Main(string[] args) { // deal with command line arguments if (args.Length > 0) { // use dvd order if (args.Contains("/dvd")) { _forceDvdOrder = true; } } ConsoleLogger.Log("Launching scraper"); CheckForNewVersion(); ConsoleLogger.LogStart("Initialising cache..."); XmlCache localCache = new XmlCache(); ConsoleLogger.LogEnd("done."); ConsoleLogger.LogStart("Gathering settings from TV Rename..."); _tvRenameSettings = new TVRenameSettings(CustomConfiguration.TVRenamePath); ConsoleLogger.LogEnd("done."); ConsoleLogger.LogStart("Searching for TV shows..."); // find all the shows and their info IEnumerable <TVRenameShow> shows = GetAllTVShowsFromTVRename(_tvRenameSettings, _forceDvdOrder); ConsoleLogger.LogEnd("done."); // loop through each show); foreach (var tvRenameShow in shows) { if (Directory.Exists(tvRenameShow.FolderPath)) { SeriesInfo seriesInfo = null; // attempt to get series name from cache string seriesTitle = localCache.GetShowTitle(tvRenameShow.TvdbId); if (string.IsNullOrWhiteSpace(seriesTitle)) { seriesInfo = TheTvdb.GetSeriesInfo(tvRenameShow.TvdbId); localCache.AddShowTitle(tvRenameShow.TvdbId, seriesInfo.Title); seriesTitle = seriesInfo.Title; } ConsoleLogger.Highlight(seriesTitle); bool needFanartJpg; bool needFolderJpg; bool needAllSeasonTbn; bool needShowNfo; DirectoryInfo showFolder = new DirectoryInfo(tvRenameShow.FolderPath); IEnumerable <FileInfo> rootFileNames = showFolder.GetFiles(); needFanartJpg = (from p in rootFileNames where p.Name == FANART_FILE_NAME select p).Count() == 0; needFolderJpg = (from p in rootFileNames where p.Name == FOLDER_FILE_NAME select p).Count() == 0; needAllSeasonTbn = (from p in rootFileNames where p.Name == ALL_SEASON_FILE_NAME select p).Count() == 0; needShowNfo = (from p in rootFileNames where p.Name == SHOW_INFO_FILE_NAME select p).Count() == 0; // check if we need to get series info if ((needShowNfo || needFolderJpg || needFanartJpg || needAllSeasonTbn) && seriesInfo == null) { seriesInfo = TheTvdb.GetSeriesInfo(tvRenameShow.TvdbId); } if (needShowNfo) { ConsoleLogger.Log("Show Info needed for '" + seriesInfo.Title + "'."); Xbmc.ShowInfoHandler.CreateNfoFile(seriesInfo, tvRenameShow.FolderPath, SHOW_INFO_FILE_NAME, tvRenameShow); } if (needFanartJpg) { ConsoleLogger.Log("Fanart needed for '" + seriesInfo.Title + "'."); Xbmc.ShowInfoHandler.CreateFanart(seriesInfo, tvRenameShow.FolderPath, FANART_FILE_NAME); } if (needFolderJpg) { ConsoleLogger.Log("Folder art needed for '" + seriesInfo.Title + "'."); Xbmc.ShowInfoHandler.CreateFolderArt(seriesInfo, tvRenameShow.FolderPath, FOLDER_FILE_NAME); } if (needAllSeasonTbn) { ConsoleLogger.Log("All season thumbnail needed for '" + seriesInfo.Title + "'."); Xbmc.ShowInfoHandler.CreateFolderArt(seriesInfo, tvRenameShow.FolderPath, ALL_SEASON_FILE_NAME); } // process each season if (tvRenameShow.UseFolderPerSeason) { var seasonDirectories = showFolder.GetDirectories(tvRenameShow.SeasonFolderName + "*").ToList(); // add specials folder if set in TV Rename if (!string.IsNullOrEmpty(_tvRenameSettings.SpecialsFolderName)) { seasonDirectories = seasonDirectories.Concat(showFolder.GetDirectories(_tvRenameSettings.SpecialsFolderName)) .ToList(); } foreach (var seasonDirectory in seasonDirectories) { // get the season number and test if the thumbnail exists int seasonNumber = seasonDirectory.Name.Equals(_tvRenameSettings.SpecialsFolderName) ? 0 : int.Parse(seasonDirectory.Name.Replace(tvRenameShow.SeasonFolderName, string.Empty)); // look for season thumbnail or folder.jpg for the season string seasonThumbFileName = GetSeasonThumbnailName(seasonNumber); string seasonFolderJpgFileName = seasonDirectory.FullName + "\\" + FOLDER_FILE_NAME; FileInfo seasonThumb = new FileInfo(showFolder + "\\" + seasonThumbFileName); FileInfo seasonFolderJpg = new FileInfo(seasonFolderJpgFileName); if (!seasonThumb.Exists || (CustomConfiguration.GetFolderJpgForSeasons && !seasonFolderJpg.Exists)) { if (seriesInfo == null) { seriesInfo = TheTvdb.GetSeriesInfo(tvRenameShow.TvdbId); } // download the missing season thumbnail or folder.jpg for the season ConsoleLogger.LogStart("Season thumbnail and/or folder.jpg needed for '" + seriesInfo.Title + "', season '" + seasonNumber + "'..."); BannerInfo bestMatchBanner = TheTvdb.GetSeasonBanner(seasonNumber, seriesInfo); if (bestMatchBanner != null) { if (!seasonThumb.Exists) { Xbmc.SeasonInfoHandler.CreateThumbnailArt(bestMatchBanner, tvRenameShow.FolderPath, seasonThumbFileName); } if (CustomConfiguration.GetFolderJpgForSeasons && !seasonFolderJpg.Exists) { Xbmc.SeasonInfoHandler.CreateThumbnailArt(bestMatchBanner, seasonDirectory.FullName, FOLDER_FILE_NAME); } ConsoleLogger.LogEnd("downloaded."); } else { ConsoleLogger.Warning("not found!"); } } // check episodes within this season FileInfo[] seasonDirectoryFiles = seasonDirectory.GetFiles(); foreach (var seasonDirectoryFile in seasonDirectoryFiles) { if (_tvRenameSettings.VideoExtensions.Contains(seasonDirectoryFile.Extension)) { // need to find SxxExx and extract the numbers Regex regex = new Regex("S(\\d\\d)E(\\d\\d)", RegexOptions.IgnoreCase); if (regex.IsMatch(seasonDirectoryFile.Name)) { int season = int.Parse(regex.Match(seasonDirectoryFile.Name).Groups[1].Value); int episode = int.Parse(regex.Match(seasonDirectoryFile.Name).Groups[2].Value); // check if .nfo exist string episodeInfoFileName = seasonDirectoryFile.Name.Replace(seasonDirectoryFile.Extension, ".nfo"); FileInfo episodeFileInfo = new FileInfo(seasonDirectory.FullName + "\\" + episodeInfoFileName); string episodeThumbFileName = seasonDirectoryFile.Name.Replace(seasonDirectoryFile.Extension, ".tbn"); FileInfo episodeThumbFileInfo = new FileInfo(seasonDirectory.FullName + "\\" + episodeThumbFileName); // check if the nfo file is a valid xbmc file, and delete // it if it is not Xbmc.EpisodeInfoHandler.CheckInfoIsValid(ref episodeFileInfo, season, episode); if (!episodeThumbFileInfo.Exists || !episodeFileInfo.Exists) { if (seriesInfo == null) { seriesInfo = TheTvdb.GetSeriesInfo(tvRenameShow.TvdbId); } EpisodeInfo episodeInfo = seriesInfo.GetEpisodeInfo(season, episode, tvRenameShow. UseDvdOrder); if (episodeInfo != null) { if (!episodeFileInfo.Exists) { ConsoleLogger.Log("Episode info missing: Season '" + season + "', Episode '" + episode + "'"); Xbmc.EpisodeInfoHandler.CreateNfoFile(seriesInfo, episodeInfo, seasonDirectory.FullName, episodeInfoFileName, tvRenameShow); } if (!episodeThumbFileInfo.Exists) { ConsoleLogger.Log("Episode thumbnail missing: Season '" + season + "', Episode '" + episode + "'"); Xbmc.EpisodeInfoHandler.CreateThumbnail(episodeInfo, seasonDirectory.FullName, episodeThumbFileName); } } else { ConsoleLogger.Warning(string.Format("Could not find any information for season '{0}', episode '{1}'.", season, episode)); } } } } } } } else { // TODO how does this work? (not using folder per season) ConsoleLogger.Error(string.Format("The show is not configured to use 'folder per season'. TV show (ID: '{0}' Path:'{1}')", tvRenameShow.TvdbId, tvRenameShow.FolderPath)); } } else { ConsoleLogger.Error(string.Format("Could not find file path for TV show (ID: '{0}' Path:'{1}')", tvRenameShow.TvdbId, tvRenameShow.FolderPath)); } // pause after each series Thread.Sleep(CustomConfiguration.PostSeriesDelay); } // persist the cache ConsoleLogger.LogStart("Saving cache..."); localCache.SaveCache(); ConsoleLogger.LogEnd("done."); // give time to look at console ConsoleLogger.Log("Closing..."); Thread.Sleep(CustomConfiguration.PostCompletionDelay); // for each show // look in the base folder // assets should be in the base // fanart.jpg // folder.jpg // season-all.tbn // tvshow.nfo // use the folders to get a list of the seasons // checkd base folder for // season01.tbn // then within each folder: // episode with video extension // same but with tbn extension // same but with nfo extension }