Ejemplo n.º 1
0
        private static string CreateHtml(ShowItem si)
        {
            string posterUrl      = TheTVDB.GetImageURL(si.TheSeries().GetImage(TVSettings.FolderJpgIsType.Poster));
            int    minYear        = si.TheSeries().MinYear();
            int    maxYear        = si.TheSeries().MaxYear();
            string yearRange      = (minYear == maxYear) ? minYear.ToString() : minYear + "-" + maxYear;
            string episodeSummary = si.TheSeries().AiredSeasons.Sum(pair => pair.Value.Episodes.Count).ToString();
            string stars          = ShowHtmlHelper.StarRating(si.TheSeries().GetSiteRating());
            string genreIcons     = string.Join(" ", si.TheSeries().GetGenres().Select(ShowHtmlHelper.GenreIconHtml));
            bool   ratingIsNumber = float.TryParse(si.TheSeries().GetSiteRating(), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite, CultureInfo.CreateSpecificCulture("en-US"), out float rating);
            string siteRating     = ratingIsNumber && rating > 0 ? rating + "/10" : "";

            return($@"<div class=""card card-body"">
            <div class=""row"">
            <div class=""col-md-4"">
                <img class=""show-poster rounded w-100"" src=""{posterUrl}"" alt=""{si.ShowName} Show Poster""></div>
            <div class=""col-md-8 d-flex flex-column"">
                <div class=""row"">
                    <div class=""col-md-8""><h1>{si.ShowName}</h1></div>
                    <div class=""col-md-4 text-right""><h6>{yearRange} ({si.TheSeries().GetStatus()})</h6><small class=""text-muted"">{episodeSummary} Episodes</small></div>
                </div>
            <div><blockquote>{si.TheSeries().GetOverview()}</blockquote></div>
            <div><blockquote>{string.Join(", ", si.TheSeries().GetActorNames())}</blockquote></div>
            <div class=""row align-items-bottom flex-grow-1"">
                <div class=""col-md-4 align-self-end"">{stars}<br>{siteRating}</div>
                <div class=""col-md-4 align-self-end text-center"">{si.TheSeries().GetContentRating()}<br>{si.TheSeries().GetNetwork()}</div>
                <div class=""col-md-4 align-self-end text-right"">{genreIcons}<br>{string.Join(", ", si.TheSeries().GetGenres())}</div>
            </div>
            </div></div></div>");
        }
Ejemplo n.º 2
0
        private static string CreateHtml([NotNull] ShowItem si)
        {
            SeriesInfo series = si.TheSeries();

            if (series is null)
            {
                return(string.Empty);
            }

            string posterUrl      = TheTVDB.GetImageURL(series.GetImage(TVSettings.FolderJpgIsType.Poster));
            string yearRange      = ShowHtmlHelper.YearRange(series);
            string episodeSummary = series.AiredSeasons.Sum(pair => pair.Value.Episodes.Count).ToString();
            string stars          = ShowHtmlHelper.StarRating(series.SiteRating / 2);
            string genreIcons     = string.Join("&nbsp;", series.Genres().Select(ShowHtmlHelper.GenreIconHtml));
            string siteRating     = series.SiteRating > 0 ? series.SiteRating + "/10" : "";

            return($@"<div class=""card card-body"">
            <div class=""row"">
            <div class=""col-md-4"">
                <img class=""show-poster rounded w-100"" src=""{posterUrl}"" alt=""{si.ShowName} Show Poster""></div>
            <div class=""col-md-8 d-flex flex-column"">
                <div class=""row"">
                    <div class=""col-md-8""><h1>{si.ShowName}</h1></div>
                    <div class=""col-md-4 text-right""><h6>{yearRange} ({series.Status})</h6><small class=""text-muted"">{episodeSummary} Episodes</small></div>
                </div>
            <div><blockquote>{series.Overview}</blockquote></div>
            <div><blockquote>{string.Join(", ", series.GetActorNames())}</blockquote></div>
            <div class=""row align-items-bottom flex-grow-1"">
                <div class=""col-md-4 align-self-end"">{stars}<br>{siteRating}</div>
                <div class=""col-md-4 align-self-end text-center"">{series.ContentRating}<br>{series.Network}</div>
                <div class=""col-md-4 align-self-end text-right"">{genreIcons}<br>{string.Join(", ", series.Genres())}</div>
            </div>
            </div></div></div>");
        }
Ejemplo n.º 3
0
 private static string CreatePosterHtml(SeriesInfo ser)
 {
     if ((!string.IsNullOrEmpty(ser.GetSeriesPosterPath())) &&
         (!string.IsNullOrEmpty(TheTVDB.GetImageURL(ser.GetSeriesPosterPath()))))
     {
         return($"<img class=\"show-poster rounded w-100\" src=\"{TheTVDB.GetImageURL(ser.GetSeriesPosterPath())}\" alt=\"{ser.Name} Show Poster\">");
     }
     return(string.Empty);
 }
Ejemplo n.º 4
0
        private static string CreateHorizontalBannerHtml([NotNull] this Season s)
        {
            if ((!string.IsNullOrEmpty(s.GetWideBannerPath())) &&
                (!string.IsNullOrEmpty(TheTVDB.GetImageURL(s.GetWideBannerPath()))))
            {
                return($"<img class=\"rounded w-100\" src=\"{TheTVDB.GetImageURL(s.GetWideBannerPath())}\"><br/>");
            }

            return(string.Empty);
        }
Ejemplo n.º 5
0
        private static string CreateHorizontalBannerHtml([NotNull] SeriesInfo ser)
        {
            if ((!string.IsNullOrEmpty(ser.GetSeriesWideBannerPath())) &&
                (!string.IsNullOrEmpty(TheTVDB.GetImageURL(ser.GetSeriesWideBannerPath()))))
            {
                return($"<img class=\"rounded\" src=\"{TheTVDB.GetImageURL(ser.GetSeriesWideBannerPath())}\"><br/>&nbsp;");
            }

            return(string.Empty);
        }
Ejemplo n.º 6
0
        private static string ImageSection(string title, int width, int height, [CanBeNull] string bannerPath)
        {
            if (string.IsNullOrEmpty(bannerPath))
            {
                return("");
            }

            string url = TheTVDB.GetImageURL(bannerPath);

            return(string.IsNullOrEmpty(url) ? "" : $"<h2>{title}</h2><img width={width} height={height} src=\"{url}\"><br/>");
        }
Ejemplo n.º 7
0
        private static string ScreenShotHtml(this ProcessedEpisode ei)
        {
            if (!TVSettings.Instance.ShowEpisodePictures)
            {
                return(string.Empty);
            }
            if (TVSettings.Instance.HideMyShowsSpoilers && ei.HowLong() != "Aired")
            {
                return(string.Empty);
            }
            if (string.IsNullOrEmpty(ei.Filename))
            {
                return(string.Empty);
            }
            if (string.IsNullOrWhiteSpace(TheTVDB.GetImageURL(ei.Filename)))
            {
                return(string.Empty);
            }

            return($"<img class=\"rounded w-100\" src=\"{TheTVDB.GetImageURL(ei.Filename)}\" alt=\"{ei.Name} Screenshot\">");
        }
Ejemplo n.º 8
0
        public static string GetSeasonHtmlOverviewOffline([NotNull] this ShowItem si, [NotNull] Season s)
        {
            SeriesInfo ser  = s.TheSeries;
            int        snum = s.SeasonNumber;
            string     body = "";

            if (!string.IsNullOrEmpty(ser.GetSeriesWideBannerPath()) &&
                !string.IsNullOrEmpty(TheTVDB.GetImageURL(ser.GetSeriesWideBannerPath())))
            {
                body += "<img width=758 height=140 src=\"" + TheTVDB.GetImageURL(ser.GetSeriesWideBannerPath()) +
                        "\"><br/>";
            }

            List <ProcessedEpisode> eis = si.SeasonEpisodes.ContainsKey(snum) ?
                                          si.SeasonEpisodes[snum] :
                                          ShowItem.ProcessedListFromEpisodes(s.Episodes.Values, si);

            string seasText = SeasonName(si, snum);

            if ((eis.Count > 0) && (eis[0].SeasonId > 0))
            {
                seasText = " - <A HREF=\"" + TheTVDB.Instance.WebsiteUrl(ser.TvdbCode, eis[0].SeasonId, false) + "\">" +
                           seasText + "</a>";
            }
            else
            {
                seasText = " - " + seasText;
            }

            body += "<h1><A HREF=\"" + TheTVDB.Instance.WebsiteUrl(si.TvdbCode, -1, true) + "\">" + si.ShowName +
                    "</A>" + seasText + "</h1>";

            DirFilesCache dfc = new DirFilesCache();

            foreach (ProcessedEpisode ei in eis)
            {
                string epl = ei.NumsAsString();

                string episodeUrl = TheTVDB.Instance.WebsiteUrl(ei.SeriesId, ei.SeasonId, ei.EpisodeId);

                body += "<A href=\"" + episodeUrl + "\" name=\"ep" + epl + "\">"; // anchor
                if (si.DvdOrder && snum == 0)
                {
                    body += "<b>" + ei.Name + "</b>";
                }
                else
                {
                    body += "<b>" + HttpUtility.HtmlEncode(CustomEpisodeName.NameForNoExt(ei, CustomEpisodeName.OldNStyle(6))) +
                            "</b>";
                }

                body += "</A>"; // anchor
                if (si.UseSequentialMatch && (ei.OverallNumber != -1))
                {
                    body += " (#" + ei.OverallNumber + ")";
                }

                List <FileInfo> fl = dfc.FindEpOnDisk(ei);
                if (fl.Count > 0)
                {
                    foreach (FileInfo fi in fl)
                    {
                        string urlFilename = HttpUtility.UrlEncode(fi.FullName);
                        body += $" <A HREF=\"watch://{urlFilename}\" class=\"search\">Watch</A>";
                        body += $" <A HREF=\"explore://{urlFilename}\" class=\"search\">Show in Explorer</A>";
                    }
                }
                else
                {
                    body += " <A HREF=\"" + TVSettings.Instance.BTSearchURL(ei) + "\" class=\"search\">Search</A>";
                }

                DateTime?dt = ei.GetAirDateDt(true);
                if ((dt != null) && (dt.Value.CompareTo(DateTime.MaxValue) != 0))
                {
                    body += "<p>" + dt.Value.ToShortDateString() + " (" + ei.HowLong() + ")";
                }

                body += "<p><p>";

                if ((TVSettings.Instance.ShowEpisodePictures) ||
                    (TVSettings.Instance.HideMyShowsSpoilers && ei.HowLong() != "Aired"))
                {
                    body += "<table><tr>";
                    body += "<td width=100% valign=top>" + GetOverview(ei) + "</td><td width=300 height=225>";
                    // 300x168 / 300x225
                    if (!string.IsNullOrEmpty(ei.Filename))
                    {
                        body += "<img src=" + TheTVDB.GetImageURL(ei.Filename) + ">";
                    }

                    body += "</td></tr></table>";
                }
                else
                {
                    body += GetOverview(ei);
                }

                body += "<p><hr><p>";
            } // for each episode in this season

            return(body);
        }
Ejemplo n.º 9
0
        public static string GetShowHtmlOverviewOffline([NotNull] this ShowItem si)
        {
            string     body = "";
            SeriesInfo ser  = si.TheSeries();

            if ((!string.IsNullOrEmpty(ser?.GetSeriesWideBannerPath())) &&
                (!string.IsNullOrEmpty(TheTVDB.GetImageURL(ser.GetSeriesWideBannerPath()))))
            {
                body += "<img width=758 height=140 src=\"" + TheTVDB.GetImageURL(ser.GetSeriesWideBannerPath()) +
                        "\"><br/>";
            }

            body += $"<h1><A HREF=\"{TheTVDB.Instance.WebsiteUrl(si.TvdbCode, -1, true)}\">{si.ShowName}</A> </h1>";

            body += "<h2>Overview</h2>" + ser?.Overview; //get overview in either format

            bool first = true;

            foreach (Actor aa in si.Actors.Where(aa => !string.IsNullOrEmpty(aa.ActorName)))
            {
                body += first ? "<h2>Actors</h2>" : ", ";

                body += "<A HREF=\"http://www.imdb.com/find?s=nm&q=" + aa.ActorName + "\">" + aa.ActorName + $"</a> as {aa.ActorRole}";
                first = false;
            }

            string airsTime = ser?.AirsTime.PrettyPrint();
            string airsDay  = ser?.AirsDay;

            if ((!string.IsNullOrEmpty(airsTime)) && (!string.IsNullOrEmpty(airsDay)))
            {
                body += "<h2>Airs</h2> " + airsTime + " " + airsDay;
                string net = ser.Network;
                if (!string.IsNullOrEmpty(net))
                {
                    body += ", " + net;
                }
            }

            string yearRange = YearRange(ser);

            string siteRating = ser?.SiteRating > 0 ? ser.SiteRating + "/10" : string.Empty;
            string tvdbLink   = TheTVDB.Instance.WebsiteUrl(si.TvdbCode, -1, true);

            string tableHtml = string.Empty;

            tableHtml += GetOverviewPart("thetvdb.com", $"<A HREF=\"{tvdbLink}\">Visit</a>");
            tableHtml += GetOverviewPart("imdb.com", "<A HREF=\"http://www.imdb.com/title/" + ser?.Imdb + "\">Visit</a>");
            tableHtml += GetOverviewPart("tv.com", "<A HREF=\"http://www.tv.com/show/" + ser?.SeriesId + "/summary.html\">Visit</a>");
            tableHtml += GetOverviewPart("Runtime", ser?.Runtime);
            tableHtml += GetOverviewPart("Aliases", string.Join(", ", si.AliasNames));
            tableHtml += GetOverviewPart("Genres", string.Join(", ", si.Genres));
            tableHtml += GetOverviewPart("Rating", ser?.ContentRating);
            tableHtml += GetOverviewPart("User Rating", $"{siteRating}{AddRatingCount(ser?.SiteRatingVotes??0)}");
            tableHtml += GetOverviewPart("Active From", yearRange);
            tableHtml += GetOverviewPart("Status", ser?.Status);

            if (!string.IsNullOrWhiteSpace(tableHtml))
            {
                body += "<h2>Information<table border=0>" + tableHtml + "</table>";
            }

            return(body);
        }
Ejemplo n.º 10
0
        private bool WriteEpisodeMetaDataFile()
        {
            // "try" and silently fail.  eg. when file is use by other...
            try
            {
                XmlWriterSettings settings = new XmlWriterSettings
                {
                    Indent = true,
                    NewLineOnAttributes = true,
                };

                using (XmlWriter writer = XmlWriter.Create(Where.FullName, settings))
                {
                    writer.WriteStartElement("details");
                    writer.WriteElement("title", TVSettings.Instance.NamingStyle.NameFor(Episode));
                    writer.WriteElement("mpaa", Episode.TheSeries.ContentRating);

                    if (Episode.FirstAired.HasValue)
                    {
                        writer.WriteElement("year", Episode.FirstAired.Value.ToString("yyyy-MM-dd"));
                        writer.WriteElement("firstaired",
                                            Episode.FirstAired.Value.ToString("yyyy-MM-dd"));
                    }

                    writer.WriteElement("runtime", Episode.TheSeries.Runtime, true);
                    writer.WriteElement("rating", Episode.EpisodeRating);
                    writer.WriteElement("studio", Episode.TheSeries.Network);
                    writer.WriteElement("plot", Episode.TheSeries.Overview);
                    writer.WriteElement("overview", Episode.Overview);
                    foreach (string director in Episode.Directors)
                    {
                        writer.WriteElement("directors", director);
                    }

                    foreach (string epwriter in Episode.Writers)
                    {
                        writer.WriteElement("writers", epwriter);
                    }

                    foreach (string genre in Episode.TheSeries.Genres())
                    {
                        writer.WriteElement("genre", genre);
                    }

                    // actors...
                    foreach (Actor aa in Episode.TheSeries.GetActors())
                    {
                        if (string.IsNullOrEmpty(aa.ActorName))
                        {
                            continue;
                        }

                        writer.WriteStartElement("actor");
                        writer.WriteElement("name", aa.ActorName);
                        writer.WriteElement("role", aa.ActorRole);
                        writer.WriteEndElement(); // actor
                    }

                    // guest stars...
                    foreach (string guest in Episode.GuestStars)
                    {
                        writer.WriteElement("guest", guest);
                    }

                    writer.WriteElement("thumbnail", TheTVDB.GetImageURL(Episode.Filename));
                    writer.WriteElement("banner", TheTVDB.GetImageURL(Episode.AppropriateSeason.GetWideBannerPath()));
                    writer.WriteElement("backdrop", TheTVDB.GetImageURL(Episode.TheSeries.GetSeriesFanartPath()));
                    writer.WriteEndElement(); // details
                }
                Done = true;
                return(true);
            }
            catch (Exception e)
            {
                ErrorText = e.Message;
                Error     = true;
                Done      = true;
                return(false);
            }
        }
Ejemplo n.º 11
0
        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);

            writer.WriteElement("id", episode.EpisodeId);

            writer.WriteStartElement("uniqueid");
            writer.WriteAttributeString("type", "tvdb");
            writer.WriteAttributeString("default", "true");
            writer.WriteValue(episode.EpisodeId);
            writer.WriteEndElement();

            if (!string.IsNullOrEmpty(episode.ImdbCode))
            {
                writer.WriteStartElement("uniqueid");
                writer.WriteAttributeString("type", "imdb");
                writer.WriteAttributeString("default", "false");
                writer.WriteValue(episode.ImdbCode);
                writer.WriteEndElement();
            }

            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", TheTVDB.GetImageURL(aa.ActorImage), true);
                    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
        }
Ejemplo n.º 12
0
        private void WriteSeriesXmlFile([NotNull] XmlWriter writer)
        {
            SeriesInfo series = SelectedShow.TheSeries();

            // https://kodi.wiki/view/NFO_files/TV_shows
            writer.WriteStartElement("tvshow");

            writer.WriteElement("title", SelectedShow.ShowName);
            writer.WriteElement("originaltitle", series?.Name);
            writer.WriteElement("studio", series?.Network);
            float?showRating = series?.SiteRating;

            if (showRating.HasValue)
            {
                writer.WriteStartElement("ratings");

                writer.WriteStartElement("rating");
                writer.WriteAttributeString("name", "tvdb");
                writer.WriteAttributeString("max", "10");
                writer.WriteAttributeString("default", "true");

                writer.WriteElement("value", showRating.Value);
                writer.WriteElement("votes", series.SiteRatingVotes, true);

                writer.WriteEndElement(); //rating

                writer.WriteEndElement(); //ratings
            }

            string lang = TVSettings.Instance.PreferredLanguageCode;

            if (SelectedShow.UseCustomLanguage && SelectedShow.PreferredLanguage != null)
            {
                lang = SelectedShow.PreferredLanguage.Abbreviation;
            }

            //https://forum.kodi.tv/showthread.php?tid=323588
            //says that we need a format like this:
            //<episodeguide><url post="yes" cache="auth.json">https://api.thetvdb.com/login?{&quot;apikey&quot;:&quot;((API-KEY))&quot;,&quot;id&quot;:((ID))}|Content-Type=application/json</url></episodeguide>

            writer.WriteStartElement("episodeguide");
            writer.WriteStartElement("url");
            writer.WriteAttributeString("post", "yes");
            writer.WriteAttributeString("cache", "auth.json");
            writer.WriteRaw(TheTVDB.BuildUrl(SelectedShow.TvdbCode, lang));
            writer.WriteEndElement(); //url
            writer.WriteEndElement(); //episodeguide

            if (!(series is null))
            {
                writer.WriteElement("id", series.TvdbCode);
                writer.WriteElement("runtime", series.Runtime, true);
                writer.WriteElement("mpaa", series.ContentRating, true);

                writer.WriteStartElement("uniqueid");
                writer.WriteAttributeString("type", "tvdb");
                writer.WriteAttributeString("default", "true");
                writer.WriteValue(series.TvdbCode);
                writer.WriteEndElement();

                writer.WriteStartElement("uniqueid");
                writer.WriteAttributeString("type", "imdb");
                writer.WriteAttributeString("default", "false");
                writer.WriteValue(series.Imdb);
                writer.WriteEndElement();

                writer.WriteElement("plot", series.Overview);

                writer.WriteElement("premiered", series.FirstAired);
                writer.WriteElement("year", series.Year);
                writer.WriteElement("status", series.Status);
            }

            writer.WriteStringsToXml("genre", SelectedShow.Genres);

            // actors...
            foreach (Actor aa in SelectedShow.Actors.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", TheTVDB.GetImageURL(aa.ActorImage), true);
                writer.WriteEndElement(); // actor
            }

            writer.WriteEndElement(); // tvshow
        }