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 https://www.giantbomb.com website. It
10 # follows the MythTV Univeral standards set for grabbers
11 # https://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: https://www.giantbomb.com/api/documentation/
16 # Users of this script are encouraged to populate www.giantbomb.com with Game
17 # information and 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 # (https://creativecommons.org/licenses/GPL/2.0/)
30 #-------------------------------------
31 __title__ ="GiantBomb Query";
32 __author__="R.D. Vaughan"
33 __version__="0.20"
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 # 0.2.0 R. Ernst: Added python3 compatibility
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 
131 
132 IS_PY2 = sys.version_info[0] == 2
133 
134 try:
135  if IS_PY2:
136  from StringIO import StringIO
137  else:
138  from io import StringIO
139  from lxml import etree
140 except Exception as e:
141  sys.stderr.write(u'\n! Error - Importing the "lxml" and "StringIO" python libraries failed on error(%s)\n' % e)
142  sys.exit(1)
143 
144 
145 if IS_PY2:
146  stdio_type = file
147 else:
148  import io
149  stdio_type = io.TextIOWrapper
150  unicode = str
151  unichr = chr
152 
153 
154 class OutStreamEncoder(object):
155  """Wraps a stream with an encoder
156  """
157  def __init__(self, outstream, encoding=None):
158  self.out = outstream
159  if not encoding:
160  self.encoding = sys.getfilesystemencoding()
161  else:
162  self.encoding = encoding
163 
164  def write(self, obj):
165  """Wraps the output stream, encoding Unicode strings with the specified encoding"""
166  if isinstance(obj, unicode):
167  obj = obj.encode(self.encoding)
168  if IS_PY2:
169  self.out.write(obj)
170  else:
171  self.out.buffer.write(obj)
172 
173  def __getattr__(self, attr):
174  """Delegate everything but write to the stream"""
175  return getattr(self.out, attr)
176 if isinstance(sys.stdout, stdio_type):
177  sys.stdout = OutStreamEncoder(sys.stdout, 'utf8')
178  sys.stderr = OutStreamEncoder(sys.stderr, 'utf8')
179 
180 
181 # Check that the lxml library is current enough
182 # From the lxml documents it states: (https://lxml.de/installation.html)
183 # "If you want to use XPath, do not use libxml2 2.6.27. We recommend libxml2 2.7.2 or later"
184 # Testing was performed with the Ubuntu 9.10 "python-lxml" version "2.1.5-1ubuntu2" repository package
185 version = ''
186 for digit in etree.LIBXML_VERSION:
187  version+=str(digit)+'.'
188 version = version[:-1]
189 if version < '2.7.2':
190  sys.stderr.write(u'''
191 ! Error - The installed version of the "lxml" python library "libxml" version is too old.
192  At least "libxml" version 2.7.2 must be installed. Your version is (%s).
193 ''' % version)
194  sys.exit(1)
195 
196 
197 # Verify that the giantbomb_api modules are installed and accessable
198 #import giantbomb.giantbomb_api as giantbomb_api # Only used when debugging. Normally commented out.
199 
200 try:
201  import giantbomb.giantbomb_api as giantbomb_api
202 except Exception as e:
203  sys.stderr.write('''
204 The subdirectory "giantbomb" containing the modules giantbomb_api.py (v0.1.0 or greater) and
205 giantbomb_exceptions.py must have been installed with the MythTV gaming plugin.
206 Error:(%s)
207 ''' % e)
208  sys.exit(1)
209 
210 if giantbomb_api.__version__ < '0.1.0':
211  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__)
212  sys.exit(1)
213 
214 
215 def main():
216  """Gets game details using a GiantBomb# OR using a game name
217  """
218  # api.giantbomb.com api key provided for Mythtv
219  apikey = "b5883a902a8ed88b15ce21d07787c94fd6ad9f33"
220 
221  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:\nhttps://www.mythtv.org/wiki/MythTV_Universal_Metadata_Format")
222 
223  parser.add_option( "-d", "--debug", action="store_true", default=False, dest="debug",
224  help=u"Show debugging info")
225  parser.add_option( "-u", "--usage", action="store_true", default=False, dest="usage",
226  help=u"Display examples for executing the giantbomb script")
227  parser.add_option( "-v", "--version", action="store_true", default=False, dest="version",
228  help=u"Display version and author")
229  parser.add_option( "-l", "--language", metavar="LANGUAGE", default=u'en', dest="language",
230  help=u"Select data that matches the specified language. At this time giantbomb.com only supports 'en' English.")
231  parser.add_option( "-a", "--area", metavar="AREA", default=u"gb", dest="area",
232  help=u"Select data that matches the specified country. This option is currently not used.")
233  parser.add_option( "-M", "--gamelist", action="store_true", default=False, dest="gamelist",
234  help=u"Get matching Movie list")
235  parser.add_option( "-D", "--gamedata", action="store_true", default=False, dest="gamedata",
236  help=u"Get Movie metadata including graphic URLs")
237 
238  opts, args = parser.parse_args()
239 
240  # Make all command line arguments unicode utf8
241  for index in range(len(args)):
242  try: # python2
243  args[index] = unicode(args[index], 'utf8')
244  except: # python3
245  args[index] = str(args[index])
246  if opts.debug:
247  sys.stdout.write("\nopts: %s\n" % opts)
248  sys.stdout.write("\nargs: %s\n\n" % args)
249 
250  # Process version command line requests
251  if opts.version:
252  version = etree.XML(u'<grabber></grabber>')
253  etree.SubElement(version, "name").text = __title__
254  etree.SubElement(version, "author").text = __author__
255  etree.SubElement(version, "thumbnail").text = 'giantbomb.png'
256  etree.SubElement(version, "command").text = 'giantbomb.py'
257  etree.SubElement(version, "type").text = 'games'
258  etree.SubElement(version, "description").text = 'Search and Metadata downloads for Games from the giantbomb.com API'
259  etree.SubElement(version, "version").text = __version__
260  sys.stdout.write(etree.tostring(version, encoding='UTF-8', pretty_print=True))
261  sys.exit(0)
262 
263  # Process usage command line requests
264  if opts.usage:
265  sys.stdout.write(__usage_examples__)
266  sys.exit(0)
267 
268  if not len(args) == 1:
269  sys.stderr.write("! Error: There must be one value for any option. Your options are (%s)\n" % (args))
270  sys.exit(1)
271 
272  if args[0] == u'':
273  sys.stderr.write("! Error: There must be a non-empty argument, yours is empty.\n")
274  sys.exit(1)
275 
276  Queries = giantbomb_api.gamedbQueries(apikey,
277  debug = opts.debug,
278  )
279 
280  # Process requested option
281  if opts.gamelist: # Game Search -M
282  Queries.gameSearch(args[0])
283  elif opts.gamedata: # Game metadata -D
284  Queries.gameData(args[0])
285 
286  sys.exit(0)
287 # end main()
288 
289 if __name__ == '__main__':
290  main()
giantbomb.OutStreamEncoder.write
def write(self, obj)
Definition: giantbomb.py:164
giantbomb.main
def main()
Definition: giantbomb.py:215
giantbomb.OutStreamEncoder
Definition: giantbomb.py:154
giantbomb.OutStreamEncoder.__init__
def __init__(self, outstream, encoding=None)
Definition: giantbomb.py:157
giantbomb.OutStreamEncoder.out
out
Definition: giantbomb.py:158
giantbomb.unicode
unicode
Definition: giantbomb.py:150
giantbomb.giantbomb_api.gamedbQueries
Definition: giantbomb_api.py:90
giantbomb.giantbomb_api
Definition: giantbomb_api.py:1
giantbomb.OutStreamEncoder.encoding
encoding
Definition: giantbomb.py:160
giantbomb.OutStreamEncoder.__getattr__
def __getattr__(self, attr)
Definition: giantbomb.py:173