public static TraktMovieScrobble CreateMovieScrobbleData(VideoInfo info) { try { // create scrobble data TraktMovieScrobble scrobbleData = new TraktMovieScrobble { Title = info.Title, Year = info.Year, PluginVersion = TraktSettings.Version, MediaCenter = "Mediaportal", MediaCenterVersion = System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString(), MediaCenterBuildDate = String.Empty, UserName = TraktSettings.Username, Password = TraktSettings.Password }; return(scrobbleData); } catch (Exception e) { TraktLogger.Error("Error creating scrobble data: {0}", e.Message); return(null); } }
public void AuthorizeUser() { if (string.IsNullOrEmpty(PinCode) || PinCode.Length != 8) { TestStatus = "[Trakt.WrongToken]"; TraktLogger.Error("Wrong pin entered"); return; } if (!Login()) { return; } if (string.IsNullOrEmpty(Username)) { TestStatus = "[Trakt.EmptyUsername]"; TraktLogger.Error("Username is missing"); return; } ISettingsManager settingsManager = ServiceRegistration.Get <ISettingsManager>(); TraktSettings settings = settingsManager.Load <TraktSettings>(); // temp. fix to disable the authorize button, when the user already is authorized IsAuthorized = true; settings.IsAuthorized = IsAuthorized; settings.EnableTrakt = IsEnabled; settings.Username = Username; settingsManager.Save(settings); }
/// <summary> /// Reads all Skin Settings /// </summary> /// <param name="filename"></param> public static void Load(string filename) { // Check if File Exist if (!System.IO.File.Exists(filename)) { TraktLogger.Warning("Trakt Skin Settings does not exist!"); return; } XmlDocument doc = new XmlDocument(); try { doc.Load(filename); } catch (XmlException e) { TraktLogger.Error("Cannot Load skin settings xml file!: {0}", e.Message); return; } // Read and Import Skin Settings GetOverlayPositions(doc); // Read Dashboard Skin Setings GetDashboardSkinSettings(doc); }
static string LoadFileCache(string filename, string defaultValue) { string returnValue = defaultValue; try { if (File.Exists(filename)) { TraktLogger.Debug("Loading file from disk. Filename = '{0}'", filename); returnValue = File.ReadAllText(filename, Encoding.UTF8); if (string.IsNullOrEmpty(returnValue)) { TraktLogger.Warning("Unexpected contents in file '{0}', restoring default value", filename); returnValue = defaultValue; } } } catch (Exception e) { TraktLogger.Error(string.Format("Error loading file from disk. Filename = '{0}', Error = '{1}'", filename, e.Message)); return(defaultValue); } return(returnValue); }
private TraktMovieScrobble CreateMovieScrobbleData(ITrackingInfo info) { try { // create scrobble data TraktMovieScrobble scrobbleData = new TraktMovieScrobble { Title = info.Title, Year = info.Year > 1900 ? info.Year.ToString() : null, IMDBID = info.ID_IMDB, TMDBID = info.ID_TMDB, PluginVersion = TraktSettings.Version, MediaCenter = "Mediaportal", MediaCenterVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(), MediaCenterBuildDate = String.Empty, UserName = TraktSettings.Username, Password = TraktSettings.Password }; return(scrobbleData); } catch (Exception e) { TraktLogger.Error("Error creating scrobble data: {0}", e.Message); return(null); } }
static void BufferTrailer(string url) { // stop player if currently playing some other video if (g_Player.Playing) { g_Player.Stop(); } // prepare graph must be done on the MP main thread TraktLogger.Debug("Preparing graph for playback of '{0}'", url); var factory = new PlayerFactory(PlayerType.Internal, url); bool?prepareResult = ((OnlineVideosPlayer)factory.PreparedPlayer).PrepareGraph(); TraktLogger.Debug("Preparing graph complete."); switch (prepareResult) { case true: GUIBackgroundTask.Instance.ExecuteInBackgroundAndCallback(() => { TraktLogger.Info("OnlineVideo pre-buffering started."); if (((OnlineVideosPlayer)factory.PreparedPlayer).BufferFile()) { TraktLogger.Info("OnlineVideo pre-buffering complete."); return(true); } else { TraktLogger.Error("Error pre-buffering trailer."); return(null); } }, delegate(bool success, object result) { PlayTrailer(url, factory, result as bool?); }, GUI.Translation.BufferingTrailer, false); break; case false: // play without buffering PlayTrailer(url, factory, prepareResult); break; default: TraktLogger.Error("Failed to create player graph."); GUIUtils.ShowNotifyDialog(GUI.Translation.Error, GUI.Translation.UnableToPlayTrailer); break; } }
internal static bool Login(string key) { ISettingsManager settingsManager = ServiceRegistration.Get <ISettingsManager>(); TraktSettings settings = settingsManager.Load <TraktSettings>(); var response = TraktAuth.GetOAuthToken(key); if (response == null || string.IsNullOrEmpty(response.AccessToken)) { TraktLogger.Error("Unable to login to trakt"); return(false); } settings.IsAuthorized = true; settings.TraktOAuthToken = response.RefreshToken; settingsManager.Save(settings); TraktLogger.Info("Successfully logged in"); return(true); }
private bool Login() { ISettingsManager settingsManager = ServiceRegistration.Get <ISettingsManager>(); TraktSettings settings = settingsManager.Load <TraktSettings>(); TraktLogger.Info("Exchanging refresh-token for access-token"); var response = TraktAuth.GetOAuthToken(settings.TraktOAuthToken); if (response == null || string.IsNullOrEmpty(response.AccessToken)) { TraktLogger.Error("Unable to login to trakt"); return(false); } settings.TraktOAuthToken = response.RefreshToken; settingsManager.Save(settings); TraktLogger.Info("Successfully logged in"); return(true); }
static void SaveFileCache(string filename, string value) { if (value == null) { return; } TraktLogger.Debug("Saving file to disk. Filename = '{0}'", filename); try { Directory.CreateDirectory(Path.GetDirectoryName(filename)); File.WriteAllText(filename, value, Encoding.UTF8); } catch (Exception e) { TraktLogger.Error(string.Format("Error saving file. Filename = '{0}', Error = '{1}'", filename, e.Message)); } }
static string LoadFileCache(string filename, string defaultValue) { string returnValue = defaultValue; try { if (File.Exists(filename)) { TraktLogger.Debug("Loading file from disk. Filename = '{0}'", filename); returnValue = File.ReadAllText(filename, Encoding.UTF8); } } catch (Exception e) { TraktLogger.Error(string.Format("Error loading file from disk. Filename = '{0}', Error = '{1}'", filename, e.Message)); return(defaultValue); } return(returnValue); }
/// <summary> /// Get the date watched for the movie /// </summary> private static long GetLastDateWatched(IMDBMovie movie) { long dateLastPlayed = 0; if (!string.IsNullOrEmpty(movie.DateWatched) && movie.DateWatched != "0001-01-01 00:00:00") { try { DateTime dateResult; if (DateTime.TryParse(movie.DateWatched, out dateResult)) { dateLastPlayed = dateResult.ToUniversalTime().ToEpoch(); } } catch (Exception e) { TraktLogger.Error("Failed to get last watched date from movie: '{0}', Error: '{1}'", movie.Title, e.Message); } } return(dateLastPlayed); }
private TraktEpisodeScrobble CreateScrobbleData(FileLocal episode) { string seriesid = null; int seasonidx = 0; int episodeidx = 0; if (episode.AnimeEpisodes == null || episode.AnimeEpisodes.Count == 0 || !GetTVDBEpisodeInfo(episode.AnimeEpisodes[0], out seriesid, out seasonidx, out episodeidx)) { TraktLogger.Warning("Unable to scrobble episodes, no AniDb/TVDb reference in database yet. Episode will be manually marked as seen on sync when available."); return(null); } // create scrobble data try { TraktEpisodeScrobble scrobbleData = new TraktEpisodeScrobble { Title = episode.AniDB_File.AnimeSeries.SeriesName, Year = GetStartYear(episode.AniDB_File.AnimeSeries), Season = seasonidx.ToString(), Episode = episodeidx.ToString(), SeriesID = seriesid, PluginVersion = TraktSettings.Version, MediaCenter = "Mediaportal", MediaCenterVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(), MediaCenterBuildDate = String.Empty, UserName = TraktSettings.Username, Password = TraktSettings.Password }; return(scrobbleData); } catch { TraktLogger.Error("Failed to create scrobble data for '{0}'", episode.ToString()); return(null); } }
public void SyncMediaToTrakt() { if (!IsSynchronizing) { ISettingsManager settingsManager = ServiceRegistration.Get <ISettingsManager>(); TraktSettings settings = settingsManager.Load <TraktSettings>(); if (!settings.IsAuthorized) { TestStatus = "[Trakt.NotAuthorized]"; TraktLogger.Error("Trakt.tv not authorized"); return; } if (!TraktCache.RefreshData()) { return; } IsSynchronizing = true; IThreadPool threadPool = ServiceRegistration.Get <IThreadPool>(); threadPool.Add(SyncMediaToTrakt_Async, ThreadPriority.BelowNormal); } }
private bool Login() { ISettingsManager settingsManager = ServiceRegistration.Get <ISettingsManager>(); TraktSettings settings = settingsManager.Load <TraktSettings>(); TraktLogger.Info("Exchanging {0} for access-token...", PinCode.Length == 8 ? "pin-code" : "refresh-token"); var response = TraktAuth.GetOAuthToken(PinCode.Length == 8 ? PinCode : settings.TraktOAuthToken); if (response == null || string.IsNullOrEmpty(response.AccessToken)) { TestStatus = "[Trakt.CheckPin]"; TraktLogger.Error("Unable to login to trakt, wrong pin?"); PinCode = string.Empty; return(false); } TestStatus = "[Trakt.LoggedIn]"; settings.TraktOAuthToken = response.RefreshToken; settingsManager.Save(settings); TraktLogger.Info("Successfully logged in!"); return(true); }
public void SyncLibrary() { TraktLogger.Info("My Anime Starting Sync"); #region Get online data // get all episodes on trakt that are marked as in 'collection' IEnumerable <TraktLibraryShow> traktCollectionEpisodes = TraktAPI.TraktAPI.GetLibraryEpisodesForUser(TraktSettings.Username); if (traktCollectionEpisodes == null) { TraktLogger.Error("Error getting show collection from trakt server, cancelling sync."); return; } TraktLogger.Info("{0} tvshows in trakt collection", traktCollectionEpisodes.Count().ToString()); // get all episodes on trakt that are marked as 'seen' or 'watched' IEnumerable <TraktLibraryShow> traktWatchedEpisodes = TraktAPI.TraktAPI.GetWatchedEpisodesForUser(TraktSettings.Username); if (traktWatchedEpisodes == null) { TraktLogger.Error("Error getting shows watched from trakt server, cancelling sync."); return; } TraktLogger.Info("{0} tvshows with watched episodes in trakt library", traktWatchedEpisodes.Count().ToString()); // get all episodes on trakt that are marked as 'unseen' IEnumerable <TraktLibraryShow> traktUnSeenEpisodes = TraktAPI.TraktAPI.GetUnSeenEpisodesForUser(TraktSettings.Username); if (traktUnSeenEpisodes == null) { TraktLogger.Error("Error getting shows unseen from trakt server, cancelling sync."); return; } TraktLogger.Info("{0} tvshows with unseen episodes in trakt library", traktUnSeenEpisodes.Count().ToString()); #endregion #region Get local data List <FileLocal> localCollectionEpisodes = new List <FileLocal>(); List <FileLocal> localWatchedEpisodes = new List <FileLocal>(); // Get all local episodes in database localCollectionEpisodes = FileLocal.GetAll().Where(f => !string.IsNullOrEmpty(f.FileNameFull) && f.AnimeEpisodes.Count > 0).ToList(); TraktLogger.Info("{0} episodes with local files in my anime database", localCollectionEpisodes.Count.ToString()); // Get only Valid Episodes types localCollectionEpisodes.RemoveAll(lc => lc.AnimeEpisodes.Where(e => (e.EpisodeTypeEnum != enEpisodeType.Normal && e.EpisodeTypeEnum != enEpisodeType.Special)).Count() > 0); TraktLogger.Info("{0} episodes with valid episode types in my anime database", localCollectionEpisodes.Count.ToString()); // Get watched episodes localWatchedEpisodes = localCollectionEpisodes.Where(f => (f.AniDB_File != null && f.AniDB_File.IsWatched > 0) || (f.AnimeEpisodes != null && f.AnimeEpisodes[0].IsWatched > 0)).ToList(); TraktLogger.Info("{0} episodes watched in my anime database", localWatchedEpisodes.Count.ToString()); #endregion #region Sync collection/library to trakt // get list of episodes that we have not already trakt'd List <FileLocal> localEpisodesToSync = new List <FileLocal>(localCollectionEpisodes); foreach (FileLocal ep in localCollectionEpisodes) { if (TraktEpisodeExists(traktCollectionEpisodes, ep)) { // no interest in syncing, remove localEpisodesToSync.Remove(ep); } } // sync unseen episodes TraktLogger.Info("{0} episodes need to be added to Library", localEpisodesToSync.Count.ToString()); SyncLibrary(localEpisodesToSync, TraktSyncModes.library); #endregion #region Sync seen to trakt // get list of episodes that we have not already trakt'd // filter out any marked as UnSeen List <FileLocal> localWatchedEpisodesToSync = new List <FileLocal>(localWatchedEpisodes); foreach (FileLocal ep in localWatchedEpisodes) { if (TraktEpisodeExists(traktWatchedEpisodes, ep) || TraktEpisodeExists(traktUnSeenEpisodes, ep)) { // no interest in syncing, remove localWatchedEpisodesToSync.Remove(ep); } } // sync seen episodes TraktLogger.Info("{0} episodes need to be added to SeenList", localWatchedEpisodesToSync.Count.ToString()); SyncLibrary(localWatchedEpisodesToSync, TraktSyncModes.seen); #endregion #region Sync watched flags from trakt locally // Sync watched flags from trakt to local database // do not mark as watched locally if UnSeen on trakt foreach (FileLocal ep in localCollectionEpisodes.Where(e => e.AnimeEpisodes[0].IsWatched == 0)) { if (TraktEpisodeExists(traktWatchedEpisodes, ep) && !TraktEpisodeExists(traktUnSeenEpisodes, ep)) { // mark episode as watched TraktLogger.Info("Marking episode '{0}' as watched", ep.ToString()); ep.AnimeEpisodes[0].ToggleWatchedStatus(true, false); } } #endregion #region Sync unseen flags from trakt locally foreach (FileLocal ep in localCollectionEpisodes.Where(e => e.AnimeEpisodes[0].IsWatched > 1)) { if (TraktEpisodeExists(traktUnSeenEpisodes, ep)) { // mark episode as unwatched TraktLogger.Info("Marking episode '{0}' as unwatched", ep.ToString()); ep.AnimeEpisodes[0].ToggleWatchedStatus(false, false); } } #endregion #region Clean Library if (TraktSettings.KeepTraktLibraryClean && TraktSettings.TvShowPluginCount == 1) { TraktLogger.Info("Removing shows From Trakt Collection no longer in database"); // if we no longer have a file reference in database remove from library foreach (var series in traktCollectionEpisodes) { TraktEpisodeSync syncData = GetEpisodesForTraktRemoval(series, localCollectionEpisodes.Where(e => e.AniDB_File.AnimeSeries.TvDB_ID.ToString() == series.SeriesId).ToList()); if (syncData == null) { continue; } TraktResponse response = TraktAPI.TraktAPI.SyncEpisodeLibrary(syncData, TraktSyncModes.unlibrary); TraktAPI.TraktAPI.LogTraktResponse(response); Thread.Sleep(500); } } #endregion TraktLogger.Info("My Anime Sync Completed"); }
public bool SyncSeries() { TraktLogger.Info("Series Library Starting Sync"); // store list of series ids so we can update the episode counts // of any series that syncback watched flags var seriesToUpdateEpisodeCounts = new HashSet <int>(); #region Get online data from cache #region UnWatched / Watched List <TraktCache.EpisodeWatched> traktWatchedEpisodes = null; // get all episodes on trakt that are marked as 'unseen' var traktUnWatchedEpisodes = TraktCache.GetUnWatchedEpisodesFromTrakt().ToNullableList(); if (traktUnWatchedEpisodes == null) { TraktLogger.Error("Error getting tv shows unwatched from trakt.tv server, unwatched and watched sync will be skipped"); } else { TraktLogger.Info("Found {0} unwatched tv episodes in trakt.tv library", traktUnWatchedEpisodes.Count()); // now get all episodes on trakt that are marked as 'seen' or 'watched' (this will be cached already when working out unwatched) traktWatchedEpisodes = TraktCache.GetWatchedEpisodesFromTrakt().ToNullableList(); if (traktWatchedEpisodes == null) { TraktLogger.Error("Error getting tv shows watched from trakt.tv server, watched sync will be skipped"); } else { TraktLogger.Info("Found {0} watched tv episodes in trakt.tv library", traktWatchedEpisodes.Count()); } } #endregion #region Collection // get all episodes on trakt that are marked as in 'collection' var traktCollectedEpisodes = TraktCache.GetCollectedEpisodesFromTrakt().ToNullableList(); if (traktCollectedEpisodes == null) { TraktLogger.Error("Error getting tv episode collection from trakt.tv server"); } else { TraktLogger.Info("Found {0} tv episodes in trakt.tv collection", traktCollectedEpisodes.Count()); } #endregion #region Ratings #region Episodes //var traktRatedEpisodes = TraktCache.GetRatedEpisodesFromTrakt().ToNullableList(); //if (traktRatedEpisodes == null) //{ // TraktLogger.Error("Error getting rated episodes from trakt.tv server"); //} //else //{ // TraktLogger.Info("Found {0} rated tv episodes in trakt.tv library", traktRatedEpisodes.Count()); //} #endregion #region Shows //var traktRatedShows = TraktCache.GetRatedShowsFromTrakt().ToNullableList(); //if (traktRatedShows == null) //{ // TraktLogger.Error("Error getting rated shows from trakt.tv server"); //} //else //{ // TraktLogger.Info("Found {0} rated tv shows in trakt.tv library", traktRatedShows.Count()); //} #endregion #region Seasons //var traktRatedSeasons = TraktCache.GetRatedSeasonsFromTrakt().ToNullableList(); //if (traktRatedSeasons == null) //{ // TraktLogger.Error("Error getting rated seasons from trakt.tv server"); //} //else //{ // TraktLogger.Info("Found {0} rated tv seasons in trakt.tv library", traktRatedSeasons.Count()); //} #endregion #endregion #region Watchlist #region Shows //var traktWatchlistedShows = TraktCache.GetWatchlistedShowsFromTrakt(); //if (traktWatchlistedShows == null) //{ // TraktLogger.Error("Error getting watchlisted shows from trakt.tv server"); //} //else //{ // TraktLogger.Info("Found {0} watchlisted tv shows in trakt.tv library", traktWatchlistedShows.Count()); //} #endregion #region Seasons //var traktWatchlistedSeasons = TraktCache.GetWatchlistedSeasonsFromTrakt(); //if (traktWatchlistedSeasons == null) //{ // TraktLogger.Error("Error getting watchlisted seasons from trakt.tv server"); //} //else //{ // TraktLogger.Info("Found {0} watchlisted tv seasons in trakt.tv library", traktWatchlistedSeasons.Count()); //} #endregion #region Episodes //var traktWatchlistedEpisodes = TraktCache.GetWatchlistedEpisodesFromTrakt(); //if (traktWatchlistedEpisodes == null) //{ // TraktLogger.Error("Error getting watchlisted episodes from trakt.tv server"); //} //else //{ // TraktLogger.Info("Found {0} watchlisted tv episodes in trakt.tv library", traktWatchlistedEpisodes.Count()); //} #endregion #endregion #endregion if (traktCollectedEpisodes != null) { try { TestStatus = "[Trakt.SyncSeries]"; Guid[] types = { MediaAspect.ASPECT_ID, SeriesAspect.ASPECT_ID, VideoAspect.ASPECT_ID, ImporterAspect.ASPECT_ID }; MediaItemQuery mediaItemQuery = new MediaItemQuery(types, null, null); var contentDirectory = ServiceRegistration.Get <IServerConnectionManager>().ContentDirectory; if (contentDirectory == null) { TestStatus = "[Trakt.MediaLibraryNotConnected]"; return(false); } #region Get data from local database var localEpisodes = contentDirectory.Search(mediaItemQuery, true); int episodeCount = localEpisodes.Count; TraktLogger.Info("Found {0} total episodes in local database", episodeCount); // get the episodes that we have watched var localWatchedEpisodes = localEpisodes.Where(IsWatched).ToList(); TraktLogger.Info("Found {0} episodes watched in tvseries database", localWatchedEpisodes.Count); #endregion #region Add episodes to watched history at trakt.tv int showCount = 0; int iSyncCounter = 0; if (traktWatchedEpisodes != null) { var syncWatchedShows = GetWatchedShowsForSyncEx(localWatchedEpisodes, traktWatchedEpisodes); TraktLogger.Info("Found {0} local tv show(s) with {1} watched episode(s) to add to trakt.tv watched history", syncWatchedShows.Shows.Count, syncWatchedShows.Shows.Sum(sh => sh.Seasons.Sum(se => se.Episodes.Count()))); showCount = syncWatchedShows.Shows.Count; foreach (var show in syncWatchedShows.Shows) { int showEpisodeCount = show.Seasons.Sum(s => s.Episodes.Count()); TraktLogger.Info("Adding tv show [{0}/{1}] to trakt.tv episode watched history, Episode Count = '{2}', Show Title = '{3}', Show Year = '{4}', Show TVDb ID = '{5}', Show IMDb ID = '{6}'", ++iSyncCounter, showCount, showEpisodeCount, show.Title, show.Year.HasValue ? show.Year.ToString() : "<empty>", show.Ids.Tvdb, show.Ids.Imdb ?? "<empty>"); show.Seasons.ForEach(s => s.Episodes.ForEach(e => { TraktLogger.Info("Adding episode to trakt.tv watched history, Title = '{0} - {1}x{2}', Watched At = '{3}'", show.Title, s.Number, e.Number, e.WatchedAt.ToLogString()); })); // only sync one show at a time regardless of batch size in settings var pagedShows = new List <TraktSyncShowWatchedEx>(); pagedShows.Add(show); var response = TraktAPI.AddShowsToWatchedHistoryEx(new TraktSyncShowsWatchedEx { Shows = pagedShows }); TraktLogger.LogTraktResponse <TraktSyncResponse>(response); // only add to cache if it was a success // note: we don't get back the same object type so makes it hard to figure out what failed if (response != null && response.Added != null && response.Added.Episodes == showEpisodeCount) { // update local cache TraktCache.AddEpisodesToWatchHistory(show); } } } #endregion #region Add episodes to collection at trakt.tv if (traktCollectedEpisodes != null) { var syncCollectedShows = GetCollectedShowsForSyncEx(localEpisodes, traktCollectedEpisodes); TraktLogger.Info("Found {0} local tv show(s) with {1} collected episode(s) to add to trakt.tv collection", syncCollectedShows.Shows.Count, syncCollectedShows.Shows.Sum(sh => sh.Seasons.Sum(se => se.Episodes.Count()))); iSyncCounter = 0; showCount = syncCollectedShows.Shows.Count; foreach (var show in syncCollectedShows.Shows) { int showEpisodeCount = show.Seasons.Sum(s => s.Episodes.Count()); TraktLogger.Info("Adding tv show [{0}/{1}] to trakt.tv episode collection, Episode Count = '{2}', Show Title = '{3}', Show Year = '{4}', Show TVDb ID = '{5}', Show IMDb ID = '{6}'", ++iSyncCounter, showCount, showEpisodeCount, show.Title, show.Year.HasValue ? show.Year.ToString() : "<empty>", show.Ids.Tvdb, show.Ids.Imdb ?? "<empty>"); show.Seasons.ForEach(s => s.Episodes.ForEach(e => { TraktLogger.Info("Adding episode to trakt.tv collection, Title = '{0} - {1}x{2}', Collected At = '{3}', Audio Channels = '{4}', Audio Codec = '{5}', Resolution = '{6}', Media Type = '{7}', Is 3D = '{8}'", show.Title, s.Number, e.Number, e.CollectedAt.ToLogString(), e.AudioChannels.ToLogString(), e.AudioCodec.ToLogString(), e.Resolution.ToLogString(), e.MediaType.ToLogString(), e.Is3D); })); // only sync one show at a time regardless of batch size in settings var pagedShows = new List <TraktSyncShowCollectedEx>(); pagedShows.Add(show); var response = TraktAPI.AddShowsToCollectonEx(new TraktSyncShowsCollectedEx { Shows = pagedShows }); TraktLogger.LogTraktResponse <TraktSyncResponse>(response); // only add to cache if it was a success if (response != null && response.Added != null && response.Added.Episodes == showEpisodeCount) { // update local cache TraktCache.AddEpisodesToCollection(show); } } } #endregion return(true); } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Error("Trakt.tv: Exception while synchronizing media library.", ex); } } return(false); }
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"); }
public void SyncLibrary() { TraktLogger.Info("My Videos Starting Sync"); if (TraktSettings.SyncLibrary) { // get all movies ArrayList myvideos = new ArrayList(); VideoDatabase.GetMovies(ref myvideos); List <IMDBMovie> MovieList = (from IMDBMovie movie in myvideos select movie).ToList(); #region Remove Blocked Movies MovieList.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); } } MovieList.RemoveAll(m => blockedMovieIds.Contains(m.ID)); #endregion #region Skipped Movies Check // Remove Skipped Movies from previous Sync 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. 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("{0} movies available to sync in My Videos database", MovieList.Count.ToString()); // get the movies that we have watched List <IMDBMovie> SeenList = MovieList.Where(m => m.Watched > 0).ToList(); TraktLogger.Info("{0} watched movies available to sync in My Videos database", SeenList.Count.ToString()); // get the movies that we have yet to watch TraktLogger.Info("Getting user {0}'s movies from trakt", TraktSettings.Username); IEnumerable <TraktLibraryMovies> traktMoviesAll = TraktAPI.TraktAPI.GetAllMoviesForUser(TraktSettings.Username); if (traktMoviesAll == null) { TraktLogger.Error("Error getting movies from trakt server, cancelling sync."); return; } TraktLogger.Info("{0} movies in trakt library", traktMoviesAll.Count().ToString()); #region Movies to Sync to Collection List <IMDBMovie> moviesToSync = new List <IMDBMovie>(MovieList); List <TraktLibraryMovies> NoLongerInOurCollection = new List <TraktLibraryMovies>(); //Filter out a list of movies we have already sync'd in our collection foreach (TraktLibraryMovies tlm in traktMoviesAll) { bool notInLocalCollection = true; // if it is in both libraries foreach (IMDBMovie libraryMovie in MovieList.Where(m => MovieMatch(m, tlm))) { // If the users IMDb Id is empty/invalid and we have matched one then set it if (BasicHandler.IsValidImdb(tlm.IMDBID) && !BasicHandler.IsValidImdb(libraryMovie.IMDBNumber)) { TraktLogger.Info("Movie '{0}' inserted IMDb Id '{1}'", libraryMovie.Title, tlm.IMDBID); libraryMovie.IMDBNumber = tlm.IMDBID; IMDBMovie details = libraryMovie; VideoDatabase.SetMovieInfoById(libraryMovie.ID, ref details); } // if it is watched in Trakt but not My Videos update // skip if movie is watched but user wishes to have synced as unseen locally if (tlm.Plays > 0 && !tlm.UnSeen && libraryMovie.Watched == 0) { TraktLogger.Info("Movie '{0}' is watched on Trakt updating Database", libraryMovie.Title); libraryMovie.Watched = 1; if (libraryMovie.DateWatched == "0001-01-01 00:00:00") { libraryMovie.DateWatched = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); } IMDBMovie details = libraryMovie; VideoDatabase.SetMovieInfoById(libraryMovie.ID, ref details); if (libraryMovie.WatchedCount == 0) { VideoDatabase.SetMovieWatchedCount(libraryMovie.ID, tlm.Plays); VideoDatabase.SetMovieWatchedStatus(libraryMovie.ID, true, 0); } } // mark movies as unseen if watched locally if (tlm.UnSeen && libraryMovie.Watched > 0) { TraktLogger.Info("Movie '{0}' is unseen on Trakt, updating database", libraryMovie.Title); libraryMovie.Watched = 0; IMDBMovie details = libraryMovie; VideoDatabase.SetMovieInfoById(libraryMovie.ID, ref details); VideoDatabase.SetMovieWatchedStatus(libraryMovie.ID, false, 0); } notInLocalCollection = false; //filter out if its already in collection if (tlm.InCollection) { moviesToSync.RemoveAll(m => MovieMatch(m, tlm)); } break; } if (notInLocalCollection && tlm.InCollection) { NoLongerInOurCollection.Add(tlm); } } #endregion #region Movies to Sync to Seen Collection // filter out a list of movies already marked as watched on trakt // also filter out movie marked as unseen so we dont reset the unseen cache online List <IMDBMovie> watchedMoviesToSync = new List <IMDBMovie>(SeenList); foreach (TraktLibraryMovies tlm in traktMoviesAll.Where(t => t.Plays > 0 || t.UnSeen)) { foreach (IMDBMovie watchedMovie in SeenList.Where(m => MovieMatch(m, tlm))) { //filter out watchedMoviesToSync.Remove(watchedMovie); } } #endregion #region Sync Collection to trakt //Send Library/Collection TraktLogger.Info("{0} movies need to be added to Library", moviesToSync.Count.ToString()); foreach (IMDBMovie m in moviesToSync) { TraktLogger.Info("Sending movie to trakt library, Title: {0}, Year: {1}, IMDb: {2}", m.Title, m.Year.ToString(), m.IMDBNumber); } if (moviesToSync.Count > 0) { TraktSyncResponse response = TraktAPI.TraktAPI.SyncMovieLibrary(CreateSyncData(moviesToSync), TraktSyncModes.library); BasicHandler.InsertSkippedMovies(response); BasicHandler.InsertAlreadyExistMovies(response); TraktLogger.LogTraktResponse(response); } #endregion #region Sync Seen to trakt //Send Seen TraktLogger.Info("{0} movies need to be added to SeenList", watchedMoviesToSync.Count.ToString()); foreach (IMDBMovie m in watchedMoviesToSync) { TraktLogger.Info("Sending movie to trakt as seen, Title: {0}, Year: {1}, IMDb: {2}", m.Title, m.Year.ToString(), m.IMDBNumber); } if (watchedMoviesToSync.Count > 0) { TraktSyncResponse response = TraktAPI.TraktAPI.SyncMovieLibrary(CreateSyncData(watchedMoviesToSync), TraktSyncModes.seen); BasicHandler.InsertSkippedMovies(response); BasicHandler.InsertAlreadyExistMovies(response); TraktLogger.LogTraktResponse(response); } #endregion #region Clean Library //Dont clean library if more than one movie plugin installed if (TraktSettings.KeepTraktLibraryClean && TraktSettings.MoviePluginCount == 1) { //Remove movies we no longer have in our local database from Trakt foreach (var m in NoLongerInOurCollection) { TraktLogger.Info("Removing from Trakt Collection {0}", m.Title); } TraktLogger.Info("{0} movies need to be removed from Trakt Collection", NoLongerInOurCollection.Count.ToString()); if (NoLongerInOurCollection.Count > 0) { if (TraktSettings.AlreadyExistMovies != null && TraktSettings.AlreadyExistMovies.Movies != null && TraktSettings.AlreadyExistMovies.Movies.Count > 0) { TraktLogger.Warning("DISABLING CLEAN LIBRARY!!!, there are trakt library movies that can't be determined to be local in collection."); TraktLogger.Warning("To fix this, check the 'already exist' entries in log, then check movies in local collection against this list and ensure IMDb id is set then run sync again."); } else { //Then remove from library TraktSyncResponse response = TraktAPI.TraktAPI.SyncMovieLibrary(BasicHandler.CreateMovieSyncData(NoLongerInOurCollection), TraktSyncModes.unlibrary); TraktLogger.LogTraktResponse(response); } } } #endregion } TraktLogger.Info("My Videos Sync Completed"); }
private void CopyList(TraktListDetail sourceList, TraktList newList) { var copyList = new CopyList { Username = CurrentUser, Source = sourceList, Destination = newList }; var copyThread = new Thread((obj) => { var copyParams = obj as CopyList; // first create new list TraktLogger.Info("Creating new list online. Privacy = '{0}', Name = '{1}'", copyParams.Destination.Privacy, copyParams.Destination.Name); var response = TraktAPI.TraktAPI.CreateCustomList(copyParams.Destination); if (response == null || response.Ids == null) { TraktLogger.Error("Failed to create user list. List Name = '{0}'", copyParams.Destination.Name); return; } // get items from other list var userListItems = TraktAPI.TraktAPI.GetUserListItems(copyParams.Source.User.Ids.Slug, copyParams.Source.Ids.Trakt.ToString(), "min"); if (userListItems == null) { TraktLogger.Error("Failed to get user list items. List Name = '{0}', ID = '{1}'", copyParams.Destination.Name, copyParams.Source.Ids.Trakt); return; } // copy items to new list var itemsToAdd = new TraktSyncAll(); foreach (var item in userListItems) { var listItem = new TraktListItem(); listItem.Type = item.Type; switch (item.Type) { case "movie": if (itemsToAdd.Movies == null) { itemsToAdd.Movies = new List <TraktMovie>(); } itemsToAdd.Movies.Add(new TraktMovie { Ids = item.Movie.Ids }); break; case "show": if (itemsToAdd.Shows == null) { itemsToAdd.Shows = new List <TraktShow>(); } itemsToAdd.Shows.Add(new TraktShow { Ids = item.Show.Ids }); break; case "season": if (itemsToAdd.Seasons == null) { itemsToAdd.Seasons = new List <TraktSeason>(); } itemsToAdd.Seasons.Add(new TraktSeason { Ids = item.Season.Ids }); break; case "episode": if (itemsToAdd.Episodes == null) { itemsToAdd.Episodes = new List <TraktEpisode>(); } itemsToAdd.Episodes.Add(new TraktEpisode { Ids = item.Episode.Ids }); break; case "person": if (itemsToAdd.People == null) { itemsToAdd.People = new List <TraktPerson>(); } itemsToAdd.People.Add(new TraktPerson { Ids = item.Person.Ids }); break; } } // add items to the list var ItemsAddedResponse = TraktAPI.TraktAPI.AddItemsToList("me", response.Ids.Trakt.ToString(), itemsToAdd); if (ItemsAddedResponse != null) { TraktLists.ClearListCache(TraktSettings.Username); TraktCache.ClearCustomListCache(); // updated MovingPictures categories and filters menu if (TraktHelper.IsMovingPicturesAvailableAndEnabled) { MovingPictures.UpdateCategoriesMenu(SyncListType.CustomList); MovingPictures.UpdateFiltersMenu(SyncListType.CustomList); } } }) { Name = "CopyList", IsBackground = true }; copyThread.Start(copyList); }
public bool SyncMovies() { ISettingsManager settingsManager = ServiceRegistration.Get <ISettingsManager>(); TraktSettings settings = settingsManager.Load <TraktSettings>(); #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().ToString()); } } #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 #region Get rated movies from trakt.tv //var traktRatedMovies = TraktCache.GetRatedMoviesFromTrakt(); //if (traktRatedMovies == null) //{ // TraktLogger.Error("Error getting rated movies from trakt server"); //} //else //{ // TraktLogger.Info("There are {0} rated movies in trakt.tv library", traktRatedMovies.Count()); //} #endregion #region Get watchlisted movies from trakt.tv //var traktWatchlistedMovies = TraktCache.GetWatchlistedMoviesFromTrakt(); //if (traktWatchlistedMovies == null) //{ // TraktLogger.Error("Error getting watchlisted movies from trakt server"); //} //else //{ // TraktLogger.Info("There are {0} watchlisted movies in trakt.tv library", traktWatchlistedMovies.Count()); //} #endregion #region Get custom lists from trakt.tv //var traktCustomLists = TraktCache.GetCustomLists(); //if (traktCustomLists == null) //{ // TraktLogger.Error("Error getting custom lists from trakt server"); //} //else //{ // TraktLogger.Info("There are {0} custom lists in trakt.tv library", traktCustomLists.Count()); //} #endregion #endregion try { TestStatus = "[Trakt.SyncMovies]"; Guid[] types = { MediaAspect.ASPECT_ID, MovieAspect.ASPECT_ID, VideoAspect.ASPECT_ID, ImporterAspect.ASPECT_ID }; var contentDirectory = ServiceRegistration.Get <IServerConnectionManager>().ContentDirectory; if (contentDirectory == null) { TestStatus = "[Trakt.MediaLibraryNotConnected]"; return(false); } #region Get local database info var collectedMovies = contentDirectory.Search(new MediaItemQuery(types, null, null), true); TraktLogger.Info("Found {0} movies available to sync in local database", collectedMovies.Count); // get the movies that we have watched var watchedMovies = collectedMovies.Where(IsWatched).ToList(); TraktLogger.Info("Found {0} watched movies available to sync in local database", watchedMovies.Count); #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 = GetMovieImdbId(movie), Tmdb = GetMovieTmdbId(movie) }, Title = GetMovieTitle(movie), Year = GetMovieYear(movie), WatchedAt = GetLastPlayedDate(movie), }).ToList(); TraktLogger.Info("Adding {0} movies to trakt.tv watched history", syncWatchedMovies.Count); if (syncWatchedMovies.Count > 0) { // update internal cache TraktCache.AddMoviesToWatchHistory(syncWatchedMovies); int pageSize = settings.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 (settings.SkipMoviesWithNoIdsOnSync) { pagedMovies.ForEach(m => { m.Title = null; m.Year = null; }); } var response = 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 = GetMovieImdbId(movie), Tmdb = GetMovieTmdbId(movie) }, Title = GetMovieTitle(movie), Year = GetMovieYear(movie), CollectedAt = GetDateAddedToDb(movie), MediaType = GetVideoMediaType(movie), Resolution = GetVideoResolution(movie), AudioCodec = GetVideoAudioCodec(movie), AudioChannels = "", Is3D = false }).ToList(); TraktLogger.Info("Adding {0} movies to trakt.tv watched history", syncCollectedMovies.Count); if (syncCollectedMovies.Count > 0) { //update internal cache TraktCache.AddMoviesToCollection(syncCollectedMovies); int pageSize = settings.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 (settings.SkipMoviesWithNoIdsOnSync) { pagedMovies.ForEach(m => { m.Title = null; m.Year = null; }); } var response = 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 return(true); } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Error("Trakt.tv: Exception while synchronizing media library.", ex); } return(false); }
public bool Scrobble(string filename) { StopScrobble(); if (!g_Player.IsTV) { return(false); } try { CurrentProgram = GetCurrentProgram(); } catch (Exception e) { TraktLogger.Error(e.Message); return(false); } if (CurrentProgram == null) { return(false); } CurrentProgram.IsScrobbling = true; if (CurrentProgram.Type == VideoType.Series) { TraktLogger.Info("Detected tv-series '{0}' playing in 4TR TV Live", CurrentProgram.ToString()); } else { TraktLogger.Info("Detected movie '{0}' playing in 4TR TV Live", CurrentProgram.ToString()); } #region scrobble timer TraktTimer = new Timer(new TimerCallback((stateInfo) => { Thread.CurrentThread.Name = "Scrobble"; // get the current program airing on tv now // this may have changed since last status update on trakt VideoInfo videoInfo = GetCurrentProgram(); if (videoInfo != null) { // if we are watching something different, // check if we should mark previous as watched if (!videoInfo.Equals(CurrentProgram)) { TraktLogger.Info("Detected new tv program has started '{0}' -> '{1}'", CurrentProgram.ToString(), videoInfo.ToString()); if (IsProgramWatched(CurrentProgram) && CurrentProgram.IsScrobbling) { ScrobbleProgram(CurrentProgram); } CurrentProgram.IsScrobbling = true; } // continue watching new program // dont try to scrobble if previous attempt failed if (CurrentProgram.IsScrobbling) { if (videoInfo.Type == VideoType.Series) { videoInfo.IsScrobbling = BasicHandler.ScrobbleEpisode(videoInfo, TraktScrobbleStates.watching); } else { videoInfo.IsScrobbling = BasicHandler.ScrobbleMovie(videoInfo, TraktScrobbleStates.watching); } // set current program to new program CurrentProgram = videoInfo; } } }), null, 1000, 300000); #endregion return(true); }
public static int LoadTranslations(string lang) { XmlDocument doc = new XmlDocument(); Dictionary <string, string> TranslatedStrings = new Dictionary <string, string>(); string langPath = string.Empty; try { langPath = Path.Combine(path, lang + ".xml"); doc.Load(langPath); } catch (Exception e) { if (lang == "en") { return(0); // otherwise we are in an endless loop! } if (e.GetType() == typeof(FileNotFoundException)) { TraktLogger.Warning("Cannot find translation file {0}. Falling back to English", langPath); } else { TraktLogger.Error("Error in translation xml file: {0}. Falling back to English", lang); } return(LoadTranslations("en")); } foreach (XmlNode stringEntry in doc.DocumentElement.ChildNodes) { if (stringEntry.NodeType == XmlNodeType.Element) { try { string key = stringEntry.Attributes.GetNamedItem("name").Value; if (!TranslatedStrings.ContainsKey(key)) { TranslatedStrings.Add(key, stringEntry.InnerText.NormalizeTranslation()); } else { TraktLogger.Error("Error in Translation Engine, the translation key '{0}' already exists.", key); } } catch (Exception ex) { TraktLogger.Error("Error in Translation Engine: {0}", ex.Message); } } } Type TransType = typeof(Translation); FieldInfo[] fieldInfos = TransType.GetFields(BindingFlags.Public | BindingFlags.Static); foreach (FieldInfo fi in fieldInfos) { if (TranslatedStrings != null && TranslatedStrings.ContainsKey(fi.Name)) { TransType.InvokeMember(fi.Name, BindingFlags.SetField, null, TransType, new object[] { TranslatedStrings[fi.Name] }); } else { TraktLogger.Info("Translation not found for field: {0}. Using hard-coded English default.", fi.Name); } } return(TranslatedStrings.Count); }
public void SyncLibrary() { TraktLogger.Info("My Films Starting Sync"); SyncInProgress = true; // get all movies ArrayList myvideos = new ArrayList(); BaseMesFilms.GetMovies(ref myvideos); TraktLogger.Info("BaseMesFilms.GetMovies: returning " + myvideos.Count + " movies"); List <MFMovie> MovieList = (from MFMovie movie in myvideos select movie).ToList(); // Remove any blocked movies MovieList.RemoveAll(movie => TraktSettings.BlockedFolders.Any(f => movie.File.ToLowerInvariant().Contains(f.ToLowerInvariant()))); MovieList.RemoveAll(movie => TraktSettings.BlockedFilenames.Contains(movie.File)); #region Skipped Movies Check // Remove Skipped Movies from previous Sync 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. 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 <MFMovie> 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("{0} movies available to sync in MyFilms database(s)", MovieList.Count.ToString()); // get the movies that we have watched List <MFMovie> SeenList = MovieList.Where(m => m.Watched == true).ToList(); TraktLogger.Info("{0} watched movies available to sync in MyFilms database(s)", SeenList.Count.ToString()); // get the movies that we have yet to watch IEnumerable <TraktLibraryMovies> traktMoviesAll = TraktAPI.TraktAPI.GetAllMoviesForUser(TraktSettings.Username); if (traktMoviesAll == null) { SyncInProgress = false; TraktLogger.Error("Error getting movies from trakt server, cancelling sync."); return; } TraktLogger.Info("{0} movies in trakt library", traktMoviesAll.Count().ToString()); #region Movies to Sync to Collection List <MFMovie> moviesToSync = new List <MFMovie>(MovieList); List <TraktLibraryMovies> NoLongerInOurCollection = new List <TraktLibraryMovies>(); //Filter out a list of movies we have already sync'd in our collection foreach (TraktLibraryMovies tlm in traktMoviesAll) { bool notInLocalCollection = true; // if it is in both libraries foreach (MFMovie libraryMovie in MovieList.Where(m => MovieMatch(m, tlm))) { // If the users IMDb Id is empty/invalid and we have matched one then set it if (BasicHandler.IsValidImdb(tlm.IMDBID) && !BasicHandler.IsValidImdb(libraryMovie.IMDBNumber)) { TraktLogger.Info("Movie '{0}' inserted IMDb Id '{1}'", libraryMovie.Title, tlm.IMDBID); libraryMovie.IMDBNumber = tlm.IMDBID; libraryMovie.Username = TraktSettings.Username; libraryMovie.Commit(); } // If the users TMDb Id is empty/invalid and we have one then set it if (string.IsNullOrEmpty(libraryMovie.TMDBNumber) && !string.IsNullOrEmpty(tlm.TMDBID)) { TraktLogger.Info("Movie '{0}' inserted TMDb Id '{1}'", libraryMovie.Title, tlm.TMDBID); libraryMovie.TMDBNumber = tlm.TMDBID; libraryMovie.Username = TraktSettings.Username; libraryMovie.Commit(); } // if it is watched in Trakt but not My Films update // skip if movie is watched but user wishes to have synced as unseen locally if (tlm.Plays > 0 && !tlm.UnSeen && libraryMovie.Watched == false) { TraktLogger.Info("Movie '{0}' is watched on Trakt updating Database", libraryMovie.Title); libraryMovie.Watched = true; libraryMovie.WatchedCount = tlm.Plays; libraryMovie.Username = TraktSettings.Username; libraryMovie.Commit(); } // mark movies as unseen if watched locally if (tlm.UnSeen && libraryMovie.Watched == true) { TraktLogger.Info("Movie '{0}' is unseen on Trakt, updating database", libraryMovie.Title); libraryMovie.Watched = false; libraryMovie.WatchedCount = tlm.Plays; libraryMovie.Username = TraktSettings.Username; libraryMovie.Commit(); } notInLocalCollection = false; //filter out if its already in collection if (tlm.InCollection) { moviesToSync.RemoveAll(m => MovieMatch(m, tlm)); } break; } if (notInLocalCollection && tlm.InCollection) { NoLongerInOurCollection.Add(tlm); } } #endregion #region Movies to Sync to Seen Collection // filter out a list of movies already marked as watched on trakt // also filter out movie marked as unseen so we dont reset the unseen cache online List <MFMovie> watchedMoviesToSync = new List <MFMovie>(SeenList); foreach (TraktLibraryMovies tlm in traktMoviesAll.Where(t => t.Plays > 0 || t.UnSeen)) { foreach (MFMovie watchedMovie in SeenList.Where(m => MovieMatch(m, tlm))) { //filter out watchedMoviesToSync.Remove(watchedMovie); } } #endregion #region Send Library/Collection TraktLogger.Info("{0} movies need to be added to Library", moviesToSync.Count.ToString()); foreach (MFMovie m in moviesToSync) { TraktLogger.Info("Sending movie to trakt library, Title: {0}, Year: {1}, IMDb: {2}, TMDb: {3}", m.Title, m.Year.ToString(), m.IMDBNumber, m.TMDBNumber); } if (moviesToSync.Count > 0) { TraktSyncResponse response = TraktAPI.TraktAPI.SyncMovieLibrary(CreateSyncData(moviesToSync), TraktSyncModes.library); BasicHandler.InsertSkippedMovies(response); BasicHandler.InsertAlreadyExistMovies(response); TraktAPI.TraktAPI.LogTraktResponse(response); } #endregion #region Send Seen TraktLogger.Info("{0} movies need to be added to SeenList", watchedMoviesToSync.Count.ToString()); foreach (MFMovie m in watchedMoviesToSync) { TraktLogger.Info("Sending movie to trakt as seen, Title: {0}, Year: {1}, IMDb: {2}, TMDb: {3}", m.Title, m.Year.ToString(), m.IMDBNumber, m.TMDBNumber); } if (watchedMoviesToSync.Count > 0) { TraktSyncResponse response = TraktAPI.TraktAPI.SyncMovieLibrary(CreateSyncData(watchedMoviesToSync), TraktSyncModes.seen); BasicHandler.InsertSkippedMovies(response); BasicHandler.InsertAlreadyExistMovies(response); TraktAPI.TraktAPI.LogTraktResponse(response); } #endregion #region Ratings Sync // only sync ratings if we are using Advanced Ratings if (TraktSettings.SyncRatings) { var traktRatedMovies = TraktAPI.TraktAPI.GetUserRatedMovies(TraktSettings.Username); if (traktRatedMovies == null) { TraktLogger.Error("Error getting rated movies from trakt server."); } else { TraktLogger.Info("{0} rated movies in trakt library", traktRatedMovies.Count().ToString()); } if (traktRatedMovies != null) { // get the movies that we have rated/unrated var RatedList = MovieList.Where(m => m.RatingUser > 0.0).ToList(); var UnRatedList = MovieList.Except(RatedList).ToList(); TraktLogger.Info("{0} rated movies available to sync in MyFilms database", RatedList.Count.ToString()); List <MFMovie> ratedMoviesToSync = new List <MFMovie>(RatedList); foreach (var trm in traktRatedMovies) { foreach (var movie in UnRatedList.Where(m => MovieMatch(m, trm))) { // update local collection rating TraktLogger.Info("Inserting rating '{0}/10' for movie '{1} ({2})'", trm.RatingAdvanced, movie.Title, movie.Year); movie.RatingUser = trm.RatingAdvanced; movie.Username = TraktSettings.Username; movie.Commit(); } foreach (var movie in RatedList.Where(m => MovieMatch(m, trm))) { // if rating is not synced, update local collection rating to get in sync if ((int)movie.RatingUser != trm.RatingAdvanced) { TraktLogger.Info("Updating rating '{0}/10' for movie '{1} ({2})'", trm.RatingAdvanced, movie.Title, movie.Year); movie.RatingUser = trm.RatingAdvanced; movie.Username = TraktSettings.Username; movie.Commit(); } // already rated on trakt, so remove from sync collection ratedMoviesToSync.Remove(movie); } } TraktLogger.Info("{0} rated movies to sync to trakt", ratedMoviesToSync.Count); if (ratedMoviesToSync.Count > 0) { ratedMoviesToSync.ForEach(a => TraktLogger.Info("Importing rating '{0}/10' for movie '{1} ({2})'", a.RatingUser, a.Title, a.Year)); TraktResponse response = TraktAPI.TraktAPI.RateMovies(CreateRatingMoviesData(ratedMoviesToSync)); TraktAPI.TraktAPI.LogTraktResponse(response); } } } #endregion #region Clean Library //Dont clean library if more than one movie plugin installed if (TraktSettings.KeepTraktLibraryClean && TraktSettings.MoviePluginCount == 1) { //Remove movies we no longer have in our local database from Trakt foreach (var m in NoLongerInOurCollection) { TraktLogger.Info("Removing from Trakt Collection {0}", m.Title); } TraktLogger.Info("{0} movies need to be removed from Trakt Collection", NoLongerInOurCollection.Count.ToString()); if (NoLongerInOurCollection.Count > 0) { if (TraktSettings.AlreadyExistMovies != null && TraktSettings.AlreadyExistMovies.Movies != null && TraktSettings.AlreadyExistMovies.Movies.Count > 0) { TraktLogger.Warning("DISABLING CLEAN LIBRARY!!!, there are trakt library movies that can't be determined to be local in collection."); TraktLogger.Warning("To fix this, check the 'already exist' entries in log, then check movies in local collection against this list and ensure IMDb id is set then run sync again."); } else { //Then remove from library TraktSyncResponse response = TraktAPI.TraktAPI.SyncMovieLibrary(BasicHandler.CreateMovieSyncData(NoLongerInOurCollection), TraktSyncModes.unlibrary); TraktAPI.TraktAPI.LogTraktResponse(response); } } } #endregion #region Trakt Category Tags List <MFMovie> movieListAll = (from MFMovie movie in myvideos select movie).ToList(); // Add tags also to blocked movies, as it is only local // get the movies that locally have trakt categories var categoryTraktList = movieListAll.Where(m => m.CategoryTrakt.Count > 0).ToList(); if (TraktSettings.MyFilmsCategories) { TraktLogger.Info("{0} trakt-categorized movies available in MyFilms database", categoryTraktList.Count.ToString()); #region update watchlist tags IEnumerable <TraktWatchListMovie> traktWatchListMovies = null; string Watchlist = Translation.WatchList; TraktLogger.Info("Retrieving watchlist from trakt"); traktWatchListMovies = TraktAPI.TraktAPI.GetWatchListMovies(TraktSettings.Username); if (traktWatchListMovies != null) { TraktLogger.Info("Retrieved {0} watchlist items from trakt", traktWatchListMovies.Count()); var cleanupList = movieListAll.Where(m => m.CategoryTrakt.Contains(Watchlist)).ToList(); foreach (var trm in traktWatchListMovies) { TraktLogger.Debug("Processing trakt watchlist movie - Title '{0}', Year '{1}' Imdb '{2}'", trm.Title ?? "null", trm.Year, trm.IMDBID ?? "null"); foreach (var movie in movieListAll.Where(m => MovieMatch(m, trm))) { if (!movie.CategoryTrakt.Contains(Watchlist)) { TraktLogger.Info("Inserting trakt category '{0}' for movie '{1} ({2})'", Watchlist, movie.Title, movie.Year); movie.CategoryTrakt.Add(Watchlist); movie.Username = TraktSettings.Username; movie.Commit(); } cleanupList.Remove(movie); } } // remove tag from remaining films foreach (var movie in cleanupList) { TraktLogger.Info("Removing trakt category '{0}' for movie '{1} ({2})'", Watchlist, movie.Title, movie.Year); movie.CategoryTrakt.Remove(Watchlist); movie.Username = TraktSettings.Username; movie.Commit(); } } #endregion #region update user list tags IEnumerable <TraktUserList> traktUserLists = null; string Userlist = Translation.List; TraktLogger.Info("Retrieving user lists from trakt"); traktUserLists = TraktAPI.TraktAPI.GetUserLists(TraktSettings.Username); if (traktUserLists != null) { TraktLogger.Info("Retrieved {0} user lists from trakt", traktUserLists.Count()); foreach (TraktUserList traktUserList in traktUserLists) { TraktUserList traktUserListMovies = TraktAPI.TraktAPI.GetUserList(TraktSettings.Username, traktUserList.Slug); if (traktUserListMovies == null) { continue; } string userListName = Userlist + ": " + traktUserList.Name; var cleanupList = movieListAll.Where(m => m.CategoryTrakt.Contains(userListName)).ToList(); TraktLogger.Info("Processing trakt user list '{0}' as tag '{1}' with '{2}' items", traktUserList.Name, userListName, traktUserListMovies.Items.Count); // process 'movies' only foreach (var trm in traktUserListMovies.Items.Where(m => m.Type == "movie")) { TraktLogger.Debug("Processing trakt user list movie - Title '{0}', Year '{1}' ImdbId '{2}'", trm.Title ?? "null", trm.Year ?? "null", trm.ImdbId ?? "null"); foreach (var movie in movieListAll.Where(m => MovieMatch(m, trm.Movie))) { if (!movie.CategoryTrakt.Contains(userListName)) { // update local trakt category TraktLogger.Info("Inserting trakt user list '{0}' for movie '{1} ({2})'", userListName, movie.Title, movie.Year); movie.CategoryTrakt.Add(userListName); movie.Username = TraktSettings.Username; movie.Commit(); } cleanupList.Remove(movie); } } // remove tag from remaining films foreach (var movie in cleanupList) { TraktLogger.Info("Removing trakt user list '{0}' for movie '{1} ({2})'", userListName, movie.Title, movie.Year); movie.CategoryTrakt.Remove(userListName); movie.Username = TraktSettings.Username; movie.Commit(); } } } #endregion #region update recommendation tags IEnumerable <TraktMovie> traktRecommendationMovies = null; string Recommendations = Translation.Recommendations; TraktLogger.Info("Retrieving recommendations from trakt"); traktRecommendationMovies = TraktAPI.TraktAPI.GetRecommendedMovies(); if (traktRecommendationMovies != null) { TraktLogger.Info("Retrieved {0} recommendations items from trakt", traktRecommendationMovies.Count()); var cleanupList = movieListAll.Where(m => m.CategoryTrakt.Contains(Recommendations)).ToList(); foreach (var trm in traktRecommendationMovies) { TraktLogger.Debug("Processing trakt recommendations movie - Title '{0}', Year '{1}' Imdb '{2}'", trm.Title ?? "null", trm.Year ?? "null", trm.IMDBID ?? "null"); foreach (var movie in movieListAll.Where(m => MovieMatch(m, trm))) { if (!movie.CategoryTrakt.Contains(Recommendations)) { // update local trakt category TraktLogger.Info("Inserting trakt category '{0}' for movie '{1} ({2})'", Recommendations, movie.Title, movie.Year); movie.CategoryTrakt.Add(Recommendations); movie.Username = TraktSettings.Username; movie.Commit(); } cleanupList.Remove(movie); } } // remove tag from remaining films foreach (var movie in cleanupList) { // update local trakt category TraktLogger.Info("Removing trakt category '{0}' for movie '{1} ({2})'", Recommendations, movie.Title, movie.Year); movie.CategoryTrakt.Remove(Recommendations); movie.Username = TraktSettings.Username; movie.Commit(); } } #endregion #region update trending tags /*IEnumerable<TraktTrendingMovie> traktTrendingMovies = null; * string Trending = Translation.Trending; * TraktLogger.Info("Retrieving trending movies from trakt"); * traktTrendingMovies = TraktAPI.TraktAPI.GetTrendingMovies(); * * if (traktTrendingMovies != null) * { * TraktLogger.Info("Retrieved {0} trending items from trakt", traktTrendingMovies.Count()); * * var cleanupList = movieListAll.Where(m => m.CategoryTrakt.Contains(Trending)).ToList(); * foreach (var trm in traktTrendingMovies) * { * TraktLogger.Debug("Processing trakt user list movie trm.Title '{0}', trm.Year '{1}' trm.Imdb '{2}'", trm.Title ?? "null", trm.Year ?? "null", trm.Imdb ?? "null"); * foreach (var movie in movieListAll.Where(m => MovieMatch(m, trm))) * { * if (!movie.CategoryTrakt.Contains(Trending)) * { * // update local trakt category * TraktLogger.Info("Inserting trakt category '{0}' for movie '{1} ({2})'", Trending, movie.Title, movie.Year); * movie.CategoryTrakt.Add(Trending); * movie.Username = TraktSettings.Username; * movie.Commit(); * } * cleanupList.Remove(movie); * } * } * // remove tag from remaining films * foreach (var movie in cleanupList) * { * // update local trakt category * TraktLogger.Info("Removing trakt category '{0}' for movie '{1} ({2})'", Trending, movie.Title, movie.Year); * movie.CategoryTrakt.Remove(Trending); * movie.Username = TraktSettings.Username; * movie.Commit(); * } * }*/ #endregion } else { if (categoryTraktList.Count > 0) { TraktLogger.Info("clearing trakt-categorized movies from MyFilms database", categoryTraktList.Count.ToString()); foreach (var movie in categoryTraktList) { movie.CategoryTrakt.Clear(); movie.Commit(); } } } #endregion myvideos.Clear(); SyncInProgress = false; TraktLogger.Info("My Films Sync Completed"); }