]> code.delx.au - monosys/commitdiff
Added ABC iView downloader
authorJames Bunton <jamesbunton@fastmail.fm>
Mon, 18 Jul 2011 14:39:06 +0000 (00:39 +1000)
committerJames Bunton <jamesbunton@fastmail.fm>
Mon, 18 Jul 2011 14:39:06 +0000 (00:39 +1000)
scripts/iview-downloader [new file with mode: 0755]

diff --git a/scripts/iview-downloader b/scripts/iview-downloader
new file mode 100755 (executable)
index 0000000..1aa11fc
--- /dev/null
@@ -0,0 +1,133 @@
+#!/usr/bin/env python
+
+import json
+from lxml import etree
+import signal
+import subprocess
+import urllib
+
+BASE_URL = "http://www.abc.net.au/iview/"
+CONFIG_URL = BASE_URL + "xml/config.xml"
+HASH_URL = BASE_URL + "images/iview.jpg"
+NS = {
+       "auth": "http://www.abc.net.au/iView/Services/iViewHandshaker",
+}
+
+def grab_xml(path):
+       f = urllib.urlopen(path)
+       doc = etree.parse(f)
+       f.close()
+       return doc
+
+def grab_json(path):
+       f = urllib.urlopen(path)
+       doc = json.load(f)
+       f.close()
+       return doc
+
+def choose(options, allow_multi):
+       skeys = sorted(options.keys())
+       for i, key in enumerate(skeys):
+               print " %d) %s" % (i+1, key)
+       print " 0) Back"
+       while True:
+               try:
+                       values = map(int, raw_input("Choose> ").split())
+                       if len(values) == 0:
+                               continue
+                       if 0 in values:
+                               return
+                       values = [options[skeys[value-1]] for value in values]
+                       if allow_multi:
+                               return values
+                       else:
+                               if len(values) == 1:
+                                       return values[0]
+               except ValueError:
+                       pass
+
+def download_rtmp(filename, vbase, vpath):
+       cmd = [
+               "rtmpdump",
+               "-o", filename,
+               "-r", vbase,
+               "-y", vpath,
+               "--swfVfy", HASH_URL,
+       ]
+       try:
+               p = subprocess.Popen(cmd)
+               p.wait()
+       except KeyboardInterrupt:
+               print "Cancelled", cmd
+               try:
+                       p.terminate()
+                       p.wait()
+               except KeyboardInterrupt:
+                       p.send_signal(signal.SIGKILL)
+                       p.wait()
+
+def download_video(title, vpath):
+       auth_doc = grab_xml(PARAMS["auth"])
+       vbase = auth_doc.xpath("//auth:server/text()", namespaces=NS)[0]
+       token = auth_doc.xpath("//auth:token/text()", namespaces=NS)[0]
+       vbase += "?auth=" + token
+       vpath, ext = vpath.rsplit(".", 1)
+       vpath = ext + ":" + vpath
+       filename = title + "." + ext
+       download_rtmp(filename, vbase, vpath)
+
+def get_categories():
+       categories_doc = grab_xml(BASE_URL + PARAMS["categories"])
+       categories = {}
+       for category in categories_doc.xpath("//category[@genre='true']"):
+               cid = category.attrib["id"]
+               name = category.xpath("name/text()")[0]
+               categories[name] = cid
+       return categories
+
+def get_series(cid):
+       series_list_doc = grab_json(PARAMS["api"] + "seriesIndex")
+       episode_list = {}
+       for series in series_list_doc:
+               categories = series["e"].split()
+               if cid not in categories:
+                       continue
+               sid = series["a"]
+               series_title = series["b"].replace("&amp;", "&")
+               series_doc = grab_json(PARAMS["api"] + "series=" + sid)[0]
+               for episode in series_doc["f"]:
+                       vpath = episode["n"]
+                       episode_title = episode["b"].strip()
+                       if series_title != episode_title:
+                               episode_title = series_title + " " + episode_title
+                       episode_list[episode_title] = (episode_title, vpath)
+       return episode_list
+
+
+
+def main():
+       config_doc = grab_xml(CONFIG_URL)
+       global PARAMS
+       PARAMS = dict((p.attrib["name"], p.attrib["value"]) for p in config_doc.xpath("/config/param"))
+
+       while True:
+               cid = choose(get_categories(), allow_multi=False)
+               if cid is None:
+                       continue
+               while True:
+                       sid = choose(get_series(cid), allow_multi=False)
+                       if sid is None:
+                               break
+                       while True:
+                               generator = choose(get_episodes(sid), allow_multi=True)
+                               if generator is None:
+                                       break
+                               for title, vpath in generator:
+                                       download_video(title, vpath)
+
+if __name__ == "__main__":
+       try:
+               main()
+       except (KeyboardInterrupt, EOFError):
+               print "\nExiting..."
+