MythTV  master
giantbomb.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # -*- coding: UTF-8 -*-
3 # ----------------------
4 # Name: giantbomb.py
5 # Python Script
6 # Author: R.D. Vaughan
7 # Purpose:
8 # This python script is intended to perform Game data lookups
9 # based on information found on the http://www.giantbomb.com/ website. It
10 # follows the MythTV Univeral standards set for grabbers
11 # http://www.mythtv.org/wiki/MythTV_Universal_Metadata_Format
12 # This script uses the python module giantbomb_api.py which should be included
13 # with this script.
14 # The giantbomb_api.py module uses the full access XML api published by
15 # api.giantbomb.com see: http://api.giantbomb.com/documentation/
16 # Users of this script are encouraged to populate www.giantbomb.com with Game
17 # informationand images. The richer the source the more
18 # valuable the script.
19 # Command example:
20 # See help (-u and -h) options
21 #
22 # Design:
23 # 1) Verify the command line options (display help or version and exit)
24 # 2) Verify that www.giantbomb.com has the Game being requested exit if it does not exit
25 # 3) Find the requested information and send to stdout if any found
26 #
27 #
28 # License:Creative Commons GNU GPL v2
29 # (http://creativecommons.org/licenses/GPL/2.0/)
30 #-------------------------------------
31 __title__ ="GiantBomb Query";
32 __author__="R.D. Vaughan"
33 __version__="0.11"
34 # 0.10 Initial development
35 # 0.11 Added the -l option to conform to grabber standards. Currently www.giantbomb.com does not support
36 # multiple languages.
37 
38 
39 __usage_examples__='''
40 Request giantbomb.py verison number:
41 > ./giantbomb.py -v
42 <grabber>
43  <name>GiantBomb Query</name>
44  <author>R.D. Vaughan</author>
45  <thumbnail>giantbomb.png</thumbnail>
46  <command>giantbomb.py</command>
47  <type>games</type>
48  <description>Search and Metadata downloads for Games from the giantbomb.com API</description>
49  <version>v0.11</version>
50 </grabber>
51 
52 Request a list of matching game titles:
53 > ./giantbomb.py -M "Terminator"
54 <?xml version='1.0' encoding='UTF-8'?>
55 <metadata>
56  <item>
57  <language>en</language>
58  <title>Terminator Salvation</title>
59  <inetref>24514</inetref>
60  <description>Based on the “Terminator Salvation” film, the game offers players the chance to assume the role of John Connor, a soldier in the resistance, battling for survival against the far superior forces of Skynet.</description>
61  <releasedate>2009-05-19</releasedate>
62  <homepage>http://www.giantbomb.com/terminator-salvation/61-24514/</homepage>
63  <images>
64  <image type="coverart" url="http://media.giantbomb.com/uploads/1/13154/1110143-gb_super.png" thumb="http://media.giantbomb.com/uploads/1/13154/1110143-gb_thumb.png"/>
65  </images>
66  <lastupdated>Thu, 04 Mar 2010 06:23:22 GMT</lastupdated>
67  </item>
68 ...
69  <item>
70  <language>en</language>
71  <title>Terminator 2</title>
72  <inetref>28832</inetref>
73  <description>Terminator 2</description>
74  <homepage>http://www.giantbomb.com/terminator-2/61-28832/</homepage>
75  <lastupdated>Sat, 03 Oct 2009 00:21:31 GMT</lastupdated>
76  </item>
77 </metadata>
78 
79 Request game details using a GiantBomb#:
80 > ./giantbomb.py -D 24514
81 <?xml version='1.0' encoding='UTF-8'?>
82 <metadata>
83  <item>
84  <language>en</language>
85  <title>Terminator Salvation</title>
86  <description>Based on the “Terminator Salvation” film, the game offers players the chance to assume the role of John Connor, a soldier in the resistance, battling for survival against the far superior forces of Skynet.</description>
87  <categories>
88  <category type="genre" name="Shooter"/>
89  <category type="genre" name="Vehicular Combat"/>
90  <category type="genre" name="Action"/>
91  </categories>
92  <systems>
93  <system>PC</system>
94  <system>PlayStation 3</system>
95  <system>Xbox 360</system>
96  </systems>
97  <studios>
98  <studio name="GRIN"/>
99  <studio name="Evolved Games"/>
100  <studio name="Warner Bros. Interactive Entertainment Inc."/>
101  </studios>
102  <releasedate>2009-05-19</releasedate>
103  <lastupdated>Thu, 04 Mar 2010 06:23:22 GMT</lastupdated>
104  <inetref>24514</inetref>
105  <homepage>http://www.giantbomb.com/terminator-salvation/61-24514/</homepage>
106  <trailer/>
107  <people>
108  <person name="Rose McGowan" job="Actor"/>
109  </people>
110  <images>
111  <image type="coverart" url="http://media.giantbomb.com/uploads/1/13154/1110143-gb_super.png" thumb="http://media.giantbomb.com/uploads/1/13154/1110143-gb_thumb.png"/>
112  <image type="screenshot" url="http://media.giantbomb.com/uploads/0/8484/1115329-terminatorsalvation_2009_08_23_12_36_06_46_super.jpg" thumb="http://media.giantbomb.com/uploads/0/8484/1115329-terminatorsalvation_2009_08_23_12_36_06_46_thumb.jpg"/>
113  <image type="screenshot" url="http://media.giantbomb.com/uploads/0/8484/1115327-terminatorsalvation_2009_08_23_12_35_50_70_super.jpg" thumb="http://media.giantbomb.com/uploads/0/8484/1115327-terminatorsalvation_2009_08_23_12_35_50_70_thumb.jpg"/>
114  <image type="screenshot" url="http://media.giantbomb.com/uploads/0/8484/1115326-terminatorsalvation_2009_08_23_12_35_40_07_super.jpg" thumb="http://media.giantbomb.com/uploads/0/8484/1115326-terminatorsalvation_2009_08_23_12_35_40_07_thumb.jpg"/>
115  <image type="screenshot" url="http://media.giantbomb.com/uploads/0/8484/1115325-terminatorsalvation_2009_08_23_12_35_24_83_super.jpg" thumb="http://media.giantbomb.com/uploads/0/8484/1115325-terminatorsalvation_2009_08_23_12_35_24_83_thumb.jpg"/>
116  <image type="screenshot" url="http://media.giantbomb.com/uploads/0/8484/1115324-terminatorsalvation_2009_08_23_12_34_32_33_super.jpg" thumb="http://media.giantbomb.com/uploads/0/8484/1115324-terminatorsalvation_2009_08_23_12_34_32_33_thumb.jpg"/>
117  <image type="screenshot" url="http://media.giantbomb.com/uploads/0/8484/1115323-terminatorsalvation_2009_08_23_12_33_27_96_super.jpg" thumb="http://media.giantbomb.com/uploads/0/8484/1115323-terminatorsalvation_2009_08_23_12_33_27_96_thumb.jpg"/>
118  <image type="screenshot" url="http://media.giantbomb.com/uploads/0/8484/1115322-terminatorsalvation_2009_08_23_12_33_19_64_super.jpg" thumb="http://media.giantbomb.com/uploads/0/8484/1115322-terminatorsalvation_2009_08_23_12_33_19_64_thumb.jpg"/>
119  <image type="screenshot" url="http://media.giantbomb.com/uploads/0/8484/1115321-terminatorsalvation_2009_08_23_12_33_15_70_super.jpg" thumb="http://media.giantbomb.com/uploads/0/8484/1115321-terminatorsalvation_2009_08_23_12_33_15_70_thumb.jpg"/>
120  <image type="screenshot" url="http://media.giantbomb.com/uploads/0/8484/1115319-terminatorsalvation_2009_08_23_12_32_28_68_super.jpg" thumb="http://media.giantbomb.com/uploads/0/8484/1115319-terminatorsalvation_2009_08_23_12_32_28_68_thumb.jpg"/>
121  <image type="screenshot" url="http://media.giantbomb.com/uploads/0/8484/1115320-terminatorsalvation_2009_08_23_12_32_34_27_super.jpg" thumb="http://media.giantbomb.com/uploads/0/8484/1115320-terminatorsalvation_2009_08_23_12_32_34_27_thumb.jpg"/>
122  </images>
123  </item>
124 </metadata>
125 '''
126 
127 import sys, os
128 from optparse import OptionParser
129 import re
130 from string import capitalize
131 
132 
133 class OutStreamEncoder(object):
134  """Wraps a stream with an encoder
135  """
136  def __init__(self, outstream, encoding=None):
137  self.out = outstream
138  if not encoding:
139  self.encoding = sys.getfilesystemencoding()
140  else:
141  self.encoding = encoding
142 
143  def write(self, obj):
144  """Wraps the output stream, encoding Unicode strings with the specified encoding"""
145  if isinstance(obj, unicode):
146  self.out.write(obj.encode(self.encoding))
147  else:
148  self.out.write(obj)
149 
150  def __getattr__(self, attr):
151  """Delegate everything but write to the stream"""
152  return getattr(self.out, attr)
153 # Sub class sys.stdout and sys.stderr as a utf8 stream. Deals with print and stdout unicode issues
154 sys.stdout = OutStreamEncoder(sys.stdout)
155 sys.stderr = OutStreamEncoder(sys.stderr)
156 
157 
158 try:
159  from StringIO import StringIO
160  from lxml import etree
161 except Exception, e:
162  sys.stderr.write(u'\n! Error - Importing the "lxml" and "StringIO" python libraries failed on error(%s)\n' % e)
163  sys.exit(1)
164 
165 # Check that the lxml library is current enough
166 # From the lxml documents it states: (http://codespeak.net/lxml/installation.html)
167 # "If you want to use XPath, do not use libxml2 2.6.27. We recommend libxml2 2.7.2 or later"
168 # Testing was performed with the Ubuntu 9.10 "python-lxml" version "2.1.5-1ubuntu2" repository package
169 version = ''
170 for digit in etree.LIBXML_VERSION:
171  version+=str(digit)+'.'
172 version = version[:-1]
173 if version < '2.7.2':
174  sys.stderr.write(u'''
175 ! Error - The installed version of the "lxml" python library "libxml" version is too old.
176  At least "libxml" version 2.7.2 must be installed. Your version is (%s).
177 ''' % version)
178  sys.exit(1)
179 
180 
181 # Verify that the giantbomb_api modules are installed and accessable
182 #import giantbomb.giantbomb_api as giantbomb_api # Only used when debugging. Normally commented out.
183 
184 try:
185  import giantbomb.giantbomb_api as giantbomb_api
186 except Exception, e:
187  sys.stderr.write('''
188 The subdirectory "giantbomb" containing the modules giantbomb_api.py (v0.1.0 or greater) and
189 giantbomb_exceptions.py must have been installed with the MythTV gaming plugin.
190 Error:(%s)
191 ''' % e)
192  sys.exit(1)
193 
194 if giantbomb_api.__version__ < '0.1.0':
195  sys.stderr.write("\n! Error: Your current installed giantbomb_api.py version is (%s)\nYou must at least have version (0.1.0) or higher.\n" % giantbomb_api.__version__)
196  sys.exit(1)
197 
198 
199 def main():
200  """Gets game details using a GiantBomb# OR using a game name
201  """
202  # api.giantbomb.com api key provided for Mythtv
203  apikey = "b5883a902a8ed88b15ce21d07787c94fd6ad9f33"
204 
205  parser = OptionParser(usage=u"%prog usage: giantbomb -hdluvMD [parameters]\n <game name or gameid number>\n\nFor details on using giantbomb from the command execute './giantbomb.py -u'. For details on the meaning of the XML element tags see the wiki page at:\nhttp://www.mythtv.org/wiki/MythTV_Universal_Metadata_Format")
206 
207  parser.add_option( "-d", "--debug", action="store_true", default=False, dest="debug",
208  help=u"Show debugging info")
209  parser.add_option( "-u", "--usage", action="store_true", default=False, dest="usage",
210  help=u"Display examples for executing the giantbomb script")
211  parser.add_option( "-v", "--version", action="store_true", default=False, dest="version",
212  help=u"Display version and author")
213  parser.add_option( "-l", "--language", metavar="LANGUAGE", default=u'en', dest="language",
214  help=u"Select data that matches the specified language. At this time giantbomb.com only supports 'en' English.")
215  parser.add_option( "-a", "--area", metavar="AREA", default=u"gb", dest="area",
216  help=u"Select data that matches the specified country. This option is currently not used.")
217  parser.add_option( "-M", "--gamelist", action="store_true", default=False, dest="gamelist",
218  help=u"Get matching Movie list")
219  parser.add_option( "-D", "--gamedata", action="store_true", default=False, dest="gamedata",
220  help=u"Get Movie metadata including graphic URLs")
221 
222  opts, args = parser.parse_args()
223 
224  # Make all command line arguments unicode utf8
225  for index in range(len(args)):
226  args[index] = unicode(args[index], 'utf8')
227 
228  if opts.debug:
229  sys.stdout.write("\nopts: %s\n" % opts)
230  sys.stdout.write("\nargs: %s\n\n" % args)
231 
232  # Process version command line requests
233  if opts.version:
234  version = etree.XML(u'<grabber></grabber>')
235  etree.SubElement(version, "name").text = __title__
236  etree.SubElement(version, "author").text = __author__
237  etree.SubElement(version, "thumbnail").text = 'giantbomb.png'
238  etree.SubElement(version, "command").text = 'giantbomb.py'
239  etree.SubElement(version, "type").text = 'games'
240  etree.SubElement(version, "description").text = 'Search and Metadata downloads for Games from the giantbomb.com API'
241  etree.SubElement(version, "version").text = __version__
242  sys.stdout.write(etree.tostring(version, encoding='UTF-8', pretty_print=True))
243  sys.exit(0)
244 
245  # Process usage command line requests
246  if opts.usage:
247  sys.stdout.write(__usage_examples__)
248  sys.exit(0)
249 
250  if not len(args) == 1:
251  sys.stderr.write("! Error: There must be one value for any option. Your options are (%s)\n" % (args))
252  sys.exit(1)
253 
254  if args[0] == u'':
255  sys.stderr.write("! Error: There must be a non-empty argument, yours is empty.\n")
256  sys.exit(1)
257 
258  Queries = giantbomb_api.gamedbQueries(apikey,
259  debug = opts.debug,
260  )
261 
262  # Process requested option
263  if opts.gamelist: # Game Search -M
264  Queries.gameSearch(args[0])
265  elif opts.gamedata: # Game metadata -D
266  Queries.gameData(args[0])
267 
268  sys.exit(0)
269 # end main()
270 
271 if __name__ == '__main__':
272  main()
def write(self, obj)
Definition: giantbomb.py:143
def __getattr__(self, attr)
Definition: giantbomb.py:150
def main()
Definition: giantbomb.py:199
def __init__(self, outstream, encoding=None)
Definition: giantbomb.py:136