]> code.delx.au - webdl/blob - iview.py
Natural sorting + lazy loading of iView
[webdl] / iview.py
1 #!/usr/bin/env python
2 # vim:ts=4:sts=4:sw=4:noet
3
4 from common import grab_xml, grab_json, download_rtmp, Node
5 from datetime import datetime
6
7 BASE_URL = "http://www.abc.net.au/iview/"
8 CONFIG_URL = BASE_URL + "xml/config.xml"
9 HASH_URL = BASE_URL + "images/iview.jpg"
10 NS = {
11 "auth": "http://www.abc.net.au/iView/Services/iViewHandshaker",
12 }
13
14 class IviewNode(Node):
15 def __init__(self, title, parent, params, vpath):
16 Node.__init__(self, title, parent)
17 self.params = params
18 self.vpath = vpath
19 self.can_download = True
20
21 def download(self):
22 auth_doc = grab_xml(self.params["auth"], 0)
23 vbase = auth_doc.xpath("//auth:server/text()", namespaces=NS)[0]
24 token = auth_doc.xpath("//auth:token/text()", namespaces=NS)[0]
25 vbase += "?auth=" + token
26 vpath, ext = self.vpath.rsplit(".", 1)
27 vpath = ext + ":" + vpath
28 filename = self.title + "." + ext
29 return download_rtmp(filename, vbase, vpath, HASH_URL)
30
31
32 class IviewSeriesNode(Node):
33 def __init__(self, title, parent, params, series_id):
34 Node.__init__(self, title, parent)
35 self.params = params
36 self.series_id = series_id
37 self.sort_children = True
38
39 def fill_children(self):
40 series_doc = grab_json(self.params["api"] + "series=" + self.series_id, 3600)
41 if not series_doc:
42 return
43 for episode in series_doc[0]["f"]:
44 vpath = episode["n"]
45 episode_title = episode["b"].strip()
46 if not episode_title.startswith(self.title):
47 episode_title = self.title + " " + episode_title
48 if episode_title.lower().endswith(" (final)"):
49 episode_title = episode_title[:-8]
50 IviewNode(episode_title, self, self.params, vpath)
51
52 class IviewRootNode(Node):
53 def __init__(self, parent):
54 Node.__init__(self, "ABC iView", parent)
55 self.sort_children = True
56
57 def fill_children(self):
58 config_doc = grab_xml(CONFIG_URL, 24*3600)
59 params = dict((p.attrib["name"], p.attrib["value"]) for p in config_doc.xpath("/config/param"))
60
61 categories_doc = grab_xml(BASE_URL + params["categories"], 24*3600)
62 categories_map = {}
63 for category in categories_doc.xpath("//category[@genre='true']"):
64 cid = category.attrib["id"]
65 category_name = category.xpath("name/text()")[0]
66 category_node = Node(category_name, self)
67 category_node.sort_children = True
68 categories_map[cid] = category_node
69
70 # Create a duplicate of each series within each category that it appears
71 series_list_doc = grab_json(params["api"] + "seriesIndex", 3600)
72 for series in series_list_doc:
73 categories = series["e"].split()
74 sid = series["a"]
75
76 series_title = series["b"].replace("&", "&")
77 for cid in categories:
78 category_node = categories_map.get(cid, None)
79 if category_node:
80 IviewSeriesNode(series_title, category_node, params, sid)
81
82
83
84 def fill_nodes(root_node):
85 IviewRootNode(root_node)
86