// Loads an Image from a File by invoking GDI Plus instead of using build-in // .NET methods, or falls back to Image.FromFile. GDI Plus should be faster. public static Image LoadImageFastFromFile(string filename) { IntPtr imagePtr = IntPtr.Zero; Image image = null; try { if (GdipLoadImageFromFile(filename, out imagePtr) != 0) { image = LoadImageSafe(filename); } else { image = (Image)typeof(Bitmap).InvokeMember("FromGDIplus", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new object[] { imagePtr }); } } catch (Exception e) { TraktLogger.Warning("Failed to load image {0}: {1}", filename, e.Message); image = null; } return(image); }
/// <summary> /// Download an image if it does not exist locally /// </summary> /// <param name="url">Online URL of image to download</param> /// <param name="localFile">Local filename to save image</param> /// <returns>true if image downloads successfully or loads from disk successfully</returns> public static bool DownloadImage(string url, string localFile) { WebClient webClient = new WebClient(); webClient.Headers.Add("user-agent", TraktSettings.UserAgent); try { Directory.CreateDirectory(Path.GetDirectoryName(localFile)); if (!File.Exists(localFile)) { TraktLogger.Debug("Downloading new image. Url = '{0}', Filename = '{1}'", url, localFile); webClient.DownloadFile(url, localFile); } return(true); } catch (Exception) { TraktLogger.Warning("Image download failed. Url = '{0}', Filename = '{1}'", url, localFile); try { if (File.Exists(localFile)) { File.Delete(localFile); } } catch { } return(false); } }
static void PlayTrailer(string url, PlayerFactory factory, bool?preparedPlayerResult) { if (preparedPlayerResult != null) { (factory.PreparedPlayer as OVSPLayer).GoFullscreen = true; var savedFactory = g_Player.Factory; g_Player.Factory = factory; try { g_Player.Play(factory.PreparedUrl, g_Player.MediaType.Video); } catch (Exception e) { TraktLogger.Warning("Exception while playing trailer: {0}", e.Message); } g_Player.Factory = savedFactory; } else { factory.PreparedPlayer.Dispose(); GUIUtils.ShowNotifyDialog(GUI.Translation.Error, GUI.Translation.UnableToPlayTrailer); } }
/// <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); }
/// <summary> /// Shows the Rate Episode Dialog after playback has ended /// </summary> /// <param name="episode">The episode being rated</param> private void ShowRateDialog(FileLocal episode) { new Thread((o) => { FileLocal epToRate = o as FileLocal; if (epToRate == null) { return; } string seriesid = null; int seasonidx = 0; int episodeidx = 0; if (epToRate.AnimeEpisodes == null || epToRate.AnimeEpisodes.Count == 0 || !GetTVDBEpisodeInfo(epToRate.AnimeEpisodes[0], out seriesid, out seasonidx, out episodeidx)) { TraktLogger.Warning("Unable to rate episode, no AniDb/TVDb reference in database yet."); return; } if (!TraktSettings.ShowRateDialogOnWatched) { return; // not enabled } if (epToRate.AnimeEpisodes[0].UserRating > 0) { return; // already rated } TraktLogger.Debug("Showing rate dialog for '{0}'", epToRate.AnimeEpisodes[0].EpisodeName); TraktRateEpisode rateObject = new TraktRateEpisode { Title = epToRate.AniDB_File.AnimeSeries.SeriesName, Year = GetStartYear(epToRate.AniDB_File.AnimeSeries), Season = seasonidx.ToString(), Episode = episodeidx.ToString(), SeriesID = seriesid, UserName = TraktSettings.Username, Password = TraktSettings.Password }; // get the rating submitted to trakt int rating = int.Parse(GUIUtils.ShowRateDialog <TraktRateEpisode>(rateObject)); if (rating > 0) { TraktLogger.Debug("Rating {0} as {1}/10", epToRate.AnimeEpisodes[0].EpisodeName, rating.ToString()); // note: can't set rating locally as its read only } }) { Name = "Rate", IsBackground = true }.Start(episode); }
/// <summary> /// Creates Sync Data based on Series object and a List of Episode objects /// </summary> /// <param name="series">The series to base the object on</param> /// <param name="epsiodes">The list of episodes to base the object on</param> /// <returns>The Trakt Sync data to send</returns> private TraktEpisodeSync CreateSyncData(AnimeSeries series, List <FileLocal> episodes) { if (series == null || series.TvDB_ID == null) { return(null); } // set series properties for episodes TraktEpisodeSync traktSync = new TraktEpisodeSync { Password = TraktSettings.Password, UserName = TraktSettings.Username, SeriesID = series.TvDB_ID.ToString(), Year = GetStartYear(series), Title = series.SeriesName }; // get list of episodes for series List <TraktEpisodeSync.Episode> epList = new List <TraktEpisodeSync.Episode>(); foreach (FileLocal file in episodes.Where(e => (e.AniDB_File != null && e.AniDB_File.AnimeSeries.TvDB_ID == series.TvDB_ID))) { TraktEpisodeSync.Episode episode = new TraktEpisodeSync.Episode(); // can have multiple episodes linked to a file? foreach (var ep in file.AnimeEpisodes) { string seriesid = series.TvDB_ID.ToString(); int seasonidx = 0; int episodeidx = 0; if (GetTVDBEpisodeInfo(ep, out seriesid, out seasonidx, out episodeidx)) { episode.SeasonIndex = seasonidx.ToString(); episode.EpisodeIndex = episodeidx.ToString(); epList.Add(episode); } else { TraktLogger.Info("Unable to find match for episode: '{0} | airDate: {1}'", ep.ToString(), ep.AniDB_Episode.AirDateAsDate.ToString("yyyy-MM-dd")); } } } if (epList.Count == 0) { TraktLogger.Warning("Unable to find any matching TVDb episodes for series '{0}', confirm Absolute Order and/or Episode Names and/or AirDates for episodes are correct on http://theTVDb.com and your database.", series.SeriesName); return(null); } traktSync.EpisodeList = epList; return(traktSync); }
public bool Scrobble(string filename) { StopScrobble(); if (!g_Player.IsTVRecording) { return(false); } // get recording details from tv database TvBusinessLayer layer = new TvBusinessLayer(); Recording recording = layer.GetRecordingByFileName(filename); if (recording == null || string.IsNullOrEmpty(recording.Title)) { TraktLogger.Warning("Unable to get recording details from database"); return(false); } // get year from title if available, some EPG entries contain this string title = null; string year = null; BasicHandler.GetTitleAndYear(recording.Title, out title, out year); CurrentRecording = new VideoInfo { Type = !string.IsNullOrEmpty(recording.EpisodeNum) || !string.IsNullOrEmpty(recording.SeriesNum) ? VideoType.Series : VideoType.Movie, Title = title, Year = year, SeasonIdx = recording.SeriesNum, EpisodeIdx = recording.EpisodeNum, IsScrobbling = true }; TraktLogger.Info("Current program details. Title='{0}', Year='{1}', Season='{2}', Episode='{3}', StartTime='{4}', Runtime='{5}'", CurrentRecording.Title, CurrentRecording.Year.ToLogString(), CurrentRecording.SeasonIdx.ToLogString(), CurrentRecording.EpisodeIdx.ToLogString(), CurrentRecording.StartTime == null ? "<empty>" : CurrentRecording.StartTime.ToString(), CurrentRecording.Runtime); if (CurrentRecording.Type == VideoType.Series) { TraktLogger.Info("Detected tv show playing in TV Recordings. Title = '{0}'", CurrentRecording.ToString()); } else { TraktLogger.Info("Detected movie playing in TV Recordings. Title = '{0}'", CurrentRecording.ToString()); } BasicHandler.StartScrobble(CurrentRecording); return(true); }
private static string ValidateLayoutType(string layout) { switch (layout.ToLowerInvariant()) { case "list": return("List"); case "smallicons": return("SmallIcons"); case "largeicons": return("LargeIcons"); case "filmstrip": return("Filmstrip"); default: TraktLogger.Warning("Invalid MediaPortal layout '{0}' defined in the skin settings", layout); return("None"); } }
/// <summary> /// Loads an image FAST from file /// </summary> /// <param name="filename"></param> /// <returns></returns> public static Image LoadImage(string file) { if (string.IsNullOrEmpty(file) || !File.Exists(file)) { return(null); } Image img = null; try { img = ImageFast.FromFile(file); } catch { // Most likely a Zero Byte file but not always TraktLogger.Warning("Fast loading of texture {0} failed - trying safe fallback now", file); try { img = Image.FromFile(file); } catch { } } return(img); }
public static void SetProperty(string property, string value, bool log) { // prevent ugly display of property names if (string.IsNullOrEmpty(value)) { value = " "; } GUIPropertyManager.SetProperty(property, value); if (log) { if (GUIPropertyManager.Changed) { TraktLogger.Debug("Set property \"" + property + "\" to \"" + value + "\" successful"); } else { TraktLogger.Warning("Set property \"" + property + "\" to \"" + value + "\" failed"); } } }
/// <summary> /// Sends a Thread message to select an item on a facade object. Will only send if itemid parameter is currently selected /// </summary> /// <param name="self">the list object</param> /// <param name="windowId">the window id containing list control</param> /// <param name="index">the item id in list to check if selected</param> /// <param name="controlId">the id of the list control, defaults to 50</param> public static void UpdateItemIfSelected(this GUIListItem self, int windowId, int index, int controlId = 50) { if (GUIWindowManager.ActiveWindow != windowId) { return; } try { GUIListItem selectedItem = GUIControl.GetSelectedListItem(windowId, controlId); // only send message if the current item is selected if (selectedItem == self) { GUIWindowManager.SendThreadMessage(new GUIMessage(GUIMessage.MessageType.GUI_MSG_ITEM_SELECT, GUIWindowManager.ActiveWindow, 0, controlId, index, 0, null)); } } catch (Exception) { TraktLogger.Warning("Unable to update selected facade item, MediaPortal could not get a reference"); } }
public static string Encrypt(this string plainText, string passPhrase) { if (string.IsNullOrEmpty(plainText)) { return(plainText); } try { byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); using (PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null)) { byte[] keyBytes = password.GetBytes(keysize / 8); using (RijndaelManaged symmetricKey = new RijndaelManaged()) { symmetricKey.Mode = CipherMode.CBC; using (ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes)) { using (MemoryStream memoryStream = new MemoryStream()) { using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) { cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); cryptoStream.FlushFinalBlock(); byte[] cipherTextBytes = memoryStream.ToArray(); return(Convert.ToBase64String(cipherTextBytes)); } } } } } } catch (Exception ex) { TraktLogger.Warning("Failed to encyrpt password!. Reason = '{0}'", ex.Message); return(null); } }
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); } }
/// <summary> /// Download an image if it does not exist locally /// </summary> /// <param name="url">Online URL of image to download</param> /// <param name="localFile">Local filename to save image</param> /// <returns>true if image downloads successfully or loads from disk successfully</returns> public static bool DownloadImage(string url, string localFile) { WebClient webClient = new WebClient(); webClient.Headers.Add("user-agent", TraktSettings.UserAgent); // Ignore Image placeholders (series/movies with no artwork) // use skins default images instead if (url.Contains("poster-small") || url.Contains("fanart-summary")) { return(false); } if (url.Contains("poster-dark") || url.Contains("fanart-dark") || url.Contains("episode-dark")) { return(false); } try { Directory.CreateDirectory(Path.GetDirectoryName(localFile)); if (!File.Exists(localFile)) { TraktLogger.Debug("Downloading new image from: {0}", url); webClient.DownloadFile(url, localFile); } return(true); } catch (Exception) { TraktLogger.Warning("Image download failed from '{0}' to '{1}'", url, localFile); try { if (File.Exists(localFile)) { File.Delete(localFile); } } catch { } return(false); } }
public static string Decrypt(this string cipherText, string passPhrase) { if (string.IsNullOrEmpty(cipherText)) { return(cipherText); } try { byte[] cipherTextBytes = Convert.FromBase64String(cipherText); using (PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null)) { byte[] keyBytes = password.GetBytes(keysize / 8); using (RijndaelManaged symmetricKey = new RijndaelManaged()) { symmetricKey.Mode = CipherMode.CBC; using (ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes)) { using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes)) { using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) { byte[] plainTextBytes = new byte[cipherTextBytes.Length]; int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); return(Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount)); } } } } } } catch (Exception ex) { TraktLogger.Warning("Failed to decyrpt password!. Reason = '{0}'", ex.Message); return(null); } }
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 SyncProgress() { if (!TraktSettings.SyncPlayback || SyncPlaybackInProgress) { return; } SyncPlaybackInProgress = true; TraktLogger.Info("My Videos Starting Playback Sync"); // get playback data from trakt string lastPausedAtMovie; var playbackData = TraktCache.GetPausedMovies(out lastPausedAtMovie); if (playbackData == null) { TraktLogger.Warning("Failed to get resume data from trakt.tv"); SyncPlaybackInProgress = false; return; } DateTime lastPausedItemProcessed; DateTime.TryParse(lastPausedAtMovie, out lastPausedItemProcessed); TraktLogger.Info("Found {0} movies on trakt.tv with resume data, processing paused movies after {1}", playbackData.Where(p => p.Type == "movie").Count(), lastPausedAtMovie); foreach (var item in playbackData.Where(p => p.Type == "movie")) { DateTime itemPausedAt; if (DateTime.TryParse(item.PausedAt, out itemPausedAt)) { // check if we need to process if (itemPausedAt <= lastPausedItemProcessed) { continue; } } // get movie from local database if it exists var movie = GetMovies().FirstOrDefault(m => ((m.IMDBNumber == item.Movie.Ids.Imdb) && !string.IsNullOrEmpty(item.Movie.Ids.Imdb) || m.Title.ToLowerInvariant() == item.Movie.Title.ToLowerInvariant() && m.Year == item.Movie.Year)); if (movie == null) { continue; } // if the local playtime is not known then skip if (movie.Duration <= 0) { TraktLogger.Warning("Skipping item with invalid runtime in database, Title = '{0}', Year = '{1}', IMDb ID = '{2}'", item.Movie.Title, item.Movie.Year, item.Movie.Ids.Imdb); continue; } // update the stop time based on percentage watched // the video database stores duration in seconds (runtime in minutes if duration not available) and stopTime in secs var resumeData = Convert.ToInt32(movie.Duration * (item.Progress / 100.0)) - TraktSettings.SyncResumeDelta; if (resumeData < 0) { resumeData = 0; } if (string.IsNullOrEmpty(movie.VideoFileName)) { TraktLogger.Warning("Skipping item with invalid filename in database, Title = '{0}', Year = '{1}', IMDb ID = '{2}'", item.Movie.Title, item.Movie.Year, item.Movie.Ids.Imdb); continue; } // if we are syncing on plugin entry we could possibly still be sending paused data to trakt // after stopping video (stopping video == re-entry to plugin), prevent possibly reverting stale resumed data // we already have updated resume data when stopping video in real-time if (TraktSettings.SyncPlaybackOnEnterPlugin && LastMovie != null && LastMovie.VideoFileName == movie.VideoFileName) { continue; } // check if movie is restricted if (TraktSettings.BlockedFilenames.Any(f => f == movie.VideoFileName) || TraktSettings.BlockedFolders.Any(f => f == Path.GetDirectoryName(movie.VideoFileName))) { TraktLogger.Info("Ignoring resume data sync for movie, filename/folder is ignored by user. Title = '{0}', Year = '{1}', IMDb ID = '{2}', Filename = '{3}'", item.Movie.Title, item.Movie.Year, item.Movie.Ids.Imdb, movie.VideoFileName); continue; } // Get FileId from filename int fileId = VideoDatabase.GetMovieId(movie.VideoFileName); // get current stop time for movie int currentResumeData = VideoDatabase.GetMovieStopTime(fileId); if (currentResumeData != resumeData) { // Note: will need to be a bit smarter for multi-part files (who the heck still does that!) TraktLogger.Info("Setting resume time '{0}' for movie, Title = '{1}', Year = '{2}', IMDb ID = '{3}'", new TimeSpan(0, 0, 0, resumeData), item.Movie.Title, item.Movie.Year, item.Movie.Ids.Imdb); VideoDatabase.SetMovieStopTime(fileId, resumeData); } } TraktLogger.Info("My Videos Playback Sync Completed"); SyncPlaybackInProgress = false; return; }
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"); }
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"); }