Beispiel #1
0
        public void SyncLibrary()
        {
            TraktLogger.Info("My Videos Starting Library Sync");

            #region Get online data from cache

            #region Get unwatched / watched movies from trakt.tv
            IEnumerable <TraktMovieWatched> traktWatchedMovies = null;

            var traktUnWatchedMovies = TraktCache.GetUnWatchedMoviesFromTrakt();
            if (traktUnWatchedMovies == null)
            {
                TraktLogger.Error("Error getting unwatched movies from trakt server, unwatched and watched sync will be skipped");
            }
            else
            {
                TraktLogger.Info("There are {0} unwatched movies since the last sync with trakt.tv", traktUnWatchedMovies.Count());

                traktWatchedMovies = TraktCache.GetWatchedMoviesFromTrakt();
                if (traktWatchedMovies == null)
                {
                    TraktLogger.Error("Error getting watched movies from trakt server, watched sync will be skipped");
                }
                else
                {
                    TraktLogger.Info("There are {0} watched movies in trakt.tv library", traktWatchedMovies.Count());
                }
            }
            #endregion

            #region Get collected movies from trakt.tv
            var traktCollectedMovies = TraktCache.GetCollectedMoviesFromTrakt();
            if (traktCollectedMovies == null)
            {
                TraktLogger.Error("Error getting collected movies from trakt server");
            }
            else
            {
                TraktLogger.Info("There are {0} collected movies in trakt.tv library", traktCollectedMovies.Count());
            }
            #endregion

            #endregion

            // optionally do library sync
            if (TraktSettings.SyncLibrary)
            {
                var collectedMovies = GetMovies();

                #region Remove Blocked Movies
                collectedMovies.RemoveAll(m => TraktSettings.BlockedFolders.Any(f => m.Path.ToLowerInvariant().Contains(f.ToLowerInvariant())));

                List <int> blockedMovieIds = new List <int>();
                foreach (string file in TraktSettings.BlockedFilenames)
                {
                    int pathId  = 0;
                    int movieId = 0;

                    // get a list of ids for blocked filenames
                    // filename seems to always be empty for an IMDBMovie object!
                    if (VideoDatabase.GetFile(file, out pathId, out movieId, false) > 0)
                    {
                        blockedMovieIds.Add(movieId);
                    }
                }
                collectedMovies.RemoveAll(m => blockedMovieIds.Contains(m.ID));
                #endregion

                #region Remove Movies with No IDs
                // Remove any movies that don't have any valid online ID's e.g. IMDb ID or TMDb ID.
                if (TraktSettings.SkipMoviesWithNoIdsOnSync)
                {
                    TraktLogger.Info("Removing movies that contain no valid online ID from sync movie list");
                    collectedMovies.RemoveAll(m => !BasicHandler.IsValidImdb(m.IMDBNumber));
                }
                #endregion

                #region Skipped Movies Check
                // Remove Skipped Movies from previous Sync
                //TODO
                //if (TraktSettings.SkippedMovies != null)
                //{
                //    // allow movies to re-sync again after 7-days in the case user has addressed issue ie. edited movie or added to themoviedb.org
                //    if (TraktSettings.SkippedMovies.LastSkippedSync.FromEpoch() > DateTime.UtcNow.Subtract(new TimeSpan(7, 0, 0, 0)))
                //    {
                //        if (TraktSettings.SkippedMovies.Movies != null && TraktSettings.SkippedMovies.Movies.Count > 0)
                //        {
                //            TraktLogger.Info("Skipping {0} movies due to invalid data or movies don't exist on http://themoviedb.org. Next check will be {1}.", TraktSettings.SkippedMovies.Movies.Count, TraktSettings.SkippedMovies.LastSkippedSync.FromEpoch().Add(new TimeSpan(7, 0, 0, 0)));
                //            foreach (var movie in TraktSettings.SkippedMovies.Movies)
                //            {
                //                TraktLogger.Info("Skipping movie, Title: {0}, Year: {1}, IMDb: {2}", movie.Title, movie.Year, movie.IMDBID);
                //                MovieList.RemoveAll(m => (m.Title == movie.Title) && (m.Year.ToString() == movie.Year) && (m.IMDBNumber == movie.IMDBID));
                //            }
                //        }
                //    }
                //    else
                //    {
                //        if (TraktSettings.SkippedMovies.Movies != null) TraktSettings.SkippedMovies.Movies.Clear();
                //        TraktSettings.SkippedMovies.LastSkippedSync = DateTime.UtcNow.ToEpoch();
                //    }
                //}
                #endregion

                #region Already Exists Movie Check
                // Remove Already-Exists Movies, these are typically movies that are using aka names and no IMDb/TMDb set
                // When we compare our local collection with trakt collection we have english only titles, so if no imdb/tmdb exists
                // we need to fallback to title matching. When we sync aka names are sometimes accepted if defined on themoviedb.org so we need to
                // do this to revent syncing these movies every sync interval.
                //TODO
                //if (TraktSettings.AlreadyExistMovies != null && TraktSettings.AlreadyExistMovies.Movies != null && TraktSettings.AlreadyExistMovies.Movies.Count > 0)
                //{
                //    TraktLogger.Debug("Skipping {0} movies as they already exist in trakt library but failed local match previously.", TraktSettings.AlreadyExistMovies.Movies.Count.ToString());
                //    var movies = new List<TraktMovieSync.Movie>(TraktSettings.AlreadyExistMovies.Movies);
                //    foreach (var movie in movies)
                //    {
                //        Predicate<IMDBMovie> criteria = m => (m.Title == movie.Title) && (m.Year.ToString() == movie.Year) && (m.IMDBNumber == movie.IMDBID);
                //        if (MovieList.Exists(criteria))
                //        {
                //            TraktLogger.Debug("Skipping movie, Title: {0}, Year: {1}, IMDb: {2}", movie.Title, movie.Year, movie.IMDBID);
                //            MovieList.RemoveAll(criteria);
                //        }
                //        else
                //        {
                //            // remove as we have now removed from our local collection or updated movie signature
                //            if (TraktSettings.MoviePluginCount == 1)
                //            {
                //                TraktLogger.Debug("Removing 'AlreadyExists' movie, Title: {0}, Year: {1}, IMDb: {2}", movie.Title, movie.Year, movie.IMDBID);
                //                TraktSettings.AlreadyExistMovies.Movies.Remove(movie);
                //            }
                //        }
                //    }
                //}
                #endregion

                TraktLogger.Info("Found {0} movies available to sync in My Videos database", collectedMovies.Count);

                // get the movies that we have watched
                var watchedMovies = collectedMovies.Where(m => m.Watched > 0).ToList();

                TraktLogger.Info("Found {0} watched movies available to sync in My Videos database", watchedMovies.Count);

                #region Mark movies as unwatched in local database
                if (traktUnWatchedMovies != null && traktUnWatchedMovies.Count() > 0)
                {
                    foreach (var movie in traktUnWatchedMovies)
                    {
                        var localMovie = watchedMovies.FirstOrDefault(m => MovieMatch(m, movie));
                        if (localMovie == null)
                        {
                            continue;
                        }

                        TraktLogger.Info("Marking movie as unwatched in local database, movie is not watched on trakt.tv. Title = '{0}', Year = '{1}', IMDb ID = '{2}', TMDb ID = '{3}'",
                                         movie.Title, movie.Year.HasValue ? movie.Year.ToString() : "<empty>", movie.Ids.Imdb ?? "<empty>", movie.Ids.Tmdb.HasValue ? movie.Ids.Tmdb.ToString() : "<empty>");

                        localMovie.Watched = 0;
                        IMDBMovie details = localMovie;
                        VideoDatabase.SetMovieInfoById(localMovie.ID, ref details);
                        VideoDatabase.SetMovieWatchedStatus(localMovie.ID, false, 0);
                    }

                    // update watched set
                    watchedMovies = collectedMovies.Where(m => m.Watched > 0).ToList();
                }
                #endregion

                #region Mark movies as watched in local database
                if (traktWatchedMovies != null && traktWatchedMovies.Count() > 0)
                {
                    foreach (var twm in traktWatchedMovies)
                    {
                        var localMovie = collectedMovies.FirstOrDefault(m => MovieMatch(m, twm.Movie));
                        if (localMovie == null)
                        {
                            continue;
                        }

                        int  iPercent;
                        int  iWatchedCount;
                        bool localIsWatched = VideoDatabase.GetmovieWatchedStatus(localMovie.ID, out iPercent, out iWatchedCount);

                        if (!localIsWatched || iWatchedCount < twm.Plays)
                        {
                            TraktLogger.Info("Updating local movie watched state / play count to match trakt.tv. Plays = '{0}', Title = '{1}', Year = '{2}', IMDb ID = '{3}', TMDb ID = '{4}'",
                                             twm.Plays, twm.Movie.Title, twm.Movie.Year.HasValue ? twm.Movie.Year.ToString() : "<empty>", twm.Movie.Ids.Imdb ?? "<empty>", twm.Movie.Ids.Tmdb.HasValue ? twm.Movie.Ids.Tmdb.ToString() : "<empty>");

                            if (localMovie.DateWatched == "0001-01-01 00:00:00")
                            {
                                DateTime dateWatched;
                                if (DateTime.TryParse(twm.LastWatchedAt, out dateWatched))
                                {
                                    localMovie.DateWatched = dateWatched.ToString("yyyy-MM-dd HH:mm:ss");
                                }
                            }

                            localMovie.Watched        = 1;
                            localMovie.WatchedCount   = twm.Plays;
                            localMovie.WatchedPercent = iPercent;

                            VideoDatabase.SetMovieWatchedCount(localMovie.ID, twm.Plays);
                            VideoDatabase.SetMovieWatchedStatus(localMovie.ID, true, iPercent);

                            IMDBMovie details = localMovie;
                            VideoDatabase.SetMovieInfoById(localMovie.ID, ref details);
                        }
                    }
                }
                #endregion

                #region Add movies to watched history at trakt.tv
                if (traktWatchedMovies != null)
                {
                    var syncWatchedMovies = new List <TraktSyncMovieWatched>();
                    TraktLogger.Info("Finding movies to add to trakt.tv watched history");

                    syncWatchedMovies = (from movie in watchedMovies
                                         where !traktWatchedMovies.ToList().Exists(c => MovieMatch(movie, c.Movie))
                                         select new TraktSyncMovieWatched
                    {
                        Ids = new TraktMovieId {
                            Imdb = movie.IMDBNumber.ToNullIfEmpty()
                        },
                        Title = movie.Title,
                        Year = movie.Year,
                        WatchedAt = GetLastDateWatched(movie),
                    }).ToList();

                    TraktLogger.Info("Adding {0} movies to trakt.tv watched history", syncWatchedMovies.Count);

                    if (syncWatchedMovies.Count > 0)
                    {
                        // update local cache
                        TraktCache.AddMoviesToWatchHistory(syncWatchedMovies);

                        int pageSize = TraktSettings.SyncBatchSize;
                        int pages    = (int)Math.Ceiling((double)syncWatchedMovies.Count / pageSize);
                        for (int i = 0; i < pages; i++)
                        {
                            TraktLogger.Info("Adding movies [{0}/{1}] to trakt.tv watched history", i + 1, pages);

                            var pagedMovies = syncWatchedMovies.Skip(i * pageSize).Take(pageSize).ToList();

                            pagedMovies.ForEach(s => TraktLogger.Info("Adding movie to trakt.tv watched history. Title = '{0}', Year = '{1}', IMDb ID = '{2}', TMDb ID = '{3}', Date Watched = '{4}'",
                                                                      s.Title, s.Year.HasValue ? s.Year.ToString() : "<empty>", s.Ids.Imdb ?? "<empty>", s.Ids.Tmdb.HasValue ? s.Ids.Tmdb.ToString() : "<empty>", s.WatchedAt));

                            // remove title/year such that match against online ID only
                            if (TraktSettings.SkipMoviesWithNoIdsOnSync)
                            {
                                pagedMovies.ForEach(m => { m.Title = null; m.Year = null; });
                            }

                            var response = TraktAPI.TraktAPI.AddMoviesToWatchedHistory(new TraktSyncMoviesWatched {
                                Movies = pagedMovies
                            });
                            TraktLogger.LogTraktResponse <TraktSyncResponse>(response);

                            // remove movies from cache which didn't succeed
                            if (response != null && response.NotFound != null && response.NotFound.Movies.Count > 0)
                            {
                                TraktCache.RemoveMoviesFromWatchHistory(response.NotFound.Movies);
                            }
                        }
                    }
                }
                #endregion

                #region Add movies to collection at trakt.tv
                if (traktCollectedMovies != null)
                {
                    var syncCollectedMovies = new List <TraktSyncMovieCollected>();
                    TraktLogger.Info("Finding movies to add to trakt.tv collection");

                    syncCollectedMovies = (from movie in collectedMovies
                                           where !traktCollectedMovies.ToList().Exists(c => MovieMatch(movie, c.Movie))
                                           select new TraktSyncMovieCollected
                    {
                        Ids = new TraktMovieId {
                            Imdb = movie.IMDBNumber.ToNullIfEmpty()
                        },
                        Title = movie.Title,
                        Year = movie.Year,
                        CollectedAt = movie.DateAdded.ToISO8601(),
                        MediaType = GetMovieMediaType(movie),
                        Resolution = GetMovieResolution(movie),
                        AudioCodec = GetMovieAudioCodec(movie),
                        AudioChannels = GetMovieAudioChannels(movie),
                        Is3D = IsMovie3D(movie)
                    }).ToList();

                    TraktLogger.Info("Adding {0} movies to trakt.tv collection", syncCollectedMovies.Count);

                    if (syncCollectedMovies.Count > 0)
                    {
                        // update internal cache
                        TraktCache.AddMoviesToCollection(syncCollectedMovies);

                        int pageSize = TraktSettings.SyncBatchSize;
                        int pages    = (int)Math.Ceiling((double)syncCollectedMovies.Count / pageSize);
                        for (int i = 0; i < pages; i++)
                        {
                            TraktLogger.Info("Adding movies [{0}/{1}] to trakt.tv collection", i + 1, pages);

                            var pagedMovies = syncCollectedMovies.Skip(i * pageSize).Take(pageSize).ToList();

                            pagedMovies.ForEach(s => TraktLogger.Info("Adding movie to trakt.tv collection. Title = '{0}', Year = '{1}', IMDb ID = '{2}', TMDb ID = '{3}', Date Added = '{4}', MediaType = '{5}', Resolution = '{6}', Audio Codec = '{7}', Audio Channels = '{8}'",
                                                                      s.Title, s.Year.HasValue ? s.Year.ToString() : "<empty>", s.Ids.Imdb ?? "<empty>", s.Ids.Tmdb.HasValue ? s.Ids.Tmdb.ToString() : "<empty>",
                                                                      s.CollectedAt, s.MediaType ?? "<empty>", s.Resolution ?? "<empty>", s.AudioCodec ?? "<empty>", s.AudioChannels ?? "<empty>"));

                            // remove title/year such that match against online ID only
                            if (TraktSettings.SkipMoviesWithNoIdsOnSync)
                            {
                                pagedMovies.ForEach(m => { m.Title = null; m.Year = null; });
                            }

                            var response = TraktAPI.TraktAPI.AddMoviesToCollecton(new TraktSyncMoviesCollected {
                                Movies = pagedMovies
                            });
                            TraktLogger.LogTraktResponse(response);

                            // remove movies from cache which didn't succeed
                            if (response != null && response.NotFound != null && response.NotFound.Movies.Count > 0)
                            {
                                TraktCache.RemoveMoviesFromCollection(response.NotFound.Movies);
                            }
                        }
                    }
                }
                #endregion

                #region Remove movies no longer in collection from trakt.tv
                if (TraktSettings.KeepTraktLibraryClean && TraktSettings.MoviePluginCount == 1 && traktCollectedMovies != null)
                {
                    var syncUnCollectedMovies = new List <TraktMovie>();
                    TraktLogger.Info("Finding movies to remove from trakt.tv collection");

                    // workout what movies that are in trakt collection that are not in local collection
                    syncUnCollectedMovies = (from tcm in traktCollectedMovies
                                             where !collectedMovies.Exists(c => MovieMatch(c, tcm.Movie))
                                             select new TraktMovie
                    {
                        Ids = tcm.Movie.Ids,
                        Title = tcm.Movie.Title,
                        Year = tcm.Movie.Year
                    }).ToList();

                    TraktLogger.Info("Removing {0} movies from trakt.tv collection", syncUnCollectedMovies.Count);

                    if (syncUnCollectedMovies.Count > 0)
                    {
                        // update local cache
                        TraktCache.RemoveMoviesFromCollection(syncUnCollectedMovies);

                        int pageSize = TraktSettings.SyncBatchSize;
                        int pages    = (int)Math.Ceiling((double)syncUnCollectedMovies.Count / pageSize);
                        for (int i = 0; i < pages; i++)
                        {
                            TraktLogger.Info("Removing movies [{0}/{1}] from trakt.tv collection", i + 1, pages);

                            var pagedMovies = syncUnCollectedMovies.Skip(i * pageSize).Take(pageSize).ToList();

                            pagedMovies.ForEach(s => TraktLogger.Info("Removing movie from trakt.tv collection, movie no longer exists locally. Title = '{0}', Year = '{1}', IMDb ID = '{2}', TMDb ID = '{3}'",
                                                                      s.Title, s.Year.HasValue ? s.Year.ToString() : "<empty>", s.Ids.Imdb ?? "<empty>", s.Ids.Tmdb.HasValue ? s.Ids.Tmdb.ToString() : "<empty>"));

                            // remove title/year such that match against online ID only
                            if (TraktSettings.SkipMoviesWithNoIdsOnSync)
                            {
                                pagedMovies.ForEach(m => { m.Title = null; m.Year = null; });
                            }

                            var response = TraktAPI.TraktAPI.RemoveMoviesFromCollecton(new TraktSyncMovies {
                                Movies = pagedMovies
                            });
                            TraktLogger.LogTraktResponse(response);
                        }
                    }
                }
                #endregion
            }

            TraktLogger.Info("My Videos Library Sync Completed");
        }
        // Changed - cover for movies with the same name
        public void SetIMDBThumbs(IList items, bool markWatchedFiles, bool eachMovieHasDedicatedFolder)
        {
            GUIListItem pItem;
            IMDBMovie   movieDetails = new IMDBMovie();

            for (int x = 0; x < items.Count; x++)
            {
                string strThumb = string.Empty;
                pItem = (GUIListItem)items[x];
                string file = string.Empty;
                bool   isFolderPinProtected = (pItem.IsFolder && IsFolderPinProtected(pItem.Path));
                // Skip DVD backup folder
                if (pItem.IsFolder && !IsDvdDirectory(pItem.Path))
                {
                    if (pItem.Label == "..")
                    {
                        continue;
                    }

                    if (isFolderPinProtected)
                    {
                        // hide maybe rated content
                        Util.Utils.SetDefaultIcons(pItem);
                        continue;
                    }

                    // If this is enabled you'll see the thumb of the first movie in that dir - but if you put serveral movies into that dir you'll be irritated...
                    else
                    {
                        if (eachMovieHasDedicatedFolder)
                        {
                            file = GetFolderVideoFile(pItem.Path);
                        }
                    }
                }
                // If folder is DVD backup folder then take it for watched status
                else if (pItem.IsFolder && IsDvdDirectory(pItem.Path))
                {
                    file = GetFolderVideoFile(pItem.Path);
                }

                else if (!pItem.IsFolder ||
                         (pItem.IsFolder && VirtualDirectory.IsImageFile(Path.GetExtension(pItem.Path).ToLower())))
                {
                    file = pItem.Path;
                }

                else
                {
                    continue;
                }

                if (!string.IsNullOrEmpty(file))
                {
                    int  fileId       = VideoDatabase.GetFileId(file);
                    int  id           = VideoDatabase.GetMovieInfo(file, ref movieDetails);
                    bool foundWatched = false;
                    // Set thumb for movies
                    if (id >= 0)
                    {
                        if (Util.Utils.IsDVD(pItem.Path))
                        {
                            pItem.Label = String.Format("({0}:) {1}", pItem.Path.Substring(0, 1), movieDetails.Title);
                        }

                        string titleExt = movieDetails.Title + "{" + movieDetails.ID + "}";
                        strThumb = Util.Utils.GetCoverArt(Thumbs.MovieTitle, titleExt);
                    }
                    // Find watched status for videos
                    if (fileId >= 0 && markWatchedFiles)
                    {
                        if (VideoDatabase.GetmovieWatchedStatus(VideoDatabase.GetMovieId(file)))
                        {
                            foundWatched = true;
                        }
                    }
                    // Set watched status for list item
                    if (!pItem.IsFolder || (IsDvdDirectory(pItem.Path) && foundWatched))
                    {
                        pItem.IsPlayed = foundWatched;
                    }

                    if (!Util.Utils.FileExistsInCache(strThumb) || string.IsNullOrEmpty(strThumb))
                    {
                        strThumb = string.Format(@"{0}\{1}", Thumbs.MovieTitle,
                                                 Util.Utils.MakeFileName(Util.Utils.SplitFilename(Path.ChangeExtension(file, ".jpg"))));
                        if (!Util.Utils.FileExistsInCache(strThumb))
                        {
                            continue;
                        }
                    }

                    pItem.ThumbnailImage = strThumb;
                    pItem.IconImageBig   = strThumb;
                    pItem.IconImage      = strThumb;

                    strThumb = Util.Utils.ConvertToLargeCoverArt(strThumb);
                    if (Util.Utils.FileExistsInCache(strThumb))
                    {
                        pItem.ThumbnailImage = strThumb;
                    }
                } // <-- file == empty
            }     // of for (int x = 0; x < items.Count; ++x)
        }