class DmgAndroidApi::Android::App
Constants
- MARKET_ATTRIBUTES
Attributes
app_id[R]
callback[R]
error[R]
hydra[R]
Public Class Methods
new(app_id, options={})
click to toggle source
# File lib/dmg_android_api/android/app.rb, line 169 def initialize(app_id, options={}) @app_id = app_id @hydra = options[:hydra] || DmgAndroidApi.hydra @request_opts = options[:request_opts] || {} @callback = nil @error = nil end
parse(html)
click to toggle source
# File lib/dmg_android_api/android/app.rb, line 18 def self.parse(html) result = {} doc = Nokogiri::HTML(html) extra_info = doc.css('.meta-info') extra_info.each do |info| field_name = info.css('.title').text case field_name when 'Updated' result[:updated] = info.css('.content').text when 'Current Version' result[:current_version] = info.css('.content').text when 'Requires Android' result[:requires_android] = info.css('.content').text when 'Category' result[:category] = info.css('.content').text when 'Installs' result[:installs] = info.css('.content').text when 'Size' result[:size] = info.css('.content').text when 'Content Rating' result[:content_rating] = info.css('.content').text end end result[:description] = doc.css('.text-body div').first.inner_html result[:title] = doc.css('.document-title').first.text rating_elem = doc.css('.score') result[:rating] = rating_elem.text unless rating_elem.empty? votes_elem = doc.css('.reviews-num') result[:votes] = votes_elem.text unless votes_elem.empty? result[:developer] = doc.css('.document-subtitle.primary').text result[:more_from_developer] = [] result[:users_also_installed] = [] result[:related] = [] price_info = doc.css('.buy-button-container.apps.medium.play-button') price_span = price_info.css('meta[itemprop="price"]').first if price_span.attributes['content'].text == 'Free' result[:price] = '0' else result[:price] = price_span.attributes['content'].text end if similar_elem = doc.css('.doc-similar').first similar_elem.children.each do |similar_elem_child| assoc_app_type = similar_elem_child.attributes['data-analyticsid'].text next unless %w(more-from-developer users-also-installed related).include?(assoc_app_type) assoc_app_type = assoc_app_type.gsub('-', '_').to_sym result[assoc_app_type] ||= [] similar_elem_child.css('.app-left-column-related-snippet-container').each do |app_elem| assoc_app = {} assoc_app[:app_id] = app_elem.attributes['data-docid'].text result[assoc_app_type] << assoc_app end end end result[:banner_icon_url] = doc.css('.cover-container img').first.attributes['src'].value if image_elem = doc.css('.doc-banner-image-container img').first result[:banner_image_url] = image_elem.attributes['src'].value else result[:banner_image_url] = nil end if website_elem = doc.css('a').select{ |l| l.text.include?("Visit Developer's Website")}.first redirect_url = website_elem.attribute('href').value if q_param = URI(redirect_url).query.split('&').select{ |p| p =~ /q=/ }.first actual_url = q_param.gsub('q=', '') end result[:website_url] = actual_url end if email_elem = doc.css('a').select{ |l| l.text.include?("Email Developer")}.first result[:email] = email_elem.attribute('href').value.gsub(/^mailto:/, '') end unless (video_section_elem = doc.css('.doc-video-section')).empty? urls = video_section_elem.children.css('embed').map{ |e| e.attribute('src').value } result[:youtube_video_ids] = urls.map{ |u| /youtube\.com\/v\/(.*)\?/.match(u)[1] } else result[:youtube_video_ids] = [] end screenshots = doc.css('.thumbnails img') if screenshots && screenshots.length > 0 result[:screenshot_urls] = screenshots.map { |s| s.attributes['src'].value } else result[:screenshot_urls] = [] end recent_changes = doc.css('.recent-change') result[:whats_new] = '' recent_changes.each do |change| result[:whats_new] << change.text result[:whats_new] << '<br>' end result[:permissions] = permissions = [] perm_types = ['dangerous', 'safe'] perm_types.each do |type| doc.css("#doc-permissions-#{type} .doc-permission-group").each do |group_elem| title = group_elem.css('.doc-permission-group-title').text group_elem.css('.doc-permission-description').each do |desc_elem| #permissions << { :security => type, :group => title, :description => desc_elem.text } end descriptions = group_elem.css('.doc-permission-description').map { |e| e.text } descriptions_full = group_elem.css('.doc-permission-description-full').map { |e| e.text } (0...descriptions.length).each do |i| desc = descriptions[i] desc_full = descriptions_full[i] permissions << { :security => type, :group => title, :description => desc, :description_full => desc_full } end end end result[:rating_distribution] = { 5 => nil, 4 => nil, 3 => nil, 2 => nil, 1 => nil } if (histogram = doc.css('div.histogram-table').first) cur_index = 5 histogram.css('tr').each do |e| result[:rating_distribution][cur_index] = e.children.last.inner_text.gsub(/[^0-9]/, '').to_i cur_index -= 1 end end result[:html] = html result end
Public Instance Methods
enqueue_update(&block)
click to toggle source
# File lib/dmg_android_api/android/app.rb, line 189 def enqueue_update(&block) @callback = block @error = nil request = Typhoeus::Request.new(market_url, @request_opts) request.on_complete do |response| # HACK: Typhoeus <= 0.4.2 returns a response, 0.5.0pre returns the request. response = response.response if response.is_a?(Typhoeus::Request) result = nil begin result = App.parse(response.body) rescue Exception => e @error = e end update_callback(result) end hydra.queue(request) self end
market_url()
click to toggle source
# File lib/dmg_android_api/android/app.rb, line 177 def market_url "https://play.google.com/store/apps/details?id=#{@app_id}&hl=en" end
update()
click to toggle source
# File lib/dmg_android_api/android/app.rb, line 181 def update resp = Typhoeus::Request.get(market_url, @request_opts) result = App.parse(resp.body) update_callback(result) self end
Private Instance Methods
update_callback(result)
click to toggle source
# File lib/dmg_android_api/android/app.rb, line 216 def update_callback(result) unless @error MARKET_ATTRIBUTES.each do |a| attr_name = "@#{a}" attr_value = result[a] instance_variable_set(attr_name, attr_value) end end @callback.call(self) if @callback end