monkey_wrench 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.mdown +18 -0
- data/Rakefile +11 -0
- data/lib/monkey_wrench.rb +10 -0
- data/lib/monkey_wrench/array.rb +9 -0
- data/lib/monkey_wrench/base.rb +67 -0
- data/lib/monkey_wrench/campaign.rb +0 -0
- data/lib/monkey_wrench/campaign_aim.rb +0 -0
- data/lib/monkey_wrench/campaign_stats.rb +0 -0
- data/lib/monkey_wrench/config.rb +34 -0
- data/lib/monkey_wrench/error.rb +104 -0
- data/lib/monkey_wrench/hash.rb +69 -0
- data/lib/monkey_wrench/helper.rb +0 -0
- data/lib/monkey_wrench/list.rb +309 -0
- data/lib/monkey_wrench/member.rb +33 -0
- data/lib/monkey_wrench/security.rb +0 -0
- data/test/fixtures/api_fail.json +1 -0
- data/test/fixtures/campaigns_success.json +24 -0
- data/test/fixtures/listBatchSubscribe10_success.json +1 -0
- data/test/fixtures/listBatchSubscribe5_success.json +1 -0
- data/test/fixtures/listBatchSubscribe_success.json +1 -0
- data/test/fixtures/listBatchSubscribe_with_error_success.json +1 -0
- data/test/fixtures/listBatchUnsubscribe_success.json +1 -0
- data/test/fixtures/listMemberInfo_fail.json +1 -0
- data/test/fixtures/listMemberInfo_success.json +1 -0
- data/test/fixtures/listMembers_none_success.json +1 -0
- data/test/fixtures/listMembers_success.json +8 -0
- data/test/fixtures/listSubscribe_success.json +1 -0
- data/test/fixtures/listUnsubscribe_success.json +0 -0
- data/test/fixtures/listUpdateMember_success.json +1 -0
- data/test/fixtures/lists_success.json +14 -0
- data/test/monkey_wrench/campaign_aim_test.rb +0 -0
- data/test/monkey_wrench/campaign_stats_test.rb +0 -0
- data/test/monkey_wrench/campaign_test.rb +0 -0
- data/test/monkey_wrench/hash_test.rb +47 -0
- data/test/monkey_wrench/helper_test.rb +0 -0
- data/test/monkey_wrench/list_test.rb +310 -0
- data/test/monkey_wrench/security_test.rb +0 -0
- data/test/test_helper.rb +67 -0
- metadata +134 -0
data/README.mdown
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# MonkeyWrench
|
2
|
+
MonkeyWrench is a rubyesque API for interfacing with [Mailchimp](http://www.mailchimp.com) (or show me some love by registering [via my affiliate link](http://eepurl.com/Ge71)).
|
3
|
+
|
4
|
+
## Getting Started
|
5
|
+
|
6
|
+
To get started, you need to first connect to the appropriate datacenter with your API key:
|
7
|
+
|
8
|
+
MonkeyWrench::Config.new(:datacenter => "us1",
|
9
|
+
:apikey => "your-api-key-goes-here")
|
10
|
+
|
11
|
+
From there you've got a rich API for managing Lists and Members. To subscribe a new user to a list simply do the following:
|
12
|
+
|
13
|
+
list = MonkeyWrench::List.find_by_name("My Example List")
|
14
|
+
list.subscribe("foo@bar.com")
|
15
|
+
|
16
|
+
## Further Reading
|
17
|
+
|
18
|
+
For more information, [check the documentation](http://rdoc.info/projects/rubypond/monkeywrench)
|
data/Rakefile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require "httparty"
|
2
|
+
base_dir = File.join(File.dirname(__FILE__), "monkey_wrench")
|
3
|
+
["base", "config", "hash", "list", "error", "member"].each do |lib|
|
4
|
+
require File.join(base_dir, lib)
|
5
|
+
end
|
6
|
+
|
7
|
+
begin
|
8
|
+
OpenStruct.class_eval { undef :id, :type }
|
9
|
+
rescue NameError
|
10
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
begin
|
2
|
+
require 'yajl'
|
3
|
+
rescue LoadError
|
4
|
+
require 'json'
|
5
|
+
end
|
6
|
+
require 'ostruct'
|
7
|
+
module MonkeyWrench
|
8
|
+
class Base < OpenStruct
|
9
|
+
include HTTParty
|
10
|
+
|
11
|
+
@@apikey = nil
|
12
|
+
@@datacenter = nil
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def default_options
|
16
|
+
{ :output => "json", :apikey=> @@apikey}
|
17
|
+
end
|
18
|
+
|
19
|
+
def base_uri
|
20
|
+
"http://#{datacenter}.api.mailchimp.com/1.2/"
|
21
|
+
end
|
22
|
+
|
23
|
+
def get(params)
|
24
|
+
response = super(base_uri, :query => params.merge(default_options))
|
25
|
+
handle_errors(response.parsed_response)
|
26
|
+
end
|
27
|
+
|
28
|
+
def post(params)
|
29
|
+
response = super(base_uri, :query => params.merge(default_options))
|
30
|
+
handle_errors(response.parsed_response)
|
31
|
+
end
|
32
|
+
|
33
|
+
def handle_errors(objects)
|
34
|
+
return objects unless objects.respond_to?(:has_key?)
|
35
|
+
|
36
|
+
if objects.has_key?("error")
|
37
|
+
objects.replace({ "error" => MonkeyWrench::Error.new(objects['error'], objects['code']) })
|
38
|
+
elsif objects.has_key?("errors")
|
39
|
+
objects["errors"] = objects["errors"].map do |err|
|
40
|
+
message = err.delete('message')
|
41
|
+
code = err.delete('code')
|
42
|
+
MonkeyWrench::Error.new(message, code, err)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
objects
|
46
|
+
end
|
47
|
+
|
48
|
+
def apikey
|
49
|
+
@@apikey
|
50
|
+
end
|
51
|
+
|
52
|
+
def datacenter
|
53
|
+
@@datacenter
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def get(params)
|
59
|
+
self.class.get(params)
|
60
|
+
end
|
61
|
+
|
62
|
+
def post(params)
|
63
|
+
self.class.post(params)
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
module MonkeyWrench
|
3
|
+
class Config < MonkeyWrench::Base
|
4
|
+
# Establishes a connection to the Mailchimp API.
|
5
|
+
#
|
6
|
+
# Can be called with either a path to a file containing credentials, or
|
7
|
+
# a hash of credentials. The formats of each are:
|
8
|
+
#
|
9
|
+
# File:
|
10
|
+
# mailchimp:
|
11
|
+
# datacenter: us1 # Or whatever DC you use
|
12
|
+
# apikey: your-api-key-goes-here
|
13
|
+
# Hash:
|
14
|
+
# { :datacenter => "us1", :apikey => "your-api-key-goes-here"}
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# MonkeyWrench::Config.new(:datacenter => "us1",
|
18
|
+
# :apikey => "your-api-key-goes-here")
|
19
|
+
#
|
20
|
+
# @param [String, Hash] credentials accepts either a String pointing to a file
|
21
|
+
# containing the credentials, or a hash of credentials.
|
22
|
+
def initialize(credentials)
|
23
|
+
if credentials.is_a?(String)
|
24
|
+
config = YAML.load_file(credentials)["mailchimp"]
|
25
|
+
config.collect_kv!{|k,v| [k.to_sym, v]}
|
26
|
+
else
|
27
|
+
config = credentials
|
28
|
+
end
|
29
|
+
@@apikey = config[:apikey]
|
30
|
+
@@datacenter = config[:datacenter]
|
31
|
+
super({})
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module MonkeyWrench
|
2
|
+
class Error < StandardError
|
3
|
+
attr_reader :code
|
4
|
+
|
5
|
+
def initialize(message, code, extra_fields = {})
|
6
|
+
super(message)
|
7
|
+
@code = code
|
8
|
+
@extra_fields = extra_fields
|
9
|
+
end
|
10
|
+
|
11
|
+
def type
|
12
|
+
types[@code]
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(sym, *args, &block)
|
16
|
+
return @extra_fields[sym.to_s] if @extra_fields.has_key?(sym.to_s)
|
17
|
+
end
|
18
|
+
|
19
|
+
def types
|
20
|
+
{
|
21
|
+
-32601 => 'ServerError_MethodUnknown',
|
22
|
+
-32602 => 'ServerError_InvalidParameters',
|
23
|
+
-99 => 'Unknown_Exception',
|
24
|
+
-98 => 'Request_TimedOut',
|
25
|
+
-92 => 'Zend_Uri_Exception',
|
26
|
+
-91 => 'PDOException',
|
27
|
+
-91 => 'Avesta_Db_Exception',
|
28
|
+
-90 => 'XML_RPC2_Exception',
|
29
|
+
-90 => 'XML_RPC2_FaultException',
|
30
|
+
-50 => 'Too_Many_Connections',
|
31
|
+
0 => 'Parse_Exception',
|
32
|
+
100 => 'User_Unknown',
|
33
|
+
101 => 'User_Disabled',
|
34
|
+
102 => 'User_DoesNotExist',
|
35
|
+
103 => 'User_NotApproved',
|
36
|
+
104 => 'Invalid_ApiKey',
|
37
|
+
105 => 'User_UnderMaintenance',
|
38
|
+
120 => 'User_InvalidAction',
|
39
|
+
121 => 'User_MissingEmail',
|
40
|
+
122 => 'User_CannotSendCampaign',
|
41
|
+
123 => 'User_MissingModuleOutbox',
|
42
|
+
124 => 'User_ModuleAlreadyPurchased',
|
43
|
+
125 => 'User_ModuleNotPurchased',
|
44
|
+
126 => 'User_NotEnoughCredit',
|
45
|
+
127 => 'MC_InvalidPayment',
|
46
|
+
200 => 'List_DoesNotExist',
|
47
|
+
210 => 'List_InvalidInterestFieldType',
|
48
|
+
211 => 'List_InvalidOption',
|
49
|
+
212 => 'List_InvalidUnsubMember',
|
50
|
+
213 => 'List_InvalidBounceMember',
|
51
|
+
214 => 'List_AlreadySubscribed',
|
52
|
+
215 => 'List_NotSubscribed',
|
53
|
+
220 => 'List_InvalidImport',
|
54
|
+
221 => 'MC_PastedList_Duplicate',
|
55
|
+
222 => 'MC_PastedList_InvalidImport',
|
56
|
+
230 => 'Email_AlreadySubscribed',
|
57
|
+
231 => 'Email_AlreadyUnsubscribed',
|
58
|
+
232 => 'Email_NotExists',
|
59
|
+
233 => 'Email_NotSubscribed',
|
60
|
+
250 => 'List_MergeFieldRequired',
|
61
|
+
251 => 'List_CannotRemoveEmailMerge',
|
62
|
+
252 => 'List_Merge_InvalidMergeID',
|
63
|
+
253 => 'List_TooManyMergeFields',
|
64
|
+
254 => 'List_InvalidMergeField',
|
65
|
+
270 => 'List_InvalidInterestGroup',
|
66
|
+
271 => 'List_TooManyInterestGroups',
|
67
|
+
300 => 'Campaign_DoesNotExist',
|
68
|
+
301 => 'Campaign_StatsNotAvailable',
|
69
|
+
310 => 'Campaign_InvalidAbsplit',
|
70
|
+
311 => 'Campaign_InvalidContent',
|
71
|
+
312 => 'Campaign_InvalidOption',
|
72
|
+
313 => 'Campaign_InvalidStatus',
|
73
|
+
314 => 'Campaign_NotSaved',
|
74
|
+
315 => 'Campaign_InvalidSegment',
|
75
|
+
316 => 'Campaign_InvalidRss',
|
76
|
+
317 => 'Campaign_InvalidAuto',
|
77
|
+
318 => 'MC_ContentImport_InvalidArchive',
|
78
|
+
330 => 'Invalid_EcommOrder',
|
79
|
+
350 => 'Absplit_UnknownError',
|
80
|
+
351 => 'Absplit_UnknownSplitTest',
|
81
|
+
352 => 'Absplit_UnknownTestType',
|
82
|
+
353 => 'Absplit_UnknownWaitUnit',
|
83
|
+
354 => 'Absplit_UnknownWinnerType',
|
84
|
+
355 => 'Absplit_WinnerNotSelected',
|
85
|
+
500 => 'Invalid_Analytics',
|
86
|
+
501 => 'Invalid_DateTime',
|
87
|
+
502 => 'Invalid_Email',
|
88
|
+
503 => 'Invalid_SendType',
|
89
|
+
504 => 'Invalid_Template',
|
90
|
+
505 => 'Invalid_TrackingOptions',
|
91
|
+
506 => 'Invalid_Options',
|
92
|
+
507 => 'Invalid_Folder',
|
93
|
+
508 => 'Invalid_URL',
|
94
|
+
550 => 'Module_Unknown',
|
95
|
+
551 => 'MonthlyPlan_Unknown',
|
96
|
+
552 => 'Order_TypeUnknown',
|
97
|
+
553 => 'Invalid_PagingLimit',
|
98
|
+
554 => 'Invalid_PagingStart'
|
99
|
+
}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
module MonkeyWrench
|
3
|
+
module Hash
|
4
|
+
|
5
|
+
# Takes a block that returns a [key, value] pair
|
6
|
+
# and builds a new hash based on those pairs
|
7
|
+
# Courtesy of http://snuxoll.com/post/2009/02/13/ruby-better-hashcollect
|
8
|
+
def collect_kv
|
9
|
+
result = {}
|
10
|
+
each do |k,v|
|
11
|
+
new_k, new_v = yield k, v
|
12
|
+
result[new_k] = new_v
|
13
|
+
end
|
14
|
+
result
|
15
|
+
end
|
16
|
+
|
17
|
+
def collect_kv!(&blk)
|
18
|
+
replace(self.collect_kv(&blk))
|
19
|
+
end
|
20
|
+
|
21
|
+
def escape_keys!
|
22
|
+
collect_kv!{|k,v| [CGI.escape(k.to_s), v]}
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_mailchimp(index = nil, parent_name = nil)
|
26
|
+
result = self.collect_kv do |k,v|
|
27
|
+
if v.is_a?(Array) && v.first.is_a?(Hash)
|
28
|
+
i = 0
|
29
|
+
v = v.inject({}) do |acc,hash|
|
30
|
+
acc.merge!(hash.to_mailchimp(i, k))
|
31
|
+
i += 1
|
32
|
+
acc
|
33
|
+
end
|
34
|
+
elsif v.is_a?(Hash)
|
35
|
+
if parent_name
|
36
|
+
v = v.collect_kv do |key,val|
|
37
|
+
keyname = CGI.escape("#{parent_name.to_s}[#{key.to_s.upcase}]")
|
38
|
+
[keyname, val]
|
39
|
+
end
|
40
|
+
else
|
41
|
+
v = { k => v }.to_mailchimp(nil, k)
|
42
|
+
end
|
43
|
+
elsif v.is_a?(Array)
|
44
|
+
results = {}
|
45
|
+
i = 0
|
46
|
+
v.each do |val|
|
47
|
+
keyname = CGI.escape("#{k}[#{i}]")
|
48
|
+
results[keyname] = val
|
49
|
+
i += 1
|
50
|
+
end
|
51
|
+
v = results
|
52
|
+
end
|
53
|
+
k = k.to_s
|
54
|
+
k = "[#{index}][#{k.upcase}]" if index
|
55
|
+
k = [parent_name, k].join if k != parent_name.to_s
|
56
|
+
[CGI.escape(k), v]
|
57
|
+
end
|
58
|
+
if result.detect{|k,v| v.is_a?(Hash)}
|
59
|
+
result.values.first
|
60
|
+
else
|
61
|
+
result
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class Hash
|
68
|
+
include MonkeyWrench::Hash
|
69
|
+
end
|
File without changes
|
@@ -0,0 +1,309 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module MonkeyWrench
|
4
|
+
class List < MonkeyWrench::Base
|
5
|
+
|
6
|
+
# Finds a given list by name
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# MonkeyWrench::List.find_by_name("My Example List")
|
10
|
+
#
|
11
|
+
# @param [String] list_name the list name
|
12
|
+
# @return [MonkeyWrench::List] the first list found with a matching name
|
13
|
+
def self.find_by_name(list_name)
|
14
|
+
lists = find_all.detect{|list| list.name == list_name}
|
15
|
+
end
|
16
|
+
|
17
|
+
# Will compare another list against the current one and return true if
|
18
|
+
# they are the same (based on list ID)
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# list1 = MonkeyWrench::List.find("0a649eafc3")
|
22
|
+
# list2 = MonkeyWrench::List.find("9f9d54a0c4")
|
23
|
+
# list3 = MonkeyWrench::List.find("0a649eafc3") # Same as list1!!
|
24
|
+
# list1 == list2 # false
|
25
|
+
# list1 == list3 # true
|
26
|
+
# @param [MonkeyWrench::List] other_list Other list to compare against
|
27
|
+
# @return [Boolean]
|
28
|
+
def ==(other_list)
|
29
|
+
other_list.is_a?(self.class) && self.id == other_list.id
|
30
|
+
end
|
31
|
+
|
32
|
+
# Finds a given list by ID
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
# MonkeyWrench::List.find("0a649eafc3")
|
36
|
+
#
|
37
|
+
# @param [String] id the unique Mailchimp list ID
|
38
|
+
# @return [MonkeyWrench::List] the list
|
39
|
+
def self.find(id)
|
40
|
+
new(:id => id)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Finds all lists
|
44
|
+
#
|
45
|
+
# @example
|
46
|
+
# MonkeyWrench::List.find_all
|
47
|
+
#
|
48
|
+
# @return [Array<MonkeyWrench::List>]
|
49
|
+
def self.find_all
|
50
|
+
lists = post({ :method => "lists" }).map do |list|
|
51
|
+
List.new(list)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
class << self
|
55
|
+
alias :all :find_all
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns all members for this list
|
59
|
+
#
|
60
|
+
# @example Find all members that have unsubscribed in the last 24 hours:
|
61
|
+
# MonkeyWrench.members(:status => "unsubscribed",
|
62
|
+
# :since => Time.now - 86400)
|
63
|
+
#
|
64
|
+
# @param [Hash] options additional option to include when searching.
|
65
|
+
# @option options [String] :status ('subscribed') Filter the list members by status. Can be one of the following: "subscribed", "unsubscribed", "cleaned", "updated".
|
66
|
+
# @option options [DateTime] :since Return all members whose status has changed or whose profile has changed since this date/time (in GMT).
|
67
|
+
# @option options [Integer] :start (0) For large datasets, the page number to start at.
|
68
|
+
# @option options [Integer] :limit (100) For large datasets, the number of results to return. Upper limit is set at 15000.
|
69
|
+
# @option options [Boolean] :full_details (true) Return full member details and not just email address and timestamp.
|
70
|
+
# @return [Array<MonkeyWrench::Member>]
|
71
|
+
def members(options = {})
|
72
|
+
if options[:since]
|
73
|
+
options[:since] = options[:since].strftime("%Y-%m-%d %H:%M:%S")
|
74
|
+
end
|
75
|
+
options.merge!(:id => self.id, :method => "listMembers")
|
76
|
+
response = post(options)
|
77
|
+
if options[:full_details]
|
78
|
+
response.map do |response_user|
|
79
|
+
member(response_user["email"])
|
80
|
+
end
|
81
|
+
else
|
82
|
+
response.map do |response_user|
|
83
|
+
MonkeyWrench::Member.new(response_user)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Enumerates over each member and executes the provided block. Will
|
89
|
+
# automatically page and batch requests for members.
|
90
|
+
#
|
91
|
+
# @example
|
92
|
+
# list = MonkeyWrench::List.find("0a649eafc3")
|
93
|
+
# emails = []
|
94
|
+
# list.each_member do |member|
|
95
|
+
# emails << member.email
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# @param [Proc] &block code to execute for each member
|
99
|
+
def each_member(&block)
|
100
|
+
page = 0
|
101
|
+
loop do
|
102
|
+
batch = members(:start => page, :limit => 15000)
|
103
|
+
break if batch.empty?
|
104
|
+
batch.each do |member|
|
105
|
+
yield member
|
106
|
+
end
|
107
|
+
page += 1
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Updates details of list members
|
112
|
+
#
|
113
|
+
# @example Update a single member's email address
|
114
|
+
# list = MonkeyWrench::List.find("0a649eafc3")
|
115
|
+
# member = {:email => "foo@bar.com", :new_email => "bar@foo.com"}
|
116
|
+
# list.update_members(member)
|
117
|
+
#
|
118
|
+
# @example Update multiple members' email addresses
|
119
|
+
# list = MonkeyWrench::List.find("0a649eafc3")
|
120
|
+
# members = [{:email => "foo@bar.com", :new_email => "bar@foo.com"},
|
121
|
+
# {:email => "bob@bar.com", :new_email => "bob@foo.com"}]
|
122
|
+
# list.update_members(members)
|
123
|
+
#
|
124
|
+
# @param [Hash, Array<Hash>] members details of member(s) to update details
|
125
|
+
# of. Members are matched based on the value of :email, to update the
|
126
|
+
# email address assign the new address to :new_email. All other field
|
127
|
+
# names are lowercase symbols representing the MERGEVAR name in
|
128
|
+
# Mailchimp (e.g., FNAME is :fname)
|
129
|
+
# @param [Hash] options additional options when updating members.
|
130
|
+
# @option options [String] :email_type Change the email type preference for the member ('html', 'text', or 'mobile').
|
131
|
+
# @option options [Boolean] :replace_interests (true) replace the interest groups provided (will append interest groups to existing values when false).
|
132
|
+
def update_members(members, options = {})
|
133
|
+
members = members.is_a?(Array) ? members : [members]
|
134
|
+
options.merge!(:id => self.id, :method => "listUpdateMember")
|
135
|
+
members.each do |member|
|
136
|
+
mailchimp_args = {:email_address => member[:email]}
|
137
|
+
member[:email] = member[:new_email]
|
138
|
+
member.delete(:new_email)
|
139
|
+
mailchimp_args.merge!({ :merge_vars => member }.to_mailchimp)
|
140
|
+
post(options.merge(mailchimp_args))
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Find a member in this list with the given email address
|
145
|
+
#
|
146
|
+
# @example
|
147
|
+
# list = MonkeyWrench::List.find("0a649eafc3")
|
148
|
+
# list.member("glenn@rubypond.com")
|
149
|
+
#
|
150
|
+
# @param [String] email members email address
|
151
|
+
# @return [MonkeyWrench::Member]
|
152
|
+
def member(email)
|
153
|
+
response = post(:id => self.id, :method => "listMemberInfo", :email_address => email)
|
154
|
+
if response['error']
|
155
|
+
raise response['error']
|
156
|
+
else
|
157
|
+
MonkeyWrench::Member.new(response)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Subscribes a new member to the list
|
162
|
+
#
|
163
|
+
# @example Subscribe a new email address
|
164
|
+
# list.subscribe("foo@bar.com")
|
165
|
+
#
|
166
|
+
# @example Subscribe a new member with extended details
|
167
|
+
# list.subscribe({:email => "foo@bar.com", :type => :html})
|
168
|
+
#
|
169
|
+
# @example Subscribe multiple new members
|
170
|
+
# subscribers = [{:email => "foo@bar.com", :type => :html},
|
171
|
+
# {:email => "bar@foo.com", :type => :html}]
|
172
|
+
# list.subscribe(subscribe, :send_welcome => true, :double_optin => false)
|
173
|
+
#
|
174
|
+
# @param [String, Hash, Array<Hash>] contact_details the email address or hash of values for the new member
|
175
|
+
# @param [Hash] opts options when adding new member
|
176
|
+
# @option opts [Boolean] :send_welcome (false) if :double_optin if false and this is
|
177
|
+
# true, send the lists 'Welcome Email' to the member(s). Will not send email if
|
178
|
+
# updating an existing member.
|
179
|
+
# @option opts [Boolean] :double_optin (true) send an opt-in confirmation email
|
180
|
+
# @option opts [Boolean] :update_existing (false) update members that are already subscribed to the list or to return an error (false returns error)
|
181
|
+
# @option opts [Boolean] :replace_interests (true) replace interest groups or append to existing interest groups (false appends to groups)
|
182
|
+
def subscribe(contact_details, opts = {})
|
183
|
+
if contact_details.is_a?(Array)
|
184
|
+
return subscribe_many(contact_details, opts)
|
185
|
+
else
|
186
|
+
if contact_details.is_a?(Hash)
|
187
|
+
email_address = contact_details.delete(:email)
|
188
|
+
opts = opts.merge(contact_details)
|
189
|
+
else
|
190
|
+
email_address = contact_details
|
191
|
+
end
|
192
|
+
subscribe_one(email_address, opts)
|
193
|
+
return { :success => 1, :errors => []}
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# Unsubscribes a person (or list of people) from the list
|
198
|
+
#
|
199
|
+
# @example Unsubscribe a single user
|
200
|
+
# list = MonkeyWrench::List.find("0a649eafc3")
|
201
|
+
# list.unsubscribe("glenn@rubypond.com", :send_goodbye => true) # Unsubscribe a single person
|
202
|
+
#
|
203
|
+
# @example Unsubscribe a list of users
|
204
|
+
# emails = ["glenn@rubypond.com", "me@glenngillen.com"]
|
205
|
+
# list.unsubscribe(emails, :send_goodbye => true) # Unsubscribe multiple people at once
|
206
|
+
#
|
207
|
+
# @param [String, Array<String>] email address(es) of people to unsubscribe.
|
208
|
+
# @param [Hash] opts additional option to include when unsubscribing.
|
209
|
+
# @option opts [Boolean] :delete_member (false) completely delete the member from your list instead of just unsubscribing.
|
210
|
+
# @option opts [Boolean] :send_goodbye (true) send the goodbye email to the email addresses.
|
211
|
+
# @option opts [Boolean] :send_notify (false) send the unsubscribe notification email to the address defined in the list email notification settings.
|
212
|
+
# @return [Hash] contains 2 keys. :success contains the number of successful actions, :error a list of all errors.
|
213
|
+
def unsubscribe(emails, opts = {})
|
214
|
+
emails = [*emails]
|
215
|
+
params = { :method => "listBatchUnsubscribe",
|
216
|
+
:id => self.id }
|
217
|
+
params[:delete_member] = opts[:delete_member] if opts.has_key?(:delete_member)
|
218
|
+
params[:send_goodbye] = opts[:send_goodbye] if opts.has_key?(:send_goodbye)
|
219
|
+
params[:send_notify] = opts[:send_notify] if opts.has_key?(:send_notify)
|
220
|
+
params.merge!({ :emails => emails }.to_mailchimp)
|
221
|
+
response = post(params)
|
222
|
+
return { :success => response["success_count"],
|
223
|
+
:errors => response["errors"] }
|
224
|
+
end
|
225
|
+
|
226
|
+
# Will flag the email(s) as opted-out for all future mailing for this list
|
227
|
+
#
|
228
|
+
# @example Opt-out a single user
|
229
|
+
# list = MonkeyWrench::List.find("0a649eafc3")
|
230
|
+
# list.opt_out("glenn@rubypond.com") # Opt-out a single person
|
231
|
+
#
|
232
|
+
# @example Opt-out a list of users
|
233
|
+
# emails = ["glenn@rubypond.com", "me@glenngillen.com"]
|
234
|
+
# list.opt_out(emails) # Opt-out multiple people at once
|
235
|
+
#
|
236
|
+
# @param [String, Array<String>] email address(es) of people to opt-out.
|
237
|
+
# @return [Hash] contains 2 keys. :success contains the number of successful actions, :error a list of all errors.
|
238
|
+
def opt_out(emails)
|
239
|
+
emails = [*emails]
|
240
|
+
subscribe(emails.map{|email| { :email => email }})
|
241
|
+
unsubscribe(emails, :send_goodbye => false, :send_notify => false)
|
242
|
+
end
|
243
|
+
|
244
|
+
private
|
245
|
+
def self.reserved_keys
|
246
|
+
[:email, :type, :double_optin, :update_existing, :replace_interests,
|
247
|
+
:send_welcome, :emails, :send_notify, :send_goodbye, :delete_member]
|
248
|
+
end
|
249
|
+
|
250
|
+
def subscribe_many(subscribers, opts = {})
|
251
|
+
if opts[:send_welcome]
|
252
|
+
subscribe_one_at_a_time(subscribers, opts)
|
253
|
+
else
|
254
|
+
subscribe_in_batches(subscribers, opts)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def subscribe_in_batches(subscribers, opts)
|
259
|
+
cumulative_response = { :success => 0, :errors => [] }
|
260
|
+
i = 0
|
261
|
+
while i < subscribers.size
|
262
|
+
response = subscribe_one_batch(subscribers[i..i+9], opts)
|
263
|
+
cumulative_response[:success] += response['success_count']
|
264
|
+
cumulative_response[:errors] += response['errors']
|
265
|
+
i += 10
|
266
|
+
end
|
267
|
+
cumulative_response
|
268
|
+
end
|
269
|
+
|
270
|
+
def subscribe_one_batch(subscribers, opts)
|
271
|
+
params = { :id => self.id, :method => "listBatchSubscribe" }
|
272
|
+
params[:double_optin] = opts[:double_optin] if opts.has_key?(:double_optin)
|
273
|
+
params[:update_existing] = opts[:update_existing] if opts.has_key?(:update_existing)
|
274
|
+
params[:replace_interests] = opts[:replace_interests] if opts.has_key?(:replace_interests)
|
275
|
+
params.merge!({ :batch => subscribers }.to_mailchimp)
|
276
|
+
post(params)
|
277
|
+
end
|
278
|
+
|
279
|
+
def subscribe_one_at_a_time(subscribers, opts)
|
280
|
+
cumulative_response = { :success => 0, :errors => [] }
|
281
|
+
subscribers.each do |subscriber|
|
282
|
+
params = opts.merge(subscriber)
|
283
|
+
params.delete(:email)
|
284
|
+
if subscribe_one(subscriber[:email], params) == true
|
285
|
+
cumulative_response[:success] += 1
|
286
|
+
else
|
287
|
+
cumulative_response[:errors] << response["error"]
|
288
|
+
end
|
289
|
+
end
|
290
|
+
cumulative_response
|
291
|
+
end
|
292
|
+
|
293
|
+
def subscribe_one(email_address, opts = {})
|
294
|
+
params = {
|
295
|
+
:type => opts.delete(:type),
|
296
|
+
:double_optin => opts.delete(:double_optin),
|
297
|
+
:update_existing => opts.delete(:update_existing),
|
298
|
+
:replace_interests => opts.delete(:replace_interests),
|
299
|
+
:send_welcome => opts.delete(:send_welcome),
|
300
|
+
:email => email_address
|
301
|
+
}
|
302
|
+
params.reject!{ |k,v| v.nil? }
|
303
|
+
merge_vars = { :merge_vars => opts }.to_mailchimp
|
304
|
+
params.merge!(merge_vars)
|
305
|
+
params.merge!(:method => "listSubscribe", :id => self.id)
|
306
|
+
post(params)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|