intercom 3.9.5 → 4.2.1

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 +4 -4
  2. data/README.md +483 -234
  3. data/Rakefile +1 -1
  4. data/changes.txt +37 -0
  5. data/lib/intercom/api_operations/archive.rb +2 -1
  6. data/lib/intercom/api_operations/delete.rb +16 -0
  7. data/lib/intercom/api_operations/find.rb +5 -2
  8. data/lib/intercom/api_operations/find_all.rb +4 -3
  9. data/lib/intercom/api_operations/list.rb +4 -1
  10. data/lib/intercom/api_operations/load.rb +4 -2
  11. data/lib/intercom/api_operations/nested_resource.rb +68 -0
  12. data/lib/intercom/api_operations/save.rb +6 -4
  13. data/lib/intercom/api_operations/scroll.rb +4 -5
  14. data/lib/intercom/api_operations/search.rb +3 -2
  15. data/lib/intercom/article.rb +7 -0
  16. data/lib/intercom/base_collection_proxy.rb +74 -0
  17. data/lib/intercom/client.rb +48 -25
  18. data/lib/intercom/client_collection_proxy.rb +17 -39
  19. data/lib/intercom/collection.rb +7 -0
  20. data/lib/intercom/company.rb +8 -0
  21. data/lib/intercom/contact.rb +23 -3
  22. data/lib/intercom/conversation.rb +5 -0
  23. data/lib/intercom/data_attribute.rb +7 -0
  24. data/lib/intercom/deprecated_leads_collection_proxy.rb +22 -0
  25. data/lib/intercom/deprecated_resources.rb +13 -0
  26. data/lib/intercom/errors.rb +6 -0
  27. data/lib/intercom/export_content.rb +7 -0
  28. data/lib/intercom/extended_api_operations/segments.rb +3 -1
  29. data/lib/intercom/extended_api_operations/tags.rb +3 -1
  30. data/lib/intercom/lead.rb +21 -0
  31. data/lib/intercom/lib/dynamic_accessors.rb +9 -10
  32. data/lib/intercom/lib/typed_json_deserializer.rb +45 -35
  33. data/lib/intercom/note.rb +4 -0
  34. data/lib/intercom/phone_call_redirect.rb +7 -0
  35. data/lib/intercom/request.rb +39 -33
  36. data/lib/intercom/scroll_collection_proxy.rb +38 -42
  37. data/lib/intercom/search_collection_proxy.rb +30 -65
  38. data/lib/intercom/section.rb +23 -0
  39. data/lib/intercom/segment.rb +4 -0
  40. data/lib/intercom/service/article.rb +20 -0
  41. data/lib/intercom/service/base_service.rb +7 -0
  42. data/lib/intercom/service/collection.rb +24 -0
  43. data/lib/intercom/service/company.rb +2 -12
  44. data/lib/intercom/service/contact.rb +35 -10
  45. data/lib/intercom/service/conversation.rb +16 -3
  46. data/lib/intercom/service/data_attribute.rb +20 -0
  47. data/lib/intercom/service/export_content.rb +30 -0
  48. data/lib/intercom/service/lead.rb +41 -0
  49. data/lib/intercom/service/note.rb +4 -8
  50. data/lib/intercom/service/phone_call_redirect.rb +15 -0
  51. data/lib/intercom/service/section.rb +7 -0
  52. data/lib/intercom/service/subscription.rb +2 -2
  53. data/lib/intercom/service/subscription_type.rb +18 -0
  54. data/lib/intercom/service/tag.rb +9 -9
  55. data/lib/intercom/service/visitor.rb +17 -8
  56. data/lib/intercom/subscription_type.rb +12 -0
  57. data/lib/intercom/tag.rb +4 -0
  58. data/lib/intercom/traits/api_resource.rb +44 -18
  59. data/lib/intercom/traits/dirty_tracking.rb +8 -1
  60. data/lib/intercom/user.rb +12 -3
  61. data/lib/intercom/utils.rb +19 -3
  62. data/lib/intercom/version.rb +1 -1
  63. data/lib/intercom/visitor.rb +0 -2
  64. data/lib/intercom.rb +39 -22
  65. data/spec/spec_helper.rb +843 -520
  66. data/spec/unit/intercom/admin_spec.rb +2 -2
  67. data/spec/unit/intercom/article_spec.rb +40 -0
  68. data/spec/unit/intercom/base_collection_proxy_spec.rb +52 -0
  69. data/spec/unit/intercom/client_collection_proxy_spec.rb +41 -41
  70. data/spec/unit/intercom/client_spec.rb +25 -26
  71. data/spec/unit/intercom/collection_spec.rb +32 -0
  72. data/spec/unit/intercom/company_spec.rb +19 -15
  73. data/spec/unit/intercom/contact_spec.rb +402 -33
  74. data/spec/unit/intercom/conversation_spec.rb +60 -7
  75. data/spec/unit/intercom/count_spec.rb +4 -4
  76. data/spec/unit/intercom/data_attribute_spec.rb +40 -0
  77. data/spec/unit/intercom/deprecated_leads_collection_proxy_spec.rb +17 -0
  78. data/spec/unit/intercom/event_spec.rb +16 -11
  79. data/spec/unit/intercom/export_content_spec.rb +28 -0
  80. data/spec/unit/intercom/job_spec.rb +24 -24
  81. data/spec/unit/intercom/lead_spec.rb +57 -0
  82. data/spec/unit/intercom/lib/flat_store_spec.rb +22 -20
  83. data/spec/unit/intercom/message_spec.rb +1 -1
  84. data/spec/unit/intercom/note_spec.rb +4 -10
  85. data/spec/unit/intercom/phone_call_redirect.rb +12 -0
  86. data/spec/unit/intercom/request_spec.rb +14 -1
  87. data/spec/unit/intercom/scroll_collection_proxy_spec.rb +40 -39
  88. data/spec/unit/intercom/search_collection_proxy_spec.rb +32 -28
  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 +28 -14
  93. data/spec/unit/intercom/team_spec.rb +2 -2
  94. data/spec/unit/intercom/traits/api_resource_spec.rb +107 -52
  95. data/spec/unit/intercom/user_spec.rb +224 -226
  96. data/spec/unit/intercom/visitor_spec.rb +49 -0
  97. data/spec/unit/intercom_spec.rb +5 -3
  98. metadata +44 -8
  99. data/lib/intercom/customer.rb +0 -10
  100. data/lib/intercom/service/customer.rb +0 -14
  101. data/spec/unit/intercom/visitors_spec.rb +0 -61
data/Rakefile CHANGED
@@ -18,4 +18,4 @@ Rake::TestTask.new("spec:integration") do |spec|
18
18
  end
19
19
 
20
20
  task :spec => "spec:unit"
21
- task :default => :spec
21
+ task :default => :spec
data/changes.txt CHANGED
@@ -1,3 +1,40 @@
1
+ 4.1.3
2
+ - Updated ReadMe with more errors.
3
+ - Fixed issue where paginated requests could only be iterated through once.
4
+ - Moved Dynamic accessors from class level to instance level.
5
+
6
+ 4.1.2
7
+ - Adding support for company delete.
8
+ - Adding support for archiving/unarchiving contacts.
9
+ - Adding support for listing contact segments.
10
+ - Fixed issue with scroll collection proxy.
11
+ - Fixed issue with running assignment rules on a conversation.
12
+
13
+ 4.1.1
14
+ - Fixed bug with deprecated lead resource.
15
+
16
+ 4.1.0
17
+ - Added support for new Articles API.
18
+ - Added support for new Collections API.
19
+ - Added support for new Sections API.
20
+ - Added support to equate two resources.
21
+ - Fixed issue for dirty tracking nested typed objects.
22
+
23
+ 4.0.1
24
+ - Fixed bug with nested resources.
25
+ - Support for add/remove contact on conversation object.
26
+
27
+ 4.0.0
28
+ New version to support API version 2.0.
29
+ - Added support for new Contacts API.
30
+ - Added support for Conversation Search and for Conversation model changes.
31
+ - New DataAttribute class to support the Data Attributes. See README for details on usage.
32
+ - New method to run assignment rules on a conversation: `intercom.conversations.run_assignment_rules(<convo_id>)`.
33
+ - See Migration guide for breaking changes: https://github.com/intercom/intercom-ruby/wiki/Migration-guide-for-v4
34
+
35
+ 3.9.5
36
+ Add Unstable version support
37
+
1
38
  3.9.4
2
39
  Add handling for Gateway Timeouts
3
40
 
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'intercom/utils'
2
4
 
3
5
  module Intercom
4
6
  module ApiOperations
5
7
  module Archive
6
8
  def archive(object)
7
- collection_name = Utils.resource_class_to_collection_name(collection_class)
8
9
  @client.delete("/#{collection_name}/#{object.id}", {})
9
10
  object
10
11
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'intercom/utils'
4
+
5
+ module Intercom
6
+ module ApiOperations
7
+ module Delete
8
+ def delete(object)
9
+ @client.delete("/#{collection_name}/#{object.id}", {})
10
+ object
11
+ end
12
+
13
+ alias_method 'archive', 'delete'
14
+ end
15
+ end
16
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'intercom/utils'
2
4
 
3
5
  module Intercom
@@ -5,14 +7,15 @@ module Intercom
5
7
  module Find
6
8
  def find(params)
7
9
  raise BadRequestError, "#{self}#find takes a hash as its parameter but you supplied #{params.inspect}" unless params.is_a? Hash
8
- collection_name = Utils.resource_class_to_collection_name(collection_class)
10
+
9
11
  if params[:id]
10
12
  id = params.delete(:id)
11
13
  response = @client.get("/#{collection_name}/#{id}", params)
12
14
  else
13
15
  response = @client.get("/#{collection_name}", params)
14
16
  end
15
- raise Intercom::HttpError.new('Http Error - No response entity returned') unless response
17
+ raise Intercom::HttpError, 'Http Error - No response entity returned' unless response
18
+
16
19
  from_api(response)
17
20
  end
18
21
  end
@@ -1,13 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'intercom/client_collection_proxy'
2
4
  require 'intercom/utils'
3
5
 
4
6
  module Intercom
5
7
  module ApiOperations
6
8
  module FindAll
7
-
8
9
  def find_all(params)
9
10
  raise BadRequestError, "#find takes a hash as its parameter but you supplied #{params.inspect}" unless params.is_a? Hash
10
- collection_name = Utils.resource_class_to_collection_name(collection_class)
11
+
11
12
  finder_details = {}
12
13
  if params[:id] && !type_switched_finder?(params)
13
14
  finder_details[:url] = "/#{collection_name}/#{params[:id]}"
@@ -16,7 +17,7 @@ module Intercom
16
17
  finder_details[:url] = "/#{collection_name}"
17
18
  finder_details[:params] = params
18
19
  end
19
- collection_proxy_class.new(collection_name, finder_details: finder_details, client: @client)
20
+ collection_proxy_class.new(collection_name, collection_class, details: finder_details, client: @client)
20
21
  end
21
22
 
22
23
  private
@@ -1,11 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'intercom/client_collection_proxy'
4
+ require 'intercom/base_collection_proxy'
2
5
  require 'intercom/utils'
3
6
 
4
7
  module Intercom
5
8
  module ApiOperations
6
9
  module List
7
10
  def all
8
- ClientCollectionProxy.new(Utils.resource_class_to_collection_name(collection_class), client: @client)
11
+ collection_proxy_class.new(collection_name, collection_class, client: @client)
9
12
  end
10
13
  end
11
14
  end
@@ -1,16 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'intercom/utils'
2
4
 
3
5
  module Intercom
4
6
  module ApiOperations
5
7
  module Load
6
8
  def load(object)
7
- collection_name = Utils.resource_class_to_collection_name(collection_class)
8
9
  if object.id
9
10
  response = @client.get("/#{collection_name}/#{object.id}", {})
10
11
  else
11
12
  raise "Cannot load #{collection_class} as it does not have a valid id."
12
13
  end
13
- raise Intercom::HttpError.new('Http Error - No response entity returned') unless response
14
+ raise Intercom::HttpError, 'Http Error - No response entity returned' unless response
15
+
14
16
  object.from_response(response)
15
17
  end
16
18
  end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Intercom
4
+ module ApiOperations
5
+ module NestedResource
6
+ module ClassMethods
7
+ def nested_resource_methods(resource,
8
+ path: nil,
9
+ operations: nil,
10
+ resource_plural: nil)
11
+ resource_plural ||= Utils.pluralize(resource.to_s)
12
+ path ||= resource_plural
13
+ raise ArgumentError, 'operations array required' if operations.nil?
14
+
15
+ resource_url_method = :"#{resource_plural}_url"
16
+ resource_name = Utils.resource_class_to_collection_name(self)
17
+ define_method(resource_url_method.to_sym) do |id, nested_id = nil|
18
+ url = "/#{resource_name}/#{id}/#{path}"
19
+ url += "/#{nested_id}" unless nested_id.nil?
20
+ url
21
+ end
22
+
23
+ operations.each do |operation|
24
+ case operation
25
+ when :create
26
+ define_method(:"create_#{resource}") do |params|
27
+ url = send(resource_url_method, self.id)
28
+ response = client.post(url, params)
29
+ raise_no_response_error unless response
30
+ self.class.from_api(response)
31
+ end
32
+ when :add
33
+ define_method(:"add_#{resource}") do |params|
34
+ url = send(resource_url_method, self.id)
35
+ response = client.post(url, params)
36
+ raise_no_response_error unless response
37
+ self.class.from_api(response)
38
+ end
39
+ when :delete
40
+ define_method(:"remove_#{resource}") do |params|
41
+ url = send(resource_url_method, self.id, params[:id])
42
+ response = client.delete(url, params)
43
+ raise_no_response_error unless response
44
+ self.class.from_api(response)
45
+ end
46
+ when :list
47
+ define_method(resource_plural.to_sym) do
48
+ url = send(resource_url_method, self.id)
49
+ resource_class = Utils.constantize_resource_name(resource.to_s)
50
+ resource_class.collection_proxy_class.new(resource_plural, resource_class, details: { url: url }, client: client)
51
+ end
52
+ else
53
+ raise ArgumentError, "Unknown operation: #{operation.inspect}"
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ def self.included(base)
60
+ base.extend(ClassMethods)
61
+ end
62
+
63
+ private def raise_no_response_error
64
+ raise Intercom::HttpError, 'Http Error - No response entity returned'
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'intercom/utils'
2
4
  require 'ext/sliceable_hash'
3
5
 
@@ -8,8 +10,8 @@ module Intercom
8
10
  private_constant :PARAMS_NOT_PROVIDED
9
11
 
10
12
  def create(params = PARAMS_NOT_PROVIDED)
11
- if collection_class.ancestors.include?(Intercom::Contact) && params == PARAMS_NOT_PROVIDED
12
- params = Hash.new
13
+ if collection_class.ancestors.include?(Intercom::Lead) && params == PARAMS_NOT_PROVIDED
14
+ params = {}
13
15
  elsif params == PARAMS_NOT_PROVIDED
14
16
  raise ArgumentError, '.create requires 1 parameter'
15
17
  end
@@ -20,17 +22,17 @@ module Intercom
20
22
  end
21
23
 
22
24
  def save(object)
23
- collection_name = Utils.resource_class_to_collection_name(collection_class)
24
25
  if id_present?(object) && !posted_updates?(object)
25
26
  response = @client.put("/#{collection_name}/#{object.id}", object.to_submittable_hash)
26
27
  else
27
28
  response = @client.post("/#{collection_name}", object.to_submittable_hash.merge(identity_hash(object)))
28
29
  end
30
+ object.client = @client
29
31
  object.from_response(response) if response # may be nil we received back a 202
30
32
  end
31
33
 
32
34
  def identity_hash(object)
33
- object.respond_to?(:identity_vars) ? SliceableHash.new(object.to_hash).slice(*(object.identity_vars.map(&:to_s))) : {}
35
+ object.respond_to?(:identity_vars) ? SliceableHash.new(object.to_hash).slice(*object.identity_vars.map(&:to_s)) : {}
34
36
  end
35
37
 
36
38
  private
@@ -1,17 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'intercom/scroll_collection_proxy'
2
4
  require 'intercom/utils'
3
5
 
4
6
  module Intercom
5
7
  module ApiOperations
6
8
  module Scroll
7
-
8
- def scroll()
9
- collection_name = Utils.resource_class_to_collection_name(collection_class)
9
+ def scroll
10
10
  finder_details = {}
11
11
  finder_details[:url] = "/#{collection_name}"
12
- ScrollCollectionProxy.new(collection_name, finder_details: finder_details, client: @client)
12
+ ScrollCollectionProxy.new(collection_name, collection_class, details: finder_details, client: @client)
13
13
  end
14
-
15
14
  end
16
15
  end
17
16
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'intercom/search_collection_proxy'
2
4
  require 'intercom/utils'
3
5
 
@@ -5,12 +7,11 @@ module Intercom
5
7
  module ApiOperations
6
8
  module Search
7
9
  def search(params)
8
- collection_name = Utils.resource_class_to_collection_name(collection_class)
9
10
  search_details = {
10
11
  url: "/#{collection_name}/search",
11
12
  params: params
12
13
  }
13
- SearchCollectionProxy.new(collection_name, search_details: search_details, client: @client)
14
+ SearchCollectionProxy.new(collection_name, collection_class, details: search_details, client: @client)
14
15
  end
15
16
  end
16
17
  end
@@ -0,0 +1,7 @@
1
+ require 'intercom/traits/api_resource'
2
+
3
+ module Intercom
4
+ class Article
5
+ include Traits::ApiResource
6
+ end
7
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'intercom/utils'
4
+
5
+ module Intercom
6
+ class BaseCollectionProxy
7
+ attr_reader :resource_name, :url, :resource_class
8
+
9
+ def initialize(resource_name, resource_class, details: {}, client:, method: 'get')
10
+ @resource_name = resource_name
11
+ @resource_class = resource_class
12
+ @url = (details[:url] || "/#{@resource_name}")
13
+ @params = (details[:params] || {})
14
+ @client = client
15
+ @method = method
16
+ end
17
+
18
+ def each(&block)
19
+ loop do
20
+ response_hash = @client.public_send(@method, @url, payload)
21
+ raise Intercom::HttpError, 'Http Error - No response entity returned' unless response_hash
22
+
23
+ deserialize_response_hash(response_hash, block)
24
+ break unless has_next_link?(response_hash)
25
+ end
26
+ self
27
+ end
28
+
29
+ def [](target_index)
30
+ each_with_index do |item, index|
31
+ return item if index == target_index
32
+ end
33
+ nil
34
+ end
35
+
36
+ include Enumerable
37
+
38
+ private
39
+
40
+ def deserialize_response_hash(response_hash, block)
41
+ top_level_type = response_hash.delete('type')
42
+ top_level_entity_key = if resource_name == 'subscriptions'
43
+ 'items'
44
+ else
45
+ Utils.entity_key_from_type(top_level_type)
46
+ end
47
+ response_hash[top_level_entity_key].each do |object_json|
48
+ if top_level_type == 'event.summary'
49
+ block.call Lib::TypedJsonDeserializer.new(object_json, @client, top_level_type).deserialize
50
+ else
51
+ block.call Lib::TypedJsonDeserializer.new(object_json, @client).deserialize
52
+ end
53
+ end
54
+ end
55
+
56
+ def has_next_link?(response_hash)
57
+ paging_info = response_hash.delete('pages')
58
+ return false unless paging_info
59
+
60
+ paging_next = paging_info['next']
61
+ if paging_next
62
+ @params[:starting_after] = paging_next['starting_after']
63
+ return true
64
+ else
65
+ @params[:starting_after] = nil
66
+ return false
67
+ end
68
+ end
69
+
70
+ def payload
71
+ @params.keep_if { |k, v| !v.nil? }.to_h
72
+ end
73
+ end
74
+ end
@@ -1,38 +1,35 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Intercom
2
4
  class MisconfiguredClientError < StandardError; end
3
5
  class Client
4
6
  include Options
5
- attr_reader :base_url, :rate_limit_details, :username_part, :password_part, :handle_rate_limit, :timeouts, :api_version
7
+ include DeprecatedResources
8
+ attr_reader :base_url, :rate_limit_details, :token, :handle_rate_limit, :timeouts, :api_version
6
9
 
7
10
  class << self
8
11
  def set_base_url(base_url)
9
- return Proc.new do |o|
12
+ proc do |o|
10
13
  old_url = o.base_url
11
14
  o.send(:base_url=, base_url)
12
- Proc.new { |obj| set_base_url(old_url).call(o) }
15
+ proc { |_obj| set_base_url(old_url).call(o) }
13
16
  end
14
17
  end
15
18
 
16
19
  def set_timeouts(open_timeout: nil, read_timeout: nil)
17
- return Proc.new do |o|
20
+ proc do |o|
18
21
  old_timeouts = o.timeouts
19
22
  timeouts = {}
20
23
  timeouts[:open_timeout] = open_timeout if open_timeout
21
24
  timeouts[:read_timeout] = read_timeout if read_timeout
22
25
  o.send(:timeouts=, timeouts)
23
- Proc.new { |obj| set_timeouts(old_timeouts).call(o) }
26
+ proc { |_obj| set_timeouts(old_timeouts).call(o) }
24
27
  end
25
28
  end
26
29
  end
27
30
 
28
- def initialize(app_id: 'my_app_id', api_key: 'my_api_key', token: nil, base_url:'https://api.intercom.io', handle_rate_limit: false, api_version: nil)
29
- if token
30
- @username_part = token
31
- @password_part = ""
32
- else
33
- @username_part = app_id
34
- @password_part = api_key
35
- end
31
+ def initialize(token: nil, base_url: 'https://api.intercom.io', handle_rate_limit: false, api_version: nil)
32
+ @token = token
36
33
  validate_credentials!
37
34
 
38
35
  @api_version = api_version
@@ -51,6 +48,10 @@ module Intercom
51
48
  Intercom::Service::Admin.new(self)
52
49
  end
53
50
 
51
+ def articles
52
+ Intercom::Service::Article.new(self)
53
+ end
54
+
54
55
  def companies
55
56
  Intercom::Service::Company.new(self)
56
57
  end
@@ -67,10 +68,6 @@ module Intercom
67
68
  Intercom::Service::Counts.new(self)
68
69
  end
69
70
 
70
- def customers
71
- Intercom::Service::Customer.new(self)
72
- end
73
-
74
71
  def events
75
72
  Intercom::Service::Event.new(self)
76
73
  end
@@ -87,10 +84,18 @@ module Intercom
87
84
  Intercom::Service::Subscription.new(self)
88
85
  end
89
86
 
87
+ def subscription_types
88
+ Intercom::Service::SubscriptionType.new(self)
89
+ end
90
+
90
91
  def segments
91
92
  Intercom::Service::Segment.new(self)
92
93
  end
93
94
 
95
+ def sections
96
+ Intercom::Service::Section.new(self)
97
+ end
98
+
94
99
  def tags
95
100
  Intercom::Service::Tag.new(self)
96
101
  end
@@ -103,6 +108,10 @@ module Intercom
103
108
  Intercom::Service::User.new(self)
104
109
  end
105
110
 
111
+ def leads
112
+ Intercom::Service::Lead.new(self)
113
+ end
114
+
106
115
  def visitors
107
116
  Intercom::Service::Visitor.new(self)
108
117
  end
@@ -111,6 +120,22 @@ module Intercom
111
120
  Intercom::Service::Job.new(self)
112
121
  end
113
122
 
123
+ def data_attributes
124
+ Intercom::Service::DataAttribute.new(self)
125
+ end
126
+
127
+ def collections
128
+ Intercom::Service::Collection.new(self)
129
+ end
130
+
131
+ def export_content
132
+ Intercom::Service::ExportContent.new(self)
133
+ end
134
+
135
+ def phone_call_redirect
136
+ Intercom::Service::PhoneCallRedirect.new(self)
137
+ end
138
+
114
139
  def get(path, params)
115
140
  execute_request Intercom::Request.get(path, params)
116
141
  end
@@ -130,25 +155,23 @@ module Intercom
130
155
  private
131
156
 
132
157
  def validate_credentials!
133
- error = MisconfiguredClientError.new("app_id and api_key must not be nil")
134
- fail error if @username_part.nil?
158
+ error = MisconfiguredClientError.new('an access token must be provided')
159
+ raise error if @token.nil?
135
160
  end
136
161
 
137
162
  def validate_api_version!
138
- error = MisconfiguredClientError.new("api_version must be either nil or a valid API version")
139
- fail error if (@api_version && @api_version != 'Unstable' && Gem::Version.new(@api_version) < Gem::Version.new('1.0'))
163
+ error = MisconfiguredClientError.new('api_version must be either nil or a valid API version')
164
+ raise error if @api_version && @api_version != 'Unstable' && Gem::Version.new(@api_version) < Gem::Version.new('1.0')
140
165
  end
141
166
 
142
167
  def execute_request(request)
143
168
  request.handle_rate_limit = handle_rate_limit
144
- request.execute(@base_url, username: @username_part, secret: @password_part, api_version: @api_version, **timeouts)
169
+ request.execute(@base_url, token: @token, api_version: @api_version, **timeouts)
145
170
  ensure
146
171
  @rate_limit_details = request.rate_limit_details
147
172
  end
148
173
 
149
- def base_url=(new_url)
150
- @base_url = new_url
151
- end
174
+ attr_writer :base_url
152
175
 
153
176
  def timeouts=(timeouts)
154
177
  @timeouts = @timeouts.merge(timeouts)
@@ -1,71 +1,49 @@
1
- require "intercom/utils"
1
+ # frozen_string_literal: true
2
2
 
3
- module Intercom
4
- class ClientCollectionProxy
5
-
6
- attr_reader :resource_name, :finder_url, :resource_class
7
-
8
- def initialize(resource_name, finder_details: {}, client:)
9
- @resource_name = resource_name
10
- @resource_class = Utils.constantize_resource_name(resource_name)
11
- @finder_url = (finder_details[:url] || "/#{@resource_name}")
12
- @finder_params = (finder_details[:params] || {})
13
- @client = client
14
- end
3
+ require 'intercom/utils'
4
+ require 'intercom/base_collection_proxy'
15
5
 
6
+ module Intercom
7
+ class ClientCollectionProxy < BaseCollectionProxy
16
8
  def each(&block)
17
9
  next_page = nil
18
10
  current_page = nil
19
11
  loop do
20
- if next_page
21
- response_hash = @client.get(next_page, {})
22
- else
23
- response_hash = @client.get(@finder_url, @finder_params)
24
- end
25
- raise Intercom::HttpError.new('Http Error - No response entity returned') unless response_hash
12
+ response_hash = fetch(next_page)
13
+ raise Intercom::HttpError, 'Http Error - No response entity returned' unless response_hash
14
+
26
15
  current_page = extract_current_page(response_hash)
27
16
  deserialize_response_hash(response_hash, block)
28
17
  next_page = extract_next_link(response_hash)
29
- break if next_page.nil? or (@finder_params[:page] and (current_page >= @finder_params[:page]))
18
+ break if next_page.nil? || (@params[:page] && (current_page >= @params[:page]))
30
19
  end
31
20
  self
32
21
  end
33
22
 
34
- def [](target_index)
35
- self.each_with_index do |item, index|
36
- return item if index == target_index
23
+ def fetch(next_page)
24
+ if next_page
25
+ @client.get(next_page, {})
26
+ else
27
+ @client.get(@url, @params)
37
28
  end
38
- nil
39
29
  end
40
30
 
41
- include Enumerable
42
-
43
31
  private
44
32
 
45
- def deserialize_response_hash(response_hash, block)
46
- top_level_type = response_hash.delete('type')
47
- if resource_name == 'subscriptions'
48
- top_level_entity_key = 'items'
49
- else
50
- top_level_entity_key = Utils.entity_key_from_type(top_level_type)
51
- end
52
- response_hash[top_level_entity_key].each do |object_json|
53
- block.call Lib::TypedJsonDeserializer.new(object_json).deserialize
54
- end
55
- end
56
-
57
33
  def paging_info_present?(response_hash)
58
34
  !!(response_hash['pages'] && response_hash['pages']['type'])
59
35
  end
60
36
 
61
37
  def extract_next_link(response_hash)
62
38
  return nil unless paging_info_present?(response_hash)
39
+
63
40
  paging_info = response_hash.delete('pages')
64
- paging_info["next"]
41
+ paging_info['next']
65
42
  end
66
43
 
67
44
  def extract_current_page(response_hash)
68
45
  return nil unless paging_info_present?(response_hash)
46
+
69
47
  response_hash['pages']['page']
70
48
  end
71
49
  end
@@ -0,0 +1,7 @@
1
+ require 'intercom/traits/api_resource'
2
+
3
+ module Intercom
4
+ class Collection
5
+ include Traits::ApiResource
6
+ end
7
+ end
@@ -1,10 +1,18 @@
1
1
  require 'intercom/traits/incrementable_attributes'
2
2
  require 'intercom/traits/api_resource'
3
+ require 'intercom/api_operations/nested_resource'
3
4
 
4
5
  module Intercom
5
6
  class Company
6
7
  include Traits::IncrementableAttributes
7
8
  include Traits::ApiResource
9
+ include ApiOperations::NestedResource
10
+
11
+ nested_resource_methods :contact, operations: %i[list]
12
+
13
+ def self.collection_proxy_class
14
+ Intercom::ClientCollectionProxy
15
+ end
8
16
 
9
17
  def identity_vars ; [:id, :company_id] ; end
10
18
  def flat_store_attributes ; [:custom_attributes] ; end