unresponsys 0.0.3 → 0.0.5

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.
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
  - - ">="