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 +4 -4
- data/.ruby-version +1 -0
- data/Gemfile +26 -0
- data/active_campaign.gemspec +6 -11
- data/lib/active_campaign.rb +26 -17
- data/lib/active_campaign/arguments.rb +14 -0
- data/lib/active_campaign/authentication.rb +68 -0
- data/lib/active_campaign/client.rb +201 -14
- data/lib/active_campaign/configurable.rb +84 -0
- data/lib/active_campaign/default.rb +135 -0
- data/lib/active_campaign/error.rb +93 -27
- data/lib/active_campaign/response/debugger.rb +42 -0
- data/lib/active_campaign/response/instrumentation.rb +33 -0
- data/lib/active_campaign/response/json_normalizer.rb +49 -0
- data/lib/active_campaign/response/mashify.rb +40 -0
- data/lib/active_campaign/response/parse_json.rb +83 -0
- data/lib/active_campaign/response/raise_error.rb +24 -0
- data/lib/active_campaign/version.rb +1 -1
- data/spec/active_campaign_spec.rb +3 -3
- data/spec/helper.rb +1 -1
- metadata +32 -84
- data/lib/active_campaign/configuration.rb +0 -74
- data/lib/active_campaign/connection.rb +0 -52
- data/lib/active_campaign/param_validation.rb +0 -12
- data/lib/active_campaign/request.rb +0 -84
- data/lib/faraday/response/body_logger.rb +0 -37
- data/lib/faraday/response/json_normalizer.rb +0 -46
- data/lib/faraday/response/raise_active_campaign_error.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b1cbb2b00815af672e7667806db753a74683784e
|
4
|
+
data.tar.gz: 2ff0355c2990923bd87f48b9f2be58ec7e9ef2f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/active_campaign.gemspec
CHANGED
@@ -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 "
|
22
|
-
spec.add_dependency "
|
23
|
-
spec.add_dependency "
|
24
|
-
spec.add_dependency "
|
25
|
-
spec.add_dependency "
|
26
|
-
spec.
|
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
|
data/lib/active_campaign.rb
CHANGED
@@ -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
|
-
#
|
10
|
+
# API client based on configured options {Configurable}
|
15
11
|
#
|
16
|
-
# @return [ActiveCampaign::Client]
|
17
|
-
def
|
18
|
-
|
19
|
-
|
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
|
-
|
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
|
-
|
28
|
-
|
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,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 '
|
2
|
-
require '
|
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
|
-
|
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
|
15
|
-
|
16
|
-
|
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
|
-
|
21
|
-
|
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
|
-
|
24
|
-
|
25
|
-
|
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
|