gibbon 1.2.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of gibbon might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +0 -2
- data/CHANGELOG.md +10 -6
- data/README.markdown +45 -149
- data/gibbon.gemspec +9 -7
- data/lib/gibbon.rb +3 -4
- data/lib/gibbon/api_request.rb +167 -0
- data/lib/gibbon/mailchimp_error.rb +1 -1
- data/lib/gibbon/request.rb +65 -0
- data/lib/gibbon/version.rb +2 -2
- data/spec/gibbon/gibbon_spec.rb +40 -240
- metadata +17 -18
- data/lib/gibbon/api.rb +0 -38
- data/lib/gibbon/api_category.rb +0 -110
- data/lib/gibbon/export.rb +0 -106
data/lib/gibbon/api.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
module Gibbon
|
2
|
-
class API
|
3
|
-
attr_accessor :api_key, :api_endpoint, :timeout, :throws_exceptions
|
4
|
-
|
5
|
-
def initialize(api_key = nil, default_parameters = {})
|
6
|
-
@api_key = api_key || self.class.api_key || ENV['MAILCHIMP_API_KEY']
|
7
|
-
@api_key = @api_key.strip if @api_key
|
8
|
-
|
9
|
-
@api_endpoint = default_parameters.delete(:api_endpoint) || self.class.api_endpoint
|
10
|
-
@timeout = default_parameters.delete(:timeout) || self.class.timeout
|
11
|
-
@throws_exceptions = default_parameters.has_key?(:throws_exceptions) ? default_parameters.delete(:throws_exceptions) : self.class.throws_exceptions
|
12
|
-
|
13
|
-
@default_params = {:apikey => @api_key}.merge(default_parameters)
|
14
|
-
end
|
15
|
-
|
16
|
-
def get_exporter
|
17
|
-
Export.new(@api_key, @default_params)
|
18
|
-
end
|
19
|
-
|
20
|
-
def method_missing(method, *args)
|
21
|
-
api = APICategory.new(method.to_s, @api_key, @timeout, @throws_exceptions, @api_endpoint, @default_params)
|
22
|
-
api.api_endpoint = @api_endpoint if @api_endpoint
|
23
|
-
api
|
24
|
-
end
|
25
|
-
|
26
|
-
def respond_to_missing?(method, include_private = false)
|
27
|
-
%w{campaigns ecomm folders gallery lists helper reports templates users vip}.include?(method.to_s) || super
|
28
|
-
end
|
29
|
-
|
30
|
-
class << self
|
31
|
-
attr_accessor :api_key, :timeout, :throws_exceptions, :api_endpoint
|
32
|
-
|
33
|
-
def method_missing(sym, *args, &block)
|
34
|
-
new(self.api_key, {:api_endpoint => self.api_endpoint, :timeout => self.timeout, :throws_exceptions => self.throws_exceptions}).send(sym, *args, &block)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
data/lib/gibbon/api_category.rb
DELETED
@@ -1,110 +0,0 @@
|
|
1
|
-
require 'gibbon/api'
|
2
|
-
|
3
|
-
module Gibbon
|
4
|
-
class APICategory
|
5
|
-
include HTTParty
|
6
|
-
format :plain
|
7
|
-
default_timeout 30
|
8
|
-
|
9
|
-
attr_accessor :category_name, :api_key, :api_endpoint, :timeout, :throws_exceptions, :default_params
|
10
|
-
|
11
|
-
def initialize(category_name, api_key, timeout, throws_exceptions, api_endpoint, default_params)
|
12
|
-
@category_name = category_name
|
13
|
-
@api_key = api_key
|
14
|
-
@api_endpoint = api_endpoint
|
15
|
-
@default_params = default_params
|
16
|
-
@throws_exceptions = throws_exceptions
|
17
|
-
@timeout = timeout
|
18
|
-
|
19
|
-
set_instance_defaults
|
20
|
-
end
|
21
|
-
|
22
|
-
def call(method, params = {})
|
23
|
-
ensure_api_key params
|
24
|
-
|
25
|
-
api_url = base_api_url + method
|
26
|
-
params = @default_params.merge(params).merge({:apikey => @api_key})
|
27
|
-
headers = params.delete(:headers) || {}
|
28
|
-
response = self.class.post(api_url, :body => MultiJson.dump(params), :headers => headers, :timeout => @timeout)
|
29
|
-
|
30
|
-
parse_response(response.body) if response.body
|
31
|
-
end
|
32
|
-
|
33
|
-
def parse_response(response, check_error = true)
|
34
|
-
begin
|
35
|
-
parsed_response = MultiJson.load(response)
|
36
|
-
rescue MultiJson::ParseError
|
37
|
-
parsed_response = {
|
38
|
-
"error" => "Unparseable response: #{response}",
|
39
|
-
"name" => "UNPARSEABLE_RESPONSE",
|
40
|
-
"code" => 500
|
41
|
-
}
|
42
|
-
end
|
43
|
-
|
44
|
-
if should_raise_for_response?(parsed_response)
|
45
|
-
error = MailChimpError.new(parsed_response["error"])
|
46
|
-
error.code = parsed_response["code"]
|
47
|
-
error.name = parsed_response["name"]
|
48
|
-
raise error
|
49
|
-
end
|
50
|
-
parsed_response
|
51
|
-
end
|
52
|
-
|
53
|
-
def method_missing(method, *args)
|
54
|
-
# To support underscores, we replace them with hyphens when calling the API
|
55
|
-
method = method.to_s.gsub("_", "-").downcase
|
56
|
-
call("#{@category_name}/#{method}", *args)
|
57
|
-
end
|
58
|
-
|
59
|
-
def send(*args)
|
60
|
-
if ((args.length > 0) && args[0].is_a?(Hash))
|
61
|
-
method_missing(:send, args[0])
|
62
|
-
else
|
63
|
-
__send__(*args)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def set_instance_defaults
|
68
|
-
@timeout = (API.timeout || 30) if @timeout.nil?
|
69
|
-
# Two lines because the class variable could be false and (false || true) is always true
|
70
|
-
@throws_exceptions = API.throws_exceptions if @throws_exceptions.nil?
|
71
|
-
@throws_exceptions = true if @throws_exceptions.nil?
|
72
|
-
end
|
73
|
-
|
74
|
-
def api_key=(value)
|
75
|
-
@api_key = value.strip if value
|
76
|
-
end
|
77
|
-
|
78
|
-
def should_raise_for_response?(response)
|
79
|
-
@throws_exceptions && response.is_a?(Hash) && response["error"]
|
80
|
-
end
|
81
|
-
|
82
|
-
def base_api_url
|
83
|
-
"#{@api_endpoint || get_api_endpoint}/2.0/"
|
84
|
-
end
|
85
|
-
|
86
|
-
def get_api_endpoint
|
87
|
-
"https://#{get_data_center_from_api_key}api.mailchimp.com"
|
88
|
-
end
|
89
|
-
|
90
|
-
def get_data_center_from_api_key
|
91
|
-
# Return an empty string for invalid API keys so Gibbon hits the main endpoint
|
92
|
-
data_center = ""
|
93
|
-
|
94
|
-
if (@api_key && @api_key["-"])
|
95
|
-
# Add a period since the data_center is a subdomain and it keeps things dry
|
96
|
-
data_center = "#{@api_key.split('-').last}."
|
97
|
-
end
|
98
|
-
|
99
|
-
data_center
|
100
|
-
end
|
101
|
-
|
102
|
-
private
|
103
|
-
|
104
|
-
def ensure_api_key(params)
|
105
|
-
unless @api_key || @default_params[:apikey] || params[:apikey]
|
106
|
-
raise Gibbon::GibbonError, "You must set an api_key prior to making a call"
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
data/lib/gibbon/export.rb
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
module Gibbon
|
2
|
-
class Export < APICategory
|
3
|
-
|
4
|
-
def initialize(api_key = nil, default_params = {})
|
5
|
-
@api_key = api_key
|
6
|
-
@default_params = default_params
|
7
|
-
|
8
|
-
set_instance_defaults
|
9
|
-
end
|
10
|
-
|
11
|
-
protected
|
12
|
-
|
13
|
-
def export_api_url
|
14
|
-
"http://#{get_data_center_from_api_key}api.mailchimp.com/export/1.0/"
|
15
|
-
end
|
16
|
-
|
17
|
-
# fsluis: Alternative, streaming, interface to mailchimp export api
|
18
|
-
# Prevents having to keep lots of data in memory
|
19
|
-
def call(method, params = {}, &block)
|
20
|
-
rows = []
|
21
|
-
|
22
|
-
api_url = export_api_url + method + "/"
|
23
|
-
params = @default_params.merge(params).merge({:apikey => @api_key})
|
24
|
-
block = Proc.new { |row| rows << row } unless block_given?
|
25
|
-
ensure_api_key params
|
26
|
-
|
27
|
-
url = URI.parse(api_url)
|
28
|
-
req = Net::HTTP::Post.new(url.path, initheader = {'Content-Type' => 'application/json'})
|
29
|
-
req.body = MultiJson.dump(params)
|
30
|
-
Net::HTTP.start(url.host, url.port, :read_timeout => @timeout) do |http|
|
31
|
-
# http://stackoverflow.com/questions/29598196/ruby-net-http-read-body-nethttpokread-body-called-twice-ioerror
|
32
|
-
http.request req do |response|
|
33
|
-
i = -1
|
34
|
-
last = ''
|
35
|
-
response.read_body do |chunk|
|
36
|
-
next if chunk.nil? or chunk.strip.empty?
|
37
|
-
last += "\n" if last[-1, 1]==']'
|
38
|
-
lines = (last+chunk).split("\n")
|
39
|
-
last = lines.pop || ''
|
40
|
-
lines.each do |line|
|
41
|
-
block.call(parse_response(line, i < 0), i += 1) unless line.nil?
|
42
|
-
end
|
43
|
-
end
|
44
|
-
block.call(parse_response(last, i < 0), i += 1) unless last.nil? or last.empty?
|
45
|
-
end
|
46
|
-
end
|
47
|
-
rows unless block_given?
|
48
|
-
end
|
49
|
-
|
50
|
-
def parse_response(res, check_error)
|
51
|
-
return [] if res.strip.empty?
|
52
|
-
super(res, check_error)
|
53
|
-
end
|
54
|
-
|
55
|
-
def set_instance_defaults
|
56
|
-
@api_key = self.class.api_key if @api_key.nil?
|
57
|
-
@timeout = self.class.timeout if @timeout.nil?
|
58
|
-
super
|
59
|
-
end
|
60
|
-
|
61
|
-
# fsluis: added a &block to this method and function call
|
62
|
-
def method_missing(method, *args, &block)
|
63
|
-
# To support underscores, we camelize the method name
|
64
|
-
|
65
|
-
# Thanks for the camelize gsub, Rails
|
66
|
-
method = method.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
67
|
-
|
68
|
-
# We need to downcase the first letter of every API method
|
69
|
-
# and MailChimp has a few of API methods that end in "AIM," which
|
70
|
-
# must be upcased (See "Campaign Report Data Methods" in their API docs).
|
71
|
-
method = method[0].chr.downcase + method[1..-1].gsub(/aim$/i, 'AIM')
|
72
|
-
|
73
|
-
call(method, *args, &block)
|
74
|
-
end
|
75
|
-
|
76
|
-
def respond_to_missing?(method, include_private = false)
|
77
|
-
%w{list ecommOrders ecomm_orders campaignSubscriberActivity campaign_subscriber_activity}.include?(method.to_s) || super
|
78
|
-
end
|
79
|
-
|
80
|
-
private
|
81
|
-
|
82
|
-
def split_json(lines, delimiter)
|
83
|
-
lines.map do |line|
|
84
|
-
if line.include? delimiter
|
85
|
-
line.split(delimiter).each_with_index.map{ |s, i| i % 2 == 0 ? s + delimiter[0] : delimiter[1] + s }
|
86
|
-
else
|
87
|
-
line
|
88
|
-
end
|
89
|
-
end.flatten
|
90
|
-
end
|
91
|
-
|
92
|
-
def ensure_api_key(params)
|
93
|
-
unless @api_key || @default_params[:apikey] || params[:apikey]
|
94
|
-
raise Gibbon::GibbonError, "You must set an api_key prior to making a call"
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
class << self
|
99
|
-
attr_accessor :api_key, :timeout, :throws_exceptions
|
100
|
-
|
101
|
-
def method_missing(sym, *args, &block)
|
102
|
-
new(self.api_key, {:timeout => self.timeout, :throws_exceptions => self.throws_exceptions}).send(sym, *args, &block)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|