active_campaign 0.0.12 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3ef07b98e74c5fb735346d1892c8bd3a8b0a6ad3
4
- data.tar.gz: 0d77124c85dab81705442adfc9af3fab78530b0e
3
+ metadata.gz: b1cbb2b00815af672e7667806db753a74683784e
4
+ data.tar.gz: 2ff0355c2990923bd87f48b9f2be58ec7e9ef2f4
5
5
  SHA512:
6
- metadata.gz: 0c91bafde1b49f1ab0ffee41ab454fb39c0a33f835d1766ef9069055b531df8aeaa9bcbee485b9a9c7f3082590306c2983ad60fc8cda5f0bd135c9057f200b33
7
- data.tar.gz: e72487eff7c555c95e7d23474aa60983c5e6b56f79ec237d2f8bde2e56a63675da0d3f845de6cf18430030ff171e2be69435c64a4c4ee743b8a52e350d155c0e
6
+ metadata.gz: cfda3378d4504362d91b75106ef2cc9a5f4b69d8f4713a2cb5a985b733145bb7bb0da56d6c80c012111eea9a6b9cb1004ee9650b78895d2a1bc226c7de5fffdf
7
+ data.tar.gz: 05e9bce0b4936f1286819901cc3d4fcfe6dd669c0d06452f268af4912ce47c1c4c487ef8e9978c9538bf5effcc653b8b3b13ba23e99702f8b7a43d3b542f76a0
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0-p247
data/Gemfile CHANGED
@@ -1,3 +1,29 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem 'jruby-openssl', :platforms => :jruby
4
+ gem 'rake'
5
+
6
+ group :development do
7
+ gem 'awesome_print', :require => 'ap'
8
+ gem 'guard-rspec', '~> 2.5.1'
9
+ gem 'hirb-unicode'
10
+ gem 'pry'
11
+ gem 'redcarpet'
12
+ gem 'wirb'
13
+ gem 'wirble'
14
+ gem 'yard'
15
+ end
16
+
17
+ group :test do
18
+ gem 'coveralls', :require => false
19
+ gem 'json', '~> 1.7', :platforms => [:ruby_18, :jruby]
20
+ gem 'netrc', '~> 0.7.7'
21
+ gem 'rb-fsevent', '~> 0.9'
22
+ gem 'rspec', '~> 2.13.0'
23
+ gem 'simplecov', :require => false
24
+ gem 'test-queue', '~> 0.1.3'
25
+ gem 'vcr', '~> 2.4.0'
26
+ gem 'webmock', '~> 1.9.0'
27
+ end
28
+
3
29
  gemspec
@@ -18,15 +18,10 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "httpclient", "~> 2.3"
22
- spec.add_dependency "hashie", "~> 2.0"
23
- spec.add_dependency "activesupport", ">= 4.0.0"
24
- spec.add_dependency "faraday", "~> 0.8"
25
- spec.add_dependency "faraday_middleware", "~> 0.9"
26
- spec.add_dependency "multi_json", "~> 1.7"
27
- spec.add_dependency 'rake'
28
-
29
- spec.add_development_dependency 'json', '~> 1.7'
30
- spec.add_development_dependency 'rspec', '>= 2.14'
31
- spec.add_development_dependency 'webmock'
21
+ spec.add_dependency "faraday", ">= 0.8.8"
22
+ spec.add_dependency "activesupport", ">= 4.0.0"
23
+ spec.add_dependency "uri_template"
24
+ spec.add_dependency "hashie"
25
+ spec.add_dependency "oj"
26
+ spec.add_development_dependency 'bundler', '~> 1.0'
32
27
  end
@@ -1,31 +1,40 @@
1
- require 'rubygems'
2
1
  require 'active_support/core_ext'
3
- require "active_campaign/version"
4
- require 'active_campaign/configuration'
5
- require 'active_campaign/error'
6
2
  require 'active_campaign/client'
3
+ require 'active_campaign/default'
7
4
 
8
5
  module ActiveCampaign
9
6
 
10
- extend Configuration
11
-
12
7
  class << self
8
+ include ActiveCampaign::Configurable
13
9
 
14
- # Alias for ActiveCampaign::Client.new
10
+ # API client based on configured options {Configurable}
15
11
  #
16
- # @return [ActiveCampaign::Client]
17
- def new(options={})
18
- ActiveCampaign::Client.new(options)
19
- end
12
+ # @return [ActiveCampaign::Client] API wrapper
13
+ def client
14
+ unless defined?(@client) && @client.same_options?(options)
15
+ @client = ActiveCampaign::Client.new(options)
16
+ end
20
17
 
21
- # Delegate to ActiveCampaign::Client.new
22
- def method_missing(method, *args, &block)
23
- return super unless new.respond_to?(method)
24
- new.send(method, *args, &block)
18
+ @client
25
19
  end
26
20
 
27
- def respond_to?(method, include_private=false)
28
- new.respond_to?(method, include_private) || super(method, include_private)
21
+ # @private
22
+ def respond_to_missing?(method_name, include_private=false)
23
+ client.respond_to?(method_name, include_private)
24
+ end if RUBY_VERSION >= "1.9"
25
+
26
+ # @private
27
+ def respond_to?(method_name, include_private=false)
28
+ client.respond_to?(method_name, include_private) || super
29
+ end if RUBY_VERSION < "1.9"
30
+
31
+ private
32
+
33
+ def method_missing(method_name, *args, &block)
34
+ return super unless client.respond_to?(method_name)
35
+ client.send(method_name, *args, &block)
29
36
  end
30
37
  end
38
+
39
+ ActiveCampaign.setup
31
40
  end
@@ -0,0 +1,14 @@
1
+ module ActiveCampaign
2
+
3
+ # Extracts options from method arguments
4
+ # @private
5
+ class Arguments < Array
6
+ attr_reader :options
7
+
8
+ def initialize(args)
9
+ @options = args.last.is_a?(::Hash) ? args.pop : {}
10
+ super(args)
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,68 @@
1
+ module ActiveCampaign
2
+
3
+ # Authentication methods for {ActiveCampaign::Client}
4
+ module Authentication
5
+
6
+ # Indicates if the client was supplied Basic Auth
7
+ # username and password
8
+ #
9
+ # @see http://developer.github.com/v3/#authentication
10
+ # @return [Boolean]
11
+ def basic_authenticated?
12
+ @login && @password
13
+ end
14
+
15
+ # Indicates if the client was supplied an OAuth
16
+ # access token
17
+ #
18
+ # @see http://developer.github.com/v3/#authentication
19
+ # @return [Boolean]
20
+ def token_authenticated?
21
+ !!@access_token
22
+ end
23
+
24
+ # Indicates if the client was supplied an OAuth
25
+ # access token or Basic Auth username and password
26
+ #
27
+ # @see http://developer.github.com/v3/#authentication
28
+ # @return [Boolean]
29
+ def user_authenticated?
30
+ basic_authenticated? || token_authenticated?
31
+ end
32
+
33
+ # Indicates if the client has OAuth Application
34
+ # client_id and secret credentials to make anonymous
35
+ # requests at a higher rate limit
36
+ #
37
+ # @see http://developer.github.com/v3/#unauthenticated-rate-limited-requests
38
+ # @return Boolean
39
+ def application_authenticated?
40
+ !!application_authentication
41
+ end
42
+
43
+ private
44
+
45
+ def application_authentication
46
+ if @client_id && @client_secret
47
+ {
48
+ :client_id => @client_id,
49
+ :client_secret => @client_secret
50
+ }
51
+ end
52
+ end
53
+
54
+ def login_from_netrc
55
+ return unless netrc?
56
+
57
+ require 'netrc'
58
+ info = Netrc.read netrc_file
59
+ netrc_host = URI.parse(api_endpoint).host
60
+ creds = info[netrc_host]
61
+ self.login = creds.shift
62
+ self.password = creds.shift
63
+ rescue LoadError
64
+ warn "Please install netrc gem for .netrc support"
65
+ end
66
+
67
+ end
68
+ end
@@ -1,27 +1,214 @@
1
- require 'active_campaign/connection'
2
- require 'active_campaign/request'
3
-
4
-
1
+ require 'faraday'
2
+ require 'uri_template'
3
+ require 'active_campaign/arguments'
4
+ require 'active_campaign/authentication'
5
+ require 'active_campaign/configurable'
5
6
  require 'active_campaign/client/contacts'
6
7
  require 'active_campaign/client/lists'
7
8
  require 'active_campaign/client/campaigns'
8
9
 
9
10
  module ActiveCampaign
10
11
  class Client
11
- attr_accessor(*Configuration::VALID_OPTIONS_KEYS)
12
+ include ActiveCampaign::Configurable
13
+ include ActiveCampaign::Authentication
14
+ include ActiveCampaign::Client::Contacts
15
+ include ActiveCampaign::Client::Lists
16
+ include ActiveCampaign::Client::Campaigns
17
+
18
+ NO_BODY = Set.new([:get, :head])
19
+ # Header keys that can be passed in options hash to {#get},{#head}
20
+ CONVENIENCE_HEADERS = Set.new [:accept]
12
21
 
13
- def initialize(options={})
14
- options = ActiveCampaign.options.merge(options)
15
- Configuration::VALID_OPTIONS_KEYS.each do |key|
16
- send("#{key}=", options[key])
22
+ def initialize(options = {})
23
+ # Use options passed in, but fall back to module defaults
24
+ ActiveCampaign::Configurable.keys.each do |key|
25
+ instance_variable_set(:"@#{key}", options[key] ||
26
+ ActiveCampaign.instance_variable_get(:"@#{key}"))
17
27
  end
18
28
  end
19
29
 
20
- include ActiveCampaign::Connection
21
- include ActiveCampaign::Request
30
+ # Compares client options to a Hash of requested options
31
+ #
32
+ # @param opts [Hash] Options to compare with current client options
33
+ # @return [Boolean]
34
+ def same_options?(opts)
35
+ opts.hash == options.hash
36
+ end
22
37
 
23
- include ActiveCampaign::Client::Contacts
24
- include ActiveCampaign::Client::Lists
25
- include ActiveCampaign::Client::Campaigns
38
+ # Text representation of the client, masking tokens and passwords
39
+ #
40
+ # @return [String]
41
+ def inspect
42
+ inspected = super
43
+
44
+ # mask password
45
+ inspected = inspected.gsub! @password, "*******" if @password
46
+ # Only show last 4 of token, secret
47
+ if @access_token
48
+ inspected = inspected.gsub! @access_token, "#{'*'*36}#{@access_token[36..-1]}"
49
+ end
50
+ if @client_secret
51
+ inspected = inspected.gsub! @client_secret, "#{'*'*36}#{@client_secret[36..-1]}"
52
+ end
53
+
54
+ inspected
55
+ end
56
+
57
+ # Make a HTTP GET request
58
+ #
59
+ # @param url [String] The path, relative to {#api_endpoint}
60
+ # @param options [Hash] Query and header params for request
61
+ # @return [Sawyer::Resource]
62
+ def get(api_method, options = {})
63
+ request :get, api_method, parse_query_and_convenience_headers(options)
64
+ end
65
+
66
+ # Make a HTTP POST request
67
+ #
68
+ # @param url [String] The path, relative to {#api_endpoint}
69
+ # @param options [Hash] Body and header params for request
70
+ # @return [Sawyer::Resource]
71
+ def post(api_method, options = {})
72
+ request :post, api_method, options
73
+ end
74
+
75
+ # Make a HTTP PUT request
76
+ #
77
+ # @param url [String] The path, relative to {#api_endpoint}
78
+ # @param options [Hash] Body and header params for request
79
+ # @return [Sawyer::Resource]
80
+ def put(api_method, options = {})
81
+ request :put, api_method, options
82
+ end
83
+
84
+ # Make a HTTP PATCH request
85
+ #
86
+ # @param url [String] The path, relative to {#api_endpoint}
87
+ # @param options [Hash] Body and header params for request
88
+ # @return [Sawyer::Resource]
89
+ def patch(api_method, options = {})
90
+ request :patch, api_method, options
91
+ end
92
+
93
+ # Make a HTTP DELETE request
94
+ #
95
+ # @param url [String] The path, relative to {#api_endpoint}
96
+ # @param options [Hash] Query and header params for request
97
+ # @return [Sawyer::Resource]
98
+ def delete(api_method, options = {})
99
+ request :delete, api_method, options
100
+ end
101
+
102
+ # Make a HTTP HEAD request
103
+ #
104
+ # @param url [String] The path, relative to {#api_endpoint}
105
+ # @param options [Hash] Query and header params for request
106
+ # @return [Sawyer::Resource]
107
+ def head(api_method, options = {})
108
+ request :head, api_method, parse_query_and_convenience_headers(options)
109
+ end
110
+
111
+ # Response for last HTTP request
112
+ #
113
+ # @return [Sawyer::Response]
114
+ def last_response
115
+ @last_response
116
+ end
117
+
118
+ private
119
+
120
+ def request(method, api_method, data)
121
+ options = {}
122
+ options[:query] = data.delete(:query) || {}
123
+ options[:headers] = data.delete(:headers) || {}
124
+
125
+ options[:query].merge!({
126
+ api_key: api_key,
127
+ api_action: api_method.to_s,
128
+ api_output: api_output
129
+ })
130
+
131
+ if accept = data.delete(:accept)
132
+ options[:headers][:accept] = accept
133
+ end
134
+
135
+ @last_response = response = process_request(
136
+ method, URI.encode(api_path), data, options
137
+ )
138
+
139
+ response
140
+ end
141
+
142
+ def connection
143
+ @conn ||= Faraday.new do |builder|
144
+
145
+ builder.request :url_encoded
146
+
147
+ builder.response :mashify
148
+ builder.response :json_normalizer
149
+ builder.response :parse_json #, content_type: /\bjson$/
150
+
151
+ if debug
152
+ builder.use :debugger
153
+ builder.use :instrumentation
154
+ end
155
+
156
+ builder.adapter Faraday.default_adapter
157
+ builder.url_prefix = api_endpoint
158
+ end
159
+ # @conn.url_prefix api_endpoint
160
+ @conn
161
+ end
162
+
163
+
164
+ def process_request(method, url, data = {}, options = {})
165
+ if NO_BODY.include?(method)
166
+ options ||= data
167
+ data = nil
168
+ end
169
+ options ||= {}
170
+ url = expand_url(url, options[:uri])
171
+
172
+ res = connection.send method, url do |req|
173
+ req.body = data if data
174
+ if params = options[:query]
175
+ req.params.update params
176
+ end
177
+ if headers = options[:headers]
178
+ req.headers.update headers
179
+ end
180
+ end
181
+ res.body
182
+ end
183
+
184
+ # Executes the request, checking if it was successful
185
+ #
186
+ # @return [Boolean] True on success, false otherwise
187
+ def boolean_from_response(method, path, options = {})
188
+ request(method, path, options)
189
+ @last_response.status == 204
190
+ rescue ActiveCampaign::NotFound
191
+ false
192
+ end
193
+
194
+ def parse_query_and_convenience_headers(options)
195
+ headers = options.fetch(:headers, {})
196
+ CONVENIENCE_HEADERS.each do |h|
197
+ if header = options.delete(h)
198
+ headers[h] = header
199
+ end
200
+ end
201
+ query = options.delete(:query)
202
+ opts = {:query => options}
203
+ opts[:query].merge!(query) if query && query.is_a?(Hash)
204
+ opts[:headers] = headers unless headers.empty?
205
+
206
+ opts
207
+ end
208
+ def expand_url(url, options = nil)
209
+ tpl = url.respond_to?(:expand) ? url : URITemplate.new(url.to_s)
210
+ expand = tpl.method(:expand)
211
+ options ? expand.call(options) : expand.call
212
+ end
26
213
  end
27
214
  end
@@ -0,0 +1,84 @@
1
+ module ActiveCampaign
2
+
3
+ # Configuration options for {Client}, defaulting to values
4
+ # in {Default}
5
+ module Configurable
6
+
7
+ # @!attribute connection_options
8
+ # @see https://github.com/lostisland/faraday
9
+ # @return [Hash] Configure connection options for Faraday
10
+ # @!attribute middleware
11
+ # @see https://github.com/lostisland/faraday
12
+ # @return [Faraday::Builder] Configure middleware for Faraday
13
+ # @!attribute per_page
14
+ # @return [String] Configure page size for paginated results. API default: 30
15
+ # @!attribute user_agent
16
+ # @return [String] Configure User-Agent header for requests.
17
+ # @!attribute web_endpoint
18
+ # @return [String] Base URL for web URLs. default: https://github.com/
19
+
20
+ attr_accessor :api_url, :api_key, :api_output, :api_path, :api_action,
21
+ :list_id, :api_endpoint, :proxy, :user_agent,
22
+ :debug, :per_page, :connection_options,
23
+ :api_endpoint, :auto_paginate,
24
+ :default_media_type, :connection_options,
25
+ :middleware, :user_agent, :web_endpoint
26
+
27
+ attr_writer :client_secret, :password
28
+
29
+ class << self
30
+
31
+ # List of configurable keys for {ActiveCampaign::Client}
32
+ # @return [Array] of option keys
33
+ def keys
34
+ @keys ||= [
35
+ :api_key,
36
+ :api_path,
37
+ :api_output,
38
+ :api_endpoint,
39
+ :user_agent,
40
+ :debug,
41
+ :per_page,
42
+ :connection_options,
43
+ :auto_paginate,
44
+ :default_media_type,
45
+ :connection_options,
46
+ :middleware,
47
+ :user_agent,
48
+ :web_endpoint
49
+ ]
50
+ end
51
+ end
52
+
53
+ # Set configuration options using a block
54
+ def configure
55
+ yield self
56
+ end
57
+
58
+ # Reset configuration options to default values
59
+ def reset!
60
+ ActiveCampaign::Configurable.keys.each do |key|
61
+ instance_variable_set(:"@#{key}", ActiveCampaign::Default.options[key])
62
+ end
63
+ self
64
+ end
65
+ alias setup reset!
66
+
67
+ def api_endpoint
68
+ File.join(@api_endpoint, "")
69
+ end
70
+
71
+ # Base URL for generated web URLs
72
+ #
73
+ # @return [String] Default: https://www.activecampaign.com/
74
+ def web_endpoint
75
+ File.join(@web_endpoint, "")
76
+ end
77
+
78
+ private
79
+
80
+ def options
81
+ Hash[ActiveCampaign::Configurable.keys.map{|key| [key, instance_variable_get(:"@#{key}")]}]
82
+ end
83
+ end
84
+ end