# ======= # Imports # ======= import sys, os import urllib2 from own3dSettings import * import urllib2 from urllib2 import URLError from xml.dom.minidom import parseString from django.utils.html import strip_tags # ====== # Django # ====== # Paths honsapp = os.path.abspath(os.path.dirname(__file__)) honstreams = os.path.abspath(os.path.join(honsapp, '../')) if honstreams not in sys.path: sys.path.append(honstreams) # Django settings module os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' # Import models from honsapp.models import Stream, StreamInfo # ========== # Exceptions # ========== # If the channel name was not found class ChannelNotFoundError(Exception): def __init__(self, message=None): self.message = message # If the live_id was not found in the channel class StreamNotFoundError(Exception): def __init__(self, message=None): self.message = message # ========= # Functions # ========= def getStreamStatus(stream): """ Gets the status of the input stream. Returns tuple: status Boolean - True for live, False for offline viewers Integer - The number of viewers currently watching """ # Compose URL request = API_STATUS % stream.live_id try: # Connect to API connection = urllib2.urlopen(request, timeout=10) # Read the response xmlstring = connection.read() except URLError as e: # Couldn't connect raise e # Parse the XML xml = parseString(xmlstring) # Get the viewer count viewers = _getNodeText(xml.getElementsByTagName('liveViewers')[0]) viewers = int(viewers) # Get the status live = _getNodeText(xml.getElementsByTagName('isLive')[0]) live = True if live == 'true' else False # Return status return (live, viewers) def getStreamInfo(stream): """ Returns a StreamInfo object with the latest information about the input stream """ # Compose URL request = API_LIVE % stream.name tries = 0 # Try three times to make contact while True: try: # Connect to API connection = urllib2.urlopen(request, timeout=10) xmlstring = connection.read() except URLError as e: tries += 1 if tries >= 3: sys.stderr.write( 'own3dStreamsUpdater: Fatal error: Repeated timeouts') exit() # Make a document out of the XML xml = parseString(xmlstring) # Fetch all the items items = xml.getElementsByTagName('item') correctItem = False # An item represents a stream, so anything < 1 is unacceptable if len(items) < 1: raise ChannelNotFoundError() # In case multiple streams were found, narrow it down with the guid for item in items: # Dig out the guid from the xml item guidNode = item.getElementsByTagName('guid')[0] guid = _getNodeText(guidNode).split('/')[-1] if str(guid) == str(stream.live_id): correctItem = item break # Must have found the right item by now if not correctItem: raise StreamNotFoundError() # Now assemble the streaminfo title = _getNodeText(correctItem.getElementsByTagName('title')[0]) desc = _getNodeText(correctItem.getElementsByTagName('description')[0]) desc = strip_tags(desc) # Remove HTML about = None link = _getNodeText(correctItem.getElementsByTagName('link')[0]) channelImage = '/static/images/honlogo.png' screenCap = _getNodeText(correctItem.getElementsByTagName('thumbnail')[0]) si = StreamInfo() si.title = title si.description = desc si.about = about si.stream_url = link si.channelImage = channelImage si.screenCap = screenCap # Return the StreamInfo object return si def _getNodeText(node): "Returns the text content in an XML node" textNode = node.childNodes[0] text = textNode.nodeValue return text # ======================= # Debugging / development # ======================= if __name__ == '__main__': # Get the own3d stream stream = Stream.objects.filter(network__name='own3d')[0] print getStreamStatus(stream)