dmg_android_api 0.0.4

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
+ SHA1:
3
+ metadata.gz: f00475c072f0b51f86bf9a47fabccbdde1aeed92
4
+ data.tar.gz: 9227bd5ee02738b4019c7dc2b0af8bff85c5332e
5
+ SHA512:
6
+ metadata.gz: 3787fe315a5766ea665e39d365ace862f6af3e5010ef1e474910b1bd3bfb11186be5489841856425799c6a9960220acf03a44e3865da27c3957f4c2019ac03f9
7
+ data.tar.gz: a9ee189e59a4a8b0ebc971a63a08c19144598dcd946db6ed58bfee4969dc8a50a7a22b993372b144fa45a9cdd95ad415a651bc41bc1ff6722fc8f74ef1306549
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'typhoeus'
4
+ gem 'nokogiri'
5
+
6
+ group :development do
7
+ gem 'rspec', '~> 2.8.0'
8
+ gem 'bundler', '~> 1.3.5'
9
+ gem 'jeweler', '~> 1.6.4'
10
+ gem 'simplecov', '>= 0'
11
+ gem 'rdoc', '>= 3.9.4'
12
+ gem 'guard', '~> 1.2.3'
13
+ gem 'guard-rspec', '~> 1.1.0'
14
+ gem 'growl'
15
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Nhat Anh Nguyen
2
+
3
+ MIT License
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,29 @@
1
+ # DmgAndroidApi
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'dmg_android_api'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install dmg_android_api
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'dmg_android_api/version'
6
+
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = "dmg_android_api"
10
+ spec.version = DmgAndroidApi::VERSION
11
+ spec.authors = ["Nhat Anh Nguyen"]
12
+ spec.email = ["n.nguyen@thisisdmg.com"]
13
+ spec.description = %q{DMG Android Api}
14
+ spec.summary = %q{DMG Android Api}
15
+ spec.homepage = "http://www.thisisdmg.com"
16
+ spec.license = "MIT"
17
+
18
+ spec.files = `git ls-files`.split($/)
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ end
@@ -0,0 +1,221 @@
1
+ module DmgAndroidApi
2
+ module Android
3
+
4
+ class App
5
+ MARKET_ATTRIBUTES = [:title, :rating, :updated, :current_version, :requires_android,
6
+ :category, :installs, :size, :price, :content_rating, :description,
7
+ :votes, :developer, :more_from_developer, :users_also_installed,
8
+ :related, :banner_icon_url, :banner_image_url, :website_url, :email,
9
+ :youtube_video_ids, :screenshot_urls, :whats_new, :permissions,
10
+ :rating_distribution, :html]
11
+
12
+ attr_reader :app_id
13
+ attr_reader *MARKET_ATTRIBUTES
14
+ attr_reader :hydra
15
+ attr_reader :callback
16
+ attr_reader :error
17
+
18
+ def self.parse(html)
19
+ result = {}
20
+
21
+ doc = Nokogiri::HTML(html)
22
+
23
+ extra_info = doc.css('.meta-info')
24
+
25
+ extra_info.each do |info|
26
+
27
+ field_name = info.css('.title').text
28
+
29
+ case field_name
30
+ when 'Updated'
31
+ result[:updated] = info.css('.content').text
32
+ when 'Current Version'
33
+ result[:current_version] = info.css('.content').text
34
+ when 'Requires Android'
35
+ result[:requires_android] = info.css('.content').text
36
+ when 'Category'
37
+ result[:category] = info.css('.content').text
38
+ when 'Installs'
39
+ result[:installs] = info.css('.content').text
40
+ when 'Size'
41
+ result[:size] = info.css('.content').text
42
+ when 'Content Rating'
43
+ result[:content_rating] = info.css('.content').text
44
+ end
45
+ end
46
+ result[:description] = doc.css('.text-body div').first.inner_html
47
+
48
+ result[:title] = doc.css('.document-title').first.text
49
+
50
+ rating_elem = doc.css('.score')
51
+ result[:rating] = rating_elem.text unless rating_elem.empty?
52
+
53
+ votes_elem = doc.css('.reviews-num')
54
+ result[:votes] = votes_elem.text unless votes_elem.empty?
55
+
56
+ result[:developer] = doc.css('.document-subtitle.primary').text
57
+
58
+ result[:more_from_developer] = []
59
+ result[:users_also_installed] = []
60
+ result[:related] = []
61
+
62
+ if similar_elem = doc.css('.doc-similar').first
63
+ similar_elem.children.each do |similar_elem_child|
64
+ assoc_app_type = similar_elem_child.attributes['data-analyticsid'].text
65
+
66
+ next unless %w(more-from-developer users-also-installed related).include?(assoc_app_type)
67
+
68
+ assoc_app_type = assoc_app_type.gsub('-', '_').to_sym
69
+ result[assoc_app_type] ||= []
70
+
71
+ similar_elem_child.css('.app-left-column-related-snippet-container').each do |app_elem|
72
+ assoc_app = {}
73
+
74
+ assoc_app[:app_id] = app_elem.attributes['data-docid'].text
75
+
76
+ result[assoc_app_type] << assoc_app
77
+ end
78
+ end
79
+ end
80
+
81
+ result[:banner_icon_url] = doc.css('.cover-container img').first.attributes['src'].value
82
+
83
+ if image_elem = doc.css('.doc-banner-image-container img').first
84
+ result[:banner_image_url] = image_elem.attributes['src'].value
85
+ else
86
+ result[:banner_image_url] = nil
87
+ end
88
+
89
+ if website_elem = doc.css('a').select{ |l| l.text.include?("Visit Developer's Website")}.first
90
+ redirect_url = website_elem.attribute('href').value
91
+
92
+ if q_param = URI(redirect_url).query.split('&').select{ |p| p =~ /q=/ }.first
93
+ actual_url = q_param.gsub('q=', '')
94
+ end
95
+
96
+ result[:website_url] = actual_url
97
+ end
98
+
99
+ if email_elem = doc.css('a').select{ |l| l.text.include?("Email Developer")}.first
100
+ result[:email] = email_elem.attribute('href').value.gsub(/^mailto:/, '')
101
+ end
102
+
103
+ unless (video_section_elem = doc.css('.doc-video-section')).empty?
104
+ urls = video_section_elem.children.css('embed').map{ |e| e.attribute('src').value }
105
+ result[:youtube_video_ids] = urls.map{ |u| /youtube\.com\/v\/(.*)\?/.match(u)[1] }
106
+ else
107
+ result[:youtube_video_ids] = []
108
+ end
109
+
110
+
111
+ screenshots = doc.css('.thumbnails img')
112
+
113
+ if screenshots && screenshots.length > 0
114
+ result[:screenshot_urls] = screenshots.map { |s| s.attributes['src'].value }
115
+ else
116
+ result[:screenshot_urls] = []
117
+ end
118
+
119
+ recent_changes = doc.css('.recent-change')
120
+ result[:whats_new] = ''
121
+ recent_changes.each do |change|
122
+
123
+ result[:whats_new] << change.text
124
+ result[:whats_new] << '<br>'
125
+
126
+ end
127
+ result[:permissions] = permissions = []
128
+ perm_types = ['dangerous', 'safe']
129
+ perm_types.each do |type|
130
+ doc.css("#doc-permissions-#{type} .doc-permission-group").each do |group_elem|
131
+ title = group_elem.css('.doc-permission-group-title').text
132
+ group_elem.css('.doc-permission-description').each do |desc_elem|
133
+ #permissions << { :security => type, :group => title, :description => desc_elem.text }
134
+ end
135
+ descriptions = group_elem.css('.doc-permission-description').map { |e| e.text }
136
+ descriptions_full = group_elem.css('.doc-permission-description-full').map { |e| e.text }
137
+ (0...descriptions.length).each do |i|
138
+ desc = descriptions[i]
139
+ desc_full = descriptions_full[i]
140
+ permissions << { :security => type, :group => title, :description => desc, :description_full => desc_full }
141
+ end
142
+ end
143
+ end
144
+
145
+ result[:rating_distribution] = { 5 => nil, 4 => nil, 3 => nil, 2 => nil, 1 => nil }
146
+
147
+ if (histogram = doc.css('div.histogram-table').first)
148
+ cur_index = 5
149
+ histogram.css('tr').each do |e|
150
+ result[:rating_distribution][cur_index] = e.children.last.inner_text.gsub(/[^0-9]/, '').to_i
151
+ cur_index -= 1
152
+ end
153
+ end
154
+
155
+ result[:html] = html
156
+
157
+ result
158
+ end
159
+
160
+ def initialize(app_id, options={})
161
+ @app_id = app_id
162
+ @hydra = options[:hydra] || DmgAndroidApi.hydra
163
+ @request_opts = options[:request_opts] || {}
164
+ @callback = nil
165
+ @error = nil
166
+ end
167
+
168
+ def market_url
169
+ "https://play.google.com/store/apps/details?id=#{@app_id}&hl=en"
170
+ end
171
+
172
+ def update
173
+ resp = Typhoeus::Request.get(market_url, @request_opts)
174
+ result = App.parse(resp.body)
175
+ update_callback(result)
176
+
177
+ self
178
+ end
179
+
180
+ def enqueue_update(&block)
181
+ @callback = block
182
+ @error = nil
183
+
184
+ request = Typhoeus::Request.new(market_url, @request_opts)
185
+
186
+ request.on_complete do |response|
187
+ # HACK: Typhoeus <= 0.4.2 returns a response, 0.5.0pre returns the request.
188
+ response = response.response if response.is_a?(Typhoeus::Request)
189
+
190
+ result = nil
191
+
192
+ begin
193
+ result = App.parse(response.body)
194
+ rescue Exception => e
195
+ @error = e
196
+ end
197
+
198
+ update_callback(result)
199
+ end
200
+
201
+ hydra.queue(request)
202
+
203
+ self
204
+ end
205
+
206
+ private
207
+ def update_callback(result)
208
+ unless @error
209
+ MARKET_ATTRIBUTES.each do |a|
210
+ attr_name = "@#{a}"
211
+ attr_value = result[a]
212
+ instance_variable_set(attr_name, attr_value)
213
+ end
214
+ end
215
+
216
+ @callback.call(self) if @callback
217
+ end
218
+ end
219
+
220
+ end
221
+ end
@@ -0,0 +1,33 @@
1
+ module DmgAndroidApi
2
+ module Android
3
+
4
+ # Developer pages are extremely similar to leaderboard pages.
5
+ # Amazingly, this inheritence hack works!
6
+ class Developer < DmgAndroidApi::Android::Leaderboard
7
+ def initialze(developer, options={})
8
+ super(query, nil, options)
9
+ end
10
+
11
+ def market_urls(options={})
12
+ results = []
13
+
14
+ min_page = options[:min_page] || 1
15
+ max_page = options[:max_page] || 25
16
+
17
+ (min_page..max_page).each do |page|
18
+ start_val = (page - 1) * 12
19
+
20
+ url = "https://play.google.com/store/apps/developer?"
21
+ url << "id=#{URI.escape(identifier)}&"
22
+ url << "start=#{start_val}&"
23
+ url << "num=12&hl=en"
24
+
25
+ results << url
26
+ end
27
+
28
+ results
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,59 @@
1
+ module DmgAndroidApi
2
+ module Android
3
+
4
+ class Leaderboard
5
+ IDENTIFIERS = [
6
+ :editors_choice,
7
+ :featured,
8
+ :movers_shakers,
9
+ :tablet_featured,
10
+ :topgrossing,
11
+ :topselling_free,
12
+ :topselling_new_free,
13
+ :topselling_new_paid,
14
+ :topselling_paid,
15
+ :topselling_paid_game
16
+ ]
17
+
18
+ CATEGORIES = [
19
+ :application,
20
+ :app_wallpaper,
21
+ :app_widgets,
22
+ :arcade,
23
+ :books_and_reference,
24
+ :brain,
25
+ :business,
26
+ :cards,
27
+ :casual,
28
+ :comics,
29
+ :communication,
30
+ :education,
31
+ :entertainment,
32
+ :finance,
33
+ :game,
34
+ :game_wallpaper,
35
+ :game_widgets,
36
+ :health_and_fitness,
37
+ :libraries_and_demo,
38
+ :lifestyle,
39
+ :media_and_video,
40
+ :medical,
41
+ :music_and_audio,
42
+ :news_and_magazines,
43
+ :personalization,
44
+ :photography,
45
+ :productivity,
46
+ :racing,
47
+ :shopping,
48
+ :social,
49
+ :sports,
50
+ :sports_games,
51
+ :tools,
52
+ :transportation,
53
+ :travel_and_local,
54
+ :weather
55
+ ]
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,153 @@
1
+ module DmgAndroidApi
2
+ module Android
3
+
4
+ class Leaderboard
5
+ attr_reader :identifier, :category
6
+ attr_reader :hydra
7
+
8
+ def self.parse(html)
9
+ if html.include?('<title>Editor&#39;s Choice')
10
+ parse_editors_choice_page(html)
11
+ else
12
+ parse_normal_page(html)
13
+ end
14
+ end
15
+
16
+ def self.parse_normal_page(html)
17
+ results = []
18
+ doc = Nokogiri::HTML(html)
19
+ doc.css('.card').each do |snippet_node|
20
+ result = {}
21
+
22
+ details_node = snippet_node.css('.details')
23
+
24
+
25
+ unless snippet_node.css('.reason-set').empty?
26
+
27
+ ratings_node = snippet_node.css('.reason-set').css('.stars-container')
28
+ price_node = snippet_node.css('.reason-set').css('.price-container')
29
+
30
+ ratings_season_node = ratings_node.css('.reason-set-star-rating').css('.tiny-star')
31
+ current_rating = ratings_season_node.css('.current-rating')
32
+ result[:stars] = current_rating.text
33
+ result[:price_usd] = price_node.css('.buy-button-container').css('.buy').text
34
+ else
35
+ result[:stars] = nil
36
+ end
37
+
38
+ result[:title] = details_node.css('.title').text
39
+ result[:developer] = details_node.css('.subtitle-container').children.first.text
40
+ result[:market_id] = snippet_node.attributes['data-docid'].text
41
+ result[:market_url] = "https://play.google.com/store/apps/details?id=#{result[:market_id]}&hl=en"
42
+
43
+ result[:price_usd] = '$0.00' if result[:price_usd] == 'Free'
44
+
45
+ results << result
46
+ end
47
+
48
+ results
49
+ end
50
+
51
+ def self.parse_editors_choice_page(html)
52
+ results = []
53
+
54
+ doc = Nokogiri::HTML(html)
55
+
56
+ doc.css('.fsg-snippet').each do |snippet_node|
57
+ result = {}
58
+
59
+ result[:title] = snippet_node.css('.title').text
60
+ result[:price_usd] = nil
61
+ result[:developer] = snippet_node.css('.attribution').text
62
+ result[:market_id] = snippet_node.attributes['data-docid'].text
63
+ result[:market_url] = "https://play.google.com/store/apps/details?id=#{result[:market_id]}&hl=en"
64
+
65
+ results << result
66
+ end
67
+
68
+ results
69
+ end
70
+
71
+ def initialize(identifier, category=nil, options={})
72
+ @identifier = identifier
73
+ @category = category
74
+ @hydra = options[:hydra] || DmgAndroidApi.hydra
75
+ @request_opts = options[:request_opts] || {}
76
+ @parsed_results = []
77
+ end
78
+
79
+ def market_urls(options={})
80
+ results = []
81
+
82
+ min_page = options[:min_page] || 1
83
+ max_page = options[:max_page] || 10
84
+
85
+ (min_page..max_page).each do |page|
86
+ start_val = (page - 1) * 46
87
+
88
+ url = 'https://play.google.com/store/apps'
89
+ url << "/category/#{category.to_s.upcase}" if category
90
+ url << "/collection/#{identifier.to_s}?"
91
+ url << "start=#{start_val}"
92
+ url << "&num=46&hl=en"
93
+ results << url
94
+ end
95
+
96
+ results
97
+ end
98
+
99
+ def enqueue_update(options={})
100
+ if @identifier.to_s.downcase == 'editors_choice' && category == nil
101
+ url = 'https://play.google.com/store/apps/collection/editors_choice?&hl=en'
102
+ process_page(url, 1)
103
+ else
104
+ min_rank = options[:min_rank] || 1
105
+ max_rank = options[:max_rank] || 500
106
+
107
+ min_page = rank_to_page(min_rank)
108
+ max_page = rank_to_page(max_rank)
109
+
110
+ @parsed_results = []
111
+
112
+ urls = market_urls(:min_page => min_page, :max_page => max_page)
113
+ urls.each_index{ |i| process_page(urls[i], i+1) }
114
+ end
115
+
116
+ self
117
+ end
118
+
119
+ def update(options={})
120
+ enqueue_update(options)
121
+ @hydra.run
122
+
123
+ self
124
+ end
125
+
126
+ def rank_to_page(rank)
127
+ ((rank - 1) / 24) + 1
128
+ end
129
+
130
+ def results
131
+ raise 'Results do not exist yet.' unless @parsed_results
132
+ @parsed_results.reject{ |page| page.nil? || page.empty? }.flatten
133
+ end
134
+
135
+ private
136
+ def process_page(url, page_num)
137
+ request = Typhoeus::Request.new(url, @request_opts)
138
+ request.on_complete do |response|
139
+ # HACK: Typhoeus <= 0.4.2 returns a response, 0.5.0pre returns the request.
140
+ response = response.response if response.is_a?(Typhoeus::Request)
141
+ result = Leaderboard.parse(response.body)
142
+ update_callback(result, page_num)
143
+ end
144
+ @hydra.queue(request)
145
+ end
146
+
147
+ def update_callback(result, page)
148
+ @parsed_results[page] = result
149
+ end
150
+ end
151
+
152
+ end
153
+ end
@@ -0,0 +1,31 @@
1
+ module DmgAndroidApi
2
+ module Android
3
+
4
+ # Search query pages are extremely similar to leaderboard pages.
5
+ # Amazingly, this inheritence hack works!
6
+ class SearchQuery < DmgAndroidApi::Android::Leaderboard
7
+ def initialze(query, options={})
8
+ super(query, nil, options)
9
+ end
10
+
11
+ def market_urls(options={})
12
+ results = []
13
+ min_page = options[:min_page] || 1
14
+ max_page = 9
15
+ (min_page..max_page).each do |page|
16
+ start_val = (page - 1) * 46
17
+
18
+ url = "https://play.google.com/store/search?"
19
+ url << "q=#{URI.escape(identifier)}&"
20
+ url << "c=apps&start=#{start_val}&"
21
+ url << "num=46&hl=en"
22
+
23
+ results << url
24
+ end
25
+
26
+ results
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module DmgAndroidApi
2
+ VERSION = "0.0.4"
3
+ end
@@ -0,0 +1,18 @@
1
+ require "dmg_android_api/version"
2
+
3
+ require 'uri'
4
+
5
+ require 'typhoeus'
6
+ require 'nokogiri'
7
+
8
+ require 'dmg_android_api/android/app'
9
+ require 'dmg_android_api/android/leaderboard/constants'
10
+ require 'dmg_android_api/android/leaderboard'
11
+ require 'dmg_android_api/android/search_query'
12
+ require 'dmg_android_api/android/developer'
13
+
14
+ module DmgAndroidApi
15
+ def self.hydra
16
+ @hydra ||= Typhoeus::Hydra.new(:max_concurrency => 5)
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dmg_android_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Nhat Anh Nguyen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-07-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: DMG Android Api
42
+ email:
43
+ - n.nguyen@thisisdmg.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - dmg_android_api.gemspec
54
+ - lib/dmg_android_api.rb
55
+ - lib/dmg_android_api/android/app.rb
56
+ - lib/dmg_android_api/android/developer.rb
57
+ - lib/dmg_android_api/android/leaderboard.rb
58
+ - lib/dmg_android_api/android/leaderboard/constants.rb
59
+ - lib/dmg_android_api/android/search_query.rb
60
+ - lib/dmg_android_api/version.rb
61
+ homepage: http://www.thisisdmg.com
62
+ licenses:
63
+ - MIT
64
+ metadata: {}
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project:
81
+ rubygems_version: 2.0.5
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: DMG Android Api
85
+ test_files: []