tvhchgen.Service.java Source code

Java tutorial

Introduction

Here is the source code for tvhchgen.Service.java

Source

/*
 * 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);
    }

}