aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Christopher Rosell <chrippa@tanuki.se>2012-04-21 21:57:20 +0200
committerGravatar Christopher Rosell <chrippa@tanuki.se>2012-04-21 21:57:20 +0200
commit22dd8a40c8bb9c1c7e845a47df5b84dfe2a8527e (patch)
tree2a60947960ccd89fd19ad45e992545dc8454ba8b /src
parente3b3bdf86e9e9921ce6c76e8dd587dbe0b41f33e (diff)
Added PluginError exception to make error handling nicer.
Also added a utility function to do HTTP requests.
Diffstat (limited to 'src')
-rw-r--r--src/livestreamer/__init__.py3
-rw-r--r--src/livestreamer/cli.py5
-rw-r--r--src/livestreamer/plugins/__init__.py3
-rw-r--r--src/livestreamer/plugins/justintv.py33
-rw-r--r--src/livestreamer/plugins/ownedtv.py19
-rw-r--r--src/livestreamer/plugins/ustreamtv.py13
-rw-r--r--src/livestreamer/utils.py24
7 files changed, 64 insertions, 36 deletions
diff --git a/src/livestreamer/__init__.py b/src/livestreamer/__init__.py
index 6a0b463..9eb2264 100644
--- a/src/livestreamer/__init__.py
+++ b/src/livestreamer/__init__.py
@@ -16,4 +16,7 @@ def resolve_url(url):
def get_plugins():
return plugins.get_plugins()
+
+PluginError = plugins.PluginError
+
plugins.load_plugins(plugins)
diff --git a/src/livestreamer/cli.py b/src/livestreamer/cli.py
index 179b80d..6d7aac5 100644
--- a/src/livestreamer/cli.py
+++ b/src/livestreamer/cli.py
@@ -24,7 +24,10 @@ def handle_url(args):
if not channel:
exit(("No plugin can handle url: {0}").format(args.url))
- streams = channel.get_streams()
+ try:
+ streams = channel.get_streams()
+ except livestreamer.PluginError as err:
+ exit(("Error from plugin while retrieving streams: {0}").format(err))
if len(streams) == 0:
exit(("No streams found on url: {0}").format(args.url))
diff --git a/src/livestreamer/plugins/__init__.py b/src/livestreamer/plugins/__init__.py
index fe62179..d24b4de 100644
--- a/src/livestreamer/plugins/__init__.py
+++ b/src/livestreamer/plugins/__init__.py
@@ -35,6 +35,9 @@ class Plugin(object):
def _get_streams(self):
raise NotImplementedError
+class PluginError(Exception):
+ pass
+
def load_plugins(plugins):
for loader, name, ispkg in pkgutil.iter_modules(plugins.__path__):
file, pathname, desc = imp.find_module(name, plugins.__path__)
diff --git a/src/livestreamer/plugins/justintv.py b/src/livestreamer/plugins/justintv.py
index f8e4e0b..620db63 100644
--- a/src/livestreamer/plugins/justintv.py
+++ b/src/livestreamer/plugins/justintv.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
-from livestreamer.plugins import Plugin, register_plugin
+from livestreamer.plugins import Plugin, PluginError, register_plugin
from livestreamer.stream import RTMPStream
-from livestreamer.utils import swfverify
+from livestreamer.utils import swfverify, urlget
from livestreamer.compat import urllib, str
import xml.dom.minidom, re, sys, random
@@ -28,11 +28,9 @@ class JustinTV(Plugin):
self.cookie = args.jtv_cookie
def _get_channel_name(self, url):
- fd = urllib.urlopen(url)
- data = fd.read()
- fd.close()
-
+ data = urlget(url)
match = re.search(b"live_facebook_embed_player\.swf\?channel=(\w+)", data)
+
if match:
return str(match.group(1), "ascii")
@@ -43,12 +41,13 @@ class JustinTV(Plugin):
else:
req = urllib.Request(self.MetadataURL.format(channel))
+ data = urlget(req)
- fd = urllib.urlopen(req)
- data = fd.read()
- fd.close()
+ try:
+ dom = xml.dom.minidom.parseString(data)
+ except Exception as err:
+ raise PluginError(("Unable to parse config XML: {0})").format(err))
- dom = xml.dom.minidom.parseString(data)
meta = dom.getElementsByTagName("meta")[0]
metadata = {}
@@ -80,19 +79,23 @@ class JustinTV(Plugin):
randomp = int(random.random() * 999999)
if "chansub_guid" in metadata:
- fd = urllib.urlopen(self.StreamInfoURLSub.format(channelname, randomp, metadata["chansub_guid"]))
+ url = self.StreamInfoURLSub.format(channelname, randomp, metadata["chansub_guid"])
else:
- fd = urllib.urlopen(self.StreamInfoURL.format(channelname, randomp))
+ url = self.StreamInfoURL.format(channelname, randomp)
- data = fd.read()
- fd.close()
+ data = urlget(url)
# fix invalid xml
data = re.sub(b"<(\d+)", b"<_\g<1>", data)
data = re.sub(b"</(\d+)", b"</_\g<1>", data)
streams = {}
- dom = xml.dom.minidom.parseString(data)
+
+ try:
+ dom = xml.dom.minidom.parseString(data)
+ except Exception as err:
+ raise PluginError(("Unable to parse config XML: {0})").format(err))
+
nodes = dom.getElementsByTagName("nodes")[0]
swfhash, swfsize = swfverify(self.SWFURL)
diff --git a/src/livestreamer/plugins/ownedtv.py b/src/livestreamer/plugins/ownedtv.py
index 6461c15..c15e8c4 100644
--- a/src/livestreamer/plugins/ownedtv.py
+++ b/src/livestreamer/plugins/ownedtv.py
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
-from livestreamer.plugins import Plugin, register_plugin
-from livestreamer.stream import RTMPStream
from livestreamer.compat import urllib
+from livestreamer.plugins import Plugin, PluginError, register_plugin
+from livestreamer.stream import RTMPStream
+from livestreamer.utils import urlget
import xml.dom.minidom, re
@@ -34,9 +35,7 @@ class OwnedTV(Plugin):
return "own3d.tv" in url
def _get_channel_id(self, url):
- fd = urlopener.open(url)
- data = fd.read()
- fd.close()
+ data = urlget(url, opener=urlopener)
match = re.search(b"document.location.hash='/live/(\d+)'", data)
if match:
@@ -51,11 +50,13 @@ class OwnedTV(Plugin):
streams = {}
if channelid:
- fd = urllib.urlopen(self.ConfigURL.format(channelid))
- data = fd.read()
- fd.close()
+ data = urlget(self.ConfigURL.format(channelid))
+
+ try:
+ dom = xml.dom.minidom.parseString(data)
+ except Exception as err:
+ raise PluginError(("Unable to parse config XML: {0})").format(err))
- dom = xml.dom.minidom.parseString(data)
channels = dom.getElementsByTagName("channels")[0]
clip = channels.getElementsByTagName("clip")[0]
diff --git a/src/livestreamer/plugins/ustreamtv.py b/src/livestreamer/plugins/ustreamtv.py
index 63a3134..063923e 100644
--- a/src/livestreamer/plugins/ustreamtv.py
+++ b/src/livestreamer/plugins/ustreamtv.py
@@ -1,8 +1,9 @@
#!/usr/bin/env python3
-from livestreamer.plugins import Plugin, register_plugin
+from livestreamer.compat import str, bytes
+from livestreamer.plugins import Plugin, PluginError, register_plugin
from livestreamer.stream import RTMPStream
-from livestreamer.compat import urllib, str, bytes
+from livestreamer.utils import urlget
import xml.dom.minidom, re
@@ -15,9 +16,7 @@ class UStreamTV(Plugin):
return "ustream.tv" in url
def _get_channel_id(self, url):
- fd = urllib.urlopen(url)
- data = fd.read()
- fd.close()
+ data = urlget(url)
match = re.search(b"channelId=(\d+)", data)
if match:
@@ -34,9 +33,7 @@ class UStreamTV(Plugin):
channelid = self._get_channel_id(self.url)
if channelid:
- fd = urllib.urlopen(self.AMFURL.format(channelid))
- data = fd.read()
- fd.close()
+ data = urlget(self.AMFURL.format(channelid))
playpath = get_amf_value(data, "streamName")
cdnurl = get_amf_value(data, "cdnUrl")
diff --git a/src/livestreamer/utils.py b/src/livestreamer/utils.py
index 60a4d6a..5ab8a63 100644
--- a/src/livestreamer/utils.py
+++ b/src/livestreamer/utils.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
from livestreamer.compat import urllib, bytes
+from livestreamer.plugins import PluginError
import hmac, hashlib, zlib, argparse
SWF_KEY = b"Genuine Adobe Flash Player 001"
@@ -36,10 +37,26 @@ class ArgumentParser(argparse.ArgumentParser):
val = line[split+1:].strip()
yield "--%s=%s" % (key, val)
+def urlget(url, data=None, timeout=None, opener=None):
+ try:
+ if opener is not None:
+ fd = opener.open(url)
+ else:
+ fd = urllib.urlopen(url, data, timeout)
+
+ data = fd.read()
+ fd.close()
+
+ except IOError as err:
+ if type(err) is urllib.URLError:
+ raise PluginError(err.reason)
+ else:
+ raise PluginError(err)
+
+ return data
+
def swfverify(url):
- fd = urllib.urlopen(url)
- swf = fd.read()
- fd.close()
+ swf = urlget(url)
if swf[:3] == b"CWS":
swf = b"F" + swf[1:8] + zlib.decompress(swf[8:])
@@ -47,3 +64,4 @@ def swfverify(url):
h = hmac.new(SWF_KEY, swf, hashlib.sha256)
return h.hexdigest(), len(swf)
+