MythTV  master
bliptvXSL_api.py
Go to the documentation of this file.
1 # -*- coding: UTF-8 -*-
2 
3 # ----------------------
4 # Name: bliptvXSL_api - XPath and XSLT functions for the Blip.tv RSS/HTML itmes
5 # Python Script
6 # Author: R.D. Vaughan
7 # Purpose: This python script is intended to perform a variety of utility functions
8 # for the conversion of data to the MNV standard RSS output format.
9 # See this link for the specifications:
10 # http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format
11 #
12 # License:Creative Commons GNU GPL v2
13 # (http://creativecommons.org/licenses/GPL/2.0/)
14 #-------------------------------------
15 __title__ ="bliptvXSL_api - XPath and XSLT functions for the Blip.tv RSS/HTML"
16 __author__="R.D. Vaughan"
17 __purpose__='''
18 This python script is intended to perform a variety of utility functions
19 for the conversion of data to the MNV standard RSS output format.
20 See this link for the specifications:
21 http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format
22 '''
23 
24 __version__="v0.1.1"
25 # 0.1.0 Initial development
26 # 0.1.1 Fixed a bug when an autoplay link cannot be created
27 # Added MP4 as an acceptable downloadable video file type
28 
29 
30 # Specify the class names that have XPath extention functions
31 __xpathClassList__ = ['xpathFunctions', ]
32 
33 # Specify the XSLT extention class names. Each class is a stand lone extention function
34 #__xsltExtentionList__ = ['xsltExtExample', ]
35 __xsltExtentionList__ = []
36 
37 import os, sys, re, time, datetime, shutil, urllib.request, urllib.parse, urllib.error, string
38 from copy import deepcopy
39 import io
40 
41 class OutStreamEncoder(object):
42  """Wraps a stream with an encoder"""
43  def __init__(self, outstream, encoding=None):
44  self.out = outstream
45  if not encoding:
46  self.encoding = sys.getfilesystemencoding()
47  else:
48  self.encoding = encoding
49 
50  def write(self, obj):
51  """Wraps the output stream, encoding Unicode strings with the specified encoding"""
52  if isinstance(obj, str):
53  obj = obj.encode(self.encoding)
54  try:
55  self.out.buffer.write(obj)
56  except OSError:
57  pass
58 
59 
60  def __getattr__(self, attr):
61  """Delegate everything but write to the stream"""
62  return getattr(self.out, attr)
63 
64 if isinstance(sys.stdout, io.TextIOWrapper):
65  sys.stdout = OutStreamEncoder(sys.stdout, 'utf8')
66  sys.stderr = OutStreamEncoder(sys.stderr, 'utf8')
67 
68 try:
69  from io import StringIO
70  from lxml import etree
71 except Exception as e:
72  sys.stderr.write('\n! Error - Importing the "lxml" and "StringIO" python libraries failed on error(%s)\n' % e)
73  sys.exit(1)
74 
75 # Check that the lxml library is current enough
76 # From the lxml documents it states: (http://codespeak.net/lxml/installation.html)
77 # "If you want to use XPath, do not use libxml2 2.6.27. We recommend libxml2 2.7.2 or later"
78 # Testing was performed with the Ubuntu 9.10 "python-lxml" version "2.1.5-1ubuntu2" repository package
79 version = ''
80 for digit in etree.LIBXML_VERSION:
81  version+=str(digit)+'.'
82 version = version[:-1]
83 if version < '2.7.2':
84  sys.stderr.write('''
85 ! Error - The installed version of the "lxml" python library "libxml" version is too old.
86  At least "libxml" version 2.7.2 must be installed. Your version is (%s).
87 ''' % version)
88  sys.exit(1)
89 
90 
91 class xpathFunctions(object):
92  """Functions specific extending XPath
93  """
94  def __init__(self):
95  self.functList = ['bliptvFlvLinkGeneration', 'bliptvDownloadLinkGeneration', 'bliptvEpisode', 'bliptvIsCustomHTML', ]
96  self.episodeRegex = [
97  re.compile('''TERRA\\ (?P<episodeno>[0-9]+).*$''', re.UNICODE),
98  ]
99  self.namespaces = {
100  'xsi': "http://www.w3.org/2001/XMLSchema-instance",
101  'media': "http://search.yahoo.com/mrss/",
102  'xhtml': "http://www.w3.org/1999/xhtml",
103  'atm': "http://www.w3.org/2005/Atom",
104  'mythtv': "http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format",
105  'itunes':"http://www.itunes.com/dtds/podcast-1.0.dtd",
106  'creativeCommons': "http://backend.userland.com/creativeCommonsRssModule",
107  'geo': "http://www.w3.org/2003/01/geo/wgs84_pos#",
108  'blip': "http://blip.tv/dtd/blip/1.0",
109  'wfw': "http://wellformedweb.org/CommentAPI/",
110  'amp': "http://www.adobe.com/amp/1.0",
111  'dcterms': "http://purl.org/dc/terms",
112  'gm': "http://www.google.com/schemas/gm/1.1",
113  'mediaad': "http://blip.tv/dtd/mediaad/1.0",
114  }
115  self.flvFilter = etree.XPath(".//media:content[@type='video/x-flv']", namespaces=self.namespaces)
116  self.m4vFilter = etree.XPath(".//media:content[@type='video/mp4' or @type='video/quicktime' or @type='video/x-m4v']", namespaces=self.namespaces)
117  self.durationFilter = etree.XPath(".//blip:runtime/text()", namespaces=self.namespaces)
118  self.linkFilter = etree.XPath("./link/text()", namespaces=self.namespaces)
119  self.languageFilter = etree.XPath("../language/text()", namespaces=self.namespaces)
120  # end __init__()
121 
122 
127 
128  def bliptvFlvLinkGeneration(self, context, arg):
129  '''Generate a link for the Blip.tv site.
130  Call example: 'mnvXpath:bliptvFlvLinkGeneration(.)'
131  return the url link
132  '''
133  flvFile = self.flvFilter(arg[0])
134  if len(flvFile):
135  flvFileLink = flvFile[0].attrib['url']
136  return '%s%s' % (common.linkWebPage('dummy', 'bliptv'), flvFileLink.replace('.flv', '').replace('http://blip.tv/file/get/', ''))
137  else:
138  return self.linkFilter(arg[0])[0]
139  # end bliptvXSLLinkGeneration()
140 
141  def bliptvDownloadLinkGeneration(self, context, arg):
142  '''Generate a download link for the Blip.tv site.
143  Call example: 'mnvXpath:bliptvDownloadLinkGeneration(.)'
144  return an array of one download link element
145  '''
146  downloadLink = etree.XML('<link></link>')
147  flvFile = self.flvFilter(arg[0])
148  m4vFile = self.m4vFilter(arg[0])
149  if len(m4vFile):
150  downloadLink.attrib['url'] = m4vFile[0].attrib['url']
151  if m4vFile[0].attrib.get('width'):
152  downloadLink.attrib['width'] = m4vFile[0].attrib['width']
153  if m4vFile[0].attrib.get('height'):
154  downloadLink.attrib['height'] = m4vFile[0].attrib['height']
155  if m4vFile[0].attrib.get('fileSize'):
156  downloadLink.attrib['length'] = m4vFile[0].attrib['fileSize']
157  if len(self.durationFilter(arg[0])):
158  downloadLink.attrib['duration'] = self.durationFilter(arg[0])[0]
159  downloadLink.attrib['lang'] = self.languageFilter(arg[0])[0]
160  return [downloadLink]
161  elif len(flvFile):
162  downloadLink.attrib['url'] = flvFile[0].attrib['url']
163  if flvFile[0].attrib.get('width'):
164  downloadLink.attrib['width'] = flvFile[0].attrib['width']
165  if flvFile[0].attrib.get('height'):
166  downloadLink.attrib['height'] = flvFile[0].attrib['height']
167  if flvFile[0].attrib.get('fileSize'):
168  downloadLink.attrib['length'] = flvFile[0].attrib['fileSize']
169  if len(self.durationFilter(arg[0])):
170  downloadLink.attrib['duration'] = self.durationFilter(arg[0])[0]
171  downloadLink.attrib['lang'] = self.languageFilter(arg[0])[0]
172  return [downloadLink]
173  else:
174  downloadLink.attrib['url'] = self.linkFilter(arg[0])[0]
175  if len(self.durationFilter(arg[0])):
176  downloadLink.attrib['duration'] = self.durationFilter(arg[0])[0]
177  downloadLink.attrib['lang'] = self.languageFilter(arg[0])[0]
178  return [downloadLink]
179  # end bliptvDownloadLinkGeneration()
180 
181  def bliptvEpisode(self, context, arg):
182  '''Parse the title string and extract an episode number
183  Call example: 'mnvXpath:bliptvEpisode(./title/text())'
184  return the url link
185  '''
186  episodeNumber = ''
187  for index in range(len(self.episodeRegex)):
188  match = self.episodeRegex[index].match(arg[0])
189  if match:
190  episodeNumber = match.groups()
191  break
192  return etree.XML('<episode>%s</episode>' % episodeNumber)
193  # end bliptvEpisode()
194 
195  def bliptvIsCustomHTML(self, context, arg):
196  '''Parse the item element and deternmine if there is a flv file
197  Call example: 'mnvXpath:bliptvIsCustomHTML(.)'
198  return True is there is a '.flv' file
199  return False if there is no .flv' file
200  '''
201  if len(self.flvFilter(arg[0])):
202  return True
203  return False
204  # end bliptvIsCustomHTML()
205 
206 
211 
212 
217 
218 
nv_python_libs.xsltfunctions.bliptvXSL_api.xpathFunctions.bliptvDownloadLinkGeneration
def bliptvDownloadLinkGeneration(self, context, arg)
Definition: bliptvXSL_api.py:141
nv_python_libs.xsltfunctions.bliptvXSL_api.xpathFunctions.bliptvFlvLinkGeneration
def bliptvFlvLinkGeneration(self, context, arg)
Start of XPath extension functions.
Definition: bliptvXSL_api.py:128
nv_python_libs.xsltfunctions.bliptvXSL_api.OutStreamEncoder
Definition: bliptvXSL_api.py:41
nv_python_libs.xsltfunctions.bliptvXSL_api.xpathFunctions.functList
functList
Definition: bliptvXSL_api.py:95
nv_python_libs.xsltfunctions.bliptvXSL_api.xpathFunctions.episodeRegex
episodeRegex
Definition: bliptvXSL_api.py:96
nv_python_libs.xsltfunctions.bliptvXSL_api.xpathFunctions.flvFilter
flvFilter
Definition: bliptvXSL_api.py:115
nv_python_libs.xsltfunctions.bliptvXSL_api.OutStreamEncoder.__init__
def __init__(self, outstream, encoding=None)
Definition: bliptvXSL_api.py:43
nv_python_libs.xsltfunctions.bliptvXSL_api.OutStreamEncoder.__getattr__
def __getattr__(self, attr)
Definition: bliptvXSL_api.py:60
nv_python_libs.xsltfunctions.bliptvXSL_api.xpathFunctions.namespaces
namespaces
Definition: bliptvXSL_api.py:99
nv_python_libs.xsltfunctions.bliptvXSL_api.OutStreamEncoder.out
out
Definition: bliptvXSL_api.py:44
nv_python_libs.xsltfunctions.bliptvXSL_api.xpathFunctions.__init__
def __init__(self)
Definition: bliptvXSL_api.py:94
nv_python_libs.xsltfunctions.bliptvXSL_api.xpathFunctions.linkFilter
linkFilter
Definition: bliptvXSL_api.py:118
nv_python_libs.xsltfunctions.bliptvXSL_api.xpathFunctions.bliptvIsCustomHTML
def bliptvIsCustomHTML(self, context, arg)
Definition: bliptvXSL_api.py:195
nv_python_libs.xsltfunctions.bliptvXSL_api.xpathFunctions
Definition: bliptvXSL_api.py:91
nv_python_libs.xsltfunctions.bliptvXSL_api.xpathFunctions.bliptvEpisode
def bliptvEpisode(self, context, arg)
Definition: bliptvXSL_api.py:181
nv_python_libs.xsltfunctions.bliptvXSL_api.OutStreamEncoder.encoding
encoding
Definition: bliptvXSL_api.py:46
nv_python_libs.xsltfunctions.bliptvXSL_api.xpathFunctions.m4vFilter
m4vFilter
Definition: bliptvXSL_api.py:116
nv_python_libs.xsltfunctions.bliptvXSL_api.OutStreamEncoder.write
def write(self, obj)
Definition: bliptvXSL_api.py:50
nv_python_libs.xsltfunctions.bliptvXSL_api.xpathFunctions.languageFilter
languageFilter
Definition: bliptvXSL_api.py:119
nv_python_libs.xsltfunctions.bliptvXSL_api.xpathFunctions.durationFilter
durationFilter
Definition: bliptvXSL_api.py:117