Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package tvhchgen; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.security.MessageDigest; import java.util.ArrayList; import java.util.HashMap; import java.util.zip.GZIPInputStream; import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; /** * */ class Service { public String id; public long sid; public long lcn; public String name; public String provider; public long type; public boolean enabled; public long pcr; public long pmt; public Service() { } public Service(String id, JSONObject obj) throws Exception { this.id = id; sid = (Long) obj.get("sid"); lcn = (Long) obj.get("lcn"); name = (String) obj.get("svcname"); provider = (String) obj.get("provider"); type = (Long) obj.get("dvb_servicetype"); enabled = (Boolean) obj.get("enabled"); pcr = (Long) obj.get("pcr"); pmt = (Long) obj.get("pmt"); } } class Tag { public int id; public String name; } /** * */ class Channel { public String id; public long number; public long preTime; public long postTime; public String icon; public JSONArray services; public JSONArray tags; public Channel() throws Exception { this.id = ""; number = 0; preTime = 0; postTime = 0; icon = ""; services = new JSONArray(); tags = new JSONArray(); } public String getService(int index) { if (index < services.size()) { return (String) services.get(index); } return ""; } public long getTag(int index) { if (index < tags.size()) { return (long) tags.get(index); } return -1; } public void write() { try { File file = new File(id); if (file.exists()) { file.delete(); } file.createNewFile(); JSONObject jsonObject = new JSONObject(); jsonObject.put("number", this.number); jsonObject.put("dvr_pre_time", this.preTime); jsonObject.put("dvr_pst_time", this.postTime); if (!icon.isEmpty()) { jsonObject.put("icon", this.icon); } jsonObject.put("services", this.services); jsonObject.put("tags", this.tags); FileWriter fw = new FileWriter(file); String jsonStr = jsonObject.toString(); jsonStr = jsonStr.replace("{", "{\n\t"); jsonStr = jsonStr.replace(",\"", ",\n\t\""); jsonStr = jsonStr.replace("}", "\n}"); fw.write(jsonStr); //System.out.println( jsonStr ); fw.flush(); fw.close(); } catch (Exception e) { System.out.println("Exception: " + e.toString()); } } } class ChannelDef { public static final int CATEGORY_ENTERTAINMENT = 12; public static final int CATEGORY_LIVESTYLE = 13; public static final int CATEGORY_MOVIES = 14; public static final int CATEGORY_SPORTS = 15; public static final int CATEGORY_NEWS = 16; public static final int CATEGORY_DOCUMENTARIES = 17; public static final int CATEGORY_KIDS = 18; public static final int CATEGORY_MUSIC = 19; public static final int CATEGORY_SHOPPING = 21; public static final int CATEGORY_RELIGION = 22; public static final int CATEGORY_INTERNATIONAL = 23; public static final int CATEGORY_GAMING = 24; public static final int CATEGORY_SPECIALIST = 25; public static final HashMap<Integer, String> CATEGORIES; static { HashMap<Integer, String> categories = new HashMap<>(); categories.put(12, "Entertainment"); categories.put(13, "Livestyle"); categories.put(14, "Movies"); categories.put(15, "Sports"); categories.put(16, "News"); categories.put(17, "Documentaries"); categories.put(18, "Kids"); categories.put(19, "Music"); categories.put(21, "Shopping"); categories.put(22, "Religion"); categories.put(23, "International"); categories.put(24, "Gaming"); categories.put(25, "Specialist"); CATEGORIES = categories; } public long id; public long number; public long category; public boolean isHD; public String showName; public boolean isFree; public String netName; //{"c":[2002,101,12,0],"lcn":"BBC One London","pt":"F","t":"BBC One Lon"} public ChannelDef(JSONObject obj) { JSONArray c = (JSONArray) obj.get("c"); id = (Long) c.get(0); number = (Long) c.get(1); category = (Long) c.get(2); isHD = ((Long) c.get(3) == 1); showName = (String) obj.get("lcn"); isFree = false; String pt = (String) obj.get("pt"); if (pt != null) { isFree = pt.toLowerCase().equals("f"); } netName = (String) obj.get("t"); } } class ChannelTag { public static final int CATEGORY_TVCHANNELS = 1; public static final int CATEGORY_HDTV = 2; public static final int CATEGORY_SDTV = 3; public static final String[] DEFAULT_CHANNELTAGS = { "TV channels", "HDTV", "SDTV", "Radio", "Entertainment", "Livestyle", "Movies", "Sports", "News", "Documentaries", "Kids", "Music", "Shopping", "Religion", "International", "Gaming", "Specialist" }; public boolean enabled; public boolean internal; public boolean titledIcon; public String name; public String comment; public String icon; public long id; ChannelTag(String name, int id) { enabled = true; internal = false; titledIcon = false; this.name = name; comment = ""; icon = ""; this.id = id; } ChannelTag(JSONObject obj) { enabled = (Boolean) obj.get("enabled"); internal = (Boolean) obj.get("internal"); titledIcon = (Boolean) obj.get("titledIcon"); name = (String) obj.get("name"); comment = (String) obj.get("comment"); id = (Long) obj.get("id"); } /** * * @param filePath */ public void write(String filePath) { try { File file = new File(filePath); if (file.exists()) { file.delete(); } file.createNewFile(); JSONObject jsonObject = new JSONObject(); jsonObject.put("enabled", this.enabled); jsonObject.put("internal", this.internal); jsonObject.put("titledIcon", this.titledIcon); jsonObject.put("name", this.name); jsonObject.put("comment", this.comment); jsonObject.put("id", this.id); FileWriter fw = new FileWriter(file); String jsonStr = jsonObject.toString(); jsonStr = jsonStr.replace("{", "{\n\t"); jsonStr = jsonStr.replace(",\"", ",\n\t\""); jsonStr = jsonStr.replace("}", "\n}"); fw.write(jsonStr); //System.out.println( jsonStr ); fw.flush(); fw.close(); } catch (Exception e) { System.out.println("Exception: " + e.toString()); } } } /** * * @author jrios */ public class TvhChGen { public final String DEFAULT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/33.0.1750.152 Chrome/33.0.1750.152 Safari/537.36"; public final String DEFAULT_REFERER = "http://tv.sky.com/tv-guide"; public final String CHANNELS_FILENAME = "channels.dat"; public final String CHANNELS_DEFINITION_REGCODE = "4101-1"; public final String CHANNELS_DEFINITION_URL = "http://tv.sky.com/channel/index/" + CHANNELS_DEFINITION_REGCODE; public final String ICON_SKY_URL = "http://tv.sky.com/logo/%d/%d/skychb%d.png"; // protected final int PROCESS_ARGS_RESULT_OK = 0; protected final int PROCESS_ARGS_RESULT_EXIT = 1; protected final int PROCESS_ARGS_RESULT_ERROR = 2; String tvhPath; String channelsPath; String iconsPath; Boolean resetChannels; ArrayList<Channel> channels; ArrayList<Service> services; ArrayList<ChannelDef> channelsDefs; ArrayList<ChannelTag> channelTags; /** * */ public TvhChGen() { channels = new ArrayList<>(); services = new ArrayList<>(); channelsDefs = new ArrayList<>(); channelTags = new ArrayList<>(); tvhPath = ""; channelsPath = CHANNELS_FILENAME; iconsPath = ""; } /** * */ private void showUsage() { System.out.println("TVHeadEnd channel number process. J.Rios anonbeat@gmail.com"); System.out.println("==========================================================="); System.out.println("Use : htschedit [options]\n"); System.out.println("Options:"); System.out.println("\t--tvh-dir=path to tvheadend"); System.out.println("\t--channels=path to channels csv file"); System.out.println("\t--update-definitions"); System.out.println("\t--create-tags"); System.out.println("\t--icons-dir=path to store icons"); System.out.println("\t--reset (Delete all previous channels)"); System.out.println(); } /** * * @param args * @return */ private int processArgs(String[] args) { for (String arg : args) { if (arg.startsWith("--tvh-dir=")) { tvhPath = arg.substring(10).trim(); } else if (arg.startsWith("--channels=")) { channelsPath = arg.substring(11).trim(); } else if (arg.startsWith("--update-definitions")) { updateChannelDefinitions(); return this.PROCESS_ARGS_RESULT_EXIT; } else if (arg.startsWith("--create-tags")) { createChannelTags(); return this.PROCESS_ARGS_RESULT_EXIT; } else if (arg.startsWith("--icons-dir=")) { iconsPath = arg.substring(12).trim(); if (!checkIconsPath()) { return PROCESS_ARGS_RESULT_EXIT; } } else if (arg.equals("--reset")) { resetChannels(); } else { System.out.println("Error in param '" + arg + "'"); return this.PROCESS_ARGS_RESULT_ERROR; } } return (!tvhPath.isEmpty() && !channelsPath.isEmpty()) ? this.PROCESS_ARGS_RESULT_OK : this.PROCESS_ARGS_RESULT_ERROR; } /** * * @return */ boolean checkIconsPath() { File iconsDir = new File(iconsPath); if (!iconsDir.exists()) { return iconsDir.mkdirs(); } return iconsDir.isDirectory(); } /** * * @param serviceFile * @return */ boolean loadService(File serviceFile) { try { JSONParser parser = new JSONParser(); JSONObject jsonObject = (JSONObject) parser.parse(new FileReader(serviceFile)); String servicePath = serviceFile.getAbsolutePath(); Service service = new Service( servicePath.substring(servicePath.lastIndexOf("" + File.separatorChar) + 1), jsonObject); services.add(service); //System.out.println( "Service: '" + servicePath + "'" ); } catch (Exception e) { System.out.println("Exception: " + e.toString()); return false; } return true; } /** * * @param muxFile * @return */ boolean loadServices(File muxFile) { String servicesPath = muxFile.getAbsolutePath() + File.separatorChar + "services"; File servicesDir = new File(servicesPath); if (servicesDir.exists() && servicesDir.isDirectory()) { File[] servicesFiles = servicesDir.listFiles(); for (File serviceFile : servicesFiles) { if (!loadService(serviceFile)) { return false; } } } return true; } boolean loadMux(File muxFile) { try { return loadServices(muxFile); } catch (Exception e) { System.out.println("Exception: " + e.toString()); } return false; } /** * * @param network * @return */ boolean loadMuxes(File networkFile) { String muxesPath = networkFile.getAbsolutePath() + File.separatorChar + "muxes"; File muxesDir = new File(muxesPath); if (muxesDir.exists() && muxesDir.isDirectory()) { File[] muxesFiles = muxesDir.listFiles(); for (File muxFile : muxesFiles) { if (!loadMux(muxFile)) { return false; } } } else { System.out.println("Error: The path '" + muxesPath + "' don't exist."); } return true; } /** * * @param networkFile * @return */ boolean loadNetwork(File networkFile) { System.out.println("Loading networks..."); try { return loadMuxes(networkFile); } catch (Exception e) { System.out.println("Exception: " + e.toString()); } return false; } /** * * @return */ boolean loadNetworks() { String networkPath = tvhPath + File.separatorChar + "input/dvb/networks"; File networkDir = new File(networkPath); if (networkDir.exists() && networkDir.isDirectory()) { File[] networkFiles = networkDir.listFiles(); for (File networkFile : networkFiles) { if (!loadNetwork(networkFile)) { return false; } } } else { System.out.println("Error: The path '" + networkPath + "' don't exist."); } return true; } /** * * @param obj */ void loadChannelDef(JSONObject obj) throws Exception { ChannelDef chDef = new ChannelDef(obj); channelsDefs.add(chDef); } /** * * @return */ protected boolean loadChannelsDefs() { try { File channelsCsvFile = new File(channelsPath); if (channelsCsvFile.exists()) { JSONParser parser = new JSONParser(); JSONObject jsonObject = (JSONObject) parser.parse(new FileReader(channelsCsvFile)); jsonObject = (JSONObject) jsonObject.get("init"); JSONArray channelDefs = (JSONArray) jsonObject.get("channels"); for (Object channelDef : channelDefs) { loadChannelDef((JSONObject) channelDef); } return true; } else { System.out.println("Error: The path '" + channelsPath + "' don't exist."); } } catch (Exception e) { System.out.println("Exception: " + e.toString()); e.printStackTrace(); } return false; } /** * Delete all the channels */ protected void resetChannels() { try { String channelPath = tvhPath + File.separatorChar + "channel"; File channelDir = new File(channelPath); if (channelDir.exists() && channelDir.isDirectory()) { File[] channelFiles = channelDir.listFiles(); for (File channelFile : channelFiles) { channelFile.deleteOnExit(); } } else { System.out.println("Error: The path '" + channelPath + "' don't exist."); } } catch (Exception e) { System.out.println("Exception: " + e.toString()); e.printStackTrace(); } } /** * * @param serviceId * @return */ Service findService(String serviceId) { for (Service service : services) { if (service.id.equals(serviceId)) { return service; } } return null; } /** * * @param name * @return */ ChannelDef findChannelDef(String name) { for (ChannelDef channelDef : channelsDefs) { if (channelDef.netName.toLowerCase().equals(name)) { return channelDef; } } return null; } /** * * @param tagFile * @throws Exception */ protected void loadChannelTag(File tagFile) throws Exception { JSONParser parser = new JSONParser(); JSONObject jsonObject = (JSONObject) parser.parse(new FileReader(tagFile)); ChannelTag channelTag = new ChannelTag(jsonObject); channelTags.add(channelTag); } /** * * @return */ protected boolean loadChannelTags() { try { String networkPath = tvhPath + File.separatorChar + "channeltags"; File tagsDir = new File(networkPath); if (tagsDir.exists() && tagsDir.isDirectory()) { File[] tagsFiles = tagsDir.listFiles(); for (File tagFile : tagsFiles) { loadChannelTag(tagFile); } } else { System.out.println("Error: The path '" + networkPath + "' don't exist."); } return true; } catch (Exception e) { System.out.println("Exception: " + e.toString()); e.printStackTrace(); } return false; } /** * * @param name * @return */ ChannelTag findChannelTag(String name) { for (ChannelTag channelTag : channelTags) { if (channelTag.name.toLowerCase().equals(name)) { return channelTag; } } return null; } /** * Calcula el md5 de una cadena de entrada * @param in : la cadena para calcular el md5 * @return el md5 de la cadena pasada como parmetro */ private static String md5ToStr(String in) throws Exception { MessageDigest md = MessageDigest.getInstance("MD5"); md.reset(); md.update(in.getBytes()); byte[] md5bytes = md.digest(); StringBuilder result = new StringBuilder(); for (int index = 0; index < md5bytes.length; index++) { result.append(String.format("%02x", 0xFF & md5bytes[index])); } return result.toString(); } /** * */ void processChannels() { int channelsFound = 0; for (Service service : services) { if ((service.name != null) && !service.name.isEmpty()) { ChannelDef channelDef = findChannelDef(service.name.toLowerCase()); if (channelDef != null) { try { channelsFound++; System.out.println("Service: '" + service.name + "' " + channelDef.number); Channel channel = new Channel(); String hashStr = md5ToStr("" + channelDef.number); channel.id = tvhPath + File.separatorChar + "channel" + File.separatorChar + hashStr; channel.number = channelDef.number; channel.services.add(service.id); channel.tags.add(ChannelTag.CATEGORY_TVCHANNELS); channel.tags.add(channelDef.isHD ? ChannelTag.CATEGORY_HDTV : ChannelTag.CATEGORY_SDTV); String catName = ChannelDef.CATEGORIES.get((int) channelDef.category); //System.out.println( "Category: " + catName ); ChannelTag channelTag = findChannelTag(catName.toLowerCase()); if (channelTag != null) { channel.tags.add(channelTag.id); } if (!iconsPath.isEmpty()) { String iconPath = iconsPath + File.separatorChar + channelDef.id + ".png"; File iconFile = new File(iconPath); if (!iconFile.exists()) { if (!saveUrl(String.format(ICON_SKY_URL, 320, 140, channelDef.id), iconPath)) { // Some icons dont scale to bigger size saveUrl(String.format(ICON_SKY_URL, 200, 87, channelDef.id), iconPath); } Thread.sleep(300); } channel.icon = "file://" + iconPath; } File channelFile = new File(channel.id); if (channelFile.exists()) { channelFile.delete(); } channel.write(); } catch (Exception e) { System.out.println("Exception: " + e.toString()); e.printStackTrace(); } } } } System.out.println("Found " + channelsFound + " channels."); } /** * * @param args */ public void go(String[] args) { int result = processArgs(args); if (result == this.PROCESS_ARGS_RESULT_OK) { if (loadNetworks()) { System.out.println("Loaded " + services.size() + " services."); if (loadChannelsDefs() && loadChannelTags()) { processChannels(); } } } else if (result == this.PROCESS_ARGS_RESULT_ERROR) { showUsage(); } } /** * Save the channels definitions to the specified file. */ void updateChannelDefinitions() { System.out.println("Saving channels definitions to the file '" + channelsPath + "'"); try { File channelsFile = new File(channelsPath); if (channelsFile.exists()) { channelsFile.delete(); } // saveUrl(CHANNELS_DEFINITION_URL, channelsPath); System.out.println("Done."); } catch (Exception e) { System.out.println("Exception: " + e.toString()); } } /** * Create all the channelTags */ private void createChannelTags() { for (int index = 0; index < ChannelTag.DEFAULT_CHANNELTAGS.length; index++) { ChannelTag channelTag = new ChannelTag(ChannelTag.DEFAULT_CHANNELTAGS[index], index + 1); channelTag.write(tvhPath + File.separatorChar + "channeltags" + File.separatorChar + (index + 1)); } } /** * Save the content of the Url to the given path * @param urlStr * @param outPath * @return */ public boolean saveUrl(String urlStr, String outPath) { InputStream is = null; try { //System.out.println( "Getting: " + urlStr ); URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); HttpURLConnection.setFollowRedirects(true); // allow both GZip and Deflate (ZLib) encodings conn.setRequestProperty("Accept-Encoding", "gzip, deflate"); conn.setRequestProperty("User-Agent", DEFAULT_USER_AGENT); conn.setRequestProperty("Referer", DEFAULT_REFERER); String encoding = conn.getContentEncoding(); InputStream inStr; // create the appropriate stream wrapper based on // the encoding type if (encoding != null && encoding.equalsIgnoreCase("gzip")) { inStr = new GZIPInputStream(conn.getInputStream()); } else if (encoding != null && encoding.equalsIgnoreCase("deflate")) { inStr = new InflaterInputStream(conn.getInputStream(), new Inflater(true)); } else { inStr = conn.getInputStream(); } //System.out.println( filePath ); File file = new File(outPath); if (!file.exists()) { file.createNewFile(); FileOutputStream fos = new FileOutputStream(file); ReadableByteChannel rbc = Channels.newChannel(inStr); fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); fos.close(); return true; } } catch (Exception e) { System.out.println("Exception: " + e.toString()); } finally { if (is != null) { try { is.close(); } catch (Exception e) { System.out.println("Exception: " + e.toString()); } } } return false; } /** * * @param args */ public static void main(String[] args) { TvhChGen tvhChGen = new TvhChGen(); tvhChGen.go(args); } }