package org.lodder.subtools.sublibrary.data.thetvdb; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import javax.xml.parsers.ParserConfigurationException; import org.lodder.subtools.sublibrary.Manager; import org.lodder.subtools.sublibrary.ManagerException; import org.lodder.subtools.sublibrary.ManagerSetupException; import org.lodder.subtools.sublibrary.data.XmlHTTP; import org.lodder.subtools.sublibrary.data.thetvdb.model.TheTVDBEpisode; import org.lodder.subtools.sublibrary.data.thetvdb.model.TheTVDBSerie; import org.lodder.subtools.sublibrary.xml.XMLHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class TheTVDBApi { private final XmlHTTP xmlHTTPAPI; private final TheTVDBMirrors theTVDBMirrors; private String apiKey; private static final String XML_EXTENSION = ".xml"; private static final String SERIES_URL = "/series/"; private static final String ALL_URL = "/all/"; private static final Logger LOGGER = LoggerFactory.getLogger(TheTVDBApi.class); public TheTVDBApi(String apikey, Manager manager) throws TheTVDBException { xmlHTTPAPI = new XmlHTTP(manager); try { theTVDBMirrors = new TheTVDBMirrors(apikey, manager); } catch (Exception e) { throw new TheTVDBException("Trouble getting a mirror"); } setApiKey(apikey); } public int searchSerie(String seriename, String language) throws TheTVDBException { String url = getXmlMirror() + "/api/GetSeries.php?seriesname="; try { url = url + URLEncoder.encode(seriename, "UTF-8"); Document doc = xmlHTTPAPI.getXMLDisk(url); NodeList nList = null; if (doc != null) { nList = doc.getElementsByTagName("Series"); } if (nList == null || nList.getLength() == 0) { // retry if failed, but delete entry! xmlHTTPAPI.removeCacheEntry(url); doc = xmlHTTPAPI.getXMLDisk(url); nList = doc.getElementsByTagName("Series"); } for (int i = 0; i < nList.getLength(); i++) { Element eElement = (Element) nList.item(i); if (eElement != null) { String seriesName = org.lodder.subtools.sublibrary.xml.XMLHelper .getStringTagValue("SeriesName", eElement); if (seriesName.replaceAll("[^A-Za-z]", "").equalsIgnoreCase( seriename.replaceAll("[^A-Za-z]", ""))) { return org.lodder.subtools.sublibrary.xml.XMLHelper .getIntTagValue("seriesid", eElement); } String aliasNames = org.lodder.subtools.sublibrary.xml.XMLHelper .getStringTagValue("AliasNames", eElement); if (aliasNames.replaceAll("[^A-Za-z]", "").equalsIgnoreCase( seriename.replaceAll("[^A-Za-z]", ""))) { return org.lodder.subtools.sublibrary.xml.XMLHelper .getIntTagValue("seriesid", eElement); } } } } catch (UnsupportedEncodingException e) { throw new TheTVDBException(e); } catch (ManagerSetupException e) { throw new TheTVDBException(e); } catch (ManagerException e) { throw new TheTVDBException(e); } catch (ParserConfigurationException e) { throw new TheTVDBException(e); } catch (SAXException e) { throw new TheTVDBException(e); } catch (IOException e) { throw new TheTVDBException(e); } return 0; } public TheTVDBSerie getSerie(int tvdbid, String language) throws TheTVDBException { try { if (tvdbid != 0) { String url = createApiUrl("series", new String[] {Integer.toString(tvdbid)}); // Use all as final resort if nothing get's found, or api returns bad results String urlAll = createApiUrl("series", new String[] {Integer.toString(tvdbid), ALL_URL}); NodeList nList = tryGettingData(new String[] {url, url, urlAll}); if (nList != null && nList.getLength() > 0 && nList.item(0).getNodeType() == Node.ELEMENT_NODE) { return parseSerieNode((Element) nList.item(0)); } } else { LOGGER.warn("TVDB ID is 0! please fix"); } } catch (Exception e) { throw new TheTVDBException("Trouble getting a mirror"); } return null; } private NodeList tryGettingData(String[] urls) throws TheTVDBException { NodeList nList = null; try { for (String url : urls) { Document doc = xmlHTTPAPI.getXMLDisk(url); if (doc != null) nList = doc.getElementsByTagName("Series"); else xmlHTTPAPI.removeCacheEntry(url); if (nList == null || nList.getLength() == 0) xmlHTTPAPI.removeCacheEntry(url); else return nList; } } catch (ManagerSetupException e) { throw new TheTVDBException(e); } catch (ManagerException e) { throw new TheTVDBException(e); } catch (ParserConfigurationException e) { throw new TheTVDBException(e); } catch (SAXException e) { throw new TheTVDBException(e); } catch (IOException e) { throw new TheTVDBException(e); } return null; } public List<TheTVDBEpisode> getAllEpisodes(int tvdbid, String language) throws TheTVDBException { List<TheTVDBEpisode> epList = new ArrayList<TheTVDBEpisode>(); String url = createApiUrl("series", new String[] {Integer.toString(tvdbid), ALL_URL}); Document doc; try { doc = xmlHTTPAPI.getXMLDisk(url); NodeList nList = doc.getElementsByTagName("Episode"); for (int i = 0; i < nList.getLength(); i++) { if (nList.item(i).getNodeType() == Node.ELEMENT_NODE) { Element eElement = (Element) nList.item(i); TheTVDBEpisode ep = parseEpisodeNode(eElement); epList.add(ep); } } } catch (ManagerSetupException e) { throw new TheTVDBException(e); } catch (ManagerException e) { throw new TheTVDBException(e); } catch (ParserConfigurationException e) { throw new TheTVDBException(e); } catch (SAXException e) { throw new TheTVDBException(e); } catch (IOException e) { throw new TheTVDBException(e); } return epList; } public TheTVDBEpisode getEpisode(int tvdbid, int season, int episode, String language) throws TheTVDBException { StringBuilder urlString = new StringBuilder(); try { urlString.append(getXmlMirror()); urlString.append("/api/"); urlString.append(apiKey); urlString.append(SERIES_URL); urlString.append(tvdbid); urlString.append("/default/"); urlString.append(season); urlString.append("/"); urlString.append(episode); urlString.append("/"); if (language != null) { urlString.append(language).append(XML_EXTENSION); } Document doc = xmlHTTPAPI.getXMLDisk(urlString.toString()); NodeList nList = doc.getElementsByTagName("Episode"); if (nList.getLength() > 0 && nList.item(0).getNodeType() == Node.ELEMENT_NODE) { return parseEpisodeNode((Element) nList.item(0)); } } catch (ManagerSetupException e) { throw new TheTVDBException(e); } catch (ManagerException e) { throw new TheTVDBException(e); } catch (ParserConfigurationException e) { throw new TheTVDBException(e); } catch (SAXException e) { throw new TheTVDBException(e); } catch (IOException e) { throw new TheTVDBException(e); } return null; } private TheTVDBEpisode parseEpisodeNode(Element eElement) { TheTVDBEpisode episode = new TheTVDBEpisode(); episode.setId(org.lodder.subtools.sublibrary.xml.XMLHelper.getStringTagValue("id", eElement)); episode.setDvdChapter(XMLHelper.getStringTagValue("DVD_chapter", eElement)); episode.setDvdDiscId(XMLHelper.getStringTagValue("DVD_discid", eElement)); episode.setDvdEpisodeNumber(XMLHelper.getStringTagValue("DVD_episodenumber", eElement)); episode.setDvdSeason(XMLHelper.getStringTagValue("DVD_season", eElement)); episode.setDirectors(parseList(XMLHelper.getStringTagValue("Director", eElement), "|,")); episode.setEpImgFlag(XMLHelper.getStringTagValue("EpImgFlag", eElement)); episode.setEpisodeName(XMLHelper.getStringTagValue("EpisodeName", eElement)); episode.setEpisodeNumber(XMLHelper.getIntTagValue("EpisodeNumber", eElement)); episode.setFirstAired(XMLHelper.getStringTagValue("FirstAired", eElement)); episode.setGuestStars(parseList(XMLHelper.getStringTagValue("GuestStars", eElement), "|,")); episode.setImdbId(XMLHelper.getStringTagValue("IMDB_ID", eElement)); episode.setLanguage(XMLHelper.getStringTagValue("Language", eElement)); episode.setOverview(XMLHelper.getStringTagValue("Overview", eElement)); episode.setProductionCode(XMLHelper.getStringTagValue("ProductionCode", eElement)); episode.setRating(XMLHelper.getStringTagValue("Rating", eElement)); episode.setSeasonNumber(XMLHelper.getIntTagValue("SeasonNumber", eElement)); episode.setWriters(parseList(XMLHelper.getStringTagValue("Writer", eElement), "|,")); episode.setAbsoluteNumber(XMLHelper.getStringTagValue("absolute_number", eElement)); // String s = XMLHelper.getStringTagValue(eElement, "filename"); // if (!s.isEmpty()) { // episode.setFilename(TheTVDB.getBannerMirror() + s); // } episode.setLastUpdated(XMLHelper.getStringTagValue("lastupdated", eElement)); episode.setSeasonId(XMLHelper.getStringTagValue("seasonid", eElement)); episode.setSeriesId(XMLHelper.getStringTagValue("seriesid", eElement)); try { episode.setAirsAfterSeason(XMLHelper.getIntTagValue("airsafter_season", eElement)); } catch (Exception ignore) { episode.setAirsAfterSeason(0); } try { episode.setAirsBeforeEpisode(XMLHelper.getIntTagValue("airsbefore_episode", eElement)); } catch (Exception ignore) { episode.setAirsBeforeEpisode(0); } try { episode.setAirsBeforeSeason(XMLHelper.getIntTagValue("airsbefore_season", eElement)); } catch (Exception ignore) { episode.setAirsBeforeSeason(0); } return episode; } private TheTVDBSerie parseSerieNode(Element eElement) { TheTVDBSerie TheTVDBSerie = new TheTVDBSerie(); try { LOGGER.trace("parseSerieNode: eElement [{}]", XMLHelper.getXMLAsString(eElement)); } catch (Exception e) { LOGGER.error("Trying to display eElement", e); } TheTVDBSerie.setId(XMLHelper.getStringTagValue("id", eElement)); TheTVDBSerie.setActors(parseList(XMLHelper.getStringTagValue("Actors", eElement), "|,")); TheTVDBSerie.setAirsDayOfWeek(XMLHelper.getStringTagValue("Airs_DayOfWeek", eElement)); TheTVDBSerie.setAirsTime(XMLHelper.getStringTagValue("Airs_Time", eElement)); TheTVDBSerie.setContentRating(XMLHelper.getStringTagValue("ContentRating", eElement)); TheTVDBSerie.setFirstAired(XMLHelper.getStringTagValue("FirstAired", eElement)); TheTVDBSerie.setGenres(parseList(XMLHelper.getStringTagValue("Genre", eElement), "|,")); TheTVDBSerie.setImdbId(XMLHelper.getStringTagValue("IMDB_ID", eElement)); TheTVDBSerie.setLanguage(XMLHelper.getStringTagValue("Language", eElement)); TheTVDBSerie.setNetwork(XMLHelper.getStringTagValue("Network", eElement)); TheTVDBSerie.setOverview(XMLHelper.getStringTagValue("Overview", eElement)); TheTVDBSerie.setRating(XMLHelper.getStringTagValue("Rating", eElement)); TheTVDBSerie.setRuntime(XMLHelper.getStringTagValue("Runtime", eElement)); TheTVDBSerie.setSerieId(XMLHelper.getStringTagValue("SeriesID", eElement)); TheTVDBSerie.setSerieName(XMLHelper.getStringTagValue("SeriesName", eElement)); TheTVDBSerie.setStatus(XMLHelper.getStringTagValue("Status", eElement)); // String artwork = XMLHelper.getValueFromElement(eTheTVDBSerie, TYPE_BANNER); // if (!artwork.isEmpty()) { // TheTVDBSerie.setBanner(bannerMirror + artwork); // } // // artwork = XMLHelper.getValueFromElement(eTheTVDBSerie, TYPE_FANART); // if (!artwork.isEmpty()) { // TheTVDBSerie.setFanart(bannerMirror + artwork); // } // // artwork = XMLHelper.getValueFromElement(eTheTVDBSerie, TYPE_POSTER); // if (!artwork.isEmpty()) { // TheTVDBSerie.setPoster(bannerMirror + artwork); // } // TheTVDBSerie.setLastUpdated(XMLHelper.getStringTagValue("lastupdated", eElement)); TheTVDBSerie.setZap2ItId(XMLHelper.getStringTagValue("zap2it_id", eElement)); return TheTVDBSerie; } private static List<String> parseList(String input, String delim) { List<String> result = new ArrayList<String>(); StringTokenizer st = new StringTokenizer(input, delim); while (st.hasMoreTokens()) { String token = st.nextToken().trim(); if (token.length() > 0) { result.add(token); } } return result; } private String createApiUrl(String command, String[] params) { LOGGER.trace("createApiUrl, command [{}], params [{}]", command, params); command = command.replace("/", ""); String urlParam = ""; for (int i = 0; i < params.length; i++) { if (i == 0) { urlParam = params[i].replace("/", ""); } else { urlParam = urlParam + "/" + params[i].replace("/", ""); } } LOGGER.trace("createApiUrl, createpart / command [{}] / urlParam [{}]", command, urlParam); return getXmlMirror() + "/api/" + this.getApiKey() + "/" + command + "/" + urlParam; } private String getXmlMirror() { return theTVDBMirrors.getMirror(TheTVDBMirrors.TYPE_XML); } public String getApiKey() { return apiKey; } public void setApiKey(String apiKey) { this.apiKey = apiKey; } }