contactology 0.0.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.
- data/.gitignore +5 -0
- data/.infinity_test +16 -0
- data/.rspec +3 -0
- data/.rvmrc +41 -0
- data/.watchr +36 -0
- data/Gemfile +6 -0
- data/Rakefile +1 -0
- data/contactology.gemspec +28 -0
- data/lib/contactology.rb +125 -0
- data/lib/contactology/api.rb +80 -0
- data/lib/contactology/basic_object.rb +21 -0
- data/lib/contactology/campaign.rb +127 -0
- data/lib/contactology/campaign/preview.rb +11 -0
- data/lib/contactology/campaigns.rb +2 -0
- data/lib/contactology/campaigns/standard.rb +80 -0
- data/lib/contactology/campaigns/transactional.rb +58 -0
- data/lib/contactology/configuration.rb +42 -0
- data/lib/contactology/contact.rb +193 -0
- data/lib/contactology/errors.rb +4 -0
- data/lib/contactology/issue.rb +24 -0
- data/lib/contactology/issues.rb +18 -0
- data/lib/contactology/list.rb +192 -0
- data/lib/contactology/list_proxy.rb +25 -0
- data/lib/contactology/parser.rb +5 -0
- data/lib/contactology/send_result.rb +35 -0
- data/lib/contactology/stash.rb +29 -0
- data/lib/contactology/transactional_message.rb +38 -0
- data/lib/contactology/version.rb +3 -0
- data/spec/factories/campaigns.rb +18 -0
- data/spec/factories/contacts.rb +3 -0
- data/spec/factories/issues.rb +9 -0
- data/spec/factories/lists.rb +3 -0
- data/spec/factories/transactional_messages.rb +5 -0
- data/spec/fixtures/net/campaign/destroy.yml +246 -0
- data/spec/fixtures/net/campaign/find/failure.yml +36 -0
- data/spec/fixtures/net/campaign/find/success.yml +176 -0
- data/spec/fixtures/net/campaign/find_by_name/failure.yml +36 -0
- data/spec/fixtures/net/campaign/find_by_name/success.yml +211 -0
- data/spec/fixtures/net/campaign/preview.yml +106 -0
- data/spec/fixtures/net/campaigns/standard/create/failure.yml +106 -0
- data/spec/fixtures/net/campaigns/standard/create/invalid.yml +141 -0
- data/spec/fixtures/net/campaigns/standard/create/success.yml +176 -0
- data/spec/fixtures/net/campaigns/standard/send_campaign/failure.yml +316 -0
- data/spec/fixtures/net/campaigns/standard/send_campaign/success.yml +316 -0
- data/spec/fixtures/net/campaigns/transactional/create/failure.yml +36 -0
- data/spec/fixtures/net/campaigns/transactional/create/success.yml +71 -0
- data/spec/fixtures/net/contact/active.yml +106 -0
- data/spec/fixtures/net/contact/change_email/success.yml +176 -0
- data/spec/fixtures/net/contact/change_email/unknown.yml +36 -0
- data/spec/fixtures/net/contact/create.yml +106 -0
- data/spec/fixtures/net/contact/destroy.yml +141 -0
- data/spec/fixtures/net/contact/find/active.yml +106 -0
- data/spec/fixtures/net/contact/find/suppressed.yml +141 -0
- data/spec/fixtures/net/contact/find/unknown.yml +36 -0
- data/spec/fixtures/net/contact/lists/empty.yml +106 -0
- data/spec/fixtures/net/contact/lists/full.yml +246 -0
- data/spec/fixtures/net/contact/lists/unknown.yml +71 -0
- data/spec/fixtures/net/contact/suppress.yml +141 -0
- data/spec/fixtures/net/list/all.yml +141 -0
- data/spec/fixtures/net/list/create.yml +106 -0
- data/spec/fixtures/net/list/destroy.yml +176 -0
- data/spec/fixtures/net/list/find/success.yml +141 -0
- data/spec/fixtures/net/list/find/unknown.yml +36 -0
- data/spec/fixtures/net/list/import/success.yml +351 -0
- data/spec/fixtures/net/list/subscribe/success.yml +211 -0
- data/spec/fixtures/net/list/unsubscribe/success.yml +246 -0
- data/spec/fixtures/net/transactional_message/send_message/failure.yml +176 -0
- data/spec/fixtures/net/transactional_message/send_message/success.yml +176 -0
- data/spec/models/contactology/api_spec.rb +51 -0
- data/spec/models/contactology/campaign_spec.rb +75 -0
- data/spec/models/contactology/campaigns/standard_spec.rb +84 -0
- data/spec/models/contactology/campaigns/transactional_spec.rb +28 -0
- data/spec/models/contactology/configuration_spec.rb +29 -0
- data/spec/models/contactology/contact_spec.rb +175 -0
- data/spec/models/contactology/issues_spec.rb +34 -0
- data/spec/models/contactology/list_spec.rb +125 -0
- data/spec/models/contactology/send_result_spec.rb +65 -0
- data/spec/models/contactology/stash_spec.rb +65 -0
- data/spec/models/contactology/transactional_message_spec.rb +65 -0
- data/spec/models/contactology_spec.rb +67 -0
- data/spec/requests/contacts_spec.rb +4 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/contactology.rb +34 -0
- data/spec/support/factory_girl.rb +19 -0
- data/spec/support/vcr.rb +11 -0
- metadata +282 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'contactology/campaign'
|
2
|
+
require 'contactology/campaigns'
|
3
|
+
|
4
|
+
class Contactology::Campaigns::Standard < Contactology::Campaign
|
5
|
+
property :content, :required => true
|
6
|
+
property :name, :from => :campaignName, :required => true
|
7
|
+
property :recipients, :required => true
|
8
|
+
property :sender_email, :from => :senderEmail, :required => true
|
9
|
+
property :sender_name, :from => :senderName, :required => true
|
10
|
+
property :subject, :required => true
|
11
|
+
|
12
|
+
|
13
|
+
def []=(property, value)
|
14
|
+
if property.to_s == 'recipients'
|
15
|
+
super 'recipients', normalize_recipients(value)
|
16
|
+
else
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def save(options = {})
|
22
|
+
self.class.query('Campaign_Create_Standard', options.merge({
|
23
|
+
'recipients' => recipients,
|
24
|
+
'campaignName' => name,
|
25
|
+
'subject' => subject,
|
26
|
+
'senderEmail' => sender_email,
|
27
|
+
'senderName' => sender_name,
|
28
|
+
'content' => content,
|
29
|
+
'optionalParameters' => {
|
30
|
+
'authenticate' => authenticate,
|
31
|
+
'replyToEmail' => reply_to_email,
|
32
|
+
'replyToName' => reply_to_name,
|
33
|
+
'trackReplies' => track_replies,
|
34
|
+
'recipientName' => recipient_name,
|
35
|
+
'showInArchive' => show_in_archive,
|
36
|
+
'viewInBrowser' => view_in_browser,
|
37
|
+
'trackOpens' => track_opens,
|
38
|
+
'trackClickThruHTML' => track_click_thru_html,
|
39
|
+
'trackClickThruText' => track_click_thru_text,
|
40
|
+
'googleAnalyticsName' => google_analytics_name,
|
41
|
+
'clickTaleName' => click_tale_name,
|
42
|
+
'clickTaleCustomFields' => click_tale_custom_fields,
|
43
|
+
'automaticTweet' => automatic_tweet
|
44
|
+
},
|
45
|
+
:on_error => false,
|
46
|
+
:on_timeout => false,
|
47
|
+
:on_success => Proc.new { |response| self.id = response; self }
|
48
|
+
}))
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Public: Sends the campaign.
|
53
|
+
#
|
54
|
+
# Returns an empty collection when successful.
|
55
|
+
# Returns a collection of issues when unsuccessful.
|
56
|
+
#
|
57
|
+
def send_campaign(options = {})
|
58
|
+
self.class.query('Campaign_Send', options.merge({
|
59
|
+
'campaignId' => id,
|
60
|
+
:on_error => Proc.new { |response| process_send_campaign_result response },
|
61
|
+
:on_timeout => process_send_campaign_result({'success' => false, 'issues' => [{'text' => 'Connection timeout'}]}),
|
62
|
+
:on_success => Proc.new { |response| process_send_campaign_result response }
|
63
|
+
}))
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
|
70
|
+
def normalize_recipients(input)
|
71
|
+
input = [input].flatten.compact.uniq
|
72
|
+
input = input.select { |i| i.kind_of?(Contactology::List) }.collect { |list| list.id }
|
73
|
+
input = {'list' => input.size == 1 ? input.first : input}
|
74
|
+
input
|
75
|
+
end
|
76
|
+
|
77
|
+
def process_send_campaign_result(data)
|
78
|
+
Contactology::SendResult.new(data)
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'contactology/campaign'
|
2
|
+
require 'contactology/campaigns'
|
3
|
+
|
4
|
+
class Contactology::Campaigns::Transactional < Contactology::Campaign
|
5
|
+
property :test_contact, :from => :testContact
|
6
|
+
property :test_replacements, :from => :testReplacements
|
7
|
+
|
8
|
+
|
9
|
+
def self.create(attributes, options = {})
|
10
|
+
new(attributes).save(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
##
|
15
|
+
# Public: Stores the campaign information onto Contactology.
|
16
|
+
#
|
17
|
+
# Returns a Transactional instance with the campaign ID when successful.
|
18
|
+
# Returns a Contactology::SendResult instance with issues on failure.
|
19
|
+
#
|
20
|
+
def save(options = {})
|
21
|
+
self.class.query('Campaign_Create_Transactional', options.merge({
|
22
|
+
'campaignName' => name,
|
23
|
+
'content' => content,
|
24
|
+
'senderEmail' => sender_email,
|
25
|
+
'senderName' => sender_name,
|
26
|
+
'subject' => subject,
|
27
|
+
'testContact' => test_contact,
|
28
|
+
'testReplacements' => test_replacements,
|
29
|
+
'optionalParameters' => {
|
30
|
+
'authenticate' => authenticate,
|
31
|
+
'automaticTweet' => automatic_tweet,
|
32
|
+
'clickTaleCustomFields' => click_tale_custom_fields,
|
33
|
+
'clickTaleName' => click_tale_name,
|
34
|
+
'googleAnalyticsName' => google_analytics_name,
|
35
|
+
'recipientName' => recipient_name,
|
36
|
+
'replyToEmail' => reply_to_email,
|
37
|
+
'replyToName' => reply_to_name,
|
38
|
+
'showInArchive' => show_in_archive,
|
39
|
+
'trackClickThruHTML' => track_click_thru_html,
|
40
|
+
'trackClickThruText' => track_click_thru_text,
|
41
|
+
'trackOpens' => track_opens,
|
42
|
+
'trackReplies' => track_replies,
|
43
|
+
'viewInBrowser' => view_in_browser
|
44
|
+
},
|
45
|
+
:on_error => Proc.new { |response| process_send_campaign_result response },
|
46
|
+
:on_timeout => process_send_campaign_result('success' => false, 'issues' => [{'text' => 'Connection error'}]),
|
47
|
+
:on_success => Proc.new { |response| self.id = response; self }
|
48
|
+
}))
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
|
55
|
+
def process_send_campaign_result(data)
|
56
|
+
Contactology::SendResult.new(data)
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
##
|
2
|
+
# Holds configuration objects used by the library. The Contactology module
|
3
|
+
# holds reference to a default Configuration, which will be used when no
|
4
|
+
# explicit configurations are given to a particular query.
|
5
|
+
#
|
6
|
+
class Contactology::Configuration
|
7
|
+
##
|
8
|
+
# Public: Set the API endpoint to be used.
|
9
|
+
#
|
10
|
+
# endpoint - The String to use for the API endpoint.
|
11
|
+
#
|
12
|
+
# Returns nothing.
|
13
|
+
#
|
14
|
+
attr_writer :endpoint
|
15
|
+
|
16
|
+
##
|
17
|
+
# Public: Get the API key used for queries.
|
18
|
+
#
|
19
|
+
# Returns the String of the key.
|
20
|
+
#
|
21
|
+
attr_reader :key
|
22
|
+
#
|
23
|
+
##
|
24
|
+
# Public: Set the API key used for queries.
|
25
|
+
#
|
26
|
+
# key - The String to use for the API key.
|
27
|
+
#
|
28
|
+
# Returns nothing.
|
29
|
+
#
|
30
|
+
attr_writer :key
|
31
|
+
|
32
|
+
##
|
33
|
+
# Public: Get the API endpoint used by the configuration. Unless explicitly
|
34
|
+
# set, the endpoint will default to the official production endpoint at
|
35
|
+
# "https://api.emailcampaigns.net/2/REST/".
|
36
|
+
#
|
37
|
+
# Returns the String for the API endpoint.
|
38
|
+
#
|
39
|
+
def endpoint
|
40
|
+
@endpoint ||= 'https://api.emailcampaigns.net/2/REST/'
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'contactology/stash'
|
2
|
+
require 'contactology/api'
|
3
|
+
|
4
|
+
module Contactology
|
5
|
+
##
|
6
|
+
# Represents a Contact on Contactology. Contacts always must have an email
|
7
|
+
# address and then may optionally carry other custom fields.
|
8
|
+
#
|
9
|
+
class Contact < Contactology::Stash
|
10
|
+
extend API
|
11
|
+
|
12
|
+
property :id, :from => :contactId
|
13
|
+
property :email, :required => true
|
14
|
+
property :status
|
15
|
+
property :source
|
16
|
+
property :custom_fields, :from => :customFields
|
17
|
+
|
18
|
+
|
19
|
+
##
|
20
|
+
# Public: Create a new contact. The only required attribute is an :email
|
21
|
+
# address.
|
22
|
+
#
|
23
|
+
# Examples
|
24
|
+
#
|
25
|
+
# Contactology::Contact.create(:email => 'joe@example.local')
|
26
|
+
# # => #<Contactology::Contact:0x000... @email="joe@example.com" ...>
|
27
|
+
#
|
28
|
+
# Returns a Contactology::Contact instance when successful.
|
29
|
+
# Returns false when unsuccessful or a network error occurs.
|
30
|
+
#
|
31
|
+
def self.create(attributes, options = {})
|
32
|
+
contact = new(attributes)
|
33
|
+
contact.save(options) ? contact : false
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Public: Lookup a contact's information by email address.
|
38
|
+
#
|
39
|
+
# Examples
|
40
|
+
#
|
41
|
+
# Contactology::Contact.find('joe@example.local')
|
42
|
+
# # => #<Contactology::Contact:0x000... @email="joe@example.local" ...>
|
43
|
+
#
|
44
|
+
# Returns a Contactology::Contact instance when a match is found. Otherise,
|
45
|
+
# returns nil.
|
46
|
+
#
|
47
|
+
def self.find(email, options = {})
|
48
|
+
query('Contact_Get', options.merge({
|
49
|
+
'email' => email,
|
50
|
+
'optionalParameters' => {'getAllCustomFields' => true},
|
51
|
+
:on_timeout => nil,
|
52
|
+
:on_error => nil,
|
53
|
+
:on_success => Proc.new { |response|
|
54
|
+
Contact.new(response.values.first) if response.respond_to?(:values)
|
55
|
+
}
|
56
|
+
}))
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
##
|
61
|
+
# Public: Indicates whether or not the contact is active. Active contacts
|
62
|
+
# may receive mailings from your campaigns.
|
63
|
+
#
|
64
|
+
# Returns true if active.
|
65
|
+
# Returns false if non-active.
|
66
|
+
#
|
67
|
+
def active?
|
68
|
+
status == 'active'
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Public: Indicates whether or not the contact has a bounced address. This
|
73
|
+
# means that mail delivery has failed in a way that Contactology is no
|
74
|
+
# longer sending mailings to this contact.
|
75
|
+
#
|
76
|
+
# Returns true if bounced.
|
77
|
+
# Returns false if non-bounced.
|
78
|
+
#
|
79
|
+
def bounced?
|
80
|
+
status == 'bounced'
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Public: Changes the contact's email address to the new address given.
|
85
|
+
#
|
86
|
+
# Examples
|
87
|
+
#
|
88
|
+
# contact = Contactology::Contact.find('joe@example.local')
|
89
|
+
# # => #<Contactology::Contact:0x000... @email="joe@example.local" ...>
|
90
|
+
# contact.change_email('jim@example.local')
|
91
|
+
# # => true
|
92
|
+
# contact.email
|
93
|
+
# # => 'jim@example.local'
|
94
|
+
#
|
95
|
+
# Returns true when successful.
|
96
|
+
# Returns false when unsuccessful or for a network failure.
|
97
|
+
#
|
98
|
+
def change_email(new_email, options = {})
|
99
|
+
self.class.query('Contact_Change_Email', options.merge({
|
100
|
+
'email' => email,
|
101
|
+
'newEmail' => new_email,
|
102
|
+
:on_timeout => false,
|
103
|
+
:on_error => false,
|
104
|
+
:on_success => Proc.new { |response| self.email = new_email; true }
|
105
|
+
}))
|
106
|
+
end
|
107
|
+
|
108
|
+
def deleted?
|
109
|
+
status == 'deleted'
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Public: Removes the contact from Contactology and from your account.
|
114
|
+
#
|
115
|
+
# Examples
|
116
|
+
#
|
117
|
+
# contact = Contactology::Contact.find('joe@example.local')
|
118
|
+
# # => #<Contactology::Contact:0x000... @email="joe@example.local" ...>
|
119
|
+
# contact.destroy
|
120
|
+
# # => true
|
121
|
+
#
|
122
|
+
# Returns true when successful.
|
123
|
+
# Returns false when unsuccessful or for a network failure.
|
124
|
+
#
|
125
|
+
def destroy(options = {})
|
126
|
+
self.class.query('Contact_Delete', options.merge({
|
127
|
+
:email => email,
|
128
|
+
:on_timeout => false,
|
129
|
+
:on_error => false,
|
130
|
+
:on_success => Proc.new { |r| self.status = 'deleted'; true }
|
131
|
+
}))
|
132
|
+
end
|
133
|
+
|
134
|
+
def lists(options = {})
|
135
|
+
self.class.query('Contact_Get_Subscriptions', options.merge({
|
136
|
+
'email' => email,
|
137
|
+
:on_timeout => [],
|
138
|
+
:on_error => [],
|
139
|
+
:on_success => Proc.new { |response|
|
140
|
+
response.collect { |listid| ListProxy.new(listid) }
|
141
|
+
}
|
142
|
+
}))
|
143
|
+
end
|
144
|
+
|
145
|
+
def save(options = {})
|
146
|
+
self.class.query('Contact_Add', {
|
147
|
+
'email' => email,
|
148
|
+
'customFields' => custom_fields,
|
149
|
+
'optionalParameters' => {'updateCustomFields' => true},
|
150
|
+
:on_timeout => false,
|
151
|
+
:on_error => false,
|
152
|
+
:on_success => Proc.new { |response| self.status = 'active'; self }
|
153
|
+
})
|
154
|
+
end
|
155
|
+
|
156
|
+
def save!(options = {})
|
157
|
+
save(options) || raise(InvalidObjectError)
|
158
|
+
end
|
159
|
+
|
160
|
+
##
|
161
|
+
# Public: Suppresses the contact, removing them from receiving campaign
|
162
|
+
# mailings.
|
163
|
+
#
|
164
|
+
# Returns true when successful.
|
165
|
+
# Returns false when unsuccessful.
|
166
|
+
#
|
167
|
+
def suppress(options = {})
|
168
|
+
response = self.class.query('Contact_Suppress', options.merge({
|
169
|
+
:email => email,
|
170
|
+
:on_timeout => false,
|
171
|
+
:on_error => false,
|
172
|
+
:on_success => Proc.new { |response| response }
|
173
|
+
}))
|
174
|
+
|
175
|
+
if response
|
176
|
+
self.status = 'suppressed'
|
177
|
+
end
|
178
|
+
|
179
|
+
response
|
180
|
+
end
|
181
|
+
|
182
|
+
##
|
183
|
+
# Public: Indicates whether or not the contact is suppressed. Suppressed
|
184
|
+
# contacts may not receive mailings from your campaigns.
|
185
|
+
#
|
186
|
+
# Returns true if suppressed.
|
187
|
+
# Returns false if non-suppressed.
|
188
|
+
#
|
189
|
+
def suppressed?
|
190
|
+
status == 'suppressed'
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Contactology
|
2
|
+
class Issue
|
3
|
+
attr_reader :type
|
4
|
+
attr_reader :text
|
5
|
+
attr_reader :message
|
6
|
+
attr_reader :context
|
7
|
+
attr_reader :col
|
8
|
+
attr_reader :deduction
|
9
|
+
|
10
|
+
def initialize(details)
|
11
|
+
details = Hash.new unless details.kind_of?(Hash)
|
12
|
+
@type = details['type']
|
13
|
+
@text = details['text']
|
14
|
+
@message = details['message']
|
15
|
+
@context = details['context']
|
16
|
+
@col = details['col']
|
17
|
+
@deduction = details['deduction']
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
"%s: %s, %d point deduction" % [type, text || message, deduction]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'contactology/issue'
|
2
|
+
|
3
|
+
module Contactology
|
4
|
+
class Issues < Array
|
5
|
+
attr_reader :score
|
6
|
+
|
7
|
+
def initialize(data = nil)
|
8
|
+
data = Hash.new unless data.kind_of?(Hash)
|
9
|
+
@score = data['score'] || 0
|
10
|
+
(data['issues'] || []).each { |i| self << i }
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def <<(o)
|
15
|
+
super(Issue.new(o))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
require 'contactology/stash'
|
2
|
+
require 'contactology/api'
|
3
|
+
|
4
|
+
module Contactology
|
5
|
+
##
|
6
|
+
# Represents a subscription List in Contactology. Lists are a convenient way
|
7
|
+
# to organize groups of Contacts in order to send large numbers of contacts
|
8
|
+
# a Campaign, easily.
|
9
|
+
#
|
10
|
+
class List < Contactology::Stash
|
11
|
+
extend API
|
12
|
+
|
13
|
+
property :id, :from => :listId
|
14
|
+
property :name, :required => true
|
15
|
+
property :description
|
16
|
+
property :type
|
17
|
+
property :opt_in, :from => :optIn
|
18
|
+
|
19
|
+
|
20
|
+
##
|
21
|
+
# Public: Returns a collection of all active lists on your account.
|
22
|
+
#
|
23
|
+
# Returns a collection of Contactology::List instances.
|
24
|
+
#
|
25
|
+
def self.all(options = {})
|
26
|
+
query('List_Get_Active_Lists', options.merge({
|
27
|
+
:on_timeout => [],
|
28
|
+
:on_error => [],
|
29
|
+
:on_success => Proc.new { |response| response.values.collect { |list| List.new(list) }}
|
30
|
+
}))
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Public: Creates a new, public list on Contactology. The new list's :name
|
35
|
+
# is the only required attribute.
|
36
|
+
#
|
37
|
+
# Returns a Contactology::List instance when successful.
|
38
|
+
# Returns false when unsuccessful or a network failure occurs.
|
39
|
+
#
|
40
|
+
def self.create(attributes, options = {})
|
41
|
+
raise ArgumentError, 'Expected an :name attribute' unless attributes.has_key?(:name)
|
42
|
+
new(attributes).save(options)
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Public: Loads a Contactology list by ID.
|
47
|
+
#
|
48
|
+
# Returns a Contactology::List instance on success.
|
49
|
+
# Returns nil for an unknown ID or network error.
|
50
|
+
#
|
51
|
+
def self.find(id, options = {})
|
52
|
+
query('List_Get_Info', options.merge({
|
53
|
+
'listId' => id,
|
54
|
+
:on_timeout => nil,
|
55
|
+
:on_error => nil,
|
56
|
+
:on_success => Proc.new { |response| new(response) if response.kind_of?(Hash) }
|
57
|
+
}))
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
##
|
62
|
+
# Public: Removes a list from Contactology.
|
63
|
+
#
|
64
|
+
# Returns true when successful.
|
65
|
+
# Returns false when unsuccessful.
|
66
|
+
#
|
67
|
+
def destroy(options = {})
|
68
|
+
self.class.query('List_Delete', options.merge({
|
69
|
+
'listId' => id,
|
70
|
+
:on_timeout => false,
|
71
|
+
:on_error => false,
|
72
|
+
:on_success => Proc.new { |response| response }
|
73
|
+
}))
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Public: Imports contacts into a list using a prescribed contact
|
78
|
+
# collection format.
|
79
|
+
#
|
80
|
+
# Examples
|
81
|
+
#
|
82
|
+
# list = Contactology::List.create :name => 'import-test'
|
83
|
+
# # => #<Contactology::List:0x000... @name="import-test" ...>
|
84
|
+
# list.import([{'email' => 'import@example.local', 'first_name' => 'Imp', 'last_name' => 'Orted'}, {...}])
|
85
|
+
# # => true
|
86
|
+
#
|
87
|
+
# Returns true if all contacts imported successfully.
|
88
|
+
# Returns false if any contact import failed or a network error occurred.
|
89
|
+
#
|
90
|
+
def import(contacts, options = {})
|
91
|
+
self.class.query('List_Import_Contacts', options.merge({
|
92
|
+
'listId' => id,
|
93
|
+
'source' => options[:source] || 'Manual Entry',
|
94
|
+
'contacts' => contacts,
|
95
|
+
'optionalParameters' => {
|
96
|
+
'activateDeleted' => true,
|
97
|
+
'updateCustomFields' => true
|
98
|
+
},
|
99
|
+
:on_timeout => false,
|
100
|
+
:on_error => false,
|
101
|
+
:on_success => Proc.new { |response|
|
102
|
+
response.kind_of?(Hash) && response['success'] == contacts.size
|
103
|
+
}
|
104
|
+
}))
|
105
|
+
end
|
106
|
+
|
107
|
+
def internal?
|
108
|
+
type == 'internal'
|
109
|
+
end
|
110
|
+
|
111
|
+
def opt_in?
|
112
|
+
opt_in
|
113
|
+
end
|
114
|
+
|
115
|
+
def public?
|
116
|
+
type == 'public'
|
117
|
+
end
|
118
|
+
|
119
|
+
def private?
|
120
|
+
type == 'private'
|
121
|
+
end
|
122
|
+
|
123
|
+
def save(options = {})
|
124
|
+
self.class.query('List_Add_Public', options.merge({
|
125
|
+
'listId' => id,
|
126
|
+
'name' => name,
|
127
|
+
'description' => description,
|
128
|
+
'optionalParameters' => {
|
129
|
+
'optIn' => opt_in
|
130
|
+
},
|
131
|
+
:on_timeout => false,
|
132
|
+
:on_error => false,
|
133
|
+
:on_success => Proc.new { |response|
|
134
|
+
data = self.class.find(response)
|
135
|
+
self.id = data.id
|
136
|
+
self.description = data.description
|
137
|
+
self.name = data.name
|
138
|
+
self.type = data.type
|
139
|
+
self.opt_in = data.opt_in
|
140
|
+
self
|
141
|
+
}
|
142
|
+
}))
|
143
|
+
end
|
144
|
+
|
145
|
+
def save!(options = {})
|
146
|
+
save(options) || raise(InvalidObjectError)
|
147
|
+
end
|
148
|
+
|
149
|
+
##
|
150
|
+
# Public: Adds an email address to the list.
|
151
|
+
#
|
152
|
+
# Examples
|
153
|
+
#
|
154
|
+
# list = Contactology::List.find 1
|
155
|
+
# # => #<Contactology::List:0x000... @id="1" ...>
|
156
|
+
# list.subscribe 'new@example.local'
|
157
|
+
# # => true
|
158
|
+
#
|
159
|
+
# Returns true when the address is successfully added.
|
160
|
+
# Returns false when the subscription fails or a network error occurs.
|
161
|
+
#
|
162
|
+
def subscribe(email, options = {})
|
163
|
+
self.class.query('List_Subscribe', options.merge({
|
164
|
+
'listId' => id,
|
165
|
+
'email' => email.respond_to?(:email) ? email.email : email,
|
166
|
+
:on_timeout => false,
|
167
|
+
:on_error => false,
|
168
|
+
:on_success => Proc.new { |response| response }
|
169
|
+
}))
|
170
|
+
end
|
171
|
+
|
172
|
+
def test?
|
173
|
+
type == 'test'
|
174
|
+
end
|
175
|
+
|
176
|
+
##
|
177
|
+
# Public: Unsubscribes an email address from the Contactology::List.
|
178
|
+
#
|
179
|
+
# Returns true when the address is removed.
|
180
|
+
# Returns false when the removal fails or a network error occurs.
|
181
|
+
#
|
182
|
+
def unsubscribe(email, options = {})
|
183
|
+
self.class.query('List_Unsubscribe', options.merge({
|
184
|
+
'listId' => id,
|
185
|
+
'email' => email,
|
186
|
+
:on_timeout => false,
|
187
|
+
:on_error => false,
|
188
|
+
:on_success => Proc.new { |response| response }
|
189
|
+
}))
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|