protected override void OnClicked(int controlId, GUIControl control, Action.ActionType actionType) { // wait for any background action to finish if (GUIBackgroundTask.Instance.IsBusy) { return; } switch (controlId) { // Facade case (50): if (actionType == Action.ActionType.ACTION_SELECT_ITEM) { GUIListItem selectedItem = this.Facade.SelectedListItem; if (selectedItem == null) { return; } TraktListDetail selectedList = null; string username = CurrentUser; if (selectedItem.TVTag is TraktListDetail) { selectedList = selectedItem.TVTag as TraktListDetail; } else if (selectedItem.TVTag is TraktListTrending) { var trending = selectedItem.TVTag as TraktListTrending; selectedList = trending.List; username = trending.List.User.Username; } else if (selectedItem.TVTag is TraktListPopular) { var popular = selectedItem.TVTag as TraktListPopular; selectedList = popular.List; username = popular.List.User.Username; } else if (selectedItem.TVTag is TraktLike) { var likedItem = selectedItem.TVTag as TraktLike; selectedList = likedItem.List; username = likedItem.List.User.Username; } // Load current selected list GUIListItems.CurrentList = selectedList; GUIListItems.CurrentUser = username; ReturningFromListItemsOrComments = true; GUIWindowManager.ActivateWindow((int)TraktGUIWindows.CustomListItems); } break; default: break; } base.OnClicked(controlId, control, actionType); }
private void OnItemSelected(GUIListItem item, GUIControl parent) { TraktListDetail list = null; if (item.TVTag is TraktListDetail) { list = item.TVTag as TraktListDetail; } else if (item.TVTag is TraktListTrending) { var trending = item.TVTag as TraktListTrending; list = trending.List; GUICommon.SetProperty("#Trakt.List.LikesThisWeek", trending.LikesThisWeek); GUICommon.SetProperty("#Trakt.List.CommentsThisWeek", trending.CommentsThisWeek); } else if (item.TVTag is TraktListPopular) { var popular = item.TVTag as TraktListPopular; list = popular.List; } else if (item.TVTag is TraktLike) { var likedItem = item.TVTag as TraktLike; list = likedItem.List; } GUICommon.SetListProperties(list); }
private void PublishListProperties(TraktListDetail list) { if (list == null) { return; } GUICommon.SetListProperties(list); }
private void EditList(TraktListDetail list) { GUIBackgroundTask.Instance.ExecuteInBackgroundAndCallback(() => { return(TraktAPI.TraktAPI.UpdateCustomList(list)); }, delegate(bool success, object result) { if (success) { var response = result as TraktListDetail; if (response == null) { // reload with new list TraktLists.ClearListCache(TraktSettings.Username); LoadLists(); var thread = new Thread((o) => { TraktCache.ClearCustomListCache(); // updated MovingPictures categories and filters menu if (TraktHelper.IsMovingPicturesAvailableAndEnabled) { TraktHandlers.MovingPictures.UpdateCategoriesMenu(SyncListType.CustomList); TraktHandlers.MovingPictures.UpdateFiltersMenu(SyncListType.CustomList); } }) { Name = "EditList", IsBackground = true }; thread.Start(); } else { GUIUtils.ShowNotifyDialog(Translation.Lists, Translation.FailedUpdateList); } } }, Translation.EditingList, true); }
/// <summary> /// Get the ids for each list selected by a user in the Multi-Select dialog /// </summary> public static List <int> GetUserListSelections(List <TraktListDetail> lists) { if (lists.Count == 0) { if (!GUIUtils.ShowYesNoDialog(Translation.Lists, Translation.NoListsFound, true)) { // nothing to do, return return(null); } var list = new TraktListDetail(); if (TraktLists.GetListDetailsFromUser(ref list)) { TraktLogger.Info("Creating new list for user online. Privacy = '{0}', Name = '{1}'", list.Privacy, list.Name); var response = TraktAPI.TraktAPI.CreateCustomList(list); if (response != null) { ClearListCache(TraktSettings.Username); return(new List <int> { (int)response.Ids.Trakt }); } } return(null); } List <MultiSelectionItem> selectedItems = GUIUtils.ShowMultiSelectionDialog(Translation.SelectLists, GetMultiSelectItems(lists)); if (selectedItems == null) { return(null); } var listIds = new List <int>(); foreach (var item in selectedItems.Where(l => l.Selected == true)) { listIds.Add(int.Parse(item.ItemID)); } return(listIds); }
private void DeleteList(TraktListDetail list) { if (!GUIUtils.ShowYesNoDialog(Translation.Lists, Translation.ConfirmDeleteList, false)) { return; } GUIBackgroundTask.Instance.ExecuteInBackgroundAndCallback(() => { TraktLogger.Info("Deleting list from online. Name = '{0}', Id = '{1}'", list.Name, list.Ids.Trakt); return(TraktAPI.TraktAPI.DeleteUserList("me", list.Ids.Trakt.ToString())); }, delegate(bool success, object result) { if (success) { if ((result as bool?) == true) { // remove from MovingPictures categories and filters menu if (TraktHelper.IsMovingPicturesAvailableAndEnabled) { // not very thread safe if we tried to delete more than one before response! TraktHandlers.MovingPictures.RemoveCustomListNode(list.Name); } // reload with new list TraktLists.ClearListCache(TraktSettings.Username); LoadLists(); } else { GUIUtils.ShowNotifyDialog(Translation.Lists, Translation.FailedDeleteList); } } }, Translation.DeletingList, true); }
public void ImportRatings() { mImportCancelled = false; var lRateItems = new List <Dictionary <string, string> >(); var lWatchlistItems = new List <Dictionary <string, string> >(); var lCustomLists = new Dictionary <string, List <Dictionary <string, string> > >(); #region Parse Ratings CSV UIUtils.UpdateStatus("Reading IMDb ratings export..."); if (mImportCsvRatings && !ParseCSVFile(mRatingsFileCsv, out lRateItems)) { UIUtils.UpdateStatus("Failed to parse IMDb ratings file!", true); Thread.Sleep(2000); return; } if (mImportCancelled) { return; } #endregion #region Parse Watchlist CSV UIUtils.UpdateStatus("Reading IMDb watchlist export..."); if (mImportCsvWatchlist && !ParseCSVFile(mWatchlistFileCsv, out lWatchlistItems)) { UIUtils.UpdateStatus("Failed to parse IMDb watchlist file!", true); Thread.Sleep(2000); return; } if (mImportCancelled) { return; } #endregion #region Parse Custom List CSVs UIUtils.UpdateStatus("Reading IMDb custom lists export..."); if (mImportCsvCustomLists) { foreach (var list in mCustomListsCsvs) { UIUtils.UpdateStatus("Reading IMDb custom list '{0}' export...", list); var lCustomList = new List <Dictionary <string, string> >(); if (!ParseCSVFile(list, out lCustomList)) { UIUtils.UpdateStatus("Failed to parse IMDb custom list file!", true); Thread.Sleep(2000); return; } lCustomLists.Add(list, lCustomList); } } if (mImportCancelled) { return; } #endregion #region Import Rated Movies var lMovies = lRateItems.Where(r => r[IMDbFieldMapping.cType].ItemType() == IMDbType.Movie && !string.IsNullOrEmpty(r[IMDbFieldMapping.cRating])).ToList(); FileLog.Info("Found {0} movie ratings in CSV file", lMovies.Count); if (lMovies.Any()) { UIUtils.UpdateStatus("Retrieving existing movie ratings from trakt.tv"); var lCurrentUserMovieRatings = TraktAPI.GetRatedMovies(); if (lCurrentUserMovieRatings != null) { UIUtils.UpdateStatus("Found {0} user movie ratings on trakt.tv", lCurrentUserMovieRatings.Count()); // Filter out movies to rate from existing ratings online lMovies.RemoveAll(m => lCurrentUserMovieRatings.Any(c => c.Movie.Ids.ImdbId == m[IMDbFieldMapping.cIMDbID])); } UIUtils.UpdateStatus("Importing {0} new movie ratings to trakt.tv", lMovies.Count()); if (lMovies.Count > 0) { int pageSize = AppSettings.BatchSize; int pages = (int)Math.Ceiling((double)lMovies.Count / pageSize); for (int i = 0; i < pages; i++) { UIUtils.UpdateStatus("Importing page {0}/{1} IMDb rated movies...", i + 1, pages); TraktSyncResponse response = TraktAPI.AddMoviesToRatings(Helper.GetRateMoviesData(lMovies.Skip(i * pageSize).Take(pageSize))); if (response == null) { UIUtils.UpdateStatus("Error importing IMDb movie ratings to trakt.tv", true); Thread.Sleep(2000); } else if (response.NotFound.Movies.Count > 0) { UIUtils.UpdateStatus("Unable to sync ratings for {0} movies as they're not found on trakt.tv!", response.NotFound.Movies.Count); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } } if (mImportCancelled) { return; } #endregion #region Import Rated TV Shows var lShows = lRateItems.Where(r => r[IMDbFieldMapping.cType].ItemType() == IMDbType.Show && !string.IsNullOrEmpty(r[IMDbFieldMapping.cRating])).ToList(); FileLog.Info("Found {0} tv show ratings in CSV file", lShows.Count); if (lShows.Any()) { UIUtils.UpdateStatus("Retrieving existing tv show ratings from trakt.tv"); var currentUserShowRatings = TraktAPI.GetRatedShows(); if (currentUserShowRatings != null) { UIUtils.UpdateStatus("Found {0} user tv show ratings on trakt.tv", currentUserShowRatings.Count()); // Filter out shows to rate from existing ratings online lShows.RemoveAll(s => currentUserShowRatings.Any(c => (c.Show.Ids.ImdbId == s[IMDbFieldMapping.cIMDbID]) || (c.Show.Title == s[IMDbFieldMapping.cTitle] && c.Show.Year.ToString() == s[IMDbFieldMapping.cYear]))); } UIUtils.UpdateStatus("Importing {0} tv show ratings to trakt.tv", lShows.Count()); if (lShows.Count > 0) { int pageSize = AppSettings.BatchSize; int pages = (int)Math.Ceiling((double)lShows.Count / pageSize); for (int i = 0; i < pages; i++) { UIUtils.UpdateStatus("Importing page {0}/{1} IMDb rated shows...", i + 1, pages); TraktSyncResponse response = TraktAPI.AddShowsToRatings(Helper.GetRateShowsData(lShows.Skip(i * pageSize).Take(pageSize))); if (response == null) { UIUtils.UpdateStatus("Error importing IMDb tv show ratings to trakt.tv", true); Thread.Sleep(2000); } else if (response.NotFound.Shows.Count > 0) { UIUtils.UpdateStatus("Unable to sync ratings for {0} shows as they're not found on trakt.tv!", response.NotFound.Shows.Count); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } } if (mImportCancelled) { return; } #endregion #region Import Rated Episodes var lImdbEpisodes = new List <IMDbEpisode>(); var lImdbCsvEpisodes = lRateItems.Where(r => r[IMDbFieldMapping.cType].ItemType() == IMDbType.Episode).ToList(); FileLog.Info("Found {0} tv episode ratings in CSV file", lImdbCsvEpisodes.Count); if (lImdbCsvEpisodes.Any()) { // we can't rely on the imdb id as trakt most likely wont have the info for episodes // search and cache all series info needed for syncing // use the tvdb API to first search for each unique series name // then GetSeries by TVDb ID to get a list of all episodes // each episode will have TVDb ID which we can use for syncing. lImdbEpisodes.AddRange(lImdbCsvEpisodes.Select(Helper.GetIMDbEpisodeFromTVDb).Where(imdbEpisode => imdbEpisode != null)); UIUtils.UpdateStatus("Retrieving existing tv episode ratings from trakt.tv"); var currentUserEpisodeRatings = TraktAPI.GetRatedEpisodes(); if (currentUserEpisodeRatings != null) { UIUtils.UpdateStatus("Found {0} user tv episode ratings on trakt.tv", currentUserEpisodeRatings.Count()); // Filter out episodes to rate from existing ratings online lImdbEpisodes.RemoveAll(e => currentUserEpisodeRatings.Any(c => c.Episode.Ids.TvdbId == e.TvdbId || c.Episode.Ids.ImdbId == e.ImdbId)); } UIUtils.UpdateStatus("Importing {0} episode ratings to trakt.tv", lImdbEpisodes.Count()); if (lImdbEpisodes.Count > 0) { int pageSize = AppSettings.BatchSize; int pages = (int)Math.Ceiling((double)lImdbEpisodes.Count / pageSize); for (int i = 0; i < pages; i++) { var episodesRated = Helper.GetTraktEpisodeRateData(lImdbEpisodes.Skip(i * pageSize).Take(pageSize)); UIUtils.UpdateStatus("Importing page {0}/{1} IMDb rated episodes...", i + 1, pages); var response = TraktAPI.AddsEpisodesToRatings(episodesRated); if (response == null) { UIUtils.UpdateStatus("Error importing IMDb episodes ratings to trakt.tv", true); Thread.Sleep(2000); } else if (response.NotFound.Episodes.Count > 0) { UIUtils.UpdateStatus("Unable to sync ratings for {0} IMDb episodes as they're not found on trakt.tv!", response.NotFound.Episodes.Count); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } } if (mImportCancelled) { return; } #endregion #region Mark Rated Items as Watched IEnumerable <TraktMoviePlays> lWatchedTraktMovies = null; if (AppSettings.MarkAsWatched) { #region Movies // compare all movies rated against what's not watched on trakt lMovies = lRateItems.Where(r => r[IMDbFieldMapping.cType].ItemType() == IMDbType.Movie).ToList(); FileLog.Info("Found {0} movies in CSV file", lMovies.Count); if (lMovies.Count > 0) { // get watched movies from trakt.tv UIUtils.UpdateStatus("Requesting watched movies from trakt..."); lWatchedTraktMovies = TraktAPI.GetWatchedMovies(); if (lWatchedTraktMovies == null) { UIUtils.UpdateStatus("Failed to get watched movies from trakt.tv, skipping watched movie import", true); Thread.Sleep(2000); } else { if (mImportCancelled) { return; } UIUtils.UpdateStatus("Found {0} watched movies on trakt", lWatchedTraktMovies.Count()); UIUtils.UpdateStatus("Filtering out watched movies that are already watched on trakt.tv"); lMovies.RemoveAll(w => lWatchedTraktMovies.FirstOrDefault(t => t.Movie.Ids.ImdbId == w[IMDbFieldMapping.cIMDbID] || (t.Movie.Title.ToLowerInvariant() == w[IMDbFieldMapping.cTitle] && t.Movie.Year.ToString() == w[IMDbFieldMapping.cYear])) != null); // mark all rated movies as watched UIUtils.UpdateStatus("Importing {0} IMDb movies as watched...", lMovies.Count); int pageSize = AppSettings.BatchSize; int pages = (int)Math.Ceiling((double)lMovies.Count / pageSize); for (int i = 0; i < pages; i++) { UIUtils.UpdateStatus("Importing page {0}/{1} IMDb movies as watched...", i + 1, pages); var response = TraktAPI.AddMoviesToWatchedHistory(Helper.GetSyncWatchedMoviesData(lMovies.Skip(i * pageSize).Take(pageSize).ToList())); if (response == null) { UIUtils.UpdateStatus("Failed to send watched status for IMDb movies to trakt.tv", true); Thread.Sleep(2000); } else if (response.NotFound.Movies.Count > 0) { UIUtils.UpdateStatus("Unable to sync watched states for {0} movies as they're not found on trakt.tv!", response.NotFound.Movies.Count); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } } #endregion #region Episodes if (lImdbEpisodes != null && lImdbEpisodes.Any()) { int pageSize = AppSettings.BatchSize; int pages = (int)Math.Ceiling((double)lImdbEpisodes.Count / pageSize); for (int i = 0; i < pages; i++) { var episodesWatched = Helper.GetTraktEpisodeWatchedData(lImdbEpisodes.Skip(i * pageSize).Take(pageSize)); UIUtils.UpdateStatus("Importing page {0}/{1} IMDb watched episodes...", i + 1, pages); var response = TraktAPI.AddEpisodesToWatchedHistory(episodesWatched); if (response == null) { UIUtils.UpdateStatus("Error importing IMDb episodes as watched to trakt.tv", true); Thread.Sleep(2000); } else if (response.NotFound.Episodes.Count > 0) { UIUtils.UpdateStatus("Unable to sync {0} IMDb episodes as watched, as they're not found on trakt.tv!", response.NotFound.Episodes.Count); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } #endregion } #endregion #region Import Watchlist Movies lMovies = lWatchlistItems.Where(r => r[IMDbFieldMapping.cType].ItemType() == IMDbType.Movie).ToList(); FileLog.Info("Found {0} movies watchlisted in CSV file", lMovies.Count); if (lMovies.Any()) { UIUtils.UpdateStatus("Requesting existing watchlist movies from trakt..."); var watchlistTraktMovies = TraktAPI.GetWatchlistMovies(); if (watchlistTraktMovies != null) { UIUtils.UpdateStatus("Found {0} watchlist movies on trakt", watchlistTraktMovies.Count()); UIUtils.UpdateStatus("Filtering out watchlist movies that are already in watchlist on trakt.tv"); lMovies.RemoveAll(w => watchlistTraktMovies.FirstOrDefault(t => t.Movie.Ids.ImdbId == w[IMDbFieldMapping.cIMDbID] || (t.Movie.Title.ToLowerInvariant() == w[IMDbFieldMapping.cTitle] && t.Movie.Year.ToString() == w[IMDbFieldMapping.cYear])) != null); } if (AppSettings.IgnoreWatchedForWatchlist && lMovies.Count > 0) { UIUtils.UpdateStatus("Requesting watched movies from trakt..."); // get watched movies from trakt so we don't import movies into watchlist that are already watched if (lWatchedTraktMovies != null) { lWatchedTraktMovies = TraktAPI.GetWatchedMovies(); if (lWatchedTraktMovies == null) { UIUtils.UpdateStatus("Failed to get watched movies from trakt.tv", true); Thread.Sleep(2000); } } if (lWatchedTraktMovies != null) { UIUtils.UpdateStatus("Found {0} watched movies on trakt", lWatchedTraktMovies.Count()); UIUtils.UpdateStatus("Filtering out watchlist movies that are watched on trakt.tv"); // remove movies from sync list which are watched already lMovies.RemoveAll(w => lWatchedTraktMovies.FirstOrDefault(t => t.Movie.Ids.ImdbId == w[IMDbFieldMapping.cIMDbID] || (t.Movie.Title.ToLowerInvariant() == w[IMDbFieldMapping.cTitle] && t.Movie.Year.ToString() == w[IMDbFieldMapping.cYear])) != null); } } // add movies to watchlist UIUtils.UpdateStatus("Importing {0} IMDb watchlist movies to trakt.tv...", lMovies.Count()); int pageSize = AppSettings.BatchSize; int pages = (int)Math.Ceiling((double)lMovies.Count / pageSize); for (int i = 0; i < pages; i++) { UIUtils.UpdateStatus("Importing page {0}/{1} IMDb watchlist movies...", i + 1, pages); var response = TraktAPI.AddMoviesToWatchlist(Helper.GetSyncMoviesData(lMovies.Skip(i * pageSize).Take(pageSize).ToList())); if (response == null) { UIUtils.UpdateStatus("Failed to send watchlist for IMDb movies", true); Thread.Sleep(2000); } else if (response.NotFound.Movies.Count > 0) { UIUtils.UpdateStatus("Unable to sync watchlist for {0} movies as they're not found on trakt.tv!", response.NotFound.Movies.Count); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } if (mImportCancelled) { return; } #endregion #region Import Watchlist TV Shows IEnumerable <TraktShowPlays> watchedTraktShows = null; lShows = lWatchlistItems.Where(r => r[IMDbFieldMapping.cType].ItemType() == IMDbType.Show).ToList(); FileLog.Info("Found {0} tv shows watchlisted in CSV file", lShows.Count); if (lShows.Any()) { UIUtils.UpdateStatus("Requesting existing watchlist shows from trakt..."); var watchlistTraktShows = TraktAPI.GetWatchlistShows(); if (watchlistTraktShows != null) { UIUtils.UpdateStatus("Found {0} watchlist shows on trakt", watchlistTraktShows.Count()); UIUtils.UpdateStatus("Filtering out watchlist shows that are already in watchlist on trakt.tv"); lShows.RemoveAll(w => watchlistTraktShows.FirstOrDefault(t => t.Show.Ids.ImdbId == w[IMDbFieldMapping.cIMDbID] || (t.Show.Title.ToLowerInvariant() == w[IMDbFieldMapping.cTitle].ToLowerInvariant() && t.Show.Year.ToString() == w[IMDbFieldMapping.cYear])) != null); } if (AppSettings.IgnoreWatchedForWatchlist && lShows.Count > 0) { UIUtils.UpdateStatus("Requesting watched shows from trakt..."); // get watched movies from trakt so we don't import shows into watchlist that are already watched watchedTraktShows = TraktAPI.GetWatchedShows(); if (watchedTraktShows != null) { UIUtils.UpdateStatus("Found {0} watched shows on trakt", watchedTraktShows.Count()); UIUtils.UpdateStatus("Filtering out watchlist shows containing watched episodes on trakt.tv."); // remove shows from sync list which are watched already lShows.RemoveAll(w => watchedTraktShows.FirstOrDefault(t => (t.Show.Ids.ImdbId == w[IMDbFieldMapping.cIMDbID]) || (t.Show.Title.ToLowerInvariant() == w[IMDbFieldMapping.cTitle].ToLowerInvariant() && t.Show.Year.ToString() == w[IMDbFieldMapping.cYear])) != null); } } // add shows to watchlist UIUtils.UpdateStatus("Importing {0} IMDb watchlist shows to trakt.tv...", lShows.Count()); int pageSize = AppSettings.BatchSize; int pages = (int)Math.Ceiling((double)lShows.Count / pageSize); for (int i = 0; i < pages; i++) { UIUtils.UpdateStatus("Importing page {0}/{1} IMDb watchlist shows...", i + 1, pages); var response = TraktAPI.AddShowsToWatchlist(Helper.GetSyncShowsData(lShows.Skip(i * pageSize).Take(pageSize))); if (response == null) { UIUtils.UpdateStatus("Failed to send watchlist for IMDb tv shows", true); Thread.Sleep(2000); } else if (response.NotFound.Shows.Count > 0) { UIUtils.UpdateStatus("Unable to sync watchlist for {0} shows as they're not found on trakt.tv!", response.NotFound.Shows.Count); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } if (mImportCancelled) { return; } #endregion #region Import Watchlist Episodes lImdbEpisodes.Clear(); lImdbCsvEpisodes = lWatchlistItems.Where(r => r[IMDbFieldMapping.cType].ItemType() == IMDbType.Episode).ToList(); FileLog.Info("Found {0} tv episodes watchlisted in CSV file", lImdbCsvEpisodes.Count); if (lImdbCsvEpisodes.Any()) { UIUtils.UpdateStatus("Found {0} IMDb watchlist episodes", lImdbCsvEpisodes.Count()); lImdbEpisodes.AddRange(lImdbCsvEpisodes.Select(Helper.GetIMDbEpisodeFromTVDb).Where(imdbEpisode => imdbEpisode != null)); // filter out existing watchlist episodes UIUtils.UpdateStatus("Requesting existing watchlist episodes from trakt..."); var watchlistTraktEpisodes = TraktAPI.GetWatchlistEpisodes(); if (watchlistTraktEpisodes != null) { UIUtils.UpdateStatus("Found {0} watchlist episodes on trakt", watchlistTraktEpisodes.Count()); UIUtils.UpdateStatus("Filtering out watchlist episodes that are already in watchlist on trakt.tv"); lImdbEpisodes.RemoveAll(e => watchlistTraktEpisodes.FirstOrDefault(w => w.Episode.Ids.ImdbId == e.ImdbId || w.Episode.Ids.TvdbId == e.TvdbId) != null); } if (AppSettings.IgnoreWatchedForWatchlist && lImdbEpisodes.Count > 0) { // we already might have it from the shows sync if (watchedTraktShows == null) { UIUtils.UpdateStatus("Requesting watched episodes from trakt..."); // get watched episodes from trakt so we don't import episodes into watchlist that are already watched watchedTraktShows = TraktAPI.GetWatchedShows(); } if (watchedTraktShows != null) { UIUtils.UpdateStatus("Filtering out watchlist episodes containing watched episodes on trakt.tv"); lImdbEpisodes.RemoveAll(e => watchedTraktShows.Where(s => s.Show.Ids.ImdbId == e.ImdbId) .Any(s => s.Seasons.Exists(se => se.Number == e.SeasonNumber && se.Episodes.Exists(ep => ep.Number == e.EpisodeNumber)))); } } UIUtils.UpdateStatus("Importing {0} episodes in watchlist to trakt.tv", lImdbEpisodes.Count()); if (lImdbEpisodes.Count > 0) { int pageSize = AppSettings.BatchSize; int pages = (int)Math.Ceiling((double)lImdbEpisodes.Count / pageSize); for (int i = 0; i < pages; i++) { UIUtils.UpdateStatus("Importing page {0}/{1} IMDb watchlist episodes...", i + 1, pages); var response = TraktAPI.AddEpisodesToWatchlist(Helper.GetTraktEpisodeData(lImdbEpisodes.Skip(i * pageSize).Take(pageSize))); if (response == null) { UIUtils.UpdateStatus("Error importing IMDb episode watchlist to trakt.tv", true); Thread.Sleep(2000); } else if (response.NotFound.Episodes.Count > 0) { UIUtils.UpdateStatus("Unable to sync watchlist for {0} IMDb episodes as they're not found on trakt.tv!", response.NotFound.Episodes.Count); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } } #endregion #region Import Custom Lists if (lCustomLists.Count > 0) { UIUtils.UpdateStatus("Requesting custom lists from trakt..."); var lTraktCustomLists = TraktAPI.GetCustomLists(); if (lTraktCustomLists == null) { UIUtils.UpdateStatus("Error requesting custom lists from trakt.tv", true); Thread.Sleep(2000); return; } UIUtils.UpdateStatus("Found {0} custom lists on trakt.tv", lTraktCustomLists.Count()); foreach (var list in lCustomLists) { bool lListCreated = false; string lListName = Path.GetFileNameWithoutExtension(list.Key); // create the list if we don't have it TraktListDetail lTraktCustomList = lTraktCustomLists.FirstOrDefault(l => l.Name == lListName); if (lTraktCustomList == null) { UIUtils.UpdateStatus("Creating new custom list '{0}' on trakt.tv", lListName); var lTraktList = new TraktList { Name = lListName, DisplayNumbers = true, }; lTraktCustomList = TraktAPI.CreateCustomList(lTraktList); if (lTraktCustomList == null) { UIUtils.UpdateStatus("Error creating custom list on trakt.tv, skipping list creation", true); Thread.Sleep(2000); continue; } lListCreated = true; } // get the CSV list items parsed var lIMDbListItems = list.Value; var lImdbListMovies = lIMDbListItems.Where(l => l.ItemType() == IMDbType.Movie).ToList(); var lImdbListShows = lIMDbListItems.Where(l => l.ItemType() == IMDbType.Show).ToList(); // if the list already exists, get current items for list if (!lListCreated) { lTraktCustomList = lTraktCustomLists.FirstOrDefault(l => l.Name == lListName); UIUtils.UpdateStatus("Requesting existing custom list '{0}' items from trakt...", lListName); var lTraktListItems = TraktAPI.GetCustomListItems(lTraktCustomList.Ids.Trakt.ToString()); if (lTraktListItems == null) { UIUtils.UpdateStatus("Error requesting custom list items on trakt.tv, skipping list creation", true); Thread.Sleep(2000); continue; } // filter out existing items from CSV so we don't send again FileLog.Info("Filtering out existing items from IMDb list '{0}' so we don't send again to trakt.tv", lListName); lImdbListMovies.RemoveAll(d => d.ItemType() == IMDbType.Movie && lTraktListItems.FirstOrDefault(l => l.Movie.Ids.ImdbId == d[IMDbFieldMapping.cIMDbID]) != null); lImdbListShows.RemoveAll(d => d.ItemType() == IMDbType.Show && lTraktListItems.FirstOrDefault(l => l.Show.Ids.ImdbId == d[IMDbFieldMapping.cIMDbID]) != null); } #region Movies UIUtils.UpdateStatus("Importing {0} movies into {1} custom list...", lImdbListMovies.Count(), lListName); int pageSize = AppSettings.BatchSize; int pages = (int)Math.Ceiling((double)lImdbListMovies.Count / pageSize); for (int i = 0; i < pages; i++) { UIUtils.UpdateStatus("Importing page {0}/{1} IMDb custom list movies...", i + 1, pages); // create list sync object to hold list items var lTraktMovieSync = new TraktSyncAll { Movies = Helper.GetSyncMoviesData(lImdbListMovies.Skip(i * pageSize).Take(pageSize).ToList()).Movies }; var response = TraktAPI.AddItemsToList(lTraktCustomList.Ids.Trakt.ToString(), lTraktMovieSync); if (response == null) { UIUtils.UpdateStatus("Failed to send custom list items for IMDb movies", true); Thread.Sleep(2000); } else if (response.NotFound.Movies.Count > 0) { UIUtils.UpdateStatus("Unable to sync custom list items for {0} movies as they're not found on trakt.tv!", response.NotFound.Movies.Count); Thread.Sleep(1000); } if (mImportCancelled) { return; } } #endregion #region Shows UIUtils.UpdateStatus("Importing {0} shows into {1} custom list...", lImdbListShows.Count(), lListName); pageSize = AppSettings.BatchSize; pages = (int)Math.Ceiling((double)lImdbListShows.Count / pageSize); for (int i = 0; i < pages; i++) { UIUtils.UpdateStatus("Importing page {0}/{1} IMDb custom list shows...", i + 1, pages); // create list sync object to hold list items var lTraktShowSync = new TraktSyncAll { Shows = Helper.GetSyncShowsData(lImdbListShows.Skip(i * pageSize).Take(pageSize).ToList()).Shows }; var response = TraktAPI.AddItemsToList(lTraktCustomList.Ids.Trakt.ToString(), lTraktShowSync); if (response == null) { UIUtils.UpdateStatus("Failed to send custom list items for IMDb shows", true); Thread.Sleep(2000); } else if (response.NotFound.Shows.Count > 0) { UIUtils.UpdateStatus("Unable to sync custom list items for {0} shows as they're not found on trakt.tv!", response.NotFound.Shows.Count); Thread.Sleep(1000); } if (mImportCancelled) { return; } } #endregion } } #endregion }
/// <summary> /// Updates existing list on trakt /// </summary> /// <param name="user">The user to get</param> public static TraktListDetail UpdateCustomList(TraktListDetail list, string username, string id) { var response = UPDATEOnTrakt(string.Format(TraktURIs.SENDListEdit, username, id), list.ToJSON()); return(response.FromJSON <TraktListDetail>()); }
private void SendUserListsToFacade(IEnumerable <TraktListDetail> lists) { // clear facade GUIControl.ClearControl(GetID, Facade.GetID); if (lists == null) { GUIUtils.ShowNotifyDialog(Translation.Error, Translation.ErrorGeneral); GUIWindowManager.ShowPreviousWindow(); return; } // check if the user has any lists (not the currently logged in user) if (ListType == TraktListType.User && lists.Count() == 0 && TraktSettings.Username != CurrentUser) { GUIUtils.ShowNotifyDialog(GUIUtils.PluginName(), string.Format(Translation.NoUserLists, CurrentUser)); CurrentUser = TraktSettings.Username; GUIWindowManager.ShowPreviousWindow(); return; } // check if the currently logged in user has any lists // if none, prompt to create one if (ListType == TraktListType.User && lists.Count() == 0) { if (!GUIUtils.ShowYesNoDialog(Translation.Lists, Translation.NoListsFound, true)) { // nothing to do, exit GUIWindowManager.ShowPreviousWindow(); return; } var list = new TraktListDetail(); if (TraktLists.GetListDetailsFromUser(ref list)) { TraktLogger.Info("Creating new list online. Privacy = '{0}', Name = '{1}'", list.Privacy, list.Name); CreateList(list); } return; } int itemId = 0; // Add each list foreach (var list in lists) { var item = new GUIListItem(list.Name); item.Label2 = string.Format("{0} {1}", list.ItemCount, list.ItemCount != 1 ? Translation.Items : Translation.Item); item.TVTag = list; item.ItemId = Int32.MaxValue - itemId; item.PinImage = TraktLists.GetPrivacyLevelIcon(list.Privacy); item.IconImage = "defaultFolder.png"; item.IconImageBig = "defaultFolderBig.png"; item.ThumbnailImage = "defaultFolderBig.png"; item.OnItemSelected += OnItemSelected; Utils.SetDefaultIcons(item); Facade.Add(item); itemId++; } // Set Facade Layout Facade.CurrentLayout = GUIFacadeControl.Layout.List; GUIControl.FocusControl(GetID, Facade.GetID); if (PreviousSelectedIndex >= lists.Count()) { Facade.SelectIndex(PreviousSelectedIndex - 1); } else { Facade.SelectIndex(PreviousSelectedIndex); } // set facade properties GUIUtils.SetProperty("#itemcount", lists.Count().ToString()); GUIUtils.SetProperty("#Trakt.Items", string.Format("{0} {1}", lists.Count().ToString(), lists.Count() > 1 ? Translation.Lists : Translation.List)); }
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); }
protected override void OnShowContextMenu() { if (GUIBackgroundTask.Instance.IsBusy) { return; } GUIListItem selectedItem = this.Facade.SelectedListItem; if (selectedItem == null) { return; } TraktListDetail selectedList = null; string username = CurrentUser; if (selectedItem.TVTag is TraktListDetail) { selectedList = selectedItem.TVTag as TraktListDetail; } else if (selectedItem.TVTag is TraktListTrending) { var trending = selectedItem.TVTag as TraktListTrending; selectedList = trending.List; username = trending.List.User.Username; } else if (selectedItem.TVTag is TraktListPopular) { var popular = selectedItem.TVTag as TraktListPopular; selectedList = popular.List; username = popular.List.User.Username; } else if (selectedItem.TVTag is TraktLike) { var likedItem = selectedItem.TVTag as TraktLike; selectedList = likedItem.List; username = likedItem.List.User.Username; } var dlg = (IDialogbox)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_MENU); if (dlg == null) { return; } dlg.Reset(); dlg.SetHeading(GUIUtils.PluginName()); GUIListItem listItem = null; // only allow add/delete/update if viewing your own lists if (username == TraktSettings.Username) { listItem = new GUIListItem(Translation.CreateList); dlg.Add(listItem); listItem.ItemId = (int)ContextMenuItem.Create; listItem = new GUIListItem(Translation.EditList); dlg.Add(listItem); listItem.ItemId = (int)ContextMenuItem.Edit; listItem = new GUIListItem(Translation.DeleteList); dlg.Add(listItem); listItem.ItemId = (int)ContextMenuItem.Delete; } else { // like list if (!selectedList.IsLiked()) { listItem = new GUIListItem(Translation.Like); dlg.Add(listItem); listItem.ItemId = (int)ContextMenuItem.Like; } else { // unLike list listItem = new GUIListItem(Translation.UnLike); dlg.Add(listItem); listItem.ItemId = (int)ContextMenuItem.Unlike; } // copy a friends list listItem = new GUIListItem(Translation.CopyList); dlg.Add(listItem); listItem.ItemId = (int)ContextMenuItem.Copy; } // allow viewing comments for any type of lists // if comments are not allowed there will most like be no comments if (selectedList.AllowComments) { listItem = new GUIListItem(Translation.Comments + "..."); dlg.Add(listItem); listItem.ItemId = (int)ContextMenuItem.Comments; } // Show Context Menu dlg.DoModal(GUIWindowManager.ActiveWindow); if (dlg.SelectedId < 0) { return; } var currentList = new TraktListDetail { Ids = selectedList.Ids, Name = selectedList.Name, Description = selectedList.Description, Privacy = selectedList.Privacy, AllowComments = selectedList.AllowComments, DisplayNumbers = selectedList.DisplayNumbers, ItemCount = selectedList.ItemCount, Likes = selectedList.Likes, UpdatedAt = selectedList.UpdatedAt }; switch (dlg.SelectedId) { case ((int)ContextMenuItem.Create): var list = new TraktListDetail(); if (TraktLists.GetListDetailsFromUser(ref list)) { if (Lists.Any(l => l.Name == list.Name)) { // list with that name already exists GUIUtils.ShowNotifyDialog(Translation.Lists, Translation.ListNameAlreadyExists); return; } TraktLogger.Info("Creating new list for user online. Privacy = '{0}', Name = '{1}'", list.Privacy, list.Name); CreateList(list); } break; case ((int)ContextMenuItem.Delete): DeleteList(selectedList); break; case ((int)ContextMenuItem.Edit): if (TraktLists.GetListDetailsFromUser(ref currentList)) { TraktLogger.Info("Editing list. Name = '{0}', Id = '{1}'", currentList.Name); EditList(currentList); } break; case ((int)ContextMenuItem.Copy): if (TraktLists.GetListDetailsFromUser(ref currentList)) { CopyList(selectedList, currentList); } break; case ((int)ContextMenuItem.Like): GUICommon.LikeList(selectedList); selectedList.Likes++; PublishListProperties(selectedList); break; case ((int)ContextMenuItem.Unlike): GUICommon.UnLikeList(selectedList); if (selectedList.Likes > 0) { // different behaviour basis the current view if (ListType == TraktListType.Liked) { // remove liked list from cache and reload TraktLists.RemovedItemFromLikedListCache(selectedList.Ids.Trakt); LoadLists(); } else { // update selected list properties as we have unliked it now. selectedList.Likes--; PublishListProperties(selectedList); } } break; case ((int)ContextMenuItem.Comments): ReturningFromListItemsOrComments = true; TraktHelper.ShowListShouts(selectedList); break; default: break; } base.OnShowContextMenu(); }
/// <summary> /// Get all details needed to create a new list or edit existing list /// </summary> /// <param name="list">returns list details</param> /// <returns>true if list details completed</returns> public static bool GetListDetailsFromUser(ref TraktListDetail list) { // the list will have ids if it exists online bool editing = list.Ids != null; // Show Keyboard for Name of list string name = editing ? list.Name : string.Empty; if (!GUIUtils.GetStringFromKeyboard(ref name)) { return(false); } if ((list.Name = name) == string.Empty) { return(false); } // Skip Description and get Privacy...this requires a custom dialog as // virtual keyboard does not allow very much text for longer descriptions. // We may create a custom dialog for this in future var items = new List <GUIListItem>(); var item = new GUIListItem(); int selectedItem = 0; // Public item = new GUIListItem { Label = Translation.PrivacyPublic, Label2 = Translation.Public }; if (list.Privacy == "public") { selectedItem = 0; item.Selected = true; } items.Add(item); // Private item = new GUIListItem { Label = Translation.PrivacyPrivate, Label2 = Translation.Private }; if (list.Privacy == "private") { selectedItem = 1; item.Selected = true; } items.Add(item); // Friends item = new GUIListItem { Label = Translation.PrivacyFriends, Label2 = Translation.Friends }; if (list.Privacy == "friends") { selectedItem = 2; item.Selected = true; } items.Add(item); selectedItem = GUIUtils.ShowMenuDialog(Translation.Privacy, items, selectedItem); if (selectedItem == -1) { return(false); } list.Privacy = GetPrivacyLevelFromTranslation(items[selectedItem].Label2); // Skip 'Show Shouts', 'Use Numbering', 'SortBy' and 'SortHow' until we have Custom Dialog for List edits return(true); }
public void ImportRatings() { mImportCancelled = false; var lRatedCsvItems = new List <IMDbRateItem>(); var lWatchlistCsvItems = new List <IMDbListItem>(); var lCustomLists = new Dictionary <string, List <IMDbListItem> >(); #region Parse Ratings CSV UIUtils.UpdateStatus("Reading IMDb ratings export..."); if (mImportCsvRatings) { mCsvConfiguration.RegisterClassMap <IMDbRatingCsvMap>(); lRatedCsvItems = ParseCsvFile <IMDbRateItem>(mRatingsFileCsv); if (lRatedCsvItems == null) { UIUtils.UpdateStatus("Failed to parse IMDb ratings file!", true); Thread.Sleep(2000); return; } mCsvConfiguration.UnregisterClassMap <IMDbRatingCsvMap>(); } if (mImportCancelled) { return; } #endregion #region Parse Watchlist CSV UIUtils.UpdateStatus("Reading IMDb watchlist export..."); if (mImportCsvWatchlist) { mCsvConfiguration.RegisterClassMap <IMDbListCsvMap>(); lWatchlistCsvItems = ParseCsvFile <IMDbListItem>(mWatchlistFileCsv); if (lWatchlistCsvItems == null) { UIUtils.UpdateStatus("Failed to parse IMDb watchlist file!", true); Thread.Sleep(2000); return; } mCsvConfiguration.UnregisterClassMap <IMDbListCsvMap>(); } if (mImportCancelled) { return; } #endregion #region Parse Custom List CSVs UIUtils.UpdateStatus("Reading IMDb custom lists export..."); if (mImportCsvCustomLists) { mCsvConfiguration.RegisterClassMap <IMDbListCsvMap>(); foreach (var list in mCustomListsCsvs) { UIUtils.UpdateStatus($"Reading IMDb custom list '{list}'"); var lListCsvItems = ParseCsvFile <IMDbListItem>(list); if (lListCsvItems == null) { UIUtils.UpdateStatus("Failed to parse IMDb custom list file!", true); Thread.Sleep(2000); continue; } lCustomLists.Add(list, lListCsvItems); } mCsvConfiguration.UnregisterClassMap <IMDbListCsvMap>(); } if (mImportCancelled) { return; } #endregion #region Import Rated Movies var lRatedCsvMovies = lRatedCsvItems.Where(r => r.Type.ItemType() == IMDbType.Movie && r.MyRating != null) .Select(s => s.ToTraktRatedMovie()).ToList(); FileLog.Info($"Found {lRatedCsvMovies.Count} movie ratings in CSV file"); if (lRatedCsvMovies.Any()) { UIUtils.UpdateStatus("Retrieving existing movie ratings from trakt.tv"); var lCurrentUserMovieRatings = TraktAPI.GetRatedMovies(); if (lCurrentUserMovieRatings != null) { UIUtils.UpdateStatus($"Found {lCurrentUserMovieRatings.Count()} user movie ratings on trakt.tv"); // Filter out movies to rate from existing ratings online lRatedCsvMovies.RemoveAll(m => lCurrentUserMovieRatings.Any(c => c.Movie.Ids.ImdbId == m.Ids.ImdbId)); } UIUtils.UpdateStatus($"Importing {lRatedCsvMovies.Count()} new movie ratings to trakt.tv"); if (lRatedCsvMovies.Count > 0) { int lPageSize = AppSettings.BatchSize; int lPages = (int)Math.Ceiling((double)lRatedCsvMovies.Count / lPageSize); for (int i = 0; i < lPages; i++) { UIUtils.UpdateStatus($"Importing page {i + 1}/{lPages} IMDb rated movies..."); var lRatingsToSync = new TraktMovieRatingSync() { movies = lRatedCsvMovies.Skip(i * lPageSize).Take(lPageSize).ToList() }; TraktSyncResponse lResponse = TraktAPI.AddMoviesToRatings(lRatingsToSync); if (lResponse == null) { UIUtils.UpdateStatus("Error importing IMDb movie ratings to trakt.tv", true); Thread.Sleep(2000); } else if (lResponse.NotFound.Movies.Count > 0) { UIUtils.UpdateStatus($"Unable to sync ratings for {lResponse.NotFound.Movies.Count} movies as they're not found on trakt.tv!"); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } } if (mImportCancelled) { return; } #endregion #region Import Rated TV Shows var lRatedCsvShows = lRatedCsvItems.Where(r => r.Type.ItemType() == IMDbType.Show && r.MyRating != null) .Select(s => s.ToTraktRatedShow()).ToList(); FileLog.Info($"Found {lRatedCsvShows.Count} tv show ratings in CSV file"); if (lRatedCsvShows.Any()) { UIUtils.UpdateStatus("Retrieving existing tv show ratings from trakt.tv"); var lCurrentUserShowRatings = TraktAPI.GetRatedShows(); if (lCurrentUserShowRatings != null) { UIUtils.UpdateStatus($"Found {lCurrentUserShowRatings.Count()} user tv show ratings on trakt.tv"); // Filter out shows to rate from existing ratings online lRatedCsvShows.RemoveAll(s => lCurrentUserShowRatings.Any(c => (c.Show.Ids.ImdbId == s.Ids.ImdbId) || (c.Show.Title.ToLowerInvariant() == s.Title.ToLowerInvariant() && c.Show.Year == s.Year))); } UIUtils.UpdateStatus($"Importing {lRatedCsvShows.Count()} tv show ratings to trakt.tv"); if (lRatedCsvShows.Count > 0) { int lPageSize = AppSettings.BatchSize; int lPages = (int)Math.Ceiling((double)lRatedCsvShows.Count / lPageSize); for (int i = 0; i < lPages; i++) { UIUtils.UpdateStatus($"Importing page {i + 1}/{lPages} IMDb rated shows..."); var lRatingsToSync = new TraktShowRatingSync() { shows = lRatedCsvShows.Skip(i * lPageSize).Take(lPageSize).ToList() }; TraktSyncResponse lResponse = TraktAPI.AddShowsToRatings(lRatingsToSync); if (lResponse == null) { UIUtils.UpdateStatus("Error importing IMDb tv show ratings to trakt.tv", true); Thread.Sleep(2000); } else if (lResponse.NotFound.Shows.Count > 0) { UIUtils.UpdateStatus($"Unable to sync ratings for {lResponse.NotFound.Shows.Count} shows as they're not found on trakt.tv!"); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } } if (mImportCancelled) { return; } #endregion #region Import Rated Episodes var lImdbRatedEpisodes = new List <IMDbEpisode>(); var lImdbRatedCsvEpisodes = lRatedCsvItems.Where(r => r.Type.ItemType() == IMDbType.Episode).ToList(); FileLog.Info($"Found {lImdbRatedCsvEpisodes.Count} tv episode ratings in CSV file"); if (lImdbRatedCsvEpisodes.Any()) { // we can't rely on the episode imdb id as trakt most likely wont have that info at the episode level lImdbRatedEpisodes.AddRange(lImdbRatedCsvEpisodes.Select(Helper.GetIMDbEpisodeFromTrakt).Where(imdbEpisode => imdbEpisode != null)); if (mImportCancelled) { return; } UIUtils.UpdateStatus("Retrieving existing tv episode ratings from trakt.tv"); var lCurrentUserEpisodeRatings = TraktAPI.GetRatedEpisodes(); if (lCurrentUserEpisodeRatings != null) { UIUtils.UpdateStatus($"Found {lCurrentUserEpisodeRatings.Count()} user tv episode ratings on trakt.tv"); // Filter out episodes to rate from existing ratings online lImdbRatedEpisodes.RemoveAll(e => lCurrentUserEpisodeRatings.Any(c => c.Episode.Ids.Trakt == e.TraktId)); } UIUtils.UpdateStatus($"Importing {lImdbRatedEpisodes.Count()} episode ratings to trakt.tv"); if (lImdbRatedEpisodes.Count > 0) { int lPageSize = AppSettings.BatchSize; int lPages = (int)Math.Ceiling((double)lImdbRatedEpisodes.Count / lPageSize); for (int i = 0; i < lPages; i++) { var lEpisodesRated = Helper.GetTraktEpisodeRateData(lImdbRatedEpisodes.Skip(i * lPageSize).Take(lPageSize)); UIUtils.UpdateStatus($"Importing page {i + 1}/{lPages} IMDb rated episodes..."); var lResponse = TraktAPI.AddsEpisodesToRatings(lEpisodesRated); if (lResponse == null) { UIUtils.UpdateStatus("Error importing IMDb episodes ratings to trakt.tv", true); Thread.Sleep(2000); } else if (lResponse.NotFound.Episodes.Count > 0) { UIUtils.UpdateStatus($"Unable to sync ratings for {lResponse.NotFound.Episodes.Count} IMDb episodes as they're not found on trakt.tv!"); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } } if (mImportCancelled) { return; } #endregion #region Mark Rated Items as Watched IEnumerable <TraktMoviePlays> lWatchedTraktMovies = null; if (AppSettings.MarkAsWatched) { #region Movies var lWatchedCsvMovies = lRatedCsvItems.Where(r => r.Type.ItemType() == IMDbType.Movie) .Select(s => s.ToTraktWatchedMovie()).ToList(); FileLog.Info("Found {0} movies in CSV file", lWatchedCsvMovies.Count); // compare all movies rated against what's not watched on trakt if (lWatchedCsvMovies.Count > 0) { // get watched movies from trakt.tv UIUtils.UpdateStatus("Requesting watched movies from trakt..."); lWatchedTraktMovies = TraktAPI.GetWatchedMovies(); if (lWatchedTraktMovies == null) { UIUtils.UpdateStatus("Failed to get watched movies from trakt.tv, skipping watched movie import", true); Thread.Sleep(2000); } else { if (mImportCancelled) { return; } UIUtils.UpdateStatus($"Found {lWatchedTraktMovies.Count()} watched movies on trakt"); UIUtils.UpdateStatus("Filtering out watched movies that are already watched on trakt.tv"); lWatchedCsvMovies.RemoveAll(w => lWatchedTraktMovies.FirstOrDefault(t => t.Movie.Ids.ImdbId == w.Ids.ImdbId || (t.Movie.Title.ToLowerInvariant() == w.Title.ToLowerInvariant() && t.Movie.Year == w.Year)) != null); // mark all rated movies as watched UIUtils.UpdateStatus($"Importing {lWatchedCsvMovies.Count} IMDb movies as watched..."); int lPageSize = AppSettings.BatchSize; int lPages = (int)Math.Ceiling((double)lRatedCsvMovies.Count / lPageSize); for (int i = 0; i < lPages; i++) { UIUtils.UpdateStatus($"Importing page {i + 1}/{lPages} IMDb movies as watched..."); var lMoviesToSync = new TraktMovieWatchedSync() { Movies = lWatchedCsvMovies.Skip(i * lPageSize).Take(lPageSize).ToList() }; var lResponse = TraktAPI.AddMoviesToWatchedHistory(lMoviesToSync); if (lResponse == null) { UIUtils.UpdateStatus("Failed to send watched status for IMDb movies to trakt.tv", true); Thread.Sleep(2000); } else if (lResponse.NotFound.Movies.Count > 0) { UIUtils.UpdateStatus($"Unable to sync watched states for {lResponse.NotFound.Movies.Count} movies as they're not found on trakt.tv!"); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } } #endregion #region Episodes if (lImdbRatedEpisodes != null && lImdbRatedEpisodes.Any()) { int lPageSize = AppSettings.BatchSize; int lPages = (int)Math.Ceiling((double)lImdbRatedEpisodes.Count / lPageSize); for (int i = 0; i < lPages; i++) { var lEpisodesWatched = Helper.GetTraktEpisodeWatchedData(lImdbRatedEpisodes.Skip(i * lPageSize).Take(lPageSize)); UIUtils.UpdateStatus($"Importing page {i + 1}/{lPages} IMDb watched episodes..."); var lResponse = TraktAPI.AddEpisodesToWatchedHistory(lEpisodesWatched); if (lResponse == null) { UIUtils.UpdateStatus("Error importing IMDb episodes as watched to trakt.tv", true); Thread.Sleep(2000); } else if (lResponse.NotFound.Episodes.Count > 0) { UIUtils.UpdateStatus($"Unable to sync {lResponse.NotFound.Episodes.Count} IMDb episodes as watched, as they're not found on trakt.tv!"); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } #endregion } #endregion #region Import Watchlist Movies var lWatchlistedCsvMovies = lWatchlistCsvItems.Where(r => r.Type.ItemType() == IMDbType.Movie) .Select(s => s.ToTraktMovie()).ToList(); FileLog.Info($"Found {lWatchlistedCsvMovies.Count} movies watchlisted in CSV file"); if (lWatchlistedCsvMovies.Any()) { UIUtils.UpdateStatus("Requesting existing watchlisted movies from trakt..."); var lWatchlistTraktMovies = TraktAPI.GetWatchlistMovies(); if (lWatchlistTraktMovies != null) { UIUtils.UpdateStatus($"Found {lWatchlistTraktMovies.Count()} watchlist movies on trakt"); UIUtils.UpdateStatus("Filtering out watchlist movies that are already in watchlist on trakt.tv"); lWatchlistedCsvMovies.RemoveAll(w => lWatchlistTraktMovies.FirstOrDefault(t => t.Movie.Ids.ImdbId == w.Ids.ImdbId || (t.Movie.Title.ToLowerInvariant() == w.Title.ToLowerInvariant() && t.Movie.Year == w.Year)) != null); } if (AppSettings.IgnoreWatchedForWatchlist && lWatchlistedCsvMovies.Count > 0) { // get watched movies from trakt so we don't import movies into watchlist that are already watched // we may already have this if we imported rated items as watched if (lWatchedTraktMovies != null) { UIUtils.UpdateStatus("Requesting watched movies from trakt..."); lWatchedTraktMovies = TraktAPI.GetWatchedMovies(); if (lWatchedTraktMovies == null) { UIUtils.UpdateStatus("Failed to get watched movies from trakt.tv", true); Thread.Sleep(2000); } } if (lWatchedTraktMovies != null) { UIUtils.UpdateStatus($"Found {lWatchedTraktMovies.Count()} watched movies on trakt"); UIUtils.UpdateStatus("Filtering out watchlist movies that are watched on trakt.tv"); // remove movies from sync list which are watched already lWatchlistedCsvMovies.RemoveAll(w => lWatchedTraktMovies.FirstOrDefault(t => t.Movie.Ids.ImdbId == w.Ids.ImdbId || (t.Movie.Title.ToLowerInvariant() == w.Title.ToLowerInvariant() && t.Movie.Year == w.Year)) != null); } } // add movies to watchlist UIUtils.UpdateStatus($"Importing {lWatchlistedCsvMovies.Count()} IMDb watchlist movies to trakt.tv..."); int lPageSize = AppSettings.BatchSize; int lPages = (int)Math.Ceiling((double)lWatchlistedCsvMovies.Count / lPageSize); for (int i = 0; i < lPages; i++) { UIUtils.UpdateStatus($"Importing page {i + 1}/{lPages} IMDb watchlist movies..."); var lWatchlistedToSync = new TraktMovieSync() { Movies = lWatchlistedCsvMovies.Skip(i * lPageSize).Take(lPageSize).ToList() }; var lResponse = TraktAPI.AddMoviesToWatchlist(lWatchlistedToSync); if (lResponse == null) { UIUtils.UpdateStatus("Failed to send watchlist for IMDb movies", true); Thread.Sleep(2000); } else if (lResponse.NotFound.Movies.Count > 0) { UIUtils.UpdateStatus($"Unable to sync watchlist for {lResponse.NotFound.Movies.Count} movies as they're not found on trakt.tv!"); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } if (mImportCancelled) { return; } #endregion #region Import Watchlist TV Shows IEnumerable <TraktShowPlays> lWatchedTraktShows = null; var lWatchlistedCsvShows = lWatchlistCsvItems.Where(r => r.Type.ItemType() == IMDbType.Show) .Select(s => s.ToTraktShow()).ToList(); FileLog.Info($"Found {lWatchlistedCsvShows.Count} tv shows watchlisted in CSV file"); if (lWatchlistedCsvShows.Any()) { UIUtils.UpdateStatus("Requesting existing watchlisted shows from trakt..."); var lWatchlistTraktShows = TraktAPI.GetWatchlistShows(); if (lWatchlistTraktShows != null) { UIUtils.UpdateStatus($"Found {lWatchlistTraktShows.Count()} watchlist shows on trakt"); UIUtils.UpdateStatus("Filtering out watchlist shows that are already in watchlist on trakt.tv"); lWatchlistedCsvShows.RemoveAll(w => lWatchlistTraktShows.FirstOrDefault(t => t.Show.Ids.ImdbId == w.Ids.ImdbId || (t.Show.Title.ToLowerInvariant() == w.Title.ToLowerInvariant() && t.Show.Year == w.Year)) != null); } if (AppSettings.IgnoreWatchedForWatchlist && lWatchlistedCsvShows.Count > 0) { UIUtils.UpdateStatus("Requesting watched shows from trakt..."); // get watched movies from trakt so we don't import shows into watchlist that are already watched lWatchedTraktShows = TraktAPI.GetWatchedShows(); if (lWatchedTraktShows != null) { UIUtils.UpdateStatus($"Found {lWatchedTraktShows.Count()} watched shows on trakt"); UIUtils.UpdateStatus("Filtering out watchlist shows containing watched episodes on trakt.tv."); // remove shows from sync list which are watched already lWatchlistedCsvShows.RemoveAll(w => lWatchedTraktShows.FirstOrDefault(t => (t.Show.Ids.ImdbId == w.Ids.ImdbId) || (t.Show.Title.ToLowerInvariant() == w.Title.ToLowerInvariant() && t.Show.Year == w.Year)) != null); } } // add shows to watchlist UIUtils.UpdateStatus($"Importing {lWatchlistedCsvShows.Count()} IMDb watchlist shows to trakt.tv..."); int lPageSize = AppSettings.BatchSize; int lPages = (int)Math.Ceiling((double)lWatchlistedCsvShows.Count / lPageSize); for (int i = 0; i < lPages; i++) { UIUtils.UpdateStatus($"Importing page {i + 1}/{lPages} IMDb watchlist shows..."); var lWatchlistShowsToSync = new TraktShowSync { Shows = lWatchlistedCsvShows.Skip(i * lPageSize).Take(lPageSize).ToList() }; var lResponse = TraktAPI.AddShowsToWatchlist(lWatchlistShowsToSync); if (lResponse == null) { UIUtils.UpdateStatus("Failed to send watchlist for IMDb tv shows", true); Thread.Sleep(2000); } else if (lResponse.NotFound.Shows.Count > 0) { UIUtils.UpdateStatus($"Unable to sync watchlist for {lResponse.NotFound.Shows.Count} shows as they're not found on trakt.tv!"); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } if (mImportCancelled) { return; } #endregion #region Import Watchlist Episodes var lImdbWatchlistedEpisodes = new List <IMDbEpisode>(); var lImdbWatchlistedCsvEpisodes = lWatchlistCsvItems.Where(r => r.Type.ItemType() == IMDbType.Episode).ToList(); FileLog.Info($"Found {lImdbWatchlistedCsvEpisodes.Count} tv episodes watchlisted in CSV file"); if (lImdbWatchlistedCsvEpisodes.Any()) { UIUtils.UpdateStatus($"Found {lImdbWatchlistedCsvEpisodes.Count()} IMDb watchlisted episodes"); lImdbWatchlistedEpisodes.AddRange(lImdbWatchlistedCsvEpisodes.Select(Helper.GetIMDbEpisodeFromTrakt).Where(imdbEpisode => imdbEpisode != null)); if (mImportCancelled) { return; } // filter out existing watchlist episodes UIUtils.UpdateStatus("Requesting existing watchlist episodes from trakt..."); var lWatchlistedTraktEpisodes = TraktAPI.GetWatchlistEpisodes(); if (lWatchlistedTraktEpisodes != null) { UIUtils.UpdateStatus($"Found {lWatchlistedTraktEpisodes.Count()} watchlist episodes on trakt"); UIUtils.UpdateStatus("Filtering out watchlist episodes that are already in watchlist on trakt.tv"); lImdbWatchlistedEpisodes.RemoveAll(e => lWatchlistedTraktEpisodes.FirstOrDefault(w => w.Episode.Ids.Trakt == e.TraktId) != null); } if (AppSettings.IgnoreWatchedForWatchlist && lImdbWatchlistedEpisodes.Count > 0) { // we already might have it from the shows sync if (lWatchedTraktShows == null) { UIUtils.UpdateStatus("Requesting watched episodes from trakt..."); // get watched episodes from trakt so we don't import episodes into watchlist that are already watched lWatchedTraktShows = TraktAPI.GetWatchedShows(); } if (lWatchedTraktShows != null) { UIUtils.UpdateStatus("Filtering out watchlist episodes containing watched episodes on trakt.tv"); // this wont work atm due to show IMDb ID not being set in the IMDbEpisode object lImdbWatchlistedEpisodes.RemoveAll(e => lWatchedTraktShows.Where(s => s.Show.Ids.ImdbId == e.ShowImdbId) .Any(s => s.Seasons.Exists(se => se.Number == e.SeasonNumber && se.Episodes.Exists(ep => ep.Number == e.EpisodeNumber)))); } } UIUtils.UpdateStatus($"Importing {lImdbWatchlistedEpisodes.Count()} episodes in watchlist to trakt.tv"); if (lImdbWatchlistedEpisodes.Count > 0) { int lPageSize = AppSettings.BatchSize; int lPages = (int)Math.Ceiling((double)lImdbWatchlistedEpisodes.Count / lPageSize); for (int i = 0; i < lPages; i++) { UIUtils.UpdateStatus($"Importing page {i + 1}/{lPages} IMDb watchlisted episodes..."); var lResponse = TraktAPI.AddEpisodesToWatchlist(Helper.GetTraktEpisodeData(lImdbWatchlistedEpisodes.Skip(i * lPageSize).Take(lPageSize))); if (lResponse == null) { UIUtils.UpdateStatus("Error importing IMDb episode watchlist to trakt.tv", true); Thread.Sleep(2000); } else if (lResponse.NotFound.Episodes.Count > 0) { UIUtils.UpdateStatus("Unable to sync watchlist for {0} IMDb episodes as they're not found on trakt.tv!", lResponse.NotFound.Episodes.Count); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } } #endregion #region Import Custom Lists if (lCustomLists.Count > 0) { UIUtils.UpdateStatus("Requesting custom lists from trakt..."); var lTraktCustomLists = TraktAPI.GetCustomLists(); if (lTraktCustomLists == null) { UIUtils.UpdateStatus("Error requesting custom lists from trakt.tv", true); Thread.Sleep(2000); return; } UIUtils.UpdateStatus($"Found {lTraktCustomLists.Count()} custom lists on trakt.tv"); foreach (var list in lCustomLists) { bool lListCreated = false; string lListName = Path.GetFileNameWithoutExtension(list.Key); // create the list if we don't have it TraktListDetail lTraktCustomList = lTraktCustomLists.FirstOrDefault(l => l.Name == lListName); if (lTraktCustomList == null) { UIUtils.UpdateStatus($"Creating new custom list '{lListName}' on trakt.tv"); var lTraktList = new TraktList { Name = lListName, DisplayNumbers = true, }; lTraktCustomList = TraktAPI.CreateCustomList(lTraktList); if (lTraktCustomList == null) { UIUtils.UpdateStatus("Error creating custom list on trakt.tv, skipping list creation", true); Thread.Sleep(2000); continue; } lListCreated = true; } // get the CSV list items parsed var lIMDbCsvListItems = list.Value; var lImdbCsvListMovies = lIMDbCsvListItems.Where(l => l.Type.ItemType() == IMDbType.Movie).Select(m => m.ToTraktMovie()).ToList(); var lImdbCsvListShows = lIMDbCsvListItems.Where(l => l.Type.ItemType() == IMDbType.Show).Select(m => m.ToTraktShow()).ToList(); FileLog.Info($"Found {lIMDbCsvListItems.Count} movies and {lImdbCsvListShows.Count} shows in IMDb {lListName} list", lListName); // if the list already exists, get current items for list if (!lListCreated) { lTraktCustomList = lTraktCustomLists.FirstOrDefault(l => l.Name == lListName); UIUtils.UpdateStatus($"Requesting existing custom list '{lListName}' items from trakt..."); var lTraktListItems = TraktAPI.GetCustomListItems(lTraktCustomList.Ids.Trakt.ToString()); if (lTraktListItems == null) { UIUtils.UpdateStatus("Error requesting custom list items from trakt.tv, skipping list creation", true); Thread.Sleep(2000); continue; } // filter out existing items from CSV so we don't send again FileLog.Info($"Filtering out existing items from IMDb list '{lListName}' so we don't send again to trakt.tv"); lImdbCsvListMovies.RemoveAll(i => lTraktListItems.FirstOrDefault(l => l.Movie.Ids.ImdbId == i.Ids.ImdbId) != null); lImdbCsvListShows.RemoveAll(i => lTraktListItems.FirstOrDefault(l => l.Show.Ids.ImdbId == i.Ids.ImdbId) != null); } #region Movies UIUtils.UpdateStatus($"Importing {lImdbCsvListMovies.Count} new movies into {lListName} custom list..."); int lPageSize = AppSettings.BatchSize; int lPages = (int)Math.Ceiling((double)lImdbCsvListMovies.Count / lPageSize); for (int i = 0; i < lPages; i++) { UIUtils.UpdateStatus($"Importing page {i + 1}/{lPages} IMDb custom list movies..."); // create list sync object to hold list items var lTraktMovieSync = new TraktSyncAll { Movies = lImdbCsvListMovies.Skip(i * lPageSize).Take(lPageSize).ToList() }; var lResponse = TraktAPI.AddItemsToList(lTraktCustomList.Ids.Trakt.ToString(), lTraktMovieSync); if (lResponse == null) { UIUtils.UpdateStatus("Failed to send custom list items for IMDb movies", true); Thread.Sleep(2000); } else if (lResponse.NotFound.Movies.Count > 0) { UIUtils.UpdateStatus($"Unable to sync custom list items for {lResponse.NotFound.Movies.Count} movies as they're not found on trakt.tv!"); Thread.Sleep(1000); } if (mImportCancelled) { return; } } #endregion #region Shows UIUtils.UpdateStatus("Importing {0} new shows into {1} custom list...", lImdbCsvListShows.Count(), lListName); lPageSize = AppSettings.BatchSize; lPages = (int)Math.Ceiling((double)lImdbCsvListShows.Count / lPageSize); for (int i = 0; i < lPages; i++) { UIUtils.UpdateStatus("Importing page {0}/{1} IMDb custom list shows...", i + 1, lPages); // create list sync object to hold list items var lTraktShowSync = new TraktSyncAll { Shows = lImdbCsvListShows.Skip(i * lPageSize).Take(lPageSize).ToList() }; var lResponse = TraktAPI.AddItemsToList(lTraktCustomList.Ids.Trakt.ToString(), lTraktShowSync); if (lResponse == null) { UIUtils.UpdateStatus("Failed to send custom list items for IMDb shows", true); Thread.Sleep(2000); } else if (lResponse.NotFound.Shows.Count > 0) { UIUtils.UpdateStatus("Unable to sync custom list items for {0} shows as they're not found on trakt.tv!", lResponse.NotFound.Shows.Count); Thread.Sleep(1000); } if (mImportCancelled) { return; } } #endregion } } #endregion }
protected override void OnShowContextMenu() { if (GUIBackgroundTask.Instance.IsBusy) { return; } GUIListItem selectedItem = this.Facade.SelectedListItem; if (selectedItem == null) { return; } var selectedList = selectedItem.TVTag as TraktListDetail; if (selectedItem == null) { return; } var dlg = (IDialogbox)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_MENU); if (dlg == null) { return; } dlg.Reset(); dlg.SetHeading(GUIUtils.PluginName()); GUIListItem listItem = null; // only allow add/delete/update if viewing your own lists if (CurrentUser == TraktSettings.Username) { listItem = new GUIListItem(Translation.CreateList); dlg.Add(listItem); listItem.ItemId = (int)ContextMenuItem.Create; listItem = new GUIListItem(Translation.EditList); dlg.Add(listItem); listItem.ItemId = (int)ContextMenuItem.Edit; listItem = new GUIListItem(Translation.DeleteList); dlg.Add(listItem); listItem.ItemId = (int)ContextMenuItem.Delete; } else { // like list if (!selectedList.IsLiked()) { listItem = new GUIListItem(Translation.Like); dlg.Add(listItem); listItem.ItemId = (int)ContextMenuItem.Like; } else { // unLike list listItem = new GUIListItem(Translation.UnLike); dlg.Add(listItem); listItem.ItemId = (int)ContextMenuItem.Unlike; } // copy a friends list listItem = new GUIListItem(Translation.CopyList); dlg.Add(listItem); listItem.ItemId = (int)ContextMenuItem.Copy; } // Show Context Menu dlg.DoModal(GUIWindowManager.ActiveWindow); if (dlg.SelectedId < 0) { return; } var currentList = new TraktListDetail { Ids = selectedList.Ids, Name = selectedList.Name, Description = selectedList.Description, Privacy = selectedList.Privacy, AllowComments = selectedList.AllowComments, DisplayNumbers = selectedList.DisplayNumbers, ItemCount = selectedList.ItemCount, Likes = selectedList.Likes, UpdatedAt = selectedList.UpdatedAt }; switch (dlg.SelectedId) { case ((int)ContextMenuItem.Create): var list = new TraktListDetail(); if (TraktLists.GetListDetailsFromUser(ref list)) { if (Lists.Any(l => l.Name == list.Name)) { // list with that name already exists GUIUtils.ShowNotifyDialog(Translation.Lists, Translation.ListNameAlreadyExists); return; } TraktLogger.Info("Creating new list for user online. Privacy = '{0}', Name = '{1}'", list.Privacy, list.Name); CreateList(list); } break; case ((int)ContextMenuItem.Delete): DeleteList(selectedList); break; case ((int)ContextMenuItem.Edit): if (TraktLists.GetListDetailsFromUser(ref currentList)) { TraktLogger.Info("Editing list. Name = '{0}', Id = '{1}'", currentList.Name); EditList(currentList); } break; case ((int)ContextMenuItem.Copy): if (TraktLists.GetListDetailsFromUser(ref currentList)) { CopyList(selectedList, currentList); } break; case ((int)ContextMenuItem.Like): GUICommon.LikeList(selectedList, CurrentUser); selectedList.Likes++; PublishListProperties(selectedList); break; case ((int)ContextMenuItem.Unlike): GUICommon.UnLikeList(selectedList, CurrentUser); if (selectedList.Likes > 0) { selectedList.Likes--; PublishListProperties(selectedList); } break; default: break; } base.OnShowContextMenu(); }
public void ImportRatings() { var lRateItems = new List <Dictionary <string, string> >(); var lWatchedItems = new List <Dictionary <string, string> >(); var lDiaryItems = new List <Dictionary <string, string> >(); var lCustomLists = new Dictionary <string, List <LetterboxdListItem> >(); mImportCancelled = false; #region Parse Ratings CSV UIUtils.UpdateStatus("Reading Letterboxd ratings export..."); if (mImportRatings && !ParseCSVFile(mLetterboxdRatingsFile, out lRateItems)) { UIUtils.UpdateStatus("Failed to parse Letterboxd ratings file!", true); Thread.Sleep(2000); return; } if (mImportCancelled) { return; } #endregion #region Parse Watched CSV UIUtils.UpdateStatus("Reading Letterboxd watched export..."); if (mImportWatched && !ParseCSVFile(mLetterboxdWatchedFile, out lWatchedItems)) { UIUtils.UpdateStatus("Failed to parse Letterboxd watched file!", true); Thread.Sleep(2000); return; } if (mImportCancelled) { return; } #endregion #region Parse Diary CSV UIUtils.UpdateStatus("Reading Letterboxd diary export..."); if (mImportDiary && !ParseCSVFile(mLetterboxdDiaryFile, out lDiaryItems)) { UIUtils.UpdateStatus("Failed to parse Letterboxd diary file!", true); Thread.Sleep(2000); return; } if (mImportCancelled) { return; } #endregion #region Parse Custom List CSVs UIUtils.UpdateStatus("Reading Letterboxd custom lists export..."); if (mImportCustomLists) { mCsvConfiguration.RegisterClassMap <LetterboxdListCsvMap>(); foreach (var list in mCustomListsCsvs) { UIUtils.UpdateStatus($"Reading Letterboxd custom list '{list}'"); var lListCsvItems = ParseCsvFile <LetterboxdListItem>(list); if (lListCsvItems == null) { UIUtils.UpdateStatus("Failed to parse Letterboxd custom list file!", true); Thread.Sleep(2000); continue; } lCustomLists.Add(list, lListCsvItems); } mCsvConfiguration.UnregisterClassMap <LetterboxdListCsvMap>(); } if (mImportCancelled) { return; } #endregion #region Import Rated Movies FileLog.Info("Found {0} movie ratings in CSV file", lRateItems.Count); if (lRateItems.Any()) { UIUtils.UpdateStatus("Retrieving existing movie ratings from trakt.tv"); var currentUserMovieRatings = TraktAPI.GetRatedMovies(); if (currentUserMovieRatings != null) { UIUtils.UpdateStatus("Found {0} user movie ratings on trakt.tv", currentUserMovieRatings.Count()); // Filter out movies to rate from existing ratings online lRateItems.RemoveAll(m => currentUserMovieRatings.Any(c => c.Movie.Title == m[LetterboxdFieldMapping.cTitle] && c.Movie.Year.ToString() == m[LetterboxdFieldMapping.cYear])); } UIUtils.UpdateStatus("Importing {0} new movie ratings to trakt.tv", lRateItems.Count()); if (lRateItems.Count > 0) { int pageSize = AppSettings.BatchSize; int pages = (int)Math.Ceiling((double)lRateItems.Count / pageSize); for (int i = 0; i < pages; i++) { UIUtils.UpdateStatus("Importing page {0}/{1} Letterboxd rated movies...", i + 1, pages); TraktSyncResponse response = TraktAPI.AddMoviesToRatings(GetRateMoviesData(lRateItems.Skip(i * pageSize).Take(pageSize))); if (response == null) { UIUtils.UpdateStatus("Error importing Letterboxd movie ratings to trakt.tv", true); Thread.Sleep(2000); } else if (response.NotFound.Movies.Count > 0) { UIUtils.UpdateStatus("Unable to sync Letterboxd ratings for {0} movies as they're not found on trakt.tv!", response.NotFound.Movies.Count); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } } if (mImportCancelled) { return; } #endregion #region Import Watched Movies // The Dairy can can include rated and watched items, it also has a watched date // if the watched movie exists in the diary use that as a watched date otherwise use date from watched file // add to diary any watched films that have been back filled foreach (var movie in lWatchedItems) { if (!lDiaryItems.Exists(d => d[LetterboxdFieldMapping.cTitle] == movie[LetterboxdFieldMapping.cTitle] && d[LetterboxdFieldMapping.cYear] == movie[LetterboxdFieldMapping.cYear])) { lDiaryItems.Add(movie); } } if (lDiaryItems.Count > 0) { // get watched movies from trakt.tv UIUtils.UpdateStatus("Requesting watched movies from trakt..."); var watchedTraktMovies = TraktAPI.GetWatchedMovies(); if (watchedTraktMovies == null) { UIUtils.UpdateStatus("Failed to get watched movies from trakt.tv, skipping watched movie import", true); Thread.Sleep(2000); } else { if (mImportCancelled) { return; } UIUtils.UpdateStatus("Found {0} watched movies on trakt", watchedTraktMovies.Count()); UIUtils.UpdateStatus("Filtering out watched movies that are already watched on trakt.tv"); lDiaryItems.RemoveAll(d => watchedTraktMovies.FirstOrDefault(t => t.Movie.Title == d[LetterboxdFieldMapping.cTitle] && t.Movie.Year.ToString() == d[LetterboxdFieldMapping.cYear]) != null); UIUtils.UpdateStatus("Importing {0} Letterboxd movies as watched...", lDiaryItems.Count); int pageSize = AppSettings.BatchSize; int pages = (int)Math.Ceiling((double)lDiaryItems.Count / pageSize); for (int i = 0; i < pages; i++) { UIUtils.UpdateStatus("Importing page {0}/{1} Letterboxd movies as watched...", i + 1, pages); var response = TraktAPI.AddMoviesToWatchedHistory(GetSyncWatchedMoviesData(lDiaryItems.Skip(i * pageSize).Take(pageSize).ToList())); if (response == null) { UIUtils.UpdateStatus("Failed to send watched status for Letterboxd movies to trakt.tv", true); Thread.Sleep(2000); } else if (response.NotFound.Movies.Count > 0) { UIUtils.UpdateStatus("Unable to sync Letterboxd watched states for {0} movies as they're not found on trakt.tv!", response.NotFound.Movies.Count); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } } #endregion #region Import Custom Lists if (lCustomLists.Count > 0) { UIUtils.UpdateStatus("Requesting custom lists from trakt..."); var lTraktCustomLists = TraktAPI.GetCustomLists(); if (lTraktCustomLists == null) { UIUtils.UpdateStatus("Error requesting custom lists from trakt.tv", true); Thread.Sleep(2000); return; } UIUtils.UpdateStatus($"Found {lTraktCustomLists.Count()} custom lists on trakt.tv"); foreach (var list in lCustomLists) { bool lListCreated = false; string lListName = Path.GetFileNameWithoutExtension(list.Key); // create the list if we don't have it TraktListDetail lTraktCustomList = lTraktCustomLists.FirstOrDefault(l => l.Name == lListName); if (lTraktCustomList == null) { UIUtils.UpdateStatus($"Creating new custom list '{lListName}' on trakt.tv"); var lTraktList = new TraktList { Name = lListName, DisplayNumbers = true, }; lTraktCustomList = TraktAPI.CreateCustomList(lTraktList); if (lTraktCustomList == null) { UIUtils.UpdateStatus("Error creating custom list on trakt.tv, skipping list creation", true); Thread.Sleep(2000); continue; } lListCreated = true; } FileLog.Info($"Found {list.Value.Count} movies in Letterboxd {lListName} list"); // if the list already exists, get current items for list if (!lListCreated) { lTraktCustomList = lTraktCustomLists.FirstOrDefault(l => l.Name == lListName); UIUtils.UpdateStatus($"Requesting existing custom list '{lListName}' items from trakt..."); var lTraktListItems = TraktAPI.GetCustomListItems(lTraktCustomList.Ids.Trakt.ToString()); if (lTraktListItems == null) { UIUtils.UpdateStatus("Error requesting custom list items from trakt.tv, skipping list creation", true); Thread.Sleep(2000); continue; } // filter out existing items from CSV so we don't send again FileLog.Info($"Filtering out existing items from Letterboxd list '{lListName}' so we don't send again to trakt.tv"); list.Value.RemoveAll(i => lTraktListItems.FirstOrDefault(l => l.Movie.Title.ToLowerInvariant() == i.Title.ToLowerInvariant() && l.Movie.Year == i.Year) != null); } UIUtils.UpdateStatus($"Importing {list.Value.Count} new movies into {lListName} custom list..."); var lLetterboxdCsvListMovies = list.Value.Select(m => m.ToTraktMovie()); int lPageSize = AppSettings.BatchSize; int lPages = ( int )Math.Ceiling(( double )list.Value.Count / lPageSize); for (int i = 0; i < lPages; i++) { UIUtils.UpdateStatus($"Importing page {i + 1}/{lPages} Letterboxd custom list movies..."); // create list sync object to hold list items var lTraktMovieSync = new TraktSyncAll { Movies = lLetterboxdCsvListMovies.Skip(i * lPageSize).Take(lPageSize).ToList() }; var lResponse = TraktAPI.AddItemsToList(lTraktCustomList.Ids.Trakt.ToString(), lTraktMovieSync); if (lResponse == null) { UIUtils.UpdateStatus("Failed to send custom list items for Letterboxd movies", true); Thread.Sleep(2000); } else if (lResponse.NotFound.Movies.Count > 0) { UIUtils.UpdateStatus($"Unable to sync custom list items for {lResponse.NotFound.Movies.Count} movies as they're not found on trakt.tv!"); Thread.Sleep(1000); } if (mImportCancelled) { return; } } } } #endregion }