From d27acdbc681deaad50a73e8fa44f59aa11e27e64 Mon Sep 17 00:00:00 2001 From: Hisham Al-Shurafa Date: Tue, 9 Apr 2013 20:58:00 -0600 Subject: [PATCH 01/18] added ref_no, added_timestamp, and icon variables to products query --- lib/appfigures.rb | 3 +++ spec/product_sales_spec.rb | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/lib/appfigures.rb b/lib/appfigures.rb index 3a69b5b..adba43c 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -17,6 +17,9 @@ def product_sales 'store_name' => hash['product']['store_name'], 'name' => hash['product']['name'], 'sku' => hash['product']['sku'], + 'ref_no' => hash['product']['ref_no'], + 'added_timestamp' => Date.parse(hash['product']['added_timestamp']), + 'icon' => hash['product']['icon'], 'downloads' => hash['downloads'].to_i, 'returns' => hash['returns'].to_i, 'updates' => hash['updates'].to_i, diff --git a/spec/product_sales_spec.rb b/spec/product_sales_spec.rb index 1527bec..4b37275 100644 --- a/spec/product_sales_spec.rb +++ b/spec/product_sales_spec.rb @@ -90,4 +90,16 @@ expect(@api.product_sales.first.revenue).to eq(100.99) end + it 'returns a ref_no' do + expect(@api.product_sales.first.ref_no).to eq('536354432') + end + + it 'returns an added timestamp' do + expect(@api.product_sales.first.added_timestamp).to eq(Date.parse('2012-07-23T00:00:00')) + end + + it 'returns an icon' do + expect(@api.product_sales.first.icon).to eq('http://a5.mzstatic.com/us/r1000/091/Purple/v4/20/69/65/20696562-4e19-17fe-5ffe-cb77a78e1651/mzl.jtpselsb.png') + end + end From e5c8cf3b799a7d107b24ba75c0d16c002efa4c50 Mon Sep 17 00:00:00 2001 From: Hisham Al-Shurafa Date: Tue, 9 Apr 2013 20:58:40 -0600 Subject: [PATCH 02/18] remove unnecessary new lines --- spec/product_sales_spec.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/spec/product_sales_spec.rb b/spec/product_sales_spec.rb index 4b37275..471c792 100644 --- a/spec/product_sales_spec.rb +++ b/spec/product_sales_spec.rb @@ -89,15 +89,12 @@ it 'returns a revenue number' do expect(@api.product_sales.first.revenue).to eq(100.99) end - it 'returns a ref_no' do expect(@api.product_sales.first.ref_no).to eq('536354432') end - it 'returns an added timestamp' do expect(@api.product_sales.first.added_timestamp).to eq(Date.parse('2012-07-23T00:00:00')) end - it 'returns an icon' do expect(@api.product_sales.first.icon).to eq('http://a5.mzstatic.com/us/r1000/091/Purple/v4/20/69/65/20696562-4e19-17fe-5ffe-cb77a78e1651/mzl.jtpselsb.png') end From 208163f9107e1bb906261eeefc70b5e3b44b5e9d Mon Sep 17 00:00:00 2001 From: Hisham Al-Shurafa Date: Wed, 10 Apr 2013 14:32:51 -0600 Subject: [PATCH 03/18] add ability to pass parameters to date_sales query --- lib/appfigures.rb | 9 +++++++-- lib/utils/hash_extensions.rb | 13 +++++++++++++ spec/date_sales_spec.rb | 18 +++++++++++++++++- 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 lib/utils/hash_extensions.rb diff --git a/lib/appfigures.rb b/lib/appfigures.rb index adba43c..94e48e0 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -1,5 +1,6 @@ require 'appfigures/version' require 'appfigures/connection' +require 'utils/hash_extensions' require 'date' @@ -31,8 +32,11 @@ def product_sales end end - def date_sales(start_date, end_date) - url = "sales/dates+products/#{start_date.strftime('%Y-%m-%d')}/#{end_date.strftime('%Y-%m-%d')}" + + # GET /sales/dates+products/2013-03-01/2013-03-31 + # See http://docs.appfigures.com/api/reference/v1-1/sales + def date_sales(start_date, end_date, options = {}) + url = "sales/dates+products/#{start_date.strftime('%Y-%m-%d')}/#{end_date.strftime('%Y-%m-%d')}#{options.to_query_string(true)}" self.connection.get(url).body.map do |date, product| product.map do |product_id, hash| Hashie::Mash.new({ @@ -42,6 +46,7 @@ def date_sales(start_date, end_date) 'store_name' => hash['product']['store_name'], 'name' => hash['product']['name'], 'sku' => hash['product']['sku'], + 'ref_no' => hash['product']['ref_no'], 'downloads' => hash['downloads'].to_i, 'returns' => hash['returns'].to_i, 'updates' => hash['updates'].to_i, diff --git a/lib/utils/hash_extensions.rb b/lib/utils/hash_extensions.rb new file mode 100644 index 0000000..6a4722a --- /dev/null +++ b/lib/utils/hash_extensions.rb @@ -0,0 +1,13 @@ + +class Hash + def to_query_string(include_question_mark = true) + query_string = '' + unless empty? + query_string << '?' if include_question_mark + query_string << inject([]) do |params, (key, value)| + params << "#{key}=#{value}" + end.join('&') + end + query_string + end +end diff --git a/spec/date_sales_spec.rb b/spec/date_sales_spec.rb index 2791ad0..69384a3 100644 --- a/spec/date_sales_spec.rb +++ b/spec/date_sales_spec.rb @@ -47,10 +47,23 @@ } } EOF + body223123 = <<-EOF + { + "2012-09-01": { + "223123": { + "downloads": 30, + "product": { + "id": 223123 + } + } + } + } + EOF @api = Appfigures.new username: 'test', password: 'test' @stubs = Faraday::Adapter::Test::Stubs.new do |stub| + stub.get('/v1.1/sales/dates+products/2012-09-01/2012-09-01?products=223123') { [status_code, headers, body223123] } stub.get('/v1.1/sales/dates+products/2012-09-01/2012-09-01') { [status_code, headers, body] } - end + end @api.connection.adapter :test, @stubs end @@ -94,5 +107,8 @@ it 'returns a revenue number' do expect(@api.date_sales(start_date, end_date).first.revenue).to eq(100.99) end + it 'returns a specific product ID' do + expect(@api.date_sales(start_date, end_date, { :products => 223123 }).first.product_id).to eq(223123) + end end From 00fac373fe652e54b74f3f6573a3a551ef47b629 Mon Sep 17 00:00:00 2001 From: Hisham Al-Shurafa Date: Fri, 12 Apr 2013 11:44:23 -0600 Subject: [PATCH 04/18] added country_sales query --- lib/appfigures.rb | 21 +++++++++++++ spec/country_sales_spec.rb | 64 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 spec/country_sales_spec.rb diff --git a/lib/appfigures.rb b/lib/appfigures.rb index 94e48e0..bac8041 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -59,5 +59,26 @@ def date_sales(start_date, end_date, options = {}) end end + # GET /sales/country/{start_date}/{end_date}?data_source={data_source}&products={product_ids}&country={country}&format={format} + # See http://docs.appfigures.com/api/reference/v1-1/sales + def country_sales(start_date, end_date, options = {}) + url = "sales/countries/#{start_date.strftime('%Y-%m-%d')}/#{end_date.strftime('%Y-%m-%d')}#{options.to_query_string(true)}" + self.connection.get(url).body.map do |country, hash| + Hashie::Mash.new({ + 'iso' => hash['iso'], + 'country' => hash['country'], + 'downloads' => hash['downloads'], + 'updates' => hash['updates'], + 'returns' => hash['returns'], + 'net_downloads' => hash['net_downloads'], + 'promos' => hash['promos'], + 'revenue' => hash['revenue'], + 'git_redemptions' => hash['gift_redemptions'], + }) + end + end + + + end diff --git a/spec/country_sales_spec.rb b/spec/country_sales_spec.rb new file mode 100644 index 0000000..267c32a --- /dev/null +++ b/spec/country_sales_spec.rb @@ -0,0 +1,64 @@ +require 'spec_helper' + +describe 'Appfigures country sales' do + before do + status_code = 200 + headers = { + 'Cache-Control' => 'private', + 'Content-Type' => 'application/json', + 'Server' => 'Microsoft-IIS/7.5', + 'X-AspNetMvc-Version' => '2.0', + 'X-Request-Limit' => '1000', + 'X-Request-Usage' => '4', + 'X-AspNet-Version' => '4.0.30319', + 'X-Server-ID' => '10', + 'Date' => 'Tue, 24 Jul 2012 19:56:51 GMT', + 'Connection' => 'close', + 'Transfer-Encoding' => 'Identity' + } + body = <<-EOF + { + "US": { + "downloads": 213, + "updates": 715, + "returns": 0, + "net_downloads": 213, + "promos": 0, + "revenue": "0.00", + "gift_redemptions": 0, + "country": "United States", + "iso": "US" + }, + "VE": { + "downloads": 1, + "updates": 2, + "returns": 0, + "net_downloads": 1, + "promos": 0, + "revenue": "0.00", + "gift_redemptions": 0, + "country": "Venezuela", + "iso": "VE" + } + } + EOF + @api = Appfigures.new username: 'test', password: 'test' + @stubs = Faraday::Adapter::Test::Stubs.new do |stub| + stub.get('/v1.1/sales/countries/2013-03-01/2013-03-31') { [status_code, headers, body] } + end + @api.connection.adapter :test, @stubs + end + + let(:start_date) { Date.parse('2013-03-01') } + let(:end_date) { Date.parse('2013-03-31') } + + it 'returns an iso' do + expect(@api.country_sales(start_date, end_date).first.iso).to eq("US") + end + + it 'returns downloads' do + expect(@api.country_sales(start_date, end_date).first.downloads).to eq(213) + end + + +end From 6c51b45f8e985aea5b4f8f81f8a78d1d42074cb1 Mon Sep 17 00:00:00 2001 From: Hisham Al-Shurafa Date: Fri, 12 Apr 2013 14:13:16 -0600 Subject: [PATCH 05/18] added product_reviews query --- lib/appfigures.rb | 30 +++++++ spec/product_reviews_spec.rb | 149 +++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 spec/product_reviews_spec.rb diff --git a/lib/appfigures.rb b/lib/appfigures.rb index bac8041..aec7c80 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -78,6 +78,36 @@ def country_sales(start_date, end_date, options = {}) end end + # GET /reviews/{productId}/{countries}/{page}/?language={language} + # See http://docs.appfigures.com/api/reference/v1-1/reviews + def product_reviews(product_id, countries, page = 0, options = {}) + url = "reviews/#{product_id}/#{countries}/#{page}#{options.to_query_string(true)}" + country_reviews = self.connection.get(url).body.map do |country, hash| + Hashie::Mash.new({ + 'num_reviews' => hash['num_reviews'], + 'all_ratings' => hash['all_ratings'], + 'ratings' => hash['ratings'], + 'all_stars' => hash['all_stars'], + 'stars' => hash['stars'], + 'all_star_breakdown' => hash['all_star_breakdown'], + 'star_breakdown' => hash['star_breakdown'], + 'iso' => hash['iso_country'], + 'country' => hash['country'], + 'reviews' => hash['reviews'].map do |review| + Hashie::Mash.new({ + 'stars' => review['stars'], + 'date' => review['date'], + 'title' => review['title'], + 'review' => review['review'], + 'version' => review['version'], + 'author' => review['author'] + }) + end + }) + end + end + + diff --git a/spec/product_reviews_spec.rb b/spec/product_reviews_spec.rb new file mode 100644 index 0000000..da117af --- /dev/null +++ b/spec/product_reviews_spec.rb @@ -0,0 +1,149 @@ +require 'spec_helper' + +describe 'Appfigures product reviews' do + before do + status_code = 200 + headers = { + 'Cache-Control' => 'private', + 'Content-Type' => 'application/json', + 'Server' => 'Microsoft-IIS/7.5', + 'X-AspNetMvc-Version' => '2.0', + 'X-Request-Limit' => '1000', + 'X-Request-Usage' => '4', + 'X-AspNet-Version' => '4.0.30319', + 'X-Server-ID' => '10', + 'Date' => 'Tue, 24 Jul 2012 19:56:51 GMT', + 'Connection' => 'close', + 'Transfer-Encoding' => 'Identity' + } + body = <<-EOF + { + "au": { + "store_id": 143460, + "country": "Australia", + "iso_country": "AU", + "all_ratings": 0, + "ratings": 0, + "all_stars": "0.00", + "stars": "0.00", + "num_pages": null, + "num_reviews": null, + "all_star_breakdown": "", + "star_breakdown": "", + "reviews": [] + }, + "ca": { + "store_id": 143455, + "country": "Canada", + "iso_country": "CA", + "all_ratings": 0, + "ratings": 0, + "all_stars": "0.00", + "stars": "0.00", + "num_pages": 1, + "num_reviews": null, + "all_star_breakdown": "", + "star_breakdown": "", + "reviews": [ + { + "title": "Future of apps", + "review": "Work data at my fingertips. Less need to be at the office.", + "original_title": "Future of app", + "original_review": "Work data at my fingertips. Less need to be at the office.", + "author": "reviewer123", + "version": "2.2.0", + "date": "31-Aug-2012", + "stars": "5.00", + "review_type": "review", + "type": "major", + "id": 143455, + "iso": "CA", + "country": "Canada" + } + ] + }, + "de": { + "store_id": 143443, + "country": "Germany", + "iso_country": "DE", + "all_ratings": 0, + "ratings": 0, + "all_stars": "0.00", + "stars": "0.00", + "num_pages": null, + "num_reviews": null, + "all_star_breakdown": "", + "star_breakdown": "", + "reviews": [] + }, + "us": { + "store_id": 143441, + "country": "United States", + "iso_country": "US", + "all_ratings": 0, + "ratings": 0, + "all_stars": "0.00", + "stars": "0.00", + "num_pages": 1, + "num_reviews": null, + "all_star_breakdown": "", + "star_breakdown": "", + "reviews": [ + { + "title": "Great app!", + "review": "Fantastic way to communicate.", + "original_title": "Great app!", + "original_review": "Fantastic way to communicate.", + "author": "OneTimeHiker", + "version": "2.0.0", + "date": "21-Jun-2012", + "stars": "5.00", + "review_type": "review", + "type": "major", + "id": 143441, + "iso": "US", + "country": "United States" + }, + { + "title": "office manager", + "review": "Lorem ipsum", + "original_title": "office manager", + "original_review": "Lorem ipsum", + "author": "Lilly, office manager", + "version": "1.0.7", + "date": "10-Apr-2012", + "stars": "5.00", + "review_type": "review", + "type": "major", + "id": 143441, + "iso": "US", + "country": "United States" + } + ] + } + } + EOF + @api = Appfigures.new username: 'test', password: 'test' + @stubs = Faraday::Adapter::Test::Stubs.new do |stub| + stub.get('/v1.1/reviews/1234567/major/0') { [status_code, headers, body] } + end + @api.connection.adapter :test, @stubs + end + + let(:product_id) { "1234567" } + let(:countries) { "major" } + + it 'returns 4 countries' do + expect(@api.product_reviews(product_id, countries).count).to eq(4) + end + + it 'au returns 0 reviews' do + expect(@api.product_reviews(product_id, countries).first.reviews.count).to eq(0) + end + + it 'ca returns review text' do + expect(@api.product_reviews(product_id, countries)[1].reviews[0].review).to eq("Work data at my fingertips. Less need to be at the office.") + end + + +end From 7cbeeb58c8c3ecc6c9a0b26f09c81b3e8d726d52 Mon Sep 17 00:00:00 2001 From: Hisham Al-Shurafa Date: Mon, 15 Apr 2013 12:20:17 -0600 Subject: [PATCH 06/18] parsed active param out of product_sales query --- lib/appfigures.rb | 3 ++- spec/product_sales_spec.rb | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/appfigures.rb b/lib/appfigures.rb index aec7c80..14e60a6 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -27,7 +27,8 @@ def product_sales 'net_downloads' => hash['net_downloads'].to_i, 'promos' => hash['promos'].to_i, 'gift_redemptions'=> hash['gift_redemptions'].to_i, - 'revenue' => hash['revenue'].to_f + 'revenue' => hash['revenue'].to_f, + 'active' => hash['product']['active'] }) end end diff --git a/spec/product_sales_spec.rb b/spec/product_sales_spec.rb index 471c792..2823fac 100644 --- a/spec/product_sales_spec.rb +++ b/spec/product_sales_spec.rb @@ -98,5 +98,8 @@ it 'returns an icon' do expect(@api.product_sales.first.icon).to eq('http://a5.mzstatic.com/us/r1000/091/Purple/v4/20/69/65/20696562-4e19-17fe-5ffe-cb77a78e1651/mzl.jtpselsb.png') end + it 'returns active' do + expect(@api.product_sales.first.active).to eq(true) + end end From 4e56fbd9a6375ba37b70de0e2a2940f91bae8f0c Mon Sep 17 00:00:00 2001 From: "halshura@gmail.com" Date: Sun, 10 May 2015 13:50:06 -0600 Subject: [PATCH 07/18] initial upgrade to v2 appfigures api --- Gemfile.lock | 16 ++++++++-------- lib/appfigures.rb | 2 +- lib/appfigures/connection.rb | 5 +++-- lib/appfigures/version.rb | 2 +- spec/country_sales_spec.rb | 4 ++-- spec/date_sales_spec.rb | 6 +++--- spec/product_reviews_spec.rb | 4 ++-- spec/product_sales_spec.rb | 4 ++-- 8 files changed, 22 insertions(+), 21 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9888bda..39a64f4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - appfigures (0.0.1) + appfigures (0.0.2) faraday faraday_middleware hashie @@ -11,13 +11,13 @@ GEM remote: https://rubygems.org/ specs: diff-lcs (1.1.3) - faraday (0.8.1) - multipart-post (~> 1.1) - faraday_middleware (0.8.8) - faraday (>= 0.7.4, < 0.9) - hashie (1.2.0) - multi_json (1.3.6) - multipart-post (1.1.5) + faraday (0.9.0) + multipart-post (>= 1.2, < 3) + faraday_middleware (0.9.1) + faraday (>= 0.7.4, < 0.10) + hashie (3.3.2) + multi_json (1.10.1) + multipart-post (2.0.0) rake (0.9.2.2) rspec (2.11.0) rspec-core (~> 2.11.0) diff --git a/lib/appfigures.rb b/lib/appfigures.rb index 14e60a6..27ade04 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -7,7 +7,7 @@ class Appfigures attr_reader :connection def initialize(options = {}) - @connection = Appfigures::Connection.new options[:username], options[:password] + @connection = Appfigures::Connection.new options[:username], options[:password], options[:client_key] end def product_sales diff --git a/lib/appfigures/connection.rb b/lib/appfigures/connection.rb index 47274e7..5230f14 100644 --- a/lib/appfigures/connection.rb +++ b/lib/appfigures/connection.rb @@ -5,8 +5,8 @@ class Appfigures class Connection < Faraday::Connection - def initialize(username, password) - super('https://api.appfigures.com/v1.1/') do |builder| + def initialize(username, password, client_key) + super('https://api.appfigures.com/v2/') do |builder| builder.use FaradayMiddleware::EncodeJson builder.adapter Faraday.default_adapter builder.response :json, :content_type => /\bjson$/ @@ -14,6 +14,7 @@ def initialize(username, password) self.basic_auth username, password self.headers["Accept"] = 'application/json' + self.headers["X-Client-Key"] = client_key end end end diff --git a/lib/appfigures/version.rb b/lib/appfigures/version.rb index 37411f8..7b71aea 100644 --- a/lib/appfigures/version.rb +++ b/lib/appfigures/version.rb @@ -1,3 +1,3 @@ class Appfigures - VERSION = "0.0.1" + VERSION = "0.0.2" end diff --git a/spec/country_sales_spec.rb b/spec/country_sales_spec.rb index 267c32a..84c7c60 100644 --- a/spec/country_sales_spec.rb +++ b/spec/country_sales_spec.rb @@ -42,9 +42,9 @@ } } EOF - @api = Appfigures.new username: 'test', password: 'test' + @api = Appfigures.new username: 'test', password: 'test', client_key: 'test' @stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/v1.1/sales/countries/2013-03-01/2013-03-31') { [status_code, headers, body] } + stub.get('/v2/sales/countries/2013-03-01/2013-03-31') { [status_code, headers, body] } end @api.connection.adapter :test, @stubs end diff --git a/spec/date_sales_spec.rb b/spec/date_sales_spec.rb index 69384a3..a631d0c 100644 --- a/spec/date_sales_spec.rb +++ b/spec/date_sales_spec.rb @@ -59,10 +59,10 @@ } } EOF - @api = Appfigures.new username: 'test', password: 'test' + @api = Appfigures.new username: 'test', password: 'test', client_key: 'test' @stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/v1.1/sales/dates+products/2012-09-01/2012-09-01?products=223123') { [status_code, headers, body223123] } - stub.get('/v1.1/sales/dates+products/2012-09-01/2012-09-01') { [status_code, headers, body] } + stub.get('/v2/sales/dates+products/2012-09-01/2012-09-01?products=223123') { [status_code, headers, body223123] } + stub.get('/v2/sales/dates+products/2012-09-01/2012-09-01') { [status_code, headers, body] } end @api.connection.adapter :test, @stubs end diff --git a/spec/product_reviews_spec.rb b/spec/product_reviews_spec.rb index da117af..0fb00e7 100644 --- a/spec/product_reviews_spec.rb +++ b/spec/product_reviews_spec.rb @@ -123,9 +123,9 @@ } } EOF - @api = Appfigures.new username: 'test', password: 'test' + @api = Appfigures.new username: 'test', password: 'test', client_key: 'test' @stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/v1.1/reviews/1234567/major/0') { [status_code, headers, body] } + stub.get('/v2/reviews/1234567/major/0') { [status_code, headers, body] } end @api.connection.adapter :test, @stubs end diff --git a/spec/product_sales_spec.rb b/spec/product_sales_spec.rb index 2823fac..d3d6dc9 100644 --- a/spec/product_sales_spec.rb +++ b/spec/product_sales_spec.rb @@ -45,9 +45,9 @@ } } EOF - @api = Appfigures.new username: 'test', password: 'test' + @api = Appfigures.new username: 'test', password: 'test', client_key: 'test' @stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/v1.1/sales/products') { [status_code, headers, body] } + stub.get('/v2/sales/products') { [status_code, headers, body] } end @api.connection.adapter :test, @stubs end From 34c8503671971f97437cefadc57bfae3dd02d498 Mon Sep 17 00:00:00 2001 From: "halshura@gmail.com" Date: Sun, 10 May 2015 15:08:46 -0600 Subject: [PATCH 08/18] more fixes to api lib and unit tests --- lib/appfigures.rb | 26 ++++++++++++++----------- spec/country_sales_spec.rb | 2 +- spec/date_sales_spec.rb | 40 ++++++-------------------------------- 3 files changed, 22 insertions(+), 46 deletions(-) diff --git a/lib/appfigures.rb b/lib/appfigures.rb index 27ade04..ad08878 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -37,17 +37,17 @@ def product_sales # GET /sales/dates+products/2013-03-01/2013-03-31 # See http://docs.appfigures.com/api/reference/v1-1/sales def date_sales(start_date, end_date, options = {}) - url = "sales/dates+products/#{start_date.strftime('%Y-%m-%d')}/#{end_date.strftime('%Y-%m-%d')}#{options.to_query_string(true)}" - self.connection.get(url).body.map do |date, product| + url = "reports/sales/dates+products" + + options = {start: start_date.strftime('%Y-%m-%d'), + end: start_date.strftime('%Y-%m-%d')}.merge(options) + + #url = "sales/dates+products/#{start_date.strftime('%Y-%m-%d')}/#{end_date.strftime('%Y-%m-%d')}#{options.to_query_string(true)}" + self.connection.get(url, options).body.map do |date, product| product.map do |product_id, hash| Hashie::Mash.new({ 'date' => Date.parse(date), - 'product_id' => hash['product']['id'], - 'store_id' => hash['product']['store_id'], - 'store_name' => hash['product']['store_name'], - 'name' => hash['product']['name'], - 'sku' => hash['product']['sku'], - 'ref_no' => hash['product']['ref_no'], + 'product_id' => hash['product_id'].to_i, 'downloads' => hash['downloads'].to_i, 'returns' => hash['returns'].to_i, 'updates' => hash['updates'].to_i, @@ -63,8 +63,12 @@ def date_sales(start_date, end_date, options = {}) # GET /sales/country/{start_date}/{end_date}?data_source={data_source}&products={product_ids}&country={country}&format={format} # See http://docs.appfigures.com/api/reference/v1-1/sales def country_sales(start_date, end_date, options = {}) - url = "sales/countries/#{start_date.strftime('%Y-%m-%d')}/#{end_date.strftime('%Y-%m-%d')}#{options.to_query_string(true)}" - self.connection.get(url).body.map do |country, hash| + url = "reports/sales" + options = {group_by: 'country', + start: start_date.strftime('%Y-%m-%d'), + end: end_date.strftime('%Y-%m-%d')}.merge(options) + #"/?group_by=country&start=#{start_date.strftime('%Y-%m-%d')}/#{end_date.strftime('%Y-%m-%d')}#{options.to_query_string(true)}" + self.connection.get(url, options).body.map do |country, hash| Hashie::Mash.new({ 'iso' => hash['iso'], 'country' => hash['country'], @@ -74,7 +78,7 @@ def country_sales(start_date, end_date, options = {}) 'net_downloads' => hash['net_downloads'], 'promos' => hash['promos'], 'revenue' => hash['revenue'], - 'git_redemptions' => hash['gift_redemptions'], + 'gift_redemptions' => hash['gift_redemptions'], }) end end diff --git a/spec/country_sales_spec.rb b/spec/country_sales_spec.rb index 84c7c60..7ecf287 100644 --- a/spec/country_sales_spec.rb +++ b/spec/country_sales_spec.rb @@ -44,7 +44,7 @@ EOF @api = Appfigures.new username: 'test', password: 'test', client_key: 'test' @stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/v2/sales/countries/2013-03-01/2013-03-31') { [status_code, headers, body] } + stub.get('/v2/reports/sales?end=2013-03-31&group_by=country&start=2013-03-01') { [status_code, headers, body] } end @api.connection.adapter :test, @stubs end diff --git a/spec/date_sales_spec.rb b/spec/date_sales_spec.rb index a631d0c..b1800d3 100644 --- a/spec/date_sales_spec.rb +++ b/spec/date_sales_spec.rb @@ -27,22 +27,8 @@ "promos": 1, "revenue": "100.99", "gift_redemptions": 10, - "product": { - "id": 123123, - "ref_no": "536354432", - "external_account_id": 397, - "store_id": 0, - "store_name": "apple", - "added_timestamp": "2012-07-23T00:00:00", - "name": "Test App", - "icon": "http://a5.mzstatic.com/us/r1000/091/Purple/v4/20/69/65/20696562-4e19-17fe-5ffe-cb77a78e1651/mzl.jtpselsb.png", - "active": true, - "hidden": false, - "sku": "TEST_APP", - "in_apps": [], - "product_type": "app", - "addons": [] - } + "date": "2012-09-01", + "product_id": 123123 } } } @@ -52,17 +38,16 @@ "2012-09-01": { "223123": { "downloads": 30, - "product": { - "id": 223123 - } + "product_id": 223123 } } } EOF @api = Appfigures.new username: 'test', password: 'test', client_key: 'test' @stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/v2/sales/dates+products/2012-09-01/2012-09-01?products=223123') { [status_code, headers, body223123] } - stub.get('/v2/sales/dates+products/2012-09-01/2012-09-01') { [status_code, headers, body] } + + stub.get('/v2/reports/sales/dates+products?end=2012-09-01&products=223123&start=2012-09-01') { [status_code, headers, body223123] } + stub.get('/v2/reports/sales/dates+products?end=2012-09-01&start=2012-09-01') { [status_code, headers, body] } end @api.connection.adapter :test, @stubs end @@ -73,19 +58,6 @@ it 'returns a product ID' do expect(@api.date_sales(start_date, end_date).first.product_id).to eq(123123) end - - it 'returns a store ID' do - expect(@api.date_sales(start_date, end_date).first.store_id).to eq(0) - end - it 'returns a store name' do - expect(@api.date_sales(start_date, end_date).first.store_name).to eq('apple') - end - it 'returns a name' do - expect(@api.date_sales(start_date, end_date).first.name).to eq('Test App') - end - it 'returns a sku' do - expect(@api.date_sales(start_date, end_date).first.sku).to eq('TEST_APP') - end it 'returns a download count' do expect(@api.date_sales(start_date, end_date).first.downloads).to eq(29) end From fec87ff3f32ec83bbbb9a39895b5b241d58ae42e Mon Sep 17 00:00:00 2001 From: "halshura@gmail.com" Date: Sun, 10 May 2015 17:00:35 -0600 Subject: [PATCH 09/18] fix product reviews api and test --- lib/appfigures.rb | 51 +++--- spec/product_reviews_spec.rb | 317 ++++++++++++++++++++++------------- 2 files changed, 228 insertions(+), 140 deletions(-) diff --git a/lib/appfigures.rb b/lib/appfigures.rb index ad08878..ba492ff 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -85,31 +85,32 @@ def country_sales(start_date, end_date, options = {}) # GET /reviews/{productId}/{countries}/{page}/?language={language} # See http://docs.appfigures.com/api/reference/v1-1/reviews - def product_reviews(product_id, countries, page = 0, options = {}) - url = "reviews/#{product_id}/#{countries}/#{page}#{options.to_query_string(true)}" - country_reviews = self.connection.get(url).body.map do |country, hash| - Hashie::Mash.new({ - 'num_reviews' => hash['num_reviews'], - 'all_ratings' => hash['all_ratings'], - 'ratings' => hash['ratings'], - 'all_stars' => hash['all_stars'], - 'stars' => hash['stars'], - 'all_star_breakdown' => hash['all_star_breakdown'], - 'star_breakdown' => hash['star_breakdown'], - 'iso' => hash['iso_country'], - 'country' => hash['country'], - 'reviews' => hash['reviews'].map do |review| - Hashie::Mash.new({ - 'stars' => review['stars'], - 'date' => review['date'], - 'title' => review['title'], - 'review' => review['review'], - 'version' => review['version'], - 'author' => review['author'] - }) - end - }) - end + def product_reviews(product_id, options = {}) + url = "reviews" + options = {products: product_id, + lang: 'en' + }.merge(options) + #url = "reviews/#{product_id}/#{countries}/#{page}#{options.to_query_string(true)}" + response = self.connection.get(url, options).body + + reviews = Hashie::Mash.new({ + 'total' => response['total'].to_i, + 'pages' => response['pages'].to_i, + 'this_page' => response['this_page'].to_i, + 'reviews' => response['reviews'].map do |review| + Hashie::Mash.new({ + 'author' => review['author'], + 'title' => review['title'], + 'review' => review['review'], + 'stars' => review['stars'], + 'iso' => review['iso'], + 'version' => review['version'], + 'date' => review['date'], + 'product' => review['product'], + 'id' => review['id'] + }) + end + }) end diff --git a/spec/product_reviews_spec.rb b/spec/product_reviews_spec.rb index 0fb00e7..a425c13 100644 --- a/spec/product_reviews_spec.rb +++ b/spec/product_reviews_spec.rb @@ -17,133 +17,220 @@ 'Transfer-Encoding' => 'Identity' } body = <<-EOF - { - "au": { - "store_id": 143460, - "country": "Australia", - "iso_country": "AU", - "all_ratings": 0, - "ratings": 0, - "all_stars": "0.00", - "stars": "0.00", - "num_pages": null, - "num_reviews": null, - "all_star_breakdown": "", - "star_breakdown": "", - "reviews": [] - }, - "ca": { - "store_id": 143455, - "country": "Canada", - "iso_country": "CA", - "all_ratings": 0, - "ratings": 0, - "all_stars": "0.00", - "stars": "0.00", - "num_pages": 1, - "num_reviews": null, - "all_star_breakdown": "", - "star_breakdown": "", - "reviews": [ - { - "title": "Future of apps", - "review": "Work data at my fingertips. Less need to be at the office.", - "original_title": "Future of app", - "original_review": "Work data at my fingertips. Less need to be at the office.", - "author": "reviewer123", - "version": "2.2.0", - "date": "31-Aug-2012", - "stars": "5.00", - "review_type": "review", - "type": "major", - "id": 143455, - "iso": "CA", - "country": "Canada" - } - ] - }, - "de": { - "store_id": 143443, - "country": "Germany", - "iso_country": "DE", - "all_ratings": 0, - "ratings": 0, - "all_stars": "0.00", - "stars": "0.00", - "num_pages": null, - "num_reviews": null, - "all_star_breakdown": "", - "star_breakdown": "", - "reviews": [] - }, - "us": { - "store_id": 143441, - "country": "United States", - "iso_country": "US", - "all_ratings": 0, - "ratings": 0, - "all_stars": "0.00", - "stars": "0.00", - "num_pages": 1, - "num_reviews": null, - "all_star_breakdown": "", - "star_breakdown": "", - "reviews": [ - { - "title": "Great app!", - "review": "Fantastic way to communicate.", - "original_title": "Great app!", - "original_review": "Fantastic way to communicate.", - "author": "OneTimeHiker", - "version": "2.0.0", - "date": "21-Jun-2012", - "stars": "5.00", - "review_type": "review", - "type": "major", - "id": 143441, - "iso": "US", - "country": "United States" - }, - { - "title": "office manager", - "review": "Lorem ipsum", - "original_title": "office manager", - "original_review": "Lorem ipsum", - "author": "Lilly, office manager", - "version": "1.0.7", - "date": "10-Apr-2012", - "stars": "5.00", - "review_type": "review", - "type": "major", - "id": 143441, - "iso": "US", - "country": "United States" - } - ] - } - } +{ + "total": 10, + "pages": 1, + "this_page": 1, + "reviews": [ + { + "author": "Extremely happy customer :)", + "title": "So happy!", + "review": "Great app & great surgeon had my nose done with him 6 months ago and very happy with the results! :)", + "original_title": "So happy!", + "original_review": "Great app & great surgeon had my nose done with him 6 months ago and very happy with the results! :)", + "stars": "5.00", + "iso": "AU", + "version": null, + "date": "2013-09-08T12:31:00", + "product": 6764936, + "weight": 0, + "id": "6764936LMZFNAEP14DA17opqFW0qkw==", + "predicted_langs": [ + "en" + ] + }, + { + "author": "Extremely happy customer :)", + "title": "So happy!", + "review": "Great app & great surgeon had my nose done with him 6 months ago and very happy with the results! :)", + "original_title": "So happy!", + "original_review": "Great app & great surgeon had my nose done with him 6 months ago and very happy with the results! :)", + "stars": "5.00", + "iso": "AU", + "version": null, + "date": "2013-09-08T12:31:00", + "product": 6764936, + "weight": 0, + "id": "6764936LIw1AZww6P2h2ot9ZkjylXQ==", + "predicted_langs": [ + "en" + ] + }, + { + "author": "GelatinousFire", + "title": "Easy to use, helpful", + "review": "I think I've been getting carried away with using this app too much. The only thing I would suggest is having a feature to save the before and after together, especially if the photo was taken in-app and not saved on the device already.", + "original_title": "Easy to use, helpful", + "original_review": "I think I've been getting carried away with using this app too much. The only thing I would suggest is having a feature to save the before and after together, especially if the photo was taken in-app and not saved on the device already.", + "stars": "5.00", + "iso": "AU", + "version": null, + "date": "2013-09-07T03:17:00", + "product": 6764936, + "weight": 0, + "id": "6764936LTWoPGlw4Jv1mL6Is4IfvJA==", + "predicted_langs": [ + "en" + ] + }, + { + "author": "Needanewnose", + "title": "Awesome from me too", + "review": "Excellent idea - very helpful if considering surgery!!", + "original_title": "Awesome from me too", + "original_review": "Excellent idea - very helpful if considering surgery!!", + "stars": "5.00", + "iso": "AU", + "version": null, + "date": "2012-12-31T08:29:00", + "product": 6764936, + "weight": 0, + "id": "6764936LABQtADfYjihiTLnGfoitww==", + "predicted_langs": [ + "en" + ] + }, + { + "author": "Aplen", + "title": "Awesome", + "review": "Love this app. Works fine.", + "original_title": "Awesome", + "original_review": "Love this app. Works fine.", + "stars": "5.00", + "iso": "AU", + "version": null, + "date": "2012-11-01T11:45:00", + "product": 6764936, + "weight": 0, + "id": "6764936LWwOvS-+7wc5CYg1fNybp+w==", + "predicted_langs": [ + "en" + ] + }, + { + "author": "Buybuybuybuy", + "title": "Awesome", + "review": "Aww now I really want a nose job!!!", + "original_title": "Awesome", + "original_review": "Aww now I really want a nose job!!!", + "stars": "5.00", + "iso": "AU", + "version": null, + "date": "2012-08-18T04:28:00", + "product": 6764936, + "weight": 0, + "id": "6764936LbHD103TUYNFH-ef0ZBJl-w==", + "predicted_langs": [ + "en" + ] + }, + { + "author": "Shnoz66", + "title": "Fix my nose", + "review": "Great app Dr Shahidi Love your work", + "original_title": "Fix my nose", + "original_review": "Great app Dr Shahidi Love your work", + "stars": "5.00", + "iso": "AU", + "version": null, + "date": "2012-06-22T22:37:00", + "product": 6764936, + "weight": 0, + "id": "6764936Lk31Vr1HbM0zRYqCw6fwxUw==", + "predicted_langs": [ + "en", + "af", + "la", + "nl" + ] + }, + { + "author": "Shnoz66", + "title": "Fix my nose", + "review": "Great app Dr Shahidi
Love your work", + "original_title": "Fix my nose", + "original_review": "Great app Dr Shahidi
Love your work", + "stars": "5.00", + "iso": "AU", + "version": null, + "date": "2012-06-22T10:37:00", + "product": 6764936, + "weight": 0, + "id": "6764936Lgo8PsGRm1+ZtKI0wLiagdQ==", + "predicted_langs": [ + "en", + "af", + "la", + "nl" + ] + }, + { + "author": "Happypatient", + "title": "Dr Shahidi", + "review": "The app is fun and Dr Shahidi is a genius!", + "original_title": "Dr Shahidi", + "original_review": "The app is fun and Dr Shahidi is a genius!", + "stars": "5.00", + "iso": "AU", + "version": null, + "date": "2012-02-16T07:30:00", + "product": 6764936, + "weight": 0, + "id": "6764936LBbqGDq1qPu6LuLMS4tCj7w==", + "predicted_langs": [ + "la", + "en", + "cy", + "af", + "lb" + ] + }, + { + "author": "Eddy EF", + "title": "Facial plastic surgery", + "review": "It's a great facial surgeries performed by this doctor, I recommend it.", + "original_title": "Facial plastic surgery", + "original_review": "It's a great facial surgeries performed by this doctor, I recommend it.", + "stars": "5.00", + "iso": "AU", + "version": null, + "date": "2011-10-13T07:30:00", + "product": 6764936, + "weight": 0, + "id": "6764936LmBQyYvLr3+vY-hWhn1lt4g==", + "predicted_langs": [ + "en" + ] + } + ] +} + EOF @api = Appfigures.new username: 'test', password: 'test', client_key: 'test' @stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/v2/reviews/1234567/major/0') { [status_code, headers, body] } + stub.get('/v2/reviews?lang=en&products=6764936') { [status_code, headers, body] } end @api.connection.adapter :test, @stubs end - let(:product_id) { "1234567" } - let(:countries) { "major" } + let(:product_id) { "6764936" } + + it 'returns 10 reviews' do + expect(@api.product_reviews(product_id).reviews.count).to eq(10) + end + - it 'returns 4 countries' do - expect(@api.product_reviews(product_id, countries).count).to eq(4) + it 'returns review text' do + expect(@api.product_reviews(product_id).reviews[0].review).to eq("Great app & great surgeon had my nose done with him 6 months ago and very happy with the results! :)") end - it 'au returns 0 reviews' do - expect(@api.product_reviews(product_id, countries).first.reviews.count).to eq(0) + it 'returns review title' do + expect(@api.product_reviews(product_id).reviews[1].title).to eq("So happy!") end - it 'ca returns review text' do - expect(@api.product_reviews(product_id, countries)[1].reviews[0].review).to eq("Work data at my fingertips. Less need to be at the office.") + it 'returns review stars' do + expect(@api.product_reviews(product_id).reviews[0].stars).to eq("5.00") end -end +end \ No newline at end of file From 4a51037096695e2b093af08ec60b3ba06536b1d4 Mon Sep 17 00:00:00 2001 From: "halshura@gmail.com" Date: Mon, 11 May 2015 11:34:57 -0600 Subject: [PATCH 10/18] finished upgrading to v2 api and updated tests --- lib/appfigures.rb | 24 +++++++++-------- spec/product_sales_spec.rb | 54 +++++++++++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 23 deletions(-) diff --git a/lib/appfigures.rb b/lib/appfigures.rb index ba492ff..0c66a67 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -11,15 +11,18 @@ def initialize(options = {}) end def product_sales - self.connection.get('sales/products').body.map do |id, hash| + url = 'reports/sales' + options = {group_by: 'product'} + + self.connection.get(url, options).body.map do |id, hash| Hashie::Mash.new({ 'product_id' => hash['product']['id'], 'store_id' => hash['product']['store_id'], - 'store_name' => hash['product']['store_name'], + 'store_name' => hash['product']['store'], 'name' => hash['product']['name'], 'sku' => hash['product']['sku'], 'ref_no' => hash['product']['ref_no'], - 'added_timestamp' => Date.parse(hash['product']['added_timestamp']), + 'added_timestamp' => Date.parse(hash['product']['source']['added_timestamp']), 'icon' => hash['product']['icon'], 'downloads' => hash['downloads'].to_i, 'returns' => hash['returns'].to_i, @@ -28,21 +31,20 @@ def product_sales 'promos' => hash['promos'].to_i, 'gift_redemptions'=> hash['gift_redemptions'].to_i, 'revenue' => hash['revenue'].to_f, - 'active' => hash['product']['active'] + 'active' => hash['product']['source']['active'] }) end end - # GET /sales/dates+products/2013-03-01/2013-03-31 - # See http://docs.appfigures.com/api/reference/v1-1/sales + # GET /reports/sales/dates+products?start=2013-03-01&end=2013-03-31 + # See http://docs.appfigures.com/api/reference/v2/sales def date_sales(start_date, end_date, options = {}) url = "reports/sales/dates+products" options = {start: start_date.strftime('%Y-%m-%d'), end: start_date.strftime('%Y-%m-%d')}.merge(options) - #url = "sales/dates+products/#{start_date.strftime('%Y-%m-%d')}/#{end_date.strftime('%Y-%m-%d')}#{options.to_query_string(true)}" self.connection.get(url, options).body.map do |date, product| product.map do |product_id, hash| Hashie::Mash.new({ @@ -60,8 +62,8 @@ def date_sales(start_date, end_date, options = {}) end end - # GET /sales/country/{start_date}/{end_date}?data_source={data_source}&products={product_ids}&country={country}&format={format} - # See http://docs.appfigures.com/api/reference/v1-1/sales + # GET /reports/sales?group_by=country&start=start_date&end=end_date + # See http://docs.appfigures.com/api/reference/v2/sales def country_sales(start_date, end_date, options = {}) url = "reports/sales" options = {group_by: 'country', @@ -83,8 +85,8 @@ def country_sales(start_date, end_date, options = {}) end end - # GET /reviews/{productId}/{countries}/{page}/?language={language} - # See http://docs.appfigures.com/api/reference/v1-1/reviews + # GET /reviews?products={productId}&lang=en + # See http://docs.appfigures.com/api/reference/v2/reviews def product_reviews(product_id, options = {}) url = "reviews" options = {products: product_id, diff --git a/spec/product_sales_spec.rb b/spec/product_sales_spec.rb index d3d6dc9..ba13e80 100644 --- a/spec/product_sales_spec.rb +++ b/spec/product_sales_spec.rb @@ -25,29 +25,59 @@ "net_downloads": 26, "promos": 1, "revenue": "100.99", + "edu_downloads": 0, + "gifts": 0, "gift_redemptions": 10, "product": { "id": 123123, - "ref_no": "536354432", - "external_account_id": 397, - "store_id": 0, - "store_name": "apple", - "added_timestamp": "2012-07-23T00:00:00", "name": "Test App", + "developer": "Test Inc", "icon": "http://a5.mzstatic.com/us/r1000/091/Purple/v4/20/69/65/20696562-4e19-17fe-5ffe-cb77a78e1651/mzl.jtpselsb.png", - "active": true, - "hidden": false, + "vendor_identifier": "23292092", + "ref_no": "536354432", "sku": "TEST_APP", - "in_apps": [], - "product_type": "app", - "addons": [] - } + "package_name": null, + "store_id": 0, + "store": "apple", + "storefront": "apple:ios", + "release_date": "2010-12-14T05:00:00", + "added_date": "2011-11-30T13:02:38", + "updated_date": "2015-05-06T09:00:53", + "version": "3.8.0", + "source": { + "external_account_id": 397, + "added_timestamp": "2012-07-23T00:00:00", + "active": true, + "hidden": false, + "type": "own" + }, + "type": "app", + "devices": [ + "Handheld", + "Tablet" + ], + "bundle_identifier": "com.appfigures.test", + "accessible_features": [ + "sales", + "reviews", + "reviews_count", + "ranks", + "featured" + ], + "children": [], + "features": [], + "parent_id": null, + "storefronts": [ + "apple:ios" + ] + }, + "product_id": 6403600 } } EOF @api = Appfigures.new username: 'test', password: 'test', client_key: 'test' @stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/v2/sales/products') { [status_code, headers, body] } + stub.get('/v2/reports/sales?group_by=product') { [status_code, headers, body] } end @api.connection.adapter :test, @stubs end From efa1ac5328c6a8e796278fb79e89cc696ccae925 Mon Sep 17 00:00:00 2001 From: "halshura@gmail.com" Date: Mon, 11 May 2015 13:41:41 -0600 Subject: [PATCH 11/18] fix start date bug with date_sales --- lib/appfigures.rb | 3 ++- spec/date_sales_spec.rb | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/appfigures.rb b/lib/appfigures.rb index 0c66a67..61319ca 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -10,6 +10,7 @@ def initialize(options = {}) @connection = Appfigures::Connection.new options[:username], options[:password], options[:client_key] end + #https://api.appfigures.com/v2/reports/sales/?group_by=product&client_key=c0725e4c875b412fbca6b12b5db44a4e def product_sales url = 'reports/sales' options = {group_by: 'product'} @@ -43,7 +44,7 @@ def date_sales(start_date, end_date, options = {}) url = "reports/sales/dates+products" options = {start: start_date.strftime('%Y-%m-%d'), - end: start_date.strftime('%Y-%m-%d')}.merge(options) + end: end_date.strftime('%Y-%m-%d')}.merge(options) self.connection.get(url, options).body.map do |date, product| product.map do |product_id, hash| diff --git a/spec/date_sales_spec.rb b/spec/date_sales_spec.rb index b1800d3..45980b4 100644 --- a/spec/date_sales_spec.rb +++ b/spec/date_sales_spec.rb @@ -46,14 +46,14 @@ @api = Appfigures.new username: 'test', password: 'test', client_key: 'test' @stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/v2/reports/sales/dates+products?end=2012-09-01&products=223123&start=2012-09-01') { [status_code, headers, body223123] } - stub.get('/v2/reports/sales/dates+products?end=2012-09-01&start=2012-09-01') { [status_code, headers, body] } + stub.get('/v2/reports/sales/dates+products?end=2012-09-30&products=223123&start=2012-09-01') { [status_code, headers, body223123] } + stub.get('/v2/reports/sales/dates+products?end=2012-09-30&start=2012-09-01') { [status_code, headers, body] } end @api.connection.adapter :test, @stubs end let(:start_date) { Date.parse('2012-09-01') } - let(:end_date) { Date.parse('2012-09-01') } + let(:end_date) { Date.parse('2012-09-30') } it 'returns a product ID' do expect(@api.date_sales(start_date, end_date).first.product_id).to eq(123123) From 9133820a9d5344f016c93ada0a40ea879622a05f Mon Sep 17 00:00:00 2001 From: "halshura@gmail.com" Date: Mon, 11 May 2015 14:45:43 -0600 Subject: [PATCH 12/18] remove old commented out code --- lib/appfigures.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/appfigures.rb b/lib/appfigures.rb index 61319ca..1c96054 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -93,9 +93,7 @@ def product_reviews(product_id, options = {}) options = {products: product_id, lang: 'en' }.merge(options) - #url = "reviews/#{product_id}/#{countries}/#{page}#{options.to_query_string(true)}" response = self.connection.get(url, options).body - reviews = Hashie::Mash.new({ 'total' => response['total'].to_i, 'pages' => response['pages'].to_i, From c96e91981208253ff798403912da90b8046c582a Mon Sep 17 00:00:00 2001 From: "halshura@gmail.com" Date: Mon, 11 May 2015 16:19:32 -0600 Subject: [PATCH 13/18] add product ratings api --- lib/appfigures.rb | 16 +++++++-- spec/ratings_spec.rb | 78 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 spec/ratings_spec.rb diff --git a/lib/appfigures.rb b/lib/appfigures.rb index 1c96054..6bfecb2 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -114,8 +114,18 @@ def product_reviews(product_id, options = {}) }) end - - - + # GET /ratings?group_by=product&products={productId} + def product_ratings(product_id, options = {}) + url = "ratings" + options = {group_by: 'product', + products: product_id}.merge(options) + self.connection.get(url, options).body.map do |product, hash| + Hashie::Mash.new({ + 'breakdown' => hash['breakdown'], + 'average' => hash['average'], + 'product_id' => hash['product_id'] + }) + end.first + end end diff --git a/spec/ratings_spec.rb b/spec/ratings_spec.rb new file mode 100644 index 0000000..c2881f3 --- /dev/null +++ b/spec/ratings_spec.rb @@ -0,0 +1,78 @@ +require 'spec_helper' + +describe 'Appfigures country sales' do + before do + status_code = 200 + headers = { + 'Cache-Control' => 'private', + 'Content-Type' => 'application/json', + 'Server' => 'Microsoft-IIS/7.5', + 'X-AspNetMvc-Version' => '2.0', + 'X-Request-Limit' => '1000', + 'X-Request-Usage' => '4', + 'X-AspNet-Version' => '4.0.30319', + 'X-Server-ID' => '10', + 'Date' => 'Tue, 24 Jul 2012 19:56:51 GMT', + 'Connection' => 'close', + 'Transfer-Encoding' => 'Identity' + } + body = <<-EOF +{ + "5556625": { + "breakdown": [ + 874, + 276, + 460, + 690, + 2300 + ], + "observed": false, + "average": "3.71", + "product": { + "id": 5556625, + "name": "Plastic Surgery w/ Dr. Miller", + "developer": "Pixineers Inc", + "icon": "https://lh6.ggpht.com/jrfahsvasiddXZkGi3HOl8nBRpk8ADqSmje_FFHZG5b-YMOC1aqX1WJSUMoPuY98jY3J", + "vendor_identifier": "com.pixineers.philipmiller", + "ref_no": null, + "sku": "com.pixineers.philipmiller", + "package_name": "com.pixineers.philipmiller", + "store_id": 2, + "store": "google_play", + "storefront": "google_play", + "release_date": "2011-12-02T19:21:57", + "added_date": "2011-12-02T19:21:57", + "updated_date": "2015-05-11T09:08:22", + "version": " 1.9.4 ", + "source": null, + "type": "app", + "devices": [ + "Handheld" + ], + "bundle_identifier": "com.pixineers.philipmiller" + }, + "product_id": 5556625 + } +} + EOF + @api = Appfigures.new username: 'test', password: 'test', client_key: 'test' + @stubs = Faraday::Adapter::Test::Stubs.new do |stub| + stub.get('/v2/ratings?group_by=product&products=5556625') { [status_code, headers, body] } + end + @api.connection.adapter :test, @stubs + end + + let(:product_id) { "5556625" } + + it 'returns star breakdown' do + expect(@api.product_ratings(product_id).breakdown).to eq([874, 276, 460, 690, 2300]) + end + + it 'returns average' do + expect(@api.product_ratings(product_id).average).to eq("3.71") + end + + + + +end From e5965a8550a8e2ab66c63675d7b0fad6d53d4780 Mon Sep 17 00:00:00 2001 From: Hisham A Date: Sun, 1 Nov 2015 21:50:05 -0500 Subject: [PATCH 14/18] update to new product ratings api --- lib/appfigures.rb | 7 +++--- spec/ratings_spec.rb | 58 +++++++++++++------------------------------- 2 files changed, 21 insertions(+), 44 deletions(-) diff --git a/lib/appfigures.rb b/lib/appfigures.rb index 6bfecb2..92e132f 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -120,10 +120,11 @@ def product_ratings(product_id, options = {}) options = {group_by: 'product', products: product_id}.merge(options) self.connection.get(url, options).body.map do |product, hash| + puts product + puts hash Hashie::Mash.new({ - 'breakdown' => hash['breakdown'], - 'average' => hash['average'], - 'product_id' => hash['product_id'] + 'stars' => product['stars'], + 'product' => product['product'] }) end.first end diff --git a/spec/ratings_spec.rb b/spec/ratings_spec.rb index c2881f3..621ce56 100644 --- a/spec/ratings_spec.rb +++ b/spec/ratings_spec.rb @@ -17,59 +17,35 @@ 'Transfer-Encoding' => 'Identity' } body = <<-EOF -{ - "5556625": { - "breakdown": [ - 874, - 276, - 460, - 690, - 2300 - ], - "observed": false, - "average": "3.71", - "product": { - "id": 5556625, - "name": "Plastic Surgery w/ Dr. Miller", - "developer": "Pixineers Inc", - "icon": "https://lh6.ggpht.com/jrfahsvasiddXZkGi3HOl8nBRpk8ADqSmje_FFHZG5b-YMOC1aqX1WJSUMoPuY98jY3J", - "vendor_identifier": "com.pixineers.philipmiller", - "ref_no": null, - "sku": "com.pixineers.philipmiller", - "package_name": "com.pixineers.philipmiller", - "store_id": 2, - "store": "google_play", - "storefront": "google_play", - "release_date": "2011-12-02T19:21:57", - "added_date": "2011-12-02T19:21:57", - "updated_date": "2015-05-11T09:08:22", - "version": " 1.9.4 ", - "source": null, - "type": "app", - "devices": [ - "Handheld" - ], - "bundle_identifier": "com.pixineers.philipmiller" - }, - "product_id": 5556625 +[ + { + "product": 6239092, + "date": "2015-11-01T00:00:00", + "stars": [ + 16, + 4, + 5, + 8, + 29 + ] } -} +] EOF @api = Appfigures.new username: 'test', password: 'test', client_key: 'test' @stubs = Faraday::Adapter::Test::Stubs.new do |stub| - stub.get('/v2/ratings?group_by=product&products=5556625') { [status_code, headers, body] } + stub.get('/v2/ratings?group_by=product&products=6239092') { [status_code, headers, body] } end @api.connection.adapter :test, @stubs end - let(:product_id) { "5556625" } + let(:product_id) { "6239092" } it 'returns star breakdown' do - expect(@api.product_ratings(product_id).breakdown).to eq([874, 276, 460, 690, 2300]) + expect(@api.product_ratings(product_id).stars).to eq([16, 4, 5, 8, 29]) end - it 'returns average' do - expect(@api.product_ratings(product_id).average).to eq("3.71") + it 'returns product' do + expect(@api.product_ratings(product_id).product).to eq(product_id.to_i) end From a92bbd2c1fb51e94530ecfe43ce4a0c06741008a Mon Sep 17 00:00:00 2001 From: Hisham A Date: Mon, 2 Nov 2015 15:26:26 -0500 Subject: [PATCH 15/18] by default get ratings for today (latest date) --- lib/appfigures.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/appfigures.rb b/lib/appfigures.rb index 92e132f..4e1b9b2 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -114,14 +114,17 @@ def product_reviews(product_id, options = {}) }) end - # GET /ratings?group_by=product&products={productId} + # GET /ratings?group_by=product&start_date={today}&end_date={today}products={productId} def product_ratings(product_id, options = {}) url = "ratings" + now = Time.now + today = Date.new(now.year, now.month, now.day).strftime('%Y-%m-%d') + options = {group_by: 'product', - products: product_id}.merge(options) + products: product_id, + start_date: today, + end_date: today}.merge(options) self.connection.get(url, options).body.map do |product, hash| - puts product - puts hash Hashie::Mash.new({ 'stars' => product['stars'], 'product' => product['product'] From ef63629ee0051851b6b9c4827b84e7e0ae0d012e Mon Sep 17 00:00:00 2001 From: Hisham Al-Shurafa Date: Fri, 5 May 2017 10:38:50 -0600 Subject: [PATCH 16/18] updated comment --- lib/appfigures.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/appfigures.rb b/lib/appfigures.rb index 4e1b9b2..0f316c4 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -38,7 +38,7 @@ def product_sales end - # GET /reports/sales/dates+products?start=2013-03-01&end=2013-03-31 + # GET /reports/sales/dates+products?start=2017-03-01&end=2017-03-31&products=6403600 # See http://docs.appfigures.com/api/reference/v2/sales def date_sales(start_date, end_date, options = {}) url = "reports/sales/dates+products" From 4cec25189ca2c3176dfbf03234a0e8066f357b31 Mon Sep 17 00:00:00 2001 From: Chris Kinzel Date: Tue, 27 Feb 2018 12:55:33 -0700 Subject: [PATCH 17/18] Updated appfigures methods to detect service errors and print them, fixed bug with unit tests --- lib/appfigures.rb | 161 +++++++++++++++++++++++++++----------------- spec/spec_helper.rb | 2 +- 2 files changed, 102 insertions(+), 61 deletions(-) diff --git a/lib/appfigures.rb b/lib/appfigures.rb index 0f316c4..81f6be0 100644 --- a/lib/appfigures.rb +++ b/lib/appfigures.rb @@ -3,6 +3,7 @@ require 'utils/hash_extensions' require 'date' +require 'json' class Appfigures attr_reader :connection @@ -15,25 +16,32 @@ def product_sales url = 'reports/sales' options = {group_by: 'product'} - self.connection.get(url, options).body.map do |id, hash| - Hashie::Mash.new({ - 'product_id' => hash['product']['id'], - 'store_id' => hash['product']['store_id'], - 'store_name' => hash['product']['store'], - 'name' => hash['product']['name'], - 'sku' => hash['product']['sku'], - 'ref_no' => hash['product']['ref_no'], - 'added_timestamp' => Date.parse(hash['product']['source']['added_timestamp']), - 'icon' => hash['product']['icon'], - 'downloads' => hash['downloads'].to_i, - 'returns' => hash['returns'].to_i, - 'updates' => hash['updates'].to_i, - 'net_downloads' => hash['net_downloads'].to_i, - 'promos' => hash['promos'].to_i, - 'gift_redemptions'=> hash['gift_redemptions'].to_i, - 'revenue' => hash['revenue'].to_f, - 'active' => hash['product']['source']['active'] - }) + response = self.connection.get(url, options) + response.body.map do |id, hash| + if response.status == 200 + Hashie::Mash.new({ + 'product_id' => hash['product']['id'], + 'store_id' => hash['product']['store_id'], + 'store_name' => hash['product']['store'], + 'name' => hash['product']['name'], + 'sku' => hash['product']['sku'], + 'ref_no' => hash['product']['ref_no'], + 'added_timestamp' => Date.parse(hash['product']['source']['added_timestamp']), + 'icon' => hash['product']['icon'], + 'downloads' => hash['downloads'].to_i, + 'returns' => hash['returns'].to_i, + 'updates' => hash['updates'].to_i, + 'net_downloads' => hash['net_downloads'].to_i, + 'promos' => hash['promos'].to_i, + 'gift_redemptions'=> hash['gift_redemptions'].to_i, + 'revenue' => hash['revenue'].to_f, + 'active' => hash['product']['source']['active'] + }) + else + puts 'Appfigures service error:' + puts hash.to_json + Hashie::Mash.new + end end end @@ -46,20 +54,29 @@ def date_sales(start_date, end_date, options = {}) options = {start: start_date.strftime('%Y-%m-%d'), end: end_date.strftime('%Y-%m-%d')}.merge(options) - self.connection.get(url, options).body.map do |date, product| - product.map do |product_id, hash| - Hashie::Mash.new({ - 'date' => Date.parse(date), - 'product_id' => hash['product_id'].to_i, - 'downloads' => hash['downloads'].to_i, - 'returns' => hash['returns'].to_i, - 'updates' => hash['updates'].to_i, - 'net_downloads' => hash['net_downloads'].to_i, - 'promos' => hash['promos'].to_i, - 'gift_redemptions'=> hash['gift_redemptions'].to_i, - 'revenue' => hash['revenue'].to_f - }) - end.first + response = self.connection.get(url, options) + if response.status == 200 + response.body.map do |date, product| + product.map do |product_id, hash| + Hashie::Mash.new({ + 'date' => Date.parse(date), + 'product_id' => hash['product_id'].to_i, + 'downloads' => hash['downloads'].to_i, + 'returns' => hash['returns'].to_i, + 'updates' => hash['updates'].to_i, + 'net_downloads' => hash['net_downloads'].to_i, + 'promos' => hash['promos'].to_i, + 'gift_redemptions'=> hash['gift_redemptions'].to_i, + 'revenue' => hash['revenue'].to_f + }) + end.first + end + else + response.body.map do |id, hash| + puts 'Appfigures service error:' + puts hash.to_json + Hashie::Mash.new + end end end @@ -71,8 +88,11 @@ def country_sales(start_date, end_date, options = {}) start: start_date.strftime('%Y-%m-%d'), end: end_date.strftime('%Y-%m-%d')}.merge(options) #"/?group_by=country&start=#{start_date.strftime('%Y-%m-%d')}/#{end_date.strftime('%Y-%m-%d')}#{options.to_query_string(true)}" - self.connection.get(url, options).body.map do |country, hash| - Hashie::Mash.new({ + + response = self.connection.get(url, options) + response.body.map do |country, hash| + if response.status == 200 + Hashie::Mash.new({ 'iso' => hash['iso'], 'country' => hash['country'], 'downloads' => hash['downloads'], @@ -82,7 +102,12 @@ def country_sales(start_date, end_date, options = {}) 'promos' => hash['promos'], 'revenue' => hash['revenue'], 'gift_redemptions' => hash['gift_redemptions'], - }) + }) + else + puts 'Appfigures service error:' + puts hash.to_json + Hashie::Mash.new + end end end @@ -93,25 +118,33 @@ def product_reviews(product_id, options = {}) options = {products: product_id, lang: 'en' }.merge(options) - response = self.connection.get(url, options).body - reviews = Hashie::Mash.new({ - 'total' => response['total'].to_i, - 'pages' => response['pages'].to_i, - 'this_page' => response['this_page'].to_i, - 'reviews' => response['reviews'].map do |review| - Hashie::Mash.new({ - 'author' => review['author'], - 'title' => review['title'], - 'review' => review['review'], - 'stars' => review['stars'], - 'iso' => review['iso'], - 'version' => review['version'], - 'date' => review['date'], - 'product' => review['product'], - 'id' => review['id'] - }) - end - }) + + response = self.connection.get(url, options) + if response.status == 200 + body = response.body + reviews = Hashie::Mash.new({ + 'total' => body['total'].to_i, + 'pages' => body['pages'].to_i, + 'this_page' => body['this_page'].to_i, + 'reviews' => body['reviews'].map do |review| + Hashie::Mash.new({ + 'author' => review['author'], + 'title' => review['title'], + 'review' => review['review'], + 'stars' => review['stars'], + 'iso' => review['iso'], + 'version' => review['version'], + 'date' => review['date'], + 'product' => review['product'], + 'id' => review['id'] + }) + end + }) + else + puts 'Appfigures service error:' + puts response.body.to_json + return Hashie::Mash.new + end end # GET /ratings?group_by=product&start_date={today}&end_date={today}products={productId} @@ -124,11 +157,19 @@ def product_ratings(product_id, options = {}) products: product_id, start_date: today, end_date: today}.merge(options) - self.connection.get(url, options).body.map do |product, hash| - Hashie::Mash.new({ - 'stars' => product['stars'], - 'product' => product['product'] - }) + + response = self.connection.get(url, options) + response.body.map do |product, hash| + if response.status == 200 + Hashie::Mash.new({ + 'stars' => product['stars'], + 'product' => product['product'] + }) + else + puts 'Appfigures service error:' + puts hash.to_json + return Hashie::Mash.new + end end.first end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6d7c93a..b7e15b5 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -7,6 +7,6 @@ require 'appfigures' RSpec.configure do |config| - config.color_enabled = true + config.color = true config.formatter = 'documentation' end From 607689106e31f8ad93a8e4276aec7e5538a23684 Mon Sep 17 00:00:00 2001 From: Chris Kinzel Date: Tue, 27 Feb 2018 14:09:51 -0700 Subject: [PATCH 18/18] Updated Faraday --- Gemfile.lock | 5 ++++- lib/appfigures/connection.rb | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 39a64f4..f6b3c9e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -11,7 +11,7 @@ GEM remote: https://rubygems.org/ specs: diff-lcs (1.1.3) - faraday (0.9.0) + faraday (0.9.2) multipart-post (>= 1.2, < 3) faraday_middleware (0.9.1) faraday (>= 0.7.4, < 0.10) @@ -35,3 +35,6 @@ DEPENDENCIES appfigures! rake rspec (>= 2.11) + +BUNDLED WITH + 1.16.1 diff --git a/lib/appfigures/connection.rb b/lib/appfigures/connection.rb index 5230f14..f515b21 100644 --- a/lib/appfigures/connection.rb +++ b/lib/appfigures/connection.rb @@ -8,8 +8,8 @@ class Connection < Faraday::Connection def initialize(username, password, client_key) super('https://api.appfigures.com/v2/') do |builder| builder.use FaradayMiddleware::EncodeJson - builder.adapter Faraday.default_adapter builder.response :json, :content_type => /\bjson$/ + builder.adapter Faraday.default_adapter end self.basic_auth username, password