|
MythTV
0.26-pre
|
00001 #!/usr/bin/env python 00002 # -*- coding: UTF-8 -*- 00003 # ---------------------- 00004 # Name: tmdb.py 00005 # Python Script 00006 # Author: R.D. Vaughan 00007 # Purpose: 00008 # This python script is intended to perform Movie data lookups 00009 # based on information found on the http://themoviedb.org/ website. It 00010 # follows the MythTV standards set for grabbers 00011 # http://www.mythtv.org/wiki/MythVideo_Grabber_Script_Format 00012 # This script uses the python module tmdb_api.py which should be included 00013 # with this script. 00014 # The tmdb_api.py module uses the full access v2.1 XML api published by 00015 # themoviedb.org see: http://api.themoviedb.org/2.1/ 00016 # Users of this script are encouraged to populate themoviedb.org with Movie 00017 # information, posters and fan art. The richer the source the more 00018 # valuable the script. 00019 # Command example: 00020 # See help (-u and -h) options 00021 # 00022 # Design: 00023 # 1) Verify the command line options (display help or version and exit) 00024 # 2) Verify that themoviedb.org has the Movie being requested exit if does not exit 00025 # 3) Find the requested information and send to stdout if any found 00026 # 00027 # 00028 # License:Creative Commons GNU GPL v2 00029 # (http://creativecommons.org/licenses/GPL/2.0/) 00030 #------------------------------------- 00031 __title__ ="TheMovieDB.org"; 00032 __author__="R.D.Vaughan" 00033 __version__="0.21" 00034 # 0.1.0 Initial development 00035 # 0.1.1 Alpha Release 00036 # 0.1.2 New movie data fields now have proper key names 00037 # Dynamic CamelCoding of keys if they are not already in the translation list 00038 # Fixed and re-arranged some code for minor issues. 00039 # 0.1.3 Fixed an abort when there is no data found for Movie and People information display 00040 # Added CamelCase to all People information keys 00041 # 0.1.4 Added handling of all of the tmdb_api exceptions and information process exceptions with proper exit 00042 # codes (0-Script Normal exit; 1-Script Exception exit) 00043 # 0.1.5 Corrected processing of Person images 00044 # Added a specific check and error when there is an empty argument passed 00045 # Changed the formatting of person information for AlsoKnownAs and Filmography 00046 # 0.1.6 Stopped stderr output when any TMDB meta data search or access does not find anything. 00047 # This was causing issues for MythVideo. 00048 # 0.1.7 Change over to the installed TMDB api library 00049 # 0.1.8 Improved displayed messages on an exception abort 00050 # 0.1.9 Added support for XML output 00051 # 0.2.0 Make XML output the default 00052 # Version 1.12 Convert version information to XML 00053 # 1.13 Add test mode 00054 00055 00056 __usage_examples__=''' 00057 Request tmdb.py verison number: 00058 > ./tmdb.py -v 00059 <grabber> 00060 <name>TheMovieDB.org</name> 00061 <author>R.D.Vaughan</author> 00062 <thumbnail>tmdb.png</thumbnail> 00063 <command>tmdb.py</command> 00064 <type>movie</type> 00065 <description>Search and metadata downloads for themoviedb.org</description> 00066 <version>0.XX</version> 00067 </grabber> 00068 00069 Request a list of matching movie titles: 00070 > ./tmdb.py -M "Avatar" 00071 <?xml version='1.0' encoding='UTF-8'?> 00072 <metadata> 00073 <item> 00074 <language>en</language> 00075 <title>Avatar</title> 00076 <subtitle>Creating the World of Pandora</subtitle> 00077 <inetref>31631</inetref> 00078 <imdb/> 00079 <userrating>8.5</userrating> 00080 <certifications> 00081 <certification locale="us" name="PG"/> 00082 </certifications> 00083 <description>The cast and crew take you on an in-depth look at the making of James Cameron's epic.</description> 00084 <releasedate>2009-12-01</releasedate> 00085 ... 00086 <item> 00087 <language>en</language> 00088 <title>Avatar 2</title> 00089 <inetref>37739</inetref> 00090 <imdb>1630029</imdb> 00091 <userrating>0.0</userrating> 00092 <description>soon :)</description> 00093 <releasedate>2014-04-10</releasedate> 00094 <lastupdated>Fri, 14 May 2010 05:41:13 GMT</lastupdated> 00095 </item> 00096 </metadata> 00097 00098 Request movie details using a TMDB#: 00099 > ./tmdb.py -D 19995 00100 <?xml version='1.0' encoding='UTF-8'?> 00101 <metadata> 00102 <item> 00103 <title>Avatar</title> 00104 <tagline>Enter the World</tagline> 00105 <language>en</language> 00106 <description>A paraplegic former Marine finds a new life on the distant planet of Pandora. Only to find himself battling humankind alongside the planet's indigenous Na'vi race in this ambitious digital 3D sci-fi epic from Academy Award-winning Titanic director James Cameron.</description> 00107 <certifications> 00108 <certification locale="us" name="PG-13"/> 00109 </certifications> 00110 <categories> 00111 <category type="genre" name="Action"/> 00112 <category type="genre" name="Adventure"/> 00113 <category type="genre" name="Fantasy"/> 00114 <category type="genre" name="Science Fiction"/> 00115 <category type="genre" name="Thriller"/> 00116 </categories> 00117 <studios> 00118 <studio name="20th Century Fox"/> 00119 </studios> 00120 ... 00121 <image type="fanart" thumb="http://i1.themoviedb.org/backdrops/9fa/4bc95845017a3c57fe0279fa/avatar-thumb.jpg" url="http://i2.themoviedb.org/backdrops/9fa/4bc95845017a3c57fe0279fa/avatar-original.jpg" width="1920" height="1080"/> 00122 <image type="fanart" thumb="http://i2.themoviedb.org/backdrops/a1e/4bc9584d017a3c57fe027a1e/avatar-thumb.jpg" url="http://i2.themoviedb.org/backdrops/a1e/4bc9584d017a3c57fe027a1e/avatar-original.jpg" width="1920" height="1080"/> 00123 <image type="fanart" thumb="http://i1.themoviedb.org/backdrops/9fe/4bc95846017a3c57fe0279fe/avatar-thumb.jpg" url="http://i3.themoviedb.org/backdrops/9fe/4bc95846017a3c57fe0279fe/avatar-original.jpg" width="1920" height="1080"/> 00124 </images> 00125 </item> 00126 </metadata> 00127 00128 Request movie details using a IMDB#: 00129 > ./tmdb.py -D 0499549 00130 <?xml version='1.0' encoding='UTF-8'?> 00131 <metadata> 00132 <item> 00133 <title>Avatar</title> 00134 <language>en</language> 00135 <description>A paraplegic former Marine finds a new life on the distant planet of Pandora. Only to find himself battling humankind alongside the planet's indigenous Na'vi race in this ambitious digital 3D sci-fi epic from Academy Award-winning Titanic director James Cameron.</description> 00136 <certifications> 00137 <certification locale="us" name="PG-13"/> 00138 </certifications> 00139 ... 00140 width="1920" height="1080"/> 00141 <image type="fanart" thumb="http://i1.themoviedb.org/backdrops/9fe/4bc95846017a3c57fe0279fe/avatar-thumb.jpg" url="http://i2.themoviedb.org/backdrops/9fe/4bc95846017a3c57fe0279fe/avatar-original.jpg" width="1920" height="1080"/> 00142 </images> 00143 </item> 00144 </metadata> 00145 00146 Request a list of People matching a name: 00147 > ./tmdb.py -P "Cruise" 00148 500:Tom Cruise 00149 77716:Cruise Moylan 00150 00151 Request a Person's information using their TMDB id number: 00152 > ./tmdb.py -I 2638 00153 Name:Cary Grant 00154 AlsoKnownAs:Alexander Archibald Leach|Archibald Alec Leach 00155 Birthday:1904-01-18 00156 Birthplace:Bristol, England 00157 Filmography:North by Northwest|Character:Roger O. Thornhill|Id:213|Job:Actor|URL:http://www.themoviedb.org/movie/213 00158 Filmography:Arsenic and Old Lace|Character:Mortimer Brewster|Id:212|Job:Actor|URL:http://www.themoviedb.org/movie/212 00159 ... 00160 Filmography:The Grass Is Greener|Character:Victor Rhyall, Earl|Id:25767|Job:Actor|URL:http://www.themoviedb.org/movie/25767 00161 Id:2638 00162 Profile:http://images.themoviedb.org/profiles/11078/CG_profile.jpg,http://images.themoviedb.org/profiles/11075/CG_profile.jpg,http://images.themoviedb.org/profiles/10994/CG_profile.jpg,http://images.themoviedb.org/profiles/10991/CG_profile.jpg,http://images.themoviedb.org/profiles/10988/CG_profile.jpg,http://images.themoviedb.org/profiles/10985/CG_profile.jpg,http://images.themoviedb.org/profiles/4414/Cary_Grant_profile.jpg 00163 Original:http://images.themoviedb.org/profiles/11078/CG.jpg,http://images.themoviedb.org/profiles/11075/CG.jpg,http://images.themoviedb.org/profiles/10994/CG.jpg,http://images.themoviedb.org/profiles/10991/CG.jpg,http://images.themoviedb.org/profiles/10988/CG.jpg,http://images.themoviedb.org/profiles/10985/CG.jpg,http://images.themoviedb.org/profiles/4414/Cary_Grant.jpg 00164 Thumb:http://images.themoviedb.org/profiles/11078/CG_thumb.jpg,http://images.themoviedb.org/profiles/11075/CG_thumb.jpg,http://images.themoviedb.org/profiles/10994/CG_thumb.jpg,http://images.themoviedb.org/profiles/10991/CG_thumb.jpg,http://images.themoviedb.org/profiles/10988/CG_thumb.jpg,http://images.themoviedb.org/profiles/10985/CG_thumb.jpg,http://images.themoviedb.org/profiles/4414/Cary_Grant_thumb.jpg 00165 KnownMovies:25 00166 Popularity:2 00167 URL:http://www.themoviedb.org/person/2638 00168 00169 Request Movie details using a Hash value: 00170 > ./tmdb.py -H "00277ff46533b155" 00171 <?xml version='1.0' encoding='UTF-8'?> 00172 <metadata> 00173 <item> 00174 <title>Underworld</title> 00175 <language>en</language> 00176 <description>Selene, a beautiful vampire warrior, is entrenched in a war between the vampire and Lycan races. Although she is aligned with the vampires, she falls in love with Michael, a recently turned Lycan whose blood may lead to the end of the war, raging for centuries.</description> 00177 <categories> 00178 <category type="genre" name="Action"/> 00179 <category type="genre" name="Fantasy"/> 00180 <category type="genre" name="Horror"/> 00181 <category type="genre" name="Science Fiction"/> 00182 </categories> 00183 ... 00184 <image type="fanart" thumb="http://i1.themoviedb.org/backdrops/db0/4bc90605017a3c57fe001db0/underworld-thumb.jpg" url="http://i1.themoviedb.org/backdrops/db0/4bc90605017a3c57fe001db0/underworld-original.jpg" width="1920" height="1080"/> 00185 </images> 00186 </item> 00187 </metadata> 00188 ''' 00189 00190 import sys, os 00191 from optparse import OptionParser 00192 import re 00193 from string import capitalize 00194 00195 00196 class OutStreamEncoder(object): 00197 """Wraps a stream with an encoder 00198 """ 00199 def __init__(self, outstream, encoding=None): 00200 self.out = outstream 00201 if not encoding: 00202 self.encoding = sys.getfilesystemencoding() 00203 else: 00204 self.encoding = encoding 00205 00206 def write(self, obj): 00207 """Wraps the output stream, encoding Unicode strings with the specified encoding""" 00208 if isinstance(obj, unicode): 00209 self.out.write(obj.encode(self.encoding)) 00210 else: 00211 self.out.write(obj) 00212 00213 def __getattr__(self, attr): 00214 """Delegate everything but write to the stream""" 00215 return getattr(self.out, attr) 00216 # Sub class sys.stdout and sys.stderr as a utf8 stream. Deals with print and stdout unicode issues 00217 sys.stdout = OutStreamEncoder(sys.stdout) 00218 sys.stderr = OutStreamEncoder(sys.stderr) 00219 00220 # Verify that the tmdb_api modules are installed and accessable 00221 00222 00223 try: 00224 import MythTV.tmdb.tmdb_api as tmdb_api 00225 from MythTV.tmdb.tmdb_exceptions import (TmdBaseError, TmdHttpError, TmdXmlError, TmdbUiAbort, TmdbMovieOrPersonNotFound,) 00226 except Exception, e: 00227 sys.stderr.write(''' 00228 The subdirectory "tmdb" containing the modules tmdb_api.py (v0.1.3 or greater), tmdb_ui.py, 00229 tmdb_exceptions.py must have been installed with the MythTV python bindings. 00230 Error:(%s) 00231 ''' % e) 00232 sys.exit(1) 00233 00234 if tmdb_api.__version__ < '0.1.3': 00235 sys.stderr.write("\n! Error: Your current installed tmdb_api.py version is (%s)\nYou must at least have version (0.1.3) or higher.\n" % tmdb_api.__version__) 00236 sys.exit(1) 00237 00238 00239 try: 00240 from StringIO import StringIO 00241 from lxml import etree as etree 00242 except Exception, e: 00243 sys.stderr.write(u'\n! Error - Importing the "lxml" and "StringIO" python libraries failed on error(%s)\n' % e) 00244 sys.exit(1) 00245 00246 # Check that the lxml library is current enough 00247 # From the lxml documents it states: (http://codespeak.net/lxml/installation.html) 00248 # "If you want to use XPath, do not use libxml2 2.6.27. We recommend libxml2 2.7.2 or later" 00249 # Testing was performed with the Ubuntu 9.10 "python-lxml" version "2.1.5-1ubuntu2" repository package 00250 version = '' 00251 for digit in etree.LIBXML_VERSION: 00252 version+=str(digit)+'.' 00253 version = version[:-1] 00254 if version < '2.7.2': 00255 sys.stderr.write(u''' 00256 ! Error - The installed version of the "lxml" python library "libxml" version is too old. 00257 At least "libxml" version 2.7.2 must be installed. Your version is (%s). 00258 ''' % version) 00259 sys.exit(1) 00260 00261 00262 class moviedbQueries(): 00263 '''Methods that query themoviedb.org for metadata and outputs the results to stdout any errors are output 00264 to stderr. 00265 ''' 00266 def __init__(self, 00267 apikey, 00268 mythtv = False, 00269 interactive = False, 00270 select_first = False, 00271 debug = False, 00272 custom_ui = None, 00273 language = None, 00274 search_all_languages = False, ###CHANGE - Needs to be added 00275 ): 00276 """apikey (str/unicode): 00277 Specify the themoviedb.org API key. Applications need their own key. 00278 See http://api.themoviedb.org/2.1/ to get your own API key 00279 00280 mythtv (True/False): 00281 When True, the movie metadata is being returned has the key and values massaged to match MythTV 00282 When False, the movie metadata is being returned matches what TMDB returned 00283 00284 interactive (True/False): 00285 When True, uses built-in console UI is used to select the correct show. 00286 When False, the first search result is used. 00287 00288 select_first (True/False): 00289 Automatically selects the first series search result (rather 00290 than showing the user a list of more than one series). 00291 Is overridden by interactive = False, or specifying a custom_ui 00292 00293 debug (True/False): 00294 shows verbose debugging information 00295 00296 custom_ui (tvdb_ui.BaseUI subclass): 00297 A callable subclass of tvdb_ui.BaseUI (overrides interactive option) 00298 00299 language (2 character language abbreviation): 00300 The language of the returned data. Is also the language search 00301 uses. Default is "en" (English). For full list, run.. 00302 00303 >>> MovieDb().config['valid_languages'] #doctest: +ELLIPSIS 00304 ['da', 'fi', 'nl', ...] 00305 00306 search_all_languages (True/False): 00307 By default, TMDB will only search in the language specified using 00308 the language option. When this is True, it will search for the 00309 show in any language 00310 00311 """ 00312 self.config = {} 00313 00314 self.config['apikey'] = apikey 00315 self.config['moviedb'] = tmdb_api.MovieDb(apikey, mythtv = mythtv, 00316 interactive = interactive, 00317 select_first = select_first, 00318 debug = debug, 00319 custom_ui = custom_ui, 00320 language = language, 00321 search_all_languages = search_all_languages,) 00322 self.mythtvgrabber = [u'Title', u'Subtitle', u'Year', u'ReleaseDate', u'InetRef', u'URL', u'Director', u'Plot', u'UserRating', u'MovieRating', u'Runtime', u'Season', u'Episode', u'Coverart', u'Fanart', u'Banner', u'Screenshot', u'Cast', u'Genres', u'Countries', u'ScreenPlay', u'Studios', u'Producer', u'ProductionDesign', u'DirectorOfPhotography', u'OriginalMusicComposer', u'Story', u'CostumeDesign', u'Editor', u'Type', u'Casting', u'AssociateProducer', u'Popularity', u'Budget', u'Imdb', u'ArtDirection', u'MovieRating'] 00323 self.error_messages = {'TmdHttpError': u"! Error: A connection error to themoviedb.org was raised (%s)\n", 'TmdXmlError': u"! Error: Invalid XML was received from themoviedb.org (%s)\n", 'TmdBaseError': u"! Error: A user interface error was raised (%s)\n", 'TmdbUiAbort': u"! Error: A user interface input error was raised (%s)\n", } 00324 # end __init__() 00325 00326 def movieSearch(self, title): 00327 '''Search for movies that match the title and output their "tmdb#:Title" to stdout 00328 ''' 00329 try: 00330 data = self.config['moviedb'].searchTitle(title) 00331 except TmdbMovieOrPersonNotFound, msg: 00332 #sys.stderr.write(u"%s\n" % msg) 00333 return 00334 except TmdHttpError, msg: 00335 sys.stderr.write(self.error_messages['TmdHttpError'] % msg) 00336 sys.exit(1) 00337 except TmdXmlError, msg: 00338 sys.stderr.write(self.error_messages['TmdXmlError'] % msg) 00339 sys.exit(1) 00340 except TmdBaseError, msg: 00341 sys.stderr.write(self.error_messages['TmdBaseError'] % msg) 00342 sys.exit(1) 00343 except TmdbUiAbort, msg: 00344 sys.stderr.write(self.error_messages['TmdbUiAbort'] % msg) 00345 sys.exit(1) 00346 except Exception, e: 00347 sys.stderr.write(u"! Error: Unknown error during a Title search (%s)\nError(%s)\n" % (title, e)) 00348 sys.exit(1) 00349 00350 if data != None: 00351 for match in data: 00352 if not match.has_key('released'): 00353 name = match['name'] 00354 elif len(match['released']) > 3: 00355 name = u"%s (%s)" % (match['name'], match['released'][:4]) 00356 else: 00357 name = match['name'] 00358 sys.stdout.write( u'%s:%s\n' % (match[u'id'], name)) 00359 # end movieSearch() 00360 00361 def peopleSearch(self, persons_name): 00362 '''Search for People that match the name and output their "tmdb#:Name" to stdout 00363 ''' 00364 try: 00365 for match in self.config['moviedb'].searchPeople(persons_name): 00366 sys.stdout.write( u'%s:%s\n' % (match[u'id'], match['name'])) 00367 except TmdbMovieOrPersonNotFound, msg: 00368 #sys.stderr.write(u"%s\n" % msg) 00369 return 00370 except TmdHttpError, msg: 00371 sys.stderr.write(self.error_messages['TmdHttpError'] % msg) 00372 sys.exit(1) 00373 except TmdXmlError, msg: 00374 sys.stderr.write(self.error_messages['TmdXmlError'] % msg) 00375 sys.exit(1) 00376 except TmdBaseError, msg: 00377 sys.stderr.write(self.error_messages['TmdBaseError'] % msg) 00378 sys.exit(1) 00379 except TmdbUiAbort, msg: 00380 sys.stderr.write(self.error_messages['TmdbUiAbort'] % msg) 00381 sys.exit(1) 00382 except Exception, e: 00383 sys.stderr.write(u"! Error: Unknown error during a People search for (%s)\nError(%s)\n" % (persons_name, e)) 00384 sys.exit(1) 00385 # end moviePeople() 00386 00387 def camelcase(self, value): 00388 '''Make a string CamelCase 00389 ''' 00390 if not value.strip(u'ABCEDFGHIJKLMNOPQRSTUVWXYZ'): 00391 return value 00392 if value == u'url': 00393 return u'URL' 00394 return u"".join([capitalize(w) for w in re.split(re.compile(u"[\W_]*"), value)]) 00395 # end camelcase() 00396 00397 def displayMovieData(self, data): 00398 '''Display movie data to stdout 00399 ''' 00400 if data == None: 00401 return 00402 data_keys = data.keys() 00403 data_keys_org = data.keys() 00404 for index in range(len(data_keys)): 00405 data_keys[index] = data_keys[index].replace(u' ',u'').lower() 00406 00407 for key in self.mythtvgrabber: 00408 if key.lower() in data_keys: 00409 sys.stdout.write(u"%s:%s\n" % (key, data[data_keys_org[data_keys.index(key.lower())]])) 00410 00411 mythtvgrabber = [] 00412 for item in self.mythtvgrabber: 00413 mythtvgrabber.append(item.lower()) 00414 for key in data_keys: 00415 if not key in mythtvgrabber: 00416 sys.stdout.write(u"%s:%s\n" % (self.camelcase(data_keys_org[data_keys.index(key)]), data[data_keys_org[data_keys.index(key)]])) 00417 # end displayMovieData(() 00418 00419 00420 def movieData(self, tmdb_id): 00421 '''Get Movie data by IMDB or TMDB number and display "key:value" pairs to stdout 00422 ''' 00423 try: 00424 if len(tmdb_id) == 7: 00425 self.displayMovieData(self.config['moviedb'].searchIMDB(tmdb_id)) 00426 else: 00427 self.displayMovieData(self.config['moviedb'].searchTMDB(tmdb_id)) 00428 except TmdbMovieOrPersonNotFound, msg: 00429 #sys.stderr.write(u"%s\n" % msg) 00430 return 00431 except TmdHttpError, msg: 00432 sys.stderr.write(self.error_messages['TmdHttpError'] % msg) 00433 sys.exit(1) 00434 except TmdXmlError, msg: 00435 sys.stderr.write(self.error_messages['TmdXmlError'] % msg) 00436 sys.exit(1) 00437 except TmdBaseError, msg: 00438 sys.stderr.write(self.error_messages['TmdBaseError'] % msg) 00439 sys.exit(1) 00440 except TmdbUiAbort, msg: 00441 sys.stderr.write(self.error_messages['TmdbUiAbort'] % msg) 00442 sys.exit(1) 00443 except Exception, e: 00444 sys.stderr.write(u"! Error: Unknown error during a Movie (%s) information display\nError(%s)\n" % (tmdb_id, e)) 00445 sys.exit(1) 00446 # end movieData() 00447 00448 def peopleData(self, person_id): 00449 '''Get People data by TMDB people id number and display "key:value" pairs to stdout 00450 ''' 00451 try: 00452 data = self.config['moviedb'].personInfo(person_id) 00453 except TmdbMovieOrPersonNotFound, msg: 00454 #sys.stderr.write(u"%s\n" % msg) 00455 return 00456 except TmdHttpError, msg: 00457 sys.stderr.write(self.error_messages['TmdHttpError'] % msg) 00458 sys.exit(1) 00459 except TmdXmlError, msg: 00460 sys.stderr.write(self.error_messages['TmdXmlError'] % msg) 00461 sys.exit(1) 00462 except TmdBaseError, msg: 00463 sys.stderr.write(self.error_messages['TmdBaseError'] % msg) 00464 sys.exit(1) 00465 except TmdbUiAbort, msg: 00466 sys.stderr.write(self.error_messages['TmdbUiAbort'] % msg) 00467 sys.exit(1) 00468 except Exception, e: 00469 sys.stderr.write(u"! Error: Unknown error during a Person (%s) information display\n" % (person_id, e)) 00470 sys.exit(1) 00471 00472 if data == None: 00473 return 00474 sys.stdout.write(u'%s:%s\n' % (u'Name', data[u'name'])) 00475 keys = sorted(data.keys()) 00476 images = {} 00477 for key in keys: 00478 if key == u'name': 00479 continue 00480 if key in ['also_known_as', 'filmography', 'images' ]: 00481 if key == 'images': 00482 images = {} 00483 for k in data[key].keys(): 00484 images[k] = u'' 00485 if key == 'also_known_as': 00486 alias = u'' 00487 for k in data[key]: 00488 alias+=u'%s|' % k.replace(u'|', u' ') 00489 if alias: 00490 sys.stdout.write(u'%s:%s\n' % (self.camelcase(key), alias[:-1])) 00491 continue 00492 for k in data[key]: 00493 if key == 'filmography': 00494 kys = sorted(k.keys()) 00495 filmography = u'' 00496 for c in kys: 00497 if c == u'name': 00498 continue 00499 filmography+=u'%s:%s|' % (self.camelcase(c.replace(u'|', u' ')), k[c].replace(u'|', u' ')) 00500 if filmography: 00501 sys.stdout.write(u'%s:%s|%s\n' % (self.camelcase(key), k[u'name'].replace(u'|', u' '), filmography[:-1])) 00502 elif key == 'images': 00503 sys.stdout.write(u'%s:%s\n' % (self.camelcase(k), data[key][k])) 00504 else: 00505 sys.stdout.write(u'%s:%s\n' % (self.camelcase(key), data[key])) 00506 # end peopleData() 00507 00508 def hashData(self, hash_value): 00509 '''Get Movie data by Hash value and display "key:value" pairs to stdout 00510 ''' 00511 try: 00512 self.displayMovieData(self.config['moviedb'].searchHash(hash_value)) 00513 except TmdbMovieOrPersonNotFound, msg: 00514 #sys.stderr.write(u"%s\n" % msg) 00515 return 00516 except TmdHttpError, msg: 00517 sys.stderr.write(self.error_messages['TmdHttpError'] % msg) 00518 sys.exit(1) 00519 except TmdXmlError, msg: 00520 sys.stderr.write(self.error_messages['TmdXmlError'] % msg) 00521 sys.exit(1) 00522 except TmdBaseError, msg: 00523 sys.stderr.write(self.error_messages['TmdBaseError'] % msg) 00524 sys.exit(1) 00525 except TmdbUiAbort, msg: 00526 sys.stderr.write(self.error_messages['TmdbUiAbort'] % msg) 00527 sys.exit(1) 00528 except Exception, e: 00529 sys.stderr.write(u"! Error: Unknown error during a Hash value Movie information display for (%s)\nError(%s)\n" % (hash_value, e)) 00530 sys.exit(1) 00531 # end hashData() 00532 00533 # end Class moviedbQueries() 00534 00535 00536 def main(): 00537 """Gets movie details using an IMDB# and a TMDB# OR get People information using a name 00538 """ 00539 # themoviedb.org api key given by Travis Bell for Mythtv 00540 apikey = "c27cb71cff5bd76e1a7a009380562c62" 00541 00542 parser = OptionParser(usage=u"%prog usage: tmdb -hdruviomMPFBDS [parameters]\n <series name or 'series and season number' or 'series and season number and episode number'>\n\nFor details on using tmdb with Mythvideo see the tmdb wiki page at:\nhttp://www.mythtv.org/wiki/tmdb.py") 00543 00544 parser.add_option( "-d", "--debug", action="store_true", default=False, dest="debug", 00545 help=u"Show debugging info") 00546 parser.add_option( "-r", "--raw", action="store_true",default=False, dest="raw", 00547 help=u"Dump raw data only") 00548 parser.add_option( "-u", "--usage", action="store_true", default=False, dest="usage", 00549 help=u"Display examples for executing the tmdb script") 00550 parser.add_option( "-v", "--version", action="store_true", default=False, dest="version", 00551 help=u"Display version and author") 00552 parser.add_option( "-i", "--interactive", action="store_true", default=False, dest="interactive", 00553 help=u"Interaction mode (allows selection of a specific Movie or Person)") 00554 parser.add_option( "-l", "--language", metavar="LANGUAGE", default=u'en', dest="language", 00555 help=u"Select data that matches the specified language fall back to english if nothing found (e.g. 'es' EspaƱol, 'de' Deutsch ... etc)") 00556 parser.add_option( "-M", "--movielist", action="store_true", default=False, dest="movielist", 00557 help=u"Get matching Movie list") 00558 parser.add_option( "-D", "--moviedata", action="store_true", default=False, dest="moviedata", 00559 help=u"Get Movie metadata including graphic URLs") 00560 parser.add_option( "-H", "--moviehash", action="store_true", default=False, dest="moviehash", 00561 help=u"Get Movie metadata including graphic URLs using a Hash value.\nSee: http://api.themoviedb.org/2.1/methods/Hash.getInfo") 00562 parser.add_option( "-P", "--peoplelist", action="store_true", default=False, dest="peoplelist", 00563 help=u"Get matching People list") 00564 parser.add_option( "-I", "--peopleinfo", action="store_true", default=False, dest="peopleinfo", 00565 help=u"Get A Person's metadata including graphic URLs") 00566 parser.add_option( "-t", action="store_true", default=False, dest="test", 00567 help=u"Test for the availability of runtime dependencies") 00568 00569 opts, args = parser.parse_args() 00570 00571 # Test mode, if we've made it here, everything is ok 00572 if opts.test: 00573 print "Everything appears to be in order" 00574 sys.exit(0) 00575 00576 # Make all command line arguments unicode utf8 00577 for index in range(len(args)): 00578 args[index] = unicode(args[index], 'utf8') 00579 00580 if opts.debug: 00581 sys.stdout.write("\nopts: %s\n" % opts) 00582 sys.stdout.write("\nargs: %s\n\n" % args) 00583 00584 # Process version command line requests 00585 if opts.version: 00586 version = etree.XML(u'<grabber></grabber>') 00587 etree.SubElement(version, "name").text = __title__ 00588 etree.SubElement(version, "author").text = __author__ 00589 etree.SubElement(version, "thumbnail").text = 'tmdb.png' 00590 etree.SubElement(version, "command").text = 'tmdb.py' 00591 etree.SubElement(version, "type").text = 'movie' 00592 etree.SubElement(version, "description").text = 'Search and metadata downloads for themoviedb.org' 00593 etree.SubElement(version, "version").text = __version__ 00594 sys.stdout.write(etree.tostring(version, encoding='UTF-8', pretty_print=True)) 00595 sys.exit(0) 00596 00597 # Process usage command line requests 00598 if opts.usage: 00599 sys.stdout.write(__usage_examples__) 00600 sys.exit(0) 00601 00602 if not len(args) == 1: 00603 sys.stderr.write("! Error: There must be one value for any option. Your options are (%s)\n" % (args)) 00604 sys.exit(1) 00605 00606 if args[0] == u'': 00607 sys.stderr.write("! Error: There must be a non-empty argument, yours is empty.\n") 00608 sys.exit(1) 00609 00610 Queries = moviedbQueries(apikey, 00611 mythtv = True, 00612 interactive = opts.interactive, 00613 select_first = False, 00614 debug = opts.debug, 00615 custom_ui = None, 00616 language = opts.language, 00617 search_all_languages = False,) 00618 00619 # Display in XML format 00620 # See: http://www.mythtv.org/wiki/MythTV_Universal_Metadata_Format 00621 Queries.config['moviedb'].xml = True 00622 00623 # Process requested option 00624 if opts.movielist: # Movie Search -M 00625 Queries.movieSearch(args[0]) 00626 elif opts.moviedata: # Movie metadata -D 00627 Queries.movieData(args[0]) 00628 elif opts.peoplelist: # People Search -P 00629 Queries.peopleSearch(args[0]) 00630 elif opts.peopleinfo: # Person metadata -I 00631 Queries.peopleData(args[0]) 00632 elif opts.moviehash: # Movie metadata using a hash value -H 00633 Queries.hashData(args[0]) 00634 00635 sys.exit(0) 00636 # end main() 00637 00638 if __name__ == '__main__': 00639 main()
1.7.6.1