contactology 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/.gitignore +5 -0
  2. data/.infinity_test +16 -0
  3. data/.rspec +3 -0
  4. data/.rvmrc +41 -0
  5. data/.watchr +36 -0
  6. data/Gemfile +6 -0
  7. data/Rakefile +1 -0
  8. data/contactology.gemspec +28 -0
  9. data/lib/contactology.rb +125 -0
  10. data/lib/contactology/api.rb +80 -0
  11. data/lib/contactology/basic_object.rb +21 -0
  12. data/lib/contactology/campaign.rb +127 -0
  13. data/lib/contactology/campaign/preview.rb +11 -0
  14. data/lib/contactology/campaigns.rb +2 -0
  15. data/lib/contactology/campaigns/standard.rb +80 -0
  16. data/lib/contactology/campaigns/transactional.rb +58 -0
  17. data/lib/contactology/configuration.rb +42 -0
  18. data/lib/contactology/contact.rb +193 -0
  19. data/lib/contactology/errors.rb +4 -0
  20. data/lib/contactology/issue.rb +24 -0
  21. data/lib/contactology/issues.rb +18 -0
  22. data/lib/contactology/list.rb +192 -0
  23. data/lib/contactology/list_proxy.rb +25 -0
  24. data/lib/contactology/parser.rb +5 -0
  25. data/lib/contactology/send_result.rb +35 -0
  26. data/lib/contactology/stash.rb +29 -0
  27. data/lib/contactology/transactional_message.rb +38 -0
  28. data/lib/contactology/version.rb +3 -0
  29. data/spec/factories/campaigns.rb +18 -0
  30. data/spec/factories/contacts.rb +3 -0
  31. data/spec/factories/issues.rb +9 -0
  32. data/spec/factories/lists.rb +3 -0
  33. data/spec/factories/transactional_messages.rb +5 -0
  34. data/spec/fixtures/net/campaign/destroy.yml +246 -0
  35. data/spec/fixtures/net/campaign/find/failure.yml +36 -0
  36. data/spec/fixtures/net/campaign/find/success.yml +176 -0
  37. data/spec/fixtures/net/campaign/find_by_name/failure.yml +36 -0
  38. data/spec/fixtures/net/campaign/find_by_name/success.yml +211 -0
  39. data/spec/fixtures/net/campaign/preview.yml +106 -0
  40. data/spec/fixtures/net/campaigns/standard/create/failure.yml +106 -0
  41. data/spec/fixtures/net/campaigns/standard/create/invalid.yml +141 -0
  42. data/spec/fixtures/net/campaigns/standard/create/success.yml +176 -0
  43. data/spec/fixtures/net/campaigns/standard/send_campaign/failure.yml +316 -0
  44. data/spec/fixtures/net/campaigns/standard/send_campaign/success.yml +316 -0
  45. data/spec/fixtures/net/campaigns/transactional/create/failure.yml +36 -0
  46. data/spec/fixtures/net/campaigns/transactional/create/success.yml +71 -0
  47. data/spec/fixtures/net/contact/active.yml +106 -0
  48. data/spec/fixtures/net/contact/change_email/success.yml +176 -0
  49. data/spec/fixtures/net/contact/change_email/unknown.yml +36 -0
  50. data/spec/fixtures/net/contact/create.yml +106 -0
  51. data/spec/fixtures/net/contact/destroy.yml +141 -0
  52. data/spec/fixtures/net/contact/find/active.yml +106 -0
  53. data/spec/fixtures/net/contact/find/suppressed.yml +141 -0
  54. data/spec/fixtures/net/contact/find/unknown.yml +36 -0
  55. data/spec/fixtures/net/contact/lists/empty.yml +106 -0
  56. data/spec/fixtures/net/contact/lists/full.yml +246 -0
  57. data/spec/fixtures/net/contact/lists/unknown.yml +71 -0
  58. data/spec/fixtures/net/contact/suppress.yml +141 -0
  59. data/spec/fixtures/net/list/all.yml +141 -0
  60. data/spec/fixtures/net/list/create.yml +106 -0
  61. data/spec/fixtures/net/list/destroy.yml +176 -0
  62. data/spec/fixtures/net/list/find/success.yml +141 -0
  63. data/spec/fixtures/net/list/find/unknown.yml +36 -0
  64. data/spec/fixtures/net/list/import/success.yml +351 -0
  65. data/spec/fixtures/net/list/subscribe/success.yml +211 -0
  66. data/spec/fixtures/net/list/unsubscribe/success.yml +246 -0
  67. data/spec/fixtures/net/transactional_message/send_message/failure.yml +176 -0
  68. data/spec/fixtures/net/transactional_message/send_message/success.yml +176 -0
  69. data/spec/models/contactology/api_spec.rb +51 -0
  70. data/spec/models/contactology/campaign_spec.rb +75 -0
  71. data/spec/models/contactology/campaigns/standard_spec.rb +84 -0
  72. data/spec/models/contactology/campaigns/transactional_spec.rb +28 -0
  73. data/spec/models/contactology/configuration_spec.rb +29 -0
  74. data/spec/models/contactology/contact_spec.rb +175 -0
  75. data/spec/models/contactology/issues_spec.rb +34 -0
  76. data/spec/models/contactology/list_spec.rb +125 -0
  77. data/spec/models/contactology/send_result_spec.rb +65 -0
  78. data/spec/models/contactology/stash_spec.rb +65 -0
  79. data/spec/models/contactology/transactional_message_spec.rb +65 -0
  80. data/spec/models/contactology_spec.rb +67 -0
  81. data/spec/requests/contacts_spec.rb +4 -0
  82. data/spec/spec_helper.rb +15 -0
  83. data/spec/support/contactology.rb +34 -0
  84. data/spec/support/factory_girl.rb +19 -0
  85. data/spec/support/vcr.rb +11 -0
  86. metadata +282 -0
@@ -0,0 +1,25 @@
1
+ require 'contactology/basic_object'
2
+ require 'contactology/list'
3
+
4
+ module Contactology
5
+ class ListProxy < ::Contactology::BasicObject
6
+ attr_reader :list_id
7
+
8
+ def initialize(list_id)
9
+ @list_id = list_id
10
+ end
11
+
12
+
13
+ private
14
+
15
+
16
+ def get_list(id)
17
+ List.find(id)
18
+ end
19
+
20
+ def method_missing(method, *args, &block)
21
+ @list ||= get_list(list_id)
22
+ @list.send(method, *args, &block) if @list
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ module Contactology
2
+ class Parser < HTTParty::Parser
3
+ SupportedFormats.merge!({'text/plain' => :json})
4
+ end
5
+ end
@@ -0,0 +1,35 @@
1
+ require 'contactology/issues'
2
+
3
+ module Contactology
4
+ ##
5
+ # Contains the campaign send request results which indicate success or
6
+ # failure, as well as any issues found with the campaign.
7
+ #
8
+ class SendResult
9
+ attr_reader :issues
10
+
11
+ def initialize(response)
12
+ @success = response['success']
13
+ @issues = Issues.new(response['issues'])
14
+ end
15
+
16
+ ##
17
+ # Public: Indicates whether or not the send was successful
18
+ #
19
+ # Returns true when successful.
20
+ # Returns false when unsuccessful.
21
+ #
22
+ def successful?
23
+ !!@success
24
+ end
25
+
26
+ ##
27
+ # Public: Returns the spam score of the campaign.
28
+ #
29
+ # Returns a numeric from 0 to 100 (where higher is better).
30
+ #
31
+ def score
32
+ @issues.score
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ require 'hashie/trash'
2
+
3
+ module Contactology
4
+ ##
5
+ # A Stash is a 'suppressing' Hashie::Trash where keys that are not defined
6
+ # are simply ignored and unavailable to the local object.
7
+ #
8
+ # A Stash is useful when you need to read data from another application,
9
+ # but you only want a predefined subset of the returned data to become
10
+ # available, locally.
11
+ #
12
+ class Stash < ::Hashie::Trash
13
+ def []=(property, value)
14
+ if self.class.translations.include? property.to_sym
15
+ send("#{property}=", value)
16
+ elsif property_exists? property
17
+ super
18
+ end
19
+ end
20
+
21
+
22
+ private
23
+
24
+
25
+ def property_exists?(property)
26
+ self.class.property?(property.to_sym)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,38 @@
1
+ require 'contactology/stash'
2
+
3
+ module Contactology
4
+ class TransactionalMessage < Contactology::Stash
5
+ extend API
6
+
7
+ property :campaign, :required => true
8
+ property :contact, :required => true
9
+ property :source, :required => true
10
+ property :replacements, :required => true
11
+
12
+ def replacements
13
+ self['replacements'] || Hash.new
14
+ end
15
+
16
+ def send_message(options = {})
17
+ self.class.query('Campaign_Send_Transactional', options.merge({
18
+ 'campaignId' => campaign.id,
19
+ 'contact' => normalize_contact(contact),
20
+ 'source' => source,
21
+ 'replacements' => {:_contactology => 'Contactology'}.merge(replacements),
22
+ :on_error => false,
23
+ :on_timeout => false,
24
+ :on_success => true
25
+ }))
26
+ end
27
+
28
+
29
+ private
30
+
31
+
32
+ def normalize_contact(contact)
33
+ return contact if contact.kind_of?(Hash)
34
+
35
+ { 'email' => contact.email }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ module Contactology
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,18 @@
1
+ Factory.define :standard_campaign, :class => Contactology::Campaigns::Standard do |c|
2
+ c.content 'text' => 'This is a good message! {COMPANY_ADDRESS}'
3
+ c.name 'factory campaign'
4
+ c.recipients { Factory.build_via_new :list }
5
+ c.sender_email 'nate@envylabs.com'
6
+ c.sender_name 'Nate Bibler'
7
+ c.subject 'Factory Campaign Message'
8
+ end
9
+
10
+ Factory.define :transactional_campaign, :class => Contactology::Campaigns::Transactional do |c|
11
+ c.content 'text' => 'This is a good email. {COMPANY_ADDRESS}'
12
+ c.name 'factory campaign'
13
+ c.sender_email 'sender@example.com'
14
+ c.sender_name 'Sender Example'
15
+ c.subject 'Test Creation'
16
+ c.test_contact 'email' => 'test-contact@example.com'
17
+ c.test_replacements 'first_name' => 'John'
18
+ end
@@ -0,0 +1,3 @@
1
+ Factory.define :contact, :class => Contactology::Contact do |c|
2
+ c.email 'factory-contact@example.com'
3
+ end
@@ -0,0 +1,9 @@
1
+ Factory.define :issue, :class => Contactology::Issue do |i|
2
+ i.level ''
3
+ i.type 'SPAM'
4
+ i.text 'BODY: TVD_SPACE_RATIO'
5
+ i.message ''
6
+ i.context ''
7
+ i.col ''
8
+ i.deduction 29
9
+ end
@@ -0,0 +1,3 @@
1
+ Factory.define :list, :class => Contactology::List do |l|
2
+ l.name 'Factory List'
3
+ end
@@ -0,0 +1,5 @@
1
+ Factory.define :transactional_message, :class => Contactology::TransactionalMessage do |m|
2
+ m.campaign { Factory.build_via_new :transactional_campaign }
3
+ m.contact { Factory.attributes_for :contact }
4
+ m.source 'Factory Created'
5
+ end
@@ -0,0 +1,246 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: https://api.emailcampaigns.net:443/2/REST/?key=%{API_KEY}&method=List_Add_Public&name=Factory%20List
6
+ body:
7
+ headers:
8
+ accept:
9
+ - application/json
10
+ user-agent:
11
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
12
+ response: !ruby/struct:VCR::Response
13
+ status: !ruby/struct:VCR::ResponseStatus
14
+ code: 200
15
+ message: OK
16
+ headers:
17
+ x-powered-by:
18
+ - PHP/5.2.10
19
+ set-cookie:
20
+ - PHPSESSID=6a8cdfd44b31c3d7987dd6492f075491; path=/
21
+ expires:
22
+ - Thu, 19 Nov 1981 08:52:00 GMT
23
+ cache-control:
24
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
25
+ pragma:
26
+ - no-cache
27
+ content-type:
28
+ - text/plain;charset=UTF-8
29
+ transfer-encoding:
30
+ - chunked
31
+ date:
32
+ - Wed, 03 Aug 2011 18:23:53 GMT
33
+ server:
34
+ - lighttpd/1.4.28
35
+ body: "46"
36
+ http_version: "1.1"
37
+ - !ruby/struct:VCR::HTTPInteraction
38
+ request: !ruby/struct:VCR::Request
39
+ method: :get
40
+ uri: https://api.emailcampaigns.net:443/2/REST/?key=%{API_KEY}&listId=46&method=List_Get_Info
41
+ body:
42
+ headers:
43
+ accept:
44
+ - application/json
45
+ user-agent:
46
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
47
+ response: !ruby/struct:VCR::Response
48
+ status: !ruby/struct:VCR::ResponseStatus
49
+ code: 200
50
+ message: OK
51
+ headers:
52
+ x-powered-by:
53
+ - PHP/5.2.10
54
+ set-cookie:
55
+ - PHPSESSID=295f4ba34b7f033e8cad0c6cf83b9b75; path=/
56
+ expires:
57
+ - Thu, 19 Nov 1981 08:52:00 GMT
58
+ cache-control:
59
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
60
+ pragma:
61
+ - no-cache
62
+ content-type:
63
+ - text/plain;charset=UTF-8
64
+ transfer-encoding:
65
+ - chunked
66
+ date:
67
+ - Wed, 03 Aug 2011 18:23:57 GMT
68
+ server:
69
+ - lighttpd/1.4.28
70
+ body: "{\"listId\":\"46\",\"name\":\"Factory List\",\"description\":null,\"type\":\"public\",\"optIn\":false}"
71
+ http_version: "1.1"
72
+ - !ruby/struct:VCR::HTTPInteraction
73
+ request: !ruby/struct:VCR::Request
74
+ method: :get
75
+ uri: https://api.emailcampaigns.net:443/2/REST/?campaignName=factory%20campaign&key=%{API_KEY}&method=Campaign_Create_Standard&senderEmail=nate@envylabs.com&senderName=Nate%20Bibler&subject=Factory%20Campaign%20Message&content%5Btext%5D=This%20is%20a%20good%20message!%20%7BCOMPANY_ADDRESS%7D&recipients%5Blist%5D=46
76
+ body:
77
+ headers:
78
+ accept:
79
+ - application/json
80
+ user-agent:
81
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
82
+ response: !ruby/struct:VCR::Response
83
+ status: !ruby/struct:VCR::ResponseStatus
84
+ code: 200
85
+ message: OK
86
+ headers:
87
+ x-powered-by:
88
+ - PHP/5.2.10
89
+ set-cookie:
90
+ - PHPSESSID=3b70f5bce9c49f9029c6ff3472b58274; path=/
91
+ expires:
92
+ - Thu, 19 Nov 1981 08:52:00 GMT
93
+ cache-control:
94
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
95
+ pragma:
96
+ - no-cache
97
+ content-type:
98
+ - text/plain;charset=UTF-8
99
+ transfer-encoding:
100
+ - chunked
101
+ date:
102
+ - Wed, 03 Aug 2011 18:23:58 GMT
103
+ server:
104
+ - lighttpd/1.4.28
105
+ body: "33"
106
+ http_version: "1.1"
107
+ - !ruby/struct:VCR::HTTPInteraction
108
+ request: !ruby/struct:VCR::Request
109
+ method: :get
110
+ uri: https://api.emailcampaigns.net:443/2/REST/?campaignId=33&key=%{API_KEY}&method=Campaign_Get_Info
111
+ body:
112
+ headers:
113
+ accept:
114
+ - application/json
115
+ user-agent:
116
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
117
+ response: !ruby/struct:VCR::Response
118
+ status: !ruby/struct:VCR::ResponseStatus
119
+ code: 200
120
+ message: OK
121
+ headers:
122
+ x-powered-by:
123
+ - PHP/5.2.10
124
+ set-cookie:
125
+ - PHPSESSID=f0b1859e137c96c71fa9dacdf108536e; path=/
126
+ expires:
127
+ - Thu, 19 Nov 1981 08:52:00 GMT
128
+ cache-control:
129
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
130
+ pragma:
131
+ - no-cache
132
+ content-type:
133
+ - text/plain;charset=UTF-8
134
+ transfer-encoding:
135
+ - chunked
136
+ date:
137
+ - Wed, 03 Aug 2011 18:23:59 GMT
138
+ server:
139
+ - lighttpd/1.4.28
140
+ body: "{\"campaignId\":\"33\",\"campaignName\":\"factory campaign\",\"type\":\"standard\",\"contentType\":\"standard\",\"status\":\"draft\",\"recipients\":{\"list\":[\"46\"]},\"subject\":\"Factory Campaign Message\",\"senderName\":\"Nate Bibler\",\"senderEmail\":\"nate@envylabs.com\",\"recipientName\":\"\",\"replyToName\":\"\",\"replyToEmail\":null,\"content\":{\"html\":\"\",\"text\":\"This is a good message! {COMPANY_ADDRESS}\"},\"startTime\":\"2011-08-03 18:23:58\",\"authenticate\":false,\"trackReplies\":false,\"showInArchive\":false,\"viewInBrowser\":false,\"trackOpens\":true,\"trackClickThruHTML\":true,\"trackClickThruText\":true,\"googleAnalyticsName\":null,\"automaticTweet\":false,\"clickTaleName\":null,\"clickTaleCustomFields\":[\"\"],\"useCustomUrlParameters\":null,\"customUrlParameters\":null}"
141
+ http_version: "1.1"
142
+ - !ruby/struct:VCR::HTTPInteraction
143
+ request: !ruby/struct:VCR::Request
144
+ method: :get
145
+ uri: https://api.emailcampaigns.net:443/2/REST/?key=%{API_KEY}&listId=46&method=List_Delete
146
+ body:
147
+ headers:
148
+ accept:
149
+ - application/json
150
+ user-agent:
151
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
152
+ response: !ruby/struct:VCR::Response
153
+ status: !ruby/struct:VCR::ResponseStatus
154
+ code: 200
155
+ message: OK
156
+ headers:
157
+ x-powered-by:
158
+ - PHP/5.2.10
159
+ set-cookie:
160
+ - PHPSESSID=84399ae8907f376ee7017cb061cb3b3f; path=/
161
+ expires:
162
+ - Thu, 19 Nov 1981 08:52:00 GMT
163
+ cache-control:
164
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
165
+ pragma:
166
+ - no-cache
167
+ content-type:
168
+ - text/plain;charset=UTF-8
169
+ transfer-encoding:
170
+ - chunked
171
+ date:
172
+ - Wed, 03 Aug 2011 18:24:00 GMT
173
+ server:
174
+ - lighttpd/1.4.28
175
+ body: "true"
176
+ http_version: "1.1"
177
+ - !ruby/struct:VCR::HTTPInteraction
178
+ request: !ruby/struct:VCR::Request
179
+ method: :get
180
+ uri: https://api.emailcampaigns.net:443/2/REST/?campaignId=33&key=%{API_KEY}&method=Campaign_Delete
181
+ body:
182
+ headers:
183
+ accept:
184
+ - application/json
185
+ user-agent:
186
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
187
+ response: !ruby/struct:VCR::Response
188
+ status: !ruby/struct:VCR::ResponseStatus
189
+ code: 200
190
+ message: OK
191
+ headers:
192
+ x-powered-by:
193
+ - PHP/5.2.10
194
+ set-cookie:
195
+ - PHPSESSID=fb7cd68453b20088187ed9db9ef0a4ff; path=/
196
+ expires:
197
+ - Thu, 19 Nov 1981 08:52:00 GMT
198
+ cache-control:
199
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
200
+ pragma:
201
+ - no-cache
202
+ content-type:
203
+ - text/plain;charset=UTF-8
204
+ transfer-encoding:
205
+ - chunked
206
+ date:
207
+ - Wed, 03 Aug 2011 18:24:00 GMT
208
+ server:
209
+ - lighttpd/1.4.28
210
+ body: "true"
211
+ http_version: "1.1"
212
+ - !ruby/struct:VCR::HTTPInteraction
213
+ request: !ruby/struct:VCR::Request
214
+ method: :get
215
+ uri: https://api.emailcampaigns.net:443/2/REST/?campaignId=33&key=%{API_KEY}&method=Campaign_Get_Info
216
+ body:
217
+ headers:
218
+ accept:
219
+ - application/json
220
+ user-agent:
221
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
222
+ response: !ruby/struct:VCR::Response
223
+ status: !ruby/struct:VCR::ResponseStatus
224
+ code: 200
225
+ message: OK
226
+ headers:
227
+ x-powered-by:
228
+ - PHP/5.2.10
229
+ set-cookie:
230
+ - PHPSESSID=518ac479af356a6ffd117517bb197180; path=/
231
+ expires:
232
+ - Thu, 19 Nov 1981 08:52:00 GMT
233
+ cache-control:
234
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
235
+ pragma:
236
+ - no-cache
237
+ content-type:
238
+ - text/plain;charset=UTF-8
239
+ transfer-encoding:
240
+ - chunked
241
+ date:
242
+ - Wed, 03 Aug 2011 18:24:01 GMT
243
+ server:
244
+ - lighttpd/1.4.28
245
+ body: "{\"result\":\"error\",\"message\":\"Input Error: campaignId 33 not found\",\"code\":601}"
246
+ http_version: "1.1"
@@ -0,0 +1,36 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: https://api.emailcampaigns.net:443/2/REST/?campaignId=123456789&key=%{API_KEY}&method=Campaign_Get_Info
6
+ body:
7
+ headers:
8
+ accept:
9
+ - application/json
10
+ user-agent:
11
+ - contactology/0.0.1 (Rubygems; Ruby 1.9.2 x86_64-darwin10.7.1)
12
+ response: !ruby/struct:VCR::Response
13
+ status: !ruby/struct:VCR::ResponseStatus
14
+ code: 200
15
+ message: OK
16
+ headers:
17
+ x-powered-by:
18
+ - PHP/5.2.10
19
+ set-cookie:
20
+ - PHPSESSID=891a04fa52890eb18f50ca10b699a8d1; path=/
21
+ expires:
22
+ - Thu, 19 Nov 1981 08:52:00 GMT
23
+ cache-control:
24
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
25
+ pragma:
26
+ - no-cache
27
+ content-type:
28
+ - text/plain;charset=UTF-8
29
+ transfer-encoding:
30
+ - chunked
31
+ date:
32
+ - Wed, 03 Aug 2011 18:24:35 GMT
33
+ server:
34
+ - lighttpd/1.4.28
35
+ body: "{\"result\":\"error\",\"message\":\"Input Error: campaignId 123456789 not found\",\"code\":601}"
36
+ http_version: "1.1"