public static DBSeries getCorrespondingSeries(int id) { try { DBSeries cached = cache.getSeries(id); if (cached != null) { return(cached); } SQLCondition cond = new SQLCondition(); cond.Add(new DBSeries(), DBSeries.cID, id, SQLConditionType.Equal); List <DBSeries> tmpSeries = DBSeries.Get(cond); foreach (DBSeries series in tmpSeries) // should only be one! { if (series[DBSeries.cID] == id) { cache.addChangeSeries(series); return(series); } } return(null); } catch (Exception) { return(null); } }
protected override void OnLoad(EventArgs e) { // Get list of series in view SQLCondition conditions = new SQLCondition(); conditions.Add(new DBOnlineSeries(), DBOnlineSeries.cTraktIgnore, 1, SQLConditionType.Equal); CheckedItems = DBSeries.Get(conditions); // Get list of series not in view conditions = new SQLCondition(); conditions.Add(new DBOnlineSeries(), DBOnlineSeries.cTraktIgnore, 1, SQLConditionType.NotEqual); UnCheckedItems = DBSeries.Get(conditions); // Populate series list, // mark as checked at top of list foreach (DBSeries series in CheckedItems) { checkedListBoxSeries.Items.Add(series, true); } foreach (DBSeries series in UnCheckedItems) { checkedListBoxSeries.Items.Add(series, false); } CheckedCount = CheckedItems.Count; labelSeriesSelected.Text = CheckedCount.ToString() + " Series Selected"; this.checkedListBoxSeries.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.checkedListBoxSeries_ItemCheck); base.OnLoad(e); }
void MarkEpisodeAsWatched(DBEpisode episode) { // Could be a double episode, so mark both as watched SQLCondition condition = new SQLCondition(); condition.Add(new DBEpisode(), DBEpisode.cFilename, episode[DBEpisode.cFilename], SQLConditionType.Equal); List <DBEpisode> episodes = DBEpisode.Get(condition, false); foreach (DBEpisode ep in episodes) { string date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); ep[DBOnlineEpisode.cWatched] = 1; ep[DBOnlineEpisode.cPlayCount] = ep[DBOnlineEpisode.cPlayCount] + 1; ep[DBEpisode.cDateWatched] = date; ep[DBOnlineEpisode.cLastWatchedDate] = date; if (string.IsNullOrEmpty(ep[DBOnlineEpisode.cFirstWatchedDate])) { ep[DBOnlineEpisode.cFirstWatchedDate] = date; } ep.Commit(); } // Update Episode Counts DBSeries series = Helper.getCorrespondingSeries(m_currentEpisode[DBEpisode.cSeriesID]); DBSeason season = Helper.getCorrespondingSeason(episode[DBEpisode.cSeriesID], episode[DBEpisode.cSeasonIndex]); DBSeason.UpdateEpisodeCounts(series, season); }
/// <summary> /// Get a series id by show name /// </summary> /// <param name="seriesName">Name of the series to look for</param> /// <returns>A series id or null if none was found</returns> public static int? GetSeriesIdByName(string seriesName) { SQLCondition conditions = new SQLCondition(); conditions.Add(new DBOnlineSeries(), DBOnlineSeries.cPrettyName, seriesName, SQLConditionType.Like); List<DBSeries> seriesList = DBSeries.Get(conditions); // Return best matching series or null if no result was found if (seriesList.Count == 1) { return seriesList[0][DBOnlineSeries.cID]; } else if (seriesList.Count > 1) { foreach (DBSeries series in seriesList) { if (series[DBOnlineSeries.cPrettyName].Equals(seriesName)) { return series[DBOnlineSeries.cID]; } } return seriesList[0][DBOnlineSeries.cID]; } else { return null; } }
public List <string> deleteSeries(TVSeriesPlugin.DeleteMenuItems type) { List <string> resultMsg = new List <string>(); // Always delete from Local episode table if deleting from disk or database SQLCondition condition = new SQLCondition(); condition.Add(new DBSeason(), DBSeason.cSeriesID, this[DBSeries.cID], SQLConditionType.Equal); /* TODO dunno if to include or exclude hidden items. * if they are excluded then the if (resultMsg.Count is wrong and should do another select to get proper count * if (!DBOption.GetOptions(DBOption.cShowHiddenItems)) * { * //don't include hidden seasons unless the ShowHiddenItems option is set * condition.Add(new DBSeason(), DBSeason.cHidden, 0, SQLConditionType.Equal); * } */ List <DBSeason> seasons = DBSeason.Get(condition, false); if (seasons != null) { foreach (DBSeason season in seasons) { resultMsg.AddRange(season.deleteSeason(type)); } } #region Facade Remote Color // if we were successful at deleting all episodes of series from disk, set HasLocalFiles to false // note: we only do this if the database entries still exist if (resultMsg.Count == 0 && type == TVSeriesPlugin.DeleteMenuItems.disk) { this[DBOnlineSeries.cHasLocalFiles] = false; this.Commit(); } #endregion #region Cleanup // if there are no error messages and if we need to delete from db // Delete from online tables and season/series tables IsSeriesRemoved = false; if (resultMsg.Count == 0 && type != TVSeriesPlugin.DeleteMenuItems.disk) { condition = new SQLCondition(); condition.Add(new DBSeries(), DBSeries.cID, this[DBSeries.cID], SQLConditionType.Equal); DBSeries.Clear(condition); condition = new SQLCondition(); condition.Add(new DBOnlineSeries(), DBOnlineSeries.cID, this[DBSeries.cID], SQLConditionType.Equal); DBOnlineSeries.Clear(condition); IsSeriesRemoved = true; } #endregion return(resultMsg); }
public static List <DBSeason> Get(int nSeriesID, SQLCondition otherConditions) { // create table if it doesn't exist already if (nSeriesID != default(int)) { otherConditions.Add(new DBSeason(), cSeriesID, nSeriesID, SQLConditionType.Equal); } return(Get(otherConditions)); }
public static List <DBEpisode> GetEpisodesToSync(DBSeries series, TraktSyncModes mode) { List <DBEpisode> episodes = new List <DBEpisode>(); SQLCondition conditions = new SQLCondition(); if (series == null) { // Get episodes for every series conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, 0, SQLConditionType.GreaterThan); } else { // Get episodes for a single series conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, series[DBSeries.cID], SQLConditionType.Equal); } switch (mode) { case TraktSyncModes.library: conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cTraktLibrary, 0, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cHidden, 0, SQLConditionType.Equal); conditions.Add(new DBEpisode(), DBEpisode.cFilename, string.Empty, SQLConditionType.NotEqual); episodes = DBEpisode.Get(conditions, false); break; case TraktSyncModes.seen: conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cHidden, 0, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cWatched, 1, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cTraktSeen, 0, SQLConditionType.Equal); episodes = DBEpisode.Get(conditions, false); break; case TraktSyncModes.unseen: conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cHidden, 0, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cTraktSeen, 2, SQLConditionType.Equal); episodes = DBEpisode.Get(conditions, false); break; } return(episodes); }
public static DBSeries Get(int seriesID, bool includeStdCond) { SQLCondition cond = new SQLCondition(); cond.Add(new DBOnlineSeries(), DBOnlineSeries.cID, seriesID, SQLConditionType.Equal); foreach (DBSeries series in Get(cond, false, includeStdCond)) { return(series); } return(null); }
public static void UpdateEpisodeCounts(DBSeries series) { if (series == null) { return; } int seriesEpsTotal = 0; int seriesEpsUnWatched = 0; int epsTotal = 0; int epsUnWatched = 0; // Update for each season in series and add each to total series count SQLCondition condition = new SQLCondition(); if (!DBOption.GetOptions(DBOption.cShowHiddenItems)) { //don't include hidden seasons unless the ShowHiddenItems option is set condition.Add(new DBSeason(), DBSeason.cHidden, 0, SQLConditionType.Equal); } List <DBSeason> Seasons = DBSeason.Get(series[DBSeries.cID], condition); foreach (DBSeason season in Seasons) { epsTotal = 0; epsUnWatched = 0; DBEpisode.GetSeasonEpisodeCounts(series, season, out epsTotal, out epsUnWatched); season[DBSeason.cEpisodeCount] = epsTotal; season[DBSeason.cEpisodesUnWatched] = epsUnWatched; season[DBSeason.cUnwatchedItems] = epsUnWatched > 0; season.Commit(); seriesEpsTotal += epsTotal; // Count the Special (Season 0 (zero)) episodes as watched! if ((season[DBSeason.cIndex] != 0) || (season[DBSeason.cIndex] == 0 && !DBOption.GetOptions(DBOption.cCountSpecialEpisodesAsWatched))) { seriesEpsUnWatched += epsUnWatched; } MPTVSeriesLog.Write(string.Format("Series \"{0} Season {1}\" has {2}/{3} unwatched episodes", series.ToString(), season[DBSeason.cIndex], epsUnWatched, epsTotal), MPTVSeriesLog.LogLevel.Debug); } MPTVSeriesLog.Write(string.Format("Series \"{0}\" has {1}/{2} unwatched episodes", series.ToString(), seriesEpsUnWatched, seriesEpsTotal), MPTVSeriesLog.LogLevel.Debug); series[DBOnlineSeries.cEpisodeCount] = seriesEpsTotal; series[DBOnlineSeries.cEpisodesUnWatched] = seriesEpsUnWatched; series[DBOnlineSeries.cUnwatchedItems] = seriesEpsUnWatched > 0; series.Commit(); }
private bool AddItem(string episodeID) { SQLCondition condition = new SQLCondition(); condition.Add(new DBOnlineEpisode(), DBOnlineEpisode.cID, episodeID, SQLConditionType.Equal); List <DBEpisode> ep = DBEpisode.Get(condition, false); if (ep.Count > 0) { PlayListItem newItem = new PlayListItem(ep[0]); playlist.Add(newItem); } return(true); }
/// <summary> /// does not use StdCond /// </summary> /// <param name="seriesID"></param> /// <param name="index"></param> /// <returns></returns> public static DBSeason getRaw(int seriesID, int index) { SQLCondition cond = new SQLCondition(new DBSeason(), cSeriesID, seriesID, SQLConditionType.Equal); cond.Add(new DBSeason(), cIndex, index, SQLConditionType.Equal); List <DBSeason> res = Get(cond, false); if (res.Count > 0) { return(res[0]); } else { return(null); } }
public bool ReadPrimary(DBValue Value) { try { m_fields[PrimaryKey()].Value = Value; SQLCondition condition = new SQLCondition(); condition.Add(this, PrimaryKey(), m_fields[PrimaryKey()].Value, SQLConditionType.Equal); String sqlQuery = "select * from " + m_tableName + condition; SQLiteResultSet records = DBTVSeries.Execute(sqlQuery); return(Read(ref records, 0)); } catch (Exception ex) { MPTVSeriesLog.Write("An Error Occurred (" + ex.Message + ")."); } return(false); }
private void treeView_Library_AfterExpand(object sender, TreeViewEventArgs e) { TreeNode node = e.Node; if (node.Level != 0) return; Font defaultFont = treeView_Library.Font; DBSeries series = (DBSeries)node.Tag; int seriesID = series[DBSeries.cID]; ////////////////////////////////////////////////////////////////////////////// #region Load Episodes into season tree child nodes of expanding series foreach (TreeNode childNode in node.Nodes) { // Check if we have already loaded episodes into season nodes if (childNode.Nodes.Count == 0) { // ensure we use the correct season field for DVD sort order string seasonField = series[DBOnlineSeries.cEpisodeSortOrder] == "DVD" ? DBOnlineEpisode.cCombinedSeason : DBOnlineEpisode.cSeasonIndex; string episodeField = series[DBOnlineSeries.cEpisodeSortOrder] == "DVD" ? DBOnlineEpisode.cCombinedEpisodeNumber : DBOnlineEpisode.cEpisodeIndex; DBSeason season = (DBSeason)childNode.Tag; int seasonIndex = season[DBSeason.cIndex]; SQLCondition conditions = new SQLCondition(); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, series[DBSeries.cID], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), seasonField, seasonIndex, SQLConditionType.Equal); List<DBEpisode> episodes = DBEpisode.Get(conditions); // sort by correct order episodes.Sort(); foreach (DBEpisode episode in episodes) { String episodeName = (String)episode[DBEpisode.cEpisodeName]; TreeNode episodeNode = new TreeNode(episode[seasonField] + "x" + episode[episodeField] + " - " + episodeName); episodeNode.Name = DBEpisode.cTableName; episodeNode.Tag = (DBEpisode)episode; // set color for non-local file if (episode[DBEpisode.cFilename].ToString().Length == 0) { episodeNode.ForeColor = System.Drawing.SystemColors.GrayText; } else { // set color for watched episode if (episode[DBOnlineEpisode.cWatched] == 1) episodeNode.ForeColor = System.Drawing.Color.DarkBlue; } // set FontStyle for hidden episodes if (episode[DBOnlineEpisode.cHidden]) episodeNode.NodeFont = new Font(defaultFont.Name, defaultFont.Size, FontStyle.Italic); childNode.Nodes.Add(episodeNode); } } } #endregion ////////////////////////////////////////////////////////////////////////////// }
private void UpdateNode(TreeNode nodeUpdated) { if (nodeUpdated != null) { SQLCondition conditions = new SQLCondition(); List<DBValue> epIdsUpdates = new List<DBValue>(); List<DBValue> seriesIDsUpdates = new List<DBValue>(); switch (nodeUpdated.Name) { case DBSeries.cTableName: DBSeries series = nodeUpdated.Tag as DBSeries; seriesIDsUpdates.Add(series[DBSeries.cID]); conditions = new SQLCondition(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, series[DBSeries.cID], SQLConditionType.Equal); epIdsUpdates.AddRange(DBEpisode.GetSingleField(DBOnlineEpisode.cID, conditions, new DBOnlineEpisode())); break; case DBSeason.cTableName: DBSeason season = nodeUpdated.Tag as DBSeason; conditions = new SQLCondition(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, season[DBSeason.cSeriesID], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeasonIndex, season[DBSeason.cIndex], SQLConditionType.Equal); epIdsUpdates.AddRange(DBEpisode.GetSingleField(DBOnlineEpisode.cID, conditions, new DBOnlineEpisode())); break; case DBEpisode.cTableName: DBEpisode episode = nodeUpdated.Tag as DBEpisode; epIdsUpdates.Add(episode[DBOnlineEpisode.cID]); break; } if (epIdsUpdates.Count > 0) { Parsing_Start((new CParsingParameters(new List<ParsingAction> { ParsingAction.UpdateSeries, ParsingAction.UpdateEpisodes, ParsingAction.UpdateEpisodeThumbNails, ParsingAction.UpdateCommunityRatings }, seriesIDsUpdates, epIdsUpdates))); } } }
public bool Scrobble(string filename) { if (!EpisodeWatching) return false; StopScrobble(); TraktLogger.Info(string.Format("Found playing episode {0}", CurrentEpisode.ToString())); MarkedFirstAsWatched = false; // create timer 15 minute timer to send watching status #region scrobble timer TraktTimer = new Timer(new TimerCallback((stateInfo) => { Thread.CurrentThread.Name = "Scrobble Episode"; // duration in minutes double duration = CurrentEpisode[DBEpisode.cLocalPlaytime] / 60000; double progress = 0.0; // get current progress of player (in seconds) to work out percent complete if (duration > 0.0) progress = ((g_Player.CurrentPosition / 60.0) / duration) * 100.0; TraktEpisodeScrobble scrobbleData = null; // check if double episode has passed halfway mark and set as watched if (CurrentEpisode[DBEpisode.cEpisodeIndex2] > 0 && progress > 50.0) { SQLCondition condition = new SQLCondition(); condition.Add(new DBEpisode(), DBEpisode.cFilename, CurrentEpisode[DBEpisode.cFilename], SQLConditionType.Equal); List<DBEpisode> episodes = DBEpisode.Get(condition, false); if (!MarkedFirstAsWatched) { // send scrobble Watched status of first episode OnEpisodeWatched(episodes[0]); Thread.Sleep(5000); } EpisodeWatching = true; MarkedFirstAsWatched = true; // we are now watching 2nd part of double episode scrobbleData = CreateScrobbleData(episodes[1]); } else { // we are watching a single episode or 1st part of double episode scrobbleData = CreateScrobbleData(CurrentEpisode); } if (scrobbleData == null) return; // set duration/progress in scrobble data scrobbleData.Duration = Convert.ToInt32(duration).ToString(); scrobbleData.Progress = Convert.ToInt32(progress).ToString(); // set watching status on trakt TraktResponse response = TraktAPI.TraktAPI.ScrobbleEpisodeState(scrobbleData, TraktScrobbleStates.watching); TraktAPI.TraktAPI.LogTraktResponse(response); }), null, 3000, 900000); #endregion return true; }
public List<string> deleteSeries(TVSeriesPlugin.DeleteMenuItems type) { List<string> resultMsg = new List<string>(); // Always delete from Local episode table if deleting from disk or database SQLCondition condition = new SQLCondition(); condition.Add(new DBSeason(), DBSeason.cSeriesID, this[DBSeries.cID], SQLConditionType.Equal); /* TODO dunno if to include or exclude hidden items. * if they are excluded then the if (resultMsg.Count is wrong and should do another select to get proper count if (!DBOption.GetOptions(DBOption.cShowHiddenItems)) { //don't include hidden seasons unless the ShowHiddenItems option is set condition.Add(new DBSeason(), DBSeason.cHidden, 0, SQLConditionType.Equal); } */ List<DBSeason> seasons = DBSeason.Get(condition, false); if (seasons != null) { foreach (DBSeason season in seasons) { resultMsg.AddRange(season.deleteSeason(type)); } } #region Facade Remote Color // if we were successful at deleting all episodes of series from disk, set HasLocalFiles to false // note: we only do this if the database entries still exist if (resultMsg.Count == 0 && type == TVSeriesPlugin.DeleteMenuItems.disk) { this[DBOnlineSeries.cHasLocalFiles] = false; this.Commit(); } #endregion #region Cleanup // if there are no error messages and if we need to delete from db // Delete from online tables and season/series tables IsSeriesRemoved = false; if (resultMsg.Count == 0 && type != TVSeriesPlugin.DeleteMenuItems.disk) { condition = new SQLCondition(); condition.Add(new DBSeries(), DBSeries.cID, this[DBSeries.cID], SQLConditionType.Equal); DBSeries.Clear(condition); condition = new SQLCondition(); condition.Add(new DBOnlineSeries(), DBOnlineSeries.cID, this[DBSeries.cID], SQLConditionType.Equal); DBOnlineSeries.Clear(condition); IsSeriesRemoved = true; } #endregion return resultMsg; }
public void SyncLibrary() { TraktLogger.Info("MP-TVSeries Library Starting Sync"); // store list of series ids so we can update the episode counts // of any series that syncback watched flags var seriesToUpdateEpisodeCounts = new HashSet<int>(); #region Get online data from cache #region UnWatched / Watched List<TraktCache.EpisodeWatched> traktWatchedEpisodes = null; // get all episodes on trakt that are marked as 'unseen' var traktUnWatchedEpisodes = TraktCache.GetUnWatchedEpisodesFromTrakt().ToNullableList(); if (traktUnWatchedEpisodes == null) { TraktLogger.Error("Error getting tv shows unwatched from trakt.tv server, unwatched and watched sync will be skipped"); } else { TraktLogger.Info("Found {0} unwatched tv episodes in trakt.tv library", traktUnWatchedEpisodes.Count()); // now get all episodes on trakt that are marked as 'seen' or 'watched' (this will be cached already when working out unwatched) traktWatchedEpisodes = TraktCache.GetWatchedEpisodesFromTrakt().ToNullableList(); if (traktWatchedEpisodes == null) { TraktLogger.Error("Error getting tv shows watched from trakt.tv server, watched sync will be skipped"); } else { TraktLogger.Info("Found {0} watched tv episodes in trakt.tv library", traktWatchedEpisodes.Count()); } } #endregion #region Collection // get all episodes on trakt that are marked as in 'collection' var traktCollectedEpisodes = TraktCache.GetCollectedEpisodesFromTrakt().ToNullableList(); if (traktCollectedEpisodes == null) { TraktLogger.Error("Error getting tv episode collection from trakt.tv server"); } else { TraktLogger.Info("Found {0} tv episodes in trakt.tv collection", traktCollectedEpisodes.Count()); } #endregion #region Ratings #region Episodes var traktRatedEpisodes = TraktCache.GetRatedEpisodesFromTrakt().ToNullableList(); if (traktRatedEpisodes == null) { TraktLogger.Error("Error getting rated episodes from trakt.tv server"); } else { TraktLogger.Info("Found {0} rated tv episodes in trakt.tv library", traktRatedEpisodes.Count()); } #endregion #region Shows var traktRatedShows = TraktCache.GetRatedShowsFromTrakt().ToNullableList(); if (traktRatedShows == null) { TraktLogger.Error("Error getting rated shows from trakt.tv server"); } else { TraktLogger.Info("Found {0} rated tv shows in trakt.tv library", traktRatedShows.Count()); } #endregion #region Seasons var traktRatedSeasons = TraktCache.GetRatedSeasonsFromTrakt().ToNullableList(); if (traktRatedSeasons == null) { TraktLogger.Error("Error getting rated seasons from trakt.tv server"); } else { TraktLogger.Info("Found {0} rated tv seasons in trakt.tv library", traktRatedSeasons.Count()); } #endregion #endregion #region Watchlist #region Shows var traktWatchlistedShows = TraktCache.GetWatchlistedShowsFromTrakt(); if (traktWatchlistedShows == null) { TraktLogger.Error("Error getting watchlisted shows from trakt.tv server"); } else { TraktLogger.Info("Found {0} watchlisted tv shows in trakt.tv library", traktWatchlistedShows.Count()); } #endregion #region Seasons var traktWatchlistedSeasons = TraktCache.GetWatchlistedSeasonsFromTrakt(); if (traktWatchlistedSeasons == null) { TraktLogger.Error("Error getting watchlisted seasons from trakt.tv server"); } else { TraktLogger.Info("Found {0} watchlisted tv seasons in trakt.tv library", traktWatchlistedSeasons.Count()); } #endregion #region Episodes var traktWatchlistedEpisodes = TraktCache.GetWatchlistedEpisodesFromTrakt(); if (traktWatchlistedEpisodes == null) { TraktLogger.Error("Error getting watchlisted episodes from trakt.tv server"); } else { TraktLogger.Info("Found {0} watchlisted tv episodes in trakt.tv library", traktWatchlistedEpisodes.Count()); } #endregion #endregion #endregion // optionally do library sync if (TraktSettings.SyncLibrary) { #region Get data from local database TraktLogger.Info("Getting local episodes from tvseries database, Ignoring {0} tv show(s) set by user", IgnoredSeries.Count); // Get all episodes in database SQLCondition conditions = new SQLCondition(); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, 0, SQLConditionType.GreaterThan); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cHidden, 0, SQLConditionType.Equal); var localEpisodes = DBEpisode.Get(conditions, false); int episodeCount = localEpisodes.Count; // filter out the ignored shows localEpisodes.RemoveAll(e => IgnoredSeries.Contains(e[DBOnlineEpisode.cSeriesID])); TraktLogger.Info("Found {0} total episodes in tvseries database{1}", episodeCount, IgnoredSeries.Count > 0 ? string.Format(" and {0} ignored episodes", episodeCount - localEpisodes.Count) : ""); // Get episodes of files that we have locally var localCollectedEpisodes = localEpisodes.Where(e => !string.IsNullOrEmpty(e[DBEpisode.cFilename].ToString())).ToList(); TraktLogger.Info("Found {0} episodes with local files in tvseries database", localCollectedEpisodes.Count); // Get watched episodes of files that we have locally or are remote // user could of deleted episode from disk but still have reference to it in database var localWatchedEpisodes = localEpisodes.Where(e => e[DBOnlineEpisode.cWatched] > 0).ToList(); var localUnWatchedEpisodes = localEpisodes.Except(localWatchedEpisodes).ToList(); TraktLogger.Info("Found {0} episodes watched in tvseries database", localWatchedEpisodes.Count); var localRatedEpisodes = new List<DBEpisode>(); var localNonRatedEpisodes = new List<DBEpisode>(); var localRatedShows = new List<DBSeries>(); var localNonRatedShows = new List<DBSeries>(); if (TraktSettings.SyncRatings) { // get the episodes that we have rated/unrated localRatedEpisodes.AddRange(localEpisodes.Where(e => e[DBOnlineEpisode.cMyRating] > 0)); localNonRatedEpisodes = localEpisodes.Except(localRatedEpisodes).ToList(); TraktLogger.Info("Found {0} episodes rated in tvseries database", localRatedEpisodes.Count); // get the shows that we have rated/unrated var shows = DBSeries.Get(new SQLCondition()); localRatedShows.AddRange(shows.Where(s => s[DBOnlineSeries.cMyRating] > 0 && !IgnoredSeries.Contains(s[DBOnlineSeries.cID]))); localNonRatedShows = shows.Except(localRatedShows).ToList(); TraktLogger.Info("Found {0} shows rated in tvseries database", localRatedShows.Count); } #endregion #region Mark episodes as unwatched in local database TraktLogger.Info("Start sync of tv episode unwatched state to local database"); if (traktUnWatchedEpisodes != null && traktUnWatchedEpisodes.Count() > 0) { // create a unique key to lookup and search for faster var localLookupEpisodes = localWatchedEpisodes.ToLookup(twe => CreateLookupKey(twe), twe => twe); foreach (var episode in traktUnWatchedEpisodes) { if (IgnoredSeries.Exists(tvdbid => tvdbid == episode.ShowTvdbId)) continue; string tvdbKey = CreateLookupKey(episode); var watchedEpisode = localLookupEpisodes[tvdbKey].FirstOrDefault(); if (watchedEpisode != null) { TraktLogger.Info("Marking episode as unwatched in local database, episode is not watched on trakt.tv. Title = '{0}', Year = '{1}', Season = '{2}', Episode = '{3}', Show TVDb ID = '{4}', Show IMDb ID = '{5}'", episode.ShowTitle, episode.ShowYear.HasValue ? episode.ShowYear.ToString() : "<empty>", episode.Season, episode.Number, episode.ShowTvdbId.HasValue ? episode.ShowTvdbId.ToString() : "<empty>", episode.ShowImdbId ?? "<empty>"); watchedEpisode[DBOnlineEpisode.cWatched] = false; watchedEpisode.Commit(); // update watched/unwatched counter later seriesToUpdateEpisodeCounts.Add(watchedEpisode[DBOnlineEpisode.cSeriesID]); // update watched episodes localWatchedEpisodes.Remove(watchedEpisode); } } } #endregion #region Mark episodes as watched in local database TraktLogger.Info("Start sync of tv episode watched state to local database"); if (traktWatchedEpisodes != null && traktWatchedEpisodes.Count() > 0) { // create a unique key to lookup and search for faster var onlineEpisodes = traktWatchedEpisodes.ToLookup(twe => CreateLookupKey(twe), twe => twe); foreach (var episode in localUnWatchedEpisodes) { string tvdbKey = CreateLookupKey(episode); var traktEpisode = onlineEpisodes[tvdbKey].FirstOrDefault(); if (traktEpisode != null) { TraktLogger.Info("Marking episode as watched in local database, episode is watched on trakt.tv. Plays = '{0}', Title = '{1}', Year = '{2}', Season = '{3}', Episode = '{4}', Show TVDb ID = '{5}', Show IMDb ID = '{6}', Last Watched = '{7}'", traktEpisode.Plays, traktEpisode.ShowTitle, traktEpisode.ShowYear.HasValue ? traktEpisode.ShowYear.ToString() : "<empty>", traktEpisode.Season, traktEpisode.Number, traktEpisode.ShowTvdbId.HasValue ? traktEpisode.ShowTvdbId.ToString() : "<empty>", traktEpisode.ShowImdbId ?? "<empty>", traktEpisode.WatchedAt); episode[DBOnlineEpisode.cWatched] = true; episode[DBOnlineEpisode.cPlayCount] = traktEpisode.Plays; if (string.IsNullOrEmpty(episode[DBOnlineEpisode.cLastWatchedDate])) episode[DBOnlineEpisode.cLastWatchedDate] = traktEpisode.WatchedAt.FromISO8601().ToString("yyyy-MM-dd HH:mm:ss"); if (string.IsNullOrEmpty(episode[DBOnlineEpisode.cFirstWatchedDate])) episode[DBOnlineEpisode.cFirstWatchedDate] = traktEpisode.WatchedAt.FromISO8601().ToString("yyyy-MM-dd HH:mm:ss"); if (!string.IsNullOrEmpty(episode[DBEpisode.cFilename]) && string.IsNullOrEmpty(episode[DBEpisode.cDateWatched])) episode[DBEpisode.cDateWatched] = traktEpisode.WatchedAt.FromISO8601().ToString("yyyy-MM-dd HH:mm:ss"); episode.Commit(); // update watched/unwatched counter later seriesToUpdateEpisodeCounts.Add(episode[DBOnlineEpisode.cSeriesID]); } } } #endregion #region Rate episodes/shows in local database if (TraktSettings.SyncRatings) { #region Episodes TraktLogger.Info("Start sync of tv episode ratings to local database"); if (traktRatedEpisodes != null && traktRatedEpisodes.Count() > 0) { // create a unique key to lookup and search for faster var onlineEpisodes = traktRatedEpisodes.ToLookup(tre => CreateLookupKey(tre), tre => tre); foreach (var episode in localNonRatedEpisodes) { string tvdbKey = CreateLookupKey(episode); var traktEpisode = onlineEpisodes[tvdbKey].FirstOrDefault(); if (traktEpisode != null) { // update local collection rating TraktLogger.Info("Inserting rating for tv episode in local database, episode is rated on trakt.tv. Rating = '{0}/10', Title = '{1}', Year = '{2}' Season = '{3}', Episode = '{4}', Show TVDb ID = '{5}', Show IMDb ID = '{6}', Episode TVDb ID = '{7}'", traktEpisode.Rating, traktEpisode.Show.Title, traktEpisode.Show.Year.HasValue ? traktEpisode.Show.Year.ToString() : "<empty>", traktEpisode.Episode.Season, traktEpisode.Episode.Number, traktEpisode.Show.Ids.Tvdb.HasValue ? traktEpisode.Show.Ids.Tvdb.ToString() : "<empty>", traktEpisode.Show.Ids.Imdb ?? "<empty>", traktEpisode.Episode.Ids.Tvdb.HasValue ? traktEpisode.Episode.Ids.Tvdb.ToString() : "<empty>"); // we could potentially use the RatedAt date to insert a DateWatched if empty or less than episode[DBOnlineEpisode.cMyRating] = traktEpisode.Rating; episode["myRatingAt"] = traktEpisode.RatedAt.FromISO8601().ToString("yyyy-MM-dd HH:mm:ss"); episode.Commit(); } } } #endregion #region Shows TraktLogger.Info("Start sync of tv show ratings to local database"); if (traktRatedShows != null && traktRatedShows.Count() > 0) { foreach (var show in localNonRatedShows) { if (IgnoredSeries.Exists(tvdbid => tvdbid == show[DBSeries.cID])) continue; // if we have the episode unrated, rate it var traktShow = traktRatedShows.FirstOrDefault(trs => ShowMatch(show, trs.Show)); if (traktShow == null) continue; // update local collection rating TraktLogger.Info("Inserting rating for tv show in local database, show is rated on trakt.tv. Rating = '{0}/10', Title = '{1}', Year = '{1}', Show TVDb ID = '{2}'", traktShow.Rating, traktShow.Show.Title, traktShow.Show.Year.HasValue ? traktShow.Show.Year.ToString() : "<empty>" , traktShow.Show.Ids.Tvdb.HasValue ? traktShow.Show.Ids.Tvdb.ToString() : "<empty>"); show[DBOnlineSeries.cMyRating] = traktShow.Rating; show["myRatingAt"] = traktShow.RatedAt.FromISO8601().ToString("yyyy-MM-dd HH:mm:ss"); show.Commit(); } } #endregion } #endregion #region Add episodes to watched history at trakt.tv int showCount = 0; int iSyncCounter = 0; if (traktWatchedEpisodes != null) { var syncWatchedShows = GetWatchedShowsForSyncEx(localWatchedEpisodes, traktWatchedEpisodes); TraktLogger.Info("Found {0} local tv show(s) with {1} watched episode(s) to add to trakt.tv watched history", syncWatchedShows.Shows.Count, syncWatchedShows.Shows.Sum(sh => sh.Seasons.Sum(se => se.Episodes.Count()))); showCount = syncWatchedShows.Shows.Count; foreach (var show in syncWatchedShows.Shows) { int showEpisodeCount = show.Seasons.Sum(s => s.Episodes.Count()); TraktLogger.Info("Adding tv show [{0}/{1}] to trakt.tv episode watched history, Episode Count = '{2}', Show Title = '{3}', Show Year = '{4}', Show TVDb ID = '{5}', Show IMDb ID = '{6}'", ++iSyncCounter, showCount, showEpisodeCount, show.Title, show.Year.HasValue ? show.Year.ToString() : "<empty>", show.Ids.Tvdb, show.Ids.Imdb ?? "<empty>"); show.Seasons.ForEach(s => s.Episodes.ForEach(e => { TraktLogger.Info("Adding episode to trakt.tv watched history, Title = '{0} - {1}x{2}', Watched At = '{3}'", show.Title, s.Number, e.Number, e.WatchedAt.ToLogString()); })); // only sync one show at a time regardless of batch size in settings var pagedShows = new List<TraktSyncShowWatchedEx>(); pagedShows.Add(show); var response = TraktAPI.TraktAPI.AddShowsToWatchedHistoryEx(new TraktSyncShowsWatchedEx { Shows = pagedShows }); TraktLogger.LogTraktResponse<TraktSyncResponse>(response); // only add to cache if it was a success // note: we don't get back the same object type so makes it hard to figure out what failed if (response != null && response.Added != null && response.Added.Episodes == showEpisodeCount) { // update local cache TraktCache.AddEpisodesToWatchHistory(show); } } } #endregion #region Add episodes to collection at trakt.tv if (traktCollectedEpisodes != null) { var syncCollectedShows = GetCollectedShowsForSyncEx(localCollectedEpisodes, traktCollectedEpisodes); TraktLogger.Info("Found {0} local tv show(s) with {1} collected episode(s) to add to trakt.tv collection", syncCollectedShows.Shows.Count, syncCollectedShows.Shows.Sum(sh => sh.Seasons.Sum(se => se.Episodes.Count()))); iSyncCounter = 0; showCount = syncCollectedShows.Shows.Count; foreach (var show in syncCollectedShows.Shows) { int showEpisodeCount = show.Seasons.Sum(s => s.Episodes.Count()); TraktLogger.Info("Adding tv show [{0}/{1}] to trakt.tv episode collection, Episode Count = '{2}', Show Title = '{3}', Show Year = '{4}', Show TVDb ID = '{5}', Show IMDb ID = '{6}'", ++iSyncCounter, showCount, showEpisodeCount, show.Title, show.Year.HasValue ? show.Year.ToString() : "<empty>", show.Ids.Tvdb, show.Ids.Imdb ?? "<empty>"); show.Seasons.ForEach(s => s.Episodes.ForEach(e => { TraktLogger.Info("Adding episode to trakt.tv collection, Title = '{0} - {1}x{2}', Collected At = '{3}', Audio Channels = '{4}', Audio Codec = '{5}', Resolution = '{6}', Media Type = '{7}', Is 3D = '{8}'", show.Title, s.Number, e.Number, e.CollectedAt.ToLogString(), e.AudioChannels.ToLogString(), e.AudioCodec.ToLogString(), e.Resolution.ToLogString(), e.MediaType.ToLogString(), e.Is3D); })); // only sync one show at a time regardless of batch size in settings var pagedShows = new List<TraktSyncShowCollectedEx>(); pagedShows.Add(show); var response = TraktAPI.TraktAPI.AddShowsToCollectonEx(new TraktSyncShowsCollectedEx { Shows = pagedShows }); TraktLogger.LogTraktResponse<TraktSyncResponse>(response); // only add to cache if it was a success if (response != null && response.Added != null && response.Added.Episodes == showEpisodeCount) { // update local cache TraktCache.AddEpisodesToCollection(show); } } } #endregion #region Add episode/show ratings to trakt.tv if (TraktSettings.SyncRatings) { #region Episodes if (traktRatedEpisodes != null) { var syncRatedShowsEx = GetRatedEpisodesForSyncEx(localRatedEpisodes, traktRatedEpisodes); TraktLogger.Info("Found {0} local tv show(s) with {1} rated episode(s) to add to trakt.tv ratings", syncRatedShowsEx.Shows.Count, syncRatedShowsEx.Shows.Sum(sh => sh.Seasons.Sum(se => se.Episodes.Count()))); iSyncCounter = 0; showCount = syncRatedShowsEx.Shows.Count; foreach (var show in syncRatedShowsEx.Shows) { int showEpisodeCount = show.Seasons.Sum(s => s.Episodes.Count()); TraktLogger.Info("Adding tv show [{0}/{1}] to trakt.tv episode ratings, Episode Count = '{2}', Show Title = '{3}', Show Year = '{4}', Show TVDb ID = '{5}', Show IMDb ID = '{6}'", ++iSyncCounter, showCount, showEpisodeCount, show.Title, show.Year.HasValue ? show.Year.ToString() : "<empty>", show.Ids.Tvdb, show.Ids.Imdb ?? "<empty>"); show.Seasons.ForEach(s => s.Episodes.ForEach(e => { TraktLogger.Info("Adding episode to trakt.tv ratings, Title = '{0} - {1}x{2}', Rating = '{3}', Rated At = '{4}'", show.Title, s.Number, e.Number, e.Rating, e.RatedAt.ToLogString()); })); // only sync one show at a time regardless of batch size in settings var pagedShows = new List<TraktSyncShowRatedEx>(); pagedShows.Add(show); var response = TraktAPI.TraktAPI.AddShowsToRatingsEx(new TraktSyncShowsRatedEx { Shows = pagedShows }); TraktLogger.LogTraktResponse<TraktSyncResponse>(response); // only add to cache if it was a success if (response != null && response.Added != null && response.Added.Episodes == showEpisodeCount) { // update local cache TraktCache.AddEpisodesToRatings(show); } } } #endregion #region Shows if (traktRatedShows != null) { var syncRatedShows = new List<TraktSyncShowRated>(); TraktLogger.Info("Finding local tv shows to add to trakt.tv ratings"); syncRatedShows = (from show in localRatedShows where !traktRatedShows.ToList().Exists(trs => ShowMatch(show, trs.Show)) select new TraktSyncShowRated { Ids = new TraktShowId { Tvdb = show[DBSeries.cID], Imdb = BasicHandler.GetProperImdbId(show[DBOnlineSeries.cIMDBID]) }, Title = show[DBOnlineSeries.cOriginalName], Year = show.Year.ToNullableInt32(), Rating = show[DBOnlineSeries.cMyRating], RatedAt = DateTime.UtcNow.ToISO8601(), }).ToList(); TraktLogger.Info("Found {0} local tv show(s) rated to add to trakt.tv ratings", syncRatedShows.Count); if (syncRatedShows.Count > 0) { // update local cache TraktCache.AddShowsToRatings(syncRatedShows); int pageSize = TraktSettings.SyncBatchSize; int pages = (int)Math.Ceiling((double)syncRatedShows.Count / pageSize); for (int i = 0; i < pages; i++) { TraktLogger.Info("Adding tv shows [{0}/{1}] to trakt.tv ratings", i + 1, pages); var pagedShows = syncRatedShows.Skip(i * pageSize).Take(pageSize).ToList(); pagedShows.ForEach(s => { TraktLogger.Info("Adding tv show to trakt.tv ratings, Title = '{0}', Year = '{1}', TVDb ID = '{2}', IMDb ID = '{3}', Rating = '{4}', Rated At = '{5}'", s.Title, s.Year.ToLogString(), s.Ids.Tvdb.ToLogString(), s.Ids.Imdb.ToLogString(), s.Rating, s.RatedAt.ToLogString()); }); var response = TraktAPI.TraktAPI.AddShowsToRatings(new TraktSyncShowsRated { Shows = pagedShows }); TraktLogger.LogTraktResponse(response); // remove from cache if not a success if (response != null && response.NotFound != null && response.NotFound.Shows.Count > 0) { TraktCache.RemoveShowsFromRatings(response.NotFound.Shows); } } } } #endregion } #endregion #region Remove episodes no longer in collection from trakt.tv if (TraktSettings.KeepTraktLibraryClean && TraktSettings.TvShowPluginCount == 1 && traktCollectedEpisodes != null) { var syncRemovedShows = GetRemovedShowsForSyncEx(localCollectedEpisodes, traktCollectedEpisodes); TraktLogger.Info("Found {0} local tv show(s) with {1} episode(s) to remove from trakt.tv collection", syncRemovedShows.Shows.Count, syncRemovedShows.Shows.Sum(sh => sh.Seasons.Sum(se => se.Episodes.Count()))); iSyncCounter = 0; showCount = syncRemovedShows.Shows.Count; foreach (var show in syncRemovedShows.Shows) { int showEpisodeCount = show.Seasons.Sum(s => s.Episodes.Count()); TraktLogger.Info("Removing tv show [{0}/{1}] from trakt.tv episode collection, Episode Count = '{2}', Show Title = '{3}', Show Year = '{4}', Show TVDb ID = '{5}', Show IMDb ID = '{6}'", ++iSyncCounter, showCount, showEpisodeCount, show.Title, show.Year.HasValue ? show.Year.ToString() : "<empty>", show.Ids.Tvdb, show.Ids.Imdb ?? "<empty>"); show.Seasons.ForEach(s => s.Episodes.ForEach(e => { TraktLogger.Info("Removing episode from trakt.tv collection, Title = '{0} - {1}x{2}'", show.Title, s.Number, e.Number); })); // only sync one show at a time regardless of batch size in settings var pagedShows = new List<TraktSyncShowEx>(); pagedShows.Add(show); // update local cache TraktCache.RemoveEpisodesFromCollection(show); var response = TraktAPI.TraktAPI.RemoveShowsFromCollectonEx(new TraktSyncShowsEx { Shows = pagedShows }); TraktLogger.LogTraktResponse<TraktSyncResponse>(response); } } #endregion #region Update episode counts in local database foreach (int seriesID in seriesToUpdateEpisodeCounts) { var series = Helper.getCorrespondingSeries(seriesID); if (series == null) continue; TraktLogger.Info("Updating episode counts in local database for series. Title = '{0}', Year = '{1}', Show TVDb ID = '{2}'", series.ToString(), series.Year ?? "<empty>", series[DBSeries.cID]); DBSeries.UpdateEpisodeCounts(series); } #endregion } TraktLogger.Info("MP-TVSeries Library Sync Completed"); }
public List <string> deleteSeason(TVSeriesPlugin.DeleteMenuItems type) { List <string> resultMsg = new List <string>(); // Always delete from Local episode table if deleting from disk or database SQLCondition condition = new SQLCondition(); condition.Add(new DBEpisode(), DBEpisode.cSeriesID, this[DBSeason.cSeriesID], SQLConditionType.Equal); condition.Add(new DBEpisode(), DBEpisode.cSeasonIndex, this[DBSeason.cIndex], SQLConditionType.Equal); /* TODO will include hidden episodes as hidden attribute is only in onlineepisodes. maybe we should include it in localepisodes also.. * if hidden episodes are excluded then the if (resultMsg.Count is wrong and should do another select to get proper count * if (!DBOption.GetOptions(DBOption.cShowHiddenItems)) * { * //don't include hidden seasons unless the ShowHiddenItems option is set * condition.Add(new DBEpisode(), idden, 0, SQLConditionType.Equal); * } */ List <DBEpisode> episodes = DBEpisode.Get(condition, false); if (episodes != null) { bool hasLocalEpisodesToDelete = episodes.Exists(e => !string.IsNullOrEmpty(e[DBEpisode.cFilename])); hasLocalEpisodesToDelete &= (type == TVSeriesPlugin.DeleteMenuItems.disk || type == TVSeriesPlugin.DeleteMenuItems.diskdatabase); DBSeries series = Helper.getCorrespondingSeries(this[DBSeason.cSeriesID]); string seriesName = series == null ? this[DBSeason.cSeriesID].ToString() : series.ToString(); // show progress dialog as this can be a long process esp for network drives // will show new progress for each season if deleting from the series level GUIDialogProgress progressDialog = null; if (!Settings.isConfig) { progressDialog = (GUIDialogProgress)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_PROGRESS); progressDialog.Reset(); progressDialog.DisplayProgressBar = true; progressDialog.ShowWaitCursor = false; progressDialog.DisableCancel(true); progressDialog.SetHeading(Translation.Delete); progressDialog.Percentage = 0; progressDialog.SetLine(1, string.Format("{0} {1} {2}", seriesName, Translation.Season, this[DBSeason.cIndex])); progressDialog.SetLine(2, string.Empty); // only show progress dialog if we have local files in season if (hasLocalEpisodesToDelete) { progressDialog.StartModal(GUIWindowManager.ActiveWindow); } } int counter = 0; foreach (DBEpisode episode in episodes) { string episodeName = string.Format("{0}x{1} - {2}", episode[DBOnlineEpisode.cSeasonIndex], episode[DBOnlineEpisode.cEpisodeIndex], episode[DBOnlineEpisode.cEpisodeName]); if (!Settings.isConfig) { progressDialog.SetLine(2, episodeName); } if (!Settings.isConfig) { GUIWindowManager.Process(); } resultMsg.AddRange(episode.deleteEpisode(type, true)); if (!Settings.isConfig) { progressDialog.Percentage = Convert.ToInt32(((double)++counter / (double)episodes.Count) * 100.0); } if (!Settings.isConfig) { GUIWindowManager.Process(); } } // close progress dialog if (!Settings.isConfig) { progressDialog.Close(); } // if we have removed all episodes in season without error, cleanup the online table if (resultMsg.Count == 0 && type != TVSeriesPlugin.DeleteMenuItems.disk) { condition = new SQLCondition(); condition.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, this[DBSeason.cSeriesID], SQLConditionType.Equal); condition.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeasonIndex, this[DBSeason.cIndex], SQLConditionType.Equal); DBOnlineEpisode.Clear(condition); } } #region Facade Remote Color // if we were successful at deleting all episodes of season from disk, set HasLocalFiles to false // note: we only do this if the database entries still exist if (resultMsg.Count == 0 && type == TVSeriesPlugin.DeleteMenuItems.disk) { this[cHasLocalFiles] = false; this.Commit(); } // if we were successful at deleting all episodes of season from disk, // also check if any local episodes exist on disk for series and set HasLocalFiles to false if (resultMsg.Count == 0 && type != TVSeriesPlugin.DeleteMenuItems.database) { // Check Series for Local Files SQLCondition episodeConditions = new SQLCondition(); episodeConditions.Add(new DBEpisode(), DBEpisode.cSeriesID, this[DBSeason.cSeriesID], SQLConditionType.Equal); List <DBEpisode> localEpisodes = DBEpisode.Get(episodeConditions); if (localEpisodes.Count == 0 && !DBSeries.IsSeriesRemoved) { DBSeries series = DBSeries.Get(this[DBSeason.cSeriesID]); if (series != null) { series[DBOnlineSeries.cHasLocalFiles] = false; series.Commit(); } } } #endregion #region Cleanup // if there are no error messages and if we need to delete from db if (resultMsg.Count == 0 && type != TVSeriesPlugin.DeleteMenuItems.disk) { condition = new SQLCondition(); condition.Add(new DBSeason(), DBSeason.cSeriesID, this[DBSeason.cSeriesID], SQLConditionType.Equal); condition.Add(new DBSeason(), DBSeason.cIndex, this[DBSeason.cIndex], SQLConditionType.Equal); DBSeason.Clear(condition); } DBSeries.IsSeriesRemoved = false; if (type != TVSeriesPlugin.DeleteMenuItems.disk) { // If local/online episode count is zero then delete the series and all seasons condition = new SQLCondition(); condition.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, this[DBSeason.cSeriesID], SQLConditionType.Equal); episodes = DBEpisode.Get(condition, false); if (episodes.Count == 0) { // Delete Seasons condition = new SQLCondition(); condition.Add(new DBSeason(), DBSeason.cSeriesID, this[DBSeason.cSeriesID], SQLConditionType.Equal); DBSeason.Clear(condition); // Delete Local Series condition = new SQLCondition(); condition.Add(new DBSeries(), DBSeries.cID, this[DBSeason.cSeriesID], SQLConditionType.Equal); DBSeries.Clear(condition); // Delete Online Series condition = new SQLCondition(); condition.Add(new DBOnlineSeries(), DBOnlineSeries.cID, this[DBSeason.cSeriesID], SQLConditionType.Equal); DBOnlineSeries.Clear(condition); DBSeries.IsSeriesRemoved = true; } } #endregion return(resultMsg); }
private void btnRemoveView_Click(object sender, EventArgs e) { if (availViews.Count == 0) return; // Get Selected View from list selectedView = Helper.getElementFromList<logicalView, string>((string)_availViews.SelectedItem, "Name", 0, availViews); // Confirm Delete string message = string.Format("Are you sure you want to delete view \"{0}\"?",selectedView.prettyName); DialogResult result = MessageBox.Show(message, "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (result == DialogResult.No) return; // if view is a tagged view, remove series attached to view if (selectedView.IsTaggedView) { // Get list of series in view SQLCondition conditions = new SQLCondition(); conditions.Add(new DBOnlineSeries(), DBOnlineSeries.cViewTags, selectedView.Name, SQLConditionType.Like); List<DBSeries> series = DBSeries.Get(conditions); foreach (DBSeries s in series) { s[DBOnlineSeries.cViewTags] = Helper.GetSeriesViewTags(s, false, selectedView.Name); s.Commit(); // Remove from online database if (selectedView.Name == DBView.cTranslateTokenOnlineFavourite) Online_Parsing_Classes.OnlineAPI.ConfigureFavourites(false, DBOption.GetOptions(DBOption.cOnlineUserID), s[DBOnlineSeries.cID]); } } // Get All current Views DBView[] views = DBView.getAll(true); // Remove all Rows from Database DBView.ClearAll(); int index = 0; // Add Rows back excluding deleted one foreach (DBView view in views) { if (view[DBView.cIndex] != int.Parse(selectedView.m_uniqueID)) { DBView newView = new DBView(); newView[DBView.cIndex] = index; newView[DBView.cEnabled] = view[DBView.cEnabled]; newView[DBView.cSort] = view[DBView.cSort]; newView[DBView.cTransToken] = view[DBView.cTransToken]; newView[DBView.cPrettyName] = view[DBView.cPrettyName]; newView[DBView.cViewConfig] = view[DBView.cViewConfig]; newView[DBView.cTaggedView] = view[DBView.cTaggedView]; newView[DBView.cParentalControl] = view[DBView.cParentalControl]; newView.Commit(); index++; } } // Reload List and available Views LoadViews(); // Select First Item in list if (_availViews.Items.Count > 0) _availViews.SelectedIndex = 0; }
private void linkExWatched_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { SaveFileDialog fd = new SaveFileDialog(); fd.Filter = "Exported Watched Flags (*.watched)|*.watched"; if (fd.ShowDialog() == DialogResult.OK) { StreamWriter w = new StreamWriter(fd.FileName); SQLCondition cond = new SQLCondition(); cond.Add(new DBOnlineEpisode(), DBOnlineEpisode.cWatched, true, SQLConditionType.Equal); foreach (DBValue val in DBOnlineEpisode.GetSingleField(DBOnlineEpisode.cCompositeID, cond, new DBOnlineEpisode())) { try { w.WriteLine((string)val); } catch(IOException exception) { MPTVSeriesLog.Write("Watched info NOT exported! Error: " + exception.ToString()); return; } } w.Close(); MPTVSeriesLog.Write("Watched info succesfully exported!"); } }
private void ChangeEpisodeMatchingOrder(DBSeries series, string order) { MPTVSeriesLog.Write("Changing Episode Match Order for {0}, to {1}", series.ToString(), order); // get list of local episodes to re-match SQLCondition conditions = new SQLCondition(); conditions.Add(new DBEpisode(), DBEpisode.cSeriesID, series[DBSeries.cID], SQLConditionType.Equal); List<DBEpisode> localEpisodes = DBEpisode.Get(conditions); OnlineParsing.matchOnlineToLocalEpisodes(series, localEpisodes, new GetEpisodes(series[DBSeries.cID]), order); return; }
private void UpdateEpisodes(DBSeries series, DBSeason season, DBEpisode episode) { List<DBValue> epIDsUpdates = new List<DBValue>(); List<DBValue> seriesIDsUpdates = new List<DBValue>(); SQLCondition conditions = null; string searchPattern = string.Empty; // Get selected Series and/or list of Episode(s) to update switch (this.listLevel) { case Listlevel.Series: seriesIDsUpdates.Add(series[DBSeries.cID]); conditions = new SQLCondition(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, series[DBSeries.cID], SQLConditionType.Equal); epIDsUpdates.AddRange(DBEpisode.GetSingleField(DBOnlineEpisode.cID, conditions, new DBOnlineEpisode())); searchPattern = "*.jpg"; break; case Listlevel.Season: conditions = new SQLCondition(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, season[DBSeason.cSeriesID], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeasonIndex, season[DBSeason.cIndex], SQLConditionType.Equal); epIDsUpdates.AddRange(DBEpisode.GetSingleField(DBOnlineEpisode.cID, conditions, new DBOnlineEpisode())); searchPattern = season[DBSeason.cIndex] + "x*.jpg"; break; case Listlevel.Episode: epIDsUpdates.Add(episode[DBOnlineEpisode.cID]); conditions = new SQLCondition(new DBOnlineEpisode(), DBOnlineEpisode.cID, episode[DBOnlineEpisode.cID], SQLConditionType.Equal); searchPattern = episode[DBOnlineEpisode.cSeasonIndex] + "x" + episode[DBOnlineEpisode.cEpisodeIndex] + ".jpg"; break; } // Delete Physical Thumbnails // Dont prompt if just doing a single episode update bool deleteThumbs = true; if (this.listLevel != Listlevel.Episode) { GUIDialogYesNo dlgYesNo = (GUIDialogYesNo)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_YES_NO); if (dlgYesNo != null) { dlgYesNo.Reset(); dlgYesNo.SetHeading(Translation.DeleteThumbnailsHeading); dlgYesNo.SetLine(1, Translation.DeleteThumbnailsLine1); dlgYesNo.SetLine(2, Translation.DeleteThumbnailsLine2); dlgYesNo.SetDefaultToYes(false); dlgYesNo.DoModal(GUIWindowManager.ActiveWindow); if (!dlgYesNo.IsConfirmed) deleteThumbs = false; } } if (deleteThumbs) { string thumbnailPath = Helper.PathCombine(Settings.GetPath(Settings.Path.banners), Helper.cleanLocalPath(series.ToString()) + @"\Episodes"); // Search and delete matching files that actually exist string[] fileList = Directory.GetFiles(thumbnailPath, searchPattern); foreach (string file in fileList) { MPTVSeriesLog.Write("Deleting Episode Thumbnail: " + file); FileInfo fileInfo = new FileInfo(file); try { fileInfo.Delete(); } catch (Exception ex) { MPTVSeriesLog.Write("Failed to Delete Episode Thumbnail: " + file + ": " + ex.Message); } } // Remove local thumbnail reference from db so that it thumbnails will be downloaded DBEpisode.GlobalSet(new DBOnlineEpisode(), DBOnlineEpisode.cEpisodeThumbnailFilename, (DBValue)"", conditions); } // Execute Online Parsing Actions if (epIDsUpdates.Count > 0) { lock (m_parserUpdaterQueue) { List<ParsingAction> parsingActions = new List<ParsingAction>(); // Conditional parsing actions if (this.listLevel == Listlevel.Series) parsingActions.Add(ParsingAction.UpdateSeries); parsingActions.Add(ParsingAction.UpdateEpisodes); if (deleteThumbs) parsingActions.Add(ParsingAction.UpdateEpisodeThumbNails); parsingActions.Add(ParsingAction.UpdateEpisodeCounts); m_parserUpdaterQueue.Add(new CParsingParameters(parsingActions, seriesIDsUpdates, epIDsUpdates)); } } }
protected override void OnShowContextMenu() { try { GUIListItem currentitem = this.m_Facade.SelectedListItem; if (currentitem == null) return; IDialogbox dlg = (IDialogbox)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_MENU); if (dlg == null) return; DBEpisode selectedEpisode = null; DBSeason selectedSeason = null; DBSeries selectedSeries = null; bool emptyList = currentitem.Label == Translation.No_items; if (!emptyList) { switch (this.listLevel) { case Listlevel.Episode: { selectedEpisode = (DBEpisode)currentitem.TVTag; selectedSeason = Helper.getCorrespondingSeason(selectedEpisode[DBEpisode.cSeriesID], selectedEpisode[DBEpisode.cSeasonIndex]); selectedSeries = Helper.getCorrespondingSeries(selectedEpisode[DBEpisode.cSeriesID]); } break; case Listlevel.Season: { selectedSeason = (DBSeason)currentitem.TVTag; selectedSeries = Helper.getCorrespondingSeries(selectedSeason[DBSeason.cSeriesID]); } break; case Listlevel.Series: { selectedSeries = (DBSeries)currentitem.TVTag; } break; } } bool bExitMenu = false; do { dlg.Reset(); GUIListItem pItem = null; bool subtitleDownloadEnabled = DBOption.GetOptions(DBOption.cSubCentralEnabled) && Helper.IsSubCentralAvailableAndEnabled; if (!emptyList) { switch (this.listLevel) { case Listlevel.Episode: dlg.SetHeading(Translation.Episode + ": " + selectedEpisode[DBEpisode.cEpisodeName]); break; case Listlevel.Season: dlg.SetHeading(Translation.Season + ": " + selectedSeason[DBSeason.cIndex]); break; case Listlevel.Series: dlg.SetHeading(Translation.Series + ": " + selectedSeries[DBOnlineSeries.cPrettyName]); break; default: // group dlg.SetHeading(m_CurrLView.Name); break; } #region Top Level Menu Items - Context Sensitive if (this.listLevel == Listlevel.Episode) { pItem = new GUIListItem(Translation.Toggle_watched_flag); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.toggleWatched; if (!String.IsNullOrEmpty(DBOption.GetOptions(DBOption.cOnlineUserID)) || FollwitConnector.Enabled) { pItem = new GUIListItem(Translation.RateEpisode + " ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextMenus.rate; } } else if (this.listLevel != Listlevel.Group) { if (!String.IsNullOrEmpty(DBOption.GetOptions(DBOption.cOnlineUserID)) || FollwitConnector.Enabled) { pItem = new GUIListItem(Translation.RateSeries + " ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextMenus.rate; } pItem = new GUIListItem(Translation.Mark_all_as_watched); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.actionMarkAllWatched; pItem = new GUIListItem(Translation.Mark_all_as_unwatched); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.actionMarkAllUnwatched; } // Add To Playlist is supported on all views // Group: Add all episodes for all series in selected group (TODO) // Series: Add all episodes for selected series // Season: Add all episodes for selected season // Episode: Add selected episode if (this.listLevel != Listlevel.Group) { pItem = new GUIListItem(Translation.AddToPlaylist); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.addToPlaylist; } if (this.listLevel != Listlevel.Group) { if (m_SelectedSeries != null && FanartBackground != null && // only if skins supports it m_SelectedSeries[DBOnlineSeries.cID] > 0) { pItem = new GUIListItem(Translation.FanArt + " ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.showFanartChooser; } if (File.Exists(GUIGraphicsContext.Skin + @"\TVSeries.Actors.xml")) { pItem = new GUIListItem(Translation.Actors + " ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.showActorsGUI; } } if (this.listLevel == Listlevel.Series) { if (selectedSeries.PosterList.Count > 1) { pItem = new GUIListItem(Translation.CycleSeriesPoster); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.cycleSeriesPoster; } if (selectedSeries.BannerList.Count > 1) { pItem = new GUIListItem(Translation.CycleSeriesBanner); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.cycleSeriesBanner; } pItem = new GUIListItem(Translation.Force_Online_Match); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.forceSeriesQuery; } // Season View may not be available so show cycle season banner at episode level as well if (this.listLevel == Listlevel.Season || this.listLevel == Listlevel.Episode) { if (selectedSeason.BannerList.Count > 1) { pItem = new GUIListItem(Translation.CycleSeasonBanner); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.cycleSeasonPoster; } } // Can always add to existing or new view if (listLevel == Listlevel.Series) { pItem = new GUIListItem(Translation.AddViewTag + " ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextMenus.addToView; } // Dont show if not a member of any view if (listLevel == Listlevel.Series) { if (!String.IsNullOrEmpty(selectedSeries[DBOnlineSeries.cViewTags])) { pItem = new GUIListItem(Translation.RemoveViewTag + " ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextMenus.removeFromView; } } #endregion } else dlg.SetHeading(m_CurrLView.Name); #region Top Level Menu Items - Non-Context Sensitive pItem = new GUIListItem(Translation.ChangeView + " ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextMenus.switchView; if (SkinSettings.GetLayoutCount(this.listLevel.ToString()) > 1) { pItem = new GUIListItem(Translation.ChangeLayout + " ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextMenus.switchLayout; } if (listLevel != Listlevel.Group) { pItem = new GUIListItem(Translation.Actions + " ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextMenus.action; pItem = new GUIListItem(Translation.Filters + " ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextMenus.filters; } pItem = new GUIListItem(Translation.Options + " ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextMenus.options; #endregion #region trakt.tv menu if (Helper.IsTraktAvailableAndEnabled) { pItem = new GUIListItem("Trakt ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.trakt; } #endregion #region My Torrents Search if (listLevel != Listlevel.Group && Helper.IsMyTorrentsAvailableAndEnabled) { pItem = new GUIListItem(Translation.SearchTorrent + " ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.downloadTorrent; } #endregion #region NZB Search if (listLevel == Listlevel.Episode && Helper.IsMpNZBAvailableAndEnabled) { pItem = new GUIListItem(Translation.SearchNZB + " ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.downloadNZB; } #endregion #region Subtitles - keep at the bottom for fast access (menu + up => there) if (!emptyList && subtitleDownloadEnabled && this.listLevel == Listlevel.Episode) { pItem = new GUIListItem(Translation.Subtitles); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.downloadSubtitle; } #endregion dlg.DoModal(GUIWindowManager.ActiveWindow); #region Selected Menu Item Actions (Sub-Menus) switch (dlg.SelectedId) { case (int)eContextMenus.action: { dlg.Reset(); dlg.SetHeading(Translation.Actions); if (listLevel != Listlevel.Group) { if (DBOption.GetOptions(DBOption.cShowDeleteMenu)) { pItem = new GUIListItem(Translation.Delete + " ..."); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.actionDelete; } if (!m_parserUpdaterWorking) { pItem = new GUIListItem(Translation.Update); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.actionUpdate; } // add hidden menu // check if item is already hidden pItem = new GUIListItem(); switch (listLevel) { case Listlevel.Series: pItem.Label = selectedSeries[DBSeries.cHidden] ? Translation.UnHide : Translation.Hide; break; case Listlevel.Season: pItem.Label = selectedSeason[DBSeries.cHidden] ? Translation.UnHide : Translation.Hide; break; case Listlevel.Episode: pItem.Label = selectedEpisode[DBSeries.cHidden] ? Translation.UnHide : Translation.Hide; break; } dlg.Add(pItem); pItem.ItemId = (int)eContextItems.actionHide; pItem = new GUIListItem(Translation.updateMI); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.actionRecheckMI; } // Online to Local Episode Matching order if (this.listLevel != Listlevel.Group) { // get current online episode to local episode matching order string currMatchOrder = selectedSeries[DBOnlineSeries.cChosenEpisodeOrder].ToString(); if (string.IsNullOrEmpty(currMatchOrder)) currMatchOrder = "Aired"; pItem = new GUIListItem(Translation.ChangeOnlineMatchOrder); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.actionChangeOnlineEpisodeMatchOrder; } // Episode Sort By if (this.listLevel == Listlevel.Episode || this.listLevel == Listlevel.Season) { // get current episode sort order (DVD or Aired) string currSortBy = selectedSeries[DBOnlineSeries.cEpisodeSortOrder].ToString(); if (string.IsNullOrEmpty(currSortBy)) currSortBy = "Aired"; pItem = new GUIListItem(string.Format("{0}: {1}", Translation.SortBy, Translation.GetByName(currSortBy + "Order"))); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.actionEpisodeSortBy; } pItem = new GUIListItem(Translation.Force_Local_Scan + (m_parserUpdaterWorking ? Translation.In_Progress_with_Barracks : "")); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.actionLocalScan; pItem = new GUIListItem(Translation.Force_Online_Refresh + (m_parserUpdaterWorking ? Translation.In_Progress_with_Barracks : "")); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.actionFullRefresh; pItem = new GUIListItem(Translation.Play_Random_Episode); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.actionPlayRandom; if (!String.IsNullOrEmpty(DBOption.GetOptions(DBOption.cParentalControlPinCode))) { pItem = new GUIListItem(Translation.ParentalControlLocked); dlg.Add(pItem); pItem.ItemId = (int)eContextItems.actionLockViews; } dlg.DoModal(GUIWindowManager.ActiveWindow); if (dlg.SelectedId != -1) bExitMenu = true; } break; case (int)eContextMenus.options: { dlg.Reset(); ShowOptionsMenu(); return; } case (int)eContextMenus.switchView: { dlg.Reset(); if (showViewSwitchDialog()) return; } break; case (int)eContextMenus.switchLayout: { dlg.Reset(); ShowLayoutMenu(); return; } case (int)eContextMenus.addToView: dlg.Reset(); ShowViewTagsMenu(true, selectedSeries); return; case (int)eContextMenus.removeFromView: dlg.Reset(); ShowViewTagsMenu(false, selectedSeries); return; case (int)eContextMenus.rate: { switch (listLevel) { case Listlevel.Episode: showRatingsDialog(m_SelectedEpisode, false); break; case Listlevel.Series: case Listlevel.Season: showRatingsDialog(m_SelectedSeries, false); break; } LoadFacade(); if (dlg.SelectedId != -1) bExitMenu = true; return; } case (int)eContextMenus.filters: dlg.Reset(); ShowFiltersMenu(); return; default: bExitMenu = true; break; } #endregion } while (!bExitMenu); if (dlg.SelectedId == -1) return; #region Selected Menu Item Actions List<DBEpisode> episodeList = new List<DBEpisode>(); SQLCondition conditions = null; switch (dlg.SelectedId) { #region Watched/Unwatched case (int)eContextItems.toggleWatched: // toggle watched if (selectedEpisode != null) { bool watched = selectedEpisode[DBOnlineEpisode.cWatched]; selectedEpisode[DBOnlineEpisode.cWatched] = !watched; selectedEpisode.Commit(); FollwitConnector.Watch(selectedEpisode, !watched, false); // Update Episode Counts DBSeason.UpdateEpisodeCounts(m_SelectedSeries, m_SelectedSeason); // notify any listeners that user toggled watched if (ToggleWatched != null) { List<DBEpisode> eps = new List<DBEpisode>(); eps.Add(selectedEpisode); ToggleWatched(m_SelectedSeries, eps, !watched); } LoadFacade(); } break; case (int)eContextItems.actionMarkAllWatched: // Mark all watched that are visible on the facade and // do not air in the future...its misleading marking watched on episodes // you cant see. People could import a new episode and have it marked as watched accidently if (selectedSeries != null) { conditions = new SQLCondition(); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, selectedSeries[DBSeries.cID], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cFirstAired, DateTime.Now.ToString("yyyy-MM-dd"), SQLConditionType.LessEqualThan); } if (selectedSeason != null) { conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeasonIndex, selectedSeason[DBSeason.cIndex], SQLConditionType.Equal); } episodeList = DBEpisode.Get(conditions, true); // and set watched state foreach (DBEpisode episode in episodeList) { episode[DBOnlineEpisode.cWatched] = 1; episode.Commit(); } FollwitConnector.Watch(episodeList, true); if (ToggleWatched != null) ToggleWatched(selectedSeries, episodeList, true); // Updated Episode Counts if (this.listLevel == Listlevel.Series && selectedSeries != null) { DBSeries.UpdateEpisodeCounts(selectedSeries); } else if (this.listLevel == Listlevel.Season && selectedSeason != null) { DBSeason.UpdateEpisodeCounts(selectedSeries, selectedSeason); } cache.dump(); // refresh facade LoadFacade(); break; case (int)eContextItems.actionMarkAllUnwatched: // Mark all unwatched that are visible on the facade if (selectedSeries != null) { conditions = new SQLCondition(); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, selectedSeries[DBSeries.cID], SQLConditionType.Equal); } if (selectedSeason != null) { conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeasonIndex, selectedSeason[DBSeason.cIndex], SQLConditionType.Equal); } episodeList = DBEpisode.Get(conditions, true); foreach (DBEpisode episode in episodeList) { episode[DBOnlineEpisode.cWatched] = 0; episode.Commit(); } FollwitConnector.Watch(episodeList, false); if (ToggleWatched != null) ToggleWatched(selectedSeries, episodeList, false); // Updated Episode Counts if (this.listLevel == Listlevel.Series && selectedSeries != null) { DBSeries.UpdateEpisodeCounts(selectedSeries); } else if (this.listLevel == Listlevel.Season && selectedSeason != null) { DBSeason.UpdateEpisodeCounts(selectedSeries, selectedSeason); } cache.dump(); // refresh facade LoadFacade(); break; #endregion #region Playlist case (int)eContextItems.addToPlaylist: AddItemToPlayList(); break; #endregion #region Cycle Artwork case (int)eContextItems.cycleSeriesBanner: CycleSeriesBanner(selectedSeries, true); break; case (int)eContextItems.cycleSeriesPoster: CycleSeriesPoster(selectedSeries, true); break; case (int)eContextItems.cycleSeasonPoster: CycleSeasonPoster(selectedSeason, true); break; #endregion #region Fanart Chooser case (int)eContextItems.showFanartChooser: ShowFanartChooser(m_SelectedSeries[DBOnlineSeries.cID]); break; #endregion #region Actors GUI case (int)eContextItems.showActorsGUI: GUIActors.SeriesId = m_SelectedSeries[DBOnlineSeries.cID]; GUIWindowManager.ActivateWindow(9816); break; #endregion #region Force Online Series Query case (int)eContextItems.forceSeriesQuery: { // clear the series SQLCondition condition = new SQLCondition(); condition.Add(new DBEpisode(), DBEpisode.cSeriesID, selectedSeries[DBSeries.cID], SQLConditionType.Equal); DBEpisode.Clear(condition); condition = new SQLCondition(); condition.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, selectedSeries[DBSeries.cID], SQLConditionType.Equal); DBOnlineEpisode.Clear(condition); condition = new SQLCondition(); condition.Add(new DBSeason(), DBSeason.cSeriesID, selectedSeries[DBSeries.cID], SQLConditionType.Equal); DBSeason.Clear(condition); condition = new SQLCondition(); condition.Add(new DBSeries(), DBSeries.cID, selectedSeries[DBSeries.cID], SQLConditionType.Equal); DBSeries.Clear(condition); condition = new SQLCondition(); condition.Add(new DBOnlineSeries(), DBOnlineSeries.cID, selectedSeries[DBSeries.cID], SQLConditionType.Equal); DBOnlineSeries.Clear(condition); // look for it again m_parserUpdaterQueue.Add(new CParsingParameters(ParsingAction.NoExactMatch, null, true, false)); // Start Import if delayed m_scanTimer.Change(1000, 1000); } break; #endregion #region trakt.tv case (int)eContextItems.trakt: ShowTraktMenu(); break; #endregion #region My Torrents case (int)eContextItems.downloadTorrent: ShowMyTorrents(); break; #endregion #region mpNZB case (int)eContextItems.downloadNZB: ShowMPNZB(); break; #endregion #region Subtitles case (int)eContextItems.downloadSubtitle: { if (selectedEpisode != null) { DBEpisode episode = (DBEpisode)currentitem.TVTag; ShowSubtitleMenu(episode); } } break; #endregion #region Favourites /*case (int)eContextItems.actionToggleFavorite: { // Toggle Favourites m_SelectedSeries.toggleFavourite(); // If we are in favourite view we need to reload to remove the series LoadFacade(); break; }*/ #endregion #region Actions #region Hide case (int)eContextItems.actionHide: switch (this.listLevel) { case Listlevel.Series: selectedSeries.HideSeries(!selectedSeries[DBSeries.cHidden]); break; case Listlevel.Season: selectedSeason.HideSeason(!selectedSeason[DBSeason.cHidden]); DBSeries.UpdateEpisodeCounts(m_SelectedSeries); break; case Listlevel.Episode: selectedEpisode.HideEpisode(!selectedEpisode[DBOnlineEpisode.cHidden]); DBSeason.UpdateEpisodeCounts(m_SelectedSeries, m_SelectedSeason); break; } LoadFacade(); break; #endregion #region Delete case (int)eContextItems.actionDelete: { dlg.Reset(); ShowDeleteMenu(selectedSeries, selectedSeason, selectedEpisode); } break; #endregion #region Update Series/Episode Information case (int)eContextItems.actionUpdate: { dlg.Reset(); UpdateEpisodes(selectedSeries, m_SelectedSeason, m_SelectedEpisode); } break; #endregion #region MediaInfo case (int)eContextItems.actionRecheckMI: switch (listLevel) { case Listlevel.Episode: m_SelectedEpisode.ReadMediaInfo(); // reload here so logos update LoadFacade(); break; case Listlevel.Season: foreach (DBEpisode ep in DBEpisode.Get(m_SelectedSeason[DBSeason.cSeriesID], m_SelectedSeason[DBSeason.cIndex], false)) ep.ReadMediaInfo(); break; case Listlevel.Series: foreach (DBEpisode ep in DBEpisode.Get((int)m_SelectedSeries[DBSeries.cID], false)) ep.ReadMediaInfo(); break; } break; #endregion #region Import case (int)eContextItems.actionLocalScan: // queue scan lock (m_parserUpdaterQueue) { m_parserUpdaterQueue.Add(new CParsingParameters(true, false)); } // Start Import if delayed m_scanTimer.Change(1000, 1000); break; case (int)eContextItems.actionFullRefresh: // queue scan lock (m_parserUpdaterQueue) { m_parserUpdaterQueue.Add(new CParsingParameters(false, true)); } // Start Import if delayed m_scanTimer.Change(1000, 1000); break; #endregion #region Play case (int)eContextItems.actionPlayRandom: playRandomEp(); break; #endregion #region Episode Sort By case (int)eContextItems.actionEpisodeSortBy: ShowEpisodeSortByMenu(selectedSeries, false); break; #endregion #region Local to Online Episode Match Order case (int)eContextItems.actionChangeOnlineEpisodeMatchOrder: ShowEpisodeSortByMenu(selectedSeries, true); break; #endregion #region Lock Views case (int)eContextItems.actionLockViews: logicalView.IsLocked = true; break; #endregion #endregion } #endregion } catch (Exception ex) { MPTVSeriesLog.Write("The 'OnShowContextMenu' function has generated an error: " + ex.Message + ", StackTrace : " + ex.StackTrace); } }
protected void AddItemToPlayList() { if (_playlistPlayer == null) { _playlistPlayer = PlayListPlayer.SingletonPlayer; _playlistPlayer.PlaylistAutoPlay = DBOption.GetOptions(DBOption.cPlaylistAutoPlay); _playlistPlayer.RepeatPlaylist = DBOption.GetOptions(DBOption.cRepeatPlaylist); } SQLCondition condition = new SQLCondition(); List<DBEpisode> episodes; if (this.listLevel == Listlevel.Group) { return; } else if (this.listLevel == Listlevel.Series && m_SelectedSeries != null) { condition.Add(new DBEpisode(), DBEpisode.cSeriesID, m_SelectedSeries[DBSeries.cID], SQLConditionType.Equal); if (DBOption.GetOptions(DBOption.cPlaylistUnwatchedOnly)) condition.Add(new DBOnlineEpisode(), DBOnlineEpisode.cWatched, false, SQLConditionType.Equal); } else if (this.listLevel == Listlevel.Season && m_SelectedSeason != null) { condition.Add(new DBEpisode(), DBEpisode.cSeriesID, m_SelectedSeries[DBSeries.cID], SQLConditionType.Equal); condition.Add(new DBEpisode(), DBEpisode.cSeasonIndex, m_SelectedSeason[DBSeason.cIndex], SQLConditionType.Equal); if (DBOption.GetOptions(DBOption.cPlaylistUnwatchedOnly)) condition.Add(new DBOnlineEpisode(), DBOnlineEpisode.cWatched, false, SQLConditionType.Equal); } else if (this.listLevel == Listlevel.Episode && m_SelectedEpisode != null) { condition.Add(new DBEpisode(), DBEpisode.cSeriesID, m_SelectedSeries[DBSeries.cID], SQLConditionType.Equal); condition.Add(new DBEpisode(), DBEpisode.cSeasonIndex, m_SelectedSeason[DBSeason.cIndex], SQLConditionType.Equal); condition.Add(new DBEpisode(), DBEpisode.cEpisodeIndex, m_SelectedEpisode[DBEpisode.cEpisodeIndex], SQLConditionType.Equal); } episodes = DBEpisode.Get(condition, false); episodes.Sort(); foreach (DBEpisode episode in episodes) { PlayListItem playlistItem = new PlayListItem(episode); _playlistPlayer.GetPlaylist(PlayListType.PLAYLIST_TVSERIES).Add(playlistItem); } // Select next item in list int item = m_Facade.SelectedListItemIndex; if (item < m_Facade.Count) m_Facade.SelectedListItemIndex = item + 1; }
private bool AddItem(string episodeID) { SQLCondition condition = new SQLCondition(); condition.Add(new DBOnlineEpisode(), DBOnlineEpisode.cID, episodeID, SQLConditionType.Equal); List<DBEpisode> ep = DBEpisode.Get(condition, false); if (ep.Count > 0) { PlayListItem newItem = new PlayListItem(ep[0]); playlist.Add(newItem); } return true; }
private void ToggleWatchedNode(TreeNode nodeWatched, int watched) { if (nodeWatched != null) { Font fontDefault = treeView_Library.Font; SQLCondition conditions = new SQLCondition(); List<DBEpisode> episodeList = new List<DBEpisode>(); DBSeries series = null; DBSeason season = null; DBEpisode episode = null; switch (nodeWatched.Name) { case DBSeries.cTableName: series = (DBSeries)nodeWatched.Tag; conditions = new SQLCondition(); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, series[DBSeries.cID], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cFirstAired, DateTime.Now.ToString("yyyy-MM-dd"), SQLConditionType.LessEqualThan); episodeList = DBEpisode.Get(conditions, false); foreach (DBEpisode ep in episodeList) { ep[DBOnlineEpisode.cWatched] = watched; if (watched == 1 && ep[DBOnlineEpisode.cPlayCount] == 0) ep[DBOnlineEpisode.cPlayCount] = 1; if (watched == 1 && string.IsNullOrEmpty(ep[DBOnlineEpisode.cLastWatchedDate])) ep[DBOnlineEpisode.cLastWatchedDate] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); if (watched == 1 && string.IsNullOrEmpty(ep[DBOnlineEpisode.cFirstWatchedDate])) ep[DBOnlineEpisode.cFirstWatchedDate] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); ep.Commit(); } // Updated Episode Counts DBSeries.UpdateEpisodeCounts(series); if (nodeWatched.Nodes.Count > 0) { for (int i = 0; i < nodeWatched.Nodes.Count; i++) { // set color of nodeWatched if (watched == 1 && series[DBOnlineSeries.cHasLocalFiles]) nodeWatched.ForeColor = System.Drawing.Color.DarkBlue; else if (watched == 0 && series[DBOnlineSeries.cHasLocalFiles]) nodeWatched.ForeColor = treeView_Library.ForeColor; // Child Season fonts: DBSeason s = (DBSeason)nodeWatched.Nodes[i].Tag; if (watched == 1 && s[DBSeason.cHasLocalFiles]) nodeWatched.Nodes[i].ForeColor = System.Drawing.Color.DarkBlue; else if (watched == 0 && s[DBSeason.cHasLocalFiles]) nodeWatched.Nodes[i].ForeColor = treeView_Library.ForeColor; // Child Episode fonts: if (nodeWatched.Nodes[i].Nodes.Count > 0) { // only mark the ones we have actually set as watched int epCount = 0; if (watched == 1) epCount = episodeList.Where(e => e[DBOnlineEpisode.cSeasonIndex] == s[DBSeason.cIndex]).Count(); else epCount = nodeWatched.Nodes[i].Nodes.Count; for (int j = 0; j < epCount; j++) { DBEpisode ep = (DBEpisode)nodeWatched.Nodes[i].Nodes[j].Tag; if (watched == 1 && !string.IsNullOrEmpty(ep[DBEpisode.cFilename])) nodeWatched.Nodes[i].Nodes[j].ForeColor = System.Drawing.Color.DarkBlue; else if (watched == 0 && !string.IsNullOrEmpty(ep[DBEpisode.cFilename])) nodeWatched.Nodes[i].Nodes[j].ForeColor = treeView_Library.ForeColor; } } } } cache.dump(); break; case DBSeason.cTableName: season = (DBSeason)nodeWatched.Tag; series = DBSeries.Get(season[DBSeason.cSeriesID]); conditions = new SQLCondition(); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, series[DBSeries.cID], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeasonIndex, season[DBSeason.cIndex], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cFirstAired, DateTime.Now.ToString("yyyy-MM-dd"), SQLConditionType.LessEqualThan); episodeList = DBEpisode.Get(conditions, false); foreach (DBEpisode ep in episodeList) { ep[DBOnlineEpisode.cWatched] = watched; if (watched == 1 && ep[DBOnlineEpisode.cPlayCount] == 0) ep[DBOnlineEpisode.cPlayCount] = 1; if (watched == 1 && string.IsNullOrEmpty(ep[DBOnlineEpisode.cLastWatchedDate])) ep[DBOnlineEpisode.cLastWatchedDate] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); if (watched == 1 && string.IsNullOrEmpty(ep[DBOnlineEpisode.cFirstWatchedDate])) ep[DBOnlineEpisode.cFirstWatchedDate] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); ep.Commit(); } // update episode counts DBSeason.UpdateEpisodeCounts(series, season); // set color of nodeWatched if (watched == 1 && season[DBSeason.cHasLocalFiles]) nodeWatched.ForeColor = System.Drawing.Color.DarkBlue; else if (watched == 0 && season[DBSeason.cHasLocalFiles]) nodeWatched.ForeColor = treeView_Library.ForeColor; // Parent Series color: if (series[DBOnlineSeries.cUnwatchedItems] == 0 && series[DBOnlineSeries.cHasLocalFiles]) nodeWatched.Parent.ForeColor = System.Drawing.Color.DarkBlue; else if (series[DBOnlineSeries.cUnwatchedItems] == 1 && series[DBOnlineSeries.cHasLocalFiles]) nodeWatched.Parent.ForeColor = treeView_Library.ForeColor; // Child Episodes color: if (episodeList.Count > 0) { // only mark the ones we have actually set as watched int epCount = 0; if (watched == 1) epCount = episodeList.Count(); else epCount = nodeWatched.Nodes.Count; for (int i = 0; i < epCount; i++) { DBEpisode ep = (DBEpisode)nodeWatched.Nodes[i].Tag; if (watched == 1 && !string.IsNullOrEmpty(ep[DBEpisode.cFilename])) nodeWatched.Nodes[i].ForeColor = System.Drawing.Color.DarkBlue; else if (watched == 0 && !string.IsNullOrEmpty(ep[DBEpisode.cFilename])) nodeWatched.Nodes[i].ForeColor = treeView_Library.ForeColor; } } cache.dump(); break; case DBEpisode.cTableName: episode = (DBEpisode)nodeWatched.Tag; episode[DBOnlineEpisode.cWatched] = watched; if (watched == 1 && episode[DBOnlineEpisode.cPlayCount] == 0) episode[DBOnlineEpisode.cPlayCount] = 1; if (watched == 1 && string.IsNullOrEmpty(episode[DBOnlineEpisode.cLastWatchedDate])) episode[DBOnlineEpisode.cLastWatchedDate] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); if (watched == 1 && string.IsNullOrEmpty(episode[DBOnlineEpisode.cFirstWatchedDate])) episode[DBOnlineEpisode.cFirstWatchedDate] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); episode.Commit(); series = DBSeries.Get(episode[DBEpisode.cSeriesID]); season = Helper.getCorrespondingSeason(episode[DBEpisode.cSeriesID], episode[DBEpisode.cSeasonIndex]); DBSeason.UpdateEpisodeCounts(series, season); // set color of nodeWatched if (watched == 1 && !string.IsNullOrEmpty(episode[DBEpisode.cFilename])) nodeWatched.ForeColor = System.Drawing.Color.DarkBlue; else if (watched == 0 && !string.IsNullOrEmpty(episode[DBEpisode.cFilename])) nodeWatched.ForeColor = treeView_Library.ForeColor; // Parent Series color if (series[DBOnlineSeries.cUnwatchedItems] == 0 && series[DBOnlineSeries.cHasLocalFiles]) nodeWatched.Parent.ForeColor = System.Drawing.Color.DarkBlue; else if (series[DBOnlineSeries.cUnwatchedItems] == 1 && series[DBOnlineSeries.cHasLocalFiles]) nodeWatched.Parent.ForeColor = treeView_Library.ForeColor; // Parent Season color if (season[DBSeason.cUnwatchedItems] == 0 && season[DBSeason.cHasLocalFiles]) nodeWatched.Parent.Parent.ForeColor = System.Drawing.Color.DarkBlue; else if (season[DBSeason.cUnwatchedItems] == 1 && season[DBSeason.cHasLocalFiles]) nodeWatched.Parent.Parent.ForeColor = treeView_Library.ForeColor; cache.dump(); break; } // Refresh treeView this.treeView_Library.ResumeLayout(); } }
public bool ResumeOrPlay(DBEpisode episode) { try { MPTVSeriesLog.Write("Attempting to play: ", episode[DBEpisode.cFilename].ToString(), MPTVSeriesLog.LogLevel.Debug); // don't have this file ! if (episode[DBEpisode.cFilename].ToString().Length == 0) { return(false); } // check that we are not playing an episode out of episode if unwatched // ignore specials as they can be pretty out of wack! #region PlayBack Order // check sort order so our check is accurate var series = Helper.getCorrespondingSeries(episode[DBOnlineEpisode.cSeriesID]); bool dvdSortOrder = series[DBOnlineSeries.cEpisodeSortOrder] == "DVD"; string seasonField = dvdSortOrder ? DBOnlineEpisode.cCombinedSeason : DBOnlineEpisode.cSeasonIndex; string episodeField = dvdSortOrder ? DBOnlineEpisode.cCombinedEpisodeNumber : DBOnlineEpisode.cEpisodeIndex; if (DBOption.GetOptions(DBOption.cCheckPlayOutOfOrder) && !episode[DBOnlineEpisode.cWatched] && episode[seasonField] > 0 && episode[episodeField] > 1) { // first get the next unwatched episode from previously played // we are only interested in current season (could be multi-user watching multiple seasons) // API for GetNextUnwatched is not desirable as that works from Date Watched, we only care about watched here var conditions = new SQLCondition(); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, episode[DBOnlineSeries.cSeriesID], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), seasonField, episode[seasonField], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), episodeField, episode[episodeField], SQLConditionType.LessThan); conditions.Add(new DBOnlineEpisode(), episodeField, 0, SQLConditionType.GreaterThan); var episodes = DBEpisode.Get(conditions, false); if (episodes != null && episodes.Count > 0) { // set logical playback order based on sort order episodes.Sort(); // if the previous found episode is not watched then we are playing out of order // if we have a gap in episode collection then assume it has not been watched (this check is needed when user does not download all episode info) if (!episodes.Last()[DBOnlineEpisode.cWatched] || (episode[episodeField] - episodes.Last()[episodeField]) > 1) { GUIDialogYesNo dlgYesNo = (GUIDialogYesNo)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_YES_NO); dlgYesNo.SetHeading(Translation.Warning); dlgYesNo.SetLine(1, Translation.PlaybackOutOfOrderLine1); dlgYesNo.SetLine(2, string.Format("{0} - {1}x{2}", series.ToString(), episode[seasonField], episode[episodeField] - 1)); dlgYesNo.SetLine(3, Translation.PlaybackOutOfOrderLine2); dlgYesNo.DoModal(GUIWindowManager.ActiveWindow); if (!dlgYesNo.IsConfirmed) { return(false); } } } } #endregion m_previousEpisode = m_currentEpisode; m_currentEpisode = episode; int timeMovieStopped = m_currentEpisode[DBEpisode.cStopTime]; // Check if file is an Image e.g. ISO string filename = m_currentEpisode[DBEpisode.cFilename]; m_bIsImageFile = Helper.IsImageFile(filename); #region Invoke Before Playback // see if we have an invokeOption set up string invoke = (string)DBOption.GetOptions(DBOption.cInvokeExtBeforePlayback); if (!string.IsNullOrEmpty(invoke)) { string invokeArgs = (string)DBOption.GetOptions(DBOption.cInvokeExtBeforePlaybackArgs); try { // replace any placeholders in the arguments for the script if any have been supplied. if (!string.IsNullOrEmpty(invokeArgs)) { invokeArgs = FieldGetter.resolveDynString(invokeArgs, m_currentEpisode, true); } invoke = FieldGetter.resolveDynString(invoke, m_currentEpisode, true); // use ProcessStartInfo instead of Process.Start(string) as latter produces a "cannot find file" // error if you pass in command line arguments. // also allows us to run the script hidden, preventing, for example, a command prompt popping up. ProcessStartInfo psi = new ProcessStartInfo(invoke, invokeArgs); psi.WindowStyle = ProcessWindowStyle.Hidden; Process proc = System.Diagnostics.Process.Start(psi); MPTVSeriesLog.Write(string.Format("Sucessfully Invoked BeforeFilePlay Command: '{0}' '{1}'", invoke, invokeArgs)); // if not present in database this evaluates to false. If present and not a valid bool then // it evaluates to true bool waitForExit = (bool)DBOption.GetOptions(DBOption.cInvokeExtBeforePlaybackWaitForExit); // if true this thread will wait for the external user script to complete before continuing. if (waitForExit) { proc.WaitForExit(); } } catch (Exception e) { MPTVSeriesLog.Write(string.Format("Unable to Invoke BeforeFilePlay Command: '{0}' '{1}'", invoke, invokeArgs)); MPTVSeriesLog.Write(e.Message); } } #endregion #region Removable Media Handling if (!File.Exists(m_currentEpisode[DBEpisode.cFilename])) { string episodeVolumeLabel = m_currentEpisode[DBEpisode.cVolumeLabel].ToString(); if (string.IsNullOrEmpty(episodeVolumeLabel)) { episodeVolumeLabel = LocalParse.getImportPath(m_currentEpisode[DBEpisode.cFilename]); } // ask the user to input cd/dvd, usb disk or confirm network drive is connected GUIDialogOK dlgOK = (GUIDialogOK)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_OK); if (null == dlgOK) { return(false); } dlgOK.SetHeading(Translation.insertDisk); dlgOK.SetLine(1, Translation.InsertDiskMessage1); dlgOK.SetLine(2, Translation.InsertDiskMessage2); dlgOK.SetLine(3, Translation.InsertDiskMessage3); dlgOK.SetLine(4, string.Format(Translation.InsertDiskMessage4, episodeVolumeLabel)); dlgOK.DoModal(GUIWindowManager.ActiveWindow); if (!File.Exists(m_currentEpisode[DBEpisode.cFilename])) { return(false); // still not found, return to list } } #endregion #region Ask user to Resume // skip this if we are using an External Player bool bExternalPlayer = m_bIsImageFile ? m_bIsExternalDVDPlayer : m_bIsExternalPlayer; if (timeMovieStopped > 0 && !bExternalPlayer) { MPTVSeriesLog.Write("Asking user to resume episode from: " + Utils.SecondsToHMSString(timeMovieStopped)); GUIDialogYesNo dlgYesNo = (GUIDialogYesNo)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_YES_NO); if (null != dlgYesNo) { dlgYesNo.SetHeading(Translation.ResumeEpisode); dlgYesNo.SetLine(1, m_currentEpisode.onlineEpisode.CompleteTitle); dlgYesNo.SetLine(2, GUILocalizeStrings.Get(936) + " " + Utils.SecondsToHMSString(timeMovieStopped)); dlgYesNo.SetDefaultToYes(true); dlgYesNo.DoModal(GUIWindowManager.ActiveWindow); // reset resume data in DB if (!dlgYesNo.IsConfirmed) { timeMovieStopped = 0; m_currentEpisode[DBEpisode.cStopTime] = timeMovieStopped; m_currentEpisode.Commit(); MPTVSeriesLog.Write("User selected to start episode from beginning", MPTVSeriesLog.LogLevel.Debug); } else { MPTVSeriesLog.Write("User selected to resume episode", MPTVSeriesLog.LogLevel.Debug); // dont scrobble first of double episode if resuming past halfway double duration = m_currentEpisode[DBEpisode.cLocalPlaytime]; } } } #endregion Play(timeMovieStopped); return(true); } catch (Exception e) { MPTVSeriesLog.Write("TVSeriesPlugin.VideoHandler.ResumeOrPlay()\r\n" + e.ToString()); return(false); } }
private void linkMediaInfoUpdate_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { DialogResult result = MessageBox.Show("Force update of Media Info for all files?\n\nSelect No to update new files only.", "Update Media Info", MessageBoxButtons.YesNoCancel); if (result == DialogResult.Cancel) { return; } SQLCondition cond = new SQLCondition(); cond.Add(new DBEpisode(), DBEpisode.cFilename, "", SQLConditionType.NotEqual); List<DBEpisode> episodes = new List<DBEpisode>(); // get all the episodes episodes = DBEpisode.Get(cond, false); if (result == DialogResult.No) { List<DBEpisode> todoeps = new List<DBEpisode>(); // only get the episodes that dont have their resolutions read out already for (int i = 0; i < episodes.Count; i++) if (!episodes[i].HasMediaInfo) todoeps.Add(episodes[i]); episodes = todoeps; } UpdateMediaInfoASync(episodes); }
public bool ReadPrimary(DBValue Value) { try { m_fields[PrimaryKey()].Value = Value; SQLCondition condition = new SQLCondition(); condition.Add(this, PrimaryKey(), m_fields[PrimaryKey()].Value, SQLConditionType.Equal); String sqlQuery = "select * from " + m_tableName + condition; SQLiteResultSet records = DBTVSeries.Execute(sqlQuery); return Read(ref records, 0); } catch (Exception ex) { MPTVSeriesLog.Write("An Error Occurred (" + ex.Message + ")."); } return false; }
private void linkImpWatched_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { OpenFileDialog fd = new OpenFileDialog(); fd.Filter = "Exported Watched Flags (*.watched)|*.watched"; if (fd.ShowDialog() == DialogResult.OK && System.IO.File.Exists(fd.FileName)) { StreamReader r = new StreamReader(fd.FileName); SQLCondition cond = new SQLCondition(); string line = string.Empty; // set unwatched for all DBOnlineEpisode.GlobalSet(new DBOnlineEpisode(), DBOnlineEpisode.cWatched, false, new SQLCondition()); // now set watched for all in file while ((line = r.ReadLine()) != null) { cond = new SQLCondition(); cond.Add(new DBOnlineEpisode(), DBOnlineEpisode.cCompositeID, line, SQLConditionType.Equal); DBOnlineEpisode.GlobalSet(new DBOnlineEpisode(), DBOnlineEpisode.cWatched, true, cond); } r.Close(); MPTVSeriesLog.Write("Watched info succesfully imported!"); LoadTree(); // reload tree so the changes are visible } }
public bool Scrobble(string filename) { if (!EpisodeWatching) return false; FirstEpisodeWatched = false; var scrobbleThread = new Thread((episodeObj) => { var scrobbleEpisode = episodeObj as DBEpisode; if (scrobbleEpisode == null) return; var show = Helper.getCorrespondingSeries(scrobbleEpisode[DBEpisode.cSeriesID]); if (show == null || show[DBOnlineSeries.cTraktIgnore]) return; // get the current player progress double progress = GetPlayerProgress(scrobbleEpisode); // check if it's a double episode and handle accordingly based on start time TraktScrobbleEpisode scrobbleData = null; if (scrobbleEpisode.IsDoubleEpisode) { // get both episodes from filename query var condition = new SQLCondition(); condition.Add(new DBEpisode(), DBEpisode.cFilename, scrobbleEpisode[DBEpisode.cFilename], SQLConditionType.Equal); var episodes = DBEpisode.Get(condition, false); if (episodes == null || episodes.Count != 2) { TraktLogger.Error("Unable to retrieve double episode information from tvseries database for current playing episode. Title = '{0}'", scrobbleEpisode.ToString()); return; } // store the second episode so we can use seperately SecondEpisode = episodes[1]; // if we're already past the half way mark scrobble the second part only if (progress > 50) { // don't scrobble the first part when we stop FirstEpisodeWatched = true; TraktLogger.Info("Sending start scrobble of second part of episode to trakt.tv. Show Title = '{0}', Season = '{1}', Episode = '{2}', Episode Title = '{3}', Show TVDb ID = '{4}', Episode TVDb ID = '{5}'", show[DBOnlineSeries.cOriginalName], episodes[1][DBOnlineEpisode.cSeasonIndex], episodes[1][DBOnlineEpisode.cEpisodeIndex], episodes[1][DBOnlineEpisode.cEpisodeName], episodes[1][DBOnlineEpisode.cSeriesID], episodes[1][DBOnlineEpisode.cID]); scrobbleData = CreateScrobbleData(episodes[1], progress); if (scrobbleData == null) return; var response = TraktAPI.TraktAPI.StartEpisodeScrobble(scrobbleData); TraktLogger.LogTraktResponse(response); return; } } TraktLogger.Info("Sending start scrobble of episode to trakt.tv. Show Title = '{0}', Season = '{1}', Episode = '{2}', Episode Title = '{3}', Show TVDb ID = '{4}', Episode TVDb ID = '{5}'", show[DBOnlineSeries.cOriginalName], scrobbleEpisode[DBOnlineEpisode.cSeasonIndex], scrobbleEpisode[DBOnlineEpisode.cEpisodeIndex], scrobbleEpisode[DBOnlineEpisode.cEpisodeName], scrobbleEpisode[DBOnlineEpisode.cSeriesID], scrobbleEpisode[DBOnlineEpisode.cID]); scrobbleData = CreateScrobbleData(scrobbleEpisode, progress); if (scrobbleData == null) return; TraktLogger.LogTraktResponse(TraktAPI.TraktAPI.StartEpisodeScrobble(scrobbleData)); }) { Name = "Scrobble", IsBackground = true }; scrobbleThread.Start(CurrentEpisode); return true; }
void MarkEpisodeAsWatched(DBEpisode episode) { // Could be a double episode, so mark both as watched SQLCondition condition = new SQLCondition(); condition.Add(new DBEpisode(), DBEpisode.cFilename, episode[DBEpisode.cFilename], SQLConditionType.Equal); List<DBEpisode> episodes = DBEpisode.Get(condition, false); foreach (DBEpisode ep in episodes) { string date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); ep[DBOnlineEpisode.cWatched] = 1; ep[DBOnlineEpisode.cPlayCount] = ep[DBOnlineEpisode.cPlayCount] + 1; ep[DBEpisode.cDateWatched] = date; ep[DBOnlineEpisode.cLastWatchedDate] = date; if (string.IsNullOrEmpty(ep[DBOnlineEpisode.cFirstWatchedDate])) { ep[DBOnlineEpisode.cFirstWatchedDate] = date; } ep.Commit(); } // Update Episode Counts DBSeries series = Helper.getCorrespondingSeries(m_currentEpisode[DBEpisode.cSeriesID]); DBSeason season = Helper.getCorrespondingSeason(episode[DBEpisode.cSeriesID], episode[DBEpisode.cSeasonIndex]); DBSeason.UpdateEpisodeCounts(series, season); }
private void OnEpisodeWatched(DBEpisode episode) { if (TraktSettings.AccountStatus != ConnectionState.Connected) return; DBEpisode currentEpisode = null; EpisodeWatching = false; Thread scrobbleEpisode = new Thread(delegate(object o) { DBEpisode ep = o as DBEpisode; if (o == null) return; // submit watched state to trakt API // could be a double episode so mark last one as watched // 1st episode is set to watched during playback timer if (ep[DBEpisode.cEpisodeIndex2] > 0 && MarkedFirstAsWatched) { // only set 2nd episode as watched here SQLCondition condition = new SQLCondition(); condition.Add(new DBEpisode(), DBEpisode.cFilename, ep[DBEpisode.cFilename], SQLConditionType.Equal); List<DBEpisode> episodes = DBEpisode.Get(condition, false); currentEpisode = episodes[1]; } else { // single episode currentEpisode = ep; } // show trakt rating dialog ShowRateDialog(currentEpisode); TraktLogger.Info("TVSeries episode considered watched '{0}'", currentEpisode.ToString()); // get scrobble data to send to api TraktEpisodeScrobble scrobbleData = CreateScrobbleData(currentEpisode); if (scrobbleData == null) return; // set duration/progress in scrobble data double duration = currentEpisode[DBEpisode.cLocalPlaytime] / 60000; scrobbleData.Duration = Convert.ToInt32(duration).ToString(); scrobbleData.Progress = "100"; TraktResponse response = TraktAPI.TraktAPI.ScrobbleEpisodeState(scrobbleData, TraktScrobbleStates.scrobble); TraktAPI.TraktAPI.LogTraktResponse(response); }) { IsBackground = true, Name = "Scrobble Episode" }; scrobbleEpisode.Start(episode); }
public bool ResumeOrPlay(DBEpisode episode) { try { MPTVSeriesLog.Write("Attempting to play: ", episode[DBEpisode.cFilename].ToString(), MPTVSeriesLog.LogLevel.Debug); // don't have this file ! if (episode[DBEpisode.cFilename].ToString().Length == 0) return false; // check that we are not playing an episode out of episode if unwatched // ignore specials as they can be pretty out of wack! #region PlayBack Order // check sort order so our check is accurate var series = Helper.getCorrespondingSeries(episode[DBOnlineEpisode.cSeriesID]); bool dvdSortOrder = series[DBOnlineSeries.cEpisodeSortOrder] == "DVD"; string seasonField = dvdSortOrder ? DBOnlineEpisode.cCombinedSeason : DBOnlineEpisode.cSeasonIndex; string episodeField = dvdSortOrder ? DBOnlineEpisode.cCombinedEpisodeNumber : DBOnlineEpisode.cEpisodeIndex; if (DBOption.GetOptions(DBOption.cCheckPlayOutOfOrder) && !episode[DBOnlineEpisode.cWatched] && episode[seasonField] > 0 && episode[episodeField] > 1) { // first get the next unwatched episode from previously played // we are only interested in current season (could be multi-user watching multiple seasons) // API for GetNextUnwatched is not desirable as that works from Date Watched, we only care about watched here var conditions = new SQLCondition(); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, episode[DBOnlineSeries.cSeriesID], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), seasonField, episode[seasonField], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), episodeField, episode[episodeField], SQLConditionType.LessThan); conditions.Add(new DBOnlineEpisode(), episodeField, 0, SQLConditionType.GreaterThan); var episodes = DBEpisode.Get(conditions, false); if (episodes != null && episodes.Count > 0) { // set logical playback order based on sort order episodes.Sort(); // if the previous found episode is not watched then we are playing out of order // if we have a gap in episode collection then assume it has not been watched (this check is needed when user does not download all episode info) if (!episodes.Last()[DBOnlineEpisode.cWatched] || (episode[episodeField] - episodes.Last()[episodeField]) > 1) { GUIDialogYesNo dlgYesNo = (GUIDialogYesNo)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_YES_NO); dlgYesNo.SetHeading(Translation.Warning); dlgYesNo.SetLine(1, Translation.PlaybackOutOfOrderLine1); dlgYesNo.SetLine(2, string.Format("{0} - {1}x{2}", series.ToString(), episode[seasonField], episode[episodeField] - 1)); dlgYesNo.SetLine(3, Translation.PlaybackOutOfOrderLine2); dlgYesNo.DoModal(GUIWindowManager.ActiveWindow); if (!dlgYesNo.IsConfirmed) return false; } } } #endregion m_previousEpisode = m_currentEpisode; m_currentEpisode = episode; int timeMovieStopped = m_currentEpisode[DBEpisode.cStopTime]; // Check if file is an Image e.g. ISO string filename = m_currentEpisode[DBEpisode.cFilename]; m_bIsImageFile = Helper.IsImageFile(filename); #region Invoke Before Playback // see if we have an invokeOption set up string invoke = (string)DBOption.GetOptions(DBOption.cInvokeExtBeforePlayback); if (!string.IsNullOrEmpty(invoke)) { string invokeArgs = (string)DBOption.GetOptions(DBOption.cInvokeExtBeforePlaybackArgs); try { // replace any placeholders in the arguments for the script if any have been supplied. if (!string.IsNullOrEmpty(invokeArgs)) { invokeArgs = FieldGetter.resolveDynString(invokeArgs, m_currentEpisode, true); } invoke = FieldGetter.resolveDynString(invoke, m_currentEpisode, true); // use ProcessStartInfo instead of Process.Start(string) as latter produces a "cannot find file" // error if you pass in command line arguments. // also allows us to run the script hidden, preventing, for example, a command prompt popping up. ProcessStartInfo psi = new ProcessStartInfo(invoke, invokeArgs); psi.WindowStyle = ProcessWindowStyle.Hidden; Process proc = System.Diagnostics.Process.Start(psi); MPTVSeriesLog.Write(string.Format("Sucessfully Invoked BeforeFilePlay Command: '{0}' '{1}'", invoke, invokeArgs)); // if not present in database this evaluates to false. If present and not a valid bool then // it evaluates to true bool waitForExit = (bool)DBOption.GetOptions(DBOption.cInvokeExtBeforePlaybackWaitForExit); // if true this thread will wait for the external user script to complete before continuing. if (waitForExit) { proc.WaitForExit(); } } catch (Exception e) { MPTVSeriesLog.Write(string.Format("Unable to Invoke BeforeFilePlay Command: '{0}' '{1}'", invoke, invokeArgs)); MPTVSeriesLog.Write(e.Message); } } #endregion #region Removable Media Handling if (!File.Exists(m_currentEpisode[DBEpisode.cFilename])) { string episodeVolumeLabel = m_currentEpisode[DBEpisode.cVolumeLabel].ToString(); if (string.IsNullOrEmpty(episodeVolumeLabel)) episodeVolumeLabel = LocalParse.getImportPath(m_currentEpisode[DBEpisode.cFilename]); // ask the user to input cd/dvd, usb disk or confirm network drive is connected GUIDialogOK dlgOK = (GUIDialogOK)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_OK); if (null == dlgOK) return false; dlgOK.SetHeading(Translation.insertDisk); dlgOK.SetLine(1, Translation.InsertDiskMessage1); dlgOK.SetLine(2, Translation.InsertDiskMessage2); dlgOK.SetLine(3, Translation.InsertDiskMessage3); dlgOK.SetLine(4, string.Format(Translation.InsertDiskMessage4, episodeVolumeLabel)); dlgOK.DoModal(GUIWindowManager.ActiveWindow); if (!File.Exists(m_currentEpisode[DBEpisode.cFilename])) { return false; // still not found, return to list } } #endregion #region Ask user to Resume // skip this if we are using an External Player bool bExternalPlayer = m_bIsImageFile ? m_bIsExternalDVDPlayer : m_bIsExternalPlayer; if (timeMovieStopped > 0 && !bExternalPlayer) { MPTVSeriesLog.Write("Asking user to resume episode from: " + Utils.SecondsToHMSString(timeMovieStopped)); GUIDialogYesNo dlgYesNo = (GUIDialogYesNo)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_YES_NO); if (null != dlgYesNo) { dlgYesNo.SetHeading(Translation.ResumeEpisode); dlgYesNo.SetLine(1, m_currentEpisode.onlineEpisode.CompleteTitle); dlgYesNo.SetLine(2, GUILocalizeStrings.Get(936) + " " + Utils.SecondsToHMSString(timeMovieStopped)); dlgYesNo.SetDefaultToYes(true); dlgYesNo.DoModal(GUIWindowManager.ActiveWindow); // reset resume data in DB if (!dlgYesNo.IsConfirmed) { timeMovieStopped = 0; m_currentEpisode[DBEpisode.cStopTime] = timeMovieStopped; m_currentEpisode.Commit(); MPTVSeriesLog.Write("User selected to start episode from beginning", MPTVSeriesLog.LogLevel.Debug); } else { MPTVSeriesLog.Write("User selected to resume episode", MPTVSeriesLog.LogLevel.Debug); // dont scrobble first of double episode if resuming past halfway double duration = m_currentEpisode[DBEpisode.cLocalPlaytime]; } } } #endregion Play(timeMovieStopped); return true; } catch (Exception e) { MPTVSeriesLog.Write("TVSeriesPlugin.VideoHandler.ResumeOrPlay()\r\n" + e.ToString()); return false; } }
public void addHierarchyConditions(ref int stepIndex, ref string[] currentStepSelection, ref SQLCondition conditions) { logicalViewStep step = m_steps[stepIndex]; conditions = step.conds.Copy(); // important, don't change the steps themselves // we need to add one additional condition to reflect the selection one hierarchy up if (currentStepSelection != null && currentStepSelection.Length > 0 && stepIndex > 0) { switch (m_steps[stepIndex - 1].Type) { case logicalViewStep.type.group: bool requiresSplit = false; // use sql 'like' for split fields // selected group label string selectedItem = currentStepSelection[0]; // we expect to get the selected group's label // unknown really is "" so get all with null values here if (selectedItem == Translation.Unknown) { selectedItem = string.Empty; } else if (m_steps[stepIndex - 1].groupedBy.attempSplit) { requiresSplit = true; } string fieldName = m_steps[stepIndex - 1].groupedBy.rawFieldname; string tableName = m_steps[stepIndex - 1].groupedBy.table.m_tableName; string tableField = tableName + "." + fieldName; string userEditField = tableField + DBTable.cUserEditPostFix; string value = requiresSplit ? "like " + "'%" + selectedItem + "%'" : "= " + "'" + selectedItem + "'"; string sql = string.Empty; // check if the useredit column exists if (DBTable.ColumnExists(tableName, fieldName + DBTable.cUserEditPostFix)) { sql = "(case when (" + userEditField + " is null or " + userEditField + " = " + "'" + "'" + ") " + "then " + tableField + " else " + userEditField + " " + "end) " + value; } else { sql = tableField + " " + value; } conditions.AddCustom(sql); break; case logicalViewStep.type.series: // we expect to get the seriesID as stepSel conditions.Add(new DBSeason(), DBSeason.cSeriesID, currentStepSelection[0], SQLConditionType.Equal); if (DBOption.GetOptions(DBOption.cSortSpecialSeasonLast)) { conditions.InsertOrderItem(DBSeason.cTableName + "." + DBSeason.cIndex + " = 0", SQLCondition.orderType.Ascending); } break; case logicalViewStep.type.season: // we expect to get the seriesID/seasonIndex as stepSel // we want to query episodes using the CombinedSeason if Sort Order is "DVD" // CombinedSeason gives us the DVD Season and if empty will give us the Aired Season DBSeries series = Helper.getCorrespondingSeries(int.Parse(currentStepSelection[0])); bool SortByDVD = series[DBOnlineSeries.cEpisodeSortOrder] == "DVD"; string seasonIndex = SortByDVD ? DBOnlineEpisode.cCombinedSeason : DBOnlineEpisode.cSeasonIndex; conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, currentStepSelection[0], SQLConditionType.Equal); conditions.beginGroup(); conditions.Add(new DBOnlineEpisode(), seasonIndex, currentStepSelection[1], SQLConditionType.Equal); if (DBOption.GetOptions(DBOption.cSortSpecials) && !SortByDVD) { conditions.nextIsOr = true; conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cAirsBeforeSeason, currentStepSelection[1], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cAirsAfterSeason, currentStepSelection[1], SQLConditionType.Equal); conditions.nextIsOr = false; } conditions.endGroup(); break; } } }
public void SyncLibrary() { TraktLogger.Info("TVSeries Starting Sync"); SyncInProgress = true; #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."); SyncInProgress = false; 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."); SyncInProgress = false; 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."); SyncInProgress = false; return; } TraktLogger.Info("{0} tvshows with unseen episodes in trakt library", traktUnSeenEpisodes.Count().ToString()); #endregion #region Get local data List<DBEpisode> localAllEpisodes = new List<DBEpisode>(); List<DBEpisode> localCollectionEpisodes = new List<DBEpisode>(); List<DBEpisode> localWatchedEpisodes = new List<DBEpisode>(); // store list of series ids so we can update the episode counts // of any series that syncback watched flags List<int> seriesToUpdateEpisodeCounts = new List<int>(); // Get all episodes in database SQLCondition conditions = new SQLCondition(); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, 0, SQLConditionType.GreaterThan); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cHidden, 0, SQLConditionType.Equal); localAllEpisodes = DBEpisode.Get(conditions, false); TraktLogger.Info("{0} total episodes in tvseries database", localAllEpisodes.Count.ToString()); // Get episodes of files that we have locally localCollectionEpisodes = localAllEpisodes.Where(e => !string.IsNullOrEmpty(e[DBEpisode.cFilename].ToString())).ToList(); TraktLogger.Info("{0} episodes with local files in tvseries database", localCollectionEpisodes.Count.ToString()); // Get watched episodes of files that we have locally or are remote // user could of deleted episode from disk but still have reference to it in database localWatchedEpisodes = localAllEpisodes.Where(e => e[DBOnlineEpisode.cWatched] > 0).ToList(); TraktLogger.Info("{0} episodes watched in tvseries database", localWatchedEpisodes.Count.ToString()); #endregion #region Sync collection/library to trakt // get list of episodes that we have not already trakt'd List<DBEpisode> localEpisodesToSync = new List<DBEpisode>(localCollectionEpisodes); foreach (DBEpisode 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<DBEpisode> localWatchedEpisodesToSync = new List<DBEpisode>(localWatchedEpisodes); foreach (DBEpisode 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 (DBEpisode ep in localAllEpisodes.Where(e => e[DBOnlineEpisode.cWatched] == 0)) { if (TraktEpisodeExists(traktWatchedEpisodes, ep) && !TraktEpisodeExists(traktUnSeenEpisodes, ep)) { DBSeries series = Helper.getCorrespondingSeries(ep[DBOnlineEpisode.cSeriesID]); if (series == null || series[DBOnlineSeries.cTraktIgnore]) continue; // mark episode as watched TraktLogger.Info("Marking episode '{0}' as watched", ep.ToString()); ep[DBOnlineEpisode.cWatched] = true; ep.Commit(); if (!seriesToUpdateEpisodeCounts.Contains(ep[DBOnlineEpisode.cSeriesID])) seriesToUpdateEpisodeCounts.Add(ep[DBOnlineEpisode.cSeriesID]); } } #endregion #region Sync unseen flags from trakt locally foreach (DBEpisode ep in localAllEpisodes.Where(e => e[DBOnlineEpisode.cWatched] == 1)) { if (TraktEpisodeExists(traktUnSeenEpisodes, ep)) { DBSeries series = Helper.getCorrespondingSeries(ep[DBOnlineEpisode.cSeriesID]); if (series == null || series[DBOnlineSeries.cTraktIgnore]) continue; // mark episode as unwatched TraktLogger.Info("Marking episode '{0}' as unwatched", ep.ToString()); ep[DBOnlineEpisode.cWatched] = false; ep.Commit(); if (!seriesToUpdateEpisodeCounts.Contains(ep[DBOnlineEpisode.cSeriesID])) seriesToUpdateEpisodeCounts.Add(ep[DBOnlineEpisode.cSeriesID]); } } #endregion #region Update Episode counts in Local Database foreach (int seriesID in seriesToUpdateEpisodeCounts) { DBSeries series = Helper.getCorrespondingSeries(seriesID); if (series == null) continue; TraktLogger.Info("Updating Episode Counts for series '{0}'", series.ToString()); DBSeries.UpdateEpisodeCounts(series); } #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[DBOnlineEpisode.cSeriesID] == series.SeriesId).ToList()); if (syncData == null) continue; TraktResponse response = TraktAPI.TraktAPI.SyncEpisodeLibrary(syncData, TraktSyncModes.unlibrary); TraktAPI.TraktAPI.LogTraktResponse(response); Thread.Sleep(500); } } #endregion SyncInProgress = false; TraktLogger.Info("TVSeries Sync Completed"); }
public static DBSeries Get(int seriesID, bool includeStdCond) { SQLCondition cond = new SQLCondition(); cond.Add(new DBOnlineSeries(), DBOnlineSeries.cID, seriesID, SQLConditionType.Equal); foreach (DBSeries series in Get(cond, false, includeStdCond)) return series; return null; }
public void addHierarchyConditions(ref int stepIndex, ref string[] currentStepSelection, ref SQLCondition conditions) { logicalViewStep step = m_steps[stepIndex]; conditions = step.conds.Copy(); // important, don't change the steps themselves // we need to add one additional condition to reflect the selection one hierarchy up if (currentStepSelection != null && currentStepSelection.Length > 0 && stepIndex > 0) { switch (m_steps[stepIndex - 1].Type) { case logicalViewStep.type.group: bool requiresSplit = false; // use sql 'like' for split fields // selected group label string selectedItem = currentStepSelection[0]; // we expect to get the selected group's label // unknown really is "" so get all with null values here if (selectedItem == Translation.Unknown) selectedItem = string.Empty; else if (m_steps[stepIndex - 1].groupedBy.attempSplit) requiresSplit = true; string fieldName = m_steps[stepIndex - 1].groupedBy.rawFieldname; string tableName = m_steps[stepIndex - 1].groupedBy.table.m_tableName; string tableField = tableName + "." + fieldName; string userEditField = tableField + DBTable.cUserEditPostFix; string value = requiresSplit ? "like " + "'%" + selectedItem + "%'" : "= " + "'" + selectedItem + "'"; string sql = string.Empty; // check if the useredit column exists if (DBTable.ColumnExists(tableName, fieldName + DBTable.cUserEditPostFix)) { sql = "(case when (" + userEditField + " is null or " + userEditField + " = " + "'" + "'" + ") " + "then " + tableField + " else " + userEditField + " " + "end) " + value; } else { sql = tableField + " " + value; } conditions.AddCustom(sql); break; case logicalViewStep.type.series: // we expect to get the seriesID as stepSel conditions.Add(new DBSeason(), DBSeason.cSeriesID, currentStepSelection[0], SQLConditionType.Equal); if (DBOption.GetOptions(DBOption.cSortSpecialSeasonLast)) conditions.InsertOrderItem(DBSeason.cTableName + "." + DBSeason.cIndex + " = 0", SQLCondition.orderType.Ascending); break; case logicalViewStep.type.season: // we expect to get the seriesID/seasonIndex as stepSel // we want to query episodes using the CombinedSeason if Sort Order is "DVD" // CombinedSeason gives us the DVD Season and if empty will give us the Aired Season DBSeries series = Helper.getCorrespondingSeries(int.Parse(currentStepSelection[0])); bool SortByDVD = series[DBOnlineSeries.cEpisodeSortOrder] == "DVD"; string seasonIndex = SortByDVD ? DBOnlineEpisode.cCombinedSeason : DBOnlineEpisode.cSeasonIndex; conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, currentStepSelection[0], SQLConditionType.Equal); conditions.beginGroup(); conditions.Add(new DBOnlineEpisode(), seasonIndex, currentStepSelection[1], SQLConditionType.Equal); if (DBOption.GetOptions(DBOption.cSortSpecials) && !SortByDVD) { conditions.nextIsOr = true; conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cAirsBeforeSeason, currentStepSelection[1], SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cAirsAfterSeason, currentStepSelection[1], SQLConditionType.Equal); conditions.nextIsOr = false; } conditions.endGroup(); break; } } }
static DBSeries() { // make sure the table is created on first run (and columns are added before we call SET) DBSeries dummy = new DBSeries(); s_nLastLocalID = DBOption.GetOptions(DBOption.cDBSeriesLastLocalID); s_FieldToDisplayNameMap.Add(cParsedName, "Parsed Name"); int nCurrentDBVersion = cDBVersion; int nUpgradeDBVersion = DBOption.GetOptions(DBOption.cDBSeriesVersion); while (nUpgradeDBVersion != nCurrentDBVersion) { SQLCondition condEmpty = new SQLCondition(); List<DBSeries> AllSeries = Get(condEmpty); // take care of the upgrade in the table switch (nUpgradeDBVersion) { case 1: case 2: // upgrade to version 3; clear the series table (we use 2 other tables now) try { String sqlQuery = "DROP TABLE series"; DBTVSeries.Execute(sqlQuery); nUpgradeDBVersion++; } catch { } break; case 3: // set all new perseries timestamps to 0 DBOnlineSeries.GlobalSet(new DBOnlineSeries(), DBOnlineSeries.cGetEpisodesTimeStamp, 0, new SQLCondition()); DBOnlineSeries.GlobalSet(new DBOnlineSeries(), DBOnlineSeries.cUpdateBannersTimeStamp, 0, new SQLCondition()); nUpgradeDBVersion++; break; case 4: DBSeries.GlobalSet(new DBSeries(), DBSeries.cHidden, 0, new SQLCondition()); nUpgradeDBVersion++; break; case 5: // copy all local parsed name into the online series if seriesID = 0 SQLCondition conditions = new SQLCondition(); conditions.Add(new DBOnlineSeries(), DBOnlineSeries.cID, 0, SQLConditionType.LessThan); // just getting the series should be enough List<DBSeries> seriesList = DBSeries.Get(conditions); nUpgradeDBVersion++; break; case 6: // set all watched flag timestamp to 0 (will be created) DBOnlineSeries.GlobalSet(new DBOnlineSeries(), DBOnlineSeries.cWatchedFileTimeStamp, 0, new SQLCondition()); nUpgradeDBVersion++; break; case 7: // all series no tagged for auto download at first DBOnlineSeries.GlobalSet(new DBOnlineSeries(), DBOnlineSeries.cTaggedToDownload, 0, new SQLCondition()); nUpgradeDBVersion++; break; case 8: // create the unwatcheditem value by parsin the episodes foreach (DBSeries series in AllSeries) { DBEpisode episode = DBEpisode.GetFirstUnwatched(series[DBSeries.cID]); if (episode != null) series[DBOnlineSeries.cUnwatchedItems] = true; else series[DBOnlineSeries.cUnwatchedItems] = false; series.Commit(); } nUpgradeDBVersion++; break; case 9: // Set number of watched/unwatched episodes foreach (DBSeries series in AllSeries) { int epsTotal = 0; int epsUnWatched = 0; DBEpisode.GetSeriesEpisodeCounts(series[DBSeries.cID], out epsTotal, out epsUnWatched); series[DBOnlineSeries.cEpisodeCount] = epsTotal; series[DBOnlineSeries.cEpisodesUnWatched] = epsUnWatched; series.Commit(); } nUpgradeDBVersion++; break; case 10: // Update Sort Name Column foreach (DBSeries series in AllSeries) { series[DBOnlineSeries.cSortName] = Helper.GetSortByName(series[DBOnlineSeries.cPrettyName]); series.Commit(); } nUpgradeDBVersion++; break; case 11: // Migrate isFavourite to new Tagged View conditions = new SQLCondition(); conditions.Add(new DBOnlineSeries(), DBOnlineSeries.cIsFavourite, "1", SQLConditionType.Equal); seriesList = DBSeries.Get(conditions); MPTVSeriesLog.Write("Migrating Favourite Series"); foreach (DBSeries series in seriesList) { // Tagged view are seperated with the pipe "|" character string tagName = "|" + DBView.cTranslateTokenFavourite + "|"; series[DBOnlineSeries.cViewTags] = Helper.GetSeriesViewTags(series, true, tagName); series.Commit(); } // Migrate isOnlineFavourite to new TaggedView conditions = new SQLCondition(); conditions.Add(new DBOnlineSeries(), DBOnlineSeries.cIsOnlineFavourite, "1", SQLConditionType.Equal); seriesList = DBSeries.Get(conditions); MPTVSeriesLog.Write("Migrating Online Favourite Series"); foreach (DBSeries series in seriesList) { // Tagged view are seperated with the pipe "|" character string tagName = "|" + DBView.cTranslateTokenOnlineFavourite + "|"; series[DBOnlineSeries.cViewTags] = Helper.GetSeriesViewTags(series, true, tagName); series.Commit(); } nUpgradeDBVersion++; break; case 12: // we now have parsed_series names as titlecased // to avoid users having to re-identify series for new episodes, and to avoid duplicate entries, we upgrade existing series names foreach (var series in AllSeries) { string oldName = series[DBSeries.cParsedName]; string newName = oldName.ToTitleCase(); MPTVSeriesLog.Write(string.Format("Upgrading Parsed Series Name: {0} to {1}", oldName, newName)); series[DBSeries.cParsedName] = newName; series.Commit(); } nUpgradeDBVersion++; break; case 13: // original name not working in previous release DBOnlineSeries.GlobalSet(new DBOnlineSeries(), DBOnlineSeries.cOriginalName, (DBValue)string.Empty, new SQLCondition()); nUpgradeDBVersion++; break; case 14: // original name not working in previous release DBOnlineSeries.GlobalSet(new DBOnlineSeries(), DBOnlineSeries.cTraktIgnore, 0, new SQLCondition()); nUpgradeDBVersion++; break; default: // new DB, nothing special to do nUpgradeDBVersion = nCurrentDBVersion; break; } } DBOption.SetOptions(DBOption.cDBSeriesVersion, nCurrentDBVersion); }
public void SyncLibrary() { TraktLogger.Info("TVSeries Starting Sync"); SyncInProgress = true; #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."); SyncInProgress = false; 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."); SyncInProgress = false; 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."); SyncInProgress = false; return; } TraktLogger.Info("{0} tvshows with unseen episodes in trakt library", traktUnSeenEpisodes.Count().ToString()); #endregion #region Get local data List<DBEpisode> localAllEpisodes = new List<DBEpisode>(); List<DBEpisode> localCollectionEpisodes = new List<DBEpisode>(); List<DBEpisode> localWatchedEpisodes = new List<DBEpisode>(); // store list of series ids so we can update the episode counts // of any series that syncback watched flags List<int> seriesToUpdateEpisodeCounts = new List<int>(); // Get all episodes in database SQLCondition conditions = new SQLCondition(); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, 0, SQLConditionType.GreaterThan); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cHidden, 0, SQLConditionType.Equal); localAllEpisodes = DBEpisode.Get(conditions, false); TraktLogger.Info("{0} total episodes in tvseries database", localAllEpisodes.Count.ToString()); // Get episodes of files that we have locally localCollectionEpisodes = localAllEpisodes.Where(e => !string.IsNullOrEmpty(e[DBEpisode.cFilename].ToString())).ToList(); TraktLogger.Info("{0} episodes with local files in tvseries database", localCollectionEpisodes.Count.ToString()); // Get watched episodes of files that we have locally or are remote // user could of deleted episode from disk but still have reference to it in database localWatchedEpisodes = localAllEpisodes.Where(e => e[DBOnlineEpisode.cWatched] > 0).ToList(); TraktLogger.Info("{0} episodes watched in tvseries database", localWatchedEpisodes.Count.ToString()); #endregion #region Sync collection/library to trakt // get list of episodes that we have not already trakt'd List<DBEpisode> localEpisodesToSync = new List<DBEpisode>(localCollectionEpisodes); foreach (DBEpisode 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<DBEpisode> localWatchedEpisodesToSync = new List<DBEpisode>(localWatchedEpisodes); foreach (DBEpisode 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 (DBEpisode ep in localAllEpisodes.Where(e => e[DBOnlineEpisode.cWatched] == 0)) { if (TraktEpisodeExists(traktWatchedEpisodes, ep) && !TraktEpisodeExists(traktUnSeenEpisodes, ep)) { DBSeries series = Helper.getCorrespondingSeries(ep[DBOnlineEpisode.cSeriesID]); if (series == null || series[DBOnlineSeries.cTraktIgnore]) continue; // mark episode as watched TraktLogger.Info("Marking episode '{0}' as watched", ep.ToString()); ep[DBOnlineEpisode.cWatched] = true; ep.Commit(); if (!seriesToUpdateEpisodeCounts.Contains(ep[DBOnlineEpisode.cSeriesID])) seriesToUpdateEpisodeCounts.Add(ep[DBOnlineEpisode.cSeriesID]); } } #endregion #region Sync unseen flags from trakt locally foreach (DBEpisode ep in localAllEpisodes.Where(e => e[DBOnlineEpisode.cWatched] == 1)) { if (TraktEpisodeExists(traktUnSeenEpisodes, ep)) { DBSeries series = Helper.getCorrespondingSeries(ep[DBOnlineEpisode.cSeriesID]); if (series == null || series[DBOnlineSeries.cTraktIgnore]) continue; // mark episode as unwatched TraktLogger.Info("Marking episode '{0}' as unwatched", ep.ToString()); ep[DBOnlineEpisode.cWatched] = false; ep.Commit(); if (!seriesToUpdateEpisodeCounts.Contains(ep[DBOnlineEpisode.cSeriesID])) seriesToUpdateEpisodeCounts.Add(ep[DBOnlineEpisode.cSeriesID]); } } #endregion #region Ratings Sync // only sync ratings if we are using Advanced Ratings if (TraktSettings.SyncRatings) { #region Episode Ratings var traktRatedEpisodes = TraktAPI.TraktAPI.GetUserRatedEpisodes(TraktSettings.Username); if (traktRatedEpisodes == null) TraktLogger.Error("Error getting rated episodes from trakt server."); else TraktLogger.Info("{0} rated episodes in trakt library", traktRatedEpisodes.Count().ToString()); if (traktRatedEpisodes != null) { // get the episodes that we have rated/unrated var ratedEpisodeList = localAllEpisodes.Where(e => e[DBOnlineEpisode.cMyRating] > 0).ToList(); var unRatedEpisodeList = localAllEpisodes.Except(ratedEpisodeList).ToList(); TraktLogger.Info("{0} rated episodes available to sync in tvseries database", ratedEpisodeList.Count.ToString()); var ratedEpisodesToSync = new List<DBEpisode>(ratedEpisodeList); // note: these two foreach loops can be expensive! // find out what ratings are missing locally foreach (var episode in unRatedEpisodeList) { var traktEpisode = traktRatedEpisodes.FirstOrDefault(e => e.EpisodeDetails.TVDBID == episode[DBOnlineEpisode.cID]); if (traktEpisode != null) { // update local collection rating TraktLogger.Info("Inserting rating '{0}/10' for episode '{1}'", traktEpisode.RatingAdvanced, episode.ToString()); episode[DBOnlineEpisode.cMyRating] = traktEpisode.RatingAdvanced; episode.Commit(); } } // find out what ratings we can send to trakt foreach (var episode in ratedEpisodeList) { var traktEpisode = traktRatedEpisodes.FirstOrDefault(e => e.EpisodeDetails.TVDBID == episode[DBOnlineEpisode.cID]); if (traktEpisode != null) { // already rated on trakt, remove from sync collection ratedEpisodesToSync.Remove(episode); } } TraktLogger.Info("{0} rated episodes to sync to trakt", ratedEpisodesToSync.Count); if (ratedEpisodesToSync.Count > 0) { ratedEpisodesToSync.ForEach(a => TraktLogger.Info("Importing rating '{0}/10' for episode '{1}'", a[DBOnlineEpisode.cMyRating], a.ToString())); TraktResponse response = TraktAPI.TraktAPI.RateEpisodes(CreateRatingEpisodesData(ratedEpisodesToSync)); TraktAPI.TraktAPI.LogTraktResponse(response); } } #endregion #region Show Ratings var traktRatedShows = TraktAPI.TraktAPI.GetUserRatedShows(TraktSettings.Username); if (traktRatedShows == null) TraktLogger.Error("Error getting rated shows from trakt server."); else TraktLogger.Info("{0} rated shows in trakt library", traktRatedShows.Count().ToString()); if (traktRatedShows != null) { // get the shows that we have rated/unrated var localAllSeries = DBSeries.Get(new SQLCondition()); var ratedShowList = localAllSeries.Where(s => s[DBOnlineSeries.cMyRating] > 0).ToList(); var unRatedShowList = localAllSeries.Except(ratedShowList).ToList(); TraktLogger.Info("{0} rated shows available to sync in tvseries database", ratedShowList.Count.ToString()); var ratedShowsToSync = new List<DBSeries>(ratedShowList); foreach (var traktShow in traktRatedShows) { foreach (var show in unRatedShowList.Where(s => s[DBSeries.cID] == traktShow.TVDBID)) { // update local collection rating TraktLogger.Info("Inserting rating '{0}/10' for show '{1}'", traktShow.RatingAdvanced, show.ToString()); show[DBOnlineEpisode.cMyRating] = traktShow.RatingAdvanced; show.Commit(); } foreach (var show in ratedShowList.Where(s => s[DBSeries.cID] == traktShow.TVDBID)) { // already rated on trakt, remove from sync collection ratedShowsToSync.Remove(show); } } TraktLogger.Info("{0} rated shows to sync to trakt", ratedShowsToSync.Count); if (ratedShowsToSync.Count > 0) { ratedShowsToSync.ForEach(a => TraktLogger.Info("Importing rating '{0}/10' for show '{1}'", a[DBOnlineSeries.cMyRating], a.ToString())); TraktResponse response = TraktAPI.TraktAPI.RateSeries(CreateRatingShowsData(ratedShowsToSync)); TraktAPI.TraktAPI.LogTraktResponse(response); } } #endregion } #endregion #region Update Episode counts in Local Database foreach (int seriesID in seriesToUpdateEpisodeCounts) { DBSeries series = Helper.getCorrespondingSeries(seriesID); if (series == null) continue; TraktLogger.Info("Updating Episode Counts for series '{0}'", series.ToString()); DBSeries.UpdateEpisodeCounts(series); } #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[DBOnlineEpisode.cSeriesID] == series.SeriesId).ToList()); if (syncData == null) continue; TraktResponse response = TraktAPI.TraktAPI.SyncEpisodeLibrary(syncData, TraktSyncModes.unlibrary); TraktAPI.TraktAPI.LogTraktResponse(response); Thread.Sleep(500); } } #endregion SyncInProgress = false; TraktLogger.Info("TVSeries Sync Completed"); }
public static void UpdateEpisodeCounts(DBSeries series) { if (series == null) return; int seriesEpsTotal = 0; int seriesEpsUnWatched = 0; int epsTotal = 0; int epsUnWatched = 0; // Update for each season in series and add each to total series count SQLCondition condition = new SQLCondition(); if (!DBOption.GetOptions(DBOption.cShowHiddenItems)) { //don't include hidden seasons unless the ShowHiddenItems option is set condition.Add(new DBSeason(), DBSeason.cHidden, 0, SQLConditionType.Equal); } List<DBSeason> Seasons = DBSeason.Get(series[DBSeries.cID], condition); foreach (DBSeason season in Seasons) { epsTotal = 0; epsUnWatched = 0; DBEpisode.GetSeasonEpisodeCounts(series, season, out epsTotal, out epsUnWatched); season[DBSeason.cEpisodeCount] = epsTotal; season[DBSeason.cEpisodesUnWatched] = epsUnWatched; season[DBSeason.cUnwatchedItems] = epsUnWatched > 0; season.Commit(); seriesEpsTotal += epsTotal; // Count the Special (Season 0 (zero)) episodes as watched! if ((season[DBSeason.cIndex] != 0) || (season[DBSeason.cIndex] == 0 && !DBOption.GetOptions(DBOption.cCountSpecialEpisodesAsWatched))) { seriesEpsUnWatched += epsUnWatched; } MPTVSeriesLog.Write(string.Format("Series \"{0} Season {1}\" has {2}/{3} unwatched episodes", series.ToString(), season[DBSeason.cIndex], epsUnWatched, epsTotal), MPTVSeriesLog.LogLevel.Debug); } MPTVSeriesLog.Write(string.Format("Series \"{0}\" has {1}/{2} unwatched episodes", series.ToString(), seriesEpsUnWatched, seriesEpsTotal), MPTVSeriesLog.LogLevel.Debug); series[DBOnlineSeries.cEpisodeCount] = seriesEpsTotal; series[DBOnlineSeries.cEpisodesUnWatched] = seriesEpsUnWatched; series[DBOnlineSeries.cUnwatchedItems] = seriesEpsUnWatched > 0; series.Commit(); }
public List <string> getGroupItems(int stepIndex, string[] currentStepSelection) // in nested groups, eg. Networks-Genres-.. we also need selections { SQLCondition conditions = null; MPTVSeriesLog.Write("View: GetGroupItems: Begin", MPTVSeriesLog.LogLevel.Debug); if (stepIndex >= m_steps.Count) { return(null); // wrong index specified!! } addHierarchyConditions(ref stepIndex, ref currentStepSelection, ref conditions); logicalViewStep step = m_steps[stepIndex]; List <string> items = new List <string>(); // to ensure we respect on the fly filter settings if (DBOption.GetOptions(DBOption.cOnlyShowLocalFiles) && (typeof(DBOnlineEpisode) != step.groupedBy.table.GetType() && typeof(DBEpisode) != step.groupedBy.table.GetType())) { // not generic SQLCondition fullSubCond = new SQLCondition(); fullSubCond.AddCustom(DBOnlineEpisode.Q(DBOnlineEpisode.cSeriesID), DBOnlineSeries.Q(DBOnlineSeries.cID), SQLConditionType.Equal); conditions.AddCustom(" exists( " + DBEpisode.stdGetSQL(fullSubCond, false) + " )"); } else if (DBOption.GetOptions(DBOption.cOnlyShowLocalFiles)) { // has to be grouped by something episode conditions.Add(new DBEpisode(), DBEpisode.cFilename, "", SQLConditionType.NotEqual); } string fieldName = step.groupedBy.rawFieldname; string tableName = step.groupedBy.table.m_tableName; string tableField = step.groupedBy.tableField; string userEditField = tableField + DBTable.cUserEditPostFix; string sql = string.Empty; // check if the useredit column exists if (DBTable.ColumnExists(tableName, fieldName + DBTable.cUserEditPostFix)) { sql = "select distinct(" + "case when (" + userEditField + " is null or " + userEditField + " = " + "'" + "'" + ") " + "then " + tableField + " else " + userEditField + " " + "end) as gnr, " + "count(*) from " + tableName + conditions + " group by gnr" + step.conds.orderString; } else { sql = "select distinct " + tableField + " , count(*) " + " from " + tableName + conditions + " group by " + tableField + step.conds.orderString; } SQLite.NET.SQLiteResultSet results = DBTVSeries.Execute(sql); MPTVSeriesLog.Write("View: GetGroupItems: SQL complete", MPTVSeriesLog.LogLevel.Debug); if (results.Rows.Count > 0) { for (int index = 0; index < results.Rows.Count; index++) { string tmpItem = results.Rows[index].fields[0]; // assume we now have a list of all distinct ones if (step.groupedBy.attempSplit) { // we want to try to split by "|" eg. for actors/genres string[] split = DBOnlineEpisode.splitField(tmpItem); foreach (string item in split) { if (item.Trim().Length == 0) { // display "Unknown" if field is empty" items.Add(Translation.Unknown); } else { items.Add(item.Trim()); } } } else { if (tmpItem.Trim().Length == 0) { items.Add(Translation.Unknown); } else { items.Add(tmpItem.Trim()); } } } if (step.groupedBy.attempSplit) { // have to check for dups (because we split eg. Drama|Action so "Action" might be in twice items = Helper.RemoveDuplicates(items); } // now we have to sort them again (Unknown/splitting above) items.Sort(); if (step.groupedBy.attempSplit) { // and limit in memory here (again because those splits are hard to deal with) if (step.limitItems > 0) { Helper.LimitList(ref items, step.limitItems); } } } MPTVSeriesLog.Write("View: GetGroupItems: Complete", MPTVSeriesLog.LogLevel.Debug); return(items); }
static DBSeries() { // make sure the table is created on first run (and columns are added before we call SET) DBSeries dummy = new DBSeries(); s_nLastLocalID = DBOption.GetOptions(DBOption.cDBSeriesLastLocalID); s_FieldToDisplayNameMap.Add(cParsedName, "Parsed Name"); int nCurrentDBVersion = cDBVersion; int nUpgradeDBVersion = DBOption.GetOptions(DBOption.cDBSeriesVersion); while (nUpgradeDBVersion != nCurrentDBVersion) { SQLCondition condEmpty = new SQLCondition(); List <DBSeries> AllSeries = Get(condEmpty); // take care of the upgrade in the table switch (nUpgradeDBVersion) { case 1: case 2: // upgrade to version 3; clear the series table (we use 2 other tables now) try { String sqlQuery = "DROP TABLE series"; DBTVSeries.Execute(sqlQuery); nUpgradeDBVersion++; } catch { } break; case 3: // set all new perseries timestamps to 0 DBOnlineSeries.GlobalSet(new DBOnlineSeries(), DBOnlineSeries.cGetEpisodesTimeStamp, 0, new SQLCondition()); DBOnlineSeries.GlobalSet(new DBOnlineSeries(), DBOnlineSeries.cUpdateBannersTimeStamp, 0, new SQLCondition()); nUpgradeDBVersion++; break; case 4: DBSeries.GlobalSet(new DBSeries(), DBSeries.cHidden, 0, new SQLCondition()); nUpgradeDBVersion++; break; case 5: // copy all local parsed name into the online series if seriesID = 0 SQLCondition conditions = new SQLCondition(); conditions.Add(new DBOnlineSeries(), DBOnlineSeries.cID, 0, SQLConditionType.LessThan); // just getting the series should be enough List <DBSeries> seriesList = DBSeries.Get(conditions); nUpgradeDBVersion++; break; case 6: // set all watched flag timestamp to 0 (will be created) DBOnlineSeries.GlobalSet(new DBOnlineSeries(), DBOnlineSeries.cWatchedFileTimeStamp, 0, new SQLCondition()); nUpgradeDBVersion++; break; case 7: // all series no tagged for auto download at first DBOnlineSeries.GlobalSet(new DBOnlineSeries(), DBOnlineSeries.cTaggedToDownload, 0, new SQLCondition()); nUpgradeDBVersion++; break; case 8: // create the unwatcheditem value by parsin the episodes foreach (DBSeries series in AllSeries) { DBEpisode episode = DBEpisode.GetFirstUnwatched(series[DBSeries.cID]); if (episode != null) { series[DBOnlineSeries.cUnwatchedItems] = true; } else { series[DBOnlineSeries.cUnwatchedItems] = false; } series.Commit(); } nUpgradeDBVersion++; break; case 9: // Set number of watched/unwatched episodes foreach (DBSeries series in AllSeries) { int epsTotal = 0; int epsUnWatched = 0; DBEpisode.GetSeriesEpisodeCounts(series[DBSeries.cID], out epsTotal, out epsUnWatched); series[DBOnlineSeries.cEpisodeCount] = epsTotal; series[DBOnlineSeries.cEpisodesUnWatched] = epsUnWatched; series.Commit(); } nUpgradeDBVersion++; break; case 10: // Update Sort Name Column foreach (DBSeries series in AllSeries) { series[DBOnlineSeries.cSortName] = Helper.GetSortByName(series[DBOnlineSeries.cPrettyName]); series.Commit(); } nUpgradeDBVersion++; break; case 11: // Migrate isFavourite to new Tagged View conditions = new SQLCondition(); conditions.Add(new DBOnlineSeries(), DBOnlineSeries.cIsFavourite, "1", SQLConditionType.Equal); seriesList = DBSeries.Get(conditions); MPTVSeriesLog.Write("Migrating Favourite Series"); foreach (DBSeries series in seriesList) { // Tagged view are seperated with the pipe "|" character string tagName = "|" + DBView.cTranslateTokenFavourite + "|"; series[DBOnlineSeries.cViewTags] = Helper.GetSeriesViewTags(series, true, tagName); series.Commit(); } // Migrate isOnlineFavourite to new TaggedView conditions = new SQLCondition(); conditions.Add(new DBOnlineSeries(), DBOnlineSeries.cIsOnlineFavourite, "1", SQLConditionType.Equal); seriesList = DBSeries.Get(conditions); MPTVSeriesLog.Write("Migrating Online Favourite Series"); foreach (DBSeries series in seriesList) { // Tagged view are seperated with the pipe "|" character string tagName = "|" + DBView.cTranslateTokenOnlineFavourite + "|"; series[DBOnlineSeries.cViewTags] = Helper.GetSeriesViewTags(series, true, tagName); series.Commit(); } nUpgradeDBVersion++; break; case 12: // we now have parsed_series names as titlecased // to avoid users having to re-identify series for new episodes, and to avoid duplicate entries, we upgrade existing series names foreach (var series in AllSeries) { string oldName = series[DBSeries.cParsedName]; string newName = oldName.ToTitleCase(); MPTVSeriesLog.Write(string.Format("Upgrading Parsed Series Name: {0} to {1}", oldName, newName)); series[DBSeries.cParsedName] = newName; series.Commit(); } nUpgradeDBVersion++; break; case 13: // original name not working in previous release DBOnlineSeries.GlobalSet(new DBOnlineSeries(), DBOnlineSeries.cOriginalName, (DBValue)string.Empty, new SQLCondition()); nUpgradeDBVersion++; break; case 14: // original name not working in previous release DBOnlineSeries.GlobalSet(new DBOnlineSeries(), DBOnlineSeries.cTraktIgnore, 0, new SQLCondition()); nUpgradeDBVersion++; break; default: // new DB, nothing special to do nUpgradeDBVersion = nCurrentDBVersion; break; } } DBOption.SetOptions(DBOption.cDBSeriesVersion, nCurrentDBVersion); }
public void addSQLCondition(string what, string type, string condition) { if ((!what.Contains("<") || !what.Contains(".")) && !what.Contains("custom:")) { return; } SQLConditionType condtype; switch (type) { case "=": condtype = SQLConditionType.Equal; break; case ">": condtype = SQLConditionType.GreaterThan; break; case ">=": condtype = SQLConditionType.GreaterEqualThan; break; case "<": condtype = SQLConditionType.LessThan; break; case "<=": condtype = SQLConditionType.LessEqualThan; break; case "!=": condtype = SQLConditionType.NotEqual; break; case "like": condtype = SQLConditionType.Like; break; default: condtype = SQLConditionType.Equal; break; } DBTable table = null; string tableField = string.Empty; getTableFieldname(what, out table, out tableField); Type lType = table.GetType(); SQLCondition fullSubCond = new SQLCondition(); if (logicalViewStep.type.series == Type && (lType != typeof(DBSeries) && lType != typeof(DBOnlineSeries))) { if (lType == typeof(DBSeason)) { fullSubCond.AddCustom(DBSeason.Q(DBSeason.cSeriesID), DBOnlineSeries.Q(DBOnlineSeries.cID), SQLConditionType.Equal); fullSubCond.AddCustom(DBSeason.Q(tableField), condition, condtype, true); conds.AddCustom(" exists( " + DBSeason.stdGetSQL(fullSubCond, false) + " )"); } else if (lType == typeof(DBOnlineEpisode)) { fullSubCond.AddCustom(DBOnlineEpisode.Q(tableField), condition, condtype, true); conds.AddCustom(" online_series.id in ( " + DBEpisode.stdGetSQL(fullSubCond, false, true, DBOnlineEpisode.Q(DBOnlineEpisode.cSeriesID)) + " )"); } else if (lType == typeof(DBEpisode)) { fullSubCond.AddCustom(DBEpisode.Q(tableField), condition, condtype, true); conds.AddCustom(" online_series.id in ( " + DBEpisode.stdGetSQL(fullSubCond, false, true, DBOnlineEpisode.Q(DBOnlineEpisode.cSeriesID)) + " )"); } } else if (logicalViewStep.type.season == Type && lType != typeof(DBSeason)) { if (lType == typeof(DBOnlineSeries) || lType == typeof(DBSeries)) { fullSubCond.AddCustom(DBOnlineSeries.Q(DBOnlineSeries.cID), DBSeason.Q(DBSeason.cSeriesID), SQLConditionType.Equal); fullSubCond.AddCustom(DBOnlineSeries.Q(tableField), condition, condtype, true); conds.AddCustom(" exists( " + DBSeries.stdGetSQL(fullSubCond, false) + " )"); } else if (lType == typeof(DBOnlineEpisode)) { // we rely on the join in dbseason for this (much, much faster) conds.AddCustom(DBOnlineEpisode.Q(tableField), condition, condtype, true); } else if (lType == typeof(DBEpisode)) { fullSubCond.AddCustom(DBOnlineEpisode.Q(DBOnlineEpisode.cSeriesID), DBSeason.Q(DBSeason.cSeriesID), SQLConditionType.Equal); fullSubCond.AddCustom(DBOnlineEpisode.Q(DBOnlineEpisode.cSeasonIndex), DBSeason.Q(DBSeason.cIndex), SQLConditionType.Equal); fullSubCond.AddCustom(DBEpisode.Q(tableField), condition, condtype); conds.AddCustom(" exists( " + DBEpisode.stdGetSQL(fullSubCond, false) + " )"); } } else if (logicalViewStep.type.episode == Type && (lType != typeof(DBEpisode) && lType != typeof(DBOnlineEpisode))) { if (lType == typeof(DBOnlineSeries) || lType == typeof(DBSeries)) { fullSubCond.AddCustom(DBOnlineSeries.Q(DBOnlineSeries.cID), DBOnlineEpisode.Q(DBOnlineEpisode.cSeriesID), SQLConditionType.Equal); fullSubCond.AddCustom(DBOnlineSeries.Q(tableField), condition, condtype, true); conds.AddCustom(" exists( " + DBSeries.stdGetSQL(fullSubCond, false) + " )"); } if (lType == typeof(DBSeason)) { fullSubCond.AddCustom(DBSeason.Q(DBSeason.cSeriesID), DBOnlineEpisode.Q(DBOnlineEpisode.cSeriesID), SQLConditionType.Equal); fullSubCond.AddCustom(DBSeason.Q(DBSeason.cIndex), DBOnlineEpisode.Q(DBOnlineEpisode.cSeasonIndex), SQLConditionType.Equal); fullSubCond.AddCustom(DBSeason.Q(tableField), condition, condtype, true); conds.AddCustom(" exists( " + DBSeason.stdGetSQL(fullSubCond, false) + " )"); } } else { // condition is on current table itself conds.Add(table, tableField, condition.Trim(), condtype); } }
public static void SynchronizeLibrary(List <DBEpisode> episodes, TraktSyncModes mode) { if (episodes.Count == 0) { return; } // get unique series ids var uniqueSeriesIDs = (from seriesIDs in episodes select seriesIDs[DBEpisode.cSeriesID].ToString()).Distinct().ToList(); // go over each series, can only send one series at a time foreach (string seriesID in uniqueSeriesIDs) { DBSeries series = Helper.getCorrespondingSeries(int.Parse(seriesID)); if (series == null || series[DBOnlineSeries.cTraktIgnore]) { continue; } MPTVSeriesLog.Write("Trakt: Synchronizing '{0}' episodes for series '{1}'.", mode.ToString(), series.ToString()); TraktSync traktSync = GetTraktSyncObject(series, episodes); // upload to trakt TraktResponse response = TraktAPI.SyncEpisodeLibrary(traktSync, mode); if (response == null) { MPTVSeriesLog.Write("Trakt Error: Response from server was unexpected."); continue; } // check for any error and log result CheckTraktErrorAndNotify(response, false); if (response.Status == "success") { SQLCondition conditions = new SQLCondition(); // flag episodes and commit to database switch (mode) { case TraktSyncModes.seen: conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, seriesID, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cWatched, 1, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cHidden, 0, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cTraktSeen, 0, SQLConditionType.Equal); // we always flag traktLibrary field as the 'traktSeen' field counts as part of library DBOnlineEpisode.GlobalSet(new DBOnlineEpisode(), DBOnlineEpisode.cTraktLibrary, 1, conditions); DBOnlineEpisode.GlobalSet(new DBOnlineEpisode(), DBOnlineEpisode.cTraktSeen, 1, conditions); break; case TraktSyncModes.library: // we can't do a global set as our conditions are from two different tables // where filename is not empty and traktLibrary = 0 foreach (DBEpisode ep in episodes.Where(e => e[DBEpisode.cSeriesID] == seriesID)) { ep[DBOnlineEpisode.cTraktLibrary] = 1; ep.Commit(); } break; case TraktSyncModes.unseen: conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cSeriesID, seriesID, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cHidden, 0, SQLConditionType.Equal); conditions.Add(new DBOnlineEpisode(), DBOnlineEpisode.cTraktSeen, 2, SQLConditionType.Equal); DBOnlineEpisode.GlobalSet(new DBOnlineEpisode(), DBOnlineEpisode.cTraktSeen, 0, conditions); break; case TraktSyncModes.unlibrary: break; } } // wait a short period before uploading another series Thread.Sleep(2000); } }