예제 #1
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);
        }
예제 #2
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);
        }
예제 #3
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);
        }
예제 #4
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);
            }
        }