emarsys 0.1.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.
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +22 -0
- data/README.md +171 -0
- data/Rakefile +7 -0
- data/emarsys.gemspec +25 -0
- data/lib/emarsys.rb +60 -0
- data/lib/emarsys/client.rb +40 -0
- data/lib/emarsys/data_object.rb +78 -0
- data/lib/emarsys/data_objects/condition.rb +20 -0
- data/lib/emarsys/data_objects/contact.rb +121 -0
- data/lib/emarsys/data_objects/contact_list.rb +47 -0
- data/lib/emarsys/data_objects/email.rb +133 -0
- data/lib/emarsys/data_objects/email_category.rb +20 -0
- data/lib/emarsys/data_objects/email_launch_status.rb +38 -0
- data/lib/emarsys/data_objects/email_status_code.rb +39 -0
- data/lib/emarsys/data_objects/event.rb +44 -0
- data/lib/emarsys/data_objects/export.rb +22 -0
- data/lib/emarsys/data_objects/field.rb +39 -0
- data/lib/emarsys/data_objects/file.rb +39 -0
- data/lib/emarsys/data_objects/folder.rb +24 -0
- data/lib/emarsys/data_objects/form.rb +21 -0
- data/lib/emarsys/data_objects/language.rb +20 -0
- data/lib/emarsys/data_objects/segment.rb +21 -0
- data/lib/emarsys/data_objects/source.rb +40 -0
- data/lib/emarsys/error.rb +24 -0
- data/lib/emarsys/extensions.rb +8 -0
- data/lib/emarsys/field_mapping.rb +55 -0
- data/lib/emarsys/params_converter.rb +29 -0
- data/lib/emarsys/request.rb +46 -0
- data/lib/emarsys/response.rb +24 -0
- data/lib/emarsys/version.rb +3 -0
- data/spec/emarsys/client_spec.rb +85 -0
- data/spec/emarsys/data_object_spec.rb +55 -0
- data/spec/emarsys/data_objects/condition_spec.rb +9 -0
- data/spec/emarsys/data_objects/contact_list_spec.rb +9 -0
- data/spec/emarsys/data_objects/contact_spec.rb +79 -0
- data/spec/emarsys/data_objects/email_category_spec.rb +9 -0
- data/spec/emarsys/data_objects/email_launch_status_spec.rb +25 -0
- data/spec/emarsys/data_objects/email_spec.rb +84 -0
- data/spec/emarsys/data_objects/email_status_code_spec.rb +25 -0
- data/spec/emarsys/data_objects/event_spec.rb +23 -0
- data/spec/emarsys/data_objects/export_spec.rb +9 -0
- data/spec/emarsys/data_objects/field_spec.rb +19 -0
- data/spec/emarsys/data_objects/file_spec.rb +29 -0
- data/spec/emarsys/data_objects/folder_spec.rb +13 -0
- data/spec/emarsys/data_objects/form_spec.rb +9 -0
- data/spec/emarsys/data_objects/language_spec.rb +9 -0
- data/spec/emarsys/data_objects/segment_spec.rb +9 -0
- data/spec/emarsys/data_objects/source_spec.rb +25 -0
- data/spec/emarsys/extensions_spec.rb +24 -0
- data/spec/emarsys/field_mapping_spec.rb +14 -0
- data/spec/emarsys/params_converter_spec.rb +52 -0
- data/spec/emarsys/request_spec.rb +27 -0
- data/spec/emarsys/response_spec.rb +35 -0
- data/spec/emarsys_spec.rb +22 -0
- data/spec/spec_helper.rb +28 -0
- metadata +178 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
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
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
|