Пример #1
0
        /// <summary>
        /// Creates Sync Data based on a TraktLibraryShows object
        /// </summary>
        /// <param name="show">The show to base the object on</param>
        /// <returns>The Trakt Sync data to send</returns>
        public static TraktEpisodeSync CreateEpisodeSyncData(TraktLibraryShow show)
        {
            TraktEpisodeSync syncData = new TraktEpisodeSync
            {
                SeriesID = show.SeriesId,
                Title    = show.Title,
                UserName = TraktSettings.Username,
                Password = TraktSettings.Password
            };

            var episodes = new List <TraktEpisodeSync.Episode>();

            foreach (var season in show.Seasons)
            {
                foreach (var episode in season.Episodes)
                {
                    episodes.Add(new TraktEpisodeSync.Episode
                    {
                        EpisodeIndex = episode.ToString(),
                        SeasonIndex  = season.Season.ToString()
                    });
                }
            }

            syncData.EpisodeList = episodes;

            return(syncData);
        }
        private TraktEpisodeSync CreateEpisodeSyncData(TraktUserListItem item)
        {
            if (item == null)
            {
                return(null);
            }

            TraktEpisodeSync.Episode syncEpisode = new TraktEpisodeSync.Episode
            {
                EpisodeIndex = item.EpisodeNumber.ToString(),
                SeasonIndex  = item.SeasonNumber.ToString()
            };

            TraktEpisodeSync syncData = new TraktEpisodeSync
            {
                UserName    = TraktSettings.Username,
                Password    = TraktSettings.Password,
                SeriesID    = item.Show.Tvdb,
                Title       = item.Show.Title,
                Year        = item.Year,
                EpisodeList = new List <TraktEpisodeSync.Episode> {
                    syncEpisode
                }
            };

            return(syncData);
        }
Пример #3
0
        private TraktEpisodeSync CreateSyncData(KeyValuePair <TraktShow, TraktWatchListEpisode.Episode> item)
        {
            var series  = item.Key;
            var episode = item.Value;

            List <TraktEpisodeSync.Episode> episodes = new List <TraktEpisodeSync.Episode>();

            TraktEpisodeSync.Episode ep = new TraktEpisodeSync.Episode
            {
                EpisodeIndex = episode.Number.ToString(),
                SeasonIndex  = episode.Season.ToString()
            };
            episodes.Add(ep);

            TraktEpisodeSync syncData = new TraktEpisodeSync
            {
                UserName    = TraktSettings.Username,
                Password    = TraktSettings.Password,
                SeriesID    = series.Tvdb,
                Title       = series.Title,
                Year        = series.Year.ToString(),
                EpisodeList = episodes
            };

            return(syncData);
        }
Пример #4
0
        private void OnToggleWatched(List <AnimeEpisode> episodes, bool state)
        {
            if (TraktSettings.AccountStatus != ConnectionState.Connected)
            {
                return;
            }

            TraktLogger.Info("Received togglewatched event from my anime");

            Thread toggleWatched = new Thread(delegate()
            {
                foreach (var series in episodes.Select(e => e.Series.TvDB_ID).Distinct().ToList())
                {
                    if (series == null)
                    {
                        continue;
                    }
                    TraktEpisodeSync episodeSyncData = CreateSyncData(AnimeSeries.GetSeriesWithSpecificTvDB((int)series).First(), episodes);
                    if (episodeSyncData == null)
                    {
                        return;
                    }
                    TraktResponse response = TraktAPI.TraktAPI.SyncEpisodeLibrary(episodeSyncData, state ? TraktSyncModes.seen : TraktSyncModes.unseen);
                    TraktAPI.TraktAPI.LogTraktResponse(response);
                }
            })
            {
                IsBackground = true,
                Name         = "ToggleWatched"
            };

            toggleWatched.Start();
        }
Пример #5
0
        /// <summary>
        /// Removes all episode ratings from trakt
        /// </summary>
        /// <param name="syncData">list of episodes</param>
        public static TraktSyncResponse RemoveEpisodesFromRatings(TraktEpisodeSync syncData)
        {
            if (syncData == null)
            {
                return(null);
            }

            var response = TraktWeb.PostToTrakt(TraktURIs.SyncRatingsRemove, syncData.ToJSON());

            return(response.FromJSON <TraktSyncResponse>());
        }
Пример #6
0
        /// <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);
        }
Пример #7
0
        /// <summary>
        /// Sends episode sync data to Trakt Watchlist
        /// </summary>
        /// <param name="syncData">The sync data to send</param>
        /// <returns>The response from trakt</returns>
        public static TraktSyncResponse AddEpisodesToWatchlist(TraktEpisodeSync syncData)
        {
            // check that we have everything we need
            if (syncData == null || syncData.Episodes == null || syncData.Episodes.Count == 0)
                return null;

            // serialize data to JSON and send to server
            string response = TraktWeb.PostToTrakt(TraktURIs.SyncWatchlist, syncData.ToJSON());

            // return success or failure
            return response.FromJSON<TraktSyncResponse>();
        }
Пример #8
0
        /// <summary>
        /// Sends episode sync data to Trakt Watchlist
        /// </summary>
        /// <param name="syncData">The sync data to send</param>
        /// <returns>The response from trakt</returns>
        public static TraktSyncResponse AddEpisodesToWatchlist(TraktEpisodeSync syncData)
        {
            // check that we have everything we need
            if (syncData == null || syncData.Episodes == null || syncData.Episodes.Count == 0)
            {
                return(null);
            }

            // serialize data to JSON and send to server
            string response = TraktWeb.PostToTrakt(TraktURIs.SyncWatchlist, syncData.ToJSON());

            // return success or failure
            return(response.FromJSON <TraktSyncResponse>());
        }
Пример #9
0
        /// <summary>
        /// Sends episode sync data to Trakt
        /// </summary>
        /// <param name="syncData">The sync data to send</param>
        /// <param name="mode">The sync mode to use</param>
        public static TraktResponse SyncEpisodeLibrary(TraktEpisodeSync syncData, TraktSyncModes mode)
        {
            // check that we have everything we need
            if (syncData == null || string.IsNullOrEmpty(syncData.SeriesID))
            {
                return(null);
            }

            // serialize data to JSON and send to server
            string response = TraktWeb.Transmit(string.Format(TraktURIs.SyncEpisodeLibrary, mode.ToString()), syncData.ToJSON());

            // return success or failure
            return(response.FromJSON <TraktResponse>());
        }
Пример #10
0
        public static void RemoveEpisodesFromWatchlist()
        {
            if (Cancel)
            {
                return;
            }

            UIUtils.UpdateStatus("Getting watchlisted episodes from trakt.tv");
            var watchlistedEpisodes = TraktAPI.TraktAPI.GetWatchlistEpisodes();

            if (watchlistedEpisodes != null)
            {
                UIUtils.UpdateStatus("Found {0} episodes watchlisted on trakt.tv", watchlistedEpisodes.Count());

                int pageSize = AppSettings.BatchSize;
                int pages    = (int)Math.Ceiling((double)watchlistedEpisodes.Count() / pageSize);
                for (int i = 0; i < pages; i++)
                {
                    if (Cancel)
                    {
                        return;
                    }

                    var syncData = new TraktEpisodeSync
                    {
                        Episodes = watchlistedEpisodes.Select(r => new TraktEpisode {
                            Ids = r.Episode.Ids
                        })
                                   .Skip(i * pageSize).Take(pageSize).ToList()
                    };

                    UIUtils.UpdateStatus("[{0}/{1}] Removing episodes from trakt.tv watchlist", i + 1, pages);
                    var syncResponse = TraktAPI.TraktAPI.RemoveEpisodesFromWatchlist(syncData);
                    if (syncResponse == null)
                    {
                        UIUtils.UpdateStatus(string.Format("[{0}/{1}] Failed to remove episodes from trakt.tv watchlist", i + 1, pages), true);
                        Thread.Sleep(2000);
                        continue;
                    }
                }
            }
            else
            {
                UIUtils.UpdateStatus("Failed to get current list of watchlisted episodes from trakt.tv", true);
                Thread.Sleep(2000);
            }
        }
Пример #11
0
        public static TraktEpisodeSync CreateEpisodeSyncData(string title, string year, string tvdbid, string seasonidx, string episodeidx)
        {
            TraktEpisodeSync syncData = new TraktEpisodeSync
            {
                SeriesID    = tvdbid,
                Title       = title,
                EpisodeList = new List <TraktEpisodeSync.Episode> {
                    new TraktEpisodeSync.Episode {
                        EpisodeIndex = episodeidx, SeasonIndex = seasonidx
                    }
                },
                UserName = TraktSettings.Username,
                Password = TraktSettings.Password
            };

            return(syncData);
        }
Пример #12
0
        /// <summary>
        /// returns a list of shows with episodes to mark as watched
        /// must send to trakt per show!
        /// </summary>
        private List <TraktEpisodeSync> GetWatchedEpisodeData(List <TraktEpisode> episodes)
        {
            var traktEpisodesSync = new List <TraktEpisodeSync>();

            // seperate episodes list into shows
            foreach (var showId in episodes.Select(e => e.TVDbId).Distinct())
            {
                var episodesInShow      = episodes.Where(e => e.TVDbId == showId);
                var episodesWatchedData = new List <TraktEpisodeSync.Episode>();

                if (episodesInShow.Count() == 0)
                {
                    continue;
                }

                episodesWatchedData.AddRange(from episode in episodesInShow
                                             select new TraktEpisodeSync.Episode
                {
                    EpisodeIndex = episode.Episode.ToString(),
                    SeasonIndex  = episode.Season.ToString()
                });

                if (episodesWatchedData.Count() == 0)
                {
                    continue;
                }

                var episodeSyncData = new TraktEpisodeSync
                {
                    UserName    = AppSettings.TraktUsername,
                    Password    = AppSettings.TraktPassword,
                    EpisodeList = episodesWatchedData,
                    SeriesID    = showId.ToString(),
                    Title       = episodesInShow.First().Title,
                    Year        = episodesInShow.First().Year.ToString()
                };

                traktEpisodesSync.Add(episodeSyncData);
            }

            return(traktEpisodesSync);
        }
Пример #13
0
        /// <summary>
        /// Syncronize our collection on trakt
        /// </summary>
        /// <param name="episodes">local tvseries dbepisode list</param>
        /// <param name="mode">trakt sync mode</param>
        private void SyncLibrary(List <FileLocal> episodes, TraktSyncModes mode)
        {
            if (episodes.Count == 0)
            {
                return;
            }

            // get unique series ids
            var uniqueSeries = (from s in episodes where (s.AniDB_File != null && s.AniDB_File.AnimeSeries.TvDB_ID > 0) select s.AniDB_File.AnimeSeries.TvDB_ID).Distinct().ToList();

            if (uniqueSeries.Count == 0)
            {
                TraktLogger.Info("TVDb info not available for series, can not sync '{0}' with trakt.", mode.ToString());
            }

            // go over each series, can only send one series at a time
            foreach (int seriesid in uniqueSeries)
            {
                // There should only be one series
                List <AnimeSeries> series = AnimeSeries.GetSeriesWithSpecificTvDB(seriesid);
                if (series == null)
                {
                    continue;
                }

                TraktLogger.Info("Synchronizing '{0}' episodes for series '{1}'.", mode.ToString(), series[0].ToString());

                // upload to trakt
                TraktEpisodeSync episodeSync = CreateSyncData(series[0], episodes);
                if (episodeSync != null)
                {
                    TraktResponse response = TraktAPI.TraktAPI.SyncEpisodeLibrary(episodeSync, mode);

                    // check for any error and log result
                    TraktAPI.TraktAPI.LogTraktResponse(response);

                    // wait a short period before uploading another series
                    Thread.Sleep(2000);
                }
            }
        }
Пример #14
0
        /// <summary>
        /// Removes episodes on trakt that no longer exist in users database
        /// </summary>
        /// <param name="traktShows">trakt episode collection</param>
        /// <param name="episodes">list of local episodes</param>
        /// <param name="seriesID">tvdb series id of series</param>
        /// <returns>true if episode exists</returns>
        private TraktEpisodeSync GetEpisodesForTraktRemoval(TraktLibraryShow traktShow, List <FileLocal> episodes)
        {
            List <TraktEpisodeSync.Episode> episodeList = new List <TraktEpisodeSync.Episode>();

            foreach (var season in traktShow.Seasons)
            {
                foreach (var episode in season.Episodes)
                {
                    var query = episodes.Where(e => e.AniDB_File != null && e.AniDB_File.AnimeSeries.TvDB_ID.ToString() == traktShow.SeriesId &&
                                               e.AniDB_File.AnimeSeries.TvDB_Episodes.Where(t => !string.IsNullOrEmpty(t.Filename) && t.SeasonNumber == season.Season && t.EpisodeNumber == episode).Count() == 1).ToList();

                    if (query.Count == 0)
                    {
                        // we dont have the episode anymore
                        TraktLogger.Info("{0} - {1}x{2} does not exist in local database, marked for removal from trakt", traktShow.ToString(), season.Season.ToString(), episode.ToString());

                        TraktEpisodeSync.Episode ep = new TraktEpisodeSync.Episode
                        {
                            EpisodeIndex = episode.ToString(),
                            SeasonIndex  = season.Season.ToString()
                        };
                        episodeList.Add(ep);
                    }
                }
            }

            if (episodeList.Count > 0)
            {
                TraktEpisodeSync syncData = new TraktEpisodeSync
                {
                    UserName    = TraktSettings.Username,
                    Password    = TraktSettings.Password,
                    SeriesID    = traktShow.SeriesId,
                    EpisodeList = episodeList
                };
                return(syncData);
            }
            return(null);
        }
Пример #15
0
        private TraktEpisodeSync CreateEpisodeSyncData(TraktEpisode episode)
        {
            List <TraktEpisodeSync.Episode> episodes = new List <TraktEpisodeSync.Episode>();

            TraktEpisodeSync.Episode ep = new TraktEpisodeSync.Episode
            {
                EpisodeIndex = episode.Number.ToString(),
                SeasonIndex  = episode.Season.ToString()
            };
            episodes.Add(ep);

            TraktEpisodeSync syncData = new TraktEpisodeSync
            {
                UserName    = TraktSettings.Username,
                Password    = TraktSettings.Password,
                SeriesID    = Show.Tvdb,
                Title       = Show.Title,
                Year        = Show.Year.ToString(),
                EpisodeList = episodes
            };

            return(syncData);
        }
Пример #16
0
        public static void RemoveEpisodeFromLibrary(string title, string year, string tvdbid, string seasonidx, string episodeidx)
        {
            TraktEpisodeSync syncObject = BasicHandler.CreateEpisodeSyncData(title, year, tvdbid, seasonidx, episodeidx);

            if (syncObject == null)
            {
                return;
            }

            Thread syncThread = new Thread(delegate(object obj)
            {
                TraktResponse response = TraktAPI.TraktAPI.SyncEpisodeWatchList((obj as TraktEpisodeSync), TraktSyncModes.unlibrary);
                if (response == null || response.Status != "success")
                {
                    return;
                }
            })
            {
                IsBackground = true,
                Name         = "RemoveLibrary"
            };

            syncThread.Start(syncObject);
        }
Пример #17
0
        public static TraktEpisodeSync GetTraktEpisodeData(IEnumerable <IMDbEpisode> episodes)
        {
            if (episodes == null)
            {
                return(null);
            }

            var traktEpisodes = new List <TraktEpisode>();

            traktEpisodes.AddRange(from episode in episodes
                                   select new TraktEpisode
            {
                Ids = new TraktEpisodeId {
                    TvdbId = episode.TvdbId, ImdbId = episode.ImdbId
                }
            });

            var episodeSync = new TraktEpisodeSync
            {
                Episodes = traktEpisodes
            };

            return(episodeSync);
        }
Пример #18
0
        public static void RemoveEpisodesFromRatings()
        {
            if (Cancel) return;

            UIUtils.UpdateStatus("Getting rated episodes from trakt.tv");
            var ratedEpisodes = TraktAPI.TraktAPI.GetRatedEpisodes();
            if (ratedEpisodes != null)
            {
                UIUtils.UpdateStatus("Found {0} episodes rated on trakt.tv", ratedEpisodes.Count());

                int pageSize = AppSettings.BatchSize;
                int pages = (int)Math.Ceiling((double)ratedEpisodes.Count() / pageSize);
                for (int i = 0; i < pages; i++)
                {
                    if (Cancel) return;

                    var syncData = new TraktEpisodeSync
                    {
                        Episodes = ratedEpisodes.Select(r => new TraktEpisode { Ids = r.Episode.Ids })
                                                .Skip(i * pageSize).Take(pageSize).ToList()
                    };

                    UIUtils.UpdateStatus("[{0}/{1}] Removing episodes from trakt.tv ratings", i + 1, pages);
                    var syncResponse = TraktAPI.TraktAPI.RemoveEpisodesFromRatings(syncData);
                    if (syncResponse == null)
                    {
                        UIUtils.UpdateStatus(string.Format("[{0}/{1}] Failed to remove episodes from trakt.tv ratings", i + 1, pages), true);
                        Thread.Sleep(2000);
                        continue;
                    }
                }
            }
            else
            {
                UIUtils.UpdateStatus("Failed to get current list of rated episodes from trakt.tv", true);
                Thread.Sleep(2000);
            }
        }
Пример #19
0
        public static TraktEpisodeSync GetTraktEpisodeData(IEnumerable<IMDbEpisode> episodes)
        {
            if (episodes == null)
                return null;

            var traktEpisodes = new List<TraktEpisode>();

            traktEpisodes.AddRange(from episode in episodes
                                   select new TraktEpisode
                                   {
                                       Ids = new TraktEpisodeId { TvdbId = episode.TvdbId, ImdbId = episode.ImdbId }
                                   });

            var episodeSync = new TraktEpisodeSync
            {
                Episodes = traktEpisodes
            };

            return episodeSync;
        }
Пример #20
0
        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);
        }
Пример #21
0
        /// <summary>
        /// Removes all episodes from watchlist from trakt
        /// </summary>
        /// <param name="syncData">list of episodes</param>
        public static TraktSyncResponse RemoveEpisodesFromWatchlist(TraktEpisodeSync syncData)
        {
            if (syncData == null)
                return null;

            var response = TraktWeb.PostToTrakt(TraktURIs.SyncWatchlistRemove, syncData.ToJSON());
            return response.FromJSON<TraktSyncResponse>();
        }
Пример #22
0
        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");
        }