Exemple #1
0
 /// <summary>
 /// Compares 2 content instances based on their Name property.
 /// </summary>
 /// <param name="x">The first movie.</param>
 /// <param name="y">The second movie.</param>
 /// <returns>The comparison results </returns>
 public static int CompareByAirDate(TvEpisode x, TvEpisode y)
 {
     if (x == null)
     {
         if (y == null)
         {
             return(0);
         }
         else
         {
             return(-1);
         }
     }
     else
     {
         if (y == null)
         {
             return(1);
         }
         else
         {
             return(x.DisplayAirDate.CompareTo(y.DisplayAirDate));
         }
     }
 }
 public EpisodeEditorWindow(TvEpisode episode)
 {
     InitializeComponent();
     viewModel = new EpisodeEditorWindowViewModel(episode);
     viewModel.ResultsSet += vm_ResultsSet;
     this.DataContext = viewModel;
 }
        /// <summary>
        /// Gets season/episode information from database.
        /// </summary>
        /// <param name="show">Show to load episode information into</param>
        public void FullUpdate(TvShow show)
        {
            // Check for invalid ID
            if (show.Id <= 0)
            {
                return;
            }

            // Try multiple times - databases requests tend to fail randomly
            for (int i = 0; i < 5; i++)
            {
                if (Update(show))
                {
                    // Remove episodes that are no longer in the TvDb
                    for (int k = show.Episodes.Count - 1; k >= 0; k--)
                    {
                        TvEpisode ep = show.Episodes[k];
                        if (!ep.InDatabase && !ep.UserDefined && !ep.PreventDatabaseUpdates)
                        {
                            show.Episodes.Remove(ep);
                        }
                    }

                    // Update missing episodes for show
                    show.UpdateMissing();
                    show.LastUpdated = DateTime.Now;
                    break;
                }
            }
        }
Exemple #4
0
        public override List <TvEpisodeTorrent> GetAvailableTvTorrents(TvEpisode episode)
        {
            // Download show episodes page
            string showPageUrl = BASE_URL + "/search/" + episode.BuildEpString().Replace(" ", "%20");

            Limiter.DoWait();

            WebClient client = new WebClient();

            client.Headers.Add("User-Agent: Other");
            string data = client.DownloadString(showPageUrl);

            Regex           baseRegex = new Regex("<div\\s+class=\\\"detName\\\">\\s+<a\\s+href=\\\"[^\\\"]+\\\"[^>]+>([^>]+)</a>\\s+</div>\\s+<a href=\\\"(magnet:[^\\\"]+)\\\"");
            MatchCollection matches   = baseRegex.Matches(data);

            List <TvEpisodeTorrent> torrents = new List <TvEpisodeTorrent>();

            foreach (Match match in matches)
            {
                string name   = match.Groups[1].Value;
                string magnet = match.Groups[2].Value;

                MatchCollection showMatches = episode.Show.MatchFileToContent(name);
                bool            matchShow   = showMatches != null && showMatches.Count > 0;

                int season, ep1, ep2;
                if (matchShow && FileHelper.GetEpisodeInfo(name, episode.Show.DisplayName, out season, out ep1, out ep2, true) && episode.Season == season && episode.DisplayNumber == ep1)
                {
                    // Don't want to get torrent with a bunch of episodes (double is okay)
                    if (ep2 > 0 && ep2 - ep1 > 1)
                    {
                        continue;
                    }

                    TorrentQuality quality = TorrentQuality.Sd480p;
                    if (name.ToLower().Contains("720p"))
                    {
                        quality = TorrentQuality.Hd720p;
                    }
                    else if (name.ToLower().Contains("1080p"))
                    {
                        quality = TorrentQuality.Hd1080p;
                    }

                    TvEpisodeTorrent torrentEp = new TvEpisodeTorrent();
                    torrentEp.Url      = showPageUrl;
                    torrentEp.Season   = season;
                    torrentEp.Episode  = ep1;
                    torrentEp.Episode2 = ep2;
                    torrentEp.Quality  = quality;
                    torrentEp.Title    = name;
                    torrentEp.Magnet   = magnet;

                    torrents.Add(torrentEp);
                }
            }

            return(torrents);
        }
        public TvEpisodeTorrent GetBestTvTorrent(TvEpisode episode)
        {
            List<TvEpisodeTorrent> availableTorrents = GetAvailableTvTorrents(episode);
            if (availableTorrents.Count == 0)
                return null;

            Dictionary<TorrentQuality, TvEpisodeTorrent> qualityTorrents = new Dictionary<TorrentQuality, TvEpisodeTorrent>();
            foreach (TvEpisodeTorrent torrent in availableTorrents)
            {
                TorrentQuality quality = torrent.Quality;

                if (!qualityTorrents.ContainsKey(quality))
                    qualityTorrents.Add(quality, null);

                if (qualityTorrents[quality] == null)
                    qualityTorrents[quality] = torrent;
            }

            // Go through matches to find closest quality to preferred
            TorrentQuality closestQuality = TorrentQuality.Sd480p;
            if (qualityTorrents.ContainsKey(Settings.General.PreferredTorrentQuality))
                closestQuality = Settings.General.PreferredTorrentQuality;
            else
            {
                switch (Settings.General.PreferredTorrentQuality)
                {
                    case TorrentQuality.Sd480p:
                        if (qualityTorrents.ContainsKey(TorrentQuality.Hd720p))
                            closestQuality = TorrentQuality.Hd720p;
                        else
                            closestQuality = TorrentQuality.Hd1080p;
                        break;
                    case TorrentQuality.Hd720p:
                        if (qualityTorrents.ContainsKey(TorrentQuality.Sd480p))
                            closestQuality = TorrentQuality.Sd480p;
                        else
                            closestQuality = TorrentQuality.Hd1080p;
                        break;
                    case TorrentQuality.Hd1080p:
                        if (qualityTorrents.ContainsKey(TorrentQuality.Hd720p))
                            closestQuality = TorrentQuality.Hd720p;
                        else
                            closestQuality = TorrentQuality.Sd480p;
                        break;
                    default:
                        throw new Exception("Unknown torrent quality");
                }
            }

            TvEpisodeTorrent closestTorrent = qualityTorrents[closestQuality];
            UpdateTorrentLinks(closestTorrent);

            return closestTorrent;
        }
        /// <summary>
        /// Builds episode string for TV episode for both single or multi-episode files.
        /// </summary>
        /// <param name="ep1">First episode</param>
        /// <param name="ep2">Second episode (if double episode file)</param>
        /// <returns>Resulting episode string</returns>
        public string BuildEpisodeString(TvEpisode ep1, TvEpisode ep2)
        {
            // Start out with formatting string
            string epStr = string.Empty;

            // Build episode string
            for (int i = 0; i < 2; i++)
            {
                bool season = (i == 0 && this.SeasonFirst) || (i == 1 && !this.SeasonFirst);

                if (season)
                {
                    if (this.ForceSeasonDoubleDigits)
                    {
                        epStr += this.SeasonHeader + ep1.Season.ToString("00");
                    }
                    else
                    {
                        epStr += this.SeasonHeader + ep1.Season.ToString();
                    }
                }
                else
                {
                    if (this.ForceEpisodeDoubleDigits)
                    {
                        epStr += this.EpisodeHeader + ep1.DisplayNumber.ToString("00");
                    }
                    else
                    {
                        epStr += this.EpisodeHeader + ep1.DisplayNumber.ToString();
                    }

                    if (ep2 != null && ep2.DisplayNumber > 0)
                    {
                        if (this.HeaderPerEpisode)
                        {
                            epStr += this.EpisodeHeader;
                        }

                        if (this.ForceEpisodeDoubleDigits)
                        {
                            epStr += ep2.DisplayNumber.ToString("00");
                        }
                        else
                        {
                            epStr += ep2.DisplayNumber.ToString();
                        }
                    }
                }
            }

            // Return file name
            return(epStr);
        }
Exemple #7
0
 public static TvEpisodeTorrent GetEpisodeTorrent(TvEpisode episode)
 {
     try
     {
         PirateBayTorrentSite site    = new PirateBayTorrentSite();
         TvEpisodeTorrent     torrent = site.GetBestTvTorrent(episode);
         return(torrent);
     }
     catch
     {
         return(null);
     }
 }
Exemple #8
0
        /// <summary>
        /// Equals check for this episode and another episode
        /// </summary>
        /// <param name="obj">Episode to compare to</param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            // False for null/invalid objects
            if (obj == null || !(obj is TvEpisode))
            {
                return(false);
            }

            // Case object to episode
            TvEpisode ep = (TvEpisode)obj;

            // Compare is on season and episode number only (show name may not be set yet)
            return(ep.Season == this.Season && ep.DisplayNumber == this.DisplayNumber && ep.DisplayName == this.DisplayName);
        }
Exemple #9
0
        /// <summary>
        /// Builds formatted file name for TV episode file from an existing file path.
        /// </summary>
        /// <param name="episode1">First episode in file</param>
        /// <param name="episode2">Second episode in file</param>
        /// <param name="fullPath">Path of file to be formatted</param>
        /// <returns>Path with file name formatted</returns>
        public string BuildTvFileName(TvEpisode episode1, TvEpisode episode2, string fullPath)
        {
            // Get file name
            string fileName = Path.GetFileNameWithoutExtension(fullPath);

            // Get info from file using simplify function (pulls out file words and categorizes them)
            FileHelper.OptionalSimplifyRemoves simplifyOptions = FileHelper.OptionalSimplifyRemoves.Year;
            FileHelper.SimplifyStringResults   simplifyResults = FileHelper.BuildSimplifyResults(fileName, false, false, simplifyOptions, true, false, false, false);

            // Build file name
            string buildName = BuildFileName(episode1, episode2, simplifyResults);

            // Remove unsafe file characters and add extension
            return(FileHelper.GetSafeFileName(buildName));
        }
Exemple #10
0
        /// <summary>
        /// Recursive search a directory and mark missing episodes.
        /// </summary>
        /// <param name="directory">Path of directory to check for episode files</param>
        private void UpdateMissingRecursive(string directory)
        {
            string[] files = Directory.GetFiles(directory);
            foreach (string file in files)
            {
                int season, episode1, episode2;
                if (FileHelper.GetEpisodeInfo(file, this.DatabaseName, out season, out episode1, out episode2))
                {
                    // Mark episodes as not missing
                    TvEpisode ep1 = null, ep2 = null;
                    bool      matched1 = FindEpisode(season, episode1, false, out ep1);
                    bool      matched2 = episode2 != -1 && FindEpisode(season, episode2, false, out ep2);

                    if (matched1)
                    {
                        ep1.Missing = MissingStatus.Located;
                    }
                    if (matched2)
                    {
                        ep2.Missing = MissingStatus.Located;
                    }

                    // Update file info
                    if (matched1 && matched2)
                    {
                        ep1.File = new TvFile(file, 1);
                        ep2.File = new TvFile(file, 2);
                    }
                    else if (matched1)
                    {
                        ep1.File = new TvFile(file);
                    }
                }
            }

            // Recursively check subdirectories
            string[] subDirs = Directory.GetDirectories(directory);
            foreach (string subDir in subDirs)
            {
                UpdateMissingRecursive(subDir);
            }
        }
Exemple #11
0
        /// <summary>
        /// Compare method for sorting epsiodes, uses airdate.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public int CompareTo(object obj)
        {
            if (obj is TvEpisode)
            {
                TvEpisode t2 = (TvEpisode)obj;

                if (this.Season == t2.Season && this.DisplayNumber == t2.DisplayNumber)
                {
                    return(this.DisplayName.CompareTo(t2.DisplayName));
                }
                else
                {
                    return((this.Season * 1000 + this.DisplayNumber).CompareTo(t2.Season * 1000 + t2.DisplayNumber));
                }
            }
            else
            {
                throw new ArgumentException("Object is not a TvShow.");
            }
        }
Exemple #12
0
        /// <summary>
        /// Copies properties from another instance into this instance.
        /// </summary>
        /// <param name="content">Instance to copy properties from</param>
        /// <param name="replacePath">Whether path related properties should be cloned or not</param>
        /// <param name="handleEmptyPath">Whether to build path if one being cloned is empty</param>
        public override void CloneAndHandlePath(Content content, bool replacePath, bool handleEmptyPath = true)
        {
            if (!(content is TvShow))
            {
                throw new Exception("Content must be TvShow");
            }
            TvShow show = content as TvShow;

            bool updateRequired = show.Id != this.Id;

            base.CloneAndHandlePath(show, replacePath, handleEmptyPath);

            this.IncludeInSchedule = show.IncludeInSchedule;
            this.DoMissingCheck    = show.DoMissingCheck;
            this.DvdEpisodeOrder   = show.DvdEpisodeOrder;

            if (updateRequired)
            {
                this.UpdateInfoFromDatabase();
            }

            // TODO: this is a hack
            App.Current.Dispatcher.BeginInvoke((Action) delegate
            {
                this.Episodes.Clear();
                foreach (TvEpisode episode in show.Episodes)
                {
                    TvEpisode copyEp = new TvEpisode(episode);
                    this.Episodes.Add(copyEp);
                    copyEp.Show = this;
                }
            });
            this.AlternativeNameMatches = new ObservableCollection <string>();
            foreach (string altName in show.AlternativeNameMatches)
            {
                this.AlternativeNameMatches.Add(altName);
            }
        }
Exemple #13
0
 /// <summary>
 /// Updates this instance with information from another instance
 /// </summary>
 /// <param name="episode"></param>
 public void Clone(TvEpisode episode)
 {
     this.UseDatabaseName        = episode.UseDatabaseName;
     this.UserName               = episode.UserName;
     this.DatabaseName           = episode.DatabaseName;
     this.Show                   = episode.Show;
     this.Season                 = episode.Season;
     this.UseDatabaseNumber      = episode.UseDatabaseNumber;
     this.UserNumber             = episode.UserNumber;
     this.DatabaseNumber         = episode.DatabaseNumber;
     this.DatabaseDvdNumber      = episode.DatabaseDvdNumber;
     this.UseDatabaseAirDate     = episode.UseDatabaseAirDate;
     this.DatabaseAirDate        = episode.DatabaseAirDate;
     this.UserAirDate            = episode.UserAirDate;
     this.File                   = new TvFile(episode.File);
     this.Ignored                = episode.Ignored;
     this.InDatabase             = episode.InDatabase;
     this.Missing                = episode.Missing;
     this.UseDatabaseOverview    = episode.UseDatabaseOverview;
     this.DatabaseOverview       = episode.DatabaseOverview;
     this.UserOverview           = episode.UserOverview;
     this.Watched                = episode.Watched;
     this.PreventDatabaseUpdates = episode.PreventDatabaseUpdates;
 }
Exemple #14
0
        /// <summary>
        /// Updates show's season/episode information from database. Use for newly 
        /// added shows only, as it will replace all episode information in show.
        /// </summary>
        /// <param name="show">Show to load episode information into</param>
        protected override bool DoUpdate(string mirror, Content content)
        {
            TvShow show = (TvShow)content;

            bool success = true;
            string tempPath = string.Empty;
            try
            {

                // Download episodes XML string
                string showUrl = mirror + "/api/" + API_KEY + "/series/" + show.Id + "/all/en.zip";
                string basePath = Organization.GetBasePath(true);
                Guid guid = Guid.NewGuid();
                tempPath = Path.Combine(basePath, guid.ToString());
                Directory.CreateDirectory(tempPath);
                string zipPath = Path.Combine(tempPath, "data" + ".zip");
                string extractPath = Path.Combine(tempPath, "en.xml");

                WebClient webClient = new WebClient();
                webClient.DownloadFile(showUrl, zipPath);

                ZipFile zip = ZipFile.Read(zipPath);
                foreach (ZipEntry entry in zip.Entries)
                    if (entry.FileName == "en.xml")
                    {
                        entry.Extract(tempPath, ExtractExistingFileAction.OverwriteSilently);
                        break;
                    }
                zip.Dispose();

                XmlDocument showDoc = new XmlDocument();
                showDoc.Load(extractPath);

                // Get root element and children
                XmlElement root = showDoc.DocumentElement;
                XmlNodeList rootNodes = root.ChildNodes;

                // Go through each node and get info for each episode
                foreach (XmlNode node in rootNodes)
                {
                    if (node.Name == "Series")
                    {
                        XmlNodeList serNodes = node.ChildNodes;
                        foreach (XmlNode subNode in serNodes)
                        {
                            switch (subNode.Name)
                            {
                                case "Genre":
                                    string[] genres = subNode.InnerText.Split('|');
                                    foreach(string genre in genres)
                                        if(!string.IsNullOrWhiteSpace(genre) && !show.DatabaseGenres.Contains(genre))
                                            show.DatabaseGenres.Add(genre);
                                    break;
                            }
                        }
                    }
                    else if (node.Name == "Episode")
                    {
                        TvEpisode ep = new TvEpisode(show);
                        int season = -1;

                        XmlNodeList subNodes = node.ChildNodes;
                        foreach (XmlNode subNode in subNodes)
                        {
                            switch (subNode.Name)
                            {
                                case "EpisodeNumber":
                                    int epNumber = 0;
                                    int.TryParse(subNode.InnerText, out epNumber);
                                    ep.DatabaseNumber = epNumber;
                                    break;
                                case "DVD_episodenumber":
                                    double dvdNumber = -1;
                                    if (double.TryParse(subNode.InnerText, out dvdNumber))
                                        ep.DatabaseDvdNumber = (int)dvdNumber;
                                    break;
                                case "EpisodeName":
                                    ep.DatabaseName = subNode.InnerText;
                                    break;
                                case "SeasonNumber":
                                    season = Convert.ToInt32(subNode.InnerText);
                                    ep.Season = season;
                                    break;
                                case "FirstAired":
                                    DateTime airData;
                                    DateTime.TryParse(subNode.InnerText, out airData);
                                    ep.DatabaseAirDate = airData;
                                    break;
                                case "Overview":
                                    ep.DatabaseOverview = subNode.InnerText;
                                    break;
                            }
                        }
                        ep.InDatabase = true;

                        if (ep.DisplayNumber > -1 && season > -1)
                        {
                            // If episode already exists just update it, else add it
                            TvEpisode existingMatch;
                            if (show.FindEpisode(ep.Season, ep.DatabaseNumber, true, out existingMatch))
                            {
                                existingMatch.DatabaseName = ep.DatabaseName;
                                existingMatch.DatabaseAirDate = ep.DatabaseAirDate;
                                existingMatch.DatabaseOverview = ep.DatabaseOverview;
                                existingMatch.InDatabase = true;
                            }
                            else
                                show.Episodes.Add(ep);
                        }
                    }
                }

                showDoc = null;
            }
            catch(Exception e)
            {
                Console.WriteLine("Exception caught on TvDb update: " + e.ToString());
                success = false;
            }
            finally
            {
                if (Directory.Exists(tempPath))
                    Directory.Delete(tempPath, true);
            }

            return success;
        }
 public EpisodeEditorWindowViewModel(TvEpisode episode)
 {
     this.Episode = new TvEpisode(episode);
 }
Exemple #16
0
        public OrgItem ProcessPath(OrgPath orgPath, bool tvOnlyCheck, bool skipMatching, bool fast, bool threaded, int procNumber, bool allowFromLog, out bool fromLog)
        {
            fromLog = false;
            FileCategory fileCat = FileHelper.CategorizeFile(orgPath, orgPath.Path);

            // Search through dir scan log for matching source
            if (allowFromLog)
            {
                for (int i = 0; i < Organization.DirScanLog.Count; i++)
                {
                    if (Organization.DirScanLog[i].SourcePath == orgPath.Path)
                    {
                        fromLog = true;

                        if (fileCat != Organization.DirScanLog[i].Category)
                        {
                            break;
                        }

                        OrgItem newItem = UpdateItemFromPrevious(orgPath, Organization.DirScanLog[i], threaded, false, false);
                        if (newItem != null && newItem.Action != OrgAction.None)
                        {
                            if (newItem.CanEnable)
                            {
                                newItem.Enable = true;
                            }
                            return(newItem);
                        }
                    }
                }
            }

            // If similar to earlier item, wait for it to complete before continuing
            while (!skipMatching && orgPath.SimilarTo >= 0 && orgPath.SimilarTo < this.Items.Count && (this.Items[orgPath.SimilarTo].Action == OrgAction.TBD || this.Items[orgPath.SimilarTo].Action == OrgAction.Processing))
            {
                // Check for cancellation
                if (scanCanceled || procNumber < scanNumber)
                {
                    return(null);
                }

                Thread.Sleep(50);
            }

            // If similar to earlier item, check if we can use it's info
            if (orgPath.SimilarTo > 0 && orgPath.SimilarTo < this.Items.Count)
            {
                OrgItem newItem = UpdateItemFromPrevious(orgPath, this.Items[orgPath.SimilarTo], threaded, fast, skipMatching);
                if (newItem != null)
                {
                    return(newItem);
                }
            }

            // Create default none item
            OrgItem noneItem = new OrgItem(OrgAction.None, orgPath.Path, fileCat, orgPath.OrgFolder);

            // Setup match to filename and folder name (if it's in a folder inside of downloads)
            string pathBase;

            if (!string.IsNullOrEmpty(orgPath.OrgFolder.FolderPath))
            {
                pathBase = orgPath.Path.Replace(orgPath.OrgFolder.FolderPath, "");
            }
            else
            {
                pathBase = orgPath.Path;
            }
            string[] pathSplit;
            if (!string.IsNullOrEmpty(orgPath.OrgFolder.FolderPath))
            {
                pathSplit = pathBase.Split('\\');
            }
            else
            {
                pathSplit = orgPath.Path.Split('\\');
            }
            pathSplit[pathSplit.Length - 1] = Path.GetFileNameWithoutExtension(pathSplit[pathSplit.Length - 1]);

            List <string> possibleMatchPaths = new List <string>();

            // Looking to remove dummy video files by rip (e.g. "ERTG.mp4" inside "The Matrix 1999 hd ERGT rip/" folder)
            List <string> validSplits = new List <string>();

            for (int i = pathSplit.Length - 1; i > 0; i--)
            {
                if (string.IsNullOrWhiteSpace(pathSplit[i]))
                {
                    continue;
                }

                bool containedInOther = false;
                for (int j = i - 1; j > 0; j--)
                {
                    if (pathSplit[j].Length > pathSplit[i].Length && pathSplit[j].ToLower().Contains(pathSplit[i].ToLower()))
                    {
                        containedInOther = true;
                        break;
                    }
                }

                if (!containedInOther)
                {
                    validSplits.Add(pathSplit[i]);
                    possibleMatchPaths.Add(pathSplit[i] + Path.GetExtension(orgPath.Path));
                }
            }

            for (int i = validSplits.Count - 1; i >= 0; i--)
            {
                string build = string.Empty;
                for (int j = validSplits.Count - 1; j >= i; j--)
                {
                    build += validSplits[j] + " ";
                }

                build = build.Trim();

                build += Path.GetExtension(orgPath.Path);
                if (!possibleMatchPaths.Contains(build))
                {
                    possibleMatchPaths.Add(build);
                }
            }


            // Try to match to each string
            foreach (string matchString in possibleMatchPaths)
            {
                OnDebugNotificationd("Attempting to match to path: \" " + matchString + "\"");

                // Get simple file name
                string simpleFile = FileHelper.BasicSimplify(Path.GetFileNameWithoutExtension(matchString), false);
                OnDebugNotificationd("Simplifies to:  \" " + simpleFile + "\"");

                // Categorize current match string
                FileCategory matchFileCat = FileHelper.CategorizeFile(orgPath, matchString);
                OnDebugNotificationd("Classified as: " + matchFileCat);

                // Check tv
                if (tvOnlyCheck && matchFileCat != FileCategory.TvVideo)
                {
                    continue;
                }

                // Check for cancellation
                if (scanCanceled || procNumber < scanNumber)
                {
                    return(null);
                }

                // Set whether item is for new show
                bool newShow = false;

                // Check for cancellation
                if (scanCanceled || procNumber < scanNumber)
                {
                    return(null);
                }

                // Add appropriate action based on file category
                switch (matchFileCat)
                {
                // TV item
                case FileCategory.TvVideo:

                    // Try to match file to existing show
                    Dictionary <TvShow, MatchCollection> matches = new Dictionary <TvShow, MatchCollection>();
                    for (int j = 0; j < Organization.Shows.Count; j++)
                    {
                        MatchCollection match = Organization.Shows[j].MatchFileToContent(matchString);
                        if (match != null && match.Count > 0)
                        {
                            matches.Add((TvShow)Organization.Shows[j], match);
                        }
                    }

                    // Try to match to temporary show
                    lock (directoryScanLock)
                        foreach (TvShow show in temporaryShows)
                        {
                            MatchCollection match = show.MatchFileToContent(matchString);
                            if (match != null && match.Count > 0 && !matches.ContainsKey(show))
                            {
                                matches.Add(show, match);
                            }
                        }

                    // Debug notification for show matches
                    string matchNotification = "Show name matches found: ";
                    if (matches.Count == 0)
                    {
                        matchNotification += "NONE";
                    }
                    else
                    {
                        foreach (TvShow match in matches.Keys)
                        {
                            matchNotification += match.DisplayName + ", ";
                        }
                        matchNotification = matchNotification.Substring(0, matchNotification.Length - 2);
                    }
                    OnDebugNotificationd(matchNotification);

                    // Check for matches to existing show
                    TvShow bestMatch = null;
                    if (matches.Count > 0)
                    {
                        // Find best match, based on length
                        int longestMatch = 2;     // minimum of 3 letters must match (acronym)
                        foreach (KeyValuePair <TvShow, MatchCollection> match in matches)
                        {
                            foreach (Match m in match.Value)
                            {
                                // Check that match is not part of a word
                                int matchWordCnt = 0;
                                for (int l = m.Index; l < simpleFile.Length; l++)
                                {
                                    if (simpleFile[l] == ' ')
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        ++matchWordCnt;
                                    }
                                }


                                if (m.Value.Trim().Length > longestMatch && m.Length >= matchWordCnt)
                                {
                                    longestMatch = m.Length;
                                    bestMatch    = match.Key;
                                }
                            }
                        }
                        if (bestMatch != null)
                        {
                            OnDebugNotificationd("Matched to show " + bestMatch.DisplayName);
                        }
                    }

                    // Episode not matched to a TV show, search database!
                    if (bestMatch == null && !skipMatching)
                    {
                        OnDebugNotificationd("Not matched to existing show; searching database.");

                        // Setup search string
                        string showFile = Path.GetFileNameWithoutExtension(matchString);

                        // Perform search for matching TV show
                        if (SearchHelper.TvShowSearch.ContentMatch(showFile, string.Empty, string.Empty, fast, threaded, out bestMatch))
                        {
                            ContentRootFolder defaultTvFolder;
                            string            path = NO_TV_FOLDER;
                            if (Settings.GetTvFolderForContent(bestMatch, out defaultTvFolder))
                            {
                                path = defaultTvFolder.FullPath;
                            }

                            bestMatch.RootFolder = path;
                            bestMatch.Path       = bestMatch.BuildFolderPath();

                            // Save show in temporary shows list (in case there are more files that may match to it during scan)
                            lock (directoryScanLock)
                                if (!temporaryShows.Contains(bestMatch))
                                {
                                    temporaryShows.Add(bestMatch);
                                }
                            newShow = true;
                        }
                        else
                        {
                            bestMatch = null;
                        }
                    }
                    else if (temporaryShows.Contains(bestMatch))
                    {
                        newShow = true;
                    }

                    // Episode has been matched to a TV show
                    if (bestMatch != null)
                    {
                        // Try to get episode information from file
                        int seasonNum, episodeNum1, episodeNum2;
                        if (FileHelper.GetEpisodeInfo(matchString, bestMatch.DatabaseName, out seasonNum, out episodeNum1, out episodeNum2))
                        {
                            // No season match means file only had episode number, allow this for single season shows
                            if (seasonNum == -1)
                            {
                                int maxSeason = 0;
                                foreach (int season in bestMatch.Seasons)
                                {
                                    if (season > maxSeason)
                                    {
                                        maxSeason = season;
                                    }
                                }

                                if (maxSeason == 1)
                                {
                                    seasonNum = 1;
                                }
                            }

                            // Try to get the episode from the show
                            TvEpisode episode1, episode2 = null;
                            if (bestMatch.FindEpisode(seasonNum, episodeNum1, false, out episode1))
                            {
                                if (episodeNum2 != -1)
                                {
                                    bestMatch.FindEpisode(seasonNum, episodeNum2, false, out episode2);
                                }

                                OrgAction action = orgPath.Copy ? OrgAction.Copy : OrgAction.Move;

                                // If item episode already exists set action to duplicate
                                if (episode1.Missing == MissingStatus.Located)
                                {
                                    action = OrgAction.AlreadyExists;
                                }

                                // Build action and add it to results
                                string  destination = bestMatch.BuildFilePath(episode1, episode2, Path.GetExtension(orgPath.Path));
                                OrgItem newItem     = new OrgItem(action, orgPath.Path, destination, episode1, episode2, fileCat, orgPath.OrgFolder);
                                if (destination.StartsWith(NO_TV_FOLDER))
                                {
                                    newItem.Action = OrgAction.NoRootFolder;
                                }
                                if (newItem.Action == OrgAction.AlreadyExists || newItem.Action == OrgAction.NoRootFolder)
                                {
                                    newItem.Enable = false;
                                }
                                else
                                {
                                    newItem.Enable = true;
                                }
                                newItem.Category  = matchFileCat;
                                newItem.IsNewShow = newShow;
                                return(newItem);
                            }
                            else
                            {
                                OnDebugNotificationd("Couldn't find episode for season " + seasonNum + " episods " + episodeNum1);
                            }
                        }
                    }

                    // No match to TV show
                    if (!tvOnlyCheck && !fast)
                    {
                        // Try to match to a movie
                        OrgItem movieItem;
                        if (CreateMovieAction(orgPath, matchString, out movieItem, threaded, fast, skipMatching, null))
                        {
                            noneItem.Clone(movieItem);
                        }
                    }

                    break;

                // Movie item
                case FileCategory.MovieVideo:
                    // Create action
                    OrgItem item;
                    CreateMovieAction(orgPath, matchString, out item, threaded, fast, skipMatching, null);

                    // If delete action created (for sample file)
                    if (item.Action == OrgAction.Delete)
                    {
                        return(BuildDeleteAction(orgPath, fileCat));
                    }
                    else if (item.Action != OrgAction.None)
                    {
                        return(item);
                    }
                    break;

                // Trash
                case FileCategory.Trash:
                    return(BuildDeleteAction(orgPath, matchFileCat));

                // Ignore
                case FileCategory.Ignored:
                    return(new OrgItem(OrgAction.None, orgPath.Path, matchFileCat, orgPath.OrgFolder));

                // Unknown
                default:
                    return(new OrgItem(OrgAction.None, orgPath.Path, matchFileCat, orgPath.OrgFolder));
                }

                // Check for cancellation
                if (scanCanceled || procNumber < scanNumber)
                {
                    return(noneItem);
                }
            }

            // If no match on anything set none action
            return(noneItem);
        }
        /// <summary>
        /// Builds episode string for TV episode for both single or multi-episode files.
        /// </summary>
        /// <param name="ep1">First episode</param>
        /// <param name="ep2">Second episode (if double episode file)</param>
        /// <returns>Resulting episode string</returns>
        public string BuildEpisodeString(TvEpisode ep1, TvEpisode ep2)
        {
            // Start out with formatting string
            string epStr = string.Empty;

            // Build episode string
            for (int i = 0; i < 2; i++)
            {
                bool season = (i == 0 && this.SeasonFirst) || (i == 1 && !this.SeasonFirst);

                if (season)
                {
                    if (this.ForceSeasonDoubleDigits)
                        epStr += this.SeasonHeader + ep1.Season.ToString("00");
                    else
                        epStr += this.SeasonHeader + ep1.Season.ToString();
                }
                else
                {
                    if (this.ForceEpisodeDoubleDigits)
                        epStr += this.EpisodeHeader + ep1.DisplayNumber.ToString("00");
                    else
                        epStr += this.EpisodeHeader + ep1.DisplayNumber.ToString();

                    if (ep2 != null && ep2.DisplayNumber > 0)
                    {
                        if (this.HeaderPerEpisode)
                            epStr += this.EpisodeHeader;

                        if (this.ForceEpisodeDoubleDigits)
                            epStr += ep2.DisplayNumber.ToString("00");
                        else
                            epStr += ep2.DisplayNumber.ToString();
                    }
                }
            }

            // Return file name
            return epStr;
        }
Exemple #18
0
 /// <summary>
 /// Constructor for TV rename/missing check where file was not found.
 /// </summary>
 /// <param name="status">Status of rename/missing</param>
 /// <param name="action">action to be performed</param>
 /// <param name="episode">TV episode for file</param>
 /// <param name="episode2">2nd Tv epsidoe for file</param>
 /// <param name="category">file category</param>
 public OrgItem(OrgStatus status, OrgAction action, TvEpisode episode, TvEpisode episode2, FileCategory category, OrgFolder scanDir, TvEpisodeTorrent torrentEp)
     : this()
 {
     this.Status = status;
     this.Progress = 0;
     this.Action = action;
     this.SourcePath = string.Empty;
     if (action == OrgAction.Delete)
         this.DestinationPath = FileHelper.DELETE_DIRECTORY;
     else
         this.DestinationPath = string.Empty;
     this.TvEpisode = new TvEpisode(episode);
     if (episode2 != null)
         this.TvEpisode2 = new TvEpisode(episode2);
     this.TorrentTvEpisode = torrentEp;
     this.Category = category;
     this.Enable = action == OrgAction.Torrent;
     this.ScanDirectory = scanDir;
     this.Number = 0;
 }
Exemple #19
0
 /// <summary>
 /// Constructor for TV rename/missing check where file was found.
 /// </summary>
 /// <param name="status">Status of rename/missing</param>
 /// <param name="action">action to be performed</param>
 /// <param name="file">source path</param>
 /// <param name="destination">destination path</param>
 /// <param name="episode">TV episode for file</param>
 /// <param name="episode2">2nd Tv epsidoe for file</param>
 /// <param name="category">file category</param>
 public OrgItem(OrgStatus status, OrgAction action, string file, string destination, TvEpisode episode, TvEpisode episode2, FileCategory category, OrgFolder scanDir)
     : this(action, file, destination, episode, episode2, category, scanDir)
 {
     this.Status = status;
     this.Progress = 0;
 }
Exemple #20
0
        /// <summary>
        /// Loads instance from XML.
        /// </summary>
        /// <param name="itemNode">Node to load XML from</param>
        /// <returns>true if sucessfully loaded from XML</returns>
        public override bool Load(XmlNode showNode)
        {
            // Check that node is proper type
            if (showNode.Name != ROOT_XML)
                return false;

            // Read base properties out
            base.ReadContentElements(showNode);

            // Read other elements
            foreach (XmlNode propNode in showNode.ChildNodes)
            {
                XmlElements element;
                if (!Enum.TryParse<XmlElements>(propNode.Name, out element))
                    continue;

                string value = propNode.InnerText;
                switch (element)
                {
                    case XmlElements.Seasons: // Support for older versions
                        this.Episodes.Clear();
                        foreach (XmlNode seasNode in propNode.ChildNodes)
                        {
                            foreach (XmlNode seasPropNode in seasNode.ChildNodes)
                            {
                                if(seasPropNode.Name == "Episodes")
                                {
                                    foreach(XmlNode epNode in seasPropNode.ChildNodes)
                                    {
                                        TvEpisode episode = new TvEpisode(this);
                                        episode.Load(epNode);
                                        Episodes.Add(episode);
                                    }
                                }
                            }
                        }
                        break;
                    case XmlElements.Episodes:
                        this.Episodes.Clear();
                        foreach(XmlNode epNode in propNode.ChildNodes)
                        {
                            TvEpisode episode = new TvEpisode(this);
                            episode.Load(epNode);
                            Episodes.Add(episode);
                        }
                        break;
                    case XmlElements.DoMissing:
                        bool doMissing;
                        bool.TryParse(value, out doMissing);
                        this.DoMissingCheck = doMissing;
                        break;
                    case XmlElements.IncludeInSchedule:
                        bool include;
                        bool.TryParse(value, out include);
                        this.IncludeInSchedule = include;
                        break;
                    case XmlElements.AlternativeNameMatches:
                        this.AlternativeNameMatches = new ObservableCollection<string>();
                        foreach (XmlNode matchNode in propNode.ChildNodes)
                            if (!string.IsNullOrWhiteSpace(matchNode.InnerText))
                                this.AlternativeNameMatches.Add(matchNode.InnerText);
                        break;
                    case XmlElements.DvdEpisodeOrder:
                        bool dvdOrder;
                        bool.TryParse(value, out dvdOrder);
                        this.DvdEpisodeOrder = dvdOrder;
                        break;
                }
            }

            // Sucess
            return true;
        }
Exemple #21
0
 /// <summary>
 /// Constructor for cloning instance.
 /// </summary>
 /// <param name="episode">Instance to clone</param>
 public TvEpisode(TvEpisode episode)
 {
     this.Clone(episode);
 }
 /// <summary>
 /// Get available torrents for episode
 /// </summary>
 /// <returns></returns>
 public virtual List<TvEpisodeTorrent> GetAvailableTvTorrents(TvEpisode episode)
 {
     throw new NotImplementedException();
 }
Exemple #23
0
        /// <summary>
        /// Builds formatted file name for TV episode file from an existing file path.
        /// </summary>
        /// <param name="episode1">First episode in file</param>
        /// <param name="episode2">Second episode in file</param>
        /// <param name="fullPath">Path of file to be formatted</param>
        /// <returns>Path with file name formatted</returns>
        public string BuildTvFileName(TvEpisode episode1, TvEpisode episode2, string fullPath)
        {
            // Get file name
            string fileName = Path.GetFileNameWithoutExtension(fullPath);

            // Get info from file using simplify function (pulls out file words and categorizes them)
            FileHelper.OptionalSimplifyRemoves simplifyOptions = FileHelper.OptionalSimplifyRemoves.Year;
            FileHelper.SimplifyStringResults simplifyResults = FileHelper.BuildSimplifyResults(fileName, false, false, simplifyOptions, true, false, false, false);

            // Build file name
            string buildName = BuildFileName(episode1, episode2, simplifyResults);

            // Remove unsafe file characters and add extension
            return FileHelper.GetSafeFileName(buildName);
        }
Exemple #24
0
        /// <summary>
        /// Build a combined episode name for 2 episodes. Find commanality between both names
        /// and produces a joined name. e.g. From "The Final (part 1)" & "The Fina1 (part 2) the
        /// method will return "The Final (Part 1 & 2)"
        /// </summary>
        /// <param name="episode1">First episode</param>
        /// <param name="episode2">Second epsiode</param>
        /// <returns>Joined episod names from both episodes</returns>
        public string BuildEpisodeName(TvEpisode episode1, TvEpisode episode2)
        {
            string epName;

            if (episode2 != null && !string.IsNullOrEmpty(episode2.DisplayName) && episode2.DatabaseNumber > 0)
            {
                char[] ep1Chars = episode1.DisplayName.ToCharArray();
                char[] ep2Chars = episode2.DisplayName.ToCharArray();

                // Check if name have any similarities at start
                int matchLen = 0;
                for (int i = 0; i < Math.Min(ep1Chars.Length, ep2Chars.Length); i++)
                {
                    if (ep1Chars[i] == ep2Chars[i])
                    {
                        matchLen++;
                    }
                    else
                    {
                        break;
                    }
                }

                if (matchLen > 3)
                {
                    List <char> name1Build = ep1Chars.ToList();
                    List <char> name2Build = ep2Chars.ToList();

                    // Go through characters of episode names and remove identicals
                    bool closingBracketFound = false;
                    for (int i = Math.Min(ep1Chars.Length, ep2Chars.Length) - 1; i >= 0; i--)
                    {
                        if (ep1Chars[i] == ep2Chars[i])
                        {
                            if (ep1Chars[i] == ')' && !closingBracketFound)
                            {
                                closingBracketFound = true;
                                name1Build.RemoveAt(i);
                            }

                            name2Build.RemoveAt(i);
                        }
                    }

                    epName = new String(name1Build.ToArray()) + " & " + new String(name2Build.ToArray());

                    if (closingBracketFound)
                    {
                        epName += ")";
                    }
                }
                else
                {
                    epName = episode1.DisplayName + " & " + episode2.DisplayName;
                }
            }
            else
            {
                epName = episode1.DisplayName;
            }

            return(epName.Trim());
        }
Exemple #25
0
        /// <summary>
        /// Build file name for TV or movie file.
        /// </summary>
        /// <param name="movieName">Name of movie</param>
        /// <param name="episode1">First episode in file</param>
        /// <param name="episode2">Second episode in file</param>
        /// <param name="date">Date item was released</param>
        /// <param name="simplifyResults">File name simplifying results</param>
        /// <param name="differentiator"></param>
        /// <returns></returns>
        private string BuildFileName(string movieName, TvEpisode episode1, TvEpisode episode2, int year, FileHelper.SimplifyStringResults simplifyResults, string differentiator)
        {
            // Init file name
            string fileName = string.Empty;

            // Loop through each portion of format and add it to the file names
            foreach (FileNamePortion portion in this.Format)
            {
                // Get string value for current portion
                string value = portion.Header;
                switch (portion.Type)
                {
                case FileWordType.MovieName:
                    value = movieName;
                    break;

                case FileWordType.ShowName:
                    value = episode1.Show.DatabaseName;
                    break;

                case FileWordType.EpisodeName:
                    value = BuildEpisodeName(episode1, episode2);
                    break;

                case FileWordType.EpisodeNumber:
                    value = EpisodeFormat.BuildEpisodeString(episode1, episode2);
                    break;

                case FileWordType.Year:
                    value = year.ToString();
                    break;

                case FileWordType.FilePart:
                    if (!GetFileWord(simplifyResults, portion.Type, out value))
                    {
                        value = differentiator;
                    }
                    break;

                default:
                    GetFileWord(simplifyResults, portion.Type, out value);
                    break;
                }

                // Add portion with header/footer and apply option
                if (!string.IsNullOrWhiteSpace(value))
                {
                    // Add header
                    fileName += portion.Header;

                    // Apply case options
                    switch (portion.CaseOption)
                    {
                    case CaseOptionType.None:
                        break;

                    case CaseOptionType.LowerCase:
                        value = value.ToLower();
                        break;

                    case CaseOptionType.UpperCase:
                        value = value.ToUpper();
                        break;
                    }

                    // Apply whitespace options
                    fileName += Regex.Replace(value, @"\s+", portion.Whitespace);

                    // Add footer
                    fileName += portion.Footer;
                }
            }

            // Return file name that was built
            return(fileName);
        }
Exemple #26
0
 /// <summary>
 /// Build file name for TV epiosode file.
 /// </summary>
 /// <param name="episode1">First episode in file</param>
 /// <param name="episode2">Second episode in file (if any)</param>
 /// <param name="simplifyResults">File name simplifying results</param>
 /// <returns>Resulting formatted file name string</returns>
 private string BuildFileName(TvEpisode episode1, TvEpisode episode2, FileHelper.SimplifyStringResults simplifyResults)
 {
     return(BuildFileName(string.Empty, episode1, episode2, 1, simplifyResults, string.Empty));
 }
Exemple #27
0
 /// <summary>
 /// Build file name for TV epiosode file.
 /// </summary>
 /// <param name="episode1">First episode in file</param>
 /// <param name="episode2">Second episode in file (if any)</param>
 /// <param name="simplifyResults">File name simplifying results</param>
 /// <returns>Resulting formatted file name string</returns>
 private string BuildFileName(TvEpisode episode1, TvEpisode episode2, FileHelper.SimplifyStringResults simplifyResults)
 {
     return BuildFileName(string.Empty, episode1, episode2, 1, simplifyResults, string.Empty);
 }
Exemple #28
0
        /// <summary>
        /// Gets season/episode information from database
        /// </summary>
        /// <param name="show">Show to load episode information into</param>
        protected override bool DoUpdate(string mirror, Content content)
        {
            TvShow show = (TvShow)content;

            try
            {
                // Get show info from database
                string    showInfoUrl = mirror + "/showinfo.php?key=" + this.API_KEY + "&sid=" + show.Id;
                WebClient webClient   = new WebClient();
                string    showInfo    = webClient.DownloadString(showInfoUrl);

                // Create XML object from results
                XmlDocument seriesDoc = new XmlDocument();
                seriesDoc.InnerXml = showInfo;

                // Parse show info
                show.Overview = ParseShowInfo(seriesDoc.DocumentElement).Overview;

                // Get episode info from database
                string episodeListUrl = mirror + "/episode_list.php?key=" + this.API_KEY + "&sid=" + show.Id;
                webClient = new WebClient();
                string seriesList = webClient.DownloadString(episodeListUrl);

                // Create xml object with text from mirrors url
                seriesDoc          = new XmlDocument();
                seriesDoc.InnerXml = seriesList;

                // Get root element and children
                XmlElement  root  = seriesDoc.DocumentElement;
                XmlNodeList nodes = root.ChildNodes;

                // Go through each node and parse out episodes
                foreach (XmlNode subNode in nodes)
                {
                    switch (subNode.Name.ToLower())
                    {
                    case "episodelist":
                        foreach (XmlNode seasonNode in subNode.ChildNodes)
                        {
                            if (seasonNode.Name.ToLower() == "season")
                            {
                                string seasonNoStr = seasonNode.Attributes["no"].Value;
                                int    seasonNo;
                                int.TryParse(seasonNoStr, out seasonNo);

                                foreach (XmlNode epNode in seasonNode.ChildNodes)
                                {
                                    TvEpisode ep = new TvEpisode(show);
                                    ep.Season = seasonNo;
                                    foreach (XmlNode epPropNode in epNode.ChildNodes)
                                    {
                                        switch (epPropNode.Name.ToLower())
                                        {
                                        case "seasonnum":         // episode number within season
                                            int epNum;
                                            int.TryParse(epPropNode.InnerText, out epNum);
                                            ep.DatabaseNumber = epNum;
                                            break;

                                        case "airdate":
                                            DateTime airDate;
                                            DateTime.TryParse(epPropNode.InnerText, out airDate);
                                            ep.DatabaseAirDate = airDate;
                                            break;

                                        case "title":
                                            ep.DatabaseName = epPropNode.InnerText;
                                            break;

                                        case "summary":
                                            ep.DatabaseOverview = epPropNode.InnerText.Replace('\n', ' ');
                                            break;
                                        }
                                    }
                                    ep.InDatabase = true;

                                    // If episode already exists just update it, else add it
                                    TvEpisode existingMatch;
                                    if (show.FindEpisode(ep.Season, ep.DatabaseNumber, true, out existingMatch))
                                    {
                                        if (!existingMatch.PreventDatabaseUpdates)
                                        {
                                            existingMatch.DatabaseName     = ep.DatabaseName;
                                            existingMatch.DatabaseAirDate  = ep.DatabaseAirDate;
                                            existingMatch.DatabaseOverview = ep.DatabaseOverview;
                                            existingMatch.InDatabase       = true;
                                        }
                                    }
                                    else
                                    {
                                        show.Episodes.Add(ep);
                                    }
                                }
                            }
                        }
                        break;
                    }
                }
                return(true);
            }
            catch
            {
                return(false);
            }
        }
Exemple #29
0
 /// <summary>
 /// Find an episode from the show.
 /// </summary>
 /// <param name="seasonNumber">The season of the episode</param>
 /// <param name="episodeNumber">The number of the epsiode within the season</param>
 /// <param name="episode">The matched episode if one is found, else null</param>
 /// <returns>true if the episode was found, false otherwise</returns>
 public bool FindEpisode(int seasonNumber, int episodeNumber, bool databaseNum, out TvEpisode episode)
 {
     episode = null;
     foreach (TvEpisode ep in this.Episodes)
         if (ep.Season == seasonNumber && ((ep.DisplayNumber == episodeNumber && !databaseNum) || (ep.DatabaseNumber == episodeNumber && databaseNum)))
         {
             episode = ep;
             return true;
         }
     return false;
 }
Exemple #30
0
        /// <summary>
        /// Open file dialog so user can locate episode in file directory.
        /// </summary>
        /// <param name="showActionModifer">Whether to display action modifier after path is selected</param>
        /// <param name="copyAction">Whether to copy file, move otherwise</param>
        /// <param name="items">Organization items to add move/copy action to once located</param>
        /// <returns>true if locate was sucessful</returns>
        public bool UserLocate(bool showActionModifer, bool copyAction, out List <OrgItem> items)
        {
            // Initialize org items
            items = new List <OrgItem>();

            // Open file dialog
            VistaOpenFileDialog ofd = new VistaOpenFileDialog();

            ofd.Filter = "All Files|*.*";
            if (!(bool)ofd.ShowDialog())
            {
                return(false);
            }

            // Try to get episode information from file
            int  fileEpSeason, fileEpNumber1, fileEpNumber2;
            bool fileInfoFound = FileHelper.GetEpisodeInfo(ofd.FileName, this.Show.DatabaseName, out fileEpSeason, out fileEpNumber1, out fileEpNumber2);

            // Assign episodes
            TvEpisode ep1 = this;
            TvEpisode ep2 = null;

            // Locate could be for double episode file, only taken if one of the episode from file matches selected
            if (fileInfoFound && fileEpSeason == this.Season)
            {
                if (fileEpNumber1 == this.DisplayNumber)
                {
                    if (fileEpNumber2 > 0)
                    {
                        show.FindEpisode(ep1.Season, fileEpNumber2, false, out ep2);
                    }
                    else
                    {
                        ep2 = null;
                    }
                }
                else if (fileEpNumber2 == this.DisplayNumber)
                {
                    if (fileEpNumber1 > 0 && show.FindEpisode(this.Season, fileEpNumber1, false, out ep1))
                    {
                        ep2 = this;
                    }
                    else
                    {
                        ep1 = this;
                    }
                }
            }

            // Build org item
            OrgAction action      = copyAction ? OrgAction.Copy : OrgAction.Move;
            string    destination = show.BuildFilePath(ep1, ep2, Path.GetExtension(ofd.FileName));
            OrgItem   item        = new OrgItem(OrgStatus.Found, action, ofd.FileName, destination, ep1, ep2, FileCategory.TvVideo, null);

            // Display modifier
            if (showActionModifer)
            {
                OrgItemEditorWindow editor = new OrgItemEditorWindow(item);
                editor.ShowDialog();

                // Add results if valid
                if (editor.Results == null)
                {
                    return(false);
                }

                items.Add(editor.Results);
                return(true);
            }

            items.Add(item);
            return(true);
        }
        /// <summary>
        /// Updates show's season/episode information from database. Use for newly
        /// added shows only, as it will replace all episode information in show.
        /// </summary>
        /// <param name="show">Show to load episode information into</param>
        protected override bool DoUpdate(string mirror, Content content)
        {
            TvShow show = (TvShow)content;

            bool   success  = true;
            string tempPath = string.Empty;

            try
            {
                // Download episodes XML string
                string showUrl  = mirror + "/api/" + API_KEY + "/series/" + show.Id + "/all/en.zip";
                string basePath = Organization.GetBasePath(true);
                Guid   guid     = Guid.NewGuid();
                tempPath = Path.Combine(basePath, guid.ToString());
                Directory.CreateDirectory(tempPath);
                string zipPath     = Path.Combine(tempPath, "data" + ".zip");
                string extractPath = Path.Combine(tempPath, "en.xml");

                WebClient webClient = new WebClient();
                webClient.DownloadFile(showUrl, zipPath);

                ZipFile zip = ZipFile.Read(zipPath);
                foreach (ZipEntry entry in zip.Entries)
                {
                    if (entry.FileName == "en.xml")
                    {
                        entry.Extract(tempPath, ExtractExistingFileAction.OverwriteSilently);
                        break;
                    }
                }
                zip.Dispose();

                XmlDocument showDoc = new XmlDocument();
                showDoc.Load(extractPath);

                // Get root element and children
                XmlElement  root      = showDoc.DocumentElement;
                XmlNodeList rootNodes = root.ChildNodes;

                // Go through each node and get info for each episode
                foreach (XmlNode node in rootNodes)
                {
                    if (node.Name == "Series")
                    {
                        XmlNodeList serNodes = node.ChildNodes;
                        foreach (XmlNode subNode in serNodes)
                        {
                            switch (subNode.Name)
                            {
                            case "Genre":
                                string[] genres = subNode.InnerText.Split('|');
                                foreach (string genre in genres)
                                {
                                    if (!string.IsNullOrWhiteSpace(genre) && !show.DatabaseGenres.Contains(genre))
                                    {
                                        show.DatabaseGenres.Add(genre);
                                    }
                                }
                                break;
                            }
                        }
                    }
                    else if (node.Name == "Episode")
                    {
                        TvEpisode ep     = new TvEpisode(show);
                        int       season = -1;

                        XmlNodeList subNodes = node.ChildNodes;
                        foreach (XmlNode subNode in subNodes)
                        {
                            switch (subNode.Name)
                            {
                            case "EpisodeNumber":
                                int epNumber = 0;
                                int.TryParse(subNode.InnerText, out epNumber);
                                ep.DatabaseNumber = epNumber;
                                break;

                            case "DVD_episodenumber":
                                double dvdNumber = -1;
                                if (double.TryParse(subNode.InnerText, out dvdNumber))
                                {
                                    ep.DatabaseDvdNumber = (int)dvdNumber;
                                }
                                break;

                            case "EpisodeName":
                                ep.DatabaseName = subNode.InnerText;
                                break;

                            case "SeasonNumber":
                                season    = Convert.ToInt32(subNode.InnerText);
                                ep.Season = season;
                                break;

                            case "FirstAired":
                                DateTime airData;
                                DateTime.TryParse(subNode.InnerText, out airData);
                                ep.DatabaseAirDate = airData;
                                break;

                            case "Overview":
                                ep.DatabaseOverview = subNode.InnerText;
                                break;
                            }
                        }
                        ep.InDatabase = true;

                        if (ep.DisplayNumber > -1 && season > -1)
                        {
                            // If episode already exists just update it, else add it
                            TvEpisode existingMatch;
                            if (show.FindEpisode(ep.Season, ep.DatabaseNumber, true, out existingMatch))
                            {
                                existingMatch.DatabaseName     = ep.DatabaseName;
                                existingMatch.DatabaseAirDate  = ep.DatabaseAirDate;
                                existingMatch.DatabaseOverview = ep.DatabaseOverview;
                                existingMatch.InDatabase       = true;
                            }
                            else
                            {
                                show.Episodes.Add(ep);
                            }
                        }
                    }
                }

                showDoc = null;
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception caught on TvDb update: " + e.ToString());
                success = false;
            }
            finally
            {
                if (Directory.Exists(tempPath))
                {
                    Directory.Delete(tempPath, true);
                }
            }

            return(success);
        }
Exemple #32
0
        /// <summary>
        /// Build a combined episode name for 2 episodes. Find commanality between both names
        /// and produces a joined name. e.g. From "The Final (part 1)" & "The Fina1 (part 2) the
        /// method will return "The Final (Part 1 & 2)"
        /// </summary>
        /// <param name="episode1">First episode</param>
        /// <param name="episode2">Second epsiode</param>
        /// <returns>Joined episod names from both episodes</returns>
        public string BuildEpisodeName(TvEpisode episode1, TvEpisode episode2)
        {
            string epName;
            if (episode2 != null && !string.IsNullOrEmpty(episode2.DisplayName) && episode2.DatabaseNumber > 0)
            {
                char[] ep1Chars = episode1.DisplayName.ToCharArray();
                char[] ep2Chars = episode2.DisplayName.ToCharArray();

                // Check if name have any similarities at start
                int matchLen = 0;
                for (int i = 0; i < Math.Min(ep1Chars.Length, ep2Chars.Length); i++)
                    if (ep1Chars[i] == ep2Chars[i])
                        matchLen++;
                    else
                        break;

                if (matchLen > 3)
                {
                    List<char> name1Build = ep1Chars.ToList();
                    List<char> name2Build = ep2Chars.ToList();

                    // Go through characters of episode names and remove identicals
                    bool closingBracketFound = false;
                    for (int i = Math.Min(ep1Chars.Length, ep2Chars.Length) - 1; i >= 0; i--)
                        if (ep1Chars[i] == ep2Chars[i])
                        {
                            if (ep1Chars[i] == ')' && !closingBracketFound)
                            {
                                closingBracketFound = true;
                                name1Build.RemoveAt(i);
                            }

                            name2Build.RemoveAt(i);
                        }

                    epName = new String(name1Build.ToArray()) + " & " + new String(name2Build.ToArray());

                    if (closingBracketFound)
                        epName += ")";
                }
                else
                    epName = episode1.DisplayName + " & " + episode2.DisplayName;
            }
            else
                epName = episode1.DisplayName;

            return epName.Trim();
        }
Exemple #33
0
 /// <summary>
 /// Update current update from another item's data
 /// </summary>
 /// <param name="item">item to be copied</param>
 public void Clone(OrgItem item)
 {
     this.Status = item.Status;
     this.Progress = 0;
     this.Action = item.Action;
     this.SourcePath = item.SourcePath;
     this.DestinationPath = item.DestinationPath;
     this.TvEpisode = item.TvEpisode;
     this.TvEpisode2 = item.TvEpisode2;
     this.TorrentTvEpisode = item.TorrentTvEpisode;
     this.Category = item.Category;
     this.Enable = item.Enable;
     this.Movie = item.Movie;
     this.ScanDirectory = item.ScanDirectory;
     this.Replace = item.Replace;
     this.Number = item.Number;
     this.QueueStatus = item.QueueStatus;
     this.ActionComplete = item.ActionComplete;
     this.Notes = item.Notes;
     this.ActionTime = item.ActionTime;
 }
Exemple #34
0
 /// <summary>
 /// Build the file name string for a given episode
 /// </summary>
 /// <param name="episode1">Episode to build file name for</param>
 /// <param name="episode2">Second episode for double-episode files</param>
 /// <returns>Episode file name string</returns>
 public string BuildFileName(TvEpisode episode1, TvEpisode episode2, string path)
 {
     return(Settings.TvFileFormat.BuildTvFileName(episode1, episode2, path));
 }
Exemple #35
0
 /// <summary>
 /// Constructor for directory scan for file matched to TV episode.
 /// </summary>
 /// <param name="action">action to be performed</param>
 /// <param name="file">source path</param>
 /// <param name="destination">destination path</param>
 /// <param name="episode">TV episode for file</param>
 /// <param name="episode2">2nd Tv epsidoe for file</param>
 /// <param name="category">file category</param>
 public OrgItem(OrgAction action, string file, string destination, TvEpisode episode, TvEpisode episode2, FileCategory category, OrgFolder scanDir)
     : this()
 {
     this.Action = action;
     this.SourcePath = file;
     this.DestinationPath = destination;
     this.TvEpisode = new TvEpisode(episode);
     this.Category = category;
     if (episode2 != null)
         this.TvEpisode2 = new TvEpisode(episode2);
     this.Enable = false;
     this.ScanDirectory = scanDir;
     this.Number = 0;
 }
Exemple #36
0
        /// <summary>
        /// Loads instance from XML.
        /// </summary>
        /// <param name="itemNode">Node to load XML from</param>
        /// <returns>true if sucessfully loaded from XML</returns>
        public override bool Load(XmlNode showNode)
        {
            // Check that node is proper type
            if (showNode.Name != ROOT_XML)
            {
                return(false);
            }

            // Read base properties out
            base.ReadContentElements(showNode);

            // Read other elements
            foreach (XmlNode propNode in showNode.ChildNodes)
            {
                XmlElements element;
                if (!Enum.TryParse <XmlElements>(propNode.Name, out element))
                {
                    continue;
                }

                string value = propNode.InnerText;
                switch (element)
                {
                case XmlElements.Seasons:     // Support for older versions
                    this.Episodes.Clear();
                    foreach (XmlNode seasNode in propNode.ChildNodes)
                    {
                        foreach (XmlNode seasPropNode in seasNode.ChildNodes)
                        {
                            if (seasPropNode.Name == "Episodes")
                            {
                                foreach (XmlNode epNode in seasPropNode.ChildNodes)
                                {
                                    TvEpisode episode = new TvEpisode(this);
                                    episode.Load(epNode);
                                    Episodes.Add(episode);
                                }
                            }
                        }
                    }
                    break;

                case XmlElements.Episodes:
                    this.Episodes.Clear();
                    foreach (XmlNode epNode in propNode.ChildNodes)
                    {
                        TvEpisode episode = new TvEpisode(this);
                        episode.Load(epNode);
                        Episodes.Add(episode);
                    }
                    break;

                case XmlElements.DoMissing:
                    bool doMissing;
                    bool.TryParse(value, out doMissing);
                    this.DoMissingCheck = doMissing;
                    break;

                case XmlElements.IncludeInSchedule:
                    bool include;
                    bool.TryParse(value, out include);
                    this.IncludeInSchedule = include;
                    break;

                case XmlElements.AlternativeNameMatches:
                    this.AlternativeNameMatches = new ObservableCollection <string>();
                    foreach (XmlNode matchNode in propNode.ChildNodes)
                    {
                        if (!string.IsNullOrWhiteSpace(matchNode.InnerText))
                        {
                            this.AlternativeNameMatches.Add(matchNode.InnerText);
                        }
                    }
                    break;

                case XmlElements.DvdEpisodeOrder:
                    bool dvdOrder;
                    bool.TryParse(value, out dvdOrder);
                    this.DvdEpisodeOrder = dvdOrder;
                    break;
                }
            }

            // Sucess
            return(true);
        }
Exemple #37
0
        /// <summary>
        /// Run through all TV shows all looks for episodes that may need to be renamed and for missing episodes.
        /// For missing episodes it attempts to match them to files from the search directories.
        /// </summary>
        /// <param name="shows">Shows to scan</param>
        /// <param name="queuedItems">Items currently in queue (to be skipped)</param>
        /// <returns></returns>
        public List <OrgItem> RunScan(List <Content> shows, List <OrgItem> queuedItems)
        {
            // Set running flag
            scanRunning = true;

            // Initialiaze scan items
            List <OrgItem> missingCheckItem = new List <OrgItem>();

            // Initialize item numbers
            int number = 0;

            // Go through each show
            for (int i = 0; i < shows.Count; i++)
            {
                TvShow show = (TvShow)shows[i];

                if (cancelRequested)
                {
                    break;
                }

                OnProgressChange(ScanProcess.TvRename, shows[i].DatabaseName, (int)Math.Round((double)i / (shows.Count) * 30) + 70);

                // Go each show
                foreach (TvEpisode ep in show.Episodes)
                {
                    // Check for cancellation
                    if (cancelRequested)
                    {
                        break;
                    }

                    // Skipped ignored episodes
                    if (ep.Ignored)
                    {
                        continue;
                    }

                    // Init found flag
                    bool found = false;

                    // Rename check
                    if (ep.Missing == MissingStatus.Located)
                    {
                        if (shows[i].DoRenaming)
                        {
                            found = true;
                            TvEpisode ep2 = null;

                            if (ep.File.MultiPart)
                            {
                                if (ep.File.Part == 1)
                                {
                                    foreach (TvEpisode epEnumerated in show.Episodes)
                                    {
                                        if (epEnumerated.Season == ep.Season && epEnumerated.DisplayNumber == ep.DisplayNumber + 1)
                                        {
                                            ep2 = epEnumerated;
                                            break;
                                        }
                                    }
                                }
                                else
                                {
                                    continue;
                                }
                            }

                            // Build desired path
                            string builtPath = show.BuildFilePath(ep, ep2, Path.GetExtension(ep.File.FilePath));

                            // Check if rename needed (or move within folder)
                            if (ep.File.FilePath != builtPath)
                            {
                                OrgItem newItem = new OrgItem(OrgStatus.Organization, OrgAction.Rename, ep.File.FilePath, builtPath, ep, ep2, FileCategory.TvVideo, null);
                                newItem.Enable = true;
                                if (!show.DoRenaming)
                                {
                                    newItem.Category = FileCategory.Ignored;
                                }
                                newItem.Number = number++;
                                missingCheckItem.Add(newItem);
                            }
                        }
                        else
                        {
                            continue;
                        }
                    }
                    else
                    {
                        continue;
                    }

                    // Add empty item for missing
                    if (!found && ep.Aired && show.DoMissingCheck)
                    {
                        OrgItem newItem = new OrgItem(OrgStatus.Missing, OrgAction.None, ep, null, FileCategory.TvVideo, null);
                        if (!show.DoRenaming)
                        {
                            newItem.Category = FileCategory.Ignored;
                        }
                        newItem.Number = number++;
                        missingCheckItem.Add(newItem);
                    }
                }
            }

            // Convert all TV folders to org folders
            List <OrgFolder> tvFoldersAsOrgFolders = new List <OrgFolder>();

            foreach (ContentRootFolder tvFolder in Settings.TvFolders)
            {
                OrgFolder orgFolder = new OrgFolder(tvFolder.FullPath, false, false, false, false);
                tvFoldersAsOrgFolders.Add(orgFolder);
            }

            // Update progress
            OnProgressChange(ScanProcess.TvRename, string.Empty, 100);

            // Clear flags
            scanRunning     = false;
            cancelRequested = false;

            // Return results
            return(missingCheckItem);
        }
        private void AddNewEpisode()
        {
            if (show == null)
                return;

            TvEpisode ep = new TvEpisode("", show, 1, -1, DateTime.Now.ToString(), "");
            ep.UseDatabaseAirDate = false;
            ep.UseDatabaseOverview = false;
            ep.UseDatabaseNumber = false;
            ep.UseDatabaseName = false;
            ep.UserName = "";
            ep.UserNumber = 1;

            if (show.Episodes.Count > 0)
            {
                TvEpisode lastEp = show.Episodes.Last();
                ep.Season = lastEp.Season;
                ep.UserNumber = lastEp.DisplayNumber + 1;
            }

            EpisodeEditorWindow editor = new EpisodeEditorWindow(ep);
            editor.ShowDialog();

            if (editor.Results != null)
            {
                // Check if episode already exists
                if (this.show.FindEpisode(editor.Results.Season, editor.Results.DisplayNumber, false, out ep))
                {
                    MessageBox.Show("Episode with this season/number already exists. Select edit on existing episode to make changes to it (if not visible try looking with ignored episodes filter).", "Already exists");
                    return;
                }

                show.Episodes.Add(editor.Results);
                Organization.Shows.Save();
            }
        }
Exemple #39
0
        /// <summary>
        /// Gets season/episode information from database
        /// </summary>
        /// <param name="show">Show to load episode information into</param>
        protected override bool DoUpdate(string mirror, Content content)
        {
            TvShow show = (TvShow)content;
            try
            {
                // Get show info from database
                string showInfoUrl = mirror + "/showinfo.php?key=" + this.API_KEY + "&sid=" + show.Id;
                WebClient webClient = new WebClient();
                string showInfo = webClient.DownloadString(showInfoUrl);

                // Create XML object from results
                XmlDocument seriesDoc = new XmlDocument();
                seriesDoc.InnerXml = showInfo;

                // Parse show info
                show.Overview = ParseShowInfo(seriesDoc.DocumentElement).Overview;

                // Get episode info from database
                string episodeListUrl = mirror + "/episode_list.php?key=" + this.API_KEY + "&sid=" + show.Id;
                webClient = new WebClient();
                string seriesList = webClient.DownloadString(episodeListUrl);

                // Create xml object with text from mirrors url
                seriesDoc = new XmlDocument();
                seriesDoc.InnerXml = seriesList;

                // Get root element and children
                XmlElement root = seriesDoc.DocumentElement;
                XmlNodeList nodes = root.ChildNodes;

                // Go through each node and parse out episodes
                foreach (XmlNode subNode in nodes)
                {
                    switch (subNode.Name.ToLower())
                    {
                        case "episodelist":
                            foreach (XmlNode seasonNode in subNode.ChildNodes)
                            {
                                if (seasonNode.Name.ToLower() == "season")
                                {
                                    string seasonNoStr = seasonNode.Attributes["no"].Value;
                                    int seasonNo;
                                    int.TryParse(seasonNoStr, out seasonNo);

                                    foreach (XmlNode epNode in seasonNode.ChildNodes)
                                    {
                                        TvEpisode ep = new TvEpisode(show);
                                        ep.Season = seasonNo;
                                        foreach (XmlNode epPropNode in epNode.ChildNodes)
                                            switch (epPropNode.Name.ToLower())
                                            {
                                                case "seasonnum": // episode number within season
                                                    int epNum;
                                                    int.TryParse(epPropNode.InnerText, out epNum);
                                                    ep.DatabaseNumber = epNum;
                                                    break;
                                                case "airdate":
                                                    DateTime airDate;
                                                    DateTime.TryParse(epPropNode.InnerText, out airDate);
                                                    ep.DatabaseAirDate = airDate;
                                                    break;
                                                case "title":
                                                    ep.DatabaseName = epPropNode.InnerText;
                                                    break;
                                                case "summary":
                                                    ep.DatabaseOverview = epPropNode.InnerText.Replace('\n', ' ');
                                                    break;
                                            }
                                        ep.InDatabase = true;

                                        // If episode already exists just update it, else add it
                                        TvEpisode existingMatch;
                                        if (show.FindEpisode(ep.Season, ep.DatabaseNumber, true, out existingMatch))
                                        {
                                            if (!existingMatch.PreventDatabaseUpdates)
                                            {
                                                existingMatch.DatabaseName = ep.DatabaseName;
                                                existingMatch.DatabaseAirDate = ep.DatabaseAirDate;
                                                existingMatch.DatabaseOverview = ep.DatabaseOverview;
                                                existingMatch.InDatabase = true;
                                            }
                                        }
                                        else
                                            show.Episodes.Add(ep);
                                    }
                                }

                            }
                            break;
                    }
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
Exemple #40
0
        /// <summary>
        /// Build file name for TV or movie file.
        /// </summary>
        /// <param name="movieName">Name of movie</param>
        /// <param name="episode1">First episode in file</param>
        /// <param name="episode2">Second episode in file</param>
        /// <param name="date">Date item was released</param>
        /// <param name="simplifyResults">File name simplifying results</param>
        /// <param name="differentiator"></param>
        /// <returns></returns>
        private string BuildFileName(string movieName, TvEpisode episode1, TvEpisode episode2, int year, FileHelper.SimplifyStringResults simplifyResults, string differentiator)
        {
            // Init file name
            string fileName = string.Empty;

            // Loop through each portion of format and add it to the file names
            foreach (FileNamePortion portion in this.Format)
            {
                // Get string value for current portion
                string value = portion.Header;
                switch (portion.Type)
                {
                    case FileWordType.MovieName:
                        value = movieName;
                        break;
                    case FileWordType.ShowName:
                        value = episode1.Show.DatabaseName;
                        break;
                    case FileWordType.EpisodeName:
                        value = BuildEpisodeName(episode1, episode2);
                        break;
                    case FileWordType.EpisodeNumber:
                        value = EpisodeFormat.BuildEpisodeString(episode1, episode2);
                        break;
                    case FileWordType.Year:
                        value = year.ToString();
                        break;
                    case FileWordType.FilePart:
                        if (!GetFileWord(simplifyResults, portion.Type, out value))
                            value = differentiator;
                        break;
                    default:
                        GetFileWord(simplifyResults, portion.Type, out value);
                        break;
                }

                // Add portion with header/footer and apply option
                if (!string.IsNullOrWhiteSpace(value))
                {
                    // Add header
                    fileName += portion.Header;

                    // Apply case options
                    switch (portion.CaseOption)
                    {
                        case CaseOptionType.None:
                            break;
                        case CaseOptionType.LowerCase:
                            value = value.ToLower();
                            break;
                        case CaseOptionType.UpperCase:
                            value = value.ToUpper();
                            break;
                    }

                    // Apply whitespace options
                    fileName += Regex.Replace(value, @"\s+", portion.Whitespace);

                    // Add footer
                    fileName += portion.Footer;
                }
            }

            // Return file name that was built
            return fileName;
        }
Exemple #41
0
 /// <summary>
 /// Find an episode from the show.
 /// </summary>
 /// <param name="seasonNumber">The season of the episode</param>
 /// <param name="episodeNumber">The number of the epsiode within the season</param>
 /// <param name="episode">The matched episode if one is found, else null</param>
 /// <returns>true if the episode was found, false otherwise</returns>
 public bool FindEpisode(int seasonNumber, int episodeNumber, bool databaseNum, out TvEpisode episode)
 {
     episode = null;
     foreach (TvEpisode ep in this.Episodes)
     {
         if (ep.Season == seasonNumber && ((ep.DisplayNumber == episodeNumber && !databaseNum) || (ep.DatabaseNumber == episodeNumber && databaseNum)))
         {
             episode = ep;
             return(true);
         }
     }
     return(false);
 }
Exemple #42
0
 /// <summary>
 /// Compares 2 content instances based on their Name property.
 /// </summary>
 /// <param name="x">The first movie.</param>
 /// <param name="y">The second movie.</param>
 /// <returns>The comparison results </returns>
 public static int CompareByAirDate(TvEpisode x, TvEpisode y)
 {
     if (x == null)
     {
         if (y == null)
             return 0;
         else
             return -1;
     }
     else
     {
         if (y == null)
             return 1;
         else
             return x.DisplayAirDate.CompareTo(y.DisplayAirDate);
     }
 }
Exemple #43
0
 /// <summary>
 /// Build full path of file for moving/copying TV episode file.
 /// </summary>
 /// <param name="episode1">Episode to build file path for</param>
 /// <param name="episode2">Second episode for double-episode files</param>
 /// <param name="extension">File extension for path</param>
 /// <returns>Episode file path</returns>
 public string BuildFilePath(TvEpisode episode1, TvEpisode episode2, string path)
 {
     // New season created to prevent exception if episode doesn't fall into a valid season
     return(this.Path + "\\" + episode1.SeasonName + "\\" + BuildFileName(episode1, episode2, path) + System.IO.Path.GetExtension(path).ToLower());
 }
        public TvEpisodeTorrent GetBestTvTorrent(TvEpisode episode)
        {
            List <TvEpisodeTorrent> availableTorrents = GetAvailableTvTorrents(episode);

            if (availableTorrents.Count == 0)
            {
                return(null);
            }

            Dictionary <TorrentQuality, TvEpisodeTorrent> qualityTorrents = new Dictionary <TorrentQuality, TvEpisodeTorrent>();

            foreach (TvEpisodeTorrent torrent in availableTorrents)
            {
                TorrentQuality quality = torrent.Quality;

                if (!qualityTorrents.ContainsKey(quality))
                {
                    qualityTorrents.Add(quality, null);
                }

                if (qualityTorrents[quality] == null)
                {
                    qualityTorrents[quality] = torrent;
                }
            }

            // Go through matches to find closest quality to preferred
            TorrentQuality closestQuality = TorrentQuality.Sd480p;

            if (qualityTorrents.ContainsKey(Settings.General.PreferredTorrentQuality))
            {
                closestQuality = Settings.General.PreferredTorrentQuality;
            }
            else
            {
                switch (Settings.General.PreferredTorrentQuality)
                {
                case TorrentQuality.Sd480p:
                    if (qualityTorrents.ContainsKey(TorrentQuality.Hd720p))
                    {
                        closestQuality = TorrentQuality.Hd720p;
                    }
                    else
                    {
                        closestQuality = TorrentQuality.Hd1080p;
                    }
                    break;

                case TorrentQuality.Hd720p:
                    if (qualityTorrents.ContainsKey(TorrentQuality.Sd480p))
                    {
                        closestQuality = TorrentQuality.Sd480p;
                    }
                    else
                    {
                        closestQuality = TorrentQuality.Hd1080p;
                    }
                    break;

                case TorrentQuality.Hd1080p:
                    if (qualityTorrents.ContainsKey(TorrentQuality.Hd720p))
                    {
                        closestQuality = TorrentQuality.Hd720p;
                    }
                    else
                    {
                        closestQuality = TorrentQuality.Sd480p;
                    }
                    break;

                default:
                    throw new Exception("Unknown torrent quality");
                }
            }

            TvEpisodeTorrent closestTorrent = qualityTorrents[closestQuality];

            UpdateTorrentLinks(closestTorrent);

            return(closestTorrent);
        }
        /// <summary>
        /// Run through all TV shows all looks for episodes that may need to be renamed and for missing episodes.
        /// For missing episodes it attempts to match them to files from the search directories.
        /// </summary>
        /// <param name="shows">Shows to scan</param>
        /// <param name="queuedItems">Items currently in queue (to be skipped)</param>
        /// <returns></returns>
        public List <OrgItem> RunScan(List <Content> shows, List <OrgItem> queuedItems, bool fast)
        {
            // Set running flag
            scanRunning     = true;
            cancelRequested = false;

            // Do directory check on all directories (to look for missing episodes)
            while (!TvItemInScanDirHelper.Initialized)
            {
                Thread.Sleep(100);
            }

            List <OrgItem> directoryItems = TvItemInScanDirHelper.Items;

            // Initialiaze scan items
            List <OrgItem> missingCheckItem = new List <OrgItem>();

            // Initialize item numbers
            int number = 0;

            double progressPerShow = 1D / shows.Count * 100D;

            // Go through each show
            for (int i = 0; i < shows.Count; i++)
            {
                TvShow show = (TvShow)shows[i];

                if (cancelRequested)
                {
                    break;
                }

                double showsProgress = (double)i * progressPerShow;
                OnProgressChange(ScanProcess.TvMissing, shows[i].DatabaseName, (int)Math.Round(showsProgress));

                double progressPerEp = 1D / show.Episodes.Count * progressPerShow;

                // Go through missing episodes
                for (int j = 0; j < show.Episodes.Count; j++)
                {
                    // Get episode
                    TvEpisode ep = show.Episodes[j];

                    // Update progress
                    OnProgressChange(ScanProcess.TvMissing, shows[i].DatabaseName, (int)Math.Round(showsProgress + j * progressPerEp));

                    // Check for cancellation
                    if (cancelRequested)
                    {
                        break;
                    }

                    // Skipped ignored episodes
                    if (ep.Ignored || !show.DoMissingCheck)
                    {
                        continue;
                    }

                    // Init found flag
                    bool found = false;

                    // Check if episode is missing
                    if (ep.Missing == MissingStatus.Missing || ep.Missing == MissingStatus.InScanDirectory)
                    {
                        // Check directory item for episode
                        foreach (OrgItem item in directoryItems)
                        {
                            if ((item.Action == OrgAction.Move || item.Action == OrgAction.Copy) && item.TvEpisode != null && item.TvEpisode.Show.DatabaseName == show.DatabaseName)
                            {
                                // Only add item for first part of multi-part file
                                if (ep.Equals(item.TvEpisode))
                                {
                                    OrgItem newItem = new OrgItem(OrgStatus.Found, item.Action, item.SourcePath, item.DestinationPath, ep, item.TvEpisode2, FileCategory.TvVideo, item.ScanDirectory);
                                    newItem.Enable = true;
                                    newItem.Number = number++;
                                    if (!show.DoMissingCheck)
                                    {
                                        newItem.Category = FileCategory.Ignored;
                                    }
                                    missingCheckItem.Add(newItem);
                                    found = true;
                                    break;
                                }
                                else if (ep.Equals(item.TvEpisode2))
                                {
                                    found = true;
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        continue;
                    }

                    // Add empty item for missing
                    if (!found && ep.Aired && show.DoMissingCheck)
                    {
                        OrgItem          newItem;
                        TvEpisodeTorrent ezTvEpisode = TvTorrentHelper.GetEpisodeTorrent(ep);
                        if (ezTvEpisode != null)
                        {
                            newItem = new OrgItem(OrgStatus.Missing, OrgAction.Torrent, ep, null, FileCategory.TvVideo, null);
                            newItem.BuildDestination();
                        }
                        else
                        {
                            newItem = new OrgItem(OrgStatus.Missing, OrgAction.None, ep, null, FileCategory.TvVideo, null);
                        }

                        newItem.Number = number++;
                        missingCheckItem.Add(newItem);
                    }
                }
            }

            // Update progress
            OnProgressChange(ScanProcess.TvMissing, string.Empty, 100);

            // Clear flags
            scanRunning = false;

            // Return results
            return(missingCheckItem);
        }
        public override List <TvEpisodeTorrent> GetAvailableTvTorrents(TvEpisode episode)
        {
            // Download show episodes page
            string showPageUrl = BASE_URL + "/torrents.php?search=" + episode.BuildEpString().Replace(" ", "+");

            Console.WriteLine("RARBG Pre  " + DateTime.Now.ToString());
            Limiter.DoWait();
            Console.WriteLine("RARBG Post  " + DateTime.Now.ToString());

            WebClient client = new WebClient();

            client.Headers.Add("User-Agent: Other");
            string data = client.DownloadString(showPageUrl);

            Regex baseRegex = new Regex(@"<tr\s+class=.lista2.>\s*(<td.*?/td>)\s*(<td.*?/td>)\s*(<td.*?/td>)\s*(<td.*?/td>)\s*(<td.*?/td>)\s*(<td.*?/td>)\s*(<td.*?/td>)\s*</tr>");

            Regex titleRegex = new Regex(@"title=""([^""]+)""");
            Regex urlRegex   = new Regex("href=\"(/torrent/[^\"]+)\"");

            Regex sizeRegex = new Regex(@">(\S+)\s+MB<");

            MatchCollection matches = baseRegex.Matches(data);

            List <TvEpisodeTorrent> torrents = new List <TvEpisodeTorrent>();

            foreach (Match match in matches)
            {
                string name;
                Match  titleMatch = titleRegex.Match(match.Groups[2].Value);
                if (titleMatch.Success)
                {
                    name = titleMatch.Groups[1].Value;
                }
                else
                {
                    continue;
                }

                string pageUrl;
                Match  urlMatch = urlRegex.Match(match.Groups[2].Value);
                if (urlMatch.Success)
                {
                    pageUrl = BASE_URL + urlMatch.Groups[1].Value;
                }
                else
                {
                    continue;
                }

                MatchCollection showMatches = episode.Show.MatchFileToContent(name);
                bool            matchShow   = showMatches != null && showMatches.Count > 0;

                int season, ep1, ep2;
                if (matchShow && FileHelper.GetEpisodeInfo(name, episode.Show.DisplayName, out season, out ep1, out ep2, true) && episode.Season == season && episode.DisplayNumber == ep1)
                {
                    // Don't want to get torrent with a bunch of episodes (double is okay)
                    if (ep2 > 0 && ep2 - ep1 > 1)
                    {
                        continue;
                    }

                    TorrentQuality quality = TorrentQuality.Sd480p;
                    if (name.ToLower().Contains("720p"))
                    {
                        quality = TorrentQuality.Hd720p;
                    }
                    else if (name.ToLower().Contains("1080p"))
                    {
                        quality = TorrentQuality.Hd1080p;
                    }

                    TvEpisodeTorrent torrentEp = new TvEpisodeTorrent();
                    torrentEp.Url      = showPageUrl;
                    torrentEp.Season   = season;
                    torrentEp.Episode  = ep1;
                    torrentEp.Episode2 = ep2;
                    torrentEp.Quality  = quality;
                    torrentEp.Title    = name;
                    torrentEp.PageUrl  = pageUrl;

                    torrents.Add(torrentEp);
                }
            }

            return(torrents);
        }
Exemple #47
0
 /// <summary>
 /// Constructor for cloning instance.
 /// </summary>
 /// <param name="episode">Instance to clone</param>
 public TvEpisode(TvEpisode episode)
 {
     this.Clone(episode);
 }
Exemple #48
0
        public static async Task <TvEpisodeTorrent> GetEpisodeTorrentAsync(TvEpisode episode)
        {
            TvEpisodeTorrent result = await Task.Run(() => GetEpisodeTorrent(episode));

            return(result);
        }
Exemple #49
0
 /// <summary>
 /// Updates this instance with information from another instance
 /// </summary>
 /// <param name="episode"></param>
 public void Clone(TvEpisode episode)
 {
     this.UseDatabaseName = episode.UseDatabaseName;
     this.UserName = episode.UserName;
     this.DatabaseName = episode.DatabaseName;
     this.Show = episode.Show;
     this.Season = episode.Season;
     this.UseDatabaseNumber = episode.UseDatabaseNumber;
     this.UserNumber = episode.UserNumber;
     this.DatabaseNumber = episode.DatabaseNumber;
     this.DatabaseDvdNumber = episode.DatabaseDvdNumber;
     this.UseDatabaseAirDate = episode.UseDatabaseAirDate;
     this.DatabaseAirDate = episode.DatabaseAirDate;
     this.UserAirDate = episode.UserAirDate;
     this.File = new TvFile(episode.File);
     this.Ignored = episode.Ignored;
     this.InDatabase = episode.InDatabase;
     this.Missing = episode.Missing;
     this.UseDatabaseOverview = episode.UseDatabaseOverview;
     this.DatabaseOverview = episode.DatabaseOverview;
     this.UserOverview = episode.UserOverview;
     this.Watched = episode.Watched;
     this.PreventDatabaseUpdates = episode.PreventDatabaseUpdates;
 }
Exemple #50
0
 /// <summary>
 /// Build the file name string for a given episode
 /// </summary>
 /// <param name="episode1">Episode to build file name for</param>
 /// <param name="episode2">Second episode for double-episode files</param>
 /// <returns>Episode file name string</returns>
 public string BuildFileName(TvEpisode episode1, TvEpisode episode2, string path)
 {
     return Settings.TvFileFormat.BuildTvFileName(episode1, episode2, path);
 }
 /// <summary>
 /// Get available torrents for episode
 /// </summary>
 /// <returns></returns>
 public virtual List <TvEpisodeTorrent> GetAvailableTvTorrents(TvEpisode episode)
 {
     throw new NotImplementedException();
 }
Exemple #52
0
 /// <summary>
 /// Build full path of file for moving/copying TV episode file.
 /// </summary>
 /// <param name="episode1">Episode to build file path for</param>
 /// <param name="episode2">Second episode for double-episode files</param>
 /// <param name="extension">File extension for path</param>
 /// <returns>Episode file path</returns>
 public string BuildFilePath(TvEpisode episode1, TvEpisode episode2, string path)
 {
     // New season created to prevent exception if episode doesn't fall into a valid season
     return this.Path + "\\" + episode1.SeasonName + "\\" + BuildFileName(episode1, episode2, path) + System.IO.Path.GetExtension(path).ToLower();
 }
        /// <summary>
        /// Runs an episode through filter.
        /// </summary>
        /// <param name="ep">The episode to filter</param>
        /// <returns>True if the episode makes it through filter</returns>
        public bool FilterEpisode(TvEpisode ep)
        {
            if (ep.Ignored && this.Type != FilterType.Ignored)
            {
                return(false);
            }

            switch (this.Type)
            {
            case FilterType.All:
                return(true);

            case FilterType.Regular:
                if (ep.Season > 0)
                {
                    return(true);
                }
                break;

            case FilterType.Ignored:
                return(ep.Ignored);

            case FilterType.Located:
                if (ep.Missing != MissingStatus.Missing)
                {
                    return(true);
                }
                break;

            case FilterType.Missing:
                if (ep.Season > 0 && ep.Missing == MissingStatus.Missing && ep.Aired)
                {
                    return(true);
                }
                break;

            case FilterType.InScanDir:
                if (ep.Missing == MissingStatus.InScanDirectory)
                {
                    return(true);
                }
                break;

            case FilterType.Season:
                if (ep.Season == this.Season)
                {
                    return(true);
                }
                break;

            case FilterType.Unaired:
                if (!ep.Aired)
                {
                    return(true);
                }
                break;

            default:
                throw new Exception("Unknown filter type!");
            }

            return(false);
        }
Exemple #54
0
        /// <summary>
        /// Copies properties from another instance into this instance.
        /// </summary>
        /// <param name="content">Instance to copy properties from</param>
        /// <param name="replacePath">Whether path related properties should be cloned or not</param>
        /// <param name="handleEmptyPath">Whether to build path if one being cloned is empty</param>
        public override void CloneAndHandlePath(Content content, bool replacePath, bool handleEmptyPath = true)
        {
            if (!(content is TvShow))
                throw new Exception("Content must be TvShow");
            TvShow show = content as TvShow;

            bool updateRequired = show.Id != this.Id;
            base.CloneAndHandlePath(show, replacePath, handleEmptyPath);

            this.IncludeInSchedule = show.IncludeInSchedule;
            this.DoMissingCheck = show.DoMissingCheck;
            this.DvdEpisodeOrder = show.DvdEpisodeOrder;

            if (updateRequired)
                this.UpdateInfoFromDatabase();

            // TODO: this is a hack
            App.Current.Dispatcher.BeginInvoke((Action)delegate
            {
                this.Episodes.Clear();
                foreach (TvEpisode episode in show.Episodes)
                {
                    TvEpisode copyEp = new TvEpisode(episode);
                    this.Episodes.Add(copyEp);
                    copyEp.Show = this;
                }
            });
            this.AlternativeNameMatches = new ObservableCollection<string>();
            foreach (string altName in show.AlternativeNameMatches)
                this.AlternativeNameMatches.Add(altName);
        }
        /// <summary>
        /// Runs an episode through filter.
        /// </summary>
        /// <param name="ep">The episode to filter</param>
        /// <returns>True if the episode makes it through filter</returns>
        public bool FilterEpisode(TvEpisode ep)
        {
            if (ep.Ignored && this.Type != FilterType.Ignored)
                return false;

            switch (this.Type)
            {
                case FilterType.All:
                    return true;
                case FilterType.Regular:
                    if (ep.Season > 0)
                        return true;
                    break;
                case FilterType.Ignored:
                    return ep.Ignored;
                case FilterType.Located:
                    if (ep.Missing != MissingStatus.Missing)
                        return true;
                    break;
                case FilterType.Missing:
                    if (ep.Season > 0 && ep.Missing == MissingStatus.Missing && ep.Aired)
                        return true;
                    break;
                case FilterType.InScanDir:
                     if (ep.Missing == MissingStatus.InScanDirectory)
                        return true;
                    break;
                case FilterType.Season:
                    if (ep.Season == this.Season)
                        return true;
                    break;
                case FilterType.Unaired:
                    if (!ep.Aired)
                        return true;
                    break;
                default:
                    throw new Exception("Unknown filter type!");
            }

            return false;
        }
        public override List<TvEpisodeTorrent> GetAvailableTvTorrents(TvEpisode episode)
        {
            // Download show episodes page
            string showPageUrl = BASE_URL + "/torrents.php?search=" + episode.BuildEpString().Replace(" ", "+");
            WebClient client = new WebClient();
            client.Headers.Add("User-Agent: Other");
            string data = client.DownloadString(showPageUrl);

            Regex baseRegex = new Regex(@"<tr\s+class=.lista2.>\s*(<td.*?/td>)\s*(<td.*?/td>)\s*(<td.*?/td>)\s*(<td.*?/td>)\s*(<td.*?/td>)\s*(<td.*?/td>)\s*(<td.*?/td>)\s*</tr>");

            Regex titleRegex = new Regex(@"title=""([^""]+)""");
            Regex urlRegex = new Regex("href=\"(/torrent/[^\"]+)\"");

            Regex sizeRegex = new Regex(@">(\S+)\s+MB<");

            MatchCollection matches = baseRegex.Matches(data);

            List<TvEpisodeTorrent> torrents = new List<TvEpisodeTorrent>();
            foreach (Match match in matches)
            {
                string name;
                Match titleMatch = titleRegex.Match(match.Groups[2].Value);
                if (titleMatch.Success)
                    name = titleMatch.Groups[1].Value;
                else
                    continue;

                string pageUrl;
                Match urlMatch = urlRegex.Match(match.Groups[2].Value);
                if (urlMatch.Success)
                    pageUrl = BASE_URL + urlMatch.Groups[1].Value;
                else
                    continue;

                MatchCollection showMatches = episode.Show.MatchFileToContent(name);
                bool matchShow = showMatches != null && showMatches.Count > 0;

                int season, ep1, ep2;
                if (matchShow && FileHelper.GetEpisodeInfo(name, episode.Show.DisplayName, out season, out ep1, out ep2, true) && episode.Season == season && episode.DisplayNumber == ep1)
                {
                    // Don't want to get torrent with a bunch of episodes (double is okay)
                    if (ep2 > 0 && ep2 - ep1 > 1)
                        continue;

                    TorrentQuality quality = TorrentQuality.Sd480p;
                    if (name.ToLower().Contains("720p"))
                        quality = TorrentQuality.Hd720p;
                    else if (name.ToLower().Contains("1080p"))
                        quality = TorrentQuality.Hd1080p;

                    TvEpisodeTorrent torrentEp = new TvEpisodeTorrent();
                    torrentEp.Url = showPageUrl;
                    torrentEp.Season = season;
                    torrentEp.Episode = ep1;
                    torrentEp.Episode2 = ep2;
                    torrentEp.Quality = quality;
                    torrentEp.Title = name;
                    torrentEp.PageUrl = pageUrl;

                    torrents.Add(torrentEp);
                }
            }

            return torrents;
        }