aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Christopher Rosell <chrippa@tanuki.se>2012-01-19 22:52:08 +0100
committerGravatar Christopher Rosell <chrippa@tanuki.se>2012-01-19 22:52:08 +0100
commit79d4e6053995c15d79afbce24981eca430cf340d (patch)
treed8738a66c787d07fcf1af6f0421c49a82cc90f1a /src
parent96c33449eefbf0c5257c56aa8109628351a18b59 (diff)
livestreamer.plugins.justintv: Now supports subscription channels.
Needs a cookie passed with --jtv-cookie to get a subscription key.
Diffstat (limited to 'src')
-rw-r--r--src/livestreamer/plugins/justintv.py60
1 files changed, 48 insertions, 12 deletions
diff --git a/src/livestreamer/plugins/justintv.py b/src/livestreamer/plugins/justintv.py
index dacfd05..9db0932 100644
--- a/src/livestreamer/plugins/justintv.py
+++ b/src/livestreamer/plugins/justintv.py
@@ -6,14 +6,19 @@ from livestreamer.compat import urllib, str
import xml.dom.minidom, re, sys, random
-class JustinTV(object):
+class JustinTV(Plugin):
StreamInfoURL = "http://usher.justin.tv/find/{0}.xml?type=any&p={1}"
+ StreamInfoURLSub = "http://usher.justin.tv/find/{0}.xml?type=any&p={1}&b_id=true&chansub_guid={2}&private_code=null&group=&channel_subscription={2}"
+ MetadataURL = "http://www.justin.tv/meta/{0}.xml?on_site=true"
SWFURL = "http://www.justin.tv/widgets/live_embed_player.swf"
def can_handle_url(self, url):
return ("justin.tv" in url) or ("twitch.tv" in url)
- def get_channel_name(self, url):
+ def handle_parser(self, parser):
+ parser.add_argument("--jtv-cookie", metavar="cookie", help="JustinTV cookie to allow access to subscription channels")
+
+ def _get_channel_name(self, url):
fd = urllib.urlopen(url)
data = fd.read()
fd.close()
@@ -22,15 +27,40 @@ class JustinTV(object):
if match:
return str(match.group(1), "ascii")
+ def _get_metadata(self, channel, cookie=None):
+ if cookie:
+ headers = {"Cookie": cookie}
+ req = urllib.Request(self.MetadataURL.format(channel), headers=headers)
+ else:
+ req = urllib.Request(self.MetadataURL.format(channel))
- def get_streams(self, url):
- def get_node_text(element):
- res = []
- for node in element.childNodes:
- if node.nodeType == node.TEXT_NODE:
- res.append(node.data)
- return "".join(res)
+ fd = urllib.urlopen(req)
+ data = fd.read()
+ fd.close()
+
+ dom = xml.dom.minidom.parseString(data)
+ meta = dom.getElementsByTagName("meta")[0]
+ metadata = {}
+
+ metadata["title"] = self._get_node_if_exists(dom, "title")
+ metadata["chansub_guid"] = self._get_node_if_exists(dom, "chansub_guid")
+
+ return metadata
+
+ def _get_node_if_exists(self, dom, name):
+ elements = dom.getElementsByTagName(name)
+ if elements and len(elements) > 0:
+ return self._get_node_text(elements[0])
+
+ def _get_node_text(self, element):
+ res = []
+ for node in element.childNodes:
+ if node.nodeType == node.TEXT_NODE:
+ res.append(node.data)
+ return "".join(res)
+
+ def get_streams(self, url):
def clean_tag(tag):
if tag[0] == "_":
return tag[1:]
@@ -38,12 +68,18 @@ class JustinTV(object):
return tag
randomp = int(random.random() * 999999)
- channelname = self.get_channel_name(url)
+ channelname = self._get_channel_name(url)
if not channelname:
return False
- fd = urllib.urlopen(self.StreamInfoURL.format(channelname, randomp))
+ metadata = self._get_metadata(channelname, self.args.jtv_cookie)
+
+ if "chansub_guid" in metadata:
+ fd = urllib.urlopen(self.StreamInfoURLSub.format(channelname, randomp, metadata["chansub_guid"]))
+ else:
+ fd = urllib.urlopen(self.StreamInfoURL.format(channelname, randomp))
+
data = fd.read()
fd.close()
@@ -58,7 +94,7 @@ class JustinTV(object):
for node in nodes.childNodes:
stream = {}
for child in node.childNodes:
- stream[child.tagName] = get_node_text(child)
+ stream[child.tagName] = self._get_node_text(child)
sname = clean_tag(node.tagName)
streams[sname] = stream