public ProcessedEpisode(Episode e, ShowItem si) : base(e) { this.OverallNumber = -1; this.NextToAir = false; this.EpNum2 = this.EpNum; this.Ignore = false; this.SI = si; }
public Episode(Episode O) { this.EpisodeID = O.EpisodeID; this.SeriesID = O.SeriesID; this.EpNum = O.EpNum; this.FirstAired = O.FirstAired; this.Srv_LastUpdated = O.Srv_LastUpdated; this.Overview = O.Overview; this.EpisodeRating = O.EpisodeRating; this.EpisodeGuestStars = O.EpisodeGuestStars; this.EpisodeDirector = O.EpisodeDirector; this.Writer = O.Writer; this.Name = O.Name; this.TheSeason = O.TheSeason; this.TheSeries = O.TheSeries; this.SeasonID = O.SeasonID; this.Dirty = O.Dirty; this.Items = new System.Collections.Generic.Dictionary<string, string>(); foreach (System.Collections.Generic.KeyValuePair<string, string> i in O.Items) this.Items.Add(i.Key, i.Value); }
public bool SameAs(Episode o) { return (this.EpisodeID == o.EpisodeID); }
public bool ProcessTVDBResponse(Stream str, int? codeHint) { // Will have one or more series, and episodes // all wrapped in <Data> </Data> // e.g.: //<Data> // <Series> // <id>...</id> // etc. // </Series> // <Episode> // <id>...</id> // blah blah // </Episode> // <Episode> // <id>...</id> // blah blah // </Episode> // ... //</Data> if (!this.GetLock("ProcessTVDBResponse")) return false; try { XmlReaderSettings settings = new XmlReaderSettings { IgnoreComments = true, IgnoreWhitespace = true }; XmlReader r = XmlReader.Create(str, settings); r.Read(); while (!r.EOF) { if ((r.Name == "Data") && !r.IsStartElement()) break; // that's it. if (r.Name == "Series") { // The <series> returned by GetSeries have // less info than other results from // thetvdb.com, so we need to smartly merge // in a <Series> if we already have some/all // info on it (depending on which one came // first). SeriesInfo si = new SeriesInfo(r.ReadSubtree()); if (this.Series.ContainsKey(si.TVDBCode)) this.Series[si.TVDBCode].Merge(si, this.RequestLanguage); else this.Series[si.TVDBCode] = si; r.Read(); } else if (r.Name == "Episode") { Episode e = new Episode(null, null, r.ReadSubtree(), Args); if (e.OK()) { if (!this.Series.ContainsKey(e.SeriesID)) throw new TVDBException("Can't find the series to add the episode to (TheTVDB)."); SeriesInfo ser = this.Series[e.SeriesID]; Season seas = ser.GetOrAddSeason(e.ReadSeasonNum, e.SeasonID); bool added = false; for (int i = 0; i < seas.Episodes.Count; i++) { Episode ep = seas.Episodes[i]; if (ep.EpisodeID == e.EpisodeID) { seas.Episodes[i] = e; added = true; break; } } if (!added) seas.Episodes.Add(e); e.SetSeriesSeason(ser, seas); } r.Read(); } else if (r.Name == "xml") r.Read(); else if (r.Name == "BannersCache") { //this wil not be found in a standard response from the TVDB website //will only be in the response when we are reading from the cache ProcessTVDBBannerCacheResponse(r); r.Read(); } else if (r.Name == "Data") { string time = r.GetAttribute("time"); if (time != null) this.New_Srv_Time = int.Parse(time); r.Read(); } else r.ReadOuterXml(); } } catch (XmlException e) { if (!this.Args.Unattended) { string message = "Error processing data from TheTVDB (top level)."; message += "\r\n" + e.Message; String name = ""; if (codeHint.HasValue && Series.ContainsKey(codeHint.Value)) { name += "Show \"" + Series[codeHint.Value].Name + "\" "; } if (codeHint.HasValue) { name += "ID #" + codeHint.Value + " "; } MessageBox.Show(name + message, "TVRename", MessageBoxButtons.OK, MessageBoxIcon.Error); // throw new TVDBException(e.Message); } return false; } finally { this.Unlock("ProcessTVDBResponse"); } return true; }
private static void WriteEpisodeDetailsFor([NotNull] Episode episode, [CanBeNull] ShowItem show, [NotNull] XmlWriter writer, bool multi, bool dvdOrder) { // See: http://xbmc.org/wiki/?title=Import_-_Export_Library#TV_Episodes writer.WriteStartElement("episodedetails"); writer.WriteElement("title", episode.Name); writer.WriteElement("originaltitle", show?.ShowName); writer.WriteElement("showtitle", show?.ShowName); string showRating = episode.EpisodeRating; if (showRating != null) { writer.WriteStartElement("ratings"); writer.WriteStartElement("rating"); writer.WriteAttributeString("name", "tvdb"); writer.WriteAttributeString("max", "10"); writer.WriteAttributeString("default", "true"); writer.WriteElement("value", showRating); writer.WriteElement("votes", episode.SiteRatingCount ?? 0, true); writer.WriteEndElement(); //rating writer.WriteEndElement(); //ratings } if (dvdOrder) { writer.WriteElement("season", episode.DvdSeasonNumber); writer.WriteElement("episode", episode.DvdEpNum); } else { writer.WriteElement("season", episode.AiredSeasonNumber); writer.WriteElement("episode", episode.AiredEpNum); } writer.WriteElement("plot", episode.Overview); writer.WriteElement("studio", episode.TheSeries?.Network); writer.WriteStartElement("aired"); if (episode.FirstAired != null) { writer.WriteValue(episode.FirstAired.Value.ToString("yyyy-MM-dd")); } writer.WriteEndElement(); writer.WriteElement("mpaa", show?.TheSeries()?.ContentRating, true); //Director(s) string epDirector = episode.EpisodeDirector; if (!string.IsNullOrEmpty(epDirector)) { foreach (string daa in epDirector.Split('|')) { writer.WriteElement("director", daa, true); } } //Writers(s) string epWriter = episode.Writer; if (!string.IsNullOrEmpty(epWriter)) { foreach (string txtWriter in epWriter.Split('|')) { writer.WriteElement("credits", txtWriter, true); } } // Guest Stars... if (!string.IsNullOrEmpty(episode.EpisodeGuestStars)) { string recurringActors = ""; if (show != null) { recurringActors = string.Join("|", show.TheSeries()?.GetActorNames() ?? new List <string>()); } string guestActors = episode.EpisodeGuestStars; if (!string.IsNullOrEmpty(guestActors)) { foreach (string gaa in guestActors.Split('|') .Where(gaa => !string.IsNullOrEmpty(gaa)) .Where(gaa => string.IsNullOrEmpty(recurringActors) || !recurringActors.Contains(gaa))) { writer.WriteStartElement("actor"); writer.WriteElement("name", gaa); writer.WriteEndElement(); // actor } } } // actors... if (show != null) { foreach (Actor aa in (show.TheSeries()?.GetActors() ?? new List <Actor>()) .Where(aa => !string.IsNullOrEmpty(aa.ActorName))) { writer.WriteStartElement("actor"); writer.WriteElement("name", aa.ActorName); writer.WriteElement("role", aa.ActorRole); writer.WriteElement("order", aa.ActorSortOrder); writer.WriteElement("thumb", aa.ActorImage); writer.WriteEndElement(); // actor } } if (multi) { writer.WriteStartElement("resume"); //we have to put 0 as we don't know where the multipart episode starts/ends writer.WriteElement("position", 0); writer.WriteElement("total", 0); writer.WriteEndElement(); // resume //For now we only put art in for multipart episodes. Kodi finds the art appropriately //without our help for the others if (show != null) { string filename = TVSettings.Instance.FilenameFriendly( TVSettings.Instance.NamingStyle.GetTargetEpisodeName(show, episode, show.GetTimeZone(), show.DvdOrder)); string thumbFilename = filename + ".jpg"; writer.WriteElement("thumb", thumbFilename); //Should be able to do this using the local filename, but only seems to work if you provide a URL //XMLHelper.WriteElementToXML(writer, "thumb", TheTVDB.Instance.GetTVDBDownloadURL(episode.GetFilename())) } } writer.WriteEndElement(); // episodedetails }
public void AddUpdateEpisode([NotNull] Episode newEpisode) { Episodes.AddOrUpdate(newEpisode.EpisodeId, newEpisode, (i, episode) => newEpisode); }
public List<System.IO.FileInfo> FindEpOnDisk(ShowItem si, Episode epi) { List<System.IO.FileInfo> ret = new List<System.IO.FileInfo>(); int seasWanted = epi.TheSeason.SeasonNumber; int epWanted = epi.EpNum; int snum = epi.TheSeason.SeasonNumber; if (!si.AllFolderLocations(this.Settings).ContainsKey(snum)) return ret; foreach (string folder in si.AllFolderLocations(this.Settings)[snum]) { DirectoryInfo di; try { di = new DirectoryInfo(folder); } catch { return ret; } if (!di.Exists) return ret; FileInfo[] files = di.GetFiles(); foreach (FileInfo fiTemp in files) { int seasFound; int epFound; if (!this.Settings.UsefulExtension(fiTemp.Extension, false)) continue; // move on if (this.FindSeasEp(fiTemp, out seasFound, out epFound, si)) { if (seasFound == -1) seasFound = seasWanted; if ((seasFound == seasWanted) && (epFound == epWanted)) ret.Add(fiTemp); } } } return ret; }
private static bool ProcessXml([NotNull] XElement x, [NotNull] LocalCache cache) { // Will have one or more series, and episodes // all wrapped in <Data> </Data> // e.g.: //<Data> // <Series> // <id>...</id> // etc. // </Series> // <Episode> // <id>...</id> // blah blah // </Episode> // <Episode> // <id>...</id> // blah blah // </Episode> // ... //</Data> try { string time = x.Attribute("time")?.Value; cache.LatestUpdateTime.Load(time); Logger.Info($"Loaded file with updates until {cache.LatestUpdateTime.LastSuccessfulServerUpdateDateTime()}"); foreach (SeriesInfo si in x.Descendants("Series").Select(seriesXml => new SeriesInfo(seriesXml))) { // The <series> returned by GetSeries have // less info than other results from // thetvdb.com, so we need to smartly merge // in a <Series> if we already have some/all // info on it (depending on which one came // first). cache.UpdateSeries(si); } foreach (XElement episodeXml in x.Descendants("Episode")) { Episode e = new Episode(episodeXml); if (e.Ok()) { cache.AddOrUpdateEpisode(e); } else { Logger.Error($"problem with XML recieved {episodeXml}"); } } foreach (XElement banners in x.Descendants("BannersCache")) { //this wil not be found in a standard response from the TVDB website //will only be in the response when we are reading from the cache ProcessXmlBannerCache(banners, cache); } } catch (XmlException e) { string message = "Error processing data from TheTVDB (top level)."; message += "\r\n" + x; message += "\r\n" + e.Message; Logger.Error(message); Logger.Error(x.ToString()); throw new TVDBException(message); } return(true); }
public string GetTargetEpisodeName([NotNull] ShowItem show, [NotNull] Episode ep, TimeZoneInfo tz, bool dvdOrder) => GetTargetEpisodeName(show, ep, tz, dvdOrder, false);
public static List <FileInfo> FindEpOnDisk([CanBeNull] DirFilesCache dfc, [NotNull] ShowItem si, [NotNull] Episode epi, bool checkDirectoryExist = true) { DirFilesCache cache = dfc ?? new DirFilesCache(); List <FileInfo> ret = new List <FileInfo>(); int seasWanted = si.DvdOrder ? epi.TheDvdSeason.SeasonNumber : epi.TheAiredSeason.SeasonNumber; int epWanted = si.DvdOrder ? epi.DvdEpNum : epi.AiredEpNum; int snum = seasWanted; Dictionary <int, List <string> > dirs = si.AllFolderLocationsEpCheck(checkDirectoryExist); if (!dirs.ContainsKey(snum)) { return(ret); } foreach (string folder in dirs[snum]) { FileInfo[] files = cache.GetFiles(folder); if (files is null) { continue; } foreach (FileInfo fiTemp in files.Where(fiTemp => fiTemp.IsMovieFile())) { if (!FindSeasEp(fiTemp, out int seasFound, out int epFound, out int _, si)) { continue; } if (seasFound == -1) { seasFound = seasWanted; } if ((seasFound == seasWanted) && (epFound == epWanted)) { ret.Add(fiTemp); } } } return(ret); }
public string GetTargetEpisodeName([NotNull] ShowItem show, [NotNull] Episode ep) => GetTargetEpisodeName(show, ep, false);
private static bool EpisodesMatch([NotNull] Episode pep, Episode comparePep) { return(pep.FirstAired.HasValue && comparePep.FirstAired.HasValue && pep.FirstAired == comparePep.FirstAired && pep.EpisodeId < comparePep.EpisodeId); }
private string GetTargetEpisodeName([NotNull] ShowConfiguration show, [NotNull] Episode ep, bool urlEncode) { //note this is for an Episode and not a ProcessedEpisode string name = StyleString; string epname = ep.Name; name = name.ReplaceInsensitive("{ShowName}", show.ShowName); name = name.ReplaceInsensitive("{ShowNameLower}", show.ShowName.ToLower().Replace(' ', '-').RemoveCharactersFrom("()[]{}&$:")); name = name.ReplaceInsensitive("{ShowNameInitial}", show.ShowName.Initial().ToLower()); int seasonNumber; int episodeNumber; switch (show.Order) { case ProcessedSeason.SeasonType.dvd: seasonNumber = ep.DvdSeasonNumber; episodeNumber = ep.DvdEpNum; break; case ProcessedSeason.SeasonType.aired: seasonNumber = ep.AiredSeasonNumber; episodeNumber = ep.AiredEpNum; break; default: throw new ArgumentOutOfRangeException(); } string seasonName = show.CachedShow?.Season(seasonNumber)?.SeasonName; name = name.ReplaceInsensitive("{Season}", seasonNumber.ToString()); name = name.ReplaceInsensitive("{Season:2}", seasonNumber.ToString("00")); name = name.ReplaceInsensitiveLazy("{SeasonNumber}", new Lazy <string?>(() => show.GetSeasonIndex(seasonNumber).ToString()), StringComparison.CurrentCultureIgnoreCase); name = name.ReplaceInsensitiveLazy("{SeasonNumber:2}", new Lazy <string?>(() => show.GetSeasonIndex(seasonNumber).ToString("00")), StringComparison.CurrentCultureIgnoreCase); name = name.ReplaceInsensitive("{Episode}", episodeNumber.ToString("00")); name = name.ReplaceInsensitive("{Episode2}", episodeNumber.ToString("00")); name = Regex.Replace(name, "{AllEpisodes}", episodeNumber.ToString("00")); name = name.ReplaceInsensitive("{SeasonName}", seasonName ?? string.Empty); name = name.ReplaceInsensitive("{EpisodeName}", epname); name = name.ReplaceInsensitive("{Number}", ""); name = name.ReplaceInsensitive("{Number:2}", ""); name = name.ReplaceInsensitive("{Number:3}", ""); name = name.ReplaceInsensitive("{Imdb}", ep.ImdbCode ?? string.Empty); CachedSeriesInfo si = show.CachedShow; name = name.ReplaceInsensitive("{ShowImdb}", si?.Imdb ?? string.Empty); name = name.ReplaceInsensitiveLazy("{Year}", new Lazy <string?>(() => si?.MinYear.ToString() ?? string.Empty), StringComparison.CurrentCultureIgnoreCase); ProcessedSeason selectedProcessedSeason = show.GetSeason(ep.GetSeasonNumber(show.Order)); name = name.ReplaceInsensitive("{SeasonYear}", selectedProcessedSeason != null ? selectedProcessedSeason.MinYear().ToString() : string.Empty); name = ReplaceDates(urlEncode, name, ep.GetAirDateDt(show.GetTimeZone())); name = Regex.Replace(name, "([^\\\\])\\[.*?[^\\\\]\\]", "$1"); // remove optional parts name = name.Replace("\\[", "["); name = name.Replace("\\]", "]"); return(name.Trim()); }
public string GetTargetEpisodeName([NotNull] ShowConfiguration show, [NotNull] Episode ep) => GetTargetEpisodeName(show, ep, false);
public List<FileInfo> FindEpOnDisk(DirFilesCache dfc, ShowItem si, Episode epi) { if (dfc == null) dfc = new DirFilesCache(); List<FileInfo> ret = new List<FileInfo>(); int seasWanted = epi.TheSeason.SeasonNumber; int epWanted = epi.EpNum; int snum = epi.TheSeason.SeasonNumber; if (!si.AllFolderLocations().ContainsKey(snum)) return ret; foreach (string folder in si.AllFolderLocations()[snum]) { FileInfo[] files = dfc.Get(folder); if (files == null) continue; foreach (FileInfo fiTemp in files) { int seasFound; int epFound; if (!TVSettings.Instance.UsefulExtension(fiTemp.Extension, false)) continue; // move on if (FindSeasEp(fiTemp, out seasFound, out epFound, si)) { if (seasFound == -1) seasFound = seasWanted; if ((seasFound == seasWanted) && (epFound == epWanted)) ret.Add(fiTemp); } } } return ret; }
private void WriteEpisodeDetailsFor(Episode episode, XmlWriter writer, bool multi, bool dvdOrder) { // See: http://xbmc.org/wiki/?title=Import_-_Export_Library#TV_Episodes writer.WriteStartElement("episodedetails"); XMLHelper.WriteElementToXML(writer, "title", episode.Name); XMLHelper.WriteElementToXML(writer, "showtitle", this.Episode.SI.ShowName); XMLHelper.WriteElementToXML(writer, "rating", episode.EpisodeRating); if (dvdOrder) { XMLHelper.WriteElementToXML(writer, "season", episode.DVDSeasonNumber); XMLHelper.WriteElementToXML(writer, "episode", episode.DVDEpNum); } else { XMLHelper.WriteElementToXML(writer, "season", episode.AiredSeasonNumber); XMLHelper.WriteElementToXML(writer, "episode", episode.AiredEpNum); } XMLHelper.WriteElementToXML(writer, "plot", episode.Overview); writer.WriteStartElement("aired"); if (episode.FirstAired != null) { writer.WriteValue(episode.FirstAired.Value.ToString("yyyy-MM-dd")); } writer.WriteEndElement(); XMLHelper.WriteElementToXML(writer, "mpaa", this.Episode.SI?.TheSeries()?.GetContentRating(), true); //Director(s) string epDirector = episode.EpisodeDirector; if (!string.IsNullOrEmpty(epDirector)) { foreach (string daa in epDirector.Split('|')) { XMLHelper.WriteElementToXML(writer, "director", daa, true); } } //Writers(s) string epWriter = episode.Writer; if (!string.IsNullOrEmpty(epWriter)) { foreach (string txtWriter in epWriter.Split('|')) { XMLHelper.WriteElementToXML(writer, "credits", txtWriter, true); } } // Guest Stars... if (!String.IsNullOrEmpty(episode.EpisodeGuestStars)) { string recurringActors = ""; if (this.Episode.SI != null) { recurringActors = String.Join("|", this.Episode.SI.TheSeries().GetActors()); } string guestActors = episode.EpisodeGuestStars; if (!string.IsNullOrEmpty(guestActors)) { foreach (string gaa in guestActors.Split('|')) { if (string.IsNullOrEmpty(gaa)) { continue; } // Skip if the guest actor is also in the overal recurring list if (!string.IsNullOrEmpty(recurringActors) && recurringActors.Contains(gaa)) { continue; } writer.WriteStartElement("actor"); XMLHelper.WriteElementToXML(writer, "name", gaa); writer.WriteEndElement(); // actor } } } // actors... if (this.Episode.SI != null) { foreach (string aa in this.Episode.SI.TheSeries().GetActors()) { if (string.IsNullOrEmpty(aa)) { continue; } writer.WriteStartElement("actor"); XMLHelper.WriteElementToXML(writer, "name", aa); writer.WriteEndElement(); // actor } } if (multi) { writer.WriteStartElement("resume"); //we have to put 0 as we don't know where the multipart episode starts/ends XMLHelper.WriteElementToXML(writer, "position", 0); XMLHelper.WriteElementToXML(writer, "total", 0); writer.WriteEndElement(); // resume //For now we only put art in for multipart episodes. Kodi finds the art appropriately //without our help for the others ShowItem episodeSi = this.Episode.SI ?? this.SI; string filename = TVSettings.Instance.FilenameFriendly( TVSettings.Instance.NamingStyle.GetTargetEpisodeName(episode, episodeSi.ShowName, episodeSi.GetTimeZone(), episodeSi.DVDOrder)); string thumbFilename = filename + ".jpg"; XMLHelper.WriteElementToXML(writer, "thumb", thumbFilename); //Should be able to do this using the local filename, but only seems to work if you provide a URL //XMLHelper.WriteElementToXML(writer, "thumb", TheTVDB.Instance.GetTVDBDownloadURL(episode.GetFilename())); } writer.WriteEndElement(); // episodedetails }
public void AddEpisode([NotNull] Episode episode) { sourceEpisodes.TryAdd(episode.EpisodeId, episode); episode.SetSeriesSeason(this); }
public void GotoEpguideFor(Episode ep, bool changeTab) { if (changeTab) this.tabControl1.SelectTab(this.tbMyShows); this.SelectSeason(ep.TheSeason); }
public string GetTargetEpisodeName(ShowItem show, Episode ep, TimeZone tz, bool dvdOrder) => GetTargetEpisodeName(show, ep, tz, dvdOrder, false);