unresponsys 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 81c6829cb73e851171e77c2a870038cd8c98d9ee
4
- data.tar.gz: 048c2fcc64e0456265a3f4e013974b74325a579f
3
+ metadata.gz: 9ab97914beb02ad40643f37e22de5b06a9e7070d
4
+ data.tar.gz: e0926c1dfbf45986635cc7933f4b5712da8f3d8c
5
5
  SHA512:
6
- metadata.gz: 2056c1232ea19785931b7b92abf1cb5a682fba123cd7617dcab252fa6e6846e9a86731c97aa544d31c7c4005b3a8ba86283aee33e73bfec0c06856679de6d771
7
- data.tar.gz: bf075cce79a98a385c8e960c46cbe09442eaab7a3a2670471656d259d37f82a2c9aa1f306ad63f08c75a2bc2daacccb0cc819b990fd3150896fba022a427b54e
6
+ metadata.gz: 9b7130d8de52d61196231af0db584e5ef2c661c5c2877e70605df10fb54aaf80e28d205993bb05a8b2add846bcf9d038f5d90fa0882f46ed6409304599c3b1f0
7
+ data.tar.gz: a71246553a866bc3ceada31664ff8bbd7f257485d360f03c6b095e6a51a8187dc0e7959ed2397763b4b014924e1e85b5e3690fec4e5f67bce35e51ad08e0a639
@@ -0,0 +1,12 @@
1
+ require 'active_support'
2
+ require 'active_support/all'
3
+ require 'unresponsys/client'
4
+ require 'unresponsys/event'
5
+ require 'unresponsys/errors'
6
+ require 'unresponsys/folder'
7
+ require 'unresponsys/helpers'
8
+ require 'unresponsys/list'
9
+ require 'unresponsys/member'
10
+ require 'unresponsys/row'
11
+ require 'unresponsys/table'
12
+ require 'unresponsys/version'
@@ -0,0 +1,70 @@
1
+ require 'httparty'
2
+
3
+ class Unresponsys
4
+ class Client
5
+ include HTTParty
6
+
7
+ def initialize(options = {})
8
+ @@username ||= options[:username]
9
+ @@password ||= options[:password]
10
+ raise Unresponsys::Error, 'Could not authenticate' unless authenticate
11
+ self.class.debug_output($stdout) if options[:debug]
12
+ end
13
+
14
+ def self.get(path, options = {}, &block)
15
+ begin
16
+ r = perform_request Net::HTTP::Get, path, options, &block
17
+ handle_error(r)
18
+ rescue Unresponsys::Retry
19
+ r = perform_request Net::HTTP::Get, path, options, &block
20
+ handle_error(r)
21
+ end
22
+ end
23
+
24
+ def self.post(path, options = {}, &block)
25
+ begin
26
+ r = perform_request Net::HTTP::Post, path, options, &block
27
+ handle_error(r)
28
+ rescue Unresponsys::Retry
29
+ r = perform_request Net::HTTP::Post, path, options, &block
30
+ handle_error(r)
31
+ end
32
+ end
33
+
34
+ def self.delete(path, options = {}, &block)
35
+ begin
36
+ r = perform_request Net::HTTP::Delete, path, options, &block
37
+ handle_error(r)
38
+ rescue Unresponsys::Retry
39
+ r = perform_request Net::HTTP::Delete, path, options, &block
40
+ handle_error(r)
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def self.handle_error(response)
47
+ if response.is_a?(Hash) && response.keys.include?('errorCode')
48
+ if response['title'].include?('token expired')
49
+ self.new
50
+ raise Unresponsys::Retry
51
+ end
52
+ if response['title'].include?('not found')
53
+ raise Unresponsys::NotFoundError, response['detail']
54
+ end
55
+ raise Unresponsys::Error, "#{response['title']} - #{response['detail']}"
56
+ end
57
+ response
58
+ end
59
+
60
+ def authenticate
61
+ self.class.headers('Content-Type' => 'application/x-www-form-urlencoded')
62
+ body = { user_name: @@username, password: @@password, auth_type: 'password' }
63
+ r = self.class.post('https://login2.responsys.net/rest/api/v1/auth/token', body: body)
64
+ return false unless r.success?
65
+ self.class.headers('Authorization' => r['authToken'], 'Content-Type' => 'application/json')
66
+ self.class.base_uri("#{r['endPoint']}/rest/api/v1")
67
+ true
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,6 @@
1
+ class Unresponsys
2
+ class ArgumentError < StandardError; end
3
+ class Error < StandardError; end
4
+ class NotFoundError < StandardError; end
5
+ class Retry < StandardError; end
6
+ end
@@ -0,0 +1,35 @@
1
+ class Unresponsys
2
+ class Event
3
+
4
+ def initialize(options = {})
5
+ @event_name = options[:event]
6
+ @member = options[:member]
7
+ @properties = options[:properties]
8
+ end
9
+
10
+ def save
11
+ body = {
12
+ customEvent: {},
13
+ recipientData: [{
14
+ recipient: {
15
+ listName: { objectName: @member.list },
16
+ recipientId: @member.riid,
17
+ }
18
+ }]
19
+ }
20
+
21
+ # API throws an non-descriptive error if optionalData is present but empty
22
+ if @properties.present?
23
+ body[:recipientData].first[:optionalData] = []
24
+ @properties.each_pair do |key, val|
25
+ body[:recipientData].first[:optionalData] << { name: key.to_s, value: val.to_s }
26
+ end
27
+ end
28
+
29
+ r = Unresponsys::Client.post("/events/#{@event_name}", body: body.to_json)
30
+ return false if r.first['errorMessage'].present?
31
+ true
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,27 @@
1
+ class Unresponsys
2
+ class Folder
3
+ attr_reader :name
4
+
5
+ def self.find(name)
6
+ self.new(name)
7
+ end
8
+
9
+ def initialize(name)
10
+ @name = name
11
+ end
12
+
13
+ def tables
14
+ @tables ||= Tables.new(self)
15
+ end
16
+
17
+ class Tables
18
+ def initialize(folder)
19
+ @folder = folder
20
+ end
21
+
22
+ def find(table_name)
23
+ Unresponsys::Table.new(@folder, table_name)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,76 @@
1
+ class Object
2
+ def to_responsys
3
+ self.to_s
4
+ end
5
+
6
+ def to_ruby
7
+ self
8
+ end
9
+ end
10
+
11
+ class String
12
+ def is_i?
13
+ return false if self.include?('.')
14
+ !!Integer(self) rescue false
15
+ end
16
+
17
+ def is_f?
18
+ !!Float(self) rescue false
19
+ end
20
+
21
+ def is_time?
22
+ return false if /[[:alpha:]]/.match(self).present?
23
+ !!Time.parse(self) rescue false
24
+ end
25
+
26
+ def to_time
27
+ Time.parse(self)
28
+ end
29
+
30
+ def is_bool?
31
+ return false unless self.length == 1
32
+ %w(T F).include?(self)
33
+ end
34
+
35
+ def to_bool
36
+ self == 'T'
37
+ end
38
+
39
+ def to_ruby
40
+ return self.to_i if self.is_i?
41
+ return self.to_f if self.is_f?
42
+ return self.to_time if self.is_time?
43
+ return self.to_bool if self.is_bool?
44
+ self
45
+ end
46
+ end
47
+
48
+ class Date
49
+ def to_responsys
50
+ self.strftime('%Y-%m-%d %H:%M:%S')
51
+ end
52
+ end
53
+
54
+ class DateTime
55
+ def to_responsys
56
+ self.strftime('%Y-%m-%d %H:%M:%S')
57
+ end
58
+ end
59
+
60
+ class Time
61
+ def to_responsys
62
+ self.strftime('%Y-%m-%d %H:%M:%S')
63
+ end
64
+ end
65
+
66
+ class TrueClass
67
+ def to_responsys
68
+ 'T'
69
+ end
70
+ end
71
+
72
+ class FalseClass
73
+ def to_responsys
74
+ 'F'
75
+ end
76
+ end
@@ -0,0 +1,39 @@
1
+ class Unresponsys
2
+ class List
3
+ attr_reader :name
4
+
5
+ def self.find(name)
6
+ self.new(name)
7
+ end
8
+
9
+ def initialize(name)
10
+ @name = name
11
+ end
12
+
13
+ def members
14
+ @members ||= Members.new(self)
15
+ end
16
+
17
+ class Members
18
+ def initialize(list)
19
+ @list = list
20
+ end
21
+
22
+ def find(email)
23
+ options = { query: { qa: 'e', id: email.to_responsys, fs: 'all' } }
24
+ r = Unresponsys::Client.get("/lists/#{@list.name}/members", options)
25
+
26
+ fields = {}
27
+ r['recordData']['fieldNames'].each_with_index do |field, index|
28
+ fields[field] = r['recordData']['records'][0][index]
29
+ end
30
+
31
+ Unresponsys::Member.new(@list, fields)
32
+ end
33
+
34
+ def new(email)
35
+ Unresponsys::Member.new(@list, { 'EMAIL_ADDRESS_' => email })
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,132 @@
1
+ class Unresponsys
2
+ class Member
3
+ DEFAULT_FIELDS = {
4
+ 'RIID_' => '',
5
+ 'EMAIL_ADDRESS_' => '',
6
+ 'MOBILE_NUMBER_' => '',
7
+ 'CUSTOMER_ID_' => '',
8
+ 'EMAIL_PERMISSION_STATUS_' => '',
9
+ 'EMAIL_PERMISSION_REASON_' => '',
10
+ 'POSTAL_STREET_1_' => '',
11
+ 'POSTAL_STREET_2_' => '',
12
+ 'CITY_' => '',
13
+ 'STATE_' => '',
14
+ 'POSTAL_CODE_' => '',
15
+ 'COUNTRY_' => '',
16
+ 'EMAIL_MD5_HASH_' => '',
17
+ 'EMAIL_SHA256_HASH_' => ''
18
+ }
19
+
20
+ IMMUTABLE_FIELDS = %w(
21
+ RIID_
22
+ EMAIL_ADDRESS_
23
+ MOBILE_NUMBER_
24
+ EMAIL_MD5_HASH_
25
+ EMAIL_SHA256_HASH_
26
+ )
27
+
28
+ MERGE_RULE = {
29
+ insertOnNoMatch: true,
30
+ updateOnMatch: 'REPLACE_ALL',
31
+ matchColumnName1: 'EMAIL_ADDRESS_',
32
+ matchColumnName2: nil,
33
+ matchOperator: nil,
34
+ optinValue: 'I',
35
+ optoutValue: 'O',
36
+ defaultPermissionStatus: 'OPTIN',
37
+ htmlValue: 'H',
38
+ textValue: 'T',
39
+ rejectRecordIfChannelEmpty: nil,
40
+ }
41
+
42
+ def initialize(list, fields)
43
+ @fields = DEFAULT_FIELDS.merge(fields)
44
+ @list = list
45
+ @changed = ['EMAIL_ADDRESS_']
46
+
47
+ @fields.each_pair do |key, val|
48
+ str = key.downcase.chomp('_')
49
+ var = "@#{str}".to_sym
50
+ val = val.to_ruby
51
+ self.instance_variable_set(var, val)
52
+
53
+ # getter
54
+ self.class.send(:attr_reader, str)
55
+
56
+ # setter
57
+ next if IMMUTABLE_FIELDS.include?(key)
58
+ self.class.send(:define_method, "#{str}=") do |val|
59
+ @changed << key
60
+ val = val.to_ruby
61
+ self.instance_variable_set(var, val)
62
+ end
63
+ end
64
+ end
65
+
66
+ def email
67
+ email_address
68
+ end
69
+
70
+ def list
71
+ @list.name
72
+ end
73
+
74
+ def save
75
+ record_data = { fieldNames: [], records: [[]], mapTemplateName: nil }
76
+ @fields.each_pair do |key, val|
77
+ # can't send unless val changed or API breaks
78
+ next unless @changed.include?(key)
79
+
80
+ record_data[:fieldNames] << key
81
+ var = "@#{key.downcase.chomp('_')}".to_sym
82
+ val = self.instance_variable_get(var)
83
+ val = val.to_responsys
84
+ record_data[:records][0] << val
85
+ end
86
+
87
+ options = { body: { recordData: record_data, mergeRule: MERGE_RULE.dup }.to_json }
88
+ r = Unresponsys::Client.post("/lists/#{@list.name}/members", options)
89
+ return false if r['recordData']['records'][0][0].include?('MERGEFAILED')
90
+ @changed = ['EMAIL_ADDRESS_']
91
+ self.instance_variable_set(:@riid, r['recordData']['records'][0][0])
92
+ true
93
+ end
94
+
95
+ def delete
96
+ self.email_permission_status = 'O'
97
+ self.save
98
+ end
99
+
100
+ # allow to access custom fields on new record
101
+ def method_missing(sym, *args, &block)
102
+ setter = sym.to_s.include?('=')
103
+ str = sym.to_s.chomp('=')
104
+ var = "@#{str}".to_sym
105
+ val = args.first
106
+
107
+ if setter
108
+ field_name = str.upcase
109
+ @fields[field_name] = ''
110
+ @changed << field_name
111
+ val = val.to_ruby
112
+ self.instance_variable_set(var, val)
113
+ else
114
+ self.instance_variable_get(var)
115
+ end
116
+ end
117
+
118
+ def events
119
+ @events ||= Events.new(self)
120
+ end
121
+
122
+ class Events
123
+ def initialize(member)
124
+ @member = member
125
+ end
126
+
127
+ def new(event, properties = {})
128
+ Event.new(member: @member, event: event, properties: properties)
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,62 @@
1
+ class Unresponsys
2
+ class Row
3
+ def initialize(table, fields)
4
+ @table = table
5
+ @fields = fields
6
+
7
+ @fields.each_pair do |key, val|
8
+ str = key.downcase.chomp('_')
9
+ var = "@#{str}".to_sym
10
+ val = val.to_ruby
11
+ self.instance_variable_set(var, val)
12
+
13
+ if key == 'ID_'
14
+ self.class.send(:attr_reader, str)
15
+ else
16
+ self.class.send(:define_method, "#{str}=") do |val|
17
+ val = val.to_ruby
18
+ self.instance_variable_set(var, val)
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ def save
25
+ record_data = { fieldNames: [], records: [[]], mapTemplateName: nil }
26
+ @fields.each_pair do |key, val|
27
+ record_data[:fieldNames] << key
28
+ var = "@#{key.downcase.chomp('_')}".to_sym
29
+ val = self.instance_variable_get(var)
30
+ val = val.to_responsys
31
+ record_data[:records][0] << val
32
+ end
33
+
34
+ options = { body: { recordData: record_data, insertOnNoMatch: true, updateOnMatch: 'REPLACE_ALL' }.to_json }
35
+ r = Unresponsys::Client.post("/folders/#{@table.folder.name}/suppData/#{@table.name}/members", options)
36
+ r['recordData']['records'][0][0].exclude?('MERGEFAILED')
37
+ end
38
+
39
+ def delete
40
+ options = { query: { qa: 'ID_', id: @fields.primary_key } }
41
+ r = Unresponsys::Client.delete("/folders/#{@table.folder.name}/suppData/#{@table.name}/members", options)
42
+ r['recordData']['records'][0][0].exclude?('DELETEFAILED')
43
+ end
44
+
45
+ # allow to access custom fields on new record
46
+ def method_missing(sym, *args, &block)
47
+ setter = sym.to_s.include?('=')
48
+ str = sym.to_s.chomp('=')
49
+ var = "@#{str}".to_sym
50
+ val = args.first
51
+
52
+ if setter
53
+ field_name = str.upcase
54
+ @fields[field_name] = ''
55
+ val = val.to_ruby
56
+ self.instance_variable_set(var, val)
57
+ else
58
+ self.instance_variable_get(var)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,36 @@
1
+ class Unresponsys
2
+ class Table
3
+ attr_reader :folder, :name
4
+
5
+ def initialize(folder, table_name)
6
+ @folder = folder
7
+ @name = table_name
8
+ end
9
+
10
+ def rows
11
+ @rows ||= Rows.new(self)
12
+ end
13
+
14
+ class Rows
15
+ def initialize(table)
16
+ @table = table
17
+ end
18
+
19
+ def find(primary_key)
20
+ options = { query: { qa: 'ID_', id: primary_key.to_responsys, fs: 'all' } }
21
+ r = Unresponsys::Client.get("/folders/#{@table.folder.name}/suppData/#{@table.name}/members", options)
22
+
23
+ fields = {}
24
+ r['recordData']['fieldNames'].each_with_index do |field, index|
25
+ fields[field] = r['recordData']['records'][0][index]
26
+ end
27
+
28
+ Unresponsys::Row.new(@table, fields)
29
+ end
30
+
31
+ def new(primary_key)
32
+ Unresponsys::Row.new(@table, { 'ID_' => primary_key })
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ class Unresponsys
2
+ VERSION = '0.0.5'
3
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unresponsys
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Kimball
@@ -114,24 +114,25 @@ email:
114
114
  executables: []
115
115
  extensions: []
116
116
  extra_rdoc_files: []
117
- files: []
117
+ files:
118
+ - lib/unresponsys.rb
119
+ - lib/unresponsys/client.rb
120
+ - lib/unresponsys/errors.rb
121
+ - lib/unresponsys/event.rb
122
+ - lib/unresponsys/folder.rb
123
+ - lib/unresponsys/helpers.rb
124
+ - lib/unresponsys/list.rb
125
+ - lib/unresponsys/member.rb
126
+ - lib/unresponsys/row.rb
127
+ - lib/unresponsys/table.rb
128
+ - lib/unresponsys/version.rb
118
129
  homepage:
119
130
  licenses: []
120
131
  metadata: {}
121
132
  post_install_message: responsys sucks :(
122
133
  rdoc_options: []
123
134
  require_paths:
124
- - lib/unresponsys
125
- - lib/unresponsys/client
126
- - lib/unresponsys/errors
127
- - lib/unresponsys/event
128
- - lib/unresponsys/folder
129
- - lib/unresponsys/helpers
130
- - lib/unresponsys/list
131
- - lib/unresponsys/member
132
- - lib/unresponsys/row
133
- - lib/unresponsys/table
134
- - lib/unresponsys/version
135
+ - lib
135
136
  required_ruby_version: !ruby/object:Gem::Requirement
136
137
  requirements:
137
138
  - - ">="