emarsys 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|