00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 __title__ ="bliptvXSL_api - XPath and XSLT functions for the Blip.tv RSS/HTML"
00016 __author__="R.D. Vaughan"
00017 __purpose__='''
00018 This python script is intended to perform a variety of utility functions
00019 for the conversion of data to the MNV standard RSS output format.
00020 See this link for the specifications:
00021 http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format
00022 '''
00023
00024 __version__="v0.1.1"
00025
00026
00027
00028
00029
00030
00031 __xpathClassList__ = ['xpathFunctions', ]
00032
00033
00034
00035 __xsltExtentionList__ = []
00036
00037 import os, sys, re, time, datetime, shutil, urllib, string
00038 from copy import deepcopy
00039
00040
00041 class OutStreamEncoder(object):
00042 """Wraps a stream with an encoder"""
00043 def __init__(self, outstream, encoding=None):
00044 self.out = outstream
00045 if not encoding:
00046 self.encoding = sys.getfilesystemencoding()
00047 else:
00048 self.encoding = encoding
00049
00050 def write(self, obj):
00051 """Wraps the output stream, encoding Unicode strings with the specified encoding"""
00052 if isinstance(obj, unicode):
00053 try:
00054 self.out.write(obj.encode(self.encoding))
00055 except IOError:
00056 pass
00057 else:
00058 try:
00059 self.out.write(obj)
00060 except IOError:
00061 pass
00062
00063 def __getattr__(self, attr):
00064 """Delegate everything but write to the stream"""
00065 return getattr(self.out, attr)
00066 sys.stdout = OutStreamEncoder(sys.stdout, 'utf8')
00067 sys.stderr = OutStreamEncoder(sys.stderr, 'utf8')
00068
00069 try:
00070 from StringIO import StringIO
00071 from lxml import etree
00072 except Exception, e:
00073 sys.stderr.write(u'\n! Error - Importing the "lxml" and "StringIO" python libraries failed on error(%s)\n' % e)
00074 sys.exit(1)
00075
00076
00077
00078
00079
00080 version = ''
00081 for digit in etree.LIBXML_VERSION:
00082 version+=str(digit)+'.'
00083 version = version[:-1]
00084 if version < '2.7.2':
00085 sys.stderr.write(u'''
00086 ! Error - The installed version of the "lxml" python library "libxml" version is too old.
00087 At least "libxml" version 2.7.2 must be installed. Your version is (%s).
00088 ''' % version)
00089 sys.exit(1)
00090
00091
00092 class xpathFunctions(object):
00093 """Functions specific extending XPath
00094 """
00095 def __init__(self):
00096 self.functList = ['bliptvFlvLinkGeneration', 'bliptvDownloadLinkGeneration', 'bliptvEpisode', 'bliptvIsCustomHTML', ]
00097 self.episodeRegex = [
00098 re.compile(u'''TERRA\\ (?P<episodeno>[0-9]+).*$''', re.UNICODE),
00099 ]
00100 self.namespaces = {
00101 'xsi': u"http://www.w3.org/2001/XMLSchema-instance",
00102 'media': u"http://search.yahoo.com/mrss/",
00103 'xhtml': u"http://www.w3.org/1999/xhtml",
00104 'atm': u"http://www.w3.org/2005/Atom",
00105 'mythtv': "http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format",
00106 'itunes':"http://www.itunes.com/dtds/podcast-1.0.dtd",
00107 'creativeCommons': "http://backend.userland.com/creativeCommonsRssModule",
00108 'geo': "http://www.w3.org/2003/01/geo/wgs84_pos#",
00109 'blip': "http://blip.tv/dtd/blip/1.0",
00110 'wfw': "http://wellformedweb.org/CommentAPI/",
00111 'amp': "http://www.adobe.com/amp/1.0",
00112 'dcterms': "http://purl.org/dc/terms",
00113 'gm': "http://www.google.com/schemas/gm/1.1",
00114 'mediaad': "http://blip.tv/dtd/mediaad/1.0",
00115 }
00116 self.flvFilter = etree.XPath(".//media:content[@type='video/x-flv']", namespaces=self.namespaces)
00117 self.m4vFilter = etree.XPath(".//media:content[@type='video/mp4' or @type='video/quicktime' or @type='video/x-m4v']", namespaces=self.namespaces)
00118 self.durationFilter = etree.XPath(".//blip:runtime/text()", namespaces=self.namespaces)
00119 self.linkFilter = etree.XPath("./link/text()", namespaces=self.namespaces)
00120 self.languageFilter = etree.XPath("../language/text()", namespaces=self.namespaces)
00121
00122
00123
00124
00125
00126
00127
00128
00129 def bliptvFlvLinkGeneration(self, context, arg):
00130 '''Generate a link for the Blip.tv site.
00131 Call example: 'mnvXpath:bliptvFlvLinkGeneration(.)'
00132 return the url link
00133 '''
00134 flvFile = self.flvFilter(arg[0])
00135 if len(flvFile):
00136 flvFileLink = flvFile[0].attrib['url']
00137 return u'%s%s' % (common.linkWebPage('dummy', 'bliptv'), flvFileLink.replace(u'.flv', u'').replace(u'http://blip.tv/file/get/', u''))
00138 else:
00139 return self.linkFilter(arg[0])[0]
00140
00141
00142 def bliptvDownloadLinkGeneration(self, context, arg):
00143 '''Generate a download link for the Blip.tv site.
00144 Call example: 'mnvXpath:bliptvDownloadLinkGeneration(.)'
00145 return an array of one download link element
00146 '''
00147 downloadLink = etree.XML(u'<link></link>')
00148 flvFile = self.flvFilter(arg[0])
00149 m4vFile = self.m4vFilter(arg[0])
00150 if len(m4vFile):
00151 downloadLink.attrib['url'] = m4vFile[0].attrib['url']
00152 if m4vFile[0].attrib.get('width'):
00153 downloadLink.attrib['width'] = m4vFile[0].attrib['width']
00154 if m4vFile[0].attrib.get('height'):
00155 downloadLink.attrib['height'] = m4vFile[0].attrib['height']
00156 if m4vFile[0].attrib.get('fileSize'):
00157 downloadLink.attrib['length'] = m4vFile[0].attrib['fileSize']
00158 if len(self.durationFilter(arg[0])):
00159 downloadLink.attrib['duration'] = self.durationFilter(arg[0])[0]
00160 downloadLink.attrib['lang'] = self.languageFilter(arg[0])[0]
00161 return [downloadLink]
00162 elif len(flvFile):
00163 downloadLink.attrib['url'] = flvFile[0].attrib['url']
00164 if flvFile[0].attrib.get('width'):
00165 downloadLink.attrib['width'] = flvFile[0].attrib['width']
00166 if flvFile[0].attrib.get('height'):
00167 downloadLink.attrib['height'] = flvFile[0].attrib['height']
00168 if flvFile[0].attrib.get('fileSize'):
00169 downloadLink.attrib['length'] = flvFile[0].attrib['fileSize']
00170 if len(self.durationFilter(arg[0])):
00171 downloadLink.attrib['duration'] = self.durationFilter(arg[0])[0]
00172 downloadLink.attrib['lang'] = self.languageFilter(arg[0])[0]
00173 return [downloadLink]
00174 else:
00175 downloadLink.attrib['url'] = self.linkFilter(arg[0])[0]
00176 if len(self.durationFilter(arg[0])):
00177 downloadLink.attrib['duration'] = self.durationFilter(arg[0])[0]
00178 downloadLink.attrib['lang'] = self.languageFilter(arg[0])[0]
00179 return [downloadLink]
00180
00181
00182 def bliptvEpisode(self, context, arg):
00183 '''Parse the title string and extract an episode number
00184 Call example: 'mnvXpath:bliptvEpisode(./title/text())'
00185 return the url link
00186 '''
00187 episodeNumber = u''
00188 for index in range(len(self.episodeRegex)):
00189 match = self.episodeRegex[index].match(arg[0])
00190 if match:
00191 episodeNumber = match.groups()
00192 break
00193 return etree.XML(u'<episode>%s</episode>' % episodeNumber)
00194
00195
00196 def bliptvIsCustomHTML(self, context, arg):
00197 '''Parse the item element and deternmine if there is a flv file
00198 Call example: 'mnvXpath:bliptvIsCustomHTML(.)'
00199 return True is there is a '.flv' file
00200 return False if there is no .flv' file
00201 '''
00202 if len(self.flvFilter(arg[0])):
00203 return True
00204 return False
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223