game-finder 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rubocop.yml +17 -0
- data/.travis.yml +3 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +73 -0
- data/LICENCE +21 -0
- data/README.md +109 -0
- data/Rakefile +188 -0
- data/bin/game-finder +7 -0
- data/files/default_config.yaml +2 -0
- data/fixtures/fastlane.json +25 -0
- data/fixtures/gears_of_war_game.json +99 -0
- data/fixtures/gears_of_war_search.json +43 -0
- data/game-finder.gemspec +34 -0
- data/lib/game-finder.rb +8 -0
- data/lib/game-finder/api.rb +34 -0
- data/lib/game-finder/cli.rb +16 -0
- data/lib/game-finder/config.rb +26 -0
- data/lib/game-finder/format.rb +18 -0
- data/lib/game-finder/info.rb +34 -0
- data/lib/game-finder/out.rb +9 -0
- data/lib/game-finder/search.rb +30 -0
- data/lib/game-finder/util.rb +20 -0
- data/lib/game-finder/version.rb +3 -0
- metadata +196 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 76477b7fbe61cad0fefd586af30af8ded0ad6b47
|
4
|
+
data.tar.gz: 22c38cc6e1a76b2cabd6379f58dbc8664a8119cd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c2d656752ab955a039c282f94e6f2460a268f7de18ee5395180b6b5a8380493948772f8e5300b36007a9665f34f151e54e4810f4abf39725bc06f0b24c165295
|
7
|
+
data.tar.gz: 2d41c2eaa4c5770e5c0499ceb3be409d94bd0fd7b54680bda9b8d92ecbe5585c7b79f6ea3e1f2882f8a545608672740ef827af467ca1727fab4527ed5a0df0bd
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'colorize', '0.8.1'
|
4
|
+
gem 'english', '0.6.3'
|
5
|
+
gem 'httparty', '0.14.0'
|
6
|
+
gem 'thor', '0.19.4'
|
7
|
+
|
8
|
+
group :development do
|
9
|
+
gem 'rake', '11.2.2'
|
10
|
+
gem 'rspec', '3.6.0'
|
11
|
+
gem 'rubocop', '0.48.1'
|
12
|
+
gem 'simplecov', '0.12.0'
|
13
|
+
gem 'webmock', '1.22.6'
|
14
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
addressable (2.4.0)
|
5
|
+
ast (2.3.0)
|
6
|
+
colorize (0.8.1)
|
7
|
+
crack (0.4.3)
|
8
|
+
safe_yaml (~> 1.0.0)
|
9
|
+
diff-lcs (1.3)
|
10
|
+
docile (1.1.5)
|
11
|
+
english (0.6.3)
|
12
|
+
language
|
13
|
+
hashdiff (0.3.0)
|
14
|
+
httparty (0.14.0)
|
15
|
+
multi_xml (>= 0.5.2)
|
16
|
+
json (2.0.2)
|
17
|
+
language (0.6.0)
|
18
|
+
multi_xml (0.6.0)
|
19
|
+
parser (2.4.0.0)
|
20
|
+
ast (~> 2.2)
|
21
|
+
powerpack (0.1.1)
|
22
|
+
rainbow (2.2.2)
|
23
|
+
rake
|
24
|
+
rake (11.2.2)
|
25
|
+
rspec (3.6.0)
|
26
|
+
rspec-core (~> 3.6.0)
|
27
|
+
rspec-expectations (~> 3.6.0)
|
28
|
+
rspec-mocks (~> 3.6.0)
|
29
|
+
rspec-core (3.6.0)
|
30
|
+
rspec-support (~> 3.6.0)
|
31
|
+
rspec-expectations (3.6.0)
|
32
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
33
|
+
rspec-support (~> 3.6.0)
|
34
|
+
rspec-mocks (3.6.0)
|
35
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
36
|
+
rspec-support (~> 3.6.0)
|
37
|
+
rspec-support (3.6.0)
|
38
|
+
rubocop (0.48.1)
|
39
|
+
parser (>= 2.3.3.1, < 3.0)
|
40
|
+
powerpack (~> 0.1)
|
41
|
+
rainbow (>= 1.99.1, < 3.0)
|
42
|
+
ruby-progressbar (~> 1.7)
|
43
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
44
|
+
ruby-progressbar (1.8.1)
|
45
|
+
safe_yaml (1.0.4)
|
46
|
+
simplecov (0.12.0)
|
47
|
+
docile (~> 1.1.0)
|
48
|
+
json (>= 1.8, < 3)
|
49
|
+
simplecov-html (~> 0.10.0)
|
50
|
+
simplecov-html (0.10.0)
|
51
|
+
thor (0.19.4)
|
52
|
+
unicode-display_width (1.2.1)
|
53
|
+
webmock (1.22.6)
|
54
|
+
addressable (>= 2.3.6)
|
55
|
+
crack (>= 0.3.2)
|
56
|
+
hashdiff
|
57
|
+
|
58
|
+
PLATFORMS
|
59
|
+
ruby
|
60
|
+
|
61
|
+
DEPENDENCIES
|
62
|
+
colorize (= 0.8.1)
|
63
|
+
english (= 0.6.3)
|
64
|
+
httparty (= 0.14.0)
|
65
|
+
rake (= 11.2.2)
|
66
|
+
rspec (= 3.6.0)
|
67
|
+
rubocop (= 0.48.1)
|
68
|
+
simplecov (= 0.12.0)
|
69
|
+
thor (= 0.19.4)
|
70
|
+
webmock (= 1.22.6)
|
71
|
+
|
72
|
+
BUNDLED WITH
|
73
|
+
1.14.6
|
data/LICENCE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Chris Tompkinson
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
# Game Finder
|
2
|
+
|
3
|
+
Command line tool for finding games and seeing related metadata
|
4
|
+
|
5
|
+

|
6
|
+
|
7
|
+
## Installation
|
8
|
+
Theres a number of options for installation
|
9
|
+
|
10
|
+
#### Pre-Packaged
|
11
|
+
1. Download latest releases zip file for your architecture
|
12
|
+
2. Extract to an installation directory e.g. `/opt/game-finder`
|
13
|
+
3. Symlink to your path `ln -s /opt/game-finder/game-finder /usr/local/bin/game-finder`
|
14
|
+
|
15
|
+
#### Gem
|
16
|
+
- `gem install game-finder`
|
17
|
+
|
18
|
+
#### Using repository
|
19
|
+
1. Install Ruby
|
20
|
+
2. `rake install`
|
21
|
+
3. `ln -s $GIT_REPO/bin/game-finder /usr/local/bin/game-finder`
|
22
|
+
|
23
|
+
## Setup
|
24
|
+
1. Setup an account at (Giant Bomb)[https://auth.giantbomb.com/signup/]
|
25
|
+
2. Copy your API access key from there (API)[https://www.giantbomb.com/api/]
|
26
|
+
3. Run game-finder to install a default config file
|
27
|
+
4. Update your config at `~/.game-finder.yaml` changing `api_key` to your key e.g.
|
28
|
+
|
29
|
+
```
|
30
|
+
---
|
31
|
+
api_key: 0000
|
32
|
+
```
|
33
|
+
|
34
|
+
## Commands
|
35
|
+
|
36
|
+
#### `game-finder search`
|
37
|
+
```
|
38
|
+
$ game-finder search Borderlands 2
|
39
|
+
Name: Borderlands 2
|
40
|
+
Platforms: Mac, Xbox 360, PlayStation 3, PlayStation Network (PS3), PC, Android, PlayStation Vita, PlayStation Network (Vita), Linux
|
41
|
+
Release: 2012-09-18
|
42
|
+
|
43
|
+
Name: Borderlands
|
44
|
+
Platforms: Mac, Xbox 360, PlayStation 3, PC
|
45
|
+
Release: 2009-10-20
|
46
|
+
|
47
|
+
Name: Borderlands Legends
|
48
|
+
Platforms: iPhone, iPad
|
49
|
+
Release: 2012-10-31
|
50
|
+
|
51
|
+
Name: Borderlands: The Pre-Sequel!
|
52
|
+
Platforms: Mac, Xbox 360, PlayStation 3, PlayStation Network (PS3), PC, Android, Linux
|
53
|
+
Release: 2014-10-14
|
54
|
+
|
55
|
+
Name: Borderlands: The Handsome Collection
|
56
|
+
Platforms: Xbox One, PlayStation 4
|
57
|
+
Release: 2015-03-24
|
58
|
+
|
59
|
+
Name: Borderlands 3 (Working Title)
|
60
|
+
|
61
|
+
Name: Tales from the Borderlands
|
62
|
+
Platforms: Mac, Xbox 360 Games Store, PC, iPhone, iPad, Android, Xbox One, PlayStation 4
|
63
|
+
Release: 2014-11-25
|
64
|
+
|
65
|
+
Name: Hugo 2 1/2
|
66
|
+
Platforms: Game Boy Color
|
67
|
+
Release: 1999-12-31
|
68
|
+
|
69
|
+
Name: 2 Hot 2 Handle
|
70
|
+
Platforms: ZX Spectrum
|
71
|
+
Release: 1991-12-31
|
72
|
+
|
73
|
+
Name: Roundball: 2-on-2 Challenge
|
74
|
+
Platforms: Nintendo Entertainment System
|
75
|
+
Release: 1992-05-31
|
76
|
+
```
|
77
|
+
|
78
|
+
#### `game-finder info`
|
79
|
+
```
|
80
|
+
$ game-finder info Borderlands 2
|
81
|
+
Name: Borderlands 2
|
82
|
+
Platforms: Mac, Xbox 360, PlayStation 3, PlayStation Network (PS3), PC, Android, PlayStation Vita, PlayStation Network (Vita), Linux
|
83
|
+
Released: 2012-09-18
|
84
|
+
Genres: Role-Playing, First-Person Shooter
|
85
|
+
Developers: Gearbox Software LLC
|
86
|
+
DLCs:
|
87
|
+
Borderlands 2: Mechromancer
|
88
|
+
Captain Scarlett and Her Pirate's Booty
|
89
|
+
Season Pass
|
90
|
+
Mister Torgue's Campaign of Carnage
|
91
|
+
Sir Hammerlock's Big Game Hunt
|
92
|
+
Tiny Tina’s Assault on Dragon Keep
|
93
|
+
Psycho Pack
|
94
|
+
```
|
95
|
+
|
96
|
+
## Tests
|
97
|
+
To execute tests `rake test` individual test types are available under `rake test:unit` or `rake test:lint`
|
98
|
+
|
99
|
+
## Packaging
|
100
|
+
|
101
|
+
### Travelling Ruby
|
102
|
+
To package using travelling ruby run `rake package`
|
103
|
+
Invidvidual architectures are available under
|
104
|
+
- `rake package:linux:x86`
|
105
|
+
- `rake package:linux:x86_64`
|
106
|
+
- `rake package:osx`
|
107
|
+
|
108
|
+
### Gem
|
109
|
+
To build a game `rake build:gem`
|
data/Rakefile
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
TRAVELING_RUBY_VERSION = '20150210-2.2.0'.freeze
|
2
|
+
ENTRY_POINT = 'game-finder.rb'.freeze
|
3
|
+
GEMSPEC = 'game-finder.gemspec'.freeze
|
4
|
+
|
5
|
+
task default: ['test']
|
6
|
+
|
7
|
+
task :install do
|
8
|
+
sh 'bundle install'
|
9
|
+
end
|
10
|
+
|
11
|
+
task :clean do
|
12
|
+
sh 'rm *.tar.gz || true'
|
13
|
+
sh 'rm -rf packaging/vendor || true'
|
14
|
+
sh 'rm packaging/*.tar.gz || true'
|
15
|
+
sh 'rm *.gem || true'
|
16
|
+
end
|
17
|
+
|
18
|
+
################################################################################
|
19
|
+
# Test
|
20
|
+
#
|
21
|
+
namespace 'test' do
|
22
|
+
desc 'Run all tests'
|
23
|
+
task all: %i[unit lint]
|
24
|
+
|
25
|
+
desc 'Run just the unit tests'
|
26
|
+
task :unit do
|
27
|
+
separator('Unit tests')
|
28
|
+
sh 'bundle exec rspec --pattern "spec/**/*_spec.rb"'
|
29
|
+
end
|
30
|
+
|
31
|
+
desc 'Lint the code'
|
32
|
+
task :lint do
|
33
|
+
separator('Lint tests')
|
34
|
+
sh 'rubocop lib/**/* spec/**/* Rakefile'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc 'Runs all tests'
|
39
|
+
task test: ['test:all']
|
40
|
+
|
41
|
+
################################################################################
|
42
|
+
# Build
|
43
|
+
#
|
44
|
+
namespace :build do
|
45
|
+
desc 'Builds the gem'
|
46
|
+
task :gem do
|
47
|
+
sh "gem build #{GEMSPEC}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
################################################################################
|
52
|
+
# Packaging
|
53
|
+
#
|
54
|
+
|
55
|
+
desc 'Create all packages'
|
56
|
+
task package: ['package:linux:x86', 'package:linux:x86_64', 'package:osx']
|
57
|
+
|
58
|
+
namespace :package do
|
59
|
+
namespace :linux do
|
60
|
+
desc 'Package your app for Linux x86'
|
61
|
+
task x86: "packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-linux-x86.tar.gz" do
|
62
|
+
separator 'Packaging Linux x86'
|
63
|
+
create_package('linux-x86')
|
64
|
+
end
|
65
|
+
|
66
|
+
desc 'Package your app for Linux x86_64'
|
67
|
+
task x86_64: "packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-linux-x86_64.tar.gz" do
|
68
|
+
separator 'Packaging Linux x86_64'
|
69
|
+
create_package('linux-x86_64')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
desc 'Package your app for OS X'
|
74
|
+
task osx: "packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-osx.tar.gz" do
|
75
|
+
separator 'Packaging Linux OSX'
|
76
|
+
create_package('osx')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
file "packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-linux-x86.tar.gz" do
|
81
|
+
download_runtime('linux-x86')
|
82
|
+
end
|
83
|
+
|
84
|
+
file "packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-linux-x86_64.tar.gz" do
|
85
|
+
download_runtime('linux-x86_64')
|
86
|
+
end
|
87
|
+
|
88
|
+
file "packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-osx.tar.gz" do
|
89
|
+
download_runtime('osx')
|
90
|
+
end
|
91
|
+
|
92
|
+
def create_package(target)
|
93
|
+
package_dir = "#{package_name}-#{version}-#{target}"
|
94
|
+
regenerate_packing_dir(package_dir)
|
95
|
+
copy_project_files(package_dir)
|
96
|
+
install_gem_dependencies(package_dir)
|
97
|
+
install_ruby(target, package_dir)
|
98
|
+
add_wrapper(package_dir)
|
99
|
+
create_tar(package_dir) unless ENV['DIR_ONLY']
|
100
|
+
end
|
101
|
+
|
102
|
+
def regenerate_packing_dir(package_dir)
|
103
|
+
sh "rm -rf #{package_dir}"
|
104
|
+
sh "mkdir -p #{package_dir}/lib"
|
105
|
+
sh "mkdir -p #{package_dir}/bin"
|
106
|
+
sh "mkdir -p #{package_dir}/files"
|
107
|
+
sh "mkdir #{package_dir}/ruby"
|
108
|
+
end
|
109
|
+
|
110
|
+
def copy_project_files(package_dir)
|
111
|
+
sh "cp -r lib/* #{package_dir}/lib/"
|
112
|
+
sh "cp -r bin/* #{package_dir}/bin/"
|
113
|
+
sh "cp -r files/* #{package_dir}/files/"
|
114
|
+
end
|
115
|
+
|
116
|
+
def install_gem_dependencies(package_dir)
|
117
|
+
sh 'mkdir -p packaging/tmp'
|
118
|
+
sh 'cp Gemfile Gemfile.lock packaging/tmp/'
|
119
|
+
Dir.chdir('packaging/tmp') do
|
120
|
+
sh 'BUNDLE_IGNORE_CONFIG=1 bundle install --path ../vendor --without development'
|
121
|
+
end
|
122
|
+
sh 'rm -rf packaging/tmp'
|
123
|
+
sh 'rm -f packaging/vendor/*/*/cache/*'
|
124
|
+
sh "cp -pR packaging/vendor #{package_dir}/"
|
125
|
+
sh "cp Gemfile Gemfile.lock #{package_dir}/vendor/"
|
126
|
+
sh "mkdir #{package_dir}/vendor/.bundle"
|
127
|
+
sh "cp packaging/bundler-config #{package_dir}/vendor/.bundle/config"
|
128
|
+
end
|
129
|
+
|
130
|
+
def install_ruby(target, package_dir)
|
131
|
+
sh "tar -xzf packaging/traveling-ruby-#{TRAVELING_RUBY_VERSION}-#{target}.tar.gz " \
|
132
|
+
"-C #{package_dir}/ruby"
|
133
|
+
end
|
134
|
+
|
135
|
+
def add_wrapper(package_dir)
|
136
|
+
sh "cp packaging/wrapper.sh #{package_dir}/game-finder"
|
137
|
+
sh "chmod u+x #{package_dir}/game-finder"
|
138
|
+
end
|
139
|
+
|
140
|
+
def create_tar(package_dir)
|
141
|
+
sh "tar -czf #{package_dir}.tar.gz #{package_dir}"
|
142
|
+
sh "rm -rf #{package_dir}"
|
143
|
+
end
|
144
|
+
|
145
|
+
def download_runtime(target)
|
146
|
+
sh 'cd packaging && curl -L -O --fail ' \
|
147
|
+
'https://d6r77u77i8pq3.cloudfront.net/releases/' \
|
148
|
+
"traveling-ruby-#{TRAVELING_RUBY_VERSION}-#{target}.tar.gz"
|
149
|
+
end
|
150
|
+
|
151
|
+
################################################################################
|
152
|
+
# Helpers
|
153
|
+
#
|
154
|
+
|
155
|
+
def version
|
156
|
+
'1.0.0'
|
157
|
+
end
|
158
|
+
|
159
|
+
def package_name
|
160
|
+
'game-finder'
|
161
|
+
end
|
162
|
+
|
163
|
+
def separator(text)
|
164
|
+
puts
|
165
|
+
puts '-' * 80
|
166
|
+
puts "- #{text.yellow}"
|
167
|
+
puts '-' * 80
|
168
|
+
puts
|
169
|
+
end
|
170
|
+
|
171
|
+
# Define color methods to avoid gem depedencies
|
172
|
+
class String
|
173
|
+
def colorize(color_code)
|
174
|
+
"\e[#{color_code}m#{self}\e[0m"
|
175
|
+
end
|
176
|
+
|
177
|
+
def red
|
178
|
+
colorize(31)
|
179
|
+
end
|
180
|
+
|
181
|
+
def green
|
182
|
+
colorize(32)
|
183
|
+
end
|
184
|
+
|
185
|
+
def yellow
|
186
|
+
colorize(33)
|
187
|
+
end
|
188
|
+
end
|
data/bin/game-finder
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
{
|
2
|
+
"error": "OK",
|
3
|
+
"limit": 10,
|
4
|
+
"number_of_page_results": 1,
|
5
|
+
"number_of_total_results": 1,
|
6
|
+
"offset": 0,
|
7
|
+
"results": [
|
8
|
+
{
|
9
|
+
"name": "Fastlane Pinball",
|
10
|
+
"original_release_date": null,
|
11
|
+
"platforms": [
|
12
|
+
{
|
13
|
+
"abbreviation": "PC",
|
14
|
+
"api_detail_url": "https://www.giantbomb.com/api/platform/3045-94/",
|
15
|
+
"id": 94,
|
16
|
+
"name": "PC",
|
17
|
+
"site_detail_url": "https://www.giantbomb.com/pc/3045-94/"
|
18
|
+
}
|
19
|
+
],
|
20
|
+
"resource_type": "game"
|
21
|
+
}
|
22
|
+
],
|
23
|
+
"status_code": 1,
|
24
|
+
"version": "1.0"
|
25
|
+
}
|
@@ -0,0 +1,99 @@
|
|
1
|
+
{
|
2
|
+
"error": "OK",
|
3
|
+
"limit": 1,
|
4
|
+
"number_of_page_results": 1,
|
5
|
+
"number_of_total_results": 1,
|
6
|
+
"offset": 0,
|
7
|
+
"results": {
|
8
|
+
"developers": [
|
9
|
+
{
|
10
|
+
"api_detail_url": "https://www.giantbomb.com/api/company/3010-149/",
|
11
|
+
"id": 149,
|
12
|
+
"name": "Epic Games",
|
13
|
+
"site_detail_url": "https://www.giantbomb.com/epic-games/3010-149/"
|
14
|
+
},
|
15
|
+
{
|
16
|
+
"api_detail_url": "https://www.giantbomb.com/api/company/3010-8415/",
|
17
|
+
"id": 8415,
|
18
|
+
"name": "The Coalition",
|
19
|
+
"site_detail_url": "https://www.giantbomb.com/the-coalition/3010-8415/"
|
20
|
+
},
|
21
|
+
{
|
22
|
+
"api_detail_url": "https://www.giantbomb.com/api/company/3010-5054/",
|
23
|
+
"id": 5054,
|
24
|
+
"name": "Psyonix Studios",
|
25
|
+
"site_detail_url": "https://www.giantbomb.com/psyonix-studios/3010-5054/"
|
26
|
+
}
|
27
|
+
],
|
28
|
+
"dlcs": [
|
29
|
+
{
|
30
|
+
"api_detail_url": "https://www.giantbomb.com/api/dlc/3020-696/",
|
31
|
+
"id": 696,
|
32
|
+
"name": "Multiplayer Map Pack 1",
|
33
|
+
"site_detail_url": "https://www.giantbomb.com/gears-of-war/3030-12231/dlc/"
|
34
|
+
},
|
35
|
+
{
|
36
|
+
"api_detail_url": "https://www.giantbomb.com/api/dlc/3020-697/",
|
37
|
+
"id": 697,
|
38
|
+
"name": "Hidden Fronts Map Pack",
|
39
|
+
"site_detail_url": "https://www.giantbomb.com/gears-of-war/3030-12231/dlc/"
|
40
|
+
}
|
41
|
+
],
|
42
|
+
"genres": [
|
43
|
+
{
|
44
|
+
"api_detail_url": "https://www.giantbomb.com/api/genre/3060-1/",
|
45
|
+
"id": 1,
|
46
|
+
"name": "Action",
|
47
|
+
"site_detail_url": "https://www.giantbomb.com/games/?wikiSlug=action&wikiTypeId=3060&wikiId=1&genre=1"
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"api_detail_url": "https://www.giantbomb.com/api/genre/3060-11/",
|
51
|
+
"id": 11,
|
52
|
+
"name": "Shooter",
|
53
|
+
"site_detail_url": "https://www.giantbomb.com/games/?wikiSlug=shooter&wikiTypeId=3060&wikiId=11&genre=11"
|
54
|
+
}
|
55
|
+
],
|
56
|
+
"name": "Gears of War",
|
57
|
+
"original_release_date": "2006-11-07 00:00:00",
|
58
|
+
"platforms": [
|
59
|
+
{
|
60
|
+
"abbreviation": "X360",
|
61
|
+
"api_detail_url": "https://www.giantbomb.com/api/platform/3045-20/",
|
62
|
+
"id": 20,
|
63
|
+
"name": "Xbox 360",
|
64
|
+
"site_detail_url": "https://www.giantbomb.com/xbox-360/3045-20/"
|
65
|
+
},
|
66
|
+
{
|
67
|
+
"abbreviation": "XBGS",
|
68
|
+
"api_detail_url": "https://www.giantbomb.com/api/platform/3045-86/",
|
69
|
+
"id": 86,
|
70
|
+
"name": "Xbox 360 Games Store",
|
71
|
+
"site_detail_url": "https://www.giantbomb.com/xbox-360-games-store/3045-86/"
|
72
|
+
},
|
73
|
+
{
|
74
|
+
"abbreviation": "PC",
|
75
|
+
"api_detail_url": "https://www.giantbomb.com/api/platform/3045-94/",
|
76
|
+
"id": 94,
|
77
|
+
"name": "PC",
|
78
|
+
"site_detail_url": "https://www.giantbomb.com/pc/3045-94/"
|
79
|
+
},
|
80
|
+
{
|
81
|
+
"abbreviation": "XONE",
|
82
|
+
"api_detail_url": "https://www.giantbomb.com/api/platform/3045-145/",
|
83
|
+
"id": 145,
|
84
|
+
"name": "Xbox One",
|
85
|
+
"site_detail_url": "https://www.giantbomb.com/xbox-one/3045-145/"
|
86
|
+
}
|
87
|
+
],
|
88
|
+
"publishers": [
|
89
|
+
{
|
90
|
+
"api_detail_url": "https://www.giantbomb.com/api/publisher/3010-340/",
|
91
|
+
"id": 340,
|
92
|
+
"name": "Microsoft Studios",
|
93
|
+
"site_detail_url": "https://www.giantbomb.com/microsoft-studios/3010-340/"
|
94
|
+
}
|
95
|
+
]
|
96
|
+
},
|
97
|
+
"status_code": 1,
|
98
|
+
"version": "0"
|
99
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
{
|
2
|
+
"error": "OK",
|
3
|
+
"limit": 10,
|
4
|
+
"number_of_page_results": 9,
|
5
|
+
"number_of_total_results": 9,
|
6
|
+
"offset": 0,
|
7
|
+
"results": [
|
8
|
+
{
|
9
|
+
"id": 12231,
|
10
|
+
"resource_type": "game"
|
11
|
+
},
|
12
|
+
{
|
13
|
+
"id": 30615,
|
14
|
+
"resource_type": "game"
|
15
|
+
},
|
16
|
+
{
|
17
|
+
"id": 38481,
|
18
|
+
"resource_type": "game"
|
19
|
+
},
|
20
|
+
{
|
21
|
+
"id": 45269,
|
22
|
+
"resource_type": "game"
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"id": 20662,
|
26
|
+
"resource_type": "game"
|
27
|
+
},
|
28
|
+
{
|
29
|
+
"id": 565,
|
30
|
+
"resource_type": "franchise"
|
31
|
+
},
|
32
|
+
{
|
33
|
+
"id": 11636,
|
34
|
+
"resource_type": "video"
|
35
|
+
},
|
36
|
+
{
|
37
|
+
"id": 11117,
|
38
|
+
"resource_type": "video"
|
39
|
+
}
|
40
|
+
],
|
41
|
+
"status_code": 1,
|
42
|
+
"version": "1.0"
|
43
|
+
}
|
data/game-finder.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
|
4
|
+
require 'game-finder/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'game-finder'
|
8
|
+
s.version = GameFinder::VERSION
|
9
|
+
s.summary = 'Game finding utility'
|
10
|
+
s.description = 'A command line tool to allow searching of games'
|
11
|
+
s.authors = ['Chris Tompkinson']
|
12
|
+
s.email = ['ctompkinson@gmail.com']
|
13
|
+
s.homepage = 'https://github.com/ctompkinson/game-finder'
|
14
|
+
s.license = 'MIT'
|
15
|
+
s.required_ruby_version = '>= 2.1'
|
16
|
+
|
17
|
+
s.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(spec|packaging|coverage)/})
|
19
|
+
end
|
20
|
+
|
21
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
22
|
+
s.require_paths = ['lib']
|
23
|
+
|
24
|
+
s.add_dependency 'colorize', '0.8.1'
|
25
|
+
s.add_dependency 'english', '0.6.3'
|
26
|
+
s.add_dependency 'httparty', '0.14.0'
|
27
|
+
s.add_dependency 'thor', '0.19.4'
|
28
|
+
|
29
|
+
s.add_development_dependency 'rake', '11.2.2'
|
30
|
+
s.add_development_dependency 'rspec', '3.6.0'
|
31
|
+
s.add_development_dependency 'rubocop', '0.48.1'
|
32
|
+
s.add_development_dependency 'simplecov', '0.12.0'
|
33
|
+
s.add_development_dependency 'webmock', '1.22.6'
|
34
|
+
end
|
data/lib/game-finder.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'json'
|
3
|
+
require 'uri'
|
4
|
+
require 'colorize'
|
5
|
+
|
6
|
+
require 'game-finder/config'
|
7
|
+
require 'game-finder/out'
|
8
|
+
|
9
|
+
include Config
|
10
|
+
|
11
|
+
# Provides helper methods for interacting with the Game Bomb API
|
12
|
+
module Api
|
13
|
+
API_URI = 'https://www.giantbomb.com/api'.freeze
|
14
|
+
|
15
|
+
def request(path, params)
|
16
|
+
# Add default parameters if they are not set
|
17
|
+
params[:api_key] = config.api_key unless params.key?('api_key') || params.key?(:api_key)
|
18
|
+
params[:format] = 'json' unless params.key?('json')
|
19
|
+
|
20
|
+
resp = HTTParty.get("#{API_URI}/#{path}?#{param_string(params)}",
|
21
|
+
headers: { 'User-Agent' => 'game-finder' })
|
22
|
+
|
23
|
+
raise 'Unable to find what youre looking for' if resp.code == 404
|
24
|
+
raise 'Oops something went wrong!' if resp.code != 200
|
25
|
+
|
26
|
+
JSON.parse(resp.body)
|
27
|
+
rescue StandardError => e
|
28
|
+
exit Out.error "Failed to make request: #{e}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def param_string(parameters)
|
32
|
+
parameters.map { |k, v| URI.escape("#{k}=#{v}") }.join('&')
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'game-finder/search'
|
3
|
+
require 'game-finder/info'
|
4
|
+
|
5
|
+
# CLI Entry point
|
6
|
+
class Cli < Thor
|
7
|
+
desc 'search', 'Search for game titles'
|
8
|
+
def search(*query)
|
9
|
+
Search.new.game(query, options)
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'info', 'Display info for a specific game title'
|
13
|
+
def info(*name)
|
14
|
+
Info.new.find(name, options)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
require 'game-finder/util'
|
4
|
+
|
5
|
+
include Util
|
6
|
+
|
7
|
+
# Helpers for loading and interacting with configuration
|
8
|
+
module Config
|
9
|
+
CONFIG_PATH = "#{ENV['HOME']}/.game-finder.yaml".freeze
|
10
|
+
DEFAULT_CONFIG_PATH = "#{File.dirname(__FILE__)}/../../files/default_config.yaml".freeze
|
11
|
+
|
12
|
+
def config
|
13
|
+
@config ||= load_config(CONFIG_PATH)
|
14
|
+
end
|
15
|
+
|
16
|
+
def load_config(config_path)
|
17
|
+
install_default_config unless File.exist? config_path
|
18
|
+
c = symbolize(YAML.load_file(config_path))
|
19
|
+
Struct.new(*c.keys).new(*c.values)
|
20
|
+
end
|
21
|
+
|
22
|
+
def install_default_config
|
23
|
+
# Skip using FileUtils.cp to avoid image magick installation
|
24
|
+
File.write(CONFIG_PATH, File.read(DEFAULT_CONFIG_PATH))
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Helpers to format for CLI output
|
2
|
+
module Format
|
3
|
+
def format_platforms(platforms)
|
4
|
+
platforms.map { |platform| platform['name'] }.join(', ')
|
5
|
+
end
|
6
|
+
|
7
|
+
def format_genres(genres)
|
8
|
+
genres.map { |genre| genre['name'] }.join(', ')
|
9
|
+
end
|
10
|
+
|
11
|
+
def format_developers(developers)
|
12
|
+
developers.map { |developer| developer['name'] }.join(', ')
|
13
|
+
end
|
14
|
+
|
15
|
+
def format_dlcs(dlcs)
|
16
|
+
dlcs.map { |dlc| dlc['name'].strip }.uniq.join("\n")
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'colorize'
|
3
|
+
|
4
|
+
require 'game-finder/api'
|
5
|
+
require 'game-finder/format'
|
6
|
+
|
7
|
+
# Looks up a game and shows you its information
|
8
|
+
class Info
|
9
|
+
include Api
|
10
|
+
include Format
|
11
|
+
|
12
|
+
GAME_FIELD_LIST = 'name,developers,genres,publishers,platforms,' \
|
13
|
+
'dlcs,original_release_date'.freeze
|
14
|
+
|
15
|
+
def find(name, _options = {})
|
16
|
+
search_results = request('search', field_list: 'id', query: name, limit: '1')['results']
|
17
|
+
output request("game/#{search_results.first['id']}",
|
18
|
+
field_list: GAME_FIELD_LIST)['results']
|
19
|
+
end
|
20
|
+
|
21
|
+
def output(game)
|
22
|
+
puts 'Name: '.yellow + game['name']
|
23
|
+
puts 'Platforms: '.yellow + format_platforms(game['platforms']) \
|
24
|
+
if game['platforms']
|
25
|
+
puts 'Released: '.yellow + game['original_release_date'].split(' ').first \
|
26
|
+
if game['original_release_date']
|
27
|
+
puts 'Genres: '.yellow + format_genres(game['genres']) \
|
28
|
+
if game['genres']
|
29
|
+
puts 'Developers: '.yellow + format_developers(game['developers']) \
|
30
|
+
if game['developers']
|
31
|
+
puts "DLCs:\n".yellow + format_dlcs(game['dlcs']) \
|
32
|
+
if game['dlcs']
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'colorize'
|
3
|
+
|
4
|
+
require 'game-finder/api'
|
5
|
+
|
6
|
+
# Allows you to search for games
|
7
|
+
class Search
|
8
|
+
include Api
|
9
|
+
|
10
|
+
def game(query, _options = {})
|
11
|
+
output request('search',
|
12
|
+
resources: 'game',
|
13
|
+
field_list: 'name,original_release_date,platforms',
|
14
|
+
query: query)
|
15
|
+
end
|
16
|
+
|
17
|
+
def output(result)
|
18
|
+
result['results'].each do |game|
|
19
|
+
puts 'Name: '.yellow + game['name']
|
20
|
+
puts 'Platforms: '.yellow + format_platforms(game['platforms']) if game['platforms']
|
21
|
+
puts 'Release: '.yellow + game['original_release_date'].split(' ').first \
|
22
|
+
if game['original_release_date']
|
23
|
+
puts
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def format_platforms(platforms)
|
28
|
+
platforms.map { |platform| platform['name'] }.join(', ')
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Helper methods for misc utilities
|
2
|
+
module Util
|
3
|
+
# rubocop:disable Style/EachWithObject
|
4
|
+
def symbolize(obj)
|
5
|
+
if obj.is_a? Hash
|
6
|
+
return obj.reduce({}) do |memo, (k, v)|
|
7
|
+
memo.tap { |m| m[k.to_sym] = symbolize(v) }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
if obj.is_a? Array
|
12
|
+
return obj.reduce([]) do |memo, v|
|
13
|
+
memo << symbolize(v)
|
14
|
+
memo
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
obj
|
19
|
+
end
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: game-finder
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chris Tompkinson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-06-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colorize
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.8.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.8.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: english
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.6.3
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.6.3
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: httparty
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.14.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.14.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: thor
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.19.4
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.19.4
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 11.2.2
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 11.2.2
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 3.6.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 3.6.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.48.1
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.48.1
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: simplecov
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.12.0
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.12.0
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: webmock
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 1.22.6
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 1.22.6
|
139
|
+
description: A command line tool to allow searching of games
|
140
|
+
email:
|
141
|
+
- ctompkinson@gmail.com
|
142
|
+
executables:
|
143
|
+
- game-finder
|
144
|
+
extensions: []
|
145
|
+
extra_rdoc_files: []
|
146
|
+
files:
|
147
|
+
- ".gitignore"
|
148
|
+
- ".rubocop.yml"
|
149
|
+
- ".travis.yml"
|
150
|
+
- CHANGELOG.md
|
151
|
+
- Gemfile
|
152
|
+
- Gemfile.lock
|
153
|
+
- LICENCE
|
154
|
+
- README.md
|
155
|
+
- Rakefile
|
156
|
+
- bin/game-finder
|
157
|
+
- files/default_config.yaml
|
158
|
+
- fixtures/fastlane.json
|
159
|
+
- fixtures/gears_of_war_game.json
|
160
|
+
- fixtures/gears_of_war_search.json
|
161
|
+
- game-finder.gemspec
|
162
|
+
- lib/game-finder.rb
|
163
|
+
- lib/game-finder/api.rb
|
164
|
+
- lib/game-finder/cli.rb
|
165
|
+
- lib/game-finder/config.rb
|
166
|
+
- lib/game-finder/format.rb
|
167
|
+
- lib/game-finder/info.rb
|
168
|
+
- lib/game-finder/out.rb
|
169
|
+
- lib/game-finder/search.rb
|
170
|
+
- lib/game-finder/util.rb
|
171
|
+
- lib/game-finder/version.rb
|
172
|
+
homepage: https://github.com/ctompkinson/game-finder
|
173
|
+
licenses:
|
174
|
+
- MIT
|
175
|
+
metadata: {}
|
176
|
+
post_install_message:
|
177
|
+
rdoc_options: []
|
178
|
+
require_paths:
|
179
|
+
- lib
|
180
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
181
|
+
requirements:
|
182
|
+
- - ">="
|
183
|
+
- !ruby/object:Gem::Version
|
184
|
+
version: '2.1'
|
185
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
186
|
+
requirements:
|
187
|
+
- - ">="
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
190
|
+
requirements: []
|
191
|
+
rubyforge_project:
|
192
|
+
rubygems_version: 2.4.5
|
193
|
+
signing_key:
|
194
|
+
specification_version: 4
|
195
|
+
summary: Game finding utility
|
196
|
+
test_files: []
|