constantcontact-ruby 2.2.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.
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