intercom 3.5.10 → 4.1.2

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 (101) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +35 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +5 -0
  4. data/Gemfile +1 -4
  5. data/README.md +418 -216
  6. data/RELEASING.md +9 -0
  7. data/Rakefile +1 -1
  8. data/changes.txt +141 -0
  9. data/intercom.gemspec +1 -2
  10. data/lib/intercom.rb +34 -19
  11. data/lib/intercom/api_operations/archive.rb +16 -0
  12. data/lib/intercom/api_operations/delete.rb +4 -1
  13. data/lib/intercom/api_operations/find.rb +5 -2
  14. data/lib/intercom/api_operations/find_all.rb +4 -3
  15. data/lib/intercom/api_operations/list.rb +4 -1
  16. data/lib/intercom/api_operations/load.rb +4 -2
  17. data/lib/intercom/api_operations/nested_resource.rb +70 -0
  18. data/lib/intercom/api_operations/request_hard_delete.rb +12 -0
  19. data/lib/intercom/api_operations/save.rb +6 -4
  20. data/lib/intercom/api_operations/scroll.rb +4 -5
  21. data/lib/intercom/api_operations/search.rb +18 -0
  22. data/lib/intercom/article.rb +7 -0
  23. data/lib/intercom/base_collection_proxy.rb +72 -0
  24. data/lib/intercom/client.rb +66 -18
  25. data/lib/intercom/client_collection_proxy.rb +17 -39
  26. data/lib/intercom/collection.rb +7 -0
  27. data/lib/intercom/company.rb +8 -0
  28. data/lib/intercom/contact.rb +22 -3
  29. data/lib/intercom/conversation.rb +5 -0
  30. data/lib/intercom/data_attribute.rb +7 -0
  31. data/lib/intercom/deprecated_leads_collection_proxy.rb +22 -0
  32. data/lib/intercom/deprecated_resources.rb +13 -0
  33. data/lib/intercom/errors.rb +44 -4
  34. data/lib/intercom/extended_api_operations/segments.rb +3 -1
  35. data/lib/intercom/extended_api_operations/tags.rb +3 -1
  36. data/lib/intercom/lead.rb +21 -0
  37. data/lib/intercom/lib/typed_json_deserializer.rb +42 -37
  38. data/lib/intercom/note.rb +4 -0
  39. data/lib/intercom/request.rb +162 -95
  40. data/lib/intercom/scroll_collection_proxy.rb +38 -42
  41. data/lib/intercom/search_collection_proxy.rb +47 -0
  42. data/lib/intercom/section.rb +23 -0
  43. data/lib/intercom/segment.rb +4 -0
  44. data/lib/intercom/service/article.rb +20 -0
  45. data/lib/intercom/service/base_service.rb +13 -0
  46. data/lib/intercom/service/collection.rb +24 -0
  47. data/lib/intercom/service/company.rb +4 -2
  48. data/lib/intercom/service/contact.rb +29 -6
  49. data/lib/intercom/service/conversation.rb +23 -2
  50. data/lib/intercom/service/data_attribute.rb +20 -0
  51. data/lib/intercom/service/event.rb +12 -0
  52. data/lib/intercom/service/lead.rb +41 -0
  53. data/lib/intercom/service/note.rb +4 -8
  54. data/lib/intercom/service/section.rb +7 -0
  55. data/lib/intercom/service/tag.rb +8 -8
  56. data/lib/intercom/service/team.rb +17 -0
  57. data/lib/intercom/service/user.rb +4 -2
  58. data/lib/intercom/service/visitor.rb +15 -6
  59. data/lib/intercom/tag.rb +4 -0
  60. data/lib/intercom/team.rb +7 -0
  61. data/lib/intercom/traits/api_resource.rb +48 -27
  62. data/lib/intercom/traits/dirty_tracking.rb +8 -1
  63. data/lib/intercom/user.rb +12 -3
  64. data/lib/intercom/utils.rb +13 -2
  65. data/lib/intercom/version.rb +1 -1
  66. data/lib/intercom/visitor.rb +0 -2
  67. data/spec/spec_helper.rb +881 -436
  68. data/spec/unit/intercom/admin_spec.rb +2 -2
  69. data/spec/unit/intercom/article_spec.rb +40 -0
  70. data/spec/unit/intercom/base_collection_proxy_spec.rb +30 -0
  71. data/spec/unit/intercom/client_collection_proxy_spec.rb +41 -41
  72. data/spec/unit/intercom/client_spec.rb +76 -9
  73. data/spec/unit/intercom/collection_spec.rb +32 -0
  74. data/spec/unit/intercom/company_spec.rb +29 -21
  75. data/spec/unit/intercom/contact_spec.rb +365 -29
  76. data/spec/unit/intercom/conversation_spec.rb +70 -7
  77. data/spec/unit/intercom/count_spec.rb +4 -4
  78. data/spec/unit/intercom/data_attribute_spec.rb +40 -0
  79. data/spec/unit/intercom/deprecated_leads_collection_proxy_spec.rb +17 -0
  80. data/spec/unit/intercom/event_spec.rb +25 -8
  81. data/spec/unit/intercom/job_spec.rb +24 -24
  82. data/spec/unit/intercom/lead_spec.rb +57 -0
  83. data/spec/unit/intercom/lib/flat_store_spec.rb +22 -20
  84. data/spec/unit/intercom/message_spec.rb +1 -1
  85. data/spec/unit/intercom/note_spec.rb +4 -10
  86. data/spec/unit/intercom/request_spec.rb +150 -9
  87. data/spec/unit/intercom/scroll_collection_proxy_spec.rb +40 -39
  88. data/spec/unit/intercom/search_collection_proxy_spec.rb +60 -0
  89. data/spec/unit/intercom/section_spec.rb +32 -0
  90. data/spec/unit/intercom/segment_spec.rb +2 -2
  91. data/spec/unit/intercom/subscription_spec.rb +5 -6
  92. data/spec/unit/intercom/tag_spec.rb +22 -14
  93. data/spec/unit/intercom/team_spec.rb +21 -0
  94. data/spec/unit/intercom/traits/api_resource_spec.rb +129 -47
  95. data/spec/unit/intercom/user_spec.rb +227 -217
  96. data/spec/unit/intercom/visitor_spec.rb +49 -0
  97. data/spec/unit/intercom_spec.rb +5 -3
  98. metadata +63 -26
  99. data/.travis.yml +0 -6
  100. data/lib/intercom/extended_api_operations/users.rb +0 -16
  101. data/spec/unit/intercom/visitors_spec.rb +0 -61
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'intercom/service/base_service'
4
+ require 'intercom/api_operations/load'
5
+ require 'intercom/api_operations/list'
6
+ require 'intercom/api_operations/find'
7
+ require 'intercom/api_operations/find_all'
8
+ require 'intercom/api_operations/save'
9
+ require 'intercom/api_operations/scroll'
10
+ require 'intercom/api_operations/convert'
11
+ require 'intercom/api_operations/archive'
12
+ require 'intercom/api_operations/request_hard_delete'
13
+ require 'intercom/deprecated_leads_collection_proxy'
14
+
15
+ module Intercom
16
+ module Service
17
+ class Lead < BaseService
18
+ include ApiOperations::Load
19
+ include ApiOperations::List
20
+ include ApiOperations::Find
21
+ include ApiOperations::FindAll
22
+ include ApiOperations::Save
23
+ include ApiOperations::Scroll
24
+ include ApiOperations::Convert
25
+ include ApiOperations::Archive
26
+ include ApiOperations::RequestHardDelete
27
+
28
+ def collection_proxy_class
29
+ Intercom::DeprecatedLeadsCollectionProxy
30
+ end
31
+
32
+ def collection_class
33
+ Intercom::Lead
34
+ end
35
+
36
+ def collection_name
37
+ 'contacts'
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,22 +1,18 @@
1
1
  require 'intercom/service/base_service'
2
- require 'intercom/api_operations/list'
3
- require 'intercom/api_operations/find_all'
4
2
  require 'intercom/api_operations/find'
5
- require 'intercom/api_operations/load'
6
- require 'intercom/api_operations/save'
7
3
 
8
4
  module Intercom
9
5
  module Service
10
6
  class Note < BaseService
11
- include ApiOperations::Save
12
- include ApiOperations::List
13
- include ApiOperations::FindAll
14
7
  include ApiOperations::Find
15
- include ApiOperations::Load
16
8
 
17
9
  def collection_class
18
10
  Intercom::Note
19
11
  end
12
+
13
+ def collection_proxy_class
14
+ Intercom::BaseCollectionProxy
15
+ end
20
16
  end
21
17
  end
22
18
  end
@@ -0,0 +1,7 @@
1
+ require 'intercom/traits/api_resource'
2
+
3
+ module Intercom
4
+ class Section
5
+ include Traits::ApiResource
6
+ end
7
+ end
@@ -2,6 +2,7 @@ require 'intercom/service/base_service'
2
2
  require 'intercom/api_operations/save'
3
3
  require 'intercom/api_operations/list'
4
4
  require 'intercom/api_operations/find_all'
5
+ require 'intercom/api_operations/find'
5
6
 
6
7
  module Intercom
7
8
  module Service
@@ -10,11 +11,16 @@ module Intercom
10
11
  include ApiOperations::List
11
12
  include ApiOperations::FindAll
12
13
  include ApiOperations::Delete
14
+ include ApiOperations::Find
13
15
 
14
16
  def collection_class
15
17
  Intercom::Tag
16
18
  end
17
19
 
20
+ def collection_proxy_class
21
+ Intercom::BaseCollectionProxy
22
+ end
23
+
18
24
  def tag(params)
19
25
  params['tag_or_untag'] = 'tag'
20
26
  create(params)
@@ -22,17 +28,11 @@ module Intercom
22
28
 
23
29
  def untag(params)
24
30
  params['tag_or_untag'] = 'untag'
25
- users_or_companies(params).each do |user_or_company|
26
- user_or_company[:untag] = true
31
+ params[:companies].each do |company|
32
+ company[:untag] = true
27
33
  end
28
34
  create(params)
29
35
  end
30
-
31
- private
32
-
33
- def users_or_companies(params)
34
- params[:users] || params[:companies]
35
- end
36
36
  end
37
37
  end
38
38
  end
@@ -0,0 +1,17 @@
1
+ require 'intercom/service/base_service'
2
+ require 'intercom/api_operations/list'
3
+ require 'intercom/api_operations/find'
4
+
5
+ module Intercom
6
+ module Service
7
+ class Team < BaseService
8
+ include ApiOperations::List
9
+ include ApiOperations::Find
10
+
11
+ def collection_class
12
+ Intercom::Team
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -5,8 +5,9 @@ require 'intercom/api_operations/scroll'
5
5
  require 'intercom/api_operations/find'
6
6
  require 'intercom/api_operations/find_all'
7
7
  require 'intercom/api_operations/save'
8
- require 'intercom/api_operations/delete'
8
+ require 'intercom/api_operations/archive'
9
9
  require 'intercom/api_operations/bulk/submit'
10
+ require 'intercom/api_operations/request_hard_delete'
10
11
  require 'intercom/extended_api_operations/tags'
11
12
  require 'intercom/extended_api_operations/segments'
12
13
 
@@ -19,7 +20,8 @@ module Intercom
19
20
  include ApiOperations::Find
20
21
  include ApiOperations::FindAll
21
22
  include ApiOperations::Save
22
- include ApiOperations::Delete
23
+ include ApiOperations::Archive
24
+ include ApiOperations::RequestHardDelete
23
25
  include ApiOperations::Bulk::Submit
24
26
  include ExtendedApiOperations::Tags
25
27
  include ExtendedApiOperations::Segments
@@ -1,26 +1,35 @@
1
1
  require 'intercom/service/base_service'
2
2
  require 'intercom/api_operations/load'
3
- require 'intercom/api_operations/list'
4
3
  require 'intercom/api_operations/find'
5
- require 'intercom/api_operations/find_all'
6
4
  require 'intercom/api_operations/save'
7
- require 'intercom/api_operations/convert'
8
5
  require 'intercom/api_operations/delete'
9
6
 
10
7
  module Intercom
11
8
  module Service
12
9
  class Visitor < BaseService
13
10
  include ApiOperations::Load
14
- include ApiOperations::List
15
11
  include ApiOperations::Find
16
- include ApiOperations::FindAll
17
12
  include ApiOperations::Save
18
- include ApiOperations::Convert
19
13
  include ApiOperations::Delete
20
14
 
21
15
  def collection_class
22
16
  Intercom::Visitor
23
17
  end
18
+
19
+ def convert(visitor, contact = false)
20
+ req = { visitor: { user_id: visitor.user_id } }
21
+ if contact
22
+ req[:user] = identity_hash(contact)
23
+ req[:type] = 'user'
24
+ else
25
+ req[:type] = 'lead'
26
+ end
27
+ Intercom::Contact.new.from_response(
28
+ @client.post(
29
+ "/visitors/convert", req
30
+ )
31
+ )
32
+ end
24
33
  end
25
34
  end
26
35
  end
data/lib/intercom/tag.rb CHANGED
@@ -3,5 +3,9 @@ require 'intercom/traits/api_resource'
3
3
  module Intercom
4
4
  class Tag
5
5
  include Traits::ApiResource
6
+
7
+ def self.collection_proxy_class
8
+ Intercom::BaseCollectionProxy
9
+ end
6
10
  end
7
11
  end
@@ -0,0 +1,7 @@
1
+ require 'intercom/traits/api_resource'
2
+
3
+ module Intercom
4
+ class Team
5
+ include Traits::ApiResource
6
+ end
7
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'intercom/lib/flat_store'
2
4
  require 'intercom/lib/dynamic_accessors'
3
5
  require 'intercom/lib/dynamic_accessors_on_method_missing'
@@ -6,16 +8,19 @@ require 'intercom/lib/typed_json_deserializer'
6
8
 
7
9
  module Intercom
8
10
  module Traits
9
-
10
11
  module ApiResource
11
12
  include DirtyTracking
12
13
 
13
- attr_accessor :id
14
+ attr_accessor :id, :client
14
15
 
15
16
  def initialize(attributes = {})
16
17
  from_hash(attributes)
17
18
  end
18
19
 
20
+ def ==(other)
21
+ self.class == other.class && to_json == other.to_json
22
+ end
23
+
19
24
  def from_response(response)
20
25
  from_hash(response)
21
26
  reset_changed_fields!
@@ -24,7 +29,6 @@ module Intercom
24
29
 
25
30
  def from_hash(hash)
26
31
  hash.each do |attribute, value|
27
- next if type_field?(attribute)
28
32
  initialize_property(attribute, value)
29
33
  end
30
34
  initialize_missing_flat_store_attributes if respond_to? :flat_store_attributes
@@ -32,59 +36,81 @@ module Intercom
32
36
  end
33
37
 
34
38
  def to_hash
35
- instance_variables_excluding_dirty_tracking_field.inject({}) do |hash, variable|
36
- hash[variable.to_s.delete("@")] = instance_variable_get(variable)
37
- hash
39
+ instance_variables_excluding_dirty_tracking_field.each_with_object({}) do |variable, hash|
40
+ hash[variable.to_s.delete('@')] = instance_variable_get(variable)
41
+ end
42
+ end
43
+
44
+ def to_json(*args)
45
+ instance_variables_excluding_dirty_tracking_field.each_with_object({}) do |variable, hash|
46
+ next if variable == :@client
47
+
48
+ value = instance_variable_get(variable)
49
+ hash[variable.to_s.delete('@')] = value.respond_to?(:to_json) ? value.to_json(*args) : value
38
50
  end
39
51
  end
40
52
 
41
53
  def to_submittable_hash
42
54
  submittable_hash = {}
43
55
  to_hash.each do |attribute, value|
44
- submittable_hash[attribute] = value if submittable_attribute?(attribute, value)
56
+ next unless submittable_attribute?(attribute, value)
57
+
58
+ submittable_hash[attribute] = value.respond_to?(:to_submittable_hash) ? value.to_submittable_hash : value
45
59
  end
46
60
  submittable_hash
47
61
  end
48
62
 
49
63
  def method_missing(method_sym, *arguments, &block)
50
- Lib::DynamicAccessorsOnMethodMissing.new(method_sym, *arguments, self).
51
- define_accessors_or_call { super }
64
+ Lib::DynamicAccessorsOnMethodMissing.new(method_sym, *arguments, self)
65
+ .define_accessors_or_call { super }
52
66
  end
53
67
 
54
68
  def flat_store_attribute?(attribute)
55
- (respond_to?(:flat_store_attributes)) && (flat_store_attributes.map(&:to_s).include?(attribute.to_s))
69
+ respond_to?(:flat_store_attributes) && flat_store_attributes.map(&:to_s).include?(attribute.to_s)
56
70
  end
57
71
 
58
72
  private
59
73
 
60
74
  def initialize_property(attribute, value)
75
+ return if addressable_list?(attribute, value)
76
+
61
77
  Lib::DynamicAccessors.define_accessors(attribute, value, self) unless accessors_already_defined?(attribute)
62
78
  set_property(attribute, value)
63
79
  end
64
80
 
81
+ def addressable_list?(attribute, value)
82
+ return false unless typed_property?(attribute, value)
83
+
84
+ value['type'] == 'list' && value['url']
85
+ end
86
+
65
87
  def accessors_already_defined?(attribute)
66
88
  respond_to?(attribute) && respond_to?("#{attribute}=")
67
89
  end
68
90
 
69
91
  def set_property(attribute, value)
92
+ value_to_set = parsed_value_for_attribute(attribute, value)
93
+ call_setter_for_attribute(attribute, value_to_set)
94
+ end
95
+
96
+ def parsed_value_for_attribute(attribute, value)
70
97
  if typed_property?(attribute, value)
71
- value_to_set = Intercom::Lib::TypedJsonDeserializer.new(value).deserialize
98
+ Intercom::Lib::TypedJsonDeserializer.new(value, client).deserialize
72
99
  elsif flat_store_attribute?(attribute)
73
- value_to_set = Intercom::Lib::FlatStore.new(value)
100
+ Intercom::Lib::FlatStore.new(value)
74
101
  else
75
- value_to_set = value
102
+ value
76
103
  end
77
- call_setter_for_attribute(attribute, value_to_set)
78
104
  end
79
105
 
80
106
  def custom_attribute_field?(attribute)
81
- attribute == 'custom_attributes'
107
+ attribute.to_s == 'custom_attributes'
82
108
  end
83
-
109
+
84
110
  def message_from_field?(attribute, value)
85
111
  attribute.to_s == 'from' && value.is_a?(Hash) && value['type']
86
112
  end
87
-
113
+
88
114
  def message_to_field?(attribute, value)
89
115
  attribute.to_s == 'to' && value.is_a?(Hash) && value['type']
90
116
  end
@@ -94,20 +120,16 @@ module Intercom
94
120
  !custom_attribute_field?(attribute) &&
95
121
  !message_from_field?(attribute, value) &&
96
122
  !message_to_field?(attribute, value) &&
97
- attribute != 'metadata'
123
+ attribute.to_s != 'metadata'
98
124
  end
99
125
 
100
126
  def typed_value?(value)
101
- value.is_a? Hash and !!value['type']
127
+ value.is_a?(Hash) && !!value['type']
102
128
  end
103
129
 
104
130
  def call_setter_for_attribute(attribute, value)
105
- setter_method = "#{attribute.to_s}="
106
- self.send(setter_method, value)
107
- end
108
-
109
- def type_field?(attribute)
110
- attribute == 'type'
131
+ setter_method = "#{attribute}="
132
+ send(setter_method, value)
111
133
  end
112
134
 
113
135
  def initialize_missing_flat_store_attributes
@@ -125,7 +147,7 @@ module Intercom
125
147
 
126
148
  module ClassMethods
127
149
  def from_api(api_response)
128
- object = self.new
150
+ object = new
129
151
  object.from_response(api_response)
130
152
  object
131
153
  end
@@ -134,7 +156,6 @@ module Intercom
134
156
  def self.included(base)
135
157
  base.extend(ClassMethods)
136
158
  end
137
-
138
159
  end
139
160
  end
140
161
  end
@@ -22,7 +22,14 @@ module Intercom
22
22
 
23
23
  def field_changed?(field_name)
24
24
  @changed_fields ||= Set.new
25
- @changed_fields.include?(field_name.to_s)
25
+ field = instance_variable_get("@#{field_name}")
26
+ if field.respond_to?(:field_changed?)
27
+ field.to_hash.any? do |attribute, _|
28
+ field.field_changed?(attribute)
29
+ end
30
+ else
31
+ @changed_fields.include?(field_name.to_s)
32
+ end
26
33
  end
27
34
 
28
35
  def instance_variables_excluding_dirty_tracking_field
data/lib/intercom/user.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'intercom/traits/incrementable_attributes'
2
4
  require 'intercom/traits/api_resource'
3
5
 
@@ -6,9 +8,16 @@ module Intercom
6
8
  include Traits::IncrementableAttributes
7
9
  include Traits::ApiResource
8
10
 
9
- def identity_vars ; [:id, :email, :user_id] ; end
10
- def flat_store_attributes ; [:custom_attributes] ; end
11
- def update_verb ; 'post' ; end
11
+ def identity_vars
12
+ %i[id email user_id]
13
+ end
14
+
15
+ def flat_store_attributes
16
+ [:custom_attributes]
17
+ end
12
18
 
19
+ def update_verb
20
+ 'post'
21
+ end
13
22
  end
14
23
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Intercom
2
4
  module Utils
3
5
  class << self
@@ -7,6 +9,7 @@ module Intercom
7
9
 
8
10
  def pluralize(str)
9
11
  return str.gsub(/y$/, 'ies') if str =~ /y$/
12
+
10
13
  "#{str}s"
11
14
  end
12
15
 
@@ -23,7 +26,13 @@ module Intercom
23
26
  end
24
27
 
25
28
  def resource_class_to_singular_name(resource_class)
26
- resource_class.to_s.split('::')[-1].downcase
29
+ resource_name = resource_class.to_s.split('::')[-1]
30
+ resource_name = maybe_underscore_name(resource_name)
31
+ resource_name.downcase
32
+ end
33
+
34
+ def maybe_underscore_name(resource_name)
35
+ resource_name.gsub!(/(.)([A-Z])/, '\1_\2') || resource_name
27
36
  end
28
37
 
29
38
  def resource_class_to_collection_name(resource_class)
@@ -52,9 +61,11 @@ module Intercom
52
61
  end
53
62
 
54
63
  def entity_key_from_type(type)
64
+ return 'data' if type == 'list'
65
+
55
66
  is_list = type.split('.')[1] == 'list'
56
67
  entity_name = type.split('.')[0]
57
- is_list ? Utils.pluralize(entity_name) : entity_name
68
+ is_list ? Utils.pluralize(entity_name) : entity_name
58
69
  end
59
70
  end
60
71
  end