MythTV  0.26-pre
tmdb.py
Go to the documentation of this file.
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()
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends