responsys-api 0.0.3 → 0.0.4

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