constantcontact-ruby 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -0
  3. data/README.md +136 -0
  4. data/constantcontact-ruby.gemspec +31 -0
  5. data/lib/constantcontact/api.rb +1012 -0
  6. data/lib/constantcontact/auth/oauth2.rb +105 -0
  7. data/lib/constantcontact/auth/session_data_store.rb +69 -0
  8. data/lib/constantcontact/components/account/account_address.rb +26 -0
  9. data/lib/constantcontact/components/account/account_info.rb +38 -0
  10. data/lib/constantcontact/components/account/verified_email_address.rb +26 -0
  11. data/lib/constantcontact/components/activities/activity.rb +43 -0
  12. data/lib/constantcontact/components/activities/activity_error.rb +26 -0
  13. data/lib/constantcontact/components/activities/add_contacts.rb +127 -0
  14. data/lib/constantcontact/components/activities/add_contacts_import_data.rb +46 -0
  15. data/lib/constantcontact/components/activities/export_contacts.rb +30 -0
  16. data/lib/constantcontact/components/component.rb +48 -0
  17. data/lib/constantcontact/components/contacts/address.rb +27 -0
  18. data/lib/constantcontact/components/contacts/contact.rb +92 -0
  19. data/lib/constantcontact/components/contacts/contact_list.rb +26 -0
  20. data/lib/constantcontact/components/contacts/custom_field.rb +26 -0
  21. data/lib/constantcontact/components/contacts/email_address.rb +33 -0
  22. data/lib/constantcontact/components/contacts/note.rb +26 -0
  23. data/lib/constantcontact/components/email_marketing/campaign.rb +83 -0
  24. data/lib/constantcontact/components/email_marketing/campaign_preview.rb +29 -0
  25. data/lib/constantcontact/components/email_marketing/click_through_details.rb +27 -0
  26. data/lib/constantcontact/components/email_marketing/message_footer.rb +29 -0
  27. data/lib/constantcontact/components/email_marketing/schedule.rb +27 -0
  28. data/lib/constantcontact/components/email_marketing/test_send.rb +45 -0
  29. data/lib/constantcontact/components/event_spot/contact.rb +27 -0
  30. data/lib/constantcontact/components/event_spot/event.rb +69 -0
  31. data/lib/constantcontact/components/event_spot/event_address.rb +29 -0
  32. data/lib/constantcontact/components/event_spot/event_fee.rb +27 -0
  33. data/lib/constantcontact/components/event_spot/event_item.rb +36 -0
  34. data/lib/constantcontact/components/event_spot/event_item_attribute.rb +26 -0
  35. data/lib/constantcontact/components/event_spot/event_track.rb +31 -0
  36. data/lib/constantcontact/components/event_spot/guest.rb +31 -0
  37. data/lib/constantcontact/components/event_spot/guest_section.rb +34 -0
  38. data/lib/constantcontact/components/event_spot/notification_option.rb +27 -0
  39. data/lib/constantcontact/components/event_spot/online_meeting.rb +28 -0
  40. data/lib/constantcontact/components/event_spot/payment_address.rb +29 -0
  41. data/lib/constantcontact/components/event_spot/payment_summary.rb +33 -0
  42. data/lib/constantcontact/components/event_spot/promocode.rb +25 -0
  43. data/lib/constantcontact/components/event_spot/registrant.rb +52 -0
  44. data/lib/constantcontact/components/event_spot/registrant_fee.rb +29 -0
  45. data/lib/constantcontact/components/event_spot/registrant_field.rb +27 -0
  46. data/lib/constantcontact/components/event_spot/registrant_order.rb +39 -0
  47. data/lib/constantcontact/components/event_spot/registrant_promo_code.rb +31 -0
  48. data/lib/constantcontact/components/event_spot/registrant_promo_code_info.rb +27 -0
  49. data/lib/constantcontact/components/event_spot/registrant_section.rb +34 -0
  50. data/lib/constantcontact/components/event_spot/sale_item.rb +29 -0
  51. data/lib/constantcontact/components/library/file/library_file.rb +27 -0
  52. data/lib/constantcontact/components/library/folder/library_folder.rb +26 -0
  53. data/lib/constantcontact/components/library/info/library_summary.rb +26 -0
  54. data/lib/constantcontact/components/library/info/move_results.rb +26 -0
  55. data/lib/constantcontact/components/library/info/upload_status.rb +26 -0
  56. data/lib/constantcontact/components/result_set.rb +50 -0
  57. data/lib/constantcontact/components/tracking/bounce_activity.rb +28 -0
  58. data/lib/constantcontact/components/tracking/click_activity.rb +26 -0
  59. data/lib/constantcontact/components/tracking/forward_activity.rb +26 -0
  60. data/lib/constantcontact/components/tracking/open_activity.rb +26 -0
  61. data/lib/constantcontact/components/tracking/send_activity.rb +27 -0
  62. data/lib/constantcontact/components/tracking/tracking_activity.rb +26 -0
  63. data/lib/constantcontact/components/tracking/tracking_summary.rb +27 -0
  64. data/lib/constantcontact/components/tracking/unsubscribe_activity.rb +27 -0
  65. data/lib/constantcontact/exceptions/ctct_exception.rb +25 -0
  66. data/lib/constantcontact/exceptions/illegal_argument_exception.rb +11 -0
  67. data/lib/constantcontact/exceptions/oauth2_exception.rb +11 -0
  68. data/lib/constantcontact/exceptions/webhooks_exception.rb +11 -0
  69. data/lib/constantcontact/services/account_service.rb +39 -0
  70. data/lib/constantcontact/services/activity_service.rb +136 -0
  71. data/lib/constantcontact/services/base_service.rb +68 -0
  72. data/lib/constantcontact/services/campaign_schedule_service.rb +101 -0
  73. data/lib/constantcontact/services/campaign_tracking_service.rb +152 -0
  74. data/lib/constantcontact/services/contact_service.rb +105 -0
  75. data/lib/constantcontact/services/contact_tracking_service.rb +152 -0
  76. data/lib/constantcontact/services/email_marketing_service.rb +94 -0
  77. data/lib/constantcontact/services/event_spot_service.rb +448 -0
  78. data/lib/constantcontact/services/library_service.rb +281 -0
  79. data/lib/constantcontact/services/list_service.rb +81 -0
  80. data/lib/constantcontact/util/config.rb +180 -0
  81. data/lib/constantcontact/util/helpers.rb +27 -0
  82. data/lib/constantcontact/version.rb +12 -0
  83. data/lib/constantcontact/webhooks/helpers/validator.rb +30 -0
  84. data/lib/constantcontact/webhooks/models/billing_change_notification.rb +27 -0
  85. data/lib/constantcontact/webhooks/webhooks_util.rb +45 -0
  86. data/lib/constantcontact.rb +124 -0
  87. data/spec/constantcontact/api_spec.rb +1560 -0
  88. data/spec/constantcontact/auth/oauth2_spec.rb +125 -0
  89. data/spec/constantcontact/components/contacts/address_spec.rb +18 -0
  90. data/spec/constantcontact/components/contacts/contact_list_spec.rb +18 -0
  91. data/spec/constantcontact/components/contacts/contact_spec.rb +18 -0
  92. data/spec/constantcontact/components/contacts/custom_field_spec.rb +18 -0
  93. data/spec/constantcontact/components/contacts/email_address_spec.rb +18 -0
  94. data/spec/constantcontact/sdk_spec.rb +24 -0
  95. data/spec/constantcontact/services/account_service_spec.rb +46 -0
  96. data/spec/constantcontact/services/activity_service_spec.rb +244 -0
  97. data/spec/constantcontact/services/base_service_spec.rb +50 -0
  98. data/spec/constantcontact/services/campaign_schedule_service_spec.rb +115 -0
  99. data/spec/constantcontact/services/campaign_tracking_service_spec.rb +131 -0
  100. data/spec/constantcontact/services/contact_service_spec.rb +111 -0
  101. data/spec/constantcontact/services/contact_tracking_service_spec.rb +131 -0
  102. data/spec/constantcontact/services/email_marketing_spec.rb +100 -0
  103. data/spec/constantcontact/services/event_spot_spec.rb +423 -0
  104. data/spec/constantcontact/services/library_service_spec.rb +252 -0
  105. data/spec/constantcontact/services/list_service_spec.rb +89 -0
  106. data/spec/constantcontact/webhooks/webhooks_spec.rb +26 -0
  107. metadata +243 -0
@@ -0,0 +1,281 @@
1
+ #
2
+ # library_service.rb
3
+ # ConstantContact
4
+ #
5
+ # Copyright (c) 2013 Constant Contact. All rights reserved.
6
+
7
+ module ConstantContact
8
+ module Services
9
+ class LibraryService < BaseService
10
+ class << self
11
+
12
+ # Retrieve MyLibrary usage information
13
+ # @return [LibrarySummary]
14
+ def get_library_info()
15
+ url = Util::Config.get('endpoints.base_url') + Util::Config.get('endpoints.library_info')
16
+
17
+ response = RestClient.get(url, get_headers())
18
+ Components::LibrarySummary.create(JSON.parse(response.body).first)
19
+ end
20
+
21
+
22
+ # Retrieve a list of MyLibrary folders
23
+ # @param [Hash] params - hash of query parameters and values to append to the request.
24
+ # Allowed parameters include:
25
+ # sort_by - The method to sort by, valid values are :
26
+ # CREATED_DATE - sorts by date folder was added, ascending (earliest to latest)
27
+ # CREATED_DATE_DESC - (default) sorts by date folder was added, descending (latest to earliest)
28
+ # MODIFIED_DATE - sorts by date folder was last modified, ascending (earliest to latest)
29
+ # MODIFIED_DATE_DESC - sorts by date folder was last modified, descending (latest to earliest)
30
+ # NAME - sorts alphabetically by folder name, a to z
31
+ # NAME_DESC - sorts alphabetically by folder name, z to a
32
+ # limit - Specifies the number of results displayed per page of output, from 1 - 50, default = 50.
33
+ # @return [ResultSet<LibraryFolder>]
34
+ def get_library_folders(params)
35
+ url = Util::Config.get('endpoints.base_url') + Util::Config.get('endpoints.library_folders')
36
+ url = build_url(url, params)
37
+ response = RestClient.get(url, get_headers())
38
+ folders = []
39
+ body = JSON.parse(response.body)
40
+ body['results'].each do |folder|
41
+ folders << Components::LibraryFolder.create(folder)
42
+ end
43
+ Components::ResultSet.new(folders, body['meta'])
44
+ end
45
+
46
+
47
+ # Create a new MyLibrary folder
48
+ # @param [LibraryFolder] folder - MyLibrary folder to be created
49
+ # @return [LibraryFolder]
50
+ def add_library_folder(folder)
51
+ url = Util::Config.get('endpoints.base_url') + Util::Config.get('endpoints.library_folders')
52
+ url = build_url(url)
53
+ payload = folder.to_json
54
+ response = RestClient.post(url, payload, get_headers())
55
+ Components::LibraryFolder.create(JSON.parse(response.body))
56
+ end
57
+
58
+
59
+ # Retrieve a specific MyLibrary folder using the folder_id path parameter
60
+ # @param [String] folder_id - The ID for the folder to return
61
+ # @return [LibraryFolder]
62
+ def get_library_folder(folder_id)
63
+ url = Util::Config.get('endpoints.base_url') + sprintf(Util::Config.get('endpoints.library_folder'), folder_id)
64
+ url = build_url(url)
65
+ response = RestClient.get(url, get_headers())
66
+ Components::LibraryFolder.create(JSON.parse(response.body))
67
+ end
68
+
69
+
70
+ # Update a specific MyLibrary folder
71
+ # @param [LibraryFolder] folder - MyLibrary folder to be updated
72
+ # @return [LibraryFolder]
73
+ def update_library_folder(folder)
74
+ url = Util::Config.get('endpoints.base_url') +
75
+ sprintf(Util::Config.get('endpoints.library_folder'), folder.id)
76
+ url = build_url(url)
77
+ payload = folder.to_json
78
+ response = RestClient.put(url, payload, get_headers())
79
+ Components::LibraryFolder.create(JSON.parse(response.body))
80
+ end
81
+
82
+
83
+ # Delete a MyLibrary folder
84
+ # @param [String] folder_id - The ID for the MyLibrary folder to delete
85
+ # @return [Boolean]
86
+ def delete_library_folder(folder_id)
87
+ url = Util::Config.get('endpoints.base_url') + sprintf(Util::Config.get('endpoints.library_folder'), folder_id)
88
+ url = build_url(url)
89
+ response = RestClient.delete(url, get_headers())
90
+ response.code == 204
91
+ end
92
+
93
+
94
+ # Retrieve all files in the Trash folder
95
+ # @param [Hash] params - hash of query parameters and values to append to the request.
96
+ # Allowed parameters include:
97
+ # type - Specifies the type of files to retrieve, valid values are : ALL, IMAGES, or DOCUMENTS
98
+ # sort_by - The method to sort by, valid values are :
99
+ # ADDED_DATE - sorts by date folder was added, ascending (earliest to latest)
100
+ # ADDED_DATE_DESC - (default) sorts by date folder was added, descending (latest to earliest)
101
+ # MODIFIED_DATE - sorts by date folder was last modified, ascending (earliest to latest)
102
+ # MODIFIED_DATE_DESC - sorts by date folder was last modified, descending (latest to earliest)
103
+ # NAME - sorts alphabetically by file name, a to z
104
+ # NAME_DESC - sorts alphabetically by file name, z to a
105
+ # SIZE - sorts by file size, smallest to largest
106
+ # SIZE_DESC - sorts by file size, largest to smallest
107
+ # DIMENSION - sorts by file dimensions (hxw), smallest to largest
108
+ # DIMENSION_DESC - sorts by file dimensions (hxw), largest to smallest
109
+ # limit - Specifies the number of results displayed per page of output, from 1 - 50, default = 50.
110
+ # @return [ResultSet<LibraryFile>]
111
+ def get_library_trash(params)
112
+ url = Util::Config.get('endpoints.base_url') + Util::Config.get('endpoints.library_folder_trash')
113
+ url = build_url(url, params)
114
+ response = RestClient.get(url, get_headers())
115
+ files = []
116
+ body = JSON.parse(response.body)
117
+ body['results'].each do |file|
118
+ files << Components::LibraryFile.create(file)
119
+ end
120
+ Components::ResultSet.new(files, body['meta'])
121
+ end
122
+
123
+
124
+ # Permanently deletes all files in the Trash folder
125
+ # @return [Boolean]
126
+ def delete_library_trash()
127
+ url = Util::Config.get('endpoints.base_url') + Util::Config.get('endpoints.library_folder_trash')
128
+ url = build_url(url)
129
+ response = RestClient.delete(url, get_headers())
130
+ response.code == 204
131
+ end
132
+
133
+
134
+ # Retrieve a collection of MyLibrary files in the Constant Contact account
135
+ # @param [Hash] params - hash of query parameters and values to append to the request.
136
+ # Allowed parameters include:
137
+ # type - Specifies the type of files to retrieve, valid values are : ALL, IMAGES, or DOCUMENTS
138
+ # source - Specifies to retrieve files from a particular source, valid values are :
139
+ # ALL - (default) files from all sources
140
+ # MyComputer
141
+ # StockImage
142
+ # Facebook
143
+ # Instagram
144
+ # Shutterstock
145
+ # Mobile
146
+ # limit - Specifies the number of results displayed per page of output, from 1 - 1000, default = 50.
147
+ # @return [ResultSet<LibraryFile>]
148
+ def get_library_files(params = {})
149
+ url = Util::Config.get('endpoints.base_url') + Util::Config.get('endpoints.library_files')
150
+ url = build_url(url, params)
151
+ response = RestClient.get(url, get_headers())
152
+ files = []
153
+ body = JSON.parse(response.body)
154
+ body['results'].each do |file|
155
+ files << Components::LibraryFile.create(file)
156
+ end
157
+ Components::ResultSet.new(files, body['meta'])
158
+ end
159
+
160
+
161
+ # Retrieves all files from a MyLibrary folder specified by the folder_id path parameter
162
+ # @param [String] folder_id - Specifies the folder from which to retrieve files
163
+ # @param [Hash] params - hash of query parameters and values to append to the request.
164
+ # Allowed parameters include:
165
+ # limit - Specifies the number of results displayed per page of output, from 1 - 50, default = 50.
166
+ # @return [ResultSet<LibraryFile>]
167
+ def get_library_files_by_folder(folder_id, params = {})
168
+ url = Util::Config.get('endpoints.base_url') +
169
+ sprintf(Util::Config.get('endpoints.library_files_by_folder'), folder_id)
170
+ url = build_url(url, params)
171
+ response = RestClient.get(url, get_headers())
172
+ files = []
173
+ body = JSON.parse(response.body)
174
+ body['results'].each do |file|
175
+ files << Components::LibraryFile.create(file)
176
+ end
177
+ Components::ResultSet.new(files, body['meta'])
178
+ end
179
+
180
+
181
+ # Retrieve a MyLibrary file using the file_id path parameter
182
+ # @param [String] file_id - Specifies the MyLibrary file for which to retrieve information
183
+ # @return [LibraryFile]
184
+ def get_library_file(file_id)
185
+ url = Util::Config.get('endpoints.base_url') + sprintf(Util::Config.get('endpoints.library_file'), file_id)
186
+ url = build_url(url)
187
+ response = RestClient.get(url, get_headers())
188
+ Components::LibraryFile.create(JSON.parse(response.body))
189
+ end
190
+
191
+
192
+ # Adds a new MyLibrary file using the multipart content-type
193
+ # @param [String] file_name - The name of the file (ie: dinnerplate-special.jpg)
194
+ # @param [String] folder_id - Folder id to add the file to
195
+ # @param [String] description - The description of the file provided by user
196
+ # @param [String] source - indicates the source of the original file;
197
+ # image files can be uploaded from the following sources :
198
+ # MyComputer, StockImage, Facebook - MyLibrary Plus customers only,
199
+ # Instagram - MyLibrary Plus customers only, Shutterstock, Mobile
200
+ # @param [String] file_type - Specifies the file type, valid values are: JPEG, JPG, GIF, PDF, PNG
201
+ # @param [String] contents - The content of the file
202
+ # @return [LibraryFile]
203
+ def add_library_file(file_name, folder_id, description, source, file_type, contents)
204
+ url = Util::Config.get('endpoints.base_url') + Util::Config.get('endpoints.library_files')
205
+ url = build_url(url)
206
+
207
+ payload = { :file_name => file_name, :folder_id => folder_id,
208
+ :description => description, :source => source, :file_type => file_type,
209
+ :data => contents, :multipart => true }
210
+
211
+ response = RestClient.post(url, payload, get_headers())
212
+ location = response.headers[:location] || ''
213
+ location.split('/').last
214
+ end
215
+
216
+
217
+ # Update information for a specific MyLibrary file
218
+ # @param [LibraryFile] file - Library File to be updated
219
+ # @return [LibraryFile]
220
+ def update_library_file(file)
221
+ url = Util::Config.get('endpoints.base_url') + sprintf(Util::Config.get('endpoints.library_file'), file.id)
222
+ url = build_url(url)
223
+ payload = file.to_json
224
+ response = RestClient.put(url, payload, get_headers())
225
+ Components::LibraryFile.create(JSON.parse(response.body))
226
+ end
227
+
228
+
229
+ # Delete one or more MyLibrary files specified by the fileId path parameter;
230
+ # separate multiple file IDs with a comma.
231
+ # Deleted files are moved from their current folder into the system Trash folder, and its status is set to Deleted.
232
+ # @param [String] file_id - Specifies the MyLibrary file to delete
233
+ # @return [Boolean]
234
+ def delete_library_file(file_id)
235
+ url = Util::Config.get('endpoints.base_url') + sprintf(Util::Config.get('endpoints.library_file'), file_id)
236
+ url = build_url(url)
237
+ response = RestClient.delete(url, get_headers())
238
+ response.code == 204
239
+ end
240
+
241
+
242
+ # Retrieve the upload status for one or more MyLibrary files using the file_id path parameter;
243
+ # separate multiple file IDs with a comma
244
+ # @param [String] file_id - Specifies the files for which to retrieve upload status information
245
+ # @return [Array<UploadStatus>]
246
+ def get_library_files_upload_status(file_id)
247
+ url = Util::Config.get('endpoints.base_url') +
248
+ sprintf(Util::Config.get('endpoints.library_file_upload_status'), file_id)
249
+ url = build_url(url)
250
+ response = RestClient.get(url, get_headers())
251
+ statuses = []
252
+ JSON.parse(response.body).each do |status|
253
+ statuses << Components::UploadStatus.create(status)
254
+ end
255
+ statuses
256
+ end
257
+
258
+
259
+ # Move one or more MyLibrary files to a different folder in the user's account
260
+ # specify the destination folder using the folder_id path parameter.
261
+ # @param [String] folder_id - Specifies the destination MyLibrary folder to which the files will be moved
262
+ # @param [String] file_id - Specifies the files to move, in a string of comma separated file ids (e.g. 8,9)
263
+ # @return [Array<MoveResults>]
264
+ def move_library_files(folder_id, file_id)
265
+ url = Util::Config.get('endpoints.base_url') +
266
+ sprintf(Util::Config.get('endpoints.library_file_move'), folder_id)
267
+ url = build_url(url)
268
+
269
+ payload = file_id.split(',').map {|id| id.strip}.to_json
270
+ response = RestClient.put(url, payload, get_headers())
271
+ results = []
272
+ JSON.parse(response.body).each do |result|
273
+ results << Components::MoveResults.create(result)
274
+ end
275
+ results
276
+ end
277
+
278
+ end
279
+ end
280
+ end
281
+ end
@@ -0,0 +1,81 @@
1
+ #
2
+ # list_service.rb
3
+ # ConstantContact
4
+ #
5
+ # Copyright (c) 2013 Constant Contact. All rights reserved.
6
+
7
+ module ConstantContact
8
+ module Services
9
+ class ListService < BaseService
10
+ class << self
11
+
12
+ # Get lists within an account
13
+ # @param [Hash] params - query parameters to be appended to the request
14
+ # @return [Array<ContactList>]
15
+ def get_lists(params = {})
16
+ url = Util::Config.get('endpoints.base_url') + Util::Config.get('endpoints.lists')
17
+ url = build_url(url, params)
18
+ response = RestClient.get(url, get_headers())
19
+ lists = []
20
+ JSON.parse(response.body).each do |contact|
21
+ lists << Components::ContactList.create(contact)
22
+ end
23
+ lists
24
+ end
25
+
26
+
27
+ # Add a new list to the Constant Contact account
28
+ # @param [ContactList] list
29
+ # @return [ContactList]
30
+ def add_list(list)
31
+ url = Util::Config.get('endpoints.base_url') + Util::Config.get('endpoints.lists')
32
+ url = build_url(url)
33
+ payload = list.to_json
34
+ response = RestClient.post(url, payload, get_headers())
35
+ Components::ContactList.create(JSON.parse(response.body))
36
+ end
37
+
38
+
39
+ # Update a Contact List
40
+ # @param [ContactList] list - ContactList to be updated
41
+ # @return [ContactList]
42
+ def update_list(list)
43
+ url = Util::Config.get('endpoints.base_url') + sprintf(Util::Config.get('endpoints.list'), list.id)
44
+ url = build_url(url)
45
+ payload = list.to_json
46
+ response = RestClient.put(url, payload, get_headers())
47
+ Components::ContactList.create(JSON.parse(response.body))
48
+ end
49
+
50
+
51
+ # Get an individual contact list
52
+ # @param [Integer] list_id - list id
53
+ # @return [ContactList]
54
+ def get_list(list_id)
55
+ url = Util::Config.get('endpoints.base_url') + sprintf(Util::Config.get('endpoints.list'), list_id)
56
+ url = build_url(url)
57
+ response = RestClient.get(url, get_headers())
58
+ Components::ContactList.create(JSON.parse(response.body))
59
+ end
60
+
61
+
62
+ # Get all contacts from an individual list
63
+ # @param [Integer] list_id - list id to retrieve contacts for
64
+ # @param [Hash] params - query parameters to attach to request
65
+ # @return [Array<Contact>]
66
+ def get_contacts_from_list(list_id, params = nil)
67
+ url = Util::Config.get('endpoints.base_url') + sprintf(Util::Config.get('endpoints.list_contacts'), list_id)
68
+ url = build_url(url, params)
69
+ response = RestClient.get(url, get_headers())
70
+ contacts = []
71
+ body = JSON.parse(response.body)
72
+ body['results'].each do |contact|
73
+ contacts << Components::Contact.create(contact)
74
+ end
75
+ Components::ResultSet.new(contacts, body['meta'])
76
+ end
77
+
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,180 @@
1
+ #
2
+ # config.rb
3
+ # ConstantContact
4
+ #
5
+ # Copyright (c) 2013 Constant Contact. All rights reserved.
6
+
7
+ module ConstantContact
8
+ module Util
9
+ class Config
10
+
11
+ # Return a hash of configuration strings
12
+ # @return [Hash] - hash of configuration properties
13
+ @props = {
14
+ # REST endpoints
15
+ :endpoints => {
16
+ :api_url => 'https://api.constantcontact.com',
17
+ :base_url => 'https://api.constantcontact.com/v2/',
18
+
19
+ :activity => 'activities/%s',
20
+ :activities => 'activities',
21
+ :export_contacts_activity => 'activities/exportcontacts',
22
+ :clear_lists_activity => 'activities/clearlists',
23
+ :remove_from_lists_activity => 'activities/removefromlists',
24
+ :add_contacts_activity => 'activities/addcontacts',
25
+
26
+ :account_verified_addresses => 'account/verifiedemailaddresses',
27
+ :account_info => 'account/info',
28
+
29
+ :contact => 'contacts/%s',
30
+ :contacts => 'contacts',
31
+ :lists => 'lists',
32
+ :list => 'lists/%s',
33
+ :list_contacts => 'lists/%s/contacts',
34
+ :contact_lists => 'contacts/%s/lists',
35
+ :contact_list => 'contacts/%s/lists/%s',
36
+
37
+ :campaigns => 'emailmarketing/campaigns',
38
+ :campaign => 'emailmarketing/campaigns/%s',
39
+ :campaign_preview => 'emailmarketing/campaigns/%s/preview',
40
+ :campaign_schedules => 'emailmarketing/campaigns/%s/schedules',
41
+ :campaign_schedule => 'emailmarketing/campaigns/%s/schedules/%s',
42
+ :campaign_test_sends => 'emailmarketing/campaigns/%s/tests',
43
+ :campaign_tracking_summary => 'emailmarketing/campaigns/%s/tracking/reports/summary',
44
+ :campaign_tracking_bounces => 'emailmarketing/campaigns/%s/tracking/bounces',
45
+ :campaign_tracking_clicks => 'emailmarketing/campaigns/%s/tracking/clicks',
46
+ :campaign_tracking_forwards => 'emailmarketing/campaigns/%s/tracking/forwards',
47
+ :campaign_tracking_opens => 'emailmarketing/campaigns/%s/tracking/opens',
48
+ :campaign_tracking_sends => 'emailmarketing/campaigns/%s/tracking/sends',
49
+ :campaign_tracking_unsubscribes => 'emailmarketing/campaigns/%s/tracking/unsubscribes',
50
+ :campaign_tracking_link => 'emailmarketing/campaigns/%s/tracking/clicks/%s',
51
+
52
+ :events => 'eventspot/events',
53
+ :event => 'eventspot/events/%s',
54
+ :event_fees => 'eventspot/events/%s/fees',
55
+ :event_fee => 'eventspot/events/%s/fees/%s',
56
+ :event_registrants => 'eventspot/events/%s/registrants',
57
+ :event_registrant => 'eventspot/events/%s/registrants/%s',
58
+ :event_items => 'eventspot/events/%s/items',
59
+ :event_item => 'eventspot/events/%s/items/%s',
60
+ :event_item_attributes => 'eventspot/events/%s/items/%s/attributes',
61
+ :event_item_attribute => 'eventspot/events/%s/items/%s/attributes/%s',
62
+ :event_promocodes => 'eventspot/events/%s/promocodes',
63
+ :event_promocode => 'eventspot/events/%s/promocodes/%s',
64
+
65
+ :contact_tracking_summary => 'contacts/%s/tracking/reports/summary',
66
+ :contact_tracking_bounces => 'contacts/%s/tracking/bounces',
67
+ :contact_tracking_clicks => 'contacts/%s/tracking/clicks',
68
+ :contact_tracking_forwards => 'contacts/%s/tracking/forwards',
69
+ :contact_tracking_opens => 'contacts/%s/tracking/opens',
70
+ :contact_tracking_sends => 'contacts/%s/tracking/sends',
71
+ :contact_tracking_unsubscribes => 'contacts/%s/tracking/unsubscribes',
72
+ :contact_tracking_link => 'contacts/%s/tracking/clicks/%s',
73
+
74
+ :library_info => 'library/info',
75
+ :library_files => 'library/files',
76
+ :library_files_by_folder => 'library/folders/%s/files',
77
+ :library_folders => 'library/folders',
78
+ :library_folder => 'library/folders/%s',
79
+ :library_folder_trash => 'library/folders/trash/files',
80
+ :library_file => 'library/files/%s',
81
+ :library_file_upload_status => 'library/files/uploadstatus/%s',
82
+ :library_file_move => 'library/folders/%s/files'
83
+ },
84
+
85
+ # OAuth2 Authorization related configuration options
86
+ :auth => {
87
+ :base_url => 'https://oauth2.constantcontact.com/oauth2/',
88
+ :response_type_code => 'code',
89
+ :response_type_token => 'token',
90
+ :authorization_code_grant_type => 'authorization_code',
91
+ :authorization_endpoint => 'oauth/siteowner/authorize',
92
+ :token_endpoint => 'oauth/token',
93
+ :token_info => 'tokeninfo.htm',
94
+ :api_key => '',
95
+ :api_secret => '',
96
+ :redirect_uri => ''
97
+ },
98
+
99
+ # Column names used with bulk activities
100
+ :activities_columns => {
101
+ :email => 'EMAIL',
102
+ :first_name => 'FIRST NAME',
103
+ :middle_name => 'MIDDLE NAME',
104
+ :last_name => 'LAST NAME',
105
+ :birthday_day => 'BIRTHDAY_DAY',
106
+ :birthday_month => 'BIRTHDAY_MONTH',
107
+ :anniversary => 'ANNIVERSARY',
108
+ :job_title => 'JOB TITLE',
109
+ :company_name => 'COMPANY NAME',
110
+ :work_phone => 'WORK PHONE',
111
+ :home_phone => 'HOME PHONE',
112
+ :address1 => 'ADDRESS LINE 1',
113
+ :address2 => 'ADDRESS LINE 2',
114
+ :address3 => 'ADDRESS LINE 3',
115
+ :city => 'CITY',
116
+ :state => 'STATE',
117
+ :state_province => 'US STATE/CA PROVINCE',
118
+ :country => 'COUNTRY',
119
+ :postal_code => 'ZIP/POSTAL CODE',
120
+ :sub_postal_code => 'SUB ZIP/POSTAL CODE',
121
+ :custom_field_1 => 'CUSTOM FIELD 1',
122
+ :custom_field_2 => 'CUSTOM FIELD 2',
123
+ :custom_field_3 => 'CUSTOM FIELD 3',
124
+ :custom_field_4 => 'CUSTOM FIELD 4',
125
+ :custom_field_5 => 'CUSTOM FIELD 5',
126
+ :custom_field_6 => 'CUSTOM FIELD 6',
127
+ :custom_field_7 => 'CUSTOM FIELD 7',
128
+ :custom_field_8 => 'CUSTOM FIELD 8',
129
+ :custom_field_9 => 'CUSTOM FIELD 9',
130
+ :custom_field_10 => 'CUSTOM FIELD 10',
131
+ :custom_field_11 => 'CUSTOM FIELD 11',
132
+ :custom_field_12 => 'CUSTOM FIELD 12',
133
+ :custom_field_13 => 'CUSTOM FIELD 13',
134
+ :custom_field_14 => 'CUSTOM FIELD 14',
135
+ :custom_field_15 => 'CUSTOM FIELD 15'
136
+ },
137
+
138
+ # Errors to be returned for various exceptions
139
+ :errors => {
140
+ :api_key_missing => 'api_key required either explicitly or in configuration.',
141
+ :access_token_missing => 'access_token required explicitly.',
142
+ :id_or_object => 'Only an id or %s object are allowed for this method.',
143
+ :invalid_webhook => 'Invalid Webhook. The x-ctct-hmac-sha256 does not correspond to message encryption.',
144
+ :api_secret_missing => 'The api_secret is missing in explicit call or configuration.'
145
+ }
146
+ }
147
+
148
+ class << self
149
+ attr_accessor :props
150
+
151
+ def configure
152
+ yield props if block_given?
153
+ end
154
+
155
+ # Get a configuration property given a specified location, example usage: Config::get('auth.token_endpoint')
156
+ # @param [String] index - location of the property to obtain
157
+ # @return [String]
158
+ def get(index)
159
+ properties = index.split('.')
160
+ get_value(properties, props)
161
+ end
162
+
163
+ private
164
+
165
+ # Navigate through a config array looking for a particular index
166
+ # @param [Array] index The index sequence we are navigating down
167
+ # @param [Hash, String] value The portion of the config array to process
168
+ # @return [String]
169
+ def get_value(index, value)
170
+ index = index.is_a?(Array) ? index : [index]
171
+ key = index.shift.to_sym
172
+ value.is_a?(Hash) and value[key] and value[key].is_a?(Hash) ?
173
+ get_value(index, value[key]) :
174
+ value[key]
175
+ end
176
+ end
177
+
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,27 @@
1
+ #
2
+ # helpers.rb
3
+ # ConstantContact
4
+ #
5
+ # Copyright (c) 2013 Constant Contact. All rights reserved.
6
+
7
+ module ConstantContact
8
+ module Util
9
+ class Helpers
10
+ class << self
11
+
12
+ # Build the HTTP query from the given parameters
13
+ # @param [Hash] params
14
+ # @return [String] query string
15
+ def http_build_query(params)
16
+ params.collect{ |k,v| "#{k.to_s}=#{encode(v.to_s)}" }.reverse.join('&')
17
+ end
18
+
19
+ # Escape special characters
20
+ # @param [String] str
21
+ def encode(str)
22
+ CGI.escape(str).gsub('.', '%2E').gsub('-', '%2D')
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,12 @@
1
+ #
2
+ # version.rb
3
+ # ConstantContact
4
+ #
5
+ # Copyright (c) 2015 Constant Contact. All rights reserved.
6
+
7
+ module ConstantContact
8
+ module SDK
9
+ # Gem version
10
+ VERSION = "2.2.0"
11
+ end
12
+ end
@@ -0,0 +1,30 @@
1
+ #
2
+ # validator.rb
3
+ # ConstantContact
4
+ #
5
+ # Copyright (c) 2013 Constant Contact. All rights reserved.
6
+
7
+ module ConstantContact
8
+ module Webhooks
9
+ module Helpers
10
+ class Validator
11
+ class << self
12
+
13
+ # Validate the request received from Constant Contact.
14
+ # Compute the HMAC digest and compare it to the value in the x-ctct-hmac-sha256 header.
15
+ # If they match, you can be sure that the webhook was sent by Constant Contact and the message has not been compromised.
16
+ # @param [String] secret The Constant Contact secret key
17
+ # @param [String] hmac The value received in the x-ctct-hmac-sha256 header.
18
+ # @param [String] data The body message from the POST received from ConstantContact in Webhook callback.
19
+ # @return true if the computed vs. received values match; false otherwise.
20
+ def validate(secret, hmac, data)
21
+ digest = OpenSSL::Digest.new('sha256')
22
+ calculated_hmac = Base64.encode64(OpenSSL::HMAC.digest(digest, secret, data)).strip
23
+ calculated_hmac == hmac
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,27 @@
1
+ #
2
+ # billing_change_notification.rb
3
+ # ConstantContact
4
+ #
5
+ # Copyright (c) 2013 Constant Contact. All rights reserved.
6
+
7
+ module ConstantContact
8
+ module Webhooks
9
+ module Models
10
+ class BillingChangeNotification
11
+ attr_accessor :event_type, :url
12
+
13
+ # Factory method to create a BillingChangeNotification model object from a hash
14
+ # @param [Hash] props - hash of properties to create object from
15
+ # @return [BillingChangeNotification]
16
+ def self.create(props)
17
+ obj = BillingChangeNotification.new
18
+ props.each do |key, value|
19
+ key = key.to_s
20
+ obj.send("#{key}=", value) if obj.respond_to? key
21
+ end if props
22
+ obj
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end