mobile_stores 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 490e5fe108c95eb422955a2cebfcf09f6c661045
4
+ data.tar.gz: 29ded1a7088eb7ea7af6bdb3112d43f7dd8bc385
5
+ SHA512:
6
+ metadata.gz: 4f275795e220879a8354ccf3b50190691e59f93ca888ea2d4e49152d234ea83bbc9e2da3542a7eb4883656bce2cc86f9e84a8ea914b095627722338feaf4c876
7
+ data.tar.gz: dd832b7ba060981e8cf2aece4fb0c9b717f331774adcc107d2f8314e17f86666892bb78be8cd7061a509d0e4646d084587616b06bc48d7297e549bc4e5dcbdf7
Binary file
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,32 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ gem 'nokogiri'
7
+ gem 'countries'
8
+
9
+ # Add dependencies to develop your gem here.
10
+ # Include everything needed to run rake, tests, features, etc.
11
+ group :development do
12
+ gem "shoulda", ">= 0"
13
+ gem "rdoc", "~> 3.12"
14
+ gem "bundler", "~> 1.0"
15
+ gem "jeweler", "~> 1.8.7"
16
+ gem "simplecov", ">= 0", :require => false
17
+
18
+ gem 'parallel_tests'
19
+ gem 'zeus-parallel_tests'
20
+ gem 'terminal-notifier-guard'
21
+ end
22
+
23
+ group :test do
24
+ gem 'shoulda-matchers'
25
+ gem 'email_spec'
26
+ gem 'timecop'
27
+ end
28
+
29
+ group :test, :development do
30
+ gem 'rspec'
31
+ gem 'guard-rspec'
32
+ end
@@ -0,0 +1,155 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (4.0.1)
5
+ i18n (~> 0.6, >= 0.6.4)
6
+ minitest (~> 4.2)
7
+ multi_json (~> 1.3)
8
+ thread_safe (~> 0.1)
9
+ tzinfo (~> 0.3.37)
10
+ addressable (2.3.5)
11
+ atomic (1.1.14)
12
+ builder (3.2.2)
13
+ celluloid (0.15.2)
14
+ timers (~> 1.1.0)
15
+ coderay (1.1.0)
16
+ countries (0.9.3)
17
+ currencies (~> 0.4.2)
18
+ currencies (0.4.2)
19
+ diff-lcs (1.2.5)
20
+ docile (1.1.0)
21
+ email_spec (1.5.0)
22
+ launchy (~> 2.1)
23
+ mail (~> 2.2)
24
+ faraday (0.8.8)
25
+ multipart-post (~> 1.2.0)
26
+ ffi (1.9.3)
27
+ formatador (0.2.4)
28
+ git (1.2.6)
29
+ github_api (0.10.1)
30
+ addressable
31
+ faraday (~> 0.8.1)
32
+ hashie (>= 1.2)
33
+ multi_json (~> 1.4)
34
+ nokogiri (~> 1.5.2)
35
+ oauth2
36
+ guard (2.2.4)
37
+ formatador (>= 0.2.4)
38
+ listen (~> 2.1)
39
+ lumberjack (~> 1.0)
40
+ pry (>= 0.9.12)
41
+ thor (>= 0.18.1)
42
+ guard-rspec (1.2.1)
43
+ guard (>= 1.1)
44
+ hashie (2.0.5)
45
+ highline (1.6.20)
46
+ httpauth (0.2.0)
47
+ i18n (0.6.5)
48
+ jeweler (1.8.8)
49
+ builder
50
+ bundler (~> 1.0)
51
+ git (>= 1.2.5)
52
+ github_api (= 0.10.1)
53
+ highline (>= 1.6.15)
54
+ nokogiri (= 1.5.10)
55
+ rake
56
+ rdoc
57
+ json (1.8.1)
58
+ jwt (0.1.8)
59
+ multi_json (>= 1.5)
60
+ launchy (2.4.0)
61
+ addressable (~> 2.3)
62
+ listen (2.2.0)
63
+ celluloid (>= 0.15.2)
64
+ rb-fsevent (>= 0.9.3)
65
+ rb-inotify (>= 0.9)
66
+ lockfile (2.1.0)
67
+ lumberjack (1.0.4)
68
+ mail (2.5.4)
69
+ mime-types (~> 1.16)
70
+ treetop (~> 1.4.8)
71
+ method_source (0.8.2)
72
+ mime-types (1.25)
73
+ minitest (4.7.5)
74
+ multi_json (1.8.2)
75
+ multi_xml (0.5.5)
76
+ multipart-post (1.2.0)
77
+ nokogiri (1.5.10)
78
+ oauth2 (0.9.2)
79
+ faraday (~> 0.8)
80
+ httpauth (~> 0.2)
81
+ jwt (~> 0.1.4)
82
+ multi_json (~> 1.0)
83
+ multi_xml (~> 0.5)
84
+ rack (~> 1.2)
85
+ parallel (0.9.0)
86
+ parallel_tests (0.16.3)
87
+ parallel
88
+ polyglot (0.3.3)
89
+ pry (0.9.12.3)
90
+ coderay (~> 1.0)
91
+ method_source (~> 0.8)
92
+ slop (~> 3.4)
93
+ rack (1.5.2)
94
+ rake (10.1.0)
95
+ rb-fsevent (0.9.3)
96
+ rb-inotify (0.9.2)
97
+ ffi (>= 0.5.0)
98
+ rdoc (3.12.2)
99
+ json (~> 1.4)
100
+ rspec (2.14.1)
101
+ rspec-core (~> 2.14.0)
102
+ rspec-expectations (~> 2.14.0)
103
+ rspec-mocks (~> 2.14.0)
104
+ rspec-core (2.14.7)
105
+ rspec-expectations (2.14.4)
106
+ diff-lcs (>= 1.1.3, < 2.0)
107
+ rspec-mocks (2.14.4)
108
+ shoulda (3.5.0)
109
+ shoulda-context (~> 1.0, >= 1.0.1)
110
+ shoulda-matchers (>= 1.4.1, < 3.0)
111
+ shoulda-context (1.1.6)
112
+ shoulda-matchers (2.4.0)
113
+ activesupport (>= 3.0.0)
114
+ simplecov (0.8.1)
115
+ docile (~> 1.1.0)
116
+ lockfile (>= 2.1.0)
117
+ multi_json
118
+ simplecov-html (~> 0.8.0)
119
+ simplecov-html (0.8.0)
120
+ slop (3.4.7)
121
+ terminal-notifier-guard (1.5.3)
122
+ thor (0.18.1)
123
+ thread_safe (0.1.3)
124
+ atomic
125
+ timecop (0.6.3)
126
+ timers (1.1.0)
127
+ treetop (1.4.15)
128
+ polyglot
129
+ polyglot (>= 0.3.1)
130
+ tzinfo (0.3.38)
131
+ zeus (0.13.3)
132
+ method_source (>= 0.6.7)
133
+ zeus-parallel_tests (0.2.4)
134
+ parallel_tests (>= 0.11.3)
135
+ zeus (~> 0.13.3)
136
+
137
+ PLATFORMS
138
+ ruby
139
+
140
+ DEPENDENCIES
141
+ bundler (~> 1.0)
142
+ countries
143
+ email_spec
144
+ guard-rspec
145
+ jeweler (~> 1.8.7)
146
+ nokogiri
147
+ parallel_tests
148
+ rdoc (~> 3.12)
149
+ rspec
150
+ shoulda
151
+ shoulda-matchers
152
+ simplecov
153
+ terminal-notifier-guard
154
+ timecop
155
+ zeus-parallel_tests
@@ -0,0 +1,14 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch(%r{^lib/.+?/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
8
+ watch('spec/spec_helper.rb') { "spec" }
9
+
10
+ # Turnip features and steps
11
+ watch(%r{^spec/acceptance/(.+)\.feature$})
12
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
13
+ end
14
+
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Maxim Gladkov
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,65 @@
1
+ # Mobile Stores
2
+
3
+ Mobile Stores gem is a tool to fetch information from most popular mobile application stores: App Store, Google Play, Amazon Marketplace, Blackberry World and Windows Store.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'mobile_stores'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install mobile_stores
18
+
19
+ ## Usage
20
+
21
+ ### Find single app in the App Store:
22
+
23
+ App.in(:app_store).find("12345") # returns nil if app is not found
24
+ App.in(:app_store).find!("12345") # raises exceptions if app is not found
25
+
26
+ ### Search Google Play for apps:
27
+
28
+ App.in(:google_play).search("Angry Birds")
29
+ App.in(:google_play).search("Angry Birds", 10) # limit number of apps returned
30
+
31
+ ### Check if app exists in Blackberry World:
32
+
33
+ App.in(:blackberry_world).exists?("12345")
34
+
35
+ ### Specify country for searches:
36
+
37
+ App.in(:app_store).country(:in).find("12345")
38
+ App.in(:amazon_marketplace).country(:ru).search("Yandex")
39
+ App.in(:windows_store).country(:de).exists?("12345")
40
+
41
+ ### Get information from returned app:
42
+
43
+ # find Angry birds app (https://itunes.apple.com/us/app/angry-birds/id343200656)
44
+ app = App.in(:app_store).find("343200656")
45
+ app.title # => "Angry Birds"
46
+ app.application_id # => "343200656"
47
+ app.creator_name # => "Rovio Entertainment Ltd"
48
+ app.creator_id # => "298910979"
49
+ app.version # => "1.0.0"
50
+ app.rating # => 5.0
51
+ app.description # => "Use the unique powers..."
52
+ app.category # => "Games"
53
+ app.icon_url # => "http://a1974.phobos.apple.com/us/..."
54
+ app.view_url # => "https://itunes.apple.com/us/app/angry-birds/id343200656?mt=8&uo=4"
55
+ app.price # => 0.99
56
+ app.compatibility # => ["iPadWifi", "iPodTouchFifthGen", ...]
57
+ app.screenshot_urls # => ["http://a5.mzstatic.com/us/...", ...]
58
+
59
+ ## Contributing
60
+
61
+ 1. Fork it
62
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
63
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
64
+ 4. Push to the branch (`git push origin my-new-feature`)
65
+ 5. Create new Pull Request
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "mobile_stores"
18
+ gem.homepage = "http://github.com/maximgladkov/mobile_stores"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Tool to gather information from common mobile stores}
21
+ gem.description = %Q{This tool helps to gather information about any application from common mobile stores: App Store, Google Play, Blackberry World, Amazon Marketplace and Windows Store}
22
+ gem.email = "contact@maximgladkov.com"
23
+ gem.authors = ["Maxim Gladkov"]
24
+ gem.add_dependency 'nokogiri'
25
+ gem.add_dependency 'countries'
26
+ # dependencies defined in Gemfile
27
+ end
28
+ Jeweler::RubygemsDotOrgTasks.new
29
+
30
+ require 'rake/testtask'
31
+ Rake::TestTask.new(:test) do |test|
32
+ test.libs << 'lib' << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+
37
+ # require 'rcov/rcovtask'
38
+ # Rcov::RcovTask.new do |test|
39
+ # test.libs << 'test'
40
+ # test.pattern = 'test/**/test_*.rb'
41
+ # test.verbose = true
42
+ # test.rcov_opts << '--exclude "gems/*"'
43
+ # end
44
+
45
+ task :default => :test
46
+
47
+ require 'rdoc/task'
48
+ Rake::RDocTask.new do |rdoc|
49
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "mobile_stores #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
Binary file
@@ -0,0 +1,24 @@
1
+ require 'bigdecimal'
2
+ require 'bigdecimal/util'
3
+ require 'nokogiri'
4
+ require 'open-uri'
5
+ require 'countries'
6
+ require "mobile_stores/app"
7
+ require "mobile_stores/mobile_store"
8
+ require "mobile_stores/app_store"
9
+ require "mobile_stores/black_berry_world"
10
+ require "mobile_stores/google_play"
11
+ require "mobile_stores/windows_store"
12
+ require "mobile_stores/amazon_marketplace"
13
+
14
+ module MobileStores
15
+
16
+ STORES = {
17
+ :app_store => AppStore,
18
+ :google_play => GooglePlay,
19
+ :windows_store => WindowsStore,
20
+ :blackberry_world => BlackBerryWorld,
21
+ :amazon_marketplace => AmazonMarketplace
22
+ }
23
+
24
+ end
@@ -0,0 +1,70 @@
1
+ module MobileStores
2
+ class AmazonMarketplace
3
+ include MobileStore
4
+
5
+ act_as_html_source
6
+
7
+ private
8
+
9
+ def self.apps_url(query = nil, count = nil, country = nil)
10
+ url = "http://www.amazon.com/s/?url=search-alias%3Dmobile-apps&"
11
+ url = "#{ url }&field-keywords=#{ CGI::escape(query) }&keywords=#{ query }" if query
12
+ url
13
+ end
14
+
15
+ def self.app_url(id, country)
16
+ "http://www.amazon.com/gp/product/#{ id }"
17
+ end
18
+
19
+ def self.doc(url)
20
+ Nokogiri::HTML(open(url, "User-Agent" => "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"))
21
+ end
22
+
23
+ def self.process_app_html(doc)
24
+ self.parse_html_page(doc)
25
+ end
26
+
27
+ def self.process_apps_html(doc, count = nil)
28
+ self.parse_html_list(doc, count)
29
+ end
30
+
31
+ def self.parse_html_page(doc)
32
+ App.new({
33
+ application_id: doc.css('input[name="ASIN.0"]')[0]['value'],
34
+ title: doc.css('#btAsinTitle')[0].inner_text,
35
+ creator_name: doc.css('.buying span a')[0].inner_text,
36
+ creator_id: doc.css('.buying span a')[0].inner_text,
37
+ version: doc.css(".bucket .content strong:contains('Version:')").first.next.inner_text.strip,
38
+ rating: doc.css('.crAvgStars .swSprite')[0]['title'].match(/[0-9\.]/)[0].to_f,
39
+ description: doc.css(".bucket div.h2:contains('Product Description')")[0].next.css('.aplus').inner_html.gsub(%r{</?[^>]+?>}, ''),
40
+ category: doc.css(".bucket h2:contains('Look for Similar Items by Category') + div a")[1].inner_text,
41
+ icon_url: doc.css('#original_image img')[0]['src'].gsub(/SL[0-9]+/, 'SL512').gsub(/AA[0-9]+/, 'AA512'),
42
+ view_url: "http://www.amazon.com/gp/product/#{ doc.css('input[name="ASIN.0"]')[0]['value'] }",
43
+ price: doc.css('.priceLarge')[0].inner_text.gsub(/[^0-9.,]+/,'').to_d,
44
+ compatibility: doc.css(".bucket .content strong:contains('Minimum Operating System:')")[0].next.inner_text.strip,
45
+ screenshot_urls: doc.css('.productThumbnail img')[1..-1].map{ |d| d['src'].gsub(/SL[0-9]+/, 'SL1024').gsub(/AA[0-9]+/, 'AA1024') }
46
+ })
47
+ end
48
+
49
+ def self.parse_html_list(doc, count = nil, page = 1)
50
+ apps = doc.css('.product').map do |app|
51
+ App.new({
52
+ :application_id => app['name'],
53
+ :title => app.css('.productTitle a')[0].inner_text,
54
+ :icon_url => app.css('.productImage img')[0]['src']
55
+ })
56
+ end
57
+
58
+ if count and apps.size < count
59
+ while apps.size < count and doc.css('#pagnNextLink').length > 0
60
+ page += 1
61
+ doc = self.doc("http://www.amazon.com#{ doc.css('#pagnNextLink')[0]['href'].gsub('http://www.amazon.com', '') }")
62
+ apps += self.parse_html_list(doc)
63
+ end
64
+ end
65
+
66
+ count ? apps.take(count) : apps
67
+ end
68
+
69
+ end
70
+ end