monkey_wrench 0.1.0
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.
- 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
|