-<?xml version="1.0" encoding="UTF-8"?>\r
-<classpath>\r
- <classpathentry kind="src" path="src"/>\r
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>\r
- <classpathentry exported="true" kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>\r
- <classpathentry kind="output" path="target/classes"/>\r
-</classpath>\r
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
-eclipse.preferences.version=1\r
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7\r
-org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve\r
-org.eclipse.jdt.core.compiler.compliance=1.7\r
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate\r
-org.eclipse.jdt.core.compiler.debug.localVariable=generate\r
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate\r
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning\r
-org.eclipse.jdt.core.compiler.source=1.7\r
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.7
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.vanbest.xmltv.tv_grab_nl_java</groupId>
- <artifactId>tv_grab_nl_java</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <dependencies>
- <dependency>
- <groupId>net.sf.json-lib</groupId>
- <artifactId>json-lib</artifactId>
- <version>2.4</version>
- <classifier>jdk15</classifier>
- </dependency>
- <dependency>
- <groupId>commons-cli</groupId>
- <artifactId>commons-cli</artifactId>
- <version>1.2</version>
- </dependency>
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>2.1</version>
- </dependency>
- <dependency>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- <version>2.6</version>
- </dependency>
- </dependencies>
-</project>
\ No newline at end of file
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.vanbest.xmltv.tv_grab_nl_java</groupId>
+ <artifactId>tv_grab_nl_java</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <dependencies>
+ <dependency>
+ <groupId>net.sf.json-lib</groupId>
+ <artifactId>json-lib</artifactId>
+ <version>2.4</version>
+ <classifier>jdk15</classifier>
+ </dependency>
+ <dependency>
+ <groupId>commons-cli</groupId>
+ <artifactId>commons-cli</artifactId>
+ <version>1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.3</version>
+ <configuration>
+ <descriptor>src/main/assembly/dep.xml</descriptor>
+ <archive>
+ <manifest>
+ <mainClass>org.vanbest.xmltv.Main</mainClass>
+ </manifest>
+ </archive>
+
+ </configuration>
+ </plugin>
+
+ </plugins>
+ </build>
+
+</project>
--- /dev/null
+<assembly>
+ <!-- TODO: a jarjar format would be better -->
+ <id>dep</id>
+ <formats>
+ <format>jar</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <fileSets>
+ <fileSet>
+ <includes>
+ <include>target/classes</include>
+ </includes>
+ <outputDirectory>/</outputDirectory>
+ </fileSet>
+ </fileSets>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory>/</outputDirectory>
+ <unpack>true</unpack>
+ <scope>runtime</scope>
+ <excludes>
+ <exclude>junit:junit</exclude>
+ <exclude>jsch:jsch</exclude>
+ <exclude>org.apache.maven.wagon:wagon-ssh</exclude>
+ <!-- TODO: can probably be removed now -->
+ <exclude>plexus:plexus-container-default</exclude>
+ </excludes>
+ </dependencySet>
+ </dependencySets>
+</assembly>
--- /dev/null
+package org.vanbest.xmltv;
+
+public class Channel {
+ int id;
+ String name;
+ String shortName;
+ String iconUrl;
+ boolean selected;
+
+ public Channel(int id, String name, String shortName) {
+ this.id = id;
+ this.name = name;
+ this.shortName = shortName;
+ }
+ public String toString() {
+ return "id: " + id + "; name: " + name + "; shortName: " + shortName;
+ }
+
+ public String getChannelId() {
+ return id+".tvgids.nl";
+ }
+
+ public void fixup() {
+ this.name = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(name);
+ this.shortName = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(shortName);
+ }
+ public void setIconUrl(String url) {
+ this.iconUrl = url;
+ }
+}
--- /dev/null
+package org.vanbest.xmltv;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.io.FileUtils;
+
+public class Config {
+ public int niceMilliseconds;
+ public List<Channel> channels;
+ public Map<String, String> cattrans;
+ protected File cacheFile;
+ boolean quiet = false;
+ public int logLevel = LOG_DEFAULT;
+
+ public static final int LOG_INFO = 0x0001;
+ public static final int LOG_JSON = 0x0100;
+ private static final int LOG_PROGRAMME_INFO = 0x0200;
+
+ public static int LOG_DEFAULT = LOG_INFO;
+
+ private Config() {
+ }
+
+ public static Config getDefaultConfig() {
+ Config result = new Config();
+ result.channels = new ArrayList<Channel>();
+ result.cattrans = getDefaultCattrans();
+ result.cacheFile = defaultCacheFile();
+ result.niceMilliseconds = 500;
+ return result;
+ }
+
+ public Map<String,String> getCategories() {
+ return cattrans;
+ }
+
+ public void setChannels(List<Channel> channels) {
+ this.channels = channels;
+ }
+
+ public static File defaultCacheFile() {
+ return FileUtils.getFile(FileUtils.getUserDirectory(), ".xmltv", "tv_grab_nl_java.cache");
+ }
+
+ static private Map<String,String> getDefaultCattrans() {
+ Map<String,String> result = new HashMap<String,String>();
+ result.put("amusement", "Animated");
+ result.put("comedy", "Comedy");
+ result.put("documentaire", "Documentary");
+ result.put("educatief", "Educational");
+ result.put("erotiek", "Adult");
+ result.put("film", "Film");
+ result.put("muziek", "Art/Music");
+ result.put("informatief", "Educational");
+ result.put("jeugd", "Children");
+ result.put("kunst/cultuur", "Arts/Culture");
+ result.put("misdaad", "Crime/Mystery");
+ result.put("muziek", "Music");
+ result.put("natuur", "Science/Nature");
+ result.put("nieuws/actualiteiten", "News");
+ result.put("overige", "Unknown");
+ result.put("religieus", "Religion");
+ result.put("serie/soap", "Drama");
+ result.put("sport", "Sports");
+ result.put("theater", "Arts/Culture");
+ result.put("wetenschap", "Science/Nature");
+ return result;
+ }
+
+ public void writeConfig(File configFile) throws IOException {
+ FileUtils.forceMkdir(configFile.getParentFile());
+ PrintWriter out = new PrintWriter(new OutputStreamWriter( new FileOutputStream( configFile )));
+ out.println("cache-file: " + escape(cacheFile.getPath()));
+ out.println("nice-time-milliseconds: " + niceMilliseconds);
+ for(Channel c: channels) {
+ if (!c.selected) {
+ out.print("#");
+ }
+ out.print("channel: " + c.id + ": " + escape(c.name));
+ if (c.iconUrl != null) {
+ out.print(" : " + escape(c.iconUrl));
+ }
+ out.println();
+ }
+ for(Map.Entry<String,String> entry: cattrans.entrySet()) {
+ out.println("category: " + escape(entry.getKey()) + ": " + escape(entry.getValue()));
+ }
+ out.close();
+ }
+
+ public static String escape(String s) {
+ return "\"" + s.replace("\\", "\\\\").replaceAll("\\\"", "\\\\\"") + "\"";
+ }
+
+ public static List<String> splitLine(String s) {
+ List<String> parts = new ArrayList<String>(5);
+ int pos=0;
+ while (true) {
+ // Find first colon outside quotes
+ boolean quoted=false;
+ int quoteStart=-1;
+ StringBuffer buf = new StringBuffer();
+ for (; pos<s.length(); pos++) {
+ if (s.charAt(pos)=='"') {
+ if (quoted) {
+ //System.out.println(s.substring(quoteStart, pos));
+ buf.append(s.substring(quoteStart, pos).replaceAll("\\\\\"", "\\\"").replaceAll("\\\\\\\\","\\\\"));
+ } else {
+ quoteStart = pos+1;
+ }
+ quoted=!quoted;
+ continue;
+ }
+ if(s.charAt(pos)=='\\') pos++;
+ if(quoted) continue;
+ if(s.charAt(pos)==':') {
+ break;
+ }
+ buf.append(s.charAt(pos));
+ }
+ parts.add(buf.toString().trim());
+ if (pos>=s.length()) {
+ break;
+ }
+ pos++;
+ }
+ return parts;
+ }
+
+ public static Config readConfig(File file) {
+ Config result = getDefaultConfig();
+ result.cattrans = new HashMap<String,String>();
+ try {
+ BufferedReader reader = new BufferedReader( new InputStreamReader( new FileInputStream( file)));
+
+ while(true) {
+ String s = reader.readLine();
+ if(s==null) break;
+ if (!s.contains(":")) continue;
+ if (s.startsWith("#")) continue;
+ List<String> parts = splitLine(s);
+ if (parts.get(0).toLowerCase().equals("channel")) {
+ Channel c = new Channel(Integer.parseInt(parts.get(1)), parts.get(2), "");
+ if (parts.size()>3) {
+ c.setIconUrl(parts.get(3));
+ }
+ result.channels.add(c);
+ }
+ switch (parts.get(0).toLowerCase()) {
+ case "category" :
+ result.cattrans.put(parts.get(1), parts.get(2));
+ break;
+ case "cache-file":
+ result.cacheFile = new File(parts.get(1));
+ break;
+ case "nice-time-milliseconds":
+ result.niceMilliseconds = Integer.parseInt(parts.get(1));
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ System.out.println("Error reading configuration file, continuing with empty configuration");
+ return getDefaultConfig();
+ }
+ return result;
+ }
+
+ public boolean logJSON() {
+ return (logLevel & LOG_JSON) != 0;
+ }
+
+ public boolean logProgrammes() {
+ return (logLevel & LOG_PROGRAMME_INFO) != 0;
+ }
+
+}
+
--- /dev/null
+package org.vanbest.xmltv;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.Parser;
+import org.apache.commons.io.FileUtils;
+
+public class Main {
+ private File configFile;
+ private Config config;
+ private PrintStream outputWriter;
+ private int days = 5;
+ private int offset = 0;
+ /**
+ * @param args
+ */
+
+ public Main() {
+ this.configFile = defaultConfigFile();
+ this.outputWriter = System.out;
+ }
+
+ public void run() throws FactoryConfigurationError, Exception {
+ if (!config.quiet) {
+ System.out.println("Fetching programme data for days " + this.offset + "-" + (this.offset+this.days-1));
+ System.out.println("... from " + config.channels.size() + " channels");
+ System.out.println("... using cache file " + config.cacheFile.getCanonicalPath());
+ }
+
+ XmlTvWriter writer = new XmlTvWriter(outputWriter, config);
+ writer.writeChannels(config.channels);
+
+ TvGids gids = new TvGids(config);
+
+ for (int day=offset; day<offset+days; day++) {
+ if (!config.quiet) System.out.print("Fetching information for day " + day);
+ Set<Programme> programmes = new HashSet<Programme>();
+ for( Channel c: config.channels ) {
+ if (!config.quiet) System.out.print(".");
+ ArrayList<Channel> cs = new ArrayList<Channel>(2);
+ cs.add(c);
+ Set<Programme> p = gids.getProgrammes(cs, day, true);
+ writer.writePrograms(p);
+ writer.flush();
+ }
+ if (!config.quiet) System.out.println();
+ }
+
+ try {
+ gids.close();
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ writer.close();
+ if (!config.quiet) {
+ System.out.println("Number of programmes from cache: " + gids.cacheHits);
+ System.out.println("Number of programmes fetched: " + gids.cacheMisses);
+ System.out.println("Number of fetch errors: " + gids.fetchErrors);
+ }
+ }
+
+ public void configure() throws IOException {
+ TvGids gids = new TvGids(config);
+
+ Set<Integer> oldChannels = new HashSet<Integer>();
+ for (Channel c: config.channels) {
+ oldChannels.add(c.id);
+ }
+ List<Channel> channels = gids.getChannels();
+
+ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+ boolean all = false;
+ boolean none = false;
+ boolean keep = false;
+ for (Channel c: channels) {
+ boolean selected = oldChannels.contains(c.id);
+ System.out.print("add channel " + c.id + " (" + c.name + ") [[y]es,[n]o,[a]ll,[none],[k]eep selection (default=" + (selected?"yes":"no") + ")] ");
+ if (keep) {
+ c.selected = selected;
+ System.out.println(selected?"Y":"N");
+ continue;
+ }
+ if (all) {
+ c.selected = true;
+ System.out.println("Y");
+ continue;
+ }
+ if (none) {
+ c.selected = false;
+ System.out.println("N");
+ continue;
+ }
+ while(true) {
+ String s = reader.readLine().toLowerCase();
+ if (s.isEmpty()) {
+ c.selected = selected;
+ break;
+ } else if ( s.startsWith("k")) {
+ c.selected = selected;
+ keep = true;
+ break;
+ } else if ( s.startsWith("y")) {
+ c.selected = true;
+ break;
+ } else if ( s.startsWith("a")) {
+ c.selected = true;
+ all = true;
+ break;
+ } else if ( s.startsWith("none")) {
+ c.selected = false;
+ none = true;
+ break;
+ } else if ( s.startsWith("n")) {
+ c.selected = false;
+ break;
+ }
+ }
+ }
+
+ config.setChannels(channels);
+ try {
+ config.writeConfig(configFile);
+ System.out.println("Configuration file written to " + configFile.getPath());
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ public void processOptions(String[] args) throws FileNotFoundException {
+ Options options = new Options();
+ options.addOption("d", "description", false, "Display a description to identify this grabber");
+ options.addOption("c", "capabilities", false, "Show grabber capabilities");
+ options.addOption("q", "quiet", false, "Be quiet");
+ options.addOption("o", "output", true, "Set xlmtv output filename");
+ options.addOption("y", "days", true, "Number of days to grab");
+ options.addOption("s", "offset", true, "Start day for grabbing (0=today)");
+ options.addOption("n", "configure", false, "Interactive configuration");
+ options.addOption("f", "config-file", true, "Configuration file location");
+ options.addOption("h", "cache", true, "Cache file location");
+ options.addOption("e", "help", false, "Show this help");
+ options.addOption("l", "log-level", true, "Set log level (0x0100=JSON)");
+ //options.addOption("p", "preferredmethod", false, "Show preferred method");
+
+ CommandLine line = null;
+ try {
+ line = new GnuParser().parse(options, args);
+ } catch (ParseException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ if (line.hasOption("d")) {
+ System.out.println("tv_grab_nl_java is a parser for Dutch TV listings using the tvgids.nl JSON interface");
+ System.exit(0);
+ }
+ if (line.hasOption("e")) {
+ // automatically generate the help statement
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp( "tv_grab_nl_java", options );
+ System.exit(0);
+ }
+ if(line.hasOption("f")) {
+ configFile = new File(line.getOptionValue("f"));
+ }
+ config = Config.readConfig(configFile);
+ if (line.hasOption("q")) {
+ config.quiet = true;
+ }
+
+ if (line.hasOption("o")) {
+ this.outputWriter = new PrintStream( new FileOutputStream(line.getOptionValue("o")));
+ }
+ if (line.hasOption("l")) {
+ config.logLevel = Integer.parseInt(line.getOptionValue("l"));
+ }
+ if (line.hasOption("h")) {
+ config.cacheFile = new File(line.getOptionValue("h"));
+ }
+ if (line.hasOption("y")) {
+ this.days = Integer.parseInt(line.getOptionValue("y"));
+ }
+ if (line.hasOption("s")) {
+ this.offset = Integer.parseInt(line.getOptionValue("s"));
+ }
+ if (line.hasOption("c")) {
+ System.out.println("baseline");
+ System.out.println("manualconfig");
+ System.out.println("cache");
+ // System.out.println("preferredmethod");
+ System.exit(0);
+ }
+ if (line.hasOption("n")) {
+ try {
+ configure();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ System.exit(0);
+ }
+
+ }
+
+ public static File defaultConfigFile() {
+ return FileUtils.getFile(FileUtils.getUserDirectory(), ".xmltv", "tv_grab_nl_java.conf");
+ }
+
+ public static void main(String[] args) {
+ Main main = new Main();
+ try {
+ main.processOptions(args);
+ main.run();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+}
--- /dev/null
+package org.vanbest.xmltv;
+
+import java.util.Date;
+
+public class Programme {
+ public String getDb_id() {
+ return db_id;
+ }
+
+ public void setDb_id(String db_id) {
+ this.db_id = db_id;
+ }
+
+ public String getTitel() {
+ return titel;
+ }
+
+ public void setTitel(String titel) {
+ this.titel = titel;
+ }
+
+ public String getGenre() {
+ return genre;
+ }
+
+ public void setGenre(String genre) {
+ this.genre = genre;
+ }
+
+ public String getSoort() {
+ return soort;
+ }
+
+ public void setSoort(String soort) {
+ this.soort = soort;
+ }
+
+ public String getKijkwijzer() {
+ return kijkwijzer;
+ }
+
+ public void setKijkwijzer(String kijkwijzer) {
+ this.kijkwijzer = kijkwijzer;
+ }
+
+ public String getArtikel_id() {
+ return artikel_id;
+ }
+
+ public void setArtikel_id(String artikel_id) {
+ this.artikel_id = artikel_id;
+ }
+
+ public Date getDatum_start() {
+ return datum_start;
+ }
+
+ public void setDatum_start(Date datum_start) {
+ this.datum_start = datum_start;
+ }
+
+ public Date getDatum_end() {
+ return datum_end;
+ }
+
+ public void setDatum_end(Date datum_end) {
+ this.datum_end = datum_end;
+ }
+
+ public boolean isIs_highlight() {
+ return is_highlight;
+ }
+
+ public void setIs_highlight(boolean is_highlight) {
+ this.is_highlight = is_highlight;
+ }
+
+ public String getHighlight_afbeelding() {
+ return highlight_afbeelding;
+ }
+
+ public void setHighlight_afbeelding(String highlight_afbeelding) {
+ this.highlight_afbeelding = highlight_afbeelding;
+ }
+
+ public String getHighlight_content() {
+ return highlight_content;
+ }
+
+ public void setHighlight_content(String highlight_content) {
+ this.highlight_content = highlight_content;
+ }
+
+ String db_id;
+ String titel;
+ String genre;
+ String soort;
+ String kijkwijzer;
+ String artikel_id;
+ Date datum_start;
+ Date datum_end;
+ boolean is_highlight;
+ String highlight_afbeelding;
+ String highlight_content;
+ ProgrammeDetails details = null;
+ Channel channel = null;
+
+ public void fixup(Config config) {
+ this.titel = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(titel);
+ this.genre = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(genre);
+ this.soort = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(soort);
+ this.highlight_content = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(highlight_content);
+ if(config.getCategories().containsKey(genre.toLowerCase())) {
+ genre = config.getCategories().get(genre.toLowerCase());
+ }
+ }
+
+ public String toString() {
+ StringBuffer s = new StringBuffer();
+ s.append("id: " + db_id + ";");
+ s.append("titel: " + titel + ";");
+ s.append("genre: " + genre + ";");
+ s.append("soort: " + soort + ";");
+ s.append("kijkwijzer: " + kijkwijzer+ ";");
+ s.append("artikel_id: " + artikel_id + ";");
+ s.append("datum_start: " + datum_start + ";");
+ s.append("datum_end: " + datum_end + ";");
+ if (details != null) s.append("details:" + details.toString() );
+ s.append("\n");
+
+ return s.toString();
+ }
+}
--- /dev/null
+package org.vanbest.xmltv;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.io.FileUtils;
+
+public class ProgrammeCache {
+ private File cacheFile;
+ private Map<String,ProgrammeDetails> cache;
+
+ public ProgrammeCache(File cacheFile) {
+ this.cacheFile = cacheFile;
+ if (cacheFile.canRead()) {
+ try {
+ cache = (Map<String,ProgrammeDetails>) new ObjectInputStream( new FileInputStream( cacheFile ) ).readObject();
+ } catch (InvalidClassException e) {
+ // TODO Auto-generated catch block
+
+ cache = new HashMap<String,ProgrammeDetails>();
+ } catch (ClassNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ cache = new HashMap<String,ProgrammeDetails>();
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ cache = new HashMap<String,ProgrammeDetails>();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ cache = new HashMap<String,ProgrammeDetails>();
+ }
+ } else {
+ cache = new HashMap<String,ProgrammeDetails>();
+ }
+ // FileUtils.forceMkdir(root);
+ }
+
+ public ProgrammeDetails getDetails(String id) {
+ return cache.get(id);
+ }
+
+ public void add(String id, ProgrammeDetails d) {
+ cache.put(id, d);
+ }
+
+ public void close() throws FileNotFoundException, IOException {
+ new ObjectOutputStream( new FileOutputStream(cacheFile)).writeObject(cache);
+ }
+}
--- /dev/null
+package org.vanbest.xmltv;
+
+import java.io.Serializable;
+
+public class ProgrammeDetails implements Serializable {
+ String db_id;
+ String titel;
+ String datum;
+ String btijd;
+ String etijd;
+ String synop;
+ String kijkwijzer;
+ String genre;
+ String presentatie;
+ String acteursnamen_rolverdeling;
+ String regisseur;
+ String zender_id;
+ public boolean subtitle_teletekst = false;
+ public boolean stereo = false;
+ public boolean blacknwhite = false;
+ public boolean breedbeeld = false;
+ public String quality = null;
+ public boolean herhaling = false;
+
+ public void fixup(Programme p, boolean quiet) {
+ this.titel = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(titel);
+ this.genre = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(genre);
+ this.synop = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(synop);
+ this.synop = this.synop.replaceAll("<br>", " ").
+ replaceAll("<br />", " ").
+ replaceAll("<p>", " ").
+ replaceAll("</p>", " ").
+ replaceAll("<strong>", " ").
+ replaceAll("</strong>", " ").
+ replaceAll("<em>", " ").
+ replaceAll("</em>", " ").
+ trim();
+ if ((synop == null || synop.isEmpty()) && ( genre == null || (!genre.toLowerCase().equals("movies") && !genre.toLowerCase().equals("film")))) {
+ String[] parts = p.titel.split("[[:space:]]*:[[:space:]]*", 2);
+ if (parts.length >= 2 ) {
+ if (!quiet) {
+ System.out.println("Splitting title from \"" + p.titel + "\" to: \"" + parts[0].trim() + "\"; synop: \"" + parts[1].trim() + "\"");
+ }
+ titel = parts[0].trim();
+ p.titel = titel;
+ synop = parts[1].trim();
+ }
+ }
+ this.presentatie = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(presentatie);
+ this.acteursnamen_rolverdeling = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(acteursnamen_rolverdeling);
+ this.regisseur = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(regisseur);
+ }
+
+ public String getDb_id() {
+ return db_id;
+ }
+ public void setDb_id(String db_id) {
+ this.db_id = db_id;
+ }
+ public String getTitel() {
+ return titel;
+ }
+ public void setTitel(String titel) {
+ this.titel = titel;
+ }
+ public String getDatum() {
+ return datum;
+ }
+ public void setDatum(String datum) {
+ this.datum = datum;
+ }
+ public String getBtijd() {
+ return btijd;
+ }
+ public void setBtijd(String btijd) {
+ this.btijd = btijd;
+ }
+ public String getEtijd() {
+ return etijd;
+ }
+ public void setEtijd(String etijd) {
+ this.etijd = etijd;
+ }
+ public String getSynop() {
+ return synop;
+ }
+ public void setSynop(String synop) {
+ this.synop = synop;
+ }
+ public String getKijkwijzer() {
+ return kijkwijzer;
+ }
+ public void setKijkwijzer(String kijkwijzer) {
+ this.kijkwijzer = kijkwijzer;
+ }
+ public String getGenre() {
+ return genre;
+ }
+ public void setGenre(String genre) {
+ this.genre = genre;
+ }
+ public String getPresentatie() {
+ return presentatie;
+ }
+ public void setPresentatie(String presentatie) {
+ this.presentatie = presentatie;
+ }
+ public String getActeursnamen_rolverdeling() {
+ return acteursnamen_rolverdeling;
+ }
+ public void setActeursnamen_rolverdeling(String acteursnamen_rolverdeling) {
+ this.acteursnamen_rolverdeling = acteursnamen_rolverdeling;
+ }
+ public String getRegisseur() {
+ return regisseur;
+ }
+ public void setRegisseur(String regisseur) {
+ this.regisseur = regisseur;
+ }
+ public String getZender_id() {
+ return zender_id;
+ }
+ public void setZender_id(String zender_id) {
+ this.zender_id = zender_id;
+ }
+ @Override
+ public String toString() {
+ return "ProgrammeDetails [db_id=" + db_id + ", titel=" + titel
+ + ", datum=" + datum + ", btijd=" + btijd + ", etijd=" + etijd
+ + ", synop=" + synop + ", kijkwijzer=" + kijkwijzer
+ + ", genre=" + genre + ", presentatie=" + presentatie
+ + ", acteursnamen_rolverdeling=" + acteursnamen_rolverdeling
+ + ", regisseur=" + regisseur + ", zender_id=" + zender_id + "]";
+ }
+}
--- /dev/null
+package org.vanbest.xmltv;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import net.sf.ezmorph.MorpherRegistry;
+import net.sf.ezmorph.ObjectMorpher;
+import net.sf.ezmorph.object.DateMorpher;
+import net.sf.json.JSON;
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+import net.sf.json.util.JSONUtils;
+
+public class TvGids {
+
+ static String channels_url="http://www.tvgids.nl/json/lists/channels.php";
+ static String programme_base_url="http://www.tvgids.nl/json/lists/programs.php";
+ static String detail_base_url = "http://www.tvgids.nl/json/lists/program.php";
+ static String html_detail_base_url = "http://www.tvgids.nl/programma/";
+
+ Config config;
+ ProgrammeCache cache;
+ static boolean initialised = false;
+ int fetchErrors = 0;
+ int cacheHits = 0;
+ int cacheMisses = 0;
+
+ public TvGids(Config config) {
+ this.config = config;
+ cache = new ProgrammeCache(config.cacheFile);
+ if ( ! initialised ) {
+ init();
+ initialised = true;
+ }
+ }
+
+ public static void init() {
+ String[] formats = {"yyyy-MM-dd HH:mm:ss"};
+ MorpherRegistry registry = JSONUtils.getMorpherRegistry();
+ registry.registerMorpher( new DateMorpher(formats, new Locale("nl")));
+ registry.registerMorpher( new ObjectMorpher() {
+ public Object morph(Object value) {
+ String s = (String) value;
+ return org.apache.commons.lang.StringEscapeUtils.unescapeHtml(s);
+ }
+ public Class morphsTo() {
+ return String.class;
+ }
+ public boolean supports(Class clazz) {
+ return clazz == String.class;
+ }
+ }, true);
+ }
+
+ public void close() throws FileNotFoundException, IOException {
+ cache.close();
+ }
+
+ public List<Channel> getChannels() {
+ List<Channel> result = new ArrayList<Channel>(10);
+ URL url = null;
+ try {
+ url = new URL(channels_url);
+ } catch (MalformedURLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ StringBuffer json = new StringBuffer();
+ try {
+
+ BufferedReader reader = new BufferedReader( new InputStreamReader( url.openStream()));
+
+ String s;
+ while ((s = reader.readLine()) != null) json.append(s);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ if (config.logJSON()) System.out.println(json.toString());
+ JSONArray jsonArray = JSONArray.fromObject( json.toString() );
+ // System.out.println( jsonArray );
+
+ for( int i=0; i<jsonArray.size(); i++ ) {
+ JSONObject zender = jsonArray.getJSONObject(i);
+ //System.out.println( "id: " + zender.getString("id"));
+ //System.out.println( "name: " + zender.getString("name"));
+ Channel c = new Channel(zender.getInt("id"), zender.getString("name"), zender.getString("name_short"));
+ c.setIconUrl("http://tvgidsassets.nl/img/channels/53x27/" + c.id + ".png");
+ c.fixup();
+ result.add(c);
+ }
+
+ return result;
+
+ }
+
+ public static URL programmeUrl(List<Channel> channels, int day) throws Exception {
+ StringBuilder s = new StringBuilder(programme_base_url);
+ if (channels.size() < 1) {
+ throw new Exception("should have at least one channel");
+ }
+ s.append("?channels=");
+ boolean first = true;
+ for(Channel i: channels) {
+ if (first) {
+ s.append(i.id);
+ first = false;
+ } else {
+ s.append(","+i.id);
+ }
+ }
+ s.append("&day=");
+ s.append(day);
+
+ return new URL(s.toString());
+ }
+
+ public static URL JSONDetailUrl(String id) throws Exception {
+ StringBuilder s = new StringBuilder(detail_base_url);
+ s.append("?id=");
+ s.append(id);
+ return new URL(s.toString());
+ }
+
+ public static URL HTMLDetailUrl(String id) throws Exception {
+ StringBuilder s = new StringBuilder(html_detail_base_url);
+ s.append(id);
+ s.append("/");
+ return new URL(s.toString());
+ }
+
+ public Set<Programme> getProgrammes(List<Channel> channels, int day, boolean fetchDetails) throws Exception {
+ Set<Programme> result = new HashSet<Programme>();
+ URL url = programmeUrl(channels, day);
+
+ JSONObject jsonObject = fetchJSON(url);
+ //System.out.println( jsonObject );
+
+ for( Channel c: channels) {
+ JSON ps = (JSON) jsonObject.get(""+c.id);
+ if ( ps.isArray() ) {
+ JSONArray programs = (JSONArray) ps;
+ for( int i=0; i<programs.size(); i++ ) {
+ JSONObject programme = programs.getJSONObject(i);
+ Programme p = programmeFromJSON(programme, fetchDetails);
+ p.channel = c;
+ result.add( p );
+ }
+ } else {
+ JSONObject programs = (JSONObject) ps;
+ for( Object o: programs.keySet() ) {
+ JSONObject programme = programs.getJSONObject(o.toString());
+ Programme p = programmeFromJSON(programme, fetchDetails);
+ p.channel = c;
+ result.add( p );
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private Programme programmeFromJSON(JSONObject programme, boolean fetchDetails) throws Exception {
+ Programme p = (Programme) JSONObject.toBean(programme, Programme.class);
+ p.fixup(config);
+ if (fetchDetails) {
+ fillDetails(p);
+ }
+ if(config.logProgrammes()) {
+ System.out.println(p.toString());
+ }
+ return p;
+ }
+
+ private String fetchURL(URL url) throws Exception {
+ Thread.sleep(config.niceMilliseconds);
+ StringBuffer buf = new StringBuffer();
+ try {
+ BufferedReader reader = new BufferedReader( new InputStreamReader( url.openStream()));
+ String s;
+ while ((s = reader.readLine()) != null) buf.append(s);
+ } catch (IOException e) {
+ fetchErrors++;
+ throw new Exception("Error getting program data from url " + url, e);
+ }
+ return buf.toString();
+ }
+
+ private JSONObject fetchJSON(URL url) throws Exception {
+ String json = fetchURL(url);
+ if (config.logJSON()) System.out.println(json);
+ return JSONObject.fromObject( json );
+ }
+
+ private void fillDetails(Programme p) throws Exception {
+ Pattern progInfoPattern = Pattern.compile("prog-info-content.*prog-info-footer", Pattern.DOTALL);
+ Pattern infoLinePattern = Pattern.compile("<li><strong>(.*?):</strong>(.*?)</li>");
+ Pattern HDPattern = Pattern.compile("HD \\d+[ip]?");
+ Pattern kijkwijzerPattern = Pattern.compile("<img src=\"http://tvgidsassets.nl/img/kijkwijzer/.*?\" alt=\"(.*?)\" />");
+
+ p.details = cache.getDetails(p.db_id);
+ if ( p.details == null ) {
+ cacheMisses++;
+
+ URL url = JSONDetailUrl(p.db_id);
+ JSONObject json = fetchJSON(url);
+ p.details = (ProgrammeDetails) JSONObject.toBean(json, ProgrammeDetails.class);
+
+ url = HTMLDetailUrl(p.db_id);
+ String clob=fetchURL(url);
+ //System.out.println("clob:");
+ //System.out.println(clob);
+ Matcher m = progInfoPattern.matcher(clob);
+ if (m.find()) {
+ String progInfo = m.group();
+ //System.out.println("progInfo");
+ //System.out.println(progInfo);
+ Matcher m2 = infoLinePattern.matcher(progInfo);
+ while (m2.find()) {
+ //System.out.println(" infoLine: " + m2.group());
+ //System.out.println(" key: " + m2.group(1));
+ //System.out.println(" value: " + m2.group(2));
+ String key = m2.group(1);
+ String value = m2.group(2);
+ switch(key.toLowerCase()) {
+ case "bijzonderheden":
+ String[] list = value.split(",");
+ for( String item: list) {
+ if (item.toLowerCase().contains("teletekst")) {
+ p.details.subtitle_teletekst = true;
+ } else if (item.toLowerCase().contains("breedbeeld")) {
+ p.details.breedbeeld = true;
+ } else if (value.toLowerCase().contains("zwart")) {
+ p.details.blacknwhite = true;
+ } else if (value.toLowerCase().contains("stereo")) {
+ p.details.stereo = true;
+ } else if (value.toLowerCase().contains("herhaling")) {
+ p.details.herhaling = true;
+ } else {
+ Matcher m3 = HDPattern.matcher(value);
+ if (m3.find()) {
+ p.details.quality = m3.group();
+ } else {
+ if (!config.quiet) System.out.println(" Unknown value in 'bijzonderheden': " + item);
+ }
+ }
+ }
+ break;
+ }
+ Matcher m3 = kijkwijzerPattern.matcher(progInfo);
+ List<String> kijkwijzer = new ArrayList<String>();
+ while (m3.find()) {
+ kijkwijzer.add(m3.group(1));
+ }
+ if (!kijkwijzer.isEmpty()) {
+ // log.debug()
+ // System.out.println(" (kijkwijzer): " + p.details.kijkwijzer);
+ // System.out.println(" kijkwijzer: " + kijkwijzer);
+ }
+ }
+ }
+
+ p.details.fixup(p, config.quiet);
+ cache.add(p.db_id, p.details);
+ } else {
+ cacheHits++;
+ }
+ }
+}
--- /dev/null
+package org.vanbest.xmltv;
+
+import java.io.OutputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.List;
+
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLEventFactory;
+import javax.xml.stream.XMLStreamException;
+
+public class XmlTvWriter {
+
+ private XMLStreamWriter writer;
+ private XMLEventFactory eventFactory;
+ private Config config;
+
+ public XmlTvWriter(OutputStream os, Config config) throws XMLStreamException, FactoryConfigurationError {
+ this.config = config;
+ this.writer = XMLOutputFactory.newInstance().createXMLStreamWriter(os);
+ this.eventFactory = XMLEventFactory.newInstance();
+
+ writer.writeStartDocument();
+ writer.writeCharacters("\n");
+ writer.writeDTD("<!DOCTYPE tv SYSTEM \"xmltv.dtd\">");
+ writer.writeCharacters("\n");
+ writer.writeStartElement("tv");
+ writer.writeAttribute("generator-info-url","http://www.vanbest.org/");
+ writer.writeAttribute("source-info-url", "http://tvgids.nl/");
+ writer.writeAttribute("source-info-name", "TvGids.nl");
+ writer.writeAttribute("generator-info-name", "tv_grab_nl_java release 0.4");
+ writeln();
+ }
+
+ public void writeln() throws XMLStreamException {
+ writer.writeCharacters(System.getProperty("line.separator"));
+ }
+
+ public void writeChannels(List<Channel> channels) throws XMLStreamException {
+ for(Channel c: channels) {
+ writer.writeStartElement("channel");
+ writer.writeAttribute("id", c.getChannelId());
+ writer.writeStartElement("display-name");
+ writer.writeAttribute("lang", "nl");
+ writer.writeCharacters(c.name);
+ writer.writeEndElement();
+
+ if (c.iconUrl != null) {
+ writer.writeStartElement("icon");
+ writer.writeAttribute("src", c.iconUrl);
+ writer.writeEndElement();
+ }
+
+ writer.writeEndElement();
+ writeln(); }
+ }
+
+ /* TODO:
+ * boolean is_highlight;
+ * String highlight_afbeelding;
+ * String highlight_content;
+ * soort
+ * artikel_id ???
+ *
+ */
+ public void writePrograms(Collection<Programme> programs) throws XMLStreamException {
+ DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss Z");
+ for(Programme p: programs) {
+ writer.writeStartElement("programme");
+ writer.writeAttribute("start", df.format(p.datum_start));
+ writer.writeAttribute("stop", df.format(p.datum_end));
+ writer.writeAttribute("channel", ""+p.channel.getChannelId());
+ writeln();
+
+ writer.writeStartElement("title");
+ writer.writeAttribute("lang", "nl");
+ writer.writeCharacters(p.titel);
+ writer.writeEndElement();
+ writeln();
+
+ if(p.details.synop != null && ! p.details.synop.isEmpty()) {
+ writer.writeStartElement("desc");
+ writer.writeAttribute("lang", "nl");
+ writer.writeCharacters(p.details.synop);
+ writer.writeEndElement();
+ writeln();
+ }
+
+ if (p.details != null) {
+ if ( p.is_highlight) {
+ //System.out.println("Highlight");
+ //System.out.println(" " + p.highlight_afbeelding);
+ //System.out.println(" " + p.highlight_content);
+ } else {
+ if (p.highlight_afbeelding!= null && !p.highlight_afbeelding.isEmpty()) {
+ //System.out.println("highlight_afbeelding: " + p.highlight_afbeelding);
+ }
+ if (p.highlight_content!= null && !p.highlight_content.isEmpty()) {
+ //System.out.println("highlight_content: " + p.highlight_content);
+ }
+ }
+ if ( (p.details.presentatie != null && !p.details.presentatie.isEmpty()) ||
+ (p.details.regisseur != null && !p.details.regisseur.isEmpty()) ||
+ (p.details.acteursnamen_rolverdeling != null && !p.details.acteursnamen_rolverdeling.isEmpty())
+ ) {
+ writer.writeStartElement("credits");
+ if (p.details.regisseur != null && !p.details.regisseur.isEmpty()) {
+ String[] parts = p.details.regisseur.split(",");
+ for (String s: parts) {
+ writer.writeStartElement("director");
+ writer.writeCharacters(s.trim());
+ writer.writeEndElement();
+ }
+ }
+ if (p.details.acteursnamen_rolverdeling != null && !p.details.acteursnamen_rolverdeling.isEmpty()) {
+ String[] parts = p.details.acteursnamen_rolverdeling.split(",");
+ for (String s: parts) {
+ writer.writeStartElement("actor");
+ writer.writeCharacters(s.trim());
+ writer.writeEndElement();
+ }
+ }
+ if (p.details.presentatie != null && !p.details.presentatie.isEmpty()) {
+ String[] parts = p.details.presentatie.split(",");
+ for (String s: parts) {
+ writer.writeStartElement("presenter");
+ writer.writeCharacters(s.trim());
+ writer.writeEndElement();
+ }
+ }
+ writer.writeEndElement();
+ writeln();
+ }
+ writer.writeStartElement("category");
+ writer.writeAttribute("lang", "en");
+ writer.writeCharacters(p.genre);
+ writer.writeEndElement();
+ writeln();
+
+ if (p.details.blacknwhite || p.details.breedbeeld) {
+ writer.writeStartElement("video");
+ if (p.details.blacknwhite) {
+ writer.writeStartElement("colour");
+ writer.writeCharacters("no");
+ writer.writeEndElement();
+ }
+ if (p.details.breedbeeld) {
+ writer.writeStartElement("aspect");
+ writer.writeCharacters("16x9");
+ writer.writeEndElement();
+ }
+ if (p.details.quality != null) {
+ writer.writeStartElement("quality");
+ writer.writeCharacters(p.details.quality);
+ writer.writeEndElement();
+ }
+ writer.writeEndElement();
+ writeln();
+ }
+
+ if (p.details.stereo) {
+ writer.writeStartElement("audio");
+ writer.writeStartElement("stereo");
+ writer.writeCharacters("stereo");
+ writer.writeEndElement();
+ writer.writeEndElement();
+ writeln();
+ }
+
+ if (p.details.herhaling) {
+ writer.writeEmptyElement("previously-shown");
+ }
+
+ if (p.details.subtitle_teletekst) {
+ writer.writeStartElement("subtitles");
+ writer.writeAttribute("type", "teletext");
+ writer.writeEndElement();
+ writeln();
+ }
+
+ /* TODO: Icon attribuut gebruiken?
+ */
+ if (p.details.kijkwijzer != null && !p.details.kijkwijzer.isEmpty()) {
+ writer.writeStartElement("rating");
+ writer.writeAttribute("system", "kijkwijzer");
+ writer.writeStartElement("value");
+ for (int i=0; i<p.details.kijkwijzer.length(); i++) {
+ if (i!=0) writer.writeCharacters(", ");
+ char c = p.details.kijkwijzer.charAt(i);
+ switch(c) {
+ case 'a':writer.writeCharacters("Angst"); break;
+ case 'd':writer.writeCharacters("Discriminatie"); break;
+ case 's':writer.writeCharacters("Seks"); break;
+ case 'h':writer.writeCharacters("Drugs/Alcohol"); break;
+ case 'g':writer.writeCharacters("Geweld"); break;
+ case 't':writer.writeCharacters("Grof taalgebruik"); break;
+ case '1':writer.writeCharacters("Voor alle leeftijden"); break;
+ case '2':writer.writeCharacters("Afgeraden voor kinderen jonger dan 6 jaar"); break;
+ case '9':writer.writeCharacters("Afgeraden voor kinderen jonger dan 9 jaar"); break;
+ case '3':writer.writeCharacters("Afgeraden voor kinderen jonger dan 12 jaar"); break;
+ case '4':writer.writeCharacters("Afgeraden voor kinderen jonger dan 16 jaar"); break;
+ default: if (!config.quiet) {
+ System.out.println("Unknown kijkwijzer character: " + p.details.kijkwijzer);
+ System.out.println(" for show " + p.titel + " at channel " + p.channel.name + " at " + p.datum_start);
+ }
+ }
+ }
+ //writer.writeStartElement("value");
+ // writer.writeCharacters(p.details.kijkwijzer);
+ //writer.writeEndElement();
+ writer.writeEndElement();
+ writer.writeEndElement();
+ writeln();
+ }
+ }
+ writer.writeEndElement();
+ writeln();
+ }
+ }
+
+ public void close() throws XMLStreamException {
+ writer.writeEndElement();
+ writer.writeEndDocument();
+ writer.flush();
+ }
+
+ public void flush() throws XMLStreamException {
+ writer.flush();
+ }
+}
+++ /dev/null
-package org.vanbest.xmltv;
-
-public class Channel {
- int id;
- String name;
- String shortName;
- String iconUrl;
- boolean selected;
-
- public Channel(int id, String name, String shortName) {
- this.id = id;
- this.name = name;
- this.shortName = shortName;
- }
- public String toString() {
- return "id: " + id + "; name: " + name + "; shortName: " + shortName;
- }
-
- public String getChannelId() {
- return id+".tvgids.nl";
- }
-
- public void fixup() {
- this.name = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(name);
- this.shortName = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(shortName);
- }
- public void setIconUrl(String url) {
- this.iconUrl = url;
- }
-}
+++ /dev/null
-package org.vanbest.xmltv;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.io.FileUtils;
-
-public class Config {
- public int niceMilliseconds;
- public List<Channel> channels;
- public Map<String, String> cattrans;
- protected File cacheFile;
- boolean quiet = false;
- public int logLevel = LOG_DEFAULT;
-
- public static final int LOG_INFO = 0x0001;
- public static final int LOG_JSON = 0x0100;
- private static final int LOG_PROGRAMME_INFO = 0x0200;
-
- public static int LOG_DEFAULT = LOG_INFO;
-
- private Config() {
- }
-
- public static Config getDefaultConfig() {
- Config result = new Config();
- result.channels = new ArrayList<Channel>();
- result.cattrans = getDefaultCattrans();
- result.cacheFile = defaultCacheFile();
- result.niceMilliseconds = 500;
- return result;
- }
-
- public Map<String,String> getCategories() {
- return cattrans;
- }
-
- public void setChannels(List<Channel> channels) {
- this.channels = channels;
- }
-
- public static File defaultCacheFile() {
- return FileUtils.getFile(FileUtils.getUserDirectory(), ".xmltv", "tv_grab_nl_java.cache");
- }
-
- static private Map<String,String> getDefaultCattrans() {
- Map<String,String> result = new HashMap<String,String>();
- result.put("amusement", "Animated");
- result.put("comedy", "Comedy");
- result.put("documentaire", "Documentary");
- result.put("educatief", "Educational");
- result.put("erotiek", "Adult");
- result.put("film", "Film");
- result.put("muziek", "Art/Music");
- result.put("informatief", "Educational");
- result.put("jeugd", "Children");
- result.put("kunst/cultuur", "Arts/Culture");
- result.put("misdaad", "Crime/Mystery");
- result.put("muziek", "Music");
- result.put("natuur", "Science/Nature");
- result.put("nieuws/actualiteiten", "News");
- result.put("overige", "Unknown");
- result.put("religieus", "Religion");
- result.put("serie/soap", "Drama");
- result.put("sport", "Sports");
- result.put("theater", "Arts/Culture");
- result.put("wetenschap", "Science/Nature");
- return result;
- }
-
- public void writeConfig(File configFile) throws IOException {
- FileUtils.forceMkdir(configFile.getParentFile());
- PrintWriter out = new PrintWriter(new OutputStreamWriter( new FileOutputStream( configFile )));
- out.println("cache-file: " + escape(cacheFile.getPath()));
- out.println("nice-time-milliseconds: " + niceMilliseconds);
- for(Channel c: channels) {
- if (!c.selected) {
- out.print("#");
- }
- out.print("channel: " + c.id + ": " + escape(c.name));
- if (c.iconUrl != null) {
- out.print(" : " + escape(c.iconUrl));
- }
- out.println();
- }
- for(Map.Entry<String,String> entry: cattrans.entrySet()) {
- out.println("category: " + escape(entry.getKey()) + ": " + escape(entry.getValue()));
- }
- out.close();
- }
-
- public static String escape(String s) {
- return "\"" + s.replace("\\", "\\\\").replaceAll("\\\"", "\\\\\"") + "\"";
- }
-
- public static List<String> splitLine(String s) {
- List<String> parts = new ArrayList<String>(5);
- int pos=0;
- while (true) {
- // Find first colon outside quotes
- boolean quoted=false;
- int quoteStart=-1;
- StringBuffer buf = new StringBuffer();
- for (; pos<s.length(); pos++) {
- if (s.charAt(pos)=='"') {
- if (quoted) {
- //System.out.println(s.substring(quoteStart, pos));
- buf.append(s.substring(quoteStart, pos).replaceAll("\\\\\"", "\\\"").replaceAll("\\\\\\\\","\\\\"));
- } else {
- quoteStart = pos+1;
- }
- quoted=!quoted;
- continue;
- }
- if(s.charAt(pos)=='\\') pos++;
- if(quoted) continue;
- if(s.charAt(pos)==':') {
- break;
- }
- buf.append(s.charAt(pos));
- }
- parts.add(buf.toString().trim());
- if (pos>=s.length()) {
- break;
- }
- pos++;
- }
- return parts;
- }
-
- public static Config readConfig(File file) {
- Config result = getDefaultConfig();
- result.cattrans = new HashMap<String,String>();
- try {
- BufferedReader reader = new BufferedReader( new InputStreamReader( new FileInputStream( file)));
-
- while(true) {
- String s = reader.readLine();
- if(s==null) break;
- if (!s.contains(":")) continue;
- if (s.startsWith("#")) continue;
- List<String> parts = splitLine(s);
- if (parts.get(0).toLowerCase().equals("channel")) {
- Channel c = new Channel(Integer.parseInt(parts.get(1)), parts.get(2), "");
- if (parts.size()>3) {
- c.setIconUrl(parts.get(3));
- }
- result.channels.add(c);
- }
- switch (parts.get(0).toLowerCase()) {
- case "category" :
- result.cattrans.put(parts.get(1), parts.get(2));
- break;
- case "cache-file":
- result.cacheFile = new File(parts.get(1));
- break;
- case "nice-time-milliseconds":
- result.niceMilliseconds = Integer.parseInt(parts.get(1));
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- System.out.println("Error reading configuration file, continuing with empty configuration");
- return getDefaultConfig();
- }
- return result;
- }
-
- public boolean logJSON() {
- return (logLevel & LOG_JSON) != 0;
- }
-
- public boolean logProgrammes() {
- return (logLevel & LOG_PROGRAMME_INFO) != 0;
- }
-
-}
-
+++ /dev/null
-package org.vanbest.xmltv;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.xml.stream.FactoryConfigurationError;
-import javax.xml.stream.XMLStreamException;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.GnuParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.cli.Parser;
-import org.apache.commons.io.FileUtils;
-
-public class Main {
- private File configFile;
- private Config config;
- private PrintStream outputWriter;
- private int days = 5;
- private int offset = 0;
- /**
- * @param args
- */
-
- public Main() {
- this.configFile = defaultConfigFile();
- this.outputWriter = System.out;
- }
-
- public void run() throws FactoryConfigurationError, Exception {
- if (!config.quiet) {
- System.out.println("Fetching programme data for days " + this.offset + "-" + (this.offset+this.days-1));
- System.out.println("... from " + config.channels.size() + " channels");
- System.out.println("... using cache file " + config.cacheFile.getCanonicalPath());
- }
-
- XmlTvWriter writer = new XmlTvWriter(outputWriter, config);
- writer.writeChannels(config.channels);
-
- TvGids gids = new TvGids(config);
-
- for (int day=offset; day<offset+days; day++) {
- if (!config.quiet) System.out.print("Fetching information for day " + day);
- Set<Programme> programmes = new HashSet<Programme>();
- for( Channel c: config.channels ) {
- if (!config.quiet) System.out.print(".");
- ArrayList<Channel> cs = new ArrayList<Channel>(2);
- cs.add(c);
- Set<Programme> p = gids.getProgrammes(cs, day, true);
- writer.writePrograms(p);
- writer.flush();
- }
- if (!config.quiet) System.out.println();
- }
-
- try {
- gids.close();
- } catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- writer.close();
- if (!config.quiet) {
- System.out.println("Number of programmes from cache: " + gids.cacheHits);
- System.out.println("Number of programmes fetched: " + gids.cacheMisses);
- System.out.println("Number of fetch errors: " + gids.fetchErrors);
- }
- }
-
- public void configure() throws IOException {
- TvGids gids = new TvGids(config);
-
- Set<Integer> oldChannels = new HashSet<Integer>();
- for (Channel c: config.channels) {
- oldChannels.add(c.id);
- }
- List<Channel> channels = gids.getChannels();
-
- BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
- boolean all = false;
- boolean none = false;
- boolean keep = false;
- for (Channel c: channels) {
- boolean selected = oldChannels.contains(c.id);
- System.out.print("add channel " + c.id + " (" + c.name + ") [[y]es,[n]o,[a]ll,[none],[k]eep selection (default=" + (selected?"yes":"no") + ")] ");
- if (keep) {
- c.selected = selected;
- System.out.println(selected?"Y":"N");
- continue;
- }
- if (all) {
- c.selected = true;
- System.out.println("Y");
- continue;
- }
- if (none) {
- c.selected = false;
- System.out.println("N");
- continue;
- }
- while(true) {
- String s = reader.readLine().toLowerCase();
- if (s.isEmpty()) {
- c.selected = selected;
- break;
- } else if ( s.startsWith("k")) {
- c.selected = selected;
- keep = true;
- break;
- } else if ( s.startsWith("y")) {
- c.selected = true;
- break;
- } else if ( s.startsWith("a")) {
- c.selected = true;
- all = true;
- break;
- } else if ( s.startsWith("none")) {
- c.selected = false;
- none = true;
- break;
- } else if ( s.startsWith("n")) {
- c.selected = false;
- break;
- }
- }
- }
-
- config.setChannels(channels);
- try {
- config.writeConfig(configFile);
- System.out.println("Configuration file written to " + configFile.getPath());
- } catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- public void processOptions(String[] args) throws FileNotFoundException {
- Options options = new Options();
- options.addOption("d", "description", false, "Display a description to identify this grabber");
- options.addOption("c", "capabilities", false, "Show grabber capabilities");
- options.addOption("q", "quiet", false, "Be quiet");
- options.addOption("o", "output", true, "Set xlmtv output filename");
- options.addOption("y", "days", true, "Number of days to grab");
- options.addOption("s", "offset", true, "Start day for grabbing (0=today)");
- options.addOption("n", "configure", false, "Interactive configuration");
- options.addOption("f", "config-file", true, "Configuration file location");
- options.addOption("h", "cache", true, "Cache file location");
- options.addOption("e", "help", false, "Show this help");
- options.addOption("l", "log-level", true, "Set log level (0x0100=JSON)");
- //options.addOption("p", "preferredmethod", false, "Show preferred method");
-
- CommandLine line = null;
- try {
- line = new GnuParser().parse(options, args);
- } catch (ParseException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- if (line.hasOption("d")) {
- System.out.println("tv_grab_nl_java is a parser for Dutch TV listings using the tvgids.nl JSON interface");
- System.exit(0);
- }
- if (line.hasOption("e")) {
- // automatically generate the help statement
- HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp( "tv_grab_nl_java", options );
- System.exit(0);
- }
- if(line.hasOption("f")) {
- configFile = new File(line.getOptionValue("f"));
- }
- config = Config.readConfig(configFile);
- if (line.hasOption("q")) {
- config.quiet = true;
- }
-
- if (line.hasOption("o")) {
- this.outputWriter = new PrintStream( new FileOutputStream(line.getOptionValue("o")));
- }
- if (line.hasOption("l")) {
- config.logLevel = Integer.parseInt(line.getOptionValue("l"));
- }
- if (line.hasOption("h")) {
- config.cacheFile = new File(line.getOptionValue("h"));
- }
- if (line.hasOption("y")) {
- this.days = Integer.parseInt(line.getOptionValue("y"));
- }
- if (line.hasOption("s")) {
- this.offset = Integer.parseInt(line.getOptionValue("s"));
- }
- if (line.hasOption("c")) {
- System.out.println("baseline");
- System.out.println("manualconfig");
- System.out.println("cache");
- // System.out.println("preferredmethod");
- System.exit(0);
- }
- if (line.hasOption("n")) {
- try {
- configure();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- System.exit(0);
- }
-
- }
-
- public static File defaultConfigFile() {
- return FileUtils.getFile(FileUtils.getUserDirectory(), ".xmltv", "tv_grab_nl_java.conf");
- }
-
- public static void main(String[] args) {
- Main main = new Main();
- try {
- main.processOptions(args);
- main.run();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
-}
+++ /dev/null
-package org.vanbest.xmltv;
-
-import java.util.Date;
-
-public class Programme {
- public String getDb_id() {
- return db_id;
- }
-
- public void setDb_id(String db_id) {
- this.db_id = db_id;
- }
-
- public String getTitel() {
- return titel;
- }
-
- public void setTitel(String titel) {
- this.titel = titel;
- }
-
- public String getGenre() {
- return genre;
- }
-
- public void setGenre(String genre) {
- this.genre = genre;
- }
-
- public String getSoort() {
- return soort;
- }
-
- public void setSoort(String soort) {
- this.soort = soort;
- }
-
- public String getKijkwijzer() {
- return kijkwijzer;
- }
-
- public void setKijkwijzer(String kijkwijzer) {
- this.kijkwijzer = kijkwijzer;
- }
-
- public String getArtikel_id() {
- return artikel_id;
- }
-
- public void setArtikel_id(String artikel_id) {
- this.artikel_id = artikel_id;
- }
-
- public Date getDatum_start() {
- return datum_start;
- }
-
- public void setDatum_start(Date datum_start) {
- this.datum_start = datum_start;
- }
-
- public Date getDatum_end() {
- return datum_end;
- }
-
- public void setDatum_end(Date datum_end) {
- this.datum_end = datum_end;
- }
-
- public boolean isIs_highlight() {
- return is_highlight;
- }
-
- public void setIs_highlight(boolean is_highlight) {
- this.is_highlight = is_highlight;
- }
-
- public String getHighlight_afbeelding() {
- return highlight_afbeelding;
- }
-
- public void setHighlight_afbeelding(String highlight_afbeelding) {
- this.highlight_afbeelding = highlight_afbeelding;
- }
-
- public String getHighlight_content() {
- return highlight_content;
- }
-
- public void setHighlight_content(String highlight_content) {
- this.highlight_content = highlight_content;
- }
-
- String db_id;
- String titel;
- String genre;
- String soort;
- String kijkwijzer;
- String artikel_id;
- Date datum_start;
- Date datum_end;
- boolean is_highlight;
- String highlight_afbeelding;
- String highlight_content;
- ProgrammeDetails details = null;
- Channel channel = null;
-
- public void fixup(Config config) {
- this.titel = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(titel);
- this.genre = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(genre);
- this.soort = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(soort);
- this.highlight_content = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(highlight_content);
- if(config.getCategories().containsKey(genre.toLowerCase())) {
- genre = config.getCategories().get(genre.toLowerCase());
- }
- }
-
- public String toString() {
- StringBuffer s = new StringBuffer();
- s.append("id: " + db_id + ";");
- s.append("titel: " + titel + ";");
- s.append("genre: " + genre + ";");
- s.append("soort: " + soort + ";");
- s.append("kijkwijzer: " + kijkwijzer+ ";");
- s.append("artikel_id: " + artikel_id + ";");
- s.append("datum_start: " + datum_start + ";");
- s.append("datum_end: " + datum_end + ";");
- if (details != null) s.append("details:" + details.toString() );
- s.append("\n");
-
- return s.toString();
- }
-}
+++ /dev/null
-package org.vanbest.xmltv;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InvalidClassException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.io.FileUtils;
-
-public class ProgrammeCache {
- private File cacheFile;
- private Map<String,ProgrammeDetails> cache;
-
- public ProgrammeCache(File cacheFile) {
- this.cacheFile = cacheFile;
- if (cacheFile.canRead()) {
- try {
- cache = (Map<String,ProgrammeDetails>) new ObjectInputStream( new FileInputStream( cacheFile ) ).readObject();
- } catch (InvalidClassException e) {
- // TODO Auto-generated catch block
-
- cache = new HashMap<String,ProgrammeDetails>();
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- cache = new HashMap<String,ProgrammeDetails>();
- } catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- cache = new HashMap<String,ProgrammeDetails>();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- cache = new HashMap<String,ProgrammeDetails>();
- }
- } else {
- cache = new HashMap<String,ProgrammeDetails>();
- }
- // FileUtils.forceMkdir(root);
- }
-
- public ProgrammeDetails getDetails(String id) {
- return cache.get(id);
- }
-
- public void add(String id, ProgrammeDetails d) {
- cache.put(id, d);
- }
-
- public void close() throws FileNotFoundException, IOException {
- new ObjectOutputStream( new FileOutputStream(cacheFile)).writeObject(cache);
- }
-}
+++ /dev/null
-package org.vanbest.xmltv;
-
-import java.io.Serializable;
-
-public class ProgrammeDetails implements Serializable {
- String db_id;
- String titel;
- String datum;
- String btijd;
- String etijd;
- String synop;
- String kijkwijzer;
- String genre;
- String presentatie;
- String acteursnamen_rolverdeling;
- String regisseur;
- String zender_id;
- public boolean subtitle_teletekst = false;
- public boolean stereo = false;
- public boolean blacknwhite = false;
- public boolean breedbeeld = false;
- public String quality = null;
- public boolean herhaling = false;
-
- public void fixup(Programme p, boolean quiet) {
- this.titel = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(titel);
- this.genre = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(genre);
- this.synop = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(synop);
- this.synop = this.synop.replaceAll("<br>", " ").
- replaceAll("<br />", " ").
- replaceAll("<p>", " ").
- replaceAll("</p>", " ").
- replaceAll("<strong>", " ").
- replaceAll("</strong>", " ").
- replaceAll("<em>", " ").
- replaceAll("</em>", " ").
- trim();
- if ((synop == null || synop.isEmpty()) && ( genre == null || (!genre.toLowerCase().equals("movies") && !genre.toLowerCase().equals("film")))) {
- String[] parts = p.titel.split("[[:space:]]*:[[:space:]]*", 2);
- if (parts.length >= 2 ) {
- if (!quiet) {
- System.out.println("Splitting title from \"" + p.titel + "\" to: \"" + parts[0].trim() + "\"; synop: \"" + parts[1].trim() + "\"");
- }
- titel = parts[0].trim();
- p.titel = titel;
- synop = parts[1].trim();
- }
- }
- this.presentatie = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(presentatie);
- this.acteursnamen_rolverdeling = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(acteursnamen_rolverdeling);
- this.regisseur = org.apache.commons.lang.StringEscapeUtils.unescapeHtml(regisseur);
- }
-
- public String getDb_id() {
- return db_id;
- }
- public void setDb_id(String db_id) {
- this.db_id = db_id;
- }
- public String getTitel() {
- return titel;
- }
- public void setTitel(String titel) {
- this.titel = titel;
- }
- public String getDatum() {
- return datum;
- }
- public void setDatum(String datum) {
- this.datum = datum;
- }
- public String getBtijd() {
- return btijd;
- }
- public void setBtijd(String btijd) {
- this.btijd = btijd;
- }
- public String getEtijd() {
- return etijd;
- }
- public void setEtijd(String etijd) {
- this.etijd = etijd;
- }
- public String getSynop() {
- return synop;
- }
- public void setSynop(String synop) {
- this.synop = synop;
- }
- public String getKijkwijzer() {
- return kijkwijzer;
- }
- public void setKijkwijzer(String kijkwijzer) {
- this.kijkwijzer = kijkwijzer;
- }
- public String getGenre() {
- return genre;
- }
- public void setGenre(String genre) {
- this.genre = genre;
- }
- public String getPresentatie() {
- return presentatie;
- }
- public void setPresentatie(String presentatie) {
- this.presentatie = presentatie;
- }
- public String getActeursnamen_rolverdeling() {
- return acteursnamen_rolverdeling;
- }
- public void setActeursnamen_rolverdeling(String acteursnamen_rolverdeling) {
- this.acteursnamen_rolverdeling = acteursnamen_rolverdeling;
- }
- public String getRegisseur() {
- return regisseur;
- }
- public void setRegisseur(String regisseur) {
- this.regisseur = regisseur;
- }
- public String getZender_id() {
- return zender_id;
- }
- public void setZender_id(String zender_id) {
- this.zender_id = zender_id;
- }
- @Override
- public String toString() {
- return "ProgrammeDetails [db_id=" + db_id + ", titel=" + titel
- + ", datum=" + datum + ", btijd=" + btijd + ", etijd=" + etijd
- + ", synop=" + synop + ", kijkwijzer=" + kijkwijzer
- + ", genre=" + genre + ", presentatie=" + presentatie
- + ", acteursnamen_rolverdeling=" + acteursnamen_rolverdeling
- + ", regisseur=" + regisseur + ", zender_id=" + zender_id + "]";
- }
-}
+++ /dev/null
-package org.vanbest.xmltv;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import net.sf.ezmorph.MorpherRegistry;
-import net.sf.ezmorph.ObjectMorpher;
-import net.sf.ezmorph.object.DateMorpher;
-import net.sf.json.JSON;
-import net.sf.json.JSONArray;
-import net.sf.json.JSONObject;
-import net.sf.json.util.JSONUtils;
-
-public class TvGids {
-
- static String channels_url="http://www.tvgids.nl/json/lists/channels.php";
- static String programme_base_url="http://www.tvgids.nl/json/lists/programs.php";
- static String detail_base_url = "http://www.tvgids.nl/json/lists/program.php";
- static String html_detail_base_url = "http://www.tvgids.nl/programma/";
-
- Config config;
- ProgrammeCache cache;
- static boolean initialised = false;
- int fetchErrors = 0;
- int cacheHits = 0;
- int cacheMisses = 0;
-
- public TvGids(Config config) {
- this.config = config;
- cache = new ProgrammeCache(config.cacheFile);
- if ( ! initialised ) {
- init();
- initialised = true;
- }
- }
-
- public static void init() {
- String[] formats = {"yyyy-MM-dd HH:mm:ss"};
- MorpherRegistry registry = JSONUtils.getMorpherRegistry();
- registry.registerMorpher( new DateMorpher(formats, new Locale("nl")));
- registry.registerMorpher( new ObjectMorpher() {
- public Object morph(Object value) {
- String s = (String) value;
- return org.apache.commons.lang.StringEscapeUtils.unescapeHtml(s);
- }
- public Class morphsTo() {
- return String.class;
- }
- public boolean supports(Class clazz) {
- return clazz == String.class;
- }
- }, true);
- }
-
- public void close() throws FileNotFoundException, IOException {
- cache.close();
- }
-
- public List<Channel> getChannels() {
- List<Channel> result = new ArrayList<Channel>(10);
- URL url = null;
- try {
- url = new URL(channels_url);
- } catch (MalformedURLException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- StringBuffer json = new StringBuffer();
- try {
-
- BufferedReader reader = new BufferedReader( new InputStreamReader( url.openStream()));
-
- String s;
- while ((s = reader.readLine()) != null) json.append(s);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- if (config.logJSON()) System.out.println(json.toString());
- JSONArray jsonArray = JSONArray.fromObject( json.toString() );
- // System.out.println( jsonArray );
-
- for( int i=0; i<jsonArray.size(); i++ ) {
- JSONObject zender = jsonArray.getJSONObject(i);
- //System.out.println( "id: " + zender.getString("id"));
- //System.out.println( "name: " + zender.getString("name"));
- Channel c = new Channel(zender.getInt("id"), zender.getString("name"), zender.getString("name_short"));
- c.setIconUrl("http://tvgidsassets.nl/img/channels/53x27/" + c.id + ".png");
- c.fixup();
- result.add(c);
- }
-
- return result;
-
- }
-
- public static URL programmeUrl(List<Channel> channels, int day) throws Exception {
- StringBuilder s = new StringBuilder(programme_base_url);
- if (channels.size() < 1) {
- throw new Exception("should have at least one channel");
- }
- s.append("?channels=");
- boolean first = true;
- for(Channel i: channels) {
- if (first) {
- s.append(i.id);
- first = false;
- } else {
- s.append(","+i.id);
- }
- }
- s.append("&day=");
- s.append(day);
-
- return new URL(s.toString());
- }
-
- public static URL JSONDetailUrl(String id) throws Exception {
- StringBuilder s = new StringBuilder(detail_base_url);
- s.append("?id=");
- s.append(id);
- return new URL(s.toString());
- }
-
- public static URL HTMLDetailUrl(String id) throws Exception {
- StringBuilder s = new StringBuilder(html_detail_base_url);
- s.append(id);
- s.append("/");
- return new URL(s.toString());
- }
-
- public Set<Programme> getProgrammes(List<Channel> channels, int day, boolean fetchDetails) throws Exception {
- Set<Programme> result = new HashSet<Programme>();
- URL url = programmeUrl(channels, day);
-
- JSONObject jsonObject = fetchJSON(url);
- //System.out.println( jsonObject );
-
- for( Channel c: channels) {
- JSON ps = (JSON) jsonObject.get(""+c.id);
- if ( ps.isArray() ) {
- JSONArray programs = (JSONArray) ps;
- for( int i=0; i<programs.size(); i++ ) {
- JSONObject programme = programs.getJSONObject(i);
- Programme p = programmeFromJSON(programme, fetchDetails);
- p.channel = c;
- result.add( p );
- }
- } else {
- JSONObject programs = (JSONObject) ps;
- for( Object o: programs.keySet() ) {
- JSONObject programme = programs.getJSONObject(o.toString());
- Programme p = programmeFromJSON(programme, fetchDetails);
- p.channel = c;
- result.add( p );
- }
- }
- }
-
- return result;
- }
-
- private Programme programmeFromJSON(JSONObject programme, boolean fetchDetails) throws Exception {
- Programme p = (Programme) JSONObject.toBean(programme, Programme.class);
- p.fixup(config);
- if (fetchDetails) {
- fillDetails(p);
- }
- if(config.logProgrammes()) {
- System.out.println(p.toString());
- }
- return p;
- }
-
- private String fetchURL(URL url) throws Exception {
- Thread.sleep(config.niceMilliseconds);
- StringBuffer buf = new StringBuffer();
- try {
- BufferedReader reader = new BufferedReader( new InputStreamReader( url.openStream()));
- String s;
- while ((s = reader.readLine()) != null) buf.append(s);
- } catch (IOException e) {
- fetchErrors++;
- throw new Exception("Error getting program data from url " + url, e);
- }
- return buf.toString();
- }
-
- private JSONObject fetchJSON(URL url) throws Exception {
- String json = fetchURL(url);
- if (config.logJSON()) System.out.println(json);
- return JSONObject.fromObject( json );
- }
-
- private void fillDetails(Programme p) throws Exception {
- Pattern progInfoPattern = Pattern.compile("prog-info-content.*prog-info-footer", Pattern.DOTALL);
- Pattern infoLinePattern = Pattern.compile("<li><strong>(.*?):</strong>(.*?)</li>");
- Pattern HDPattern = Pattern.compile("HD \\d+[ip]?");
- Pattern kijkwijzerPattern = Pattern.compile("<img src=\"http://tvgidsassets.nl/img/kijkwijzer/.*?\" alt=\"(.*?)\" />");
-
- p.details = cache.getDetails(p.db_id);
- if ( p.details == null ) {
- cacheMisses++;
-
- URL url = JSONDetailUrl(p.db_id);
- JSONObject json = fetchJSON(url);
- p.details = (ProgrammeDetails) JSONObject.toBean(json, ProgrammeDetails.class);
-
- url = HTMLDetailUrl(p.db_id);
- String clob=fetchURL(url);
- //System.out.println("clob:");
- //System.out.println(clob);
- Matcher m = progInfoPattern.matcher(clob);
- if (m.find()) {
- String progInfo = m.group();
- //System.out.println("progInfo");
- //System.out.println(progInfo);
- Matcher m2 = infoLinePattern.matcher(progInfo);
- while (m2.find()) {
- //System.out.println(" infoLine: " + m2.group());
- //System.out.println(" key: " + m2.group(1));
- //System.out.println(" value: " + m2.group(2));
- String key = m2.group(1);
- String value = m2.group(2);
- switch(key.toLowerCase()) {
- case "bijzonderheden":
- String[] list = value.split(",");
- for( String item: list) {
- if (item.toLowerCase().contains("teletekst")) {
- p.details.subtitle_teletekst = true;
- } else if (item.toLowerCase().contains("breedbeeld")) {
- p.details.breedbeeld = true;
- } else if (value.toLowerCase().contains("zwart")) {
- p.details.blacknwhite = true;
- } else if (value.toLowerCase().contains("stereo")) {
- p.details.stereo = true;
- } else if (value.toLowerCase().contains("herhaling")) {
- p.details.herhaling = true;
- } else {
- Matcher m3 = HDPattern.matcher(value);
- if (m3.find()) {
- p.details.quality = m3.group();
- } else {
- if (!config.quiet) System.out.println(" Unknown value in 'bijzonderheden': " + item);
- }
- }
- }
- break;
- }
- Matcher m3 = kijkwijzerPattern.matcher(progInfo);
- List<String> kijkwijzer = new ArrayList<String>();
- while (m3.find()) {
- kijkwijzer.add(m3.group(1));
- }
- if (!kijkwijzer.isEmpty()) {
- // log.debug()
- // System.out.println(" (kijkwijzer): " + p.details.kijkwijzer);
- // System.out.println(" kijkwijzer: " + kijkwijzer);
- }
- }
- }
-
- p.details.fixup(p, config.quiet);
- cache.add(p.db_id, p.details);
- } else {
- cacheHits++;
- }
- }
-}
+++ /dev/null
-package org.vanbest.xmltv;
-
-import java.io.OutputStream;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Collection;
-import java.util.List;
-
-import javax.xml.stream.FactoryConfigurationError;
-import javax.xml.stream.XMLStreamWriter;
-import javax.xml.stream.XMLOutputFactory;
-import javax.xml.stream.XMLEventFactory;
-import javax.xml.stream.XMLStreamException;
-
-public class XmlTvWriter {
-
- private XMLStreamWriter writer;
- private XMLEventFactory eventFactory;
- private Config config;
-
- public XmlTvWriter(OutputStream os, Config config) throws XMLStreamException, FactoryConfigurationError {
- this.config = config;
- this.writer = XMLOutputFactory.newInstance().createXMLStreamWriter(os);
- this.eventFactory = XMLEventFactory.newInstance();
-
- writer.writeStartDocument();
- writer.writeCharacters("\n");
- writer.writeDTD("<!DOCTYPE tv SYSTEM \"xmltv.dtd\">");
- writer.writeCharacters("\n");
- writer.writeStartElement("tv");
- writer.writeAttribute("generator-info-url","http://www.vanbest.org/");
- writer.writeAttribute("source-info-url", "http://tvgids.nl/");
- writer.writeAttribute("source-info-name", "TvGids.nl");
- writer.writeAttribute("generator-info-name", "tv_grab_nl_java release 0.4");
- writeln();
- }
-
- public void writeln() throws XMLStreamException {
- writer.writeCharacters(System.getProperty("line.separator"));
- }
-
- public void writeChannels(List<Channel> channels) throws XMLStreamException {
- for(Channel c: channels) {
- writer.writeStartElement("channel");
- writer.writeAttribute("id", c.getChannelId());
- writer.writeStartElement("display-name");
- writer.writeAttribute("lang", "nl");
- writer.writeCharacters(c.name);
- writer.writeEndElement();
-
- if (c.iconUrl != null) {
- writer.writeStartElement("icon");
- writer.writeAttribute("src", c.iconUrl);
- writer.writeEndElement();
- }
-
- writer.writeEndElement();
- writeln(); }
- }
-
- /* TODO:
- * boolean is_highlight;
- * String highlight_afbeelding;
- * String highlight_content;
- * soort
- * artikel_id ???
- *
- */
- public void writePrograms(Collection<Programme> programs) throws XMLStreamException {
- DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss Z");
- for(Programme p: programs) {
- writer.writeStartElement("programme");
- writer.writeAttribute("start", df.format(p.datum_start));
- writer.writeAttribute("stop", df.format(p.datum_end));
- writer.writeAttribute("channel", ""+p.channel.getChannelId());
- writeln();
-
- writer.writeStartElement("title");
- writer.writeAttribute("lang", "nl");
- writer.writeCharacters(p.titel);
- writer.writeEndElement();
- writeln();
-
- if(p.details.synop != null && ! p.details.synop.isEmpty()) {
- writer.writeStartElement("desc");
- writer.writeAttribute("lang", "nl");
- writer.writeCharacters(p.details.synop);
- writer.writeEndElement();
- writeln();
- }
-
- if (p.details != null) {
- if ( p.is_highlight) {
- //System.out.println("Highlight");
- //System.out.println(" " + p.highlight_afbeelding);
- //System.out.println(" " + p.highlight_content);
- } else {
- if (p.highlight_afbeelding!= null && !p.highlight_afbeelding.isEmpty()) {
- //System.out.println("highlight_afbeelding: " + p.highlight_afbeelding);
- }
- if (p.highlight_content!= null && !p.highlight_content.isEmpty()) {
- //System.out.println("highlight_content: " + p.highlight_content);
- }
- }
- if ( (p.details.presentatie != null && !p.details.presentatie.isEmpty()) ||
- (p.details.regisseur != null && !p.details.regisseur.isEmpty()) ||
- (p.details.acteursnamen_rolverdeling != null && !p.details.acteursnamen_rolverdeling.isEmpty())
- ) {
- writer.writeStartElement("credits");
- if (p.details.regisseur != null && !p.details.regisseur.isEmpty()) {
- String[] parts = p.details.regisseur.split(",");
- for (String s: parts) {
- writer.writeStartElement("director");
- writer.writeCharacters(s.trim());
- writer.writeEndElement();
- }
- }
- if (p.details.acteursnamen_rolverdeling != null && !p.details.acteursnamen_rolverdeling.isEmpty()) {
- String[] parts = p.details.acteursnamen_rolverdeling.split(",");
- for (String s: parts) {
- writer.writeStartElement("actor");
- writer.writeCharacters(s.trim());
- writer.writeEndElement();
- }
- }
- if (p.details.presentatie != null && !p.details.presentatie.isEmpty()) {
- String[] parts = p.details.presentatie.split(",");
- for (String s: parts) {
- writer.writeStartElement("presenter");
- writer.writeCharacters(s.trim());
- writer.writeEndElement();
- }
- }
- writer.writeEndElement();
- writeln();
- }
- writer.writeStartElement("category");
- writer.writeAttribute("lang", "en");
- writer.writeCharacters(p.genre);
- writer.writeEndElement();
- writeln();
-
- if (p.details.blacknwhite || p.details.breedbeeld) {
- writer.writeStartElement("video");
- if (p.details.blacknwhite) {
- writer.writeStartElement("colour");
- writer.writeCharacters("no");
- writer.writeEndElement();
- }
- if (p.details.breedbeeld) {
- writer.writeStartElement("aspect");
- writer.writeCharacters("16x9");
- writer.writeEndElement();
- }
- if (p.details.quality != null) {
- writer.writeStartElement("quality");
- writer.writeCharacters(p.details.quality);
- writer.writeEndElement();
- }
- writer.writeEndElement();
- writeln();
- }
-
- if (p.details.stereo) {
- writer.writeStartElement("audio");
- writer.writeStartElement("stereo");
- writer.writeCharacters("stereo");
- writer.writeEndElement();
- writer.writeEndElement();
- writeln();
- }
-
- if (p.details.herhaling) {
- writer.writeEmptyElement("previously-shown");
- }
-
- if (p.details.subtitle_teletekst) {
- writer.writeStartElement("subtitles");
- writer.writeAttribute("type", "teletext");
- writer.writeEndElement();
- writeln();
- }
-
- /* TODO: Icon attribuut gebruiken?
- */
- if (p.details.kijkwijzer != null && !p.details.kijkwijzer.isEmpty()) {
- writer.writeStartElement("rating");
- writer.writeAttribute("system", "kijkwijzer");
- writer.writeStartElement("value");
- for (int i=0; i<p.details.kijkwijzer.length(); i++) {
- if (i!=0) writer.writeCharacters(", ");
- char c = p.details.kijkwijzer.charAt(i);
- switch(c) {
- case 'a':writer.writeCharacters("Angst"); break;
- case 'd':writer.writeCharacters("Discriminatie"); break;
- case 's':writer.writeCharacters("Seks"); break;
- case 'h':writer.writeCharacters("Drugs/Alcohol"); break;
- case 'g':writer.writeCharacters("Geweld"); break;
- case 't':writer.writeCharacters("Grof taalgebruik"); break;
- case '1':writer.writeCharacters("Voor alle leeftijden"); break;
- case '2':writer.writeCharacters("Afgeraden voor kinderen jonger dan 6 jaar"); break;
- case '9':writer.writeCharacters("Afgeraden voor kinderen jonger dan 9 jaar"); break;
- case '3':writer.writeCharacters("Afgeraden voor kinderen jonger dan 12 jaar"); break;
- case '4':writer.writeCharacters("Afgeraden voor kinderen jonger dan 16 jaar"); break;
- default: if (!config.quiet) {
- System.out.println("Unknown kijkwijzer character: " + p.details.kijkwijzer);
- System.out.println(" for show " + p.titel + " at channel " + p.channel.name + " at " + p.datum_start);
- }
- }
- }
- //writer.writeStartElement("value");
- // writer.writeCharacters(p.details.kijkwijzer);
- //writer.writeEndElement();
- writer.writeEndElement();
- writer.writeEndElement();
- writeln();
- }
- }
- writer.writeEndElement();
- writeln();
- }
- }
-
- public void close() throws XMLStreamException {
- writer.writeEndElement();
- writer.writeEndDocument();
- writer.flush();
- }
-
- public void flush() throws XMLStreamException {
- writer.flush();
- }
-}