public bool SyncSeries() { try { TestStatus = "[Trakt.SyncSeries]"; Guid[] types = { MediaAspect.ASPECT_ID, SeriesAspect.ASPECT_ID }; MediaItemQuery mediaItemQuery = new MediaItemQuery(types, null, null); var contentDirectory = ServiceRegistration.Get <IServerConnectionManager>().ContentDirectory; if (contentDirectory == null) { TestStatus = "[Trakt.MediaLibraryNotConnected]"; return(false); } var episodes = contentDirectory.Search(mediaItemQuery, true); var series = episodes.ToLookup(GetSeriesKey); foreach (var serie in series) { var imdbId = serie.Select(episode => { string value; return(MediaItemAspect.TryGetAttribute(episode.Aspects, SeriesAspect.ATTR_IMDB_ID, out value) ? value : null); }).FirstOrDefault(value => !string.IsNullOrWhiteSpace(value)); var tvdbId = serie.Select(episode => { int value; return(MediaItemAspect.TryGetAttribute(episode.Aspects, SeriesAspect.ATTR_TVDB_ID, out value) ? value : 0); }).FirstOrDefault(value => value != 0); TraktEpisodeSync syncData = new TraktEpisodeSync { UserName = Username, Password = Password, EpisodeList = new List <TraktEpisodeSync.Episode>(), Title = serie.Key, Year = serie.Min(e => { int year; string seriesTitle; GetSeriesTitleAndYear(e, out seriesTitle, out year); return(year); }).ToString() }; if (!string.IsNullOrWhiteSpace(imdbId)) { syncData.IMDBID = imdbId; } if (tvdbId > 0) { syncData.SeriesID = tvdbId.ToString(); } HashSet <TraktEpisodeSync.Episode> uniqueEpisodes = new HashSet <TraktEpisodeSync.Episode>(); foreach (var episode in serie) { string seriesTitle; int year = 0; if (!GetSeriesTitle/*AndYear*/ (episode, out seriesTitle /*, out year*/)) { continue; } // First send all movies to Trakt that we have so they appear in library CollectionUtils.AddAll(uniqueEpisodes, ToSeries(episode)); } syncData.EpisodeList = uniqueEpisodes.ToList(); TraktSyncModes traktSyncMode = TraktSyncModes.library; var response = TraktAPI.SyncEpisodeLibrary(syncData, traktSyncMode); ServiceRegistration.Get <ILogger>().Info("Trakt.tv: Series '{0}' '{1}': {2}{3}", syncData.Title, traktSyncMode, response.Message, response.Error); // Then send only the watched movies as "seen" uniqueEpisodes.Clear(); foreach (var seenEpisode in episodes.Where(IsWatched)) { CollectionUtils.AddAll(uniqueEpisodes, ToSeries(seenEpisode)); } syncData.EpisodeList = uniqueEpisodes.ToList(); traktSyncMode = TraktSyncModes.seen; response = TraktAPI.SyncEpisodeLibrary(syncData, traktSyncMode); ServiceRegistration.Get <ILogger>().Info("Trakt.tv: Series '{0}' '{1}': {2}{3}", syncData.Title, traktSyncMode, response.Message, response.Error); return(true); } } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Error("Trakt.tv: Exception while synchronizing media library.", ex); } return(false); }
public static void SynchronizeLibrary(List <DBEpisode> episodes, TraktSyncModes mode) { if (episodes.Count == 0) { return; } // get unique series ids var uniqueSeriesIDs = (from seriesIDs in episodes select seriesIDs[DBEpisode.cSeriesID].ToString()).Distinct().ToList(); // go over each series, can only send one series at a time foreach (string seriesID in uniqueSeriesIDs) { DBSeries series = Helper.getCorrespondingSeries(int.Parse(seriesID)); if (series == null || series[DBOnlineSeries.cTraktIgnore]) { continue; } MPTVSeriesLog.Write("Trakt: Synchronizing '{0}' episodes for series '{1}'.", mode.ToString(), series.ToString()); TraktSync traktSync = GetTraktSyncObject(series, episodes); // upload to trakt TraktResponse response = TraktAPI.SyncEpisodeLibrary(traktSync, mode); if (response == null) { MPTVSeriesLog.Write("Trakt Error: Response from server was unexpected."); continue; } // check for any error and log result CheckTraktErrorAndNotify(response, false); if (response.Status == "success") { SQLCondition conditions = new SQLCondition(); // flag episodes and commit to database switch (mode) { case TraktSyncModes.seen: conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, seriesID, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cWatched, 1, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cHidden, 0, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cTraktSeen, 0, SQLConditionType.Equal); // we always flag traktLibrary field as the 'traktSeen' field counts as part of library DBOnlineEpisode.GlobalSet(new DBOnlineEpisode(), DBOnlineEpisode.cTraktLibrary, 1, conditions); DBOnlineEpisode.GlobalSet(new DBOnlineEpisode(), DBOnlineEpisode.cTraktSeen, 1, conditions); break; case TraktSyncModes.library: // we can't do a global set as our conditions are from two different tables // where filename is not empty and traktLibrary = 0 foreach (DBEpisode ep in episodes.Where(e => e[DBEpisode.cSeriesID] == seriesID)) { ep[DBOnlineEpisode.cTraktLibrary] = 1; ep.Commit(); } break; case TraktSyncModes.unseen: conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, seriesID, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cHidden, 0, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cTraktSeen, 2, SQLConditionType.Equal); DBOnlineEpisode.GlobalSet(new DBOnlineEpisode(), DBOnlineEpisode.cTraktSeen, 0, conditions); break; case TraktSyncModes.unlibrary: break; } } // wait a short period before uploading another series Thread.Sleep(2000); } }