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__='''
40Request 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
52Request 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
79Request 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
127import sys, os
128from optparse import OptionParser
129import re
130
131
132IS_PY2 = sys.version_info[0] == 2
133
134try:
135 if IS_PY2:
136 from StringIO import StringIO
137 else:
138 from io import StringIO
139 from lxml import etree
140except 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
145if IS_PY2:
146 stdio_type = file
147else:
148 import io
149 stdio_type = io.TextIOWrapper
150 unicode = str
151 unichr = chr
152
153
154class 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)
176if 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
185version = ''
186for digit in etree.LIBXML_VERSION:
187 version+=str(digit)+'.'
188version = version[:-1]
189if 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
200try:
201 import giantbomb.giantbomb_api as giantbomb_api
202except Exception as e:
203 sys.stderr.write('''
204The subdirectory "giantbomb" containing the modules giantbomb_api.py (v0.1.0 or greater) and
205giantbomb_exceptions.py must have been installed with the MythTV gaming plugin.
206Error:(%s)
207''' % e)
208 sys.exit(1)
209
210if 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
215def 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
289if __name__ == '__main__':
290 main()
def __init__(self, outstream, encoding=None)
Definition: giantbomb.py:157
def __getattr__(self, attr)
Definition: giantbomb.py:173
def write(self, obj)
Definition: giantbomb.py:164
def main()
Definition: giantbomb.py:215