X-Git-Url: https://code.delx.au/webdl/blobdiff_plain/8d6b793245e362dce6ff957cdd3e245c4292d268..b6ad3911d2593698d5ed405520aa2cc0e6ce2ea0:/iview.py diff --git a/iview.py b/iview.py index f5d4737..05d0472 100644 --- a/iview.py +++ b/iview.py @@ -2,7 +2,7 @@ # vim:ts=4:sts=4:sw=4:noet from common import grab_xml, grab_json, download_rtmp, Node -from datetime import datetime +import itertools BASE_URL = "http://www.abc.net.au/iview/" CONFIG_URL = BASE_URL + "xml/config.xml" @@ -12,63 +12,125 @@ NS = { } class IviewNode(Node): - def __init__(self, title, parent, vpath): + def __init__(self, title, parent, params, vpath): Node.__init__(self, title, parent) + self.params = params self.vpath = vpath + self.filename = self.title + "." + vpath.rsplit(".", 1)[1] self.can_download = True def download(self): - auth_doc = grab_xml(PARAMS["auth"], 0) - vbase = auth_doc.xpath("//auth:server/text()", namespaces=NS)[0] + auth_doc = grab_xml(self.params["auth"], 0) + server = self.params["server_streaming"] token = auth_doc.xpath("//auth:token/text()", namespaces=NS)[0] - vbase += "?auth=" + token + playpath = auth_doc.xpath("//auth:path/text()", namespaces=NS)[0] + if playpath == "playback/_definst_/": + playpath = "flash/" + playpath + vbase = server + "?auth=" + token vpath, ext = self.vpath.rsplit(".", 1) - vpath = ext + ":" + vpath - filename = self.title + "." + ext - return download_rtmp(filename, vbase, vpath, HASH_URL) + vpath = ext + ":" + playpath + vpath + return download_rtmp(self.filename, vbase, vpath, HASH_URL) - -class IviewSeries(Node): - def __init__(self, series_title, series_id, parent): - Node.__init__(self, series_title, parent) - self.series_title = series_title - self.series_id = series_id +class IviewSeriesNode(Node): + def __init__(self, title, parent, params, series_ids): + Node.__init__(self, title, parent) + self.params = params + self.series_ids = series_ids def fill_children(self): - series_doc = grab_json(PARAMS["api"] + "series=" + self.series_id, 3600)[0] - for episode in series_doc["f"]: + for series_id in self.series_ids: + self.fill_children_for_id(series_id) + + def fill_children_for_id(self, series_id): + series_doc = grab_json(self.params["api"] + "series=" + series_id, 3600) + for episode_list in series_doc: + if episode_list["a"] == series_id: + episode_list = episode_list["f"] + break + else: + return + + for episode in episode_list: vpath = episode["n"] episode_title = episode["b"].strip() - if self.series_title != episode_title: - episode_title = self.series_title + " " + episode_title - IviewNode(episode_title, self, vpath) + if not episode_title.startswith(self.title): + episode_title = self.title + " " + episode_title + if episode_title.lower().endswith(" (final)"): + episode_title = episode_title[:-8] + IviewNode(episode_title, self, self.params, vpath) + +class SeriesInfo(object): + def __init__(self, title): + self.title = title + self.series_ids = set() + self.categories = set() + + def add_series_id(self, series_id): + self.series_ids.add(series_id) + + def add_categories(self, categories): + self.categories.update(categories) +class IviewRootNode(Node): + def __init__(self, parent): + Node.__init__(self, "ABC iView", parent) + self.params = {} + self.series_info = {} + self.categories_map = {} + + def load_params(self): + config_doc = grab_xml(CONFIG_URL, 24*3600) + for p in config_doc.xpath("/config/param"): + key = p.attrib["name"] + value = p.attrib["value"] + self.params[key] = value + + def load_series(self): + series_list_doc = grab_json(self.params["api"] + "seriesIndex", 3600) + for series in series_list_doc: + title = series["b"].replace("&", "&") + sid = series["a"] + categories = series["e"].split() + info = self.series_info.get(title, None) + if not info: + info = SeriesInfo(title) + self.series_info[title] = info + info.add_categories(categories) + info.add_series_id(sid) + + def load_categories(self): + categories_doc = grab_xml(BASE_URL + self.params["categories"], 24*3600) + by_channel = Node("By Channel", self) + by_genre = Node("By Genre", self) + for category in categories_doc.xpath("//category"): + cid = category.attrib["id"] + category_name = category.xpath("name/text()")[0] + if "genre" in category.attrib: + parent = by_genre + elif cid in ["abc1", "abc2", "abc3", "abc4", "original"]: + parent = by_channel + elif cid in ["featured", "recent", "last-chance", "trailers"]: + parent = self + else: + continue + node = Node(category_name, parent) + self.categories_map[cid] = node + + def link_series(self): + # Create a duplicate within each category for each series + for s in self.series_info.itervalues(): + for cid in s.categories: + parent = self.categories_map.get(cid) + if parent: + IviewSeriesNode(s.title, parent, self.params, s.series_ids) + + def fill_children(self): + self.load_params() + self.load_series() + self.load_categories() + self.link_series() def fill_nodes(root_node): - root_node = Node("ABC iView", root_node) - - config_doc = grab_xml(CONFIG_URL, 24*3600) - global PARAMS - PARAMS = dict((p.attrib["name"], p.attrib["value"]) for p in config_doc.xpath("/config/param")) - - categories_doc = grab_xml(BASE_URL + PARAMS["categories"], 24*3600) - categories_map = {} - for category in categories_doc.xpath("//category[@genre='true']"): - cid = category.attrib["id"] - category_name = category.xpath("name/text()")[0] - category_node = Node(category_name, root_node) - categories_map[cid] = category_node - - # Create a duplicate of each series within each category that it appears - series_list_doc = grab_json(PARAMS["api"] + "seriesIndex", 3600) - for series in series_list_doc: - categories = series["e"].split() - sid = series["a"] - - series_title = series["b"].replace("&", "&") - for cid in categories: - category_node = categories_map.get(cid, None) - if category_node: - IviewSeries(series_title, sid, category_node) + IviewRootNode(root_node)