emarsys 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.gitignore +18 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +11 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +171 -0
  6. data/Rakefile +7 -0
  7. data/emarsys.gemspec +25 -0
  8. data/lib/emarsys.rb +60 -0
  9. data/lib/emarsys/client.rb +40 -0
  10. data/lib/emarsys/data_object.rb +78 -0
  11. data/lib/emarsys/data_objects/condition.rb +20 -0
  12. data/lib/emarsys/data_objects/contact.rb +121 -0
  13. data/lib/emarsys/data_objects/contact_list.rb +47 -0
  14. data/lib/emarsys/data_objects/email.rb +133 -0
  15. data/lib/emarsys/data_objects/email_category.rb +20 -0
  16. data/lib/emarsys/data_objects/email_launch_status.rb +38 -0
  17. data/lib/emarsys/data_objects/email_status_code.rb +39 -0
  18. data/lib/emarsys/data_objects/event.rb +44 -0
  19. data/lib/emarsys/data_objects/export.rb +22 -0
  20. data/lib/emarsys/data_objects/field.rb +39 -0
  21. data/lib/emarsys/data_objects/file.rb +39 -0
  22. data/lib/emarsys/data_objects/folder.rb +24 -0
  23. data/lib/emarsys/data_objects/form.rb +21 -0
  24. data/lib/emarsys/data_objects/language.rb +20 -0
  25. data/lib/emarsys/data_objects/segment.rb +21 -0
  26. data/lib/emarsys/data_objects/source.rb +40 -0
  27. data/lib/emarsys/error.rb +24 -0
  28. data/lib/emarsys/extensions.rb +8 -0
  29. data/lib/emarsys/field_mapping.rb +55 -0
  30. data/lib/emarsys/params_converter.rb +29 -0
  31. data/lib/emarsys/request.rb +46 -0
  32. data/lib/emarsys/response.rb +24 -0
  33. data/lib/emarsys/version.rb +3 -0
  34. data/spec/emarsys/client_spec.rb +85 -0
  35. data/spec/emarsys/data_object_spec.rb +55 -0
  36. data/spec/emarsys/data_objects/condition_spec.rb +9 -0
  37. data/spec/emarsys/data_objects/contact_list_spec.rb +9 -0
  38. data/spec/emarsys/data_objects/contact_spec.rb +79 -0
  39. data/spec/emarsys/data_objects/email_category_spec.rb +9 -0
  40. data/spec/emarsys/data_objects/email_launch_status_spec.rb +25 -0
  41. data/spec/emarsys/data_objects/email_spec.rb +84 -0
  42. data/spec/emarsys/data_objects/email_status_code_spec.rb +25 -0
  43. data/spec/emarsys/data_objects/event_spec.rb +23 -0
  44. data/spec/emarsys/data_objects/export_spec.rb +9 -0
  45. data/spec/emarsys/data_objects/field_spec.rb +19 -0
  46. data/spec/emarsys/data_objects/file_spec.rb +29 -0
  47. data/spec/emarsys/data_objects/folder_spec.rb +13 -0
  48. data/spec/emarsys/data_objects/form_spec.rb +9 -0
  49. data/spec/emarsys/data_objects/language_spec.rb +9 -0
  50. data/spec/emarsys/data_objects/segment_spec.rb +9 -0
  51. data/spec/emarsys/data_objects/source_spec.rb +25 -0
  52. data/spec/emarsys/extensions_spec.rb +24 -0
  53. data/spec/emarsys/field_mapping_spec.rb +14 -0
  54. data/spec/emarsys/params_converter_spec.rb +52 -0
  55. data/spec/emarsys/request_spec.rb +27 -0
  56. data/spec/emarsys/response_spec.rb +35 -0
  57. data/spec/emarsys_spec.rb +22 -0
  58. data/spec/spec_helper.rb +28 -0
  59. metadata +178 -0
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in emarsys.gemspec
4
+
5
+ group :test do
6
+ gem 'rspec', '~> 2.13.0'
7
+ gem 'webmock', '~> 1.9.0'
8
+ end
9
+
10
+
11
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Daniel Schoppmann
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,171 @@
1
+ # emarsys-rb
2
+
3
+ Simple Ruby wrapper for the Emarsys API.
4
+
5
+ ## Installation
6
+
7
+ gem install emarsys
8
+
9
+ ## Emarsys API Hint
10
+
11
+ This wrapper tries to implement all available methods of the Emarsys API in a
12
+ Ruby-like fashion. However, the Emarsys API lacks a decent amount of methods that
13
+ you expect an API to provide.
14
+ Thus, if methods are missing or a certain implementation
15
+ style was choosen it is most likely due to the inconsistency of the API itself.
16
+ Feel free to get in touch or submit a pull request if you encounter any problems.
17
+
18
+ Must-known facts about the Emarsys API:
19
+
20
+ * Emarsys uses internal IDs as field identifiers. E.g. 'email' is mapped to the value 3.
21
+ This gem tries to work around this by letting you specify a field mapping constant.
22
+ * certain methods require the specification of a key-field, e.g. the email (internally refered to as '3' again).
23
+ * Return values differ from method to method due to the way the Emarsys API is implemented.
24
+ Thus, a Hash as a return value or an Array of Hashes was choosen as the global return object. Basically it is a parsed JSON response.
25
+ * Please refer to the Emarsys API documentation for detailed information on parameters, return values or error codes.
26
+
27
+ ## Configuration and Setup
28
+ ### Authentication
29
+
30
+ Authenticate with the api credentials provided by your Emarsys account manager.
31
+
32
+ Emarsys.configure do |c|
33
+ c.api_username = 'my_username'
34
+ c.api_password = 'my_password'
35
+ # OPTIONAL, defaults to https://suite5.emarsys.net/api/v2
36
+ c.api_endpoint = 'https://www.emarsys.net/api/v2'
37
+ end
38
+
39
+ ### Field Mapping
40
+
41
+ As said before, Emarsys loves IDs. For using an APi, they are evil. This Gem provides
42
+ an easy way to adjust the individual field settings. Internally a Ruby Mapping Constant is used,
43
+ which that can be overwritten. It will be picked up automatically. E.g.:
44
+
45
+ # Complete overwrite
46
+ Emarsys::FieldMapping::ATTRIBUTES = [
47
+ {:id => 0, :identifier => 'interests', :name => 'Interests'},
48
+ {:id => 1, :identifier => 'firstname', :name => 'First Name'},
49
+ {:id => 2, :identifier => 'lastname', :name => 'Last Name'},
50
+ ]
51
+
52
+ # Add to the Mapping-Constant
53
+ Emarsys::FieldMapping::ATTRIBUTES << {:id => 100, :identifier => 'user_id', :name => "User-ID"}
54
+
55
+ All Emarsys predefined system fields are prefixed with an underscore, e.g. '_firstname' or '_revenue' in order to not
56
+ clash with individual mappings.
57
+
58
+
59
+ ## Interacting with the API
60
+
61
+ You can interact with the API on the provided data objects:
62
+
63
+ #### Condition
64
+
65
+ # Get all conditions
66
+ Emarsys::Condition.collection
67
+
68
+ #### Contact
69
+
70
+ # Create a contact with custom key_field (one example with mapped identifier, one without)
71
+ Emarsys::Contact.create('user_id', 10, {firstname: "Jane", lastname: "Doe", email: "jane.doe@example.com"})
72
+ Emarsys::Contact.create(4980, 10, {1 => "Jane", 2 => "Doe", 3 => "jane.doe@example.com"})
73
+
74
+ # Update a contact with key_field (one example with mapped identifier, one without)
75
+ Emarsys::Contact.update('email', "jane.doe@example.com", {firstname: "John", lastname: "Doe"})
76
+ Emarsys::Contact.update(3, "jane.doe@example.com", {1 => "John", 2 => "Doe"})
77
+
78
+ #### ContactList
79
+
80
+ # Get all contact_lists
81
+ Emarsys::ContactList.collection
82
+
83
+ # Create a contact list
84
+ Emarsys::ContactList.create
85
+
86
+ #### Emails
87
+
88
+ # Get all email campaigns, optional filter
89
+ Emarsys::Email.collection
90
+ Emarsys::Email.collection(status: 3)
91
+
92
+ # Get a single email resource
93
+ Emarsys::Email.resource(1)
94
+
95
+ # Create a new email campaign
96
+ Emarsys::Email.create({})
97
+
98
+ Emarsys::Email.launch({})
99
+
100
+ #### Event
101
+
102
+ Emarsys::Event.collection
103
+
104
+ # Trigger a custom event
105
+ Emarsys::Event.trigger(65, 3, ["test@example.com"])
106
+
107
+ # Trigger a custom event which actually sends a mail
108
+ # (Emarsys way to send transactional mails with placeholders)
109
+ Emarsys::Event.trigger(2, 3, 'test@example.com', {:global => {:my_placeholder => "some content"}})
110
+
111
+ #### Export
112
+
113
+ Emarsys::Export.resource(1)
114
+
115
+ #### Field
116
+
117
+ Emarsys::Field.collection
118
+ Emarsys::Field.choice(1)
119
+
120
+ #### Folder
121
+
122
+ # Get all forms, optional filter parameters
123
+ Emarsys::Folder.collection
124
+ Emarsys::Folder.collection(:folder => 3)
125
+
126
+ #### Form
127
+
128
+ # Get all forms
129
+ Emarsys::Form.collection
130
+
131
+ #### Language
132
+
133
+ # Get all languages
134
+ Emarsys::Language.collection
135
+
136
+ #### Segment
137
+
138
+ # Get all segments
139
+ Emarsys::Segment.collection
140
+
141
+ #### Source
142
+
143
+ # Get all sources
144
+ Emarsys::Source.collection
145
+
146
+ # Create a new source
147
+ Emarsys::Source.create("New Source")
148
+
149
+ # Destroy a source
150
+ Emarsys::Source.destroy(123)
151
+
152
+
153
+ Please refer to the code for detailed instructions of each method.
154
+
155
+ ## Ruby Versions
156
+
157
+ This gem was developed and tested with versions 1.9.3 and 2.0.0
158
+
159
+
160
+ ## Contributing
161
+
162
+ 1. Fork it
163
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
164
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
165
+ 4. Push to the branch (`git push origin my-new-feature`)
166
+ 5. Create new Pull Request
167
+
168
+
169
+ ## Copyright
170
+
171
+ Copyright (c) 2013 Daniel Schoppmann. See LICENSE.txt for details.
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :test => :spec
7
+ task :default => :spec
data/emarsys.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'emarsys/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "emarsys"
8
+ spec.version = Emarsys::VERSION
9
+ spec.authors = ["Daniel Schoppmann"]
10
+ spec.email = ["daniel.schoppmann@absolventa.de"]
11
+ spec.description = %q{A Ruby library for interacting with the Emarsys API.}
12
+ spec.summary = %q{Easy to use ruby library for Emarsys Marketing Suite.}
13
+ spec.homepage = "http://www.absolventa.de"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "rest-client"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ end
data/lib/emarsys.rb ADDED
@@ -0,0 +1,60 @@
1
+ require "base64"
2
+ require 'json'
3
+ require 'rest_client'
4
+ require 'uri'
5
+
6
+ require 'emarsys/client'
7
+ require 'emarsys/data_object'
8
+ require 'emarsys/error'
9
+ require 'emarsys/extensions'
10
+ require 'emarsys/field_mapping'
11
+ require 'emarsys/params_converter'
12
+ require 'emarsys/request'
13
+ require 'emarsys/response'
14
+
15
+ require 'emarsys/data_objects/condition'
16
+ require 'emarsys/data_objects/contact_list'
17
+ require 'emarsys/data_objects/contact'
18
+ require 'emarsys/data_objects/email'
19
+ require 'emarsys/data_objects/email_category'
20
+ require 'emarsys/data_objects/email_launch_status'
21
+ require 'emarsys/data_objects/email_status_code'
22
+ require 'emarsys/data_objects/event'
23
+ require 'emarsys/data_objects/export'
24
+ require 'emarsys/data_objects/field'
25
+ require 'emarsys/data_objects/file'
26
+ require 'emarsys/data_objects/folder'
27
+ require 'emarsys/data_objects/form'
28
+ require 'emarsys/data_objects/language'
29
+ require 'emarsys/data_objects/segment'
30
+ require 'emarsys/data_objects/source'
31
+
32
+ require "emarsys/version"
33
+
34
+ # Ruby toolkit for the Emarsys API
35
+ module Emarsys
36
+ class << self
37
+
38
+ # @!attribute api_endpoint
39
+ # @return [String] Base URL for emarsys URLs. default: https://suite5.emarsys.net/api/v2
40
+ # @!attribute api_password
41
+ # @return [String] API Username given by Emarsys
42
+ # @!attribute api_username
43
+ # @return [String] API Username given by Emarsys
44
+
45
+ attr_accessor :api_endpoint, :api_username, :api_password
46
+
47
+ # Base URL for the Emarsys API
48
+ #
49
+ # @return [String] domain which should be used to query the API
50
+ def api_endpoint
51
+ @api_endpoint ||= 'https://suite5.emarsys.net/api/v2'
52
+ end
53
+
54
+ # Set configuration options using a block
55
+ def configure
56
+ yield self
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,40 @@
1
+ module Emarsys
2
+ class Client
3
+
4
+ def username
5
+ raise ArgumentError, "Emarsys.api_username is not set" if Emarsys.api_username.nil?
6
+ Emarsys.api_username
7
+ end
8
+
9
+ def password
10
+ raise ArgumentError, "Emarsys.api_password is not set" if Emarsys.api_password.nil?
11
+ Emarsys.api_password
12
+ end
13
+
14
+ def x_wsse_string
15
+ string = 'UsernameToken '
16
+ string += 'Username = "' + username + '", '
17
+ string += 'PasswordDigest = "' + header_password_digest + '", '
18
+ string += 'Nonce = "' + header_nonce + '", '
19
+ string += 'Created = "' + header_created + '"'
20
+ string
21
+ end
22
+
23
+ def header_password_digest
24
+ Base64.encode64(calculated_digest).gsub("\n", "")
25
+ end
26
+
27
+ def header_nonce
28
+ Digest::MD5.hexdigest(Time.new.to_i.to_s)
29
+ end
30
+
31
+ def header_created
32
+ Time.new.strftime("%Y-%m-%d %H:%M:%S")
33
+ end
34
+
35
+ def calculated_digest
36
+ Digest::SHA1.hexdigest(header_nonce + header_created + password)
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,78 @@
1
+ #require 'hashie'
2
+
3
+ module Emarsys
4
+ class DataObject
5
+ class << self
6
+
7
+ # Make a HTTP GET request
8
+ #
9
+ # @param method_name [String] The path, relative to Emarsys.api_endpoint
10
+ # @param params [Hash] custom params hash
11
+ # @return [Hash]
12
+ def get(method_name, params)
13
+ if params.empty?
14
+ self.new.request 'get', method_name, params
15
+ else
16
+ self.new.request 'get', [method_name, parameterize_params(params)].join("/"), {}
17
+ end
18
+ end
19
+
20
+ # Make a HTTP POST request
21
+ #
22
+ # @param method_name [String] The path, relative to Emarsys.api_endpoint
23
+ # @param params [Hash] custom params hash
24
+ # @return [Hash]
25
+ def post(method_name, params)
26
+ self.new.request 'post', method_name, params
27
+ end
28
+
29
+ # Make a HTTP PUT request
30
+ #
31
+ # @param method_name [String] The path, relative to Emarsys.api_endpoint
32
+ # @param params [Hash] custom params hash
33
+ # @return [Hash]
34
+ def put(method_name, params)
35
+ self.new.request 'put', method_name, params
36
+ end
37
+
38
+ # Make a HTTP DELETE request
39
+ #
40
+ # @param method_name [String] The path, relative to Emarsys.api_endpoint
41
+ # @param params [Hash] custom params hash
42
+ # @return [Hash]
43
+ def delete(method_name, params)
44
+ self.new.request 'delete', method_name, params
45
+ end
46
+
47
+ # Custom Parameterizer for Emarsys
48
+ #
49
+ # @param params [Hash] custom params hash
50
+ # @return [String] key => value is returned as key=value
51
+ def parameterize_params(params)
52
+ params.inject(""){|string, (k, v)| string << "#{k}=#{v}"; string << "&"; string}[0..-2]
53
+ end
54
+ end
55
+
56
+ # Make a HTTP request
57
+ #
58
+ # @param http_verb [String] Http method
59
+ # @param method_name [String] The path, relative to Emarsys.api_endpoint
60
+ # @param params [Hash] custom params hash
61
+ # @return [Hash]
62
+ def request(http_verb, method_name, params)
63
+ response = Emarsys::Request.new(http_verb, method_name, params).send_request
64
+ #hashiefy(response)
65
+ end
66
+
67
+ # TODO: Not finally evaluated. Is Hashie necessary? Maybe use "real Data Objects instead"?
68
+ # def hashiefy(response)
69
+ # if response.is_a?(Array)
70
+ # response.map!{|elem| Hashie::Mash.new(elem) }
71
+ # elsif
72
+ # Hashie::Mash.new(response)
73
+ # else
74
+ # response
75
+ # end
76
+ # end
77
+ end
78
+ end