# HG changeset patch # User StephaneLenclud # Date 1431732692 -7200 # Node ID 29ccfbf98e54c06851d9122f65d137c7f19a40fa # Parent 8372aa8d6292f6f70d202d4fb784f9cceca1d655 Group support and multiple package import. diff -r 8372aa8d6292 -r 29ccfbf98e54 KingOfSat.cs --- a/KingOfSat.cs Fri May 15 22:41:33 2015 +0200 +++ b/KingOfSat.cs Sat May 16 01:31:32 2015 +0200 @@ -9,148 +9,274 @@ namespace SatChanGen { - class KingOfSat - { - // - // Summary: - // Create a new CQ object wrapping a single element. - // - // Parameters: - // aUrl: - // URL to a KingOfSat channel list. Typically a package list. - // - // Return: - // List of channels parsed. - public static List Parse(string aUrl, string aOrbitalPosition) - { - string kos = new WebClient().DownloadString(aUrl); - //Debug.Write(kos); + class KingOfSat + { + // + // Summary: + // Create a new CQ object wrapping a single element. + // + // Parameters: + // aUrl: + // URL to a KingOfSat channel list. Typically a package list. + // + // Return: + // List of channels parsed. + public static List Parse(List aChannels, string aUrl, string aOrbitalPosition) + { + //To avoid duplicated name + Dictionary names = new Dictionary(); - CQ dom = kos; + string kos = new WebClient().DownloadString(aUrl); + //Debug.Write(kos); - //Get all the Frequency elements in our page - CQ sats = dom[".frq"]; + CQ dom = kos; - //Create our list of channels - List channels = new List(); + //Get all the Frequency elements in our page + CQ sats = dom[".frq"]; - foreach (IDomObject frq in sats.ToList()) - { - Channel common = new Channel(); + //Create our list of channels + List channels = new List(); - //Parse channel details - common.OrbitalPosition = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td > a > font").Get(0).InnerText).Trim(); - if (common.OrbitalPosition != aOrbitalPosition) - { + foreach (IDomObject frq in sats.ToList()) + { + Channel common = new Channel(); + + //Parse channel details + common.OrbitalPosition = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td > a > font").Get(0).InnerText).Trim(); + if (common.OrbitalPosition != aOrbitalPosition) + { //Wrong sat, skip - continue; - } - common.Satellite = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(2) > a").Get(0).InnerText); - common.Frequency = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(3)").Get(0).InnerText); - common.Polarisation = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(4)").Get(0).InnerText); - common.Transponder = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(5) > a").Get(0).InnerText); - common.Beam = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(6) > a").Get(0).InnerText); - common.Standard = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(7)").Get(0).InnerText); - common.Modulation = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(8)").Get(0).InnerText); - common.SymbolRate = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(9) > a").Get(0).InnerText); - common.FEC = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(9) > a:nth-child(2)").Get(0).InnerText); - try - { - common.Provider = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(10) > b").Get(0).InnerText); - } - catch (Exception) - { - } + continue; + } + common.Satellite = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(2) > a").Get(0).InnerText); + common.Frequency = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(3)").Get(0).InnerText); + common.Polarisation = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(4)").Get(0).InnerText); + common.Transponder = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(5) > a").Get(0).InnerText); + common.Beam = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(6) > a").Get(0).InnerText); + common.Standard = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(7)").Get(0).InnerText); + common.Modulation = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(8)").Get(0).InnerText); + common.SymbolRate = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(9) > a").Get(0).InnerText); + common.FEC = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(9) > a:nth-child(2)").Get(0).InnerText); + try + { + common.Provider = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(10) > b").Get(0).InnerText); + } + catch (Exception) + { + } - common.Bitrate = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(10)").Get(0).InnerText); - if (common.Bitrate.Substring(0, ", ".Length) == ", ") - { - common.Bitrate = common.Bitrate.Substring(", ".Length, common.Bitrate.Length - ", ".Length); - } - // - common.NetworkID = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(11)").Get(0).InnerText); - common.NetworkID = common.NetworkID.Substring("NID:".Length, common.NetworkID.Length - "NID:".Length); - // - common.TransponderID = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(12)").Get(0).InnerText); - common.TransponderID = common.TransponderID.Substring("TID:".Length, common.TransponderID.Length - "TID:".Length); + common.Bitrate = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(10)").Get(0).InnerText); + if (common.Bitrate.Substring(0, ", ".Length) == ", ") + { + common.Bitrate = common.Bitrate.Substring(", ".Length, common.Bitrate.Length - ", ".Length); + } + // + common.NetworkID = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(11)").Get(0).InnerText); + common.NetworkID = common.NetworkID.Substring("NID:".Length, common.NetworkID.Length - "NID:".Length); + // + common.TransponderID = WebUtility.HtmlDecode(frq.Cq().Find("tbody > tr > td:nth-child(12)").Get(0).InnerText); + common.TransponderID = common.TransponderID.Substring("TID:".Length, common.TransponderID.Length - "TID:".Length); - //We got common properties for the coming channels - //Debug.Write(common.ToString()); + //We got common properties for the coming channels + //Debug.Write(common.ToString()); - //Now get all the channels for that frequency - //Channel common = new Channel(); + //Now get all the channels for that frequency + //Channel common = new Channel(); - CQ channelsDiv = frq.Cq().Next("div"); - CQ channelsTableRows = channelsDiv.Find("table.fl > tbody").Children("tr"); + CQ channelsDiv = frq.Cq().Next("div"); + CQ channelsTableRows = channelsDiv.Find("table.fl > tbody").Children("tr"); - foreach (IDomObject row in channelsTableRows) - { - Channel channel = new Channel(); - //Initialize this channel with common properties on this frequency + foreach (IDomObject row in channelsTableRows) + { + Channel channel = new Channel(); + //Initialize this channel with common properties on this frequency channel.Copy(common); - //Try and parse channel name - CQ cqChannelName = row.Cq().Find("td:nth-child(3) > a"); - if (cqChannelName.Length == 0) - { - cqChannelName = row.Cq().Find("td:nth-child(3) > i"); - if (cqChannelName.Length == 0) - { - //Can't get channel name - Debug.Write("WARNING: Can't find channel name! Skipping this channel"); - continue; - } - } + //Try and parse channel name + CQ cqChannelName = row.Cq().Find("td:nth-child(3) > a"); + if (cqChannelName.Length == 0) + { + cqChannelName = row.Cq().Find("td:nth-child(3) > i"); + if (cqChannelName.Length == 0) + { + //Can't get channel name + Debug.Write("WARNING: Can't find channel name! Skipping this channel"); + continue; + } + } - channel.Name = WebUtility.HtmlDecode(cqChannelName.Get(0).InnerText).Trim(); - if (channel.Name == "Name") - { - //Skipping header rows - continue; - } + string channelNameInnerText = cqChannelName.Get(0).InnerText; + channel.Name = WebUtility.HtmlDecode(channelNameInnerText).Trim(); + //Encoding decoder = Encoding.UTF8; + //channel.Name = decoder.GetString(channel.Name); + //channel.Name = channelNameInnerText.Trim(); //Make up your mind :) + if (channel.Name == "Name") + { + //Skipping header rows + continue; + } - //Make sure our channel name looks descent - channel.Name = CleanChannelName(channel.Name); + //Make sure our channel name looks descent + channel.Name = CleanChannelName(channel.Name); + //Make sure the resulting name is unique to avoid having multiple tuning detail for a single channel + if (names.ContainsKey(channel.Name)) + { + names[channel.Name]++; + channel.Name += " " + names[channel.Name]; + } + else + { + names.Add(channel.Name, 1); + } - //So we have a channel name get the other properties then - channel.Country = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(4)").Get(0).InnerText).Trim(); - channel.Category = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(5)").Get(0).InnerText).Trim(); - //Skip the packages - //Skip the encryptions - channel.SID = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(8)").Get(0).InnerText).Trim(); - channel.VPID = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(9)").Get(0).InnerText).Trim(); - //Skip audios - channel.PMT = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(11)").Get(0).InnerText).Trim(); - channel.PCR = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(11)").Get(0).InnerText).Trim(); - channel.TXT = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(11)").Get(0).InnerText).Trim(); + // + //We don't want channels we already have + Channel existingChannel = aChannels.Find(c => c.Name == channel.Name); + if (existingChannel!=null) + { + continue; + } - //Append that new channel to our list - channels.Add(channel); - //Show it in debug output - Debug.Write(channel); - } //For each channel - } //For each frequency + //So we have a channel name get the other properties then + channel.Country = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(4)").Get(0).InnerText).Trim(); + channel.Category = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(5)").Get(0).InnerText).Trim(); + if (channel.Category=="") + { + channel.Category = "Other"; + } + //Skip the packages + //Skip the encryptions + channel.SID = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(8)").Get(0).InnerText).Trim(); + channel.VPID = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(9)").Get(0).InnerText).Trim(); + //Skip audios + channel.PMT = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(11)").Get(0).InnerText).Trim(); + channel.PCR = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(11)").Get(0).InnerText).Trim(); + channel.TXT = WebUtility.HtmlDecode(row.Cq().Find("td:nth-child(11)").Get(0).InnerText).Trim(); - return channels; - } + //Append that new channel to our list + channels.Add(channel); - // - public static string CleanChannelName(string aName) - { - aName.Trim(); - string[] remove = { "Germany", "Deutschland", "(Germany)", "(Deutschland)" }; + //Show it in debug output + Debug.Write(channel); + } //For each channel + } //For each frequency - foreach (string item in remove) - { - if (aName.EndsWith(item)) + return channels; + } + + // + public static string CleanChannelName(string aName) { - aName = aName.Substring(0, aName.LastIndexOf(item)); - break; //only allow one match at most + aName = aName.Trim(); + string[] remove = { " Germany", " Deutschland", " (Germany)", " (Deutschland)" }; + + foreach (string item in remove) + { + //if (aName.EndsWith(item)) + if (aName.Contains(item)) + { + aName = aName.Substring(0, aName.LastIndexOf(item)); + break; //only allow one match at most + } + } + aName = aName.Trim(); + return aName; } - } - aName.Trim(); - return aName; + + // + public static List CleanChannelList(List aChannels) + { + //Create our list of channels + List channels = new List(); + + foreach (Channel channel in aChannels) + { + Channel hdChannel = aChannels.Find(c => c.Name == channel.Name + " HD"); + if (hdChannel==null + && !(channel.Name.Contains("Bundesliga") && !channel.Name.Contains("HD")) //We don't want non HD bundesliga + && !(channel.Name.StartsWith("Sky Sport") && !channel.Name.Contains("HD")) //We don't want non HD Sky Sport + ) + { + //Patch some missing or bad categories + if (channel.Name.Contains("Bundesliga") + || channel.Name.Contains("Sport")) + { + channel.Category = "Sport"; + } + + if (channel.Name.Contains("Sky Select")) + { + channel.Category = "Pay per view"; + } + + + if (channel.Name.StartsWith("Sky Atlantic") + || channel.Name.StartsWith("SyFy") + || channel.Name.StartsWith("Fox")) + { + channel.Category = "Series"; + } + + if (channel.Name.StartsWith("Sky 3D")) + { + channel.Category = "Movies"; + } + + //Collapse some categories + if (channel.Category == "Entertainment" + || channel.Category == "Music" + || channel.Name.Contains("Music")) + { + channel.Category = "General"; + } + + if (channel.Category == "Porn") + { + channel.Category = "Erotic"; + } + + if (channel.Category == "Presentations") + { + channel.Category = "News"; + } + + if (channel.Category == "History") + { + channel.Category = "Documentaries"; + } + + if (channel.Category == "Lifestyle") + { + channel.Category = "General"; + } + + //if (channel.Category == "Regional") + //{ + // channel.Category = "General"; + //} + + if (channel.Category == "Other") + { + channel.Category = "General"; + } + + if (channel.Category == "Cultural") + { + channel.Category = "General"; + } + + + //No corresponding HD channel, keep it then + channels.Add(channel); + } + else + { + Debug.Write("WARNING: Found HD channel for " + channel.Name + ". Discarding it!\n"); + } + } + + return channels; + } } - } } diff -r 8372aa8d6292 -r 29ccfbf98e54 MainForm.cs --- a/MainForm.cs Fri May 15 22:41:33 2015 +0200 +++ b/MainForm.cs Sat May 16 01:31:32 2015 +0200 @@ -24,17 +24,21 @@ private void buttonGenerate_Click(object sender, EventArgs e) { - //List channels = new List(); - List channels=KingOfSat.Parse("http://en.kingofsat.net/pack-skygermany.php","19.2°E"); + List channels = new List(); + channels.AddRange(KingOfSat.Parse(channels, "http://en.kingofsat.net/pack-skygermany.php", "19.2°E")); + channels.AddRange(KingOfSat.Parse(channels, "http://en.kingofsat.net/pack-hdplus.php", "19.2°E")); + channels.AddRange(KingOfSat.Parse(channels, "http://en.kingofsat.net/pack-arddigital.php", "19.2°E")); + channels.AddRange(KingOfSat.Parse(channels, "http://en.kingofsat.net/pack-zdfvision.php", "19.2°E")); + channels.AddRange(KingOfSat.Parse(channels, "http://en.kingofsat.net/pack-tntsat.php", "19.2°E")); + + //Discard non HD channels we don't need + channels = KingOfSat.CleanChannelList(channels); - //Declare tuner cards so that we don't need to create mapping manually after import - List tuners = new List() - { - "3", - "4" - }; + //Declare tuner cards so that we don't need to create mapping manually after import + List tuners = new List(){"3","4"}; - MediaPortal.Export(channels, tuners, "channels.xml",false); + //Export to XML for MediaPortal to import + MediaPortal.Export(channels, tuners, "channels.xml", false); } } } diff -r 8372aa8d6292 -r 29ccfbf98e54 MediaPortal.cs --- a/MediaPortal.cs Fri May 15 22:41:33 2015 +0200 +++ b/MediaPortal.cs Sat May 16 01:31:32 2015 +0200 @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using System.Xml; +using System.IO; namespace SatChanGen { @@ -144,9 +145,18 @@ } + // + // + // public static void Export(List aChannels, List aTunerCards, string aFileName, bool aAddMapping) { + //Create a dictionary for our groups + Dictionary> groups = new Dictionary>(); + XmlDocument xmlDoc = new XmlDocument(); + XmlDeclaration xmlDeclaration = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null); + xmlDoc.AppendChild(xmlDeclaration); + XmlNode rootElement = xmlDoc.CreateElement("tvserver"); AddAttribute(rootElement, "version", "1.0"); xmlDoc.AppendChild(rootElement); @@ -155,38 +165,49 @@ rootElement.AppendChild(nodechannels); int channelId = 0; - int channelMapId = 0; + int channelMapId = 0; foreach (Channel channel in aChannels) { + //Create group if needed + if (!groups.ContainsKey(channel.Category)) + { + //KeyValuePair> entry=new KeyValuePair>(); + groups.Add(channel.Category, new List()); + } + + //Add that channel to its group + groups[channel.Category].Add(channel); + + //Create and populate channel element channelId++; XmlNode nodechannel = xmlDoc.CreateElement("channel"); AddAttribute(nodechannel, "GrabEpg", "True"); AddAttribute(nodechannel, "IdChannel", channelId); AddAttribute(nodechannel, "IsRadio", "False"); AddAttribute(nodechannel, "IsTv", "True"); - AddAttribute(nodechannel, "LastGrabTime", "2000-1-1 0:0:0"); + AddAttribute(nodechannel, "LastGrabTime", "2000-1-1 0:0:0"); //AddAttribute(nodechannel, "SortOrder", channel.SortOrder); - //sAddAttribute(nodechannel, "TimesWatched", "0"); - AddAttribute(nodechannel, "TotalTimeWatched", "2000-1-1 0:0:0"); + //AddAttribute(nodechannel, "TimesWatched", "0"); + AddAttribute(nodechannel, "TotalTimeWatched", "2000-1-1 0:0:0"); AddAttribute(nodechannel, "VisibleInGuide", "True"); AddAttribute(nodechannel, "DisplayName", channel.Name); AddAttribute(nodechannel, "ChannelNumber", channelId); - if (aAddMapping) - { - //I don't think we can get mapping to work without having corresponding server and card definition elements - XmlNode nodeMaps = xmlDoc.CreateElement("mappings"); - foreach (string tuner in aTunerCards) - { - channelMapId++; - XmlNode nodeMap = xmlDoc.CreateElement("map"); - AddAttribute(nodeMap, "IdCard", tuner); - AddAttribute(nodeMap, "IdChannel", channelId); - AddAttribute(nodeMap, "IdChannelMap", channelMapId); - nodeMaps.AppendChild(nodeMap); - } - nodechannel.AppendChild(nodeMaps); - } + if (aAddMapping) + { + //I don't think we can get mapping to work without having corresponding server and card definition elements + XmlNode nodeMaps = xmlDoc.CreateElement("mappings"); + foreach (string tuner in aTunerCards) + { + channelMapId++; + XmlNode nodeMap = xmlDoc.CreateElement("map"); + AddAttribute(nodeMap, "IdCard", tuner); + AddAttribute(nodeMap, "IdChannel", channelId); + AddAttribute(nodeMap, "IdChannelMap", channelMapId); + nodeMaps.AppendChild(nodeMap); + } + nodechannel.AppendChild(nodeMaps); + } XmlNode nodeTuningDetails = xmlDoc.CreateElement("TuningDetails"); XmlNode nodeTune = xmlDoc.CreateElement("tune"); @@ -229,9 +250,43 @@ nodechannels.AppendChild(nodechannel); } + //Create groups element + XmlNode nodeChannelGroups = xmlDoc.CreateElement("channelgroups"); + rootElement.AppendChild(nodeChannelGroups); + int groupSortOrder = 0; + foreach (KeyValuePair> group in groups) + { + //Create group element + XmlNode nodeChannelGroup = xmlDoc.CreateElement("channelgroup"); + AddAttribute(nodeChannelGroup, "GroupName", group.Key); + AddAttribute(nodeChannelGroup, "SortOrder", groupSortOrder.ToString()); + XmlNode nodeGroupMap = xmlDoc.CreateElement("mappings"); + nodeChannelGroup.AppendChild(nodeGroupMap); + nodeChannelGroups.AppendChild(nodeChannelGroup); - xmlDoc.Save(aFileName); + //Sort by name + List sortedChannels = group.Value.OrderBy(o => o.Name).ToList(); + + //Add each channel to its group + int channelSortOrder = 0; + foreach (Channel channel in sortedChannels) + { + XmlNode nodeMap = xmlDoc.CreateElement("map"); + AddAttribute(nodeMap, "ChannelName", channel.Name); + AddAttribute(nodeMap, "SortOrder", channelSortOrder.ToString()); + nodeGroupMap.AppendChild(nodeMap); + channelSortOrder++; + } + + groupSortOrder++; + } + + using (TextWriter sw = new StreamWriter(aFileName, false, Encoding.UTF8)) //Set encoding + { + xmlDoc.Save(sw); + } + //xmlDoc.Save(aFileName); } private static void AddAttribute(XmlNode node, string tagName, string tagValue)