grepdata_client 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in grepdata_client.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Dustin Chang
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
+ # GrepdataClient
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'grepdata_client'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install grepdata_client
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,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'grepdata_client/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "grepdata_client"
8
+ spec.version = GrepdataClient::VERSION
9
+ spec.authors = ["Dustin Chang"]
10
+ spec.email = ["dustin@grepdata.com"]
11
+ spec.description = %q{Ruby client to query Grepdata API}
12
+ spec.summary = %q{Ruby client to query Grepdata API}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "typhoeus",'~> 0.6.3'
22
+ spec.add_dependency "json", '~> 1.8' if RUBY_VERSION < '1.9'
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ end
@@ -0,0 +1,20 @@
1
+ module GrepdataClient
2
+ class DataRequest
3
+ attr_reader :request, :url, :params, :headers, :action
4
+
5
+ def initialize(action, options)
6
+ @action = action.to_s
7
+ @url = "#{options[:url]}/#{@action}"
8
+ @params = options[:params] || {}
9
+ @headers = options[:headers] || {}
10
+
11
+ params = Utils.format_params @action, @params
12
+
13
+ @request = ::Typhoeus::Request.new(@url, params: params, headers: @headers)
14
+ end
15
+
16
+ def get_result
17
+ return @request.response.body
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,70 @@
1
+ module GrepdataClient
2
+ module Utils
3
+ def self.date_format
4
+ "%Y%m%d%H%M"
5
+ end
6
+
7
+ def self.default_expiration
8
+ (Time.now.utc + (24*60*60)).strftime Utils.date_format
9
+ end
10
+
11
+ def self.generate_key(api_key, options)
12
+ identity = "#{options[:datamart]}\n"
13
+ identity += "#{options[:values]}\n" if options[:values].length > 0
14
+ identity += options[:expiration]
15
+
16
+ #hash identity using HMAC-SHA1. return as base64 encoded string
17
+ Base64.encode64(OpenSSL::HMAC.digest('sha1', api_key, identity)).chomp
18
+ end
19
+
20
+ def self.check_attributes(name, options)
21
+ params = options[:params]
22
+ required = options[:required]
23
+
24
+ missing = []
25
+ required.each_key do |key|
26
+ if not params[key].is_a? required[key]
27
+ message = "#{name} missing required attribute #{key.to_s} of type #{required[key].name}"
28
+ missing.push message
29
+ puts "Warning: #{message}"
30
+ end
31
+ end
32
+ raise "Error: #{name} missing required attributes" if missing.length > 0
33
+ end
34
+
35
+ def self.preprocess_dates(params, attributes)
36
+ attributes.each do |attr|
37
+ date = DateTime.parse params[attr]
38
+ params[attr] = date.strftime Utils.date_format
39
+ end
40
+ end
41
+
42
+ def self.format_params(action, params)
43
+ result = {}
44
+ result[:endpoint] = params[:endpoint] if params[:endpoint]
45
+ result[:datamart] = params[:datamart] if params[:datamart]
46
+ result[:metrics] = params[:metrics].join(',') if params[:metrics]
47
+ result[:dimensions] = params[:dimensions].join(',') if params[:dimensions]
48
+ result[:filters] = params[:filters].to_json if params[:filters]
49
+ result[:time_interval] = params[:time_interval] if params[:time_interval]
50
+
51
+ if action == "funneling"
52
+ steps = []
53
+ params[:steps].each do |step|
54
+ step[:start_date] = params[:start_date]
55
+ step[:end_date] = params[:end_date]
56
+ steps.push step
57
+ end
58
+ result[:steps] = { :steps => steps }.to_json
59
+ result[:funnel_dimension] = params[:funnel_dimension]
60
+ else
61
+ result[:start_date] = params[:start_date]
62
+ result[:end_date] = params[:end_date]
63
+ end
64
+
65
+ result[:api_key] = params[:api_key] if params[:api_key]
66
+ result[:token] = params[:token] if params[:token]
67
+ result
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,3 @@
1
+ module GrepdataClient
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,179 @@
1
+ require "typhoeus"
2
+ require 'base64'
3
+ require 'openssl'
4
+ require 'json'
5
+ require 'Date'
6
+
7
+ require "grepdata_client/version"
8
+ require "grepdata_client/query"
9
+ require "grepdata_client/utils"
10
+
11
+ module GrepdataClient
12
+ class Client
13
+
14
+ attr_accessor :api_url, :api_key, :token, :parallel, :parallel_manager
15
+
16
+ CONFIG = {
17
+ :api_url => "https://api.grepdata.com/v1",
18
+ }
19
+
20
+ def initialize(config)
21
+ @api_key, @token = config.values_at(:api_key, :token)
22
+ @api_url = config[:api_url] || CONFIG[:api_url]
23
+ @parallel = config[:parallel] || false
24
+ if config[:parallel_manager]
25
+ @parallel_manager = config[:parallel_manager]
26
+ end
27
+ end
28
+
29
+ def query(params)
30
+ params[:api_key] = params[:api_key] || @api_key
31
+ params[:filters] = params[:filters] || {}
32
+
33
+ Utils.preprocess_dates params, [:start_date, :end_date]
34
+
35
+ Utils.check_attributes "params",
36
+ params: params,
37
+ required: {
38
+ api_key: String,
39
+ datamart: String,
40
+ dimensions: Array,
41
+ metrics: Array,
42
+ filters: Hash,
43
+ time_interval: String,
44
+ start_date: String,
45
+ end_date: String
46
+ }
47
+
48
+ request(__method__, params: params)
49
+ end
50
+
51
+ def funneling(params)
52
+ params[:api_key] = params[:api_key] || @api_key
53
+ params[:filters] = params[:filters] || {}
54
+ params[:only_totals] = params[:only_totals] || false
55
+
56
+ Utils.preprocess_dates params, [:start_date, :end_date]
57
+
58
+ Utils.check_attributes "params",
59
+ params: params,
60
+ required: {
61
+ api_key: String,
62
+ datamart: String,
63
+ funnel_dimension: String,
64
+ dimensions: Array,
65
+ metrics: Array,
66
+ filters: Hash,
67
+ time_interval: String,
68
+ start_date: String,
69
+ end_date: String,
70
+ steps: Array
71
+ }
72
+
73
+ request(__method__, params: params)
74
+ end
75
+
76
+ def dimensions(params)
77
+ params[:api_key] = params[:api_key] || @api_key
78
+
79
+ Utils.check_attributes "params",
80
+ params: params,
81
+ required: {
82
+ api_key: String,
83
+ endpoint: String
84
+ }
85
+
86
+ request(__method__, params: params)
87
+ end
88
+
89
+ def query_with_token(params, access_key)
90
+ params[:token] = params[:token] || @token
91
+ params[:filters] = params[:filters] || {}
92
+
93
+ Utils.preprocess_dates params, [:start_date, :end_date]
94
+ Utils.preprocess_dates access_key, [:expiration]
95
+
96
+ Utils.check_attributes "params",
97
+ params: params,
98
+ required: {
99
+ token: String,
100
+ datamart: String,
101
+ dimensions: Array,
102
+ metrics: Array,
103
+ filters: Hash,
104
+ time_interval: String,
105
+ start_date: String,
106
+ end_date: String
107
+ }
108
+
109
+ Utils.check_attributes "access_key",
110
+ params: access_key,
111
+ required: {
112
+ signature: String,
113
+ restricted: String,
114
+ expiration: String
115
+ }
116
+
117
+ request('fetch', params: params, headers: access_key)
118
+ end
119
+
120
+ def run_requests
121
+ @parallel_manager.run if @parallel_manager
122
+ end
123
+
124
+ def request(action, options)
125
+ query = GrepdataClient::DataRequest.new action,
126
+ url: @api_url,
127
+ params: options[:params],
128
+ headers: options[:headers]
129
+
130
+ if @parallel
131
+ unless @parallel_manager
132
+ @parallel_manager = ::Typhoeus::Hydra.new
133
+ end
134
+ @parallel_manager.queue query.request
135
+ else
136
+ query.request.run
137
+ end
138
+
139
+ return query
140
+ end
141
+
142
+ def generate_access_key(api_key, options)
143
+ restricted = options[:restricted] || []
144
+ expiration = options[:expiration] || Utils.default_expiration
145
+
146
+ params = options[:params] || options[:request].params
147
+ params = Utils.format_params 'query', params
148
+
149
+ datamart = params[:datamart]
150
+
151
+ values = ""
152
+ restricted.each do |param|
153
+ value = params
154
+ segments = param.split(".")
155
+ segments.each do |segment|
156
+ value = JSON.parse value if value.is_a? String
157
+ value = value[segment.to_sym] || value[segment]
158
+ end
159
+ value = segments.length > 1? value.to_json : value.to_s
160
+ values += "&" if values.length > 0
161
+ values += "#{param}=#{value}"
162
+ end
163
+
164
+ scope = "datamart=#{datamart}"
165
+ scope += "&#{values}" if
166
+ signature = Utils.generate_key(api_key,
167
+ datamart: datamart,
168
+ values: values,
169
+ expiration: expiration)
170
+
171
+ return {
172
+ :signature => signature,
173
+ :restricted => restricted.join(','),
174
+ :expiration => expiration.to_s,
175
+ :scope => scope
176
+ }
177
+ end
178
+ end
179
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grepdata_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dustin Chang
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: typhoeus
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.6.3
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.6.3
30
+ - !ruby/object:Gem::Dependency
31
+ name: bundler
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.3'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.3'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Ruby client to query Grepdata API
63
+ email:
64
+ - dustin@grepdata.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - grepdata_client.gemspec
75
+ - lib/grepdata_client.rb
76
+ - lib/grepdata_client/query.rb
77
+ - lib/grepdata_client/utils.rb
78
+ - lib/grepdata_client/version.rb
79
+ homepage: ''
80
+ licenses:
81
+ - MIT
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ! '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 1.8.25
101
+ signing_key:
102
+ specification_version: 3
103
+ summary: Ruby client to query Grepdata API
104
+ test_files: []