MythTV master
bbciplayer.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# -*- coding: UTF-8 -*-
3# ----------------------
4# Name: bbciplayer.py
5# Python Script
6# Author: R.D. Vaughan
7# Purpose:
8# This python script is intended to perform BBC iplayer video lookups for the MythTV Netvision plugin
9# based on information found on the http://www.bbc.co.uk/iplayer/ website. It
10# follows the MythTV Netvision grabber standards.
11#
12# Command example:
13# See help (-u and -h) options
14#
15# Design:
16# 1) Read the ".../emml/feConfig.xml"
17# 2) Check if the CGI Web server should be used or if the script is run locally
18# 3) Initialize the correct target functions for processing (local or remote)
19# 4) Process the search or treeview request and display to stdout
20#
21#
22# License:Creative Commons GNU GPL v2
23# (http://creativecommons.org/licenses/GPL/2.0/)
24#-------------------------------------
25__title__ ="BBC iPlayer";
26__mashup_title__ = "bbcipplayer"
27__author__="R.D. Vaughan"
28__version__="0.15"
29# 0.1.0 Initial development
30# 0.1.1 Added treeview support
31# 0.1.2 Convert to detect and use either local or remote processing
32# 0.13 Change to support xml version information display
33# 0.14 Added the "command" tag to the xml version information display
34# 0.15 Converted to new common_api.py library
35
36__usage_examples__ ='''
37(Option Help)
38> ./bbciplayer.py -h
39Usage: ./bbciplayer.py -hduvlST [parameters] <search text>
40Version: v0.1.2 Author: R.D.Vaughan
41
42For details on the MythTV Netvision plugin see the wiki page at:
43http://www.mythtv.org/wiki/MythNetvision
44
45Options:
46 -h, --help show this help message and exit
47 -d, --debug Show debugging info (URLs, raw XML ... etc, info
48 varies per grabber)
49 -u, --usage Display examples for executing the script
50 -v, --version Display grabber name and supported options
51 -l LANGUAGE, --language=LANGUAGE
52 Select data that matches the specified language fall
53 back to English if nothing found (e.g. 'es' EspaƱol,
54 'de' Deutsch ... etc). Not all sites or grabbers
55 support this option.
56 -p PAGE NUMBER, --pagenumber=PAGE NUMBER
57 Display specific page of the search results. Default
58 is page 1. Page number is ignored with the Tree View
59 option (-T).
60 -S, --search Search for videos
61 -T, --treeview Display a Tree View of a sites videos
62
63> ./bbciplayer.py -v
64<grabber>
65 <name>BBC iPlayer</name>
66 <author>R.D. Vaughan</author>
67 <thumbnail>bbciplayer.png</thumbnail>
68 <type>video</type>
69 <description>BBC iPlayer is our service that lets you catch up with radio and television programmes from the past week.</description>
70 <version>v0.13</version>
71 <search>true</search>
72 <tree>true</tree>
73</grabber>
74
75> ./bbciplayer.py -S "Doctor Who"
76<?xml version="1.0" encoding="UTF-8"?>
77<rss version="2.0" xmlns:amp="http://www.adobe.com/amp/1.0"
78 xmlns:atom="http://www.w3.org/2005/Atom"
79 xmlns:cnettv="http://cnettv.com/mrss/"
80 xmlns:content="http://purl.org/rss/1.0/modules/content/"
81 xmlns:creativecommons="http://backend.userland.com/creativeCommonsRssModule"
82 xmlns:dc="http://purl.org/dc/elements/1.1/"
83 xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:media="http://search.yahoo.com/mrss/">
84 <channel>
85 <title>BBC iPlayer</title>
86 <link>http://www.bbc.co.uk</link>
87 <description>BBC iPlayer is our service that lets you catch up with radio and television programmes from the past week.</description>
88 <numresults>7</numresults>
89 <returned>7</returned>
90 <startindex>7</startindex>
91 <item>
92 <title>Doctor Who - Series 4 - 11. Turn Left</title>
93 <author>British Broadcasting Corporation</author>
94 <pubDate>Wed, 24 Mar 2010 18:35:41 GMT</pubDate>
95 <description>Can Donna and Rose stop the approaching Darkness? (R)</description>
96 <link>http://www.bbc.co.uk/iplayer/episode/b00c7ytx/Doctor_Who_Series_4_Turn_Left/</link>
97 <media:group>
98 <media:thumbnail url="http://node1.bbcimg.co.uk/iplayer/images/episode/b00c7ytx_120_68.jpg"/>
99 <media:content duration="" height="" lang=""
100 url="http://www.bbc.co.uk/iplayer/episode/b00c7ytx/Doctor_Who_Series_4_Turn_Left/" width=""/>
101 </media:group>
102 <rating>0.0</rating>
103 </item>
104...
105 <item>
106 <title>Doctor Who Confidential - Series 4 - 13. The End of an Era</title>
107 <author>British Broadcasting Corporation</author>
108 <pubDate>Wed, 24 Mar 2010 18:35:41 GMT</pubDate>
109 <description>The series finale as the Doctor's arch enemy brings the universe to the edge of extinction (R)</description>
110 <link>http://www.bbc.co.uk/iplayer/episode/b00cgphl/Doctor_Who_Confidential_Series_4_The_End_of_an_Era/</link>
111 <media:group>
112 <media:thumbnail url="http://node1.bbcimg.co.uk/iplayer/images/episode/b00cgphl_120_68.jpg"/>
113 <media:content duration="" height="" lang=""
114 url="http://www.bbc.co.uk/iplayer/episode/b00cgphl/Doctor_Who_Confidential_Series_4_The_End_of_an_Era/" width=""/>
115 </media:group>
116 <rating>0.0</rating>
117 </item>
118 </channel>
119</rss>
120
121> ./bbciplayer.py -T
122<?xml version="1.0" encoding="UTF-8"?>
123<rss version="2.0" xmlns:amp="http://www.adobe.com/amp/1.0"
124 xmlns:atom="http://www.w3.org/2005/Atom"
125 xmlns:cnettv="http://cnettv.com/mrss/"
126 xmlns:content="http://purl.org/rss/1.0/modules/content/"
127 xmlns:creativecommons="http://backend.userland.com/creativeCommonsRssModule"
128 xmlns:dc="http://purl.org/dc/elements/1.1/"
129 xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:media="http://search.yahoo.com/mrss/">
130 <channel>
131 <title>BBC iPlayer</title>
132 <link>http://www.bbc.co.uk</link>
133 <description>BBC iPlayer is our service that lets you catch up with radio and television programmes from the past week.</description>
134 <numresults>1</numresults>
135 <returned>1</returned>
136 <startindex>1</startindex>
137 <directory name="BBC iPlayer" thumbnail="/usr/local/share/mythtv/mythnetvision/icons/bbciplayer.png">
138 <directory name="BBC iPlayer - TV Highlights" thumbnail="/usr/local/share/mythtv/mythnetvision/icons/bbciplayer.png">
139 <item>
140 <title>Great Ormond Street: Pushing the Boundaries</title>
141 <author>BBC</author>
142 <pubDate>Wed, 07 Apr 2010 17:00:49 GMT</pubDate>
143 <description>A look at the work of the largest children&amp;apos;s cardiac unit in the UK.</description>
144 <link>http://localhost:8080/emml/cgi-bin/bbciplayer_embedded.py?videocode=b00s02ct</link>
145 <mrss:group xmlns:mrss="http://search.yahoo.com/mrss/">
146 <mrss:thumbnail url="http://node2.bbcimg.co.uk/iplayer/images/episode/b00s02ct_150_84.jpg"/>
147 <mrss:content duration="" height="" lang=""
148 url="http://localhost:8080/emml/cgi-bin/bbciplayer_embedded.py?videocode=b00s02ct" width=""/>
149 </mrss:group>
150 <rating>0.0</rating>
151 </item>
152...
153 <item>
154 <title>The Real Hustle: Series 7: On Holiday - Cutdowns: Episode 8</title>
155 <author>BBC</author>
156 <pubDate>Fri, 02 Apr 2010 07:29:46 GMT</pubDate>
157 <description>Paul relieves some unsuspecting tourists of their spending money in Oxford.</description>
158 <link>http://localhost:8080/emml/cgi-bin/bbciplayer_embedded.py?videocode=b00rw6xb</link>
159 <mrss:group xmlns:mrss="http://search.yahoo.com/mrss/">
160 <mrss:thumbnail url="http://node2.bbcimg.co.uk/iplayer/images/episode/b00rw6xb_150_84.jpg"/>
161 <mrss:content duration="" height="" lang=""
162 url="http://localhost:8080/emml/cgi-bin/bbciplayer_embedded.py?videocode=b00rw6xb" width=""/>
163 </mrss:group>
164 <rating>0.0</rating>
165 </item>
166 </directory>
167 </directory>
168 </channel>
169</rss>
170'''
171__search_max_page_items__ = 20
172__tree_max_page_items__ = 20
173
174import sys, os
175import io
176
177
178class OutStreamEncoder(object):
179 """Wraps a stream with an encoder"""
180 def __init__(self, outstream, encoding=None):
181 self.out = outstream
182 if not encoding:
183 self.encoding = sys.getfilesystemencoding()
184 else:
185 self.encoding = encoding
186
187 def write(self, obj):
188 """Wraps the output stream, encoding Unicode strings with the specified encoding"""
189 if isinstance(obj, str):
190 obj = obj.encode(self.encoding)
191 self.out.buffer.write(obj)
192
193 def __getattr__(self, attr):
194 """Delegate everything but write to the stream"""
195 return getattr(self.out, attr)
196
197if isinstance(sys.stdout, io.TextIOWrapper):
198 sys.stdout = OutStreamEncoder(sys.stdout, 'utf8')
199 sys.stderr = OutStreamEncoder(sys.stderr, 'utf8')
200
201
202# Used for debugging
203#import nv_python_libs.common.common_api
204try:
205 '''Import the common python class
206 '''
207 import nv_python_libs.common.common_api as common_api
208except Exception as e:
209 sys.stderr.write('''
210The subdirectory "nv_python_libs/common" containing the modules common_api.py and
211common_exceptions.py (v0.1.3 or greater),
212They should have been included with the distribution of MythNetvision
213Error(%s)
214''' % e)
215 sys.exit(1)
216if common_api.__version__ < '0.1.3':
217 sys.stderr.write("\n! Error: Your current installed common_api.py version is (%s)\nYou must at least have version (0.1.3) or higher.\n" % target.__version__)
218 sys.exit(1)
219
220# Used for debugging
221#import nv_python_libs.bbciplayer.bbciplayer_api as target
222try:
223 '''Import the python bbciplayer support classes
224 '''
226except Exception as e:
227 sys.stderr.write('''
228The subdirectory "nv_python_libs/bbciplayer" containing the modules bbciplayer_api and
229bbciplayer_exceptions.py (v0.1.0 or greater),
230They should have been included with the distribution of bbciplayer.py.
231Error(%s)
232''' % e)
233 sys.exit(1)
234if target.__version__ < '0.1.0':
235 sys.stderr.write("\n! Error: Your current installed bbciplayer_api.py version is (%s)\nYou must at least have version (0.1.0) or higher.\n" % target.__version__)
236 sys.exit(1)
237
238# Verify that the main process modules are installed and accessible
239try:
240 import nv_python_libs.mainProcess as process
241except Exception as e:
242 sys.stderr.write('''
243The python script "nv_python_libs/mainProcess.py" must be present.
244Error(%s)
245''' % e)
246 sys.exit(1)
247
248if process.__version__ < '0.2.0':
249 sys.stderr.write("\n! Error: Your current installed mainProcess.py version is (%s)\nYou must at least have version (0.2.0) or higher.\n" % process.__version__)
250 sys.exit(1)
251
252if __name__ == '__main__':
253 # No api key is required
254 apikey = ""
255 # Set the base processing directory that the grabber is installed
256 target.baseProcessingDir = os.path.dirname( os.path.realpath( __file__ ))
257 # Make sure the target functions have an instance of the common routines
258 target.common = common_api.Common()
259 main = process.mainProcess(target, apikey, )
260 main.grabberInfo = {}
261 main.grabberInfo['enabled'] = True
262 main.grabberInfo['title'] = __title__
263 main.grabberInfo['mashup_title'] = __mashup_title__
264 main.grabberInfo['command'] = 'bbciplayer.py'
265 main.grabberInfo['author'] = __author__
266 main.grabberInfo['thumbnail'] = 'bbciplayer.png'
267 main.grabberInfo['type'] = ['video', ]
268 main.grabberInfo['desc'] = "BBC iPlayer is our service that lets you catch up with radio and television programmes from the past week."
269 main.grabberInfo['version'] = __version__
270 main.grabberInfo['search'] = True
271 main.grabberInfo['tree'] = True
272 main.grabberInfo['html'] = False
273 main.grabberInfo['usage'] = __usage_examples__
274 main.grabberInfo['SmaxPage'] = __search_max_page_items__
275 main.grabberInfo['TmaxPage'] = __tree_max_page_items__
276 main.main()
def __init__(self, outstream, encoding=None)
Definition: bbciplayer.py:180
def __getattr__(self, attr)
Definition: bbciplayer.py:193