responsys-api 0.0.3 → 0.0.4

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.
Files changed (64) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +1 -0
  3. data/Gemfile +1 -1
  4. data/README.md +82 -10
  5. data/lib/responsys/api/all.rb +17 -0
  6. data/lib/responsys/api/campaign.rb +26 -0
  7. data/lib/responsys/api/client.rb +70 -0
  8. data/lib/responsys/api/folder.rb +25 -0
  9. data/lib/responsys/api/list.rb +39 -0
  10. data/lib/responsys/api/object/all.rb +11 -0
  11. data/lib/responsys/api/object/email_format.rb +23 -0
  12. data/lib/responsys/api/object/field.rb +20 -0
  13. data/lib/responsys/api/object/field_type.rb +23 -0
  14. data/lib/responsys/api/object/interact_object.rb +18 -0
  15. data/lib/responsys/api/object/list_merge_rule.rb +41 -0
  16. data/lib/responsys/api/object/optional_data.rb +23 -0
  17. data/lib/responsys/api/object/query_column.rb +23 -0
  18. data/lib/responsys/api/object/recipient.rb +30 -0
  19. data/lib/responsys/api/object/recipient_data.rb +21 -0
  20. data/lib/responsys/api/object/record.rb +19 -0
  21. data/lib/responsys/api/object/record_data.rb +31 -0
  22. data/lib/responsys/api/session.rb +30 -0
  23. data/lib/responsys/api/table.rb +49 -0
  24. data/lib/responsys/configuration.rb +3 -3
  25. data/lib/responsys/exceptions/all.rb +1 -0
  26. data/lib/responsys/exceptions/parameter_exception.rb +7 -0
  27. data/lib/responsys/helper.rb +78 -2
  28. data/lib/responsys/i18n/en.yml +20 -0
  29. data/lib/responsys/member.rb +80 -0
  30. data/lib/responsys_api.rb +11 -4
  31. data/responsys-api.gemspec +12 -9
  32. data/spec/api/campaign_spec.rb +27 -0
  33. data/spec/api/client_spec.rb +107 -0
  34. data/spec/api/list_spec.rb +71 -0
  35. data/spec/api/object/recipient_data_spec.rb +43 -0
  36. data/spec/api/object/recipient_spec.rb +68 -0
  37. data/spec/api/object/record_data_spec.rb +28 -0
  38. data/spec/api/table_spec.rb +111 -0
  39. data/spec/fixtures/vcr_cassettes/api/campaign/login.yml +940 -0
  40. data/spec/fixtures/vcr_cassettes/api/client/expired_session.yml +1030 -0
  41. data/spec/fixtures/vcr_cassettes/api/list/login.yml +982 -0
  42. data/spec/fixtures/vcr_cassettes/api/list/merge.yml +134 -0
  43. data/spec/fixtures/vcr_cassettes/api/list/retrieve.yml +46 -0
  44. data/spec/fixtures/vcr_cassettes/api/list/retrieve_single.yml +133 -0
  45. data/spec/fixtures/vcr_cassettes/api/list/retrieve_single_single.yml +45 -0
  46. data/spec/fixtures/vcr_cassettes/api/profile_extension/login.yml +982 -0
  47. data/spec/fixtures/vcr_cassettes/api/profile_extension/merge_profile_extension_records.yml +46 -0
  48. data/spec/fixtures/vcr_cassettes/api/profile_extension/retrieve_profile_extension_records.yml +45 -0
  49. data/spec/fixtures/vcr_cassettes/api/table/create.yml +45 -0
  50. data/spec/fixtures/vcr_cassettes/api/table/create_with_pk.yml +45 -0
  51. data/spec/fixtures/vcr_cassettes/api/table/delete.yml +45 -0
  52. data/spec/fixtures/vcr_cassettes/api/table/delete_with_pk.yml +45 -0
  53. data/spec/fixtures/vcr_cassettes/member/present1.yml +982 -0
  54. data/spec/fixtures/vcr_cassettes/member/present2.yml +45 -0
  55. data/spec/fixtures/vcr_cassettes/member/present3.yml +48 -0
  56. data/spec/fixtures/vcr_cassettes/member/present4.yml +48 -0
  57. data/spec/fixtures/vcr_cassettes/member/present5.yml +48 -0
  58. data/spec/fixtures/vcr_cassettes/member/retrieve_profile_extension.yml +87 -0
  59. data/spec/member_spec.rb +136 -0
  60. data/spec/spec_helper.rb +28 -2
  61. metadata +136 -19
  62. data/lib/responsys/responsys_api.rb +0 -41
  63. data/lib/savon/savon_api.rb +0 -22
  64. data/spec/responsys_api_spec.rb +0 -4
@@ -0,0 +1,23 @@
1
+ module Responsys
2
+ module Api
3
+ module Object
4
+ class OptionalData
5
+ include Responsys::Exceptions
6
+ attr_accessor :name, :value
7
+
8
+ def initialize(name = "", value = "")
9
+ raise ParameterException, I18n.t("api.object.optional_data.incorrect_optional_data_type") unless (name.is_a? String) && (value.is_a? String)
10
+ @name = name
11
+ @value = value
12
+ end
13
+
14
+ def to_api
15
+ {
16
+ Name: @name,
17
+ Value: @value
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module Responsys
2
+ module Api
3
+ module Object
4
+ class QueryColumn
5
+ include Responsys::Exceptions
6
+ attr_accessor :query_column_string
7
+ AVAILABLE_QUERY_COLUMN = %w(RIID CUSTOMER_ID EMAIL_ADDRESS MOBILE_NUMBER)
8
+
9
+ def initialize(query_column)
10
+ if AVAILABLE_QUERY_COLUMN.include? query_column
11
+ @query_column_string = query_column
12
+ else
13
+ raise ParameterException, I18n.t("api.object.query_column.incorrect_query_column")
14
+ end
15
+ end
16
+
17
+ def to_api
18
+ @query_column_string
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,30 @@
1
+ module Responsys
2
+ module Api
3
+ module Object
4
+ class Recipient
5
+ include Responsys::Api::Object
6
+ attr_accessor :list_name, :recipient_id, :customer_id, :email_address, :mobile_number, :email_format
7
+
8
+ def initialize(options = {})
9
+ @list_name = options[:listName] || InteractObject.new("", "")
10
+ @recipient_id = options[:recipientId] || ""
11
+ @customer_id = options[:customerId] || ""
12
+ @email_address = options[:emailAddress] || ""
13
+ @mobile_number = options[:mobileNumber] || ""
14
+ @email_format = options[:emailFormat] || EmailFormat.new
15
+ end
16
+
17
+ def to_api
18
+ {
19
+ listName: @list_name.to_api,
20
+ recipientId: @recipient_id.to_i,
21
+ customerId: @customer_id.to_s,
22
+ emailAddress: @email_address.to_s,
23
+ mobileNumber: @mobile_number.to_s,
24
+ emailFormat: @email_format.to_api
25
+ }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,21 @@
1
+ module Responsys
2
+ module Api
3
+ module Object
4
+ class RecipientData
5
+ attr_accessor :recipient, :optional_data
6
+
7
+ def initialize(recipient, optional_data = Responsys::Api::Object::OptionalData.new)
8
+ @recipient = recipient
9
+ @optional_data = optional_data
10
+ end
11
+
12
+ def to_api
13
+ {
14
+ recipient: @recipient.to_api,
15
+ optionalData: @optional_data.to_api
16
+ }
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module Responsys
2
+ module Api
3
+ module Object
4
+ class Record
5
+ include Responsys::Exceptions
6
+ attr_accessor :field_values
7
+
8
+ def initialize(field_values)
9
+ raise ParameterException, I18n.t("api.object.record.incorrect_field_values_type") unless field_values.is_a? Array
10
+ @field_values = field_values
11
+ end
12
+
13
+ def to_api
14
+ { fieldValues: @field_values }
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ module Responsys
2
+ module Api
3
+ module Object
4
+ class RecordData
5
+ include Responsys::Exceptions
6
+ include Responsys::Api::Object
7
+ attr_accessor :field_names, :records
8
+
9
+ def initialize(data)
10
+ raise ParameterException, I18n.t("api.object.record_data.incorrect_record_data_type") unless data.is_a? Array
11
+
12
+ self.field_names = data.map { |record| record.keys }.flatten.uniq
13
+
14
+ new_data = []
15
+ field_names.each { |field_name|
16
+ data.each_with_index { |entity, index|
17
+ new_data[index] ||= Record.new([])
18
+ new_data[index].field_values << (entity.has_key?(field_name) ? entity[field_name.to_sym] : "")
19
+ }
20
+ }
21
+
22
+ self.records = new_data
23
+ end
24
+
25
+ def to_api
26
+ { fieldNames: field_names, records: records.map(&:to_api) }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,30 @@
1
+ module Responsys
2
+ module Api
3
+ module Session
4
+ def login
5
+ response = run("login", credentials)
6
+ establish_session_id(response)
7
+ establish_jsession_id(response)
8
+ set_session_credentials
9
+ end
10
+
11
+ def logout
12
+ api_method(:logout)
13
+ end
14
+
15
+ private
16
+
17
+ def establish_session_id(login_response)
18
+ @session_id = login_response.body[:login_response][:result][:session_id]
19
+ end
20
+
21
+ def establish_jsession_id(login_response)
22
+ @jsession_id = login_response.http.cookies[0]
23
+ end
24
+
25
+ def set_session_credentials
26
+ @header = { SessionHeader: { sessionId: session_id } }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,49 @@
1
+ module Responsys
2
+ module Api
3
+ module Table
4
+ def create_table(interact_object, fields)
5
+ api_method(:create_table, { table: interact_object.to_api, fields: fields.map(&:to_api) })
6
+ end
7
+
8
+ def create_table_with_pk(interact_object, fields, primary_keys)
9
+ api_method(:create_table_with_pk, { table: interact_object.to_api, fields: fields.map(&:to_api), primaryKeys: primary_keys })
10
+ end
11
+
12
+ def delete_table(interact_object)
13
+ api_method(:delete_table, { table: interact_object.to_api })
14
+ end
15
+
16
+ def merge_into_profile_extension(interact_object, record_data, match_column, insert_on_no_match = false, update_on_match = "REPLACE_ALL")
17
+ api_method(:merge_into_profile_extension, { profileExtension: interact_object.to_api, recordData: record_data.to_api, matchColumn: match_column, insertOnNoMatch: insert_on_no_match, updateOnMatch: update_on_match })
18
+ end
19
+
20
+ def retrieve_profile_extension_records(interact_object, query_column, field_list, ids_to_retrieve)
21
+ api_method(:retrieve_profile_extension_records, { profileExtension: interact_object.to_api, queryColumn: query_column.to_api, fieldList: field_list, idsToRetrieve: ids_to_retrieve })
22
+ end
23
+
24
+ def delete_profile_extension_members(interact_object, query_column, ids_to_delete)
25
+ api_method(:delete_profile_extension_members, { profileExtension: interact_object.to_api, queryColumn: query_column.to_api, idsToDelete: ids_to_delete })
26
+ end
27
+
28
+ def merge_table_records
29
+
30
+ end
31
+
32
+ def merge_table_records_with_pk
33
+
34
+ end
35
+
36
+ def delete_table_records
37
+
38
+ end
39
+
40
+ def retrieve_table_records
41
+
42
+ end
43
+
44
+ def truncate_table
45
+
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,13 +1,13 @@
1
- class ResponsysApi
1
+ module Responsys
2
2
  class Configuration
3
3
  attr_accessor :settings
4
- # Put all these constants into a configurable setting hash
5
4
 
6
5
  def initialize
7
6
  @settings = {
8
7
  username: nil,
9
8
  password: nil,
10
- wsdl: ""
9
+ wsdl: "",
10
+ debug: false
11
11
  }
12
12
  end
13
13
  end
@@ -0,0 +1 @@
1
+ require "responsys/exceptions/parameter_exception"
@@ -0,0 +1,7 @@
1
+ module Responsys
2
+ module Exceptions
3
+ class ParameterException < Exception
4
+ end
5
+ end
6
+ end
7
+
@@ -1,7 +1,83 @@
1
- class ResponsysApi
1
+ module Responsys
2
2
  module Helper
3
- def self.format_response(response, action)
3
+ def self.format_response_result(response, action)
4
4
  response.body[("#{action}_response").to_sym][:result]
5
5
  end
6
+
7
+ def self.format_response_hash(response, action)
8
+ formatted_response = { status: "ok" }
9
+
10
+ return formatted_response unless response.body.has_key? "#{action}_response".to_sym
11
+
12
+ if response.body["#{action}_response".to_sym].has_key?(:result) and response.body["#{action}_response".to_sym][:result].is_a? Hash
13
+ formatted_response[:data] = handle_response_types(response.body["#{action}_response".to_sym])
14
+ elsif response.body["#{action}_response".to_sym].has_key?(:result)
15
+ formatted_response[:result] = response.body["#{action}_response".to_sym][:result]
16
+ elsif response.body["#{action}_response".to_sym].is_a? Hash and !response.body["#{action}_response".to_sym].empty?
17
+ formatted_response[:result] = response.body["#{action}_response".to_sym].values[0]
18
+ end
19
+
20
+ formatted_response
21
+ end
22
+
23
+ def self.format_record_data(record_data)
24
+ field_names = record_data[:field_names]
25
+ records = record_data[:records]
26
+
27
+ data = []
28
+ if records.is_a? Array
29
+ records.each do |record|
30
+ data << format_field_values(record, field_names)
31
+ end
32
+ else
33
+ data << format_field_values(records, field_names)
34
+ end
35
+
36
+ data
37
+ end
38
+
39
+ def self.format_field_values(record, field_names)
40
+ values = {}
41
+
42
+ if record.is_a? Hash and record[:field_values].is_a? Array
43
+ record[:field_values].each_with_index do |value, index|
44
+ values[field_names[index].to_sym] = value
45
+ end
46
+ elsif record.is_a? Hash
47
+ values[field_names.to_sym] = record[:field_values]
48
+ end
49
+
50
+ values
51
+ end
52
+
53
+ def self.handle_response_types(response_body)
54
+ data = []
55
+
56
+ if response_body[:result].has_key? :record_data
57
+ data = format_record_data(response_body[:result][:record_data])
58
+ else
59
+ data << response_body
60
+ end
61
+
62
+ data
63
+ end
64
+
65
+ def self.format_response_with_errors(error)
66
+ error_response = { status: "failure" }
67
+
68
+ if error.to_hash[:fault].has_key?(:detail) and !error.to_hash[:fault][:detail].nil?
69
+ key = error.to_hash[:fault][:detail].keys[0]
70
+ error_response[:error] = { http_status_code: error.http.code, code: error.to_hash[:fault][:detail][key][:exception_code], message: error.to_hash[:fault][:detail][key][:exception_message] }
71
+ error_response[:error][:trace] = error.to_hash[:fault][:detail][:source] if error.to_hash[:fault][:detail].has_key?(:source)
72
+ else
73
+ error_response[:error] = { http_status_code: error.http.code, code: error.to_hash[:fault][:faultcode], message: error.to_hash[:fault][:faultstring] }
74
+ end
75
+
76
+ error_response
77
+ end
78
+
79
+ def self.format_response_with_message(i18n_key)
80
+ { status: "failure", error: { http_status_code: "", code: i18n_key.split('.')[-1], message: I18n.t(i18n_key) } }
81
+ end
6
82
  end
7
83
  end
@@ -0,0 +1,20 @@
1
+ en:
2
+ api:
3
+ object:
4
+ field_type:
5
+ incorrect_field_type: The field type string you provided is incorrect
6
+ query_column:
7
+ incorrect_query_column: The query column you provided is incorrect
8
+ record_data:
9
+ incorrect_record_data_type: The data you provided is not an array
10
+ optional_data:
11
+ incorrect_optional_data_type: The name and value need to be Strings
12
+ email_format:
13
+ incorrect_email_format: The email format is not supported
14
+ record:
15
+ incorrect_field_values_type: The field_values must be an array
16
+ campaign:
17
+ incorrect_recipients_type: Recipients parameter must be an array
18
+ member:
19
+ riid_missing: Variable riid is not provided to the member
20
+ record_not_found: The member has not been found in the list
@@ -0,0 +1,80 @@
1
+ require "responsys/api/all"
2
+ require "responsys/api/object/all"
3
+
4
+ module Responsys
5
+ class Member
6
+ include Responsys::Api
7
+ include Responsys::Api::Object
8
+ attr_accessor :email, :user_riid
9
+
10
+ def initialize(email, riid = nil)
11
+ @email = email
12
+ @user_riid = riid
13
+ @client = Client.instance
14
+ end
15
+
16
+ def add_to_list(list, subscribe = false)
17
+ data = { EMAIL_ADDRESS_: @email, EMAIL_PERMISSION_STATUS_: subscribe ? "I" : "O" }
18
+ record = RecordData.new([data])
19
+
20
+ @client.merge_list_members_riid(list, record, ListMergeRule.new(insertOnNoMatch: true, updateOnMatch: "NO_UPDATE"))
21
+ end
22
+
23
+ def retrieve_profile_extension(profile_extension, fields)
24
+ return Responsys::Helper.format_response_with_message("member.riid_missing") if @user_riid.nil?
25
+ return Responsys::Helper.format_response_with_message("member.record_not_found") unless present_in_profile?(profile_extension)
26
+
27
+ @client.retrieve_profile_extension_records(profile_extension, QueryColumn.new("RIID"), fields, [@user_riid])
28
+ end
29
+
30
+ def subscribe(list)
31
+ update(list, [{ EMAIL_ADDRESS_: @email, EMAIL_PERMISSION_STATUS_: "I" }])
32
+ end
33
+
34
+ def unsubscribe(list)
35
+ update(list, [{ EMAIL_ADDRESS_: @email, EMAIL_PERMISSION_STATUS_: "O" }])
36
+ end
37
+
38
+ def update(list, data)
39
+ return Responsys::Helper.format_response_with_message("member.record_not_found") unless present_in_list?(list)
40
+
41
+ record = RecordData.new(data)
42
+ @client.merge_list_members(list, record)
43
+ end
44
+
45
+ def present_in_profile?(list)
46
+ return Responsys::Helper.format_response_with_message("member.riid_missing") if @user_riid.nil?
47
+
48
+ response = lookup_profile_via_key(list, "RIID", @user_riid)
49
+
50
+ !(response[:status] == "failure" && response[:error][:code] == "RECORD_NOT_FOUND")
51
+ end
52
+
53
+ def present_in_list?(list)
54
+ if !@user_riid.nil?
55
+ response = lookup_list_via_key(list, "RIID", @user_riid)
56
+ else
57
+ response = lookup_list_via_key(list, "EMAIL_ADDRESS", @email)
58
+ end
59
+
60
+ !(response[:status] == "failure" && response[:error][:code] == "RECORD_NOT_FOUND")
61
+ end
62
+
63
+ def subscribed?(list)
64
+ return Responsys::Helper.format_response_with_message("member.record_not_found") unless present_in_list?(list)
65
+
66
+ response = @client.retrieve_list_members(list, QueryColumn.new("EMAIL_ADDRESS"), %w(EMAIL_PERMISSION_STATUS_), [@email])
67
+ response[:data][0][:EMAIL_PERMISSION_STATUS_] == "I"
68
+ end
69
+
70
+ private
71
+
72
+ def lookup_profile_via_key(profile_extension, key, value)
73
+ @client.retrieve_profile_extension_records(profile_extension, QueryColumn.new(key), %w(RIID_), [value])
74
+ end
75
+
76
+ def lookup_list_via_key(list, key, value)
77
+ @client.retrieve_list_members(list, QueryColumn.new(key), %w(EMAIL_PERMISSION_STATUS_), [value])
78
+ end
79
+ end
80
+ end