# =======
# 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, viewers>
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)