-#!/usr/bin/env python
-# vim:ts=4:sts=4:sw=4:noet
-
import json
import random
import string
METADATA_BASE = "http://video.query.yahoo.com/v1/public/yql?"
METADATA_QUERY = {
- 'q': 'SELECT streams,status FROM yahoo.media.video.streams WHERE id="%s" AND format="mp4,flv" AND protocol="rtmp,http" AND plrs="%s" AND offnetwork="false" AND site="autv_plus7" AND lang="en-AU" AND region="AU" AND override="none";',
- 'callback': 'jsonp_callback',
- 'env': 'prod',
- 'format': 'json'
+ 'q': 'SELECT streams,status FROM yahoo.media.video.streams WHERE id="%s" AND format="mp4,flv" AND protocol="rtmp,http" AND plrs="%s" AND offnetwork="false" AND site="autv_plus7" AND lang="en-AU" AND region="AU" AND override="none";',
+ 'callback': 'jsonp_callback',
+ 'env': 'prod',
+ 'format': 'json'
}
HASH_URL = "http://d.yimg.com/m/up/ypp/au/player.swf"
def extract_and_remove(tokens, key):
- lowertokens = [x.lower() for x in tokens]
- pos = lowertokens.index(key)
+ lowertokens = [x.lower() for x in tokens]
+ pos = lowertokens.index(key)
- value = int(tokens[pos+1])
- tokens = tokens[:pos] + tokens[pos+2:]
+ value = int(tokens[pos+1])
+ tokens = tokens[:pos] + tokens[pos+2:]
- return value, tokens
+ return value, tokens
def demangle_title(title, subtitle):
- tokens = title.split()
- insert_pos = len(tokens)
- if subtitle:
- insert_pos += 1
- tokens += ["-"] + subtitle.split()
-
- try:
- season, tokens = extract_and_remove(tokens, "series")
- episode, tokens = extract_and_remove(tokens, "episode")
- if insert_pos < len(tokens):
- tokens.insert(insert_pos, "-")
- tokens.insert(insert_pos, "%sx%s" % (season, str(episode).zfill(2)))
- except ValueError:
- pass
-
- return " ".join(tokens)
+ tokens = title.split()
+ insert_pos = len(tokens)
+ if subtitle:
+ insert_pos += 1
+ tokens += ["-"] + subtitle.split()
+
+ try:
+ season, tokens = extract_and_remove(tokens, "series")
+ episode, tokens = extract_and_remove(tokens, "episode")
+ if insert_pos < len(tokens):
+ tokens.insert(insert_pos, "-")
+ tokens.insert(insert_pos, "%sx%s" % (season, str(episode).zfill(2)))
+ except ValueError:
+ pass
+
+ return " ".join(tokens)
class Plus7Node(Node):
- def __init__(self, title, parent, url):
- Node.__init__(self, title, parent)
- self.url = url
- self.can_download = True
-
- def get_video_id(self):
- doc = grab_html(self.url, 3600)
- for script in doc.xpath("//script"):
- if not script.text:
- continue
- for line in script.text.split(";"):
- line = line.strip()
- if line.find("new Y.VideoPlatform.VideoPlayer") <= 0:
- continue
-
-### vidparams = line[line.find("(")+1 : line.rfind(")")]
-### vidparams = json.loads(vidparams)
-### return vidparams["playlist"]["mediaItems"][0]["id"]
-
- # Cannot parse it as JSON :(
- pos1 = line.find('"mediaItems":')
- if pos1 < 0:
- continue
- pos2 = line.find('"id":', pos1)
- if pos2 < 0:
- continue
- pos3 = line.find('"', pos2+5)
- pos4 = line.find('"', pos2+6)
- if pos3 < 0 or pos4 < 0:
- continue
- return line[pos3+1:pos4]
-
- raise Exception("Could not find video id on page " + self.url)
-
- def generate_session(self):
- return "".join([random.choice(string.ascii_letters) for x in xrange(22)])
-
- def download(self):
- vid_id = self.get_video_id()
- qs = dict(METADATA_QUERY.items()) # copy..
- qs["q"] = qs["q"] % (vid_id, self.generate_session())
- url = METADATA_BASE + urllib.urlencode(qs)
- doc = grab_json(url, 0, skip_function=True)
- stream_data = doc["query"]["results"]["mediaObj"][0]["streams"][0]
- vbase = stream_data["host"]
- vpath = stream_data["path"]
- filename = self.title + ".flv"
- return download_rtmp(filename, vbase, vpath, HASH_URL)
+ def __init__(self, title, parent, url):
+ Node.__init__(self, title, parent)
+ self.url = url
+ self.can_download = True
+
+ def get_video_id(self):
+ doc = grab_html(self.url, 3600)
+ for script in doc.xpath("//script"):
+ if not script.text:
+ continue
+ for line in script.text.split(";"):
+ line = line.strip()
+ if line.find("new Y.VideoPlatform.VideoPlayer") <= 0:
+ continue
+
+### vidparams = line[line.find("(")+1 : line.rfind(")")]
+### vidparams = json.loads(vidparams)
+### return vidparams["playlist"]["mediaItems"][0]["id"]
+
+ # Cannot parse it as JSON :(
+ pos1 = line.find('"mediaItems":')
+ if pos1 < 0:
+ continue
+ pos2 = line.find('"id":', pos1)
+ if pos2 < 0:
+ continue
+ pos3 = line.find('"', pos2+5)
+ pos4 = line.find('"', pos2+6)
+ if pos3 < 0 or pos4 < 0:
+ continue
+ return line[pos3+1:pos4]
+
+ raise Exception("Could not find video id on page " + self.url)
+
+ def generate_session(self):
+ return "".join([random.choice(string.ascii_letters) for x in xrange(22)])
+
+ def download(self):
+ vid_id = self.get_video_id()
+ qs = dict(METADATA_QUERY.items()) # copy..
+ qs["q"] = qs["q"] % (vid_id, self.generate_session())
+ url = METADATA_BASE + urllib.urlencode(qs)
+ doc = grab_json(url, 0, skip_function=True)
+ stream_data = doc["query"]["results"]["mediaObj"][0]["streams"][0]
+ vbase = stream_data["host"]
+ vpath = stream_data["path"]
+ filename = self.title + ".flv"
+ return download_rtmp(filename, vbase, vpath, HASH_URL)
class Plus7Series(Node):
- def __init__(self, title, parent, url):
- Node.__init__(self, title, parent)
- self.url = url
-
- def fill_children(self):
- doc = grab_html(self.url, 3600)
- for item in CSSSelector("#related-episodes div.itemdetails")(doc):
- title = CSSSelector("span.title")(item)[0].text
- subtitle = CSSSelector("span.subtitle")(item)[0].xpath("string()")
- title = demangle_title(title, subtitle)
- url = CSSSelector("a")(item)[0].attrib["href"]
- Plus7Node(title, self, BASE + url)
+ def __init__(self, title, parent, url):
+ Node.__init__(self, title, parent)
+ self.url = url
+
+ def fill_children(self):
+ doc = grab_html(self.url, 3600)
+ for item in CSSSelector("#related-episodes div.itemdetails")(doc):
+ title = CSSSelector("span.title")(item)[0].text
+ subtitle = CSSSelector("span.subtitle")(item)[0].xpath("string()")
+ title = demangle_title(title, subtitle)
+ url = CSSSelector("a")(item)[0].attrib["href"]
+ Plus7Node(title, self, BASE + url)
class Plus7Root(Node):
- def __init__(self, parent=None):
- Node.__init__(self, "Yahoo Plus7", parent)
-
- def fill_children(self):
- doc = grab_html(BROWSE, 3600)
- shows = []
- for script in doc.xpath("//script"):
- if not script.text or not script.text.startswith("var shows = "):
- continue
- shows = script.text[12:]
- shows = shows.rstrip("; \n")
- shows = json.loads(shows)
- for show in shows:
- Plus7Series(show["title"], self, show["url"])
+ def __init__(self, parent):
+ Node.__init__(self, "Yahoo Plus7 (broken!)", parent)
+
+ def fill_children(self):
+ doc = grab_html(BROWSE, 3600)
+ shows = []
+ for script in doc.xpath("//script"):
+ if not script.text or not script.text.startswith("var shows = "):
+ continue
+ shows = script.text[12:]
+ shows = shows.rstrip("; \n")
+ shows = json.loads(shows)
+ for show in shows:
+ Plus7Series(show["title"], self, show["url"])
def fill_nodes(root_node):
- Plus7Root(root_node)
+ Plus7Root(root_node)