MythTV  master
mevio_api.py
Go to the documentation of this file.
1 # -*- coding: UTF-8 -*-
2 
3 # ----------------------
4 # Name: mevio_api - XPath and XSLT functions for the Mevio RSS/HTML items
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__ ="mevio_api - XPath and XSLT functions for the www.mevio.com 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 # Added checking to see if the item is already in the data base
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  def __getattr__(self, attr):
60  """Delegate everything but write to the stream"""
61  return getattr(self.out, attr)
62 
63 if isinstance(sys.stdout, io.TextIOWrapper):
64  sys.stdout = OutStreamEncoder(sys.stdout, 'utf8')
65  sys.stderr = OutStreamEncoder(sys.stderr, 'utf8')
66 
67 try:
68  from io import StringIO
69  from lxml import etree
70 except Exception as e:
71  sys.stderr.write('\n! Error - Importing the "lxml" and "StringIO" python libraries failed on error(%s)\n' % e)
72  sys.exit(1)
73 
74 # Check that the lxml library is current enough
75 # From the lxml documents it states: (http://codespeak.net/lxml/installation.html)
76 # "If you want to use XPath, do not use libxml2 2.6.27. We recommend libxml2 2.7.2 or later"
77 # Testing was performed with the Ubuntu 9.10 "python-lxml" version "2.1.5-1ubuntu2" repository package
78 version = ''
79 for digit in etree.LIBXML_VERSION:
80  version+=str(digit)+'.'
81 version = version[:-1]
82 if version < '2.7.2':
83  sys.stderr.write('''
84 ! Error - The installed version of the "lxml" python library "libxml" version is too old.
85  At least "libxml" version 2.7.2 must be installed. Your version is (%s).
86 ''' % version)
87  sys.exit(1)
88 
89 
90 class xpathFunctions(object):
91  """Functions specific extending XPath
92  """
93  def __init__(self):
94  self.functList = ['mevioLinkGeneration', 'mevioTitle', 'mevioEpisode', 'mevioCheckIfDBItem', ]
95  self.episodeRegex = [
96  # Episode 224
97  re.compile('''^.+?Episode\\ (?P<episodeno>[0-9]+).*$''', re.UNICODE),
98  # CrankyGeeks 136:
99  re.compile('''^.+?(?P<episodeno>[0-9]+)\\:.*$''', re.UNICODE),
100  ]
101  self.namespaces = {
102  'atom10': "http://www.w3.org/2005/Atom",
103  'media': "http://search.yahoo.com/mrss/",
104  'itunes':"http://www.itunes.com/dtds/podcast-1.0.dtd",
105  'xhtml': "http://www.w3.org/1999/xhtml",
106  'feedburner': "http://rssnamespace.org/feedburner/ext/1.0",
107  'mythtv': "http://www.mythtv.org/wiki/MythNetvision_Grabber_Script_Format",
108  'dc': "http://purl.org/dc/elements/1.1/",
109  'fb': "http://www.facebook.com/2008/fbml/",
110  }
111  self.mediaIdFilters = [
112  [etree.XPath(".//embed/@flashvars", namespaces=self.namespaces), re.compile('''^.+?MediaId=(?P<videocode>[0-9]+).*$''', re.UNICODE)],
113  [etree.XPath(".//div[@class='player_wrapper']/a/@href", namespaces=self.namespaces), re.compile('''^.+?\\'(?P<videocode>[0-9]+)\\'\\)\\;.*$''', re.UNICODE)]
114  ]
115  # end __init__()
116 
117 
122 
123  def mevioLinkGeneration(self, context, *arg):
124  '''Generate a link for the video.
125  Call example: 'mnvXpath:mevioLinkGeneration(string(link))'
126  return the url link
127  '''
128  webURL = arg[0]
129  try:
130  tmpHTML = etree.parse(webURL, etree.HTMLParser())
131  except Exception as errmsg:
132  sys.stderr.write("Error reading url(%s) error(%s)\n" % (webURL, errmsg))
133  return webURL
134 
135  for index in range(len(self.mediaIdFilters)):
136  mediaId = self.mediaIdFilters[index][0](tmpHTML)
137  if not len(mediaId):
138  continue
139  match = self.mediaIdFilters[index][1].match(mediaId[0])
140  if match:
141  videocode = match.groups()
142  return 'file://%s/nv_python_libs/configs/HTML/mevio.html?videocode=%s' % (common.baseProcessingDir, videocode[0])
143  else:
144  return webURL
145  # end mevioLinkGeneration()
146 
147  def mevioTitle(self, context, arg):
148  '''Parse the title string extract only the title text removing the redundant show name
149  Call example: 'mnvXpath:mevioTitle(./title/text())'
150  return the title text
151  '''
152  epText = self.mevioEpisode('dummy', arg).text
153  if epText:
154  epText = 'Ep %s: ' % epText
155  else:
156  epText = ''
157  seperatorStrs = [[' | ', 'before'], [': ', 'after'], [' - ', 'before']]
158  for sepStr in seperatorStrs:
159  if sepStr[1] == 'after':
160  index = arg[0].find(sepStr[0])
161  else:
162  index = arg[0].rfind(sepStr[0])
163  if index != -1:
164  if sepStr[1] == 'after':
165  return '%s%s' % (epText, arg[0][index+len(sepStr[0]):].strip())
166  else:
167  return '%s%s' % (epText, arg[0][:index].strip())
168  else:
169  if epText:
170  return epText
171  else:
172  return arg[0].strip()
173  # end mevioTitle()
174 
175  def mevioEpisode(self, context, arg):
176  '''Parse the title string and extract an episode number
177  Call example: 'mnvXpath:mevioEpisode(./title/text())'
178  return an episode element
179  '''
180  episodeNumber = ''
181  for index in range(len(self.episodeRegex)):
182  match = self.episodeRegex[index].match(arg[0])
183  if match:
184  episodeNumber = match.groups()
185  break
186  return etree.XML('<episode>%s</episode>' % episodeNumber)
187  # end mevioEpisode()
188 
189  def mevioCheckIfDBItem(self, context, *arg):
190  '''Use a unique key value pairing to find out if the 'internetcontentarticles' table already
191  has a matching item. This is done to save accessing the Internet when not required.
192  Call example: 'mnvXpath:mevioCheckIfDBItem(title, description)'
193  return True if a match was found
194  return False if a match was not found
195  '''
196  return common.checkIfDBItem('dummy', {'feedtitle': 'Technology', 'title': arg[0], 'description': arg[1]})
197  # end mevioCheckIfDBItem()
198 
199 
204 
205 
210 
211 
nv_python_libs.xsltfunctions.mevio_api.OutStreamEncoder.out
out
Definition: mevio_api.py:44
nv_python_libs.xsltfunctions.mevio_api.xpathFunctions.mediaIdFilters
mediaIdFilters
Definition: mevio_api.py:111
nv_python_libs.xsltfunctions.mevio_api.OutStreamEncoder.encoding
encoding
Definition: mevio_api.py:46
nv_python_libs.xsltfunctions.mevio_api.xpathFunctions.mevioCheckIfDBItem
def mevioCheckIfDBItem(self, context, *arg)
Definition: mevio_api.py:189
nv_python_libs.xsltfunctions.mevio_api.xpathFunctions.episodeRegex
episodeRegex
Definition: mevio_api.py:95
nv_python_libs.xsltfunctions.mevio_api.xpathFunctions.namespaces
namespaces
Definition: mevio_api.py:101
nv_python_libs.xsltfunctions.mevio_api.xpathFunctions.mevioLinkGeneration
def mevioLinkGeneration(self, context, *arg)
Start of XPath extension functions.
Definition: mevio_api.py:123
nv_python_libs.xsltfunctions.mevio_api.OutStreamEncoder.write
def write(self, obj)
Definition: mevio_api.py:50
nv_python_libs.xsltfunctions.mevio_api.OutStreamEncoder.__init__
def __init__(self, outstream, encoding=None)
Definition: mevio_api.py:43
nv_python_libs.xsltfunctions.mevio_api.OutStreamEncoder
Definition: mevio_api.py:41
nv_python_libs.xsltfunctions.mevio_api.xpathFunctions.functList
functList
Definition: mevio_api.py:94
nv_python_libs.xsltfunctions.mevio_api.OutStreamEncoder.__getattr__
def __getattr__(self, attr)
Definition: mevio_api.py:59
nv_python_libs.xsltfunctions.mevio_api.xpathFunctions.mevioEpisode
def mevioEpisode(self, context, arg)
Definition: mevio_api.py:175
nv_python_libs.xsltfunctions.mevio_api.xpathFunctions.__init__
def __init__(self)
Definition: mevio_api.py:93
nv_python_libs.xsltfunctions.mevio_api.xpathFunctions.mevioTitle
def mevioTitle(self, context, arg)
Definition: mevio_api.py:147
find
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
Definition: dvbstreamhandler.cpp:363
nv_python_libs.xsltfunctions.mevio_api.xpathFunctions
Definition: mevio_api.py:90