gwitch 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d5d7c8e1ed024ba5333231113ae82e55743789dbf45eef7c5d7fd3fdcd50caeb
4
+ data.tar.gz: dc6eba3677e8fcf0ee4038dfc275398b2ddc31e1fd1a70793c7505fc2eb60298
5
+ SHA512:
6
+ metadata.gz: 1e78faf779696cf21b962d04085eb0dea98f14a9c2a9baca056109f12a0c3099c370fb12c43f4e02a74aad7a1b20f8af82a585ce84f7f14ca5be23b587e6bb85
7
+ data.tar.gz: 9f5d471a7c462a01744eafa8560dddc82edb7f8fc864ddd36b6ce450d8741c27d70844c912540ca375048ab96055ee4a81aa567dd1816d2b27f49ab9fad5e0ad
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## [0.0.1](https://github.com/dounx/gwitch/releases/tag/0.0.1) (2020-05-21)
2
+
3
+ * Initial import
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2005-2020 Dounx
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # Gwitch
2
+
3
+ Gwitch can get switch games info (including price) from nintendo official API.
4
+
5
+ ## Prerequisites
6
+
7
+ * ruby >= 2.3
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ gem install gwitch
13
+ ```
14
+
15
+ Or you can install via Bundler if you are using Rails. Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'gwitch'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ ## Basic Usage
26
+
27
+ ```ruby
28
+ require 'gwitch'
29
+ ```
30
+
31
+ Get all games from americas, asia and europe eshops.
32
+
33
+ ```ruby
34
+ games = Gwitch::Game.all
35
+ ```
36
+
37
+ Get all games from one eshops.
38
+
39
+ ```ruby
40
+ # Americas, Asia and Europe
41
+ games = Gwitch::Game.all('Americas')
42
+ ```
43
+
44
+ Get all avaliable countries.
45
+
46
+ ```ruby
47
+ countries = Gwitch::Country.all
48
+ ```
49
+
50
+ Get country's info.
51
+
52
+ ```ruby
53
+ country = Gwitch::Country.new('US')
54
+ country.alpha2 # => 'US'
55
+ country.region # => 'Americas'
56
+ country.currency # => 'USD'
57
+ ```
58
+
59
+ Query game's price.
60
+
61
+ ```ruby
62
+ price = Gwitch::Game.price('US', 'en', '70010000000141')
63
+ ```
64
+
65
+ ## Build
66
+
67
+ ```bash
68
+ git clone https://github.com/Dounx/gwitch
69
+ cd gwitch
70
+ gem build gwitch.gemspec
71
+ gem install --local gwitch-0.0.1.gem
72
+ ```
73
+
74
+ ## License
75
+
76
+ Gwitch is an open-sourced software licensed under the [MIT license](LICENSE).
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'countries'
4
+ require_relative 'game'
5
+
6
+ module Gwitch
7
+ class Country
8
+ class << self
9
+ # All avaliable countries
10
+ def all
11
+ ISO3166::Country.all.map(&:alpha2).select do |alpha2|
12
+ avaliable?(alpha2)
13
+ end.map { |alpha2| Country.new(alpha2) }
14
+ end
15
+
16
+ private
17
+
18
+ def avaliable?(alpha2)
19
+ # An americas game
20
+ nsuid = '70010000000141'
21
+
22
+ !Game.price(alpha2, nsuid).nil?
23
+ end
24
+ end
25
+
26
+ def initialize(alpha2)
27
+ @country = ISO3166::Country[alpha2]
28
+ end
29
+
30
+ def alpha2
31
+ @country.alpha2
32
+ end
33
+
34
+ def region
35
+ @country.region
36
+ end
37
+
38
+ def currency
39
+ @country.currency_code
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'region'
4
+
5
+ module Gwitch
6
+ class Game
7
+ IdsExceedMaxError = Class.new(StandardError)
8
+
9
+ class << self
10
+ def all(area = nil)
11
+ case area
12
+ when 'Americas'
13
+ Region::Americas.games
14
+ when 'Asia'
15
+ Region::Asia.games
16
+ when 'Europe'
17
+ Region::Europe.games
18
+ else
19
+ Region.games
20
+ end
21
+ end
22
+
23
+ # ids can be String or Array
24
+ def price(alpha2, ids, lang = 'en')
25
+ raise IdsExceedMaxError if ids.is_a?(Array) && ids.size > 50
26
+
27
+ api_url = 'https://api.ec.nintendo.com/v1/price'
28
+ queries = {
29
+ country: alpha2,
30
+ lang: lang,
31
+ ids: ids
32
+ }
33
+
34
+ uri = URI.parse(api_url)
35
+ uri.query = URI.encode_www_form(queries)
36
+
37
+ JSON.parse(uri.read)
38
+ rescue OpenURI::HTTPError
39
+ nil
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'algoliasearch'
4
+
5
+ module Gwitch
6
+ class Region
7
+
8
+ # A class which get games from americas eshop.
9
+ class Americas
10
+ CLIENT = Algolia::Client.new(
11
+ application_id: 'U3B6GR4UA3',
12
+ api_key: '9a20c93440cf63cf1a7008d75f7438bf'
13
+ )
14
+
15
+ INDEX = CLIENT.init_index('noa_aem_game_en_us')
16
+
17
+ PLATFORM = 'platform:Nintendo Switch'
18
+
19
+ # Trick for API limitation.
20
+ # Nintendo limit each facet can only get 1000 results.
21
+ # So we use as much as possible to get results.
22
+ # Maybe incompletely got.
23
+ # DON'T use this directly.
24
+ # Use filters method.
25
+ FACETS = {
26
+ generalFilters: ['Deals', 'DLC available', 'Demo available', 'Online Play via Nintendo Switch Online', 'Nintendo Switch Game Voucher'],
27
+ availability: ['New releases', 'Available now', 'Pre-purchase', 'Coming soon'],
28
+ categories: ['Action', 'Adventure', 'Application', 'Education', 'Fitness', 'Indie', 'Music', 'Party', 'Puzzle', 'Racing', 'Role-Playing', 'Simulation', 'Sports', 'Strategy'],
29
+ filterShops: ['At retail', 'On Nintendo.com'],
30
+ virtualConsole: ['NES', 'Super NES', 'Game Boy', 'Game Boy Color', 'Nintendo 64', 'Game Boy Advance', 'Nintendo DS', 'Other'],
31
+ characters: ['Mario', 'Zelda', 'Donkey Kong', 'Metroid', 'Pokémon', 'Mii', 'Kirby', 'Animal Crossing'],
32
+ priceRange: ['Free to start', '$0 - $4.99', '$5 - $9.99', '$10 - $19.99', '$20 - $39.99', '$40+'],
33
+ esrb: ['Everyone', 'Everyone 10+', 'Teen', 'Mature'],
34
+ filterPlayers: ['1+', '2+', '3+', '4+']
35
+ }.freeze
36
+
37
+ class << self
38
+ def games
39
+ games = []
40
+
41
+ # No facets
42
+ games += fetch
43
+
44
+ # Each facet
45
+ filters.each do |filter|
46
+ games += fetch(filter)
47
+ end
48
+
49
+ parse(games.uniq)
50
+ end
51
+
52
+ private
53
+
54
+ def fetch(filter = nil)
55
+ hits = []
56
+
57
+ # Empty string means all
58
+ query = ''
59
+
60
+ # histPerPage max can be 500
61
+ search_params = {
62
+ hitsPerPage: 500
63
+ }
64
+
65
+ search_params.merge!(facetFilters: filter) if filter
66
+
67
+ page = 0
68
+
69
+ loop do
70
+ response = INDEX.search(query, search_params.merge(page: page))
71
+ total_pages = response['nbPages']
72
+ hits += response['hits']
73
+ page += 1
74
+
75
+ break unless page < total_pages
76
+ end
77
+
78
+ hits
79
+ end
80
+
81
+ # GalleryParsedError = Class.new
82
+
83
+ def parse(raw)
84
+ host = 'https://www.nintendo.com'
85
+ microsite_host = 'https://assets.nintendo.com/image/upload/f_auto,q_auto,w_960,h_540'
86
+ legacy_host = 'https://assets.nintendo.com/video/upload/f_auto,q_auto,w_960,h_540'
87
+ asset_host = 'https://assets.nintendo.com/image/upload/f_auto,q_auto,w_960,h_540/Legacy%20Videos/posters/'
88
+
89
+ raw.map do |game|
90
+ image_urls = []
91
+ image_urls << (host + game['boxArt']) if game['boxArt']
92
+
93
+ gallery_path = game['gallery']
94
+ if gallery_path.nil?
95
+ nil
96
+ # Begin with '/'
97
+ elsif gallery_path[0] == '/'
98
+ # If prefix is 'content'
99
+ if gallery_path[1] == 'c'
100
+ image_urls << host + gallery_path
101
+ # Prefix is 'Microsites'
102
+ # Just one game
103
+ elsif gallery_path[1] == 'M'
104
+ url = microsite_host + gallery_path
105
+ last_slash = url.rindex('/')
106
+ image_urls << url.insert(last_slash + 1, 'posters/')
107
+ # Prefix is 'Nintendo'
108
+ elsif gallery_path[1] == 'N'
109
+ # TODO Nintendo* url have many situations
110
+ # https://assets.nintendo.com/image/upload/f_auto,q_auto,w_960,h_540/Nintendo Switch/Games/Third Party/Overcooked 2/Video/posters/Overcooked_2_Gourmet_Edition_Trailer
111
+ # /Nintendo Switch/Games/Third Party/Overcooked 2/Video/Overcooked_2_Gourmet_Edition_Trailer
112
+
113
+ # https://assets.nintendo.com/video/upload/f_auto,q_auto,w_960,h_540/Nintendo Switch/Games/NES and Super NES/Video/NES_Super_NES_May_2020_Game_Updates_Nintendo_Switch_Online
114
+ # /Nintendo Switch/Games/NES and Super NES/Video/NES_Super_NES_May_2020_Game_Updates_Nintendo_Switch_Online
115
+ # Prefix is 'Legacy Videos'
116
+ elsif gallery_path[1] == 'L'
117
+ image_urls << legacy_host + gallery_path
118
+ else
119
+ raise GalleryParsedError
120
+ end
121
+ # Just id
122
+ else
123
+ image_urls << asset_host + gallery_path
124
+ end
125
+
126
+ url = game['url'] ? host + game['url'] : nil
127
+
128
+ {
129
+ nsuid: game['nsuid'],
130
+ title: game['title'],
131
+ description: game['description'],
132
+ categories: game['categories'],
133
+ maker: game['publishers']&.join(', '),
134
+ player: game['players'],
135
+ images: image_urls,
136
+ url: url,
137
+ release_at: game['releaseDateMask']
138
+ }
139
+ end
140
+ end
141
+
142
+ def filters
143
+ filters = []
144
+
145
+ FACETS.each do |facet, options|
146
+ options.each do |option|
147
+ filters << [PLATFORM, "#{facet}:#{option}"]
148
+ end
149
+ end
150
+
151
+ filters
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open-uri'
4
+ require 'json'
5
+
6
+ module Gwitch
7
+ class Region
8
+
9
+ # A class which get games from asia eshop.
10
+ class Asia
11
+ API_URL = 'https://search.nintendo.jp/nintendo_soft/search.json'
12
+ QUERIES = {
13
+ opt_sshow: 1,
14
+ opt_osale: 1,
15
+ opt_hard: '1_HAC',
16
+ limit: 300
17
+ }.freeze
18
+
19
+ class << self
20
+ # Get all games from asia eshop.
21
+ def games
22
+ games = []
23
+ uri = URI.parse(API_URL)
24
+ page = 1
25
+
26
+ loop do
27
+ uri.query = URI.encode_www_form(QUERIES.merge(page: page))
28
+
29
+ result = JSON.parse(uri.read)['result']
30
+
31
+ total = result['total']
32
+ games += result['items']
33
+ page += 1
34
+
35
+ break unless games.size < total
36
+ end
37
+
38
+ parse(games)
39
+ end
40
+
41
+ private
42
+
43
+ def parse(raw)
44
+ host = 'https://ec.nintendo.com/JP/ja/titles/'
45
+ image_host = 'https://img-eshop.cdn.nintendo.net/i/'
46
+ image_extension = '.jpg'
47
+
48
+ raw.map do |game|
49
+ modes = []
50
+ modes += game['pmode']&.map { |mode| mode.delete_suffix('_MODE') } || []
51
+
52
+ image_urls = []
53
+ image_urls += game['sslurl']&.map { |id| image_host + id + image_extension } if game['sslurl']
54
+ image_urls << image_host + game['iurl'] + image_extension if game['iurl']
55
+
56
+ url = game['nsuid'] ? host + game['nsuid'] : nil
57
+
58
+ {
59
+ nsuid: game['nsuid'],
60
+ code: game['icode'],
61
+ title: game['title'],
62
+ description: game['text'],
63
+ categories: game['genre'],
64
+ maker: game['maker'],
65
+ player: game['player']&.first,
66
+ languages: game['lang'],
67
+ modes: modes,
68
+ dlcs: game['cnsuid'] || [],
69
+ images: image_urls,
70
+ url: url,
71
+ release_at: game['pdate']
72
+ }
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open-uri'
4
+ require 'json'
5
+
6
+ module Gwitch
7
+ class Region
8
+
9
+ # A class which get games from europe eshop.
10
+ class Europe
11
+ RowsTooSmallError = Class.new(StandardError)
12
+
13
+ API_URL = 'https://search.nintendo-europe.com/en/select'
14
+ MAX_ROWS = 100000
15
+
16
+ # ((playable_on_txt:"HAC")) means platform is nintendo switch
17
+ QUERIES = {
18
+ q: '*',
19
+ fq: '((playable_on_txt:"HAC"))',
20
+ wt: 'json',
21
+ rows: MAX_ROWS,
22
+ start: 0
23
+ }.freeze
24
+
25
+ class << self
26
+ # Get all games from asia eshop.
27
+ def games
28
+ uri = URI.parse(API_URL)
29
+ uri.query = URI.encode_www_form(QUERIES)
30
+ response = JSON.parse(uri.read)['response']
31
+
32
+ raise RowsTooSmallError if response['numFound'] > MAX_ROWS
33
+
34
+ parse(response['docs'])
35
+ end
36
+
37
+ private
38
+
39
+ def parse(raw)
40
+ host = 'https://www.nintendo.co.uk'
41
+ schema = 'https:'
42
+
43
+ raw.map do |game|
44
+ code = game['product_code_txt']&.first
45
+ code = code[4..8] if code
46
+
47
+ modes = []
48
+ modes << 'TV' if game['play_mode_tv_mode_b']
49
+ modes << 'TABLETOP' if game['play_mode_tabletop_mode_b']
50
+ modes << 'HANDHELD' if game['play_mode_handheld_mode_b']
51
+
52
+ url = game['url'] ? host + game['url'] : nil
53
+
54
+ {
55
+ nsuid: game['nsuid_txt'] || [],
56
+ code: code,
57
+ title: game['title'],
58
+ description: game['excerpt'],
59
+ categories: game['pretty_game_categories_txt'] || [],
60
+ maker: game['publisher'],
61
+ player: game['players_to'],
62
+ languages: game['language_availability']&.first&.split(',') || [],
63
+ modes: modes,
64
+ cloud_save: game['cloud_saves_b'],
65
+ images: [
66
+ schema + game['image_url'],
67
+ schema + game['image_url_sq_s'],
68
+ schema + game['image_url_h2x1_s'],
69
+ schema + game['gift_finder_carousel_image_url_s'],
70
+ schema + game['gift_finder_detail_page_image_url_s'],
71
+ schema + game['gift_finder_wishlist_image_url_s'],
72
+ schema + game['wishlist_email_square_image_url_s'],
73
+ schema + game['wishlist_email_banner460w_image_url_s'],
74
+ schema + game['wishlist_email_banner640w_image_url_s']
75
+ ],
76
+ url: url,
77
+ release_at: game['dates_released_dts']&.first
78
+ }
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'region/americas'
4
+ require_relative 'region/asia'
5
+ require_relative 'region/europe'
6
+
7
+ module Gwitch
8
+
9
+ # Get all games from americas, asia and europe eshops
10
+ class Region
11
+ def self.games
12
+ Hash[
13
+ [Americas, Asia, Europe].collect do |region|
14
+ [region.name.split('::').last, region.games]
15
+ end
16
+ ]
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gwitch
4
+ VERSION = '0.0.1'
5
+ end
data/lib/gwitch.rb ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'gwitch/game'
4
+ require_relative 'gwitch/country'
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gwitch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dounx
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-05-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: algoliasearch
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.27'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.27'
27
+ - !ruby/object:Gem::Dependency
28
+ name: countries
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ description: This gem can get switch games info from nintendo official API.
42
+ email: imdounx@gmail.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - CHANGELOG.md
48
+ - LICENSE
49
+ - README.md
50
+ - lib/gwitch.rb
51
+ - lib/gwitch/country.rb
52
+ - lib/gwitch/game.rb
53
+ - lib/gwitch/region.rb
54
+ - lib/gwitch/region/americas.rb
55
+ - lib/gwitch/region/asia.rb
56
+ - lib/gwitch/region/europe.rb
57
+ - lib/gwitch/version.rb
58
+ homepage: https://github.com/dounx/gwitch
59
+ licenses:
60
+ - MIT
61
+ metadata:
62
+ bug_tracker_uri: https://github.com/dounx/gwitch/issues
63
+ changelog_uri: https://github.com/dounx/gwitch/blob/master/CHANGELOG.md
64
+ documentation_uri: https://github.com/dounx/gwitch/blob/master/README.md
65
+ source_code_uri: https://github.com/dounx/gwitch
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 2.3.0
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubygems_version: 3.1.2
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: Nintendo switch game API.
85
+ test_files: []