Пример #1
0
		static void Main(string[] args)
		{



			var saveToFile = false;

			try
			{
				EventLog.WriteEntry(SSource, "Starting Tvzon...", EventLogEntryType.Information);
			}
			catch (Exception)
			{
			}

			var path = Properties.Settings.Default.OutputPath;
			var days = Properties.Settings.Default.Days;
			var channels = Properties.Settings.Default.Channels;
			var daysInHistory = Properties.Settings.Default.DaysInHistory;
			var previousShownDuration = Properties.Settings.Default.PreviousShownDuration;
			var insertEpisodeInDesc = Properties.Settings.Default.InsertEpisodeInDesc;



			var dirName = Path.Combine(Environment.GetEnvironmentVariable("PROGRAMDATA"), "Tvzon");
			if (!Directory.Exists(dirName))
				Directory.CreateDirectory(dirName);

			var logPath = Path.Combine(dirName, "log.txt");

			var cacheLocation = Path.Combine(dirName, "temp.xml");


			using (_logwriter = (Properties.Settings.Default.WriteToLog ? new StreamWriter(logPath, false) : null))
			{

				if (String.IsNullOrEmpty(path))
				{
					HandleException("Invalid path");
					return;
				}
				if (channels.Count == 0)
				{
					HandleException("No channels specified.");
					return;
				}
				var dir = Path.GetDirectoryName(path);
				if (!Directory.Exists(dir))
				{
					HandleException(String.Format("Directory '{0}' does not exist.", dir));
					return;
				}
				if (days < 0)
					days = 0;

				if (daysInHistory < 1)
					daysInHistory = 1;

				if (previousShownDuration < 0)
					previousShownDuration = 0;


				var url = Settings.Default.ChannelsUrl ?? "http://xmltv.xmltv.se/channels-Sweden.xml.gz";
				//const string ApiChannelsUrl = "http://api.tvtab.la/channels.xml";
				var ChannelsLastModifiedUrl = Settings.Default.ChannelsLastModifiedUrl ?? "http://xmltv.xmltv.se/datalist.xml.gz";


				XmlDocument domInput;
				var domOutput = new XmlDocument();
				XmlDocument tempDom;
				var cacheDom = new XmlDocument();
				//XmlDocument apiChannelsDom;
				XmlDocument lastModifiedDom;


				var channelSettings = new ChannelSettings();

				if (!string.IsNullOrEmpty(Settings.Default.ChannelSettings))
					channelSettings = JsonConvert.DeserializeObject<ChannelSettings>(Settings.Default.ChannelSettings, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });
				


				cacheDom.XmlResolver = domOutput.XmlResolver = null;

				var cachedIcons = Properties.Settings.Default.ImageCache;
				if (cachedIcons == null)
					cachedIcons = new SerializableStringDictionary();
				//domOutput.PreserveWhitespace = true;
				WriteToLog("Loading Cache History...");
				if (File.Exists(cacheLocation) && daysInHistory > 0)
					cacheDom.Load(cacheLocation);

				if (cacheDom.DocumentElement == null)
					cacheDom.LoadXml("<tv generator-info-name=\"nonametv\" />");

				domOutput.LoadXml("<tv generator-info-name=\"nonametv\" />");
				WriteToLog("Retrieving channels from '{0}'...", url);
				try
				{
					domInput = GetWebResponseDom(url);
				}
				catch (Exception ex)
				{
					HandleException(ex);
					return;

				}

				WriteToLog("Retrieving channels last modified from '{0}'...", ChannelsLastModifiedUrl);
				try
				{
					lastModifiedDom = GetWebResponseDom(ChannelsLastModifiedUrl);
				}
				catch (Exception ex)
				{
					HandleException(ex);
					return;

				}

				//WriteToLog("Retrieving channels from '{0}'...", ApiChannelsUrl);
				//try
				//{
				//	apiChannelsDom = GetWebResponseDom(ApiChannelsUrl);
				//}
				//catch (Exception ex)
				//{
				//	HandleException(ex);
				//	//return;
				//	apiChannelsDom = new XmlDocument(); 
						
				//}


				var nodes = cacheDom.SelectNodes("tv/channel");
				foreach (XmlElement element in nodes)
				{
					element.ParentNode.RemoveChild(element);
				}

				nodes = cacheDom.SelectNodes("tv/programme");
				foreach (XmlElement programme in nodes)
				{
					var startString = programme.GetAttribute("start");
					var start = DateTime.MinValue;
					if (!String.IsNullOrEmpty(startString) && startString.Length >= 14)
					{
						startString = FixDateString(startString);
						DateTime.TryParse(startString, out start);
					}
					var daysCount = (int)(Today - start.Date).TotalDays;
					if (daysCount < 1 || daysCount > daysInHistory)
					{
						var titleNode = programme.SelectSingleNode("title/text()");
						if (daysCount < 1)
						{
							var lastModified = programme.GetAttribute("lastmodified");
							var programmeDay = programme.GetAttribute("programmeday");
							if (lastModified != String.Empty && programmeDay != String.Empty)
							{
								var lastModifiedNode =
									lastModifiedDom.SelectSingleNode(String.Format("/*/channel[@id={0}]/datafor[text()={1}]/@lastmodified",
																				   XPathEncode(programme.GetAttribute("channel")),
																				   XPathEncode(programmeDay)));
								if (lastModifiedNode != null && lastModifiedNode.Value == lastModified)
								{
									if (titleNode != null)
										WriteToLog("Program '{0}' on channel '{1}' found in cache...", titleNode.Value, programme.GetAttribute("channel"));
									continue;
								}
							}
						}

						if (titleNode != null)
							WriteToLog("Deleting program '{0}' on channel '{1}' in cache...", titleNode.Value, programme.GetAttribute("channel"));
						programme.ParentNode.RemoveChild(programme);
					}
				}


				nodes = domInput.SelectNodes("tv/channel");
				foreach (XmlElement element in nodes)
				{
					var id = element.GetAttribute("id");
					if (channels.Contains(id))
					{
						var channelName = id;
						var titleNode = element.SelectSingleNode("display-name");
						if (titleNode != null)
							channelName = titleNode.InnerText;

						cacheDom.DocumentElement.InsertBefore(cacheDom.ImportNode(element, true), cacheDom.DocumentElement.FirstChild);

						domOutput.DocumentElement.AppendChild(domOutput.ImportNode(element, true));
						WriteToLog("Added channel '{0}'.", channelName);
						// var apiChannelNode =
						//	apiChannelsDom.SelectSingleNode(String.Format("/*/channels/channel[tvuri={0}]/handle/text()", XPathEncode(id)));
						//if (apiChannelNode != null)
						//	ApiChannelsCache.Add(id, apiChannelNode.Value);
						//if (apiChannelNode == null && id.Contains('-') && id.Contains('.'))
						//{
						//	var idStringEnd = id;
						//	var idPart = idStringEnd.Substring(0, idStringEnd.IndexOf('.'));
						//	idStringEnd = idStringEnd.Substring(idStringEnd.IndexOf('.'));
						//	var newId = String.Empty;
						//	foreach (var sId in idPart.Split('-'))
						//	{
						//		apiChannelNode =
						//			apiChannelsDom.SelectSingleNode(String.Format("/*/channels/channel[tvuri={0}]/handle/text()",
						//														  XPathEncode(sId + idStringEnd)));
						//		if (apiChannelNode != null)
						//		{
						//			if (!String.IsNullOrEmpty(newId))
						//				newId += ";";
						//			newId += apiChannelNode.Value;
						//		}
						//	}
						//	if (!String.IsNullOrEmpty(newId))
						//		ApiChannelsCache.Add(id, newId);
						//}

					}
				}


				nodes = domOutput.SelectNodes("tv/channel");
				foreach (XmlElement element in nodes)
				{
					var id = element.GetAttribute("id");
					var channelName = id;
					var titleNode = element.SelectSingleNode("display-name");
					if (titleNode != null)
						channelName = titleNode.InnerText;

					if (channels.Contains(id))
					{
						for (var i = 0; i < days; i++)
						{
							var date = Today.AddDays(i);
							var cacheNodes =
								cacheDom.SelectNodes(String.Format("tv/programme[@channel={0} and @programmeday='{1:yyyy-MM-dd}']",
																   XPathEncode(id), date));
							if (cacheNodes.Count > 0)
							{
								foreach (XmlElement programme in cacheNodes)
								{
									var clone = (XmlElement)domOutput.ImportNode(programme, true);
									domOutput.DocumentElement.AppendChild(clone);
								}
								continue;
							}

							if (!IsProgrammeModified(id, date, lastModifiedDom, cacheDom))
								continue;


							var channelUrl = String.Format(Settings.Default.ChannelUrl ?? "http://xmltv.xmltv.se/{0}_{1:yyyy-MM-dd}.xml.gz", id, date);
							WriteToLog("Retrieving xmltv from '{0}'...", channelUrl);
							try
							{
								tempDom = GetWebResponseDom(channelUrl);
								saveToFile = true;
							}
							catch (Exception ex)
							{
								HandleException(ex);
								return;
							}
							var programmeNodes = tempDom.SelectNodes("tv/programme");

							var channel = channelSettings.Channels.FirstOrDefault(x => String.Equals(x.ChannelId, id));

							foreach (XmlElement programme in programmeNodes)
							{

								var programName = "";
								titleNode = programme.SelectSingleNode("title");
								if (titleNode != null)
									programName = titleNode.InnerText;
								var start = DateTime.MinValue;
								var startString = programme.GetAttribute("start");
								if (!String.IsNullOrEmpty(startString) && startString.Length >= 14)
								{
									startString = FixDateString(startString);
									DateTime.TryParse(startString, out start);
								}


								if (channel != null)
								{
									var timeRange = channel.GetTimeRange(date);
									if (!(start.TimeOfDay >= timeRange.Start && start.TimeOfDay < timeRange.End))
									{

										WriteToLog("Program '{0}' '{1}' was out of range '{2}-{3}' day '{4}' on channel '{5}'.", programName, start.TimeOfDay, timeRange.Start, timeRange.End, date.DayOfWeek, channelName);
										continue;
									}
									
								}

								WriteToLog("Added program '{0}' on channel '{1}'.", programName, channelName);
								var imgUrl = "";
								var programUrl = "";
								var urlNode = programme.SelectSingleNode("url");
								if (urlNode != null)
								{
									programUrl = urlNode.InnerText;

								}
								var cacheKey = programUrl;
								if (String.IsNullOrEmpty(cacheKey))
									cacheKey = string.Format("{0}_{1}", id, programName);

								if (cachedIcons.ContainsKey(cacheKey))
									imgUrl = cachedIcons[cacheKey];
								try
								{
									if (String.IsNullOrEmpty(imgUrl) && !EmptyImageCache.Contains(cacheKey))
										imgUrl = GetProgramIcon(id, i, programName, programUrl, start);
								}
								catch (Exception ex)
								{
									//HandleException(ex);
									//return;
								}
								if (!String.IsNullOrEmpty(imgUrl))
								{
									var iconNode = tempDom.CreateElement("icon");
									iconNode.SetAttribute("src", imgUrl);
									programme.AppendChild(iconNode);
									if (!cachedIcons.ContainsKey(cacheKey))
										cachedIcons.Add(cacheKey, imgUrl);
									WriteToLog("Added program icon '{0}' for program '{1}' on channel '{2}'.", imgUrl, programName, channelName);
								}
								else
									EmptyImageCache.Add(cacheKey);


								foreach (XmlElement node in programme.SelectNodes("star-rating/value"))
									node.InnerText = FixRating(node.InnerText);

								FixEpisodeNum(programme, insertEpisodeInDesc);

								foreach (XmlElement node in programme.SelectNodes("category"))
									FixCategory(node);

								if (id.IndexOf("hd", StringComparison.InvariantCultureIgnoreCase) == -1)
								{
									var qualityNode = programme.SelectSingleNode("video/quality");
									if (qualityNode != null)
										qualityNode.ParentNode.RemoveChild(qualityNode);
								}
								if (daysInHistory > 0)
								{
									var lastModifiedNode =
										lastModifiedDom.SelectSingleNode(
											String.Format("/*/channel[@id={0}]/datafor[text()='{1:yyyy-MM-dd}']/@lastmodified", XPathEncode(id), date));
									var cacheClone = (XmlElement)cacheDom.ImportNode(programme, true);
									if (lastModifiedNode != null)
									{
										cacheClone.SetAttribute("programmeday", date.ToString("yyyy-MM-dd"));
										cacheClone.SetAttribute("lastmodified", lastModifiedNode.Value);
									}

									cacheDom.DocumentElement.AppendChild(cacheClone);

								}
								domOutput.DocumentElement.AppendChild(domOutput.ImportNode(programme, true));
							}
						}
					}


				}
				if (daysInHistory > 0)
				{
					PreviousShown(domOutput, cacheDom, previousShownDuration);
					SaveHistory(cacheDom, lastModifiedDom, days, channels);
				}

//#if DEBUG
//                var list = new List<string>();
//                var tempNodes = cacheDom.SelectNodes("//category/text()");
//                foreach (XmlNode node in tempNodes)
//                    if (!list.Contains(node.Value))
//                        list.Add(node.Value);

//                Debug.Print(String.Join(Environment.NewLine, list));
//#endif

				try
				{
					if (saveToFile || !File.Exists(path))
					{
						domOutput.Save(path);
						if (cachedIcons.Count > 50000)
							cachedIcons = null;
						Properties.Settings.Default.ImageCache = cachedIcons;
						Properties.Settings.Default.Save();


						cacheDom.Save(cacheLocation);
					}
					else
						WriteToLog("No changes found, ignoring write to file...");
				}
				catch (Exception ex)
				{
					HandleException(ex);
					return;
				}

				WriteToLog("Done!");
				try
				{
					EventLog.WriteEntry(SSource, "Tvzon has successfully ended.", EventLogEntryType.Information);
				}
				catch (Exception)
				{
				}
			}
			//Thread.Sleep(2000);
		}
Пример #2
0
        static void Main(string[] args)
        {
            var saveToFile = false;

            try
            {
                EventLog.WriteEntry(SSource, "Starting Tvzon...", EventLogEntryType.Information);
            }
            catch (Exception)
            {
            }

            var path                  = Properties.Settings.Default.OutputPath;
            var days                  = Properties.Settings.Default.Days;
            var channels              = Properties.Settings.Default.Channels;
            var daysInHistory         = Properties.Settings.Default.DaysInHistory;
            var previousShownDuration = Properties.Settings.Default.PreviousShownDuration;
            var insertEpisodeInDesc   = Properties.Settings.Default.InsertEpisodeInDesc;



            var dirName = Path.Combine(Environment.GetEnvironmentVariable("PROGRAMDATA"), "Tvzon");

            if (!Directory.Exists(dirName))
            {
                Directory.CreateDirectory(dirName);
            }

            var logPath = Path.Combine(dirName, "log.txt");

            var cacheLocation = Path.Combine(dirName, "temp.xml");


            using (_logwriter = (Properties.Settings.Default.WriteToLog ? new StreamWriter(logPath, false) : null))
            {
                if (String.IsNullOrEmpty(path))
                {
                    HandleException("Invalid path");
                    return;
                }
                if (channels.Count == 0)
                {
                    HandleException("No channels specified.");
                    return;
                }
                var dir = Path.GetDirectoryName(path);
                if (!Directory.Exists(dir))
                {
                    HandleException(String.Format("Directory '{0}' does not exist.", dir));
                    return;
                }
                if (days < 0)
                {
                    days = 0;
                }

                if (daysInHistory < 1)
                {
                    daysInHistory = 1;
                }

                if (previousShownDuration < 0)
                {
                    previousShownDuration = 0;
                }


                var url = Settings.Default.ChannelsUrl ?? "http://xmltv.xmltv.se/channels-Sweden.xml.gz";
                //const string ApiChannelsUrl = "http://api.tvtab.la/channels.xml";
                var ChannelsLastModifiedUrl = Settings.Default.ChannelsLastModifiedUrl ?? "http://xmltv.xmltv.se/datalist.xml.gz";


                XmlDocument domInput;
                var         domOutput = new XmlDocument();
                XmlDocument tempDom;
                var         cacheDom = new XmlDocument();
                //XmlDocument apiChannelsDom;
                XmlDocument lastModifiedDom;


                var channelSettings = new ChannelSettings();

                if (!string.IsNullOrEmpty(Settings.Default.ChannelSettings))
                {
                    channelSettings = JsonConvert.DeserializeObject <ChannelSettings>(Settings.Default.ChannelSettings, new JsonSerializerSettings {
                        ContractResolver = new CamelCasePropertyNamesContractResolver()
                    });
                }



                cacheDom.XmlResolver = domOutput.XmlResolver = null;

                var cachedIcons = Properties.Settings.Default.ImageCache;
                if (cachedIcons == null)
                {
                    cachedIcons = new SerializableStringDictionary();
                }
                //domOutput.PreserveWhitespace = true;
                WriteToLog("Loading Cache History...");
                if (File.Exists(cacheLocation) && daysInHistory > 0)
                {
                    cacheDom.Load(cacheLocation);
                }

                if (cacheDom.DocumentElement == null)
                {
                    cacheDom.LoadXml("<tv generator-info-name=\"nonametv\" />");
                }

                domOutput.LoadXml("<tv generator-info-name=\"nonametv\" />");
                WriteToLog("Retrieving channels from '{0}'...", url);
                try
                {
                    domInput = GetWebResponseDom(url);
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                    return;
                }

                WriteToLog("Retrieving channels last modified from '{0}'...", ChannelsLastModifiedUrl);
                try
                {
                    lastModifiedDom = GetWebResponseDom(ChannelsLastModifiedUrl);
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                    return;
                }

                //WriteToLog("Retrieving channels from '{0}'...", ApiChannelsUrl);
                //try
                //{
                //	apiChannelsDom = GetWebResponseDom(ApiChannelsUrl);
                //}
                //catch (Exception ex)
                //{
                //	HandleException(ex);
                //	//return;
                //	apiChannelsDom = new XmlDocument();

                //}


                var nodes = cacheDom.SelectNodes("tv/channel");
                foreach (XmlElement element in nodes)
                {
                    element.ParentNode.RemoveChild(element);
                }

                nodes = cacheDom.SelectNodes("tv/programme");
                foreach (XmlElement programme in nodes)
                {
                    var startString = programme.GetAttribute("start");
                    var start       = DateTime.MinValue;
                    if (!String.IsNullOrEmpty(startString) && startString.Length >= 14)
                    {
                        startString = FixDateString(startString);
                        DateTime.TryParse(startString, out start);
                    }
                    var daysCount = (int)(Today - start.Date).TotalDays;
                    if (daysCount < 1 || daysCount > daysInHistory)
                    {
                        var titleNode = programme.SelectSingleNode("title/text()");
                        if (daysCount < 1)
                        {
                            var lastModified = programme.GetAttribute("lastmodified");
                            var programmeDay = programme.GetAttribute("programmeday");
                            if (lastModified != String.Empty && programmeDay != String.Empty)
                            {
                                var lastModifiedNode =
                                    lastModifiedDom.SelectSingleNode(String.Format("/*/channel[@id={0}]/datafor[text()={1}]/@lastmodified",
                                                                                   XPathEncode(programme.GetAttribute("channel")),
                                                                                   XPathEncode(programmeDay)));
                                if (lastModifiedNode != null && lastModifiedNode.Value == lastModified)
                                {
                                    if (titleNode != null)
                                    {
                                        WriteToLog("Program '{0}' on channel '{1}' found in cache...", titleNode.Value, programme.GetAttribute("channel"));
                                    }
                                    continue;
                                }
                            }
                        }

                        if (titleNode != null)
                        {
                            WriteToLog("Deleting program '{0}' on channel '{1}' in cache...", titleNode.Value, programme.GetAttribute("channel"));
                        }
                        programme.ParentNode.RemoveChild(programme);
                    }
                }


                nodes = domInput.SelectNodes("tv/channel");
                foreach (XmlElement element in nodes)
                {
                    var id = element.GetAttribute("id");
                    if (channels.Contains(id))
                    {
                        var channelName = id;
                        var titleNode   = element.SelectSingleNode("display-name");
                        if (titleNode != null)
                        {
                            channelName = titleNode.InnerText;
                        }

                        cacheDom.DocumentElement.InsertBefore(cacheDom.ImportNode(element, true), cacheDom.DocumentElement.FirstChild);

                        domOutput.DocumentElement.AppendChild(domOutput.ImportNode(element, true));
                        WriteToLog("Added channel '{0}'.", channelName);
                        // var apiChannelNode =
                        //	apiChannelsDom.SelectSingleNode(String.Format("/*/channels/channel[tvuri={0}]/handle/text()", XPathEncode(id)));
                        //if (apiChannelNode != null)
                        //	ApiChannelsCache.Add(id, apiChannelNode.Value);
                        //if (apiChannelNode == null && id.Contains('-') && id.Contains('.'))
                        //{
                        //	var idStringEnd = id;
                        //	var idPart = idStringEnd.Substring(0, idStringEnd.IndexOf('.'));
                        //	idStringEnd = idStringEnd.Substring(idStringEnd.IndexOf('.'));
                        //	var newId = String.Empty;
                        //	foreach (var sId in idPart.Split('-'))
                        //	{
                        //		apiChannelNode =
                        //			apiChannelsDom.SelectSingleNode(String.Format("/*/channels/channel[tvuri={0}]/handle/text()",
                        //														  XPathEncode(sId + idStringEnd)));
                        //		if (apiChannelNode != null)
                        //		{
                        //			if (!String.IsNullOrEmpty(newId))
                        //				newId += ";";
                        //			newId += apiChannelNode.Value;
                        //		}
                        //	}
                        //	if (!String.IsNullOrEmpty(newId))
                        //		ApiChannelsCache.Add(id, newId);
                        //}
                    }
                }


                nodes = domOutput.SelectNodes("tv/channel");
                foreach (XmlElement element in nodes)
                {
                    var id          = element.GetAttribute("id");
                    var channelName = id;
                    var titleNode   = element.SelectSingleNode("display-name");
                    if (titleNode != null)
                    {
                        channelName = titleNode.InnerText;
                    }

                    if (channels.Contains(id))
                    {
                        for (var i = 0; i < days; i++)
                        {
                            var date       = Today.AddDays(i);
                            var cacheNodes =
                                cacheDom.SelectNodes(String.Format("tv/programme[@channel={0} and @programmeday='{1:yyyy-MM-dd}']",
                                                                   XPathEncode(id), date));
                            if (cacheNodes.Count > 0)
                            {
                                foreach (XmlElement programme in cacheNodes)
                                {
                                    var clone = (XmlElement)domOutput.ImportNode(programme, true);
                                    domOutput.DocumentElement.AppendChild(clone);
                                }
                                continue;
                            }

                            if (!IsProgrammeModified(id, date, lastModifiedDom, cacheDom))
                            {
                                continue;
                            }


                            var channelUrl = String.Format(Settings.Default.ChannelUrl ?? "http://xmltv.xmltv.se/{0}_{1:yyyy-MM-dd}.xml.gz", id, date);
                            WriteToLog("Retrieving xmltv from '{0}'...", channelUrl);
                            try
                            {
                                tempDom    = GetWebResponseDom(channelUrl);
                                saveToFile = true;
                            }
                            catch (Exception ex)
                            {
                                HandleException(ex);
                                return;
                            }
                            var programmeNodes = tempDom.SelectNodes("tv/programme");

                            var channel = channelSettings.Channels.FirstOrDefault(x => String.Equals(x.ChannelId, id));

                            foreach (XmlElement programme in programmeNodes)
                            {
                                var programName = "";
                                titleNode = programme.SelectSingleNode("title");
                                if (titleNode != null)
                                {
                                    programName = titleNode.InnerText;
                                }
                                var start       = DateTime.MinValue;
                                var startString = programme.GetAttribute("start");
                                if (!String.IsNullOrEmpty(startString) && startString.Length >= 14)
                                {
                                    startString = FixDateString(startString);
                                    DateTime.TryParse(startString, out start);
                                }


                                if (channel != null)
                                {
                                    var timeRange = channel.GetTimeRange(date);
                                    if (!(start.TimeOfDay >= timeRange.Start && start.TimeOfDay < timeRange.End))
                                    {
                                        WriteToLog("Program '{0}' '{1}' was out of range '{2}-{3}' day '{4}' on channel '{5}'.", programName, start.TimeOfDay, timeRange.Start, timeRange.End, date.DayOfWeek, channelName);
                                        continue;
                                    }
                                }

                                WriteToLog("Added program '{0}' on channel '{1}'.", programName, channelName);
                                var imgUrl     = "";
                                var programUrl = "";
                                var urlNode    = programme.SelectSingleNode("url");
                                if (urlNode != null)
                                {
                                    programUrl = urlNode.InnerText;
                                }
                                var cacheKey = programUrl;
                                if (String.IsNullOrEmpty(cacheKey))
                                {
                                    cacheKey = string.Format("{0}_{1}", id, programName);
                                }

                                if (cachedIcons.ContainsKey(cacheKey))
                                {
                                    imgUrl = cachedIcons[cacheKey];
                                }
                                try
                                {
                                    if (String.IsNullOrEmpty(imgUrl) && !EmptyImageCache.Contains(cacheKey))
                                    {
                                        imgUrl = GetProgramIcon(id, i, programName, programUrl, start);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    //HandleException(ex);
                                    //return;
                                }
                                if (!String.IsNullOrEmpty(imgUrl))
                                {
                                    var iconNode = tempDom.CreateElement("icon");
                                    iconNode.SetAttribute("src", imgUrl);
                                    programme.AppendChild(iconNode);
                                    if (!cachedIcons.ContainsKey(cacheKey))
                                    {
                                        cachedIcons.Add(cacheKey, imgUrl);
                                    }
                                    WriteToLog("Added program icon '{0}' for program '{1}' on channel '{2}'.", imgUrl, programName, channelName);
                                }
                                else
                                {
                                    EmptyImageCache.Add(cacheKey);
                                }


                                foreach (XmlElement node in programme.SelectNodes("star-rating/value"))
                                {
                                    node.InnerText = FixRating(node.InnerText);
                                }

                                FixEpisodeNum(programme, insertEpisodeInDesc);

                                foreach (XmlElement node in programme.SelectNodes("category"))
                                {
                                    FixCategory(node);
                                }

                                if (id.IndexOf("hd", StringComparison.InvariantCultureIgnoreCase) == -1)
                                {
                                    var qualityNode = programme.SelectSingleNode("video/quality");
                                    if (qualityNode != null)
                                    {
                                        qualityNode.ParentNode.RemoveChild(qualityNode);
                                    }
                                }
                                if (daysInHistory > 0)
                                {
                                    var lastModifiedNode =
                                        lastModifiedDom.SelectSingleNode(
                                            String.Format("/*/channel[@id={0}]/datafor[text()='{1:yyyy-MM-dd}']/@lastmodified", XPathEncode(id), date));
                                    var cacheClone = (XmlElement)cacheDom.ImportNode(programme, true);
                                    if (lastModifiedNode != null)
                                    {
                                        cacheClone.SetAttribute("programmeday", date.ToString("yyyy-MM-dd"));
                                        cacheClone.SetAttribute("lastmodified", lastModifiedNode.Value);
                                    }

                                    cacheDom.DocumentElement.AppendChild(cacheClone);
                                }
                                domOutput.DocumentElement.AppendChild(domOutput.ImportNode(programme, true));
                            }
                        }
                    }
                }
                if (daysInHistory > 0)
                {
                    PreviousShown(domOutput, cacheDom, previousShownDuration);
                    SaveHistory(cacheDom, lastModifiedDom, days, channels);
                }

//#if DEBUG
//                var list = new List<string>();
//                var tempNodes = cacheDom.SelectNodes("//category/text()");
//                foreach (XmlNode node in tempNodes)
//                    if (!list.Contains(node.Value))
//                        list.Add(node.Value);

//                Debug.Print(String.Join(Environment.NewLine, list));
//#endif

                try
                {
                    if (saveToFile || !File.Exists(path))
                    {
                        domOutput.Save(path);
                        if (cachedIcons.Count > 50000)
                        {
                            cachedIcons = null;
                        }
                        Properties.Settings.Default.ImageCache = cachedIcons;
                        Properties.Settings.Default.Save();


                        cacheDom.Save(cacheLocation);
                    }
                    else
                    {
                        WriteToLog("No changes found, ignoring write to file...");
                    }
                }
                catch (Exception ex)
                {
                    HandleException(ex);
                    return;
                }

                WriteToLog("Done!");
                try
                {
                    EventLog.WriteEntry(SSource, "Tvzon has successfully ended.", EventLogEntryType.Information);
                }
                catch (Exception)
                {
                }
            }
            //Thread.Sleep(2000);
        }