public ContentEditorWindowViewModel(Content content)
 {
     originalContent = content;
     controlViewModel = new ContentEditorControlViewModel(content, false);
     this.ResultsOk = false;
     this.Content.PropertyChanged += Content_PropertyChanged;
 }
        public ContentEditorWindow(Content content)
        {
            InitializeComponent();

            ContentEditorWindowViewModel vm = new ContentEditorWindowViewModel(content);
            vm.ResultsSet += vm_ResultsSet;
            this.DataContext = vm;
        }
示例#3
0
 /// <summary>
 /// Constructor for file from content folder (movie or tv)
 /// </summary>
 /// <param name="path">file's path</param>
 /// <param name="copy">whether file is allowed to be copied</param>
 /// <param name="allowDelete">whether file is allowed to be deleted</param>
 /// <param name="folder">content folder file belongs to</param>
 public OrgPath(string path, bool copy, bool allowDelete, ContentRootFolder folder, Content content)
 {
     this.Path = path;
     this.Copy = copy;
     this.AllowDelete = allowDelete;
     this.RootFolder = folder;
     this.Content = content;
     this.SimilarTo = -1;
 }
        public ContentEditorControlViewModel(Content content, bool directEditing)
        {
            this.ResultsOk = false;

            // Edit item directly or through clone
            if (directEditing)
                this.Content = content;
            else
                // Clone content to allow it to be edited, but cancelled
                switch (content.ContentType)
                {
                    case ContentType.Movie:
                        this.Content = new Movie(content as Movie);
                        break;
                    case ContentType.TvShow:
                        this.Content = new TvShow(content as TvShow);
                        break;
                    default:
                        throw new Exception("Unknown content type");
                }

            if (this.Content.Id == Content.UNKNOWN_ID && string.IsNullOrEmpty(this.Content.UserName))
            {
                this.DatabaseStatusVisibility = Visibility.Collapsed;
                this.DatabaseSearchVisibility = Visibility.Visible;
            }

            // Get databases for content type
            this.Databases = new ObservableCollection<string>();
            switch (this.Content.ContentType)
            {
                case ContentType.Movie:
                    foreach (MovieDatabaseSelection selection in Enum.GetValues(typeof(MovieDatabaseSelection)))
                        this.Databases.Add(selection.Description());
                    this.SelectedSearchDatabaseIndex = (int)Settings.General.DefaultMovieDatabase;
                    break;
                case ContentType.TvShow:
                    foreach (TvDataBaseSelection selection in Enum.GetValues(typeof(TvDataBaseSelection)))
                        this.Databases.Add(selection.Description());
                    this.SelectedSearchDatabaseIndex = (int)Settings.General.DefaultTvDatabase;
                    break;
                default:
                    throw new Exception("Unknown content type");
            }

            this.SearchResults = new ObservableCollection<Content>();
            this.SearchString = System.IO.Path.GetFileName(content.Path);

            searchWorker = new BackgroundWorker();
            searchWorker.WorkerSupportsCancellation = true;
            searchWorker.DoWork += searchWorker_DoWork;
            searchWorker.RunWorkerCompleted += searchWorker_RunWorkerCompleted;

            searchUpdateTimer = new System.Timers.Timer(500);
            searchUpdateTimer.Elapsed += searchUpdateTimer_Elapsed;
        }
        public ContentControlViewModel(Content content)
        {
            this.Content = content;

            if (Content is TvShow)
            {
                TvShow show = this.Content as TvShow;
                this.EpisodesModel = new EpisodeCollectionControlViewModel(show.Episodes, show);
                this.PlayVisibility = Visibility.Collapsed;
            }
            else
                this.PlayVisibility = Visibility.Visible;
        }
示例#6
0
        /// <summary>
        /// Check if a root folder contains a specific content instance. Called
        /// recursively on child root folders.
        /// </summary>
        /// <param name="content">The movie to check for</param>
        /// <returns>Whether the movie is contained in the folder</returns>
        public bool ContainsContent(Content content, bool recursive)
        {
            // Check if movie content folder matches
            if (content.RootFolder == this.FullPath)
                return true;
            else if (recursive)
                // Recursion on sub-folders
                foreach (ContentRootFolder subFolder in this.ChildFolders)
                    if (subFolder.ContainsContent(content, recursive))
                        return true;

            // No match
            return false;
        }
示例#7
0
        /// <summary>
        /// Puts a single content item through filtering
        /// </summary>
        /// <param name="content">Content to filter</param>
        /// <param name="genre">Genre content must belong to</param>
        /// <param name="yearFilter">Enable for year filter</param>
        /// <param name="minYear">Minimum for year filter</param>
        /// <param name="maxYear">Maximum for year filter</param>
        /// <param name="nameFilter">String that must be contained in content name - empty string disables filter</param>
        /// <returns></returns>
        public bool ApplyContentFilter(Content content, bool genreEnable, GenreCollection genre, bool yearFilter, int minYear, int maxYear, string nameFilter)
        {
            // Apply genre filter
            bool genreMatch = !genreEnable;
            if (content.DatabaseGenres != null && !genreMatch)
                foreach (string contentGenre in content.DatabaseGenres)
                    if (genre.Contains(contentGenre))
                    {
                        genreMatch = true;
                        break;
                    }

            // Apply year filter
            bool yearMatch = !yearFilter || (content.DatabaseYear >= minYear && content.DatabaseYear <= maxYear);

            // Apply text filter
            bool nameMatch = string.IsNullOrEmpty(nameFilter) || content.DatabaseName.ToLower().Contains(nameFilter.ToLower());

            bool test = genreMatch && yearMatch && nameMatch;
            if (!test)
                test = true;

            // Check if movie is in the folder
            return genreMatch && yearMatch && nameMatch;
        }
示例#8
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);
        }
示例#9
0
 /// <summary>
 /// Performs update of content information from database. Should be overriden!
 /// </summary>
 /// <param name="show">Show instance to update</param>
 /// <returns>Updated show instance</returns>
 protected virtual bool DoUpdate(string mirror, Content content)
 {
     throw new NotImplementedException();
 }
示例#10
0
        /// <summary>
        /// Compares 2 movie instances based on their Path property.
        /// </summary>
        /// <param name="x">The first movie.</param>
        /// <param name="y">The second movie.</param>
        /// <returns>The comparison results </returns>
        public static int CompareByPath(Content x, Content y)
        {
            int sortResult;
            if (x == null)
            {
                if (y == null)
                    sortResult = 0;
                else
                    sortResult = -1;
            }
            else
            {
                if (y == null)
                    sortResult = 1;
                else
                    sortResult = x.Path.CompareTo(y.Path);
            }

            return SetSort(sortResult);
        }
示例#11
0
 /// <summary>
 /// Gets TV folder that is set as default
 /// </summary>
 /// <returns></returns>
 public static bool GetTvFolderForContent(Content content, out ContentRootFolder rootFolder)
 {
     rootFolder = TvFolders.GetFolderForContent(content);
     return rootFolder != null;
 }
示例#12
0
        /// <summary>
        /// Match a folder path to content in database
        /// </summary>
        /// <param name="rootFolder">Root folder content will belong to</param>
        /// <param name="path">Current path of content</param>
        /// <returns>Content from database that was matched, null if no match</returns>
        protected bool PathMatch(string rootFolder, string path, bool threaded, bool fast, out Content match, Content knownContent)
        {
            // Get folder name from full path
            string[] dirs = path.Split('\\');
            string endDir = dirs[dirs.Length - 1];

            // Do match
            return ContentMatch(endDir, rootFolder, path, fast, threaded, out match, knownContent);
        }
示例#13
0
 /// <summary>
 /// Constructor for creating instance from base class
 /// </summary>
 /// <param name="content"></param>
 public Movie(Content content)
     : this()
 {
     base.CloneAndHandlePath(content, true);
 }
        public bool Match(Content content)
        {
            string prop;
            switch (this.Property)
            {
                case ContentRootFolderMatchRuleProperty.Name:
                    prop = content.DisplayName;
                    break;
                case ContentRootFolderMatchRuleProperty.Genre:
                    if (content.DisplayGenres.Count == 0)
                        return false;
                    prop = content.DisplayGenres[0];
                    break;
                case ContentRootFolderMatchRuleProperty.Year:
                    prop = content.DisplayYear.ToString();
                    break;
                default:
                    throw new Exception("Unknown match rule property.");
            }

            string propLower = prop.ToLower();
            string valueLower = this.Value.ToLower();

            switch (this.Type)
            {
                case ContentRootFolderMatchRuleType.Equals:
                    return propLower == valueLower;
                case ContentRootFolderMatchRuleType.Contains:
                    return propLower.Contains(valueLower);
                case ContentRootFolderMatchRuleType.StartsWith:
                    return propLower.StartsWith(valueLower);
                case ContentRootFolderMatchRuleType.EndsWith:
                    return propLower.EndsWith(valueLower);
                case ContentRootFolderMatchRuleType.RegularExpression:
                    Regex re = new Regex(this.Value, RegexOptions.IgnoreCase);
                    return re.IsMatch(prop);
                case ContentRootFolderMatchRuleType.Between:
                    Regex yearsRegex = new Regex(@"^(\d{4}).*(\d{4})$");
                    Match yearMatch = yearsRegex.Match(this.Value);
                    if (yearMatch.Success)
                    {
                        int year1 = 0, year2 = 0;
                        int.TryParse(yearMatch.Groups[1].Value, out year1);
                        int.TryParse(yearMatch.Groups[1].Value, out year2);

                        int minYear = Math.Min(year1, year2);
                        int maxYear = Math.Min(year1, year2);

                        return content.DisplayYear >= minYear && content.DisplayYear <= maxYear;
                    }
                    return false;
                default:
                    throw new Exception("Unknown match rule criteria.");
            }
        }
示例#15
0
 /// <summary>
 /// Constructor for cloning instance
 /// </summary>
 /// <param name="content">Instance to clone</param>
 protected Content(Content content)
     : this()
 {
     CloneAndHandlePath(content, true);
 }
示例#16
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 virtual void CloneAndHandlePath(Content content, bool replacePath, bool handleEmptyPath = true)
        {
            this.ContentType = content.ContentType;
            this.UserName = content.UserName;
            this.UseDatabaseName = content.UseDatabaseName;
            this.DatabaseName = content.DatabaseName;
            this.DatabaseSelection = content.DatabaseSelection;
            this.UserYear = content.UserYear;
            this.UseDatabaseYear = content.UseDatabaseYear;
            this.DatabaseYear = content.DatabaseYear;
            this.Overview = content.Overview;
            this.UseDatabaseGenres = content.UseDatabaseGenres;
            this.DatabaseGenres = new GenreCollection(content.DatabaseGenres);
            this.UserGenres = new GenreCollection(content.UserGenres);
            this.Found = content.Found;

            if (replacePath)
            {
                if (handleEmptyPath)
                {
                    if (!string.IsNullOrEmpty(content.RootFolder))
                        this.RootFolder = content.RootFolder;

                    if (!string.IsNullOrEmpty(content.Path) && content.RootFolder != content.Path)
                        this.Path = content.Path;
                    else
                        this.Path = this.BuildFolderPath();
                }
                else
                {
                    this.RootFolder = content.RootFolder;
                    this.Path = content.Path;
                }
            }

            this.Id = content.Id;
            this.Watched = content.Watched;
            this.DoRenaming = content.DoRenaming;
            this.LastUpdated = content.LastUpdated;
        }
示例#17
0
        /// <summary>
        /// Compares 2 movie instances based on their Year property.
        /// </summary>
        /// <param name="x">The first movie.</param>
        /// <param name="y">The second movie.</param>
        /// <returns>The comparison results </returns>
        public static int CompareByYear(Content x, Content y)
        {
            int sortResult;
            if (x == null)
            {
                if (y == null)
                    sortResult = 0;
                else
                    sortResult = 1;
            }
            else
            {
                if (y == null)
                    sortResult = -1;
                else
                    sortResult = y.DatabaseYear.CompareTo(x.DatabaseYear);
            }

            return SetSort(sortResult);
        }
示例#18
0
        /// <summary>
        /// Updates movie instance properties from database
        /// </summary>
        /// <param name="baseMovie">Movie to update</param>
        /// <returns></returns>
        protected override bool DoUpdate(string mirror, Content content)
        {
            try
            {
                // Get movie info from database
                JsonNode searchNode = GetJsonRequest(mirror, null, "movie/" + content.Id.ToString());

                // Parse info into movie instance
                ParseMovieResult((Movie)content, searchNode.ChildNodes[0]);
                content.LastUpdated = DateTime.Now;
                return true;
            }
            catch
            {
                return false;
            }
        }
示例#19
0
            /// <summary>
            /// Get search match with lowest modification to search string
            /// </summary>
            /// <param name="status">Search status instance</param>
            /// <param name="lowestModsMatchStrLen">Length of best result's content name</param>
            /// <param name="results">Best resulting content</param>
            /// <returns>Whether a valid content match result was found</returns>
            public bool GetSearchResultWithLowestMods(out ContentSearchMod modsOnResultsSearch, out Content results)
            {
                int lowestModsMatchStrLen = 0;
                modsOnResultsSearch = ContentSearchMod.All;

                switch (this.ContentType)
                {
                    case ContentType.Movie:
                        results = new Movie();
                        break;
                    case ContentType.TvShow:
                        results = new TvShow();
                        break;
                    default:
                        throw new Exception("Unknown content type");
                }

                // Use match with lowest amount of modification made to search string and longest length (I think this is the most likely to the content we actually want to match to)
                for (int i = 0; i < this.matches.Length; i++)
                    if (this.matches[i] != null)
                        for (int j = 0; j < this.matches[i].Count; j++)
                        {
                            if (this.matches[i][j].Mods < modsOnResultsSearch || (this.matches[i][j].Mods == modsOnResultsSearch && this.matches[i][j].MatchedString.Length > lowestModsMatchStrLen))
                            {
                                results = this.matches[i][j].Content;
                                modsOnResultsSearch = this.matches[i][j].Mods;
                                lowestModsMatchStrLen = this.matches[i][j].MatchedString.Length;
                            }

                        }
                return !string.IsNullOrWhiteSpace(results.DatabaseName);
            }
示例#20
0
 /// <summary>
 /// Constructor for content folder move item.
 /// </summary>
 /// <param name="action">action to be performed</param>
 /// <param name="sourceFile">the source path</param>
 /// <param name="category">file's category</param>
 /// <param name="movie">Movie object related to file</param>
 /// <param name="destination">destination path</param>
 /// <param name="scanDir">path to content folder of movie</param>
 public OrgItem(OrgAction action, string sourceFile, Content content, string destination)
     : this()
 {
     this.Progress = 0;
     this.Action = action;
     this.SourcePath = sourceFile;
     if (content is Movie)
         this.Movie = content as Movie;
     else
         this.TvEpisode = new TvEpisode(content as TvShow);
     this.DestinationPath = destination;
     this.Category = FileCategory.Folder;
     this.Enable = false;
     this.Number = 0;
 }
示例#21
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;
            }
        }
示例#22
0
 /// <summary>
 /// Gets TV folder that is set as default
 /// </summary>
 /// <returns></returns>
 public static bool GetTvFolderForContent(Content content, out ContentRootFolder rootFolder)
 {
     rootFolder = TvFolders.GetFolderForContent(content);
     return(rootFolder != null);
 }
示例#23
0
        /// <summary>
        /// Compares 2 movie instances based on their Genre property.
        /// </summary>
        /// <param name="x">The first movie.</param>
        /// <param name="y">The second movie.</param>
        /// <returns>The comparison results </returns>
        public static int CompareByGenre(Content x, Content y)
        {
            int sortResult;
            if (x == null)
            {
                if (y == null)
                    sortResult = 0;
                else
                    sortResult = -1;
            }
            else
            {
                if (y == null)
                    sortResult = 1;
                else
                {
                    string genreX = string.Empty, genreY = string.Empty;
                    if (x.DatabaseGenres != null && x.DatabaseGenres.Count > 0)
                        genreX = x.DatabaseGenres[0].ToString();
                    if (y.DatabaseGenres != null && y.DatabaseGenres.Count > 0)
                        genreY = y.DatabaseGenres[0].ToString();

                    sortResult = genreX.CompareTo(genreY);
                }
            }

            return SetSort(sortResult);
        }
示例#24
0
        /// <summary>
        /// Search database for content and find a match from results.
        /// </summary>
        /// <param name="search">Search string to match content to</param>
        /// <param name="folderPath">Path of folder containing content</param>
        /// <param name="rootFolder">Root folder containing content folder</param>
        /// <param name="year">Year to match to content</param>
        /// <param name="result">resulting match found from search</param>
        /// <returns>whether match was successful</returns>
        private bool DoMatch(string search, string folderPath, string rootFolder, int year, ContentSearchMod baseMods, out List<SearchResult> matches, Content knownContent)
        {
            /// Debug notification
            OnDebugNotificationd("Performing database search for: " + search);

            // Search for content
            List<Content> searchResults;
            if (knownContent == null)
                searchResults = PerformSearch(search, false);
            else
                searchResults = new List<Content>() { knownContent };

            // Initialize resutls
            matches = new List<SearchResult>();

            // Go through results
            if (searchResults != null)
                foreach (Content searchResult in searchResults)
                {
                    OnDebugNotificationd("Attempting to match to database entry: " + searchResult);

                    SearchResult result = new SearchResult();
                    result.Mods = baseMods;

                    // Verify year in result matches year from folder (if any)
                    if (year != -1 && Math.Abs(year - searchResult.DatabaseYear) > 2)
                        continue;

                    // Check if search string match results string
                    string simplifiedSearch = FileHelper.SimplifyFileName(search);
                    string dbContentName = FileHelper.SimplifyFileName(searchResult.DatabaseName);

                    bool theAddedToMatch;
                    bool singleLetterDiff;

                    // Try basic match
                    bool match = FileHelper.CompareStrings(simplifiedSearch, dbContentName, out theAddedToMatch, out singleLetterDiff);
                    result.MatchedString = simplifiedSearch;

                    // Try match with year removed
                    if (!match)
                    {
                        simplifiedSearch = FileHelper.SimplifyFileName(search, true, true, false);
                        dbContentName = FileHelper.SimplifyFileName(searchResult.DatabaseName, true, true, false);
                        match = FileHelper.CompareStrings(simplifiedSearch, dbContentName, out theAddedToMatch, out singleLetterDiff);
                        result.MatchedString = simplifiedSearch;
                    }

                    // Try match with country removed
                    if (!match)
                    {
                        simplifiedSearch = FileHelper.SimplifyFileName(search, true, true, true);
                        dbContentName = FileHelper.SimplifyFileName(searchResult.DatabaseName, true, true, true);
                        match = FileHelper.CompareStrings(simplifiedSearch, dbContentName, out theAddedToMatch, out singleLetterDiff);
                        if (match)
                            result.Mods |= ContentSearchMod.WordsRemoved;
                        result.MatchedString = simplifiedSearch;
                    }

                    // Try match with spaces removed
                    if (!match)
                    {
                        string dirNoSpc = simplifiedSearch.Replace(" ", "");
                        string nameNoSpc = dbContentName.Replace(" ", "");
                        match = FileHelper.CompareStrings(dirNoSpc, nameNoSpc, out theAddedToMatch, out singleLetterDiff);
                        result.MatchedString = simplifiedSearch;
                        if (match)
                            result.Mods |= ContentSearchMod.SpaceRemoved;
                    }

                    // Try match with year added to content name
                    if (!match)
                    {
                        simplifiedSearch = FileHelper.SimplifyFileName(search);
                        dbContentName = FileHelper.SimplifyFileName(searchResult.DatabaseName + " " + searchResult.DatabaseYear.ToString());
                        match = FileHelper.CompareStrings(simplifiedSearch, dbContentName, out theAddedToMatch, out singleLetterDiff);
                        result.MatchedString = simplifiedSearch;
                    }

                    if (theAddedToMatch)
                        result.Mods |= ContentSearchMod.TheAdded;
                    if (singleLetterDiff)
                        result.Mods |= ContentSearchMod.SingleLetterAdded;

                    // Match notification
                    if (match)
                        OnDebugNotificationd("Matched with following mods: " + result.Mods);

                    // No match, next result!
                    if (!match)
                        continue;

                    // Set results folder/path
                    result.Content = searchResult;
                    result.Content.RootFolder = rootFolder;
                    if (string.IsNullOrEmpty(folderPath))
                        result.Content.Path = result.Content.BuildFolderPath();
                    else
                        result.Content.Path = folderPath;

                    // Save results
                    matches.Add(result);
                }

            return matches.Count > 0;
        }
示例#25
0
 /// <summary>
 /// Constructor for creating instance from inherited class
 /// </summary>
 /// <param name="content"></param>
 public TvShow(Content content)
     : this()
 {
     base.CloneAndHandlePath(content, true);
 }
示例#26
0
        /// <summary>
        /// Attempts to match string to content from the online database.
        /// </summary>
        /// <param name="search">Search string to match against</param>
        /// <param name="rootFolder">The root folder the content will belong to</param>
        /// <param name="folderPath">Folder path where the content should be moved to</param>
        /// <returns>Match content item, null if no match</returns>
        protected bool ContentMatch(string search, string rootFolder, string folderPath, bool fast, bool threaded, out Content match, Content knownContent)
        {
            // Create empty content
            Content emptyContent;
            switch (this.ContentType)
            {
                case ContentType.Movie:
                    emptyContent = new Movie();
                    break;
                case ContentType.TvShow:
                    emptyContent = new TvShow();
                    break;
                default:
                    throw new Exception("Unknown content type");
            }
            emptyContent.Path = folderPath;
            emptyContent.RootFolder = rootFolder;
            emptyContent.Found = true;

            // Check for empty search condition
            if (string.IsNullOrEmpty(search))
            {
                match = emptyContent;
                return false;
            }

            // Get year from search string
            int dirYear = FileHelper.GetYear(search);

            // Get list of simplified strings
            List<FileHelper.SimplifyStringResults> searches = new List<FileHelper.SimplifyStringResults>();

            // Get list of search bases
            List<string> searchBases = GetModifiedSearches(search);

            // Fast search: use first search base only
            if (fast)
            {
                FileHelper.SimplifyStringResults result = FileHelper.BuildSimplifyResults(searchBases[0], false, false, FileHelper.OptionalSimplifyRemoves.YearAndFollowing, true, false, true, false);
                searches.Add(result);
            }
            // Full search: Go through each search base and get simplified search options
            else
                foreach (string searchBase in searchBases)
                {
                    // Get results from current base
                    List<FileHelper.SimplifyStringResults> currSearches = FileHelper.SimplifyString(searchBase);
                    currSearches.Add(new FileHelper.SimplifyStringResults(searchBase, new Dictionary<FileWordType, List<string>>(), ContentSearchMod.None));

                    // Add each result to full list of searches
                    foreach (FileHelper.SimplifyStringResults results in currSearches)
                    {
                        // Check if search already exist
                        bool exists = false;
                        foreach (FileHelper.SimplifyStringResults s in searches)
                            if (s.SimplifiedString == results.SimplifiedString)
                            {
                                exists = true;
                                break;
                            }

                        // If doesn't exist add it to searches
                        if (!exists && !string.IsNullOrWhiteSpace(results.SimplifiedString))
                            searches.Add(results);
                    }
                }
            searches.Sort();

            // Create new status
            int currSeachCnt;
            MatchStatus status;
            lock (searchLock)
            {
                currSeachCnt = ++searchCount;
                status = new MatchStatus(searches.Count, this.ContentType);
                searchStatus.Add(currSeachCnt, status);
            }

            ContentSearchMod lowMods;
            Content lowestModsMatch;

            // Add thread to pool for each search that need to be performed
            int searchNum = 0;
            while (searchNum < searches.Count)
            {
                // Check for any search results so far
                if (status.GetSearchResultWithLowestMods(out lowMods, out lowestModsMatch))
                {
                    // If search results have no mods or just year removed use them as final results
                    if (lowMods == ContentSearchMod.None || lowMods == ContentSearchMod.YearRemoved)
                    {
                        match = lowestModsMatch;
                        return true;
                    }
                }

                // Limit number of search threads created
                if (status.NumStarted - status.NumCompleted >= Settings.General.NumSimultaneousSearches)
                {
                    Thread.Sleep(100);
                    continue;
                }

                // Build search arguments
                object[] args = { currSeachCnt, searchNum, searches[searchNum].SimplifiedString, folderPath, rootFolder, dirYear, searches[searchNum].Modifications, knownContent };

                // Threaded: add a search to thread pool
                if (threaded)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(SearchThread), args);
                    lock (searchLock)
                        status.SetSearchStarted(searchNum);
                }
                // Synchronized: call search method
                else
                    SearchThread(args);

                searchNum++;
            }

            // Wait for all search to complete
            while (status.NumCompleted < searches.Count)
            {
                // Check for any search results so far
                if (status.GetSearchResultWithLowestMods(out lowMods, out lowestModsMatch))
                {
                    // If search results have no mods or just year removed use them as final results
                    if (lowMods == ContentSearchMod.None || lowMods == ContentSearchMod.YearRemoved)
                    {
                        match = lowestModsMatch;
                        return true;
                    }
                }

                Thread.Sleep(100);
            }

            // Clear status
            lock (searchLock)
                searchStatus.Remove(currSeachCnt);

            // Return result with lowest mods to search string
            if (status.GetSearchResultWithLowestMods(out lowMods, out lowestModsMatch))
            {
                match = lowestModsMatch;
                return true;
            }
            else
            {
                match = emptyContent;
                return false;
            }
        }
示例#27
0
 public new void Clone(Content content)
 {
     CloneAndHandlePath(content, true, false);
 }
示例#28
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;
        }
示例#29
0
        public virtual bool Update(Content content)
        {
            string mirror;
            if (!GetMirror(this.UpdateMirrorType, out mirror))
                return false;

            // Tries up to 5 times - database can fail randomly
            for (int j = 0; j < 5; j++)
            {
                try
                {
                    DoUpdate(mirror, content);
                    return true;

                }
                catch { }
            }

            return false;
        }