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
@@ -1,32 +1,34 @@
1
- require "intercom/utils"
1
+ # frozen_string_literal: true
2
2
 
3
- module Intercom
4
- class ScrollCollectionProxy
3
+ require 'intercom/utils'
4
+ require 'intercom/base_collection_proxy'
5
5
 
6
- attr_reader :resource_name, :scroll_url, :resource_class, :scroll_param, :records
6
+ module Intercom
7
+ class ScrollCollectionProxy < BaseCollectionProxy
8
+ attr_reader :scroll_url, :scroll_param, :records
7
9
 
8
- def initialize(resource_name, finder_details: {}, client:)
10
+ def initialize(resource_name, resource_class, details: {}, client:)
9
11
  @resource_name = resource_name
10
- @resource_class = Utils.constantize_resource_name(resource_name)
11
- @scroll_url = (finder_details[:url] || "/#{@resource_name}") + '/scroll'
12
+ @resource_class = resource_class
13
+ @scroll_url = (details[:url] || "/#{@resource_name}") + '/scroll'
12
14
  @client = client
13
-
14
15
  end
15
16
 
16
- def next(scroll_parameter=nil)
17
+ def next(scroll_parameter = nil)
17
18
  @records = []
18
- if not scroll_parameter
19
- #First time so do initial get without scroll_param
20
- response_hash = @client.get(@scroll_url, '')
21
- else
22
- #Not first call so use get next page
23
- response_hash = @client.get(@scroll_url, scroll_param: scroll_parameter)
24
- end
25
- raise Intercom::HttpError.new('Http Error - No response entity returned') unless response_hash
19
+ response_hash = if !scroll_parameter
20
+ # First time so do initial get without scroll_param
21
+ @client.get(@scroll_url, '')
22
+ else
23
+ # Not first call so use get next page
24
+ @client.get(@scroll_url, scroll_param: scroll_parameter)
25
+ end
26
+ raise Intercom::HttpError, 'Http Error - No response entity returned' unless response_hash
27
+
26
28
  @scroll_param = extract_scroll_param(response_hash)
27
- top_level_entity_key = deserialize_response_hash(response_hash)
29
+ top_level_entity_key = entity_key_from_response(response_hash)
28
30
  response_hash[top_level_entity_key] = response_hash[top_level_entity_key].map do |object_json|
29
- Lib::TypedJsonDeserializer.new(object_json).deserialize
31
+ Lib::TypedJsonDeserializer.new(object_json, @client).deserialize
30
32
  end
31
33
  @records = response_hash[@resource_name]
32
34
  self
@@ -35,47 +37,41 @@ module Intercom
35
37
  def each(&block)
36
38
  scroll_param = nil
37
39
  loop do
38
- if not scroll_param
39
- response_hash = @client.get(@scroll_url, '')
40
- else
41
- response_hash = @client.get(@scroll_url, scroll_param: scroll_param)
42
- end
43
- raise Intercom::HttpError.new('Http Error - No response entity returned') unless response_hash
44
- response_hash[deserialize_response_hash(response_hash)].each do |object_json|
45
- block.call Lib::TypedJsonDeserializer.new(object_json).deserialize
40
+ response_hash = if !scroll_param
41
+ @client.get(@scroll_url, '')
42
+ else
43
+ @client.get(@scroll_url, scroll_param: scroll_param)
44
+ end
45
+ raise Intercom::HttpError, 'Http Error - No response entity returned' unless response_hash
46
+
47
+ top_level_entity_key = entity_key_from_response(response_hash)
48
+ response_hash[top_level_entity_key].each do |object_json|
49
+ block.call Lib::TypedJsonDeserializer.new(object_json, @client).deserialize
46
50
  end
47
51
  scroll_param = extract_scroll_param(response_hash)
48
- break if not records_present?(response_hash)
52
+ break unless records_present?(response_hash)
49
53
  end
50
54
  self
51
55
  end
52
56
 
53
- def [](target_index)
54
- self.each_with_index do |item, index|
55
- return item if index == target_index
56
- end
57
- nil
58
- end
59
-
60
- include Enumerable
61
-
62
57
  private
63
58
 
64
- def deserialize_response_hash(response_hash)
65
- top_level_type = response_hash.delete('type')
59
+ def entity_key_from_response(response_hash)
60
+ top_level_type = response_hash['type']
66
61
  if resource_name == 'subscriptions'
67
- top_level_entity_key = 'items'
62
+ 'items'
68
63
  else
69
- top_level_entity_key = Utils.entity_key_from_type(top_level_type)
64
+ Utils.entity_key_from_type(top_level_type)
70
65
  end
71
66
  end
72
67
 
73
68
  def records_present?(response_hash)
74
- (response_hash[@resource_name].length > 0)
69
+ !response_hash[entity_key_from_response(response_hash)].empty?
75
70
  end
76
71
 
77
72
  def extract_scroll_param(response_hash)
78
73
  return nil unless records_present?(response_hash)
74
+
79
75
  response_hash['scroll_param']
80
76
  end
81
77
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'intercom/utils'
4
+ require 'intercom/base_collection_proxy'
5
+
6
+ module Intercom
7
+ class SearchCollectionProxy < BaseCollectionProxy
8
+ def initialize(resource_name, resource_class, details: {}, client:)
9
+ super(resource_name, resource_class, details: details, client: client, method: 'post')
10
+ end
11
+
12
+ private
13
+
14
+ def payload
15
+ payload = {
16
+ query: @params[:query]
17
+ }
18
+ if sort_field || sort_order
19
+ payload[:sort] = {}
20
+ payload[:sort][:field] = sort_field if sort_field
21
+ payload[:sort][:order] = sort_order if sort_order
22
+ end
23
+ if per_page || starting_after
24
+ payload[:pagination] = {}
25
+ payload[:pagination][:per_page] = per_page if per_page
26
+ payload[:pagination][:starting_after] = starting_after if starting_after
27
+ end
28
+ payload
29
+ end
30
+
31
+ def sort_field
32
+ @params[:sort_field]
33
+ end
34
+
35
+ def sort_order
36
+ @params[:sort_order]
37
+ end
38
+
39
+ def per_page
40
+ @params[:per_page]
41
+ end
42
+
43
+ def starting_after
44
+ @params[:starting_after]
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,23 @@
1
+ require 'intercom/api_operations/list'
2
+ require 'intercom/api_operations/find'
3
+ require 'intercom/api_operations/save'
4
+ require 'intercom/api_operations/delete'
5
+
6
+ module Intercom
7
+ module Service
8
+ class Section < BaseService
9
+ include ApiOperations::List
10
+ include ApiOperations::Find
11
+ include ApiOperations::Save
12
+ include ApiOperations::Delete
13
+
14
+ def collection_class
15
+ Intercom::Section
16
+ end
17
+
18
+ def collection_name
19
+ 'help_center/sections'
20
+ end
21
+ end
22
+ end
23
+ end
@@ -3,5 +3,9 @@ require 'intercom/traits/api_resource'
3
3
  module Intercom
4
4
  class Segment
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,20 @@
1
+ require 'intercom/service/base_service'
2
+ require 'intercom/api_operations/find'
3
+ require 'intercom/api_operations/list'
4
+ require 'intercom/api_operations/delete'
5
+ require 'intercom/api_operations/save'
6
+
7
+ module Intercom
8
+ module Service
9
+ class Article < BaseService
10
+ include ApiOperations::Find
11
+ include ApiOperations::List
12
+ include ApiOperations::Delete
13
+ include ApiOperations::Save
14
+
15
+ def collection_class
16
+ Intercom::Article
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'intercom/client_collection_proxy'
4
+
1
5
  module Intercom
2
6
  module Service
3
7
  class BaseService
@@ -11,8 +15,17 @@ module Intercom
11
15
  raise NotImplementedError
12
16
  end
13
17
 
18
+ def collection_proxy_class
19
+ Intercom::ClientCollectionProxy
20
+ end
21
+
22
+ def collection_name
23
+ @collection_name ||= Utils.resource_class_to_collection_name(collection_class)
24
+ end
25
+
14
26
  def from_api(api_response)
15
27
  object = collection_class.new
28
+ object.client = @client
16
29
  object.from_response(api_response)
17
30
  object
18
31
  end
@@ -0,0 +1,24 @@
1
+ require 'intercom/service/base_service'
2
+ require 'intercom/api_operations/list'
3
+ require 'intercom/api_operations/find'
4
+ require 'intercom/api_operations/delete'
5
+ require 'intercom/api_operations/save'
6
+
7
+ module Intercom
8
+ module Service
9
+ class Collection < BaseService
10
+ include ApiOperations::List
11
+ include ApiOperations::Find
12
+ include ApiOperations::Delete
13
+ include ApiOperations::Save
14
+
15
+ def collection_class
16
+ Intercom::Collection
17
+ end
18
+
19
+ def collection_name
20
+ "help_center/collections"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,22 +1,24 @@
1
1
  require 'intercom/service/base_service'
2
+ require 'intercom/api_operations/delete'
2
3
  require 'intercom/api_operations/list'
4
+ require 'intercom/api_operations/scroll'
3
5
  require 'intercom/api_operations/find'
4
6
  require 'intercom/api_operations/find_all'
5
7
  require 'intercom/api_operations/save'
6
8
  require 'intercom/api_operations/load'
7
- require 'intercom/extended_api_operations/users'
8
9
  require 'intercom/extended_api_operations/tags'
9
10
  require 'intercom/extended_api_operations/segments'
10
11
 
11
12
  module Intercom
12
13
  module Service
13
14
  class Company < BaseService
15
+ include ApiOperations::Delete
14
16
  include ApiOperations::Find
15
17
  include ApiOperations::FindAll
16
18
  include ApiOperations::Load
17
19
  include ApiOperations::List
20
+ include ApiOperations::Scroll
18
21
  include ApiOperations::Save
19
- include ExtendedApiOperations::Users
20
22
  include ExtendedApiOperations::Tags
21
23
  include ExtendedApiOperations::Segments
22
24
 
@@ -2,11 +2,9 @@ require 'intercom/service/base_service'
2
2
  require 'intercom/api_operations/load'
3
3
  require 'intercom/api_operations/list'
4
4
  require 'intercom/api_operations/find'
5
- require 'intercom/api_operations/find_all'
6
5
  require 'intercom/api_operations/save'
7
- require 'intercom/api_operations/scroll'
8
- require 'intercom/api_operations/convert'
9
6
  require 'intercom/api_operations/delete'
7
+ require 'intercom/api_operations/search'
10
8
 
11
9
  module Intercom
12
10
  module Service
@@ -14,15 +12,40 @@ module Intercom
14
12
  include ApiOperations::Load
15
13
  include ApiOperations::List
16
14
  include ApiOperations::Find
17
- include ApiOperations::FindAll
18
15
  include ApiOperations::Save
19
- include ApiOperations::Scroll
20
- include ApiOperations::Convert
21
16
  include ApiOperations::Delete
17
+ include ApiOperations::Search
22
18
 
23
19
  def collection_class
24
20
  Intercom::Contact
25
21
  end
22
+
23
+ def collection_proxy_class
24
+ Intercom::BaseCollectionProxy
25
+ end
26
+
27
+ def merge(lead, user)
28
+ raise_invalid_merge_error unless lead.role == 'lead' && user.role == 'user'
29
+
30
+ response = @client.post('/contacts/merge', from: lead.id, into: user.id)
31
+ raise Intercom::HttpError, 'Http Error - No response entity returned' unless response
32
+
33
+ user.from_response(response)
34
+ end
35
+
36
+ def archive(contact)
37
+ @client.post("/#{collection_name}/#{contact.id}/archive", {})
38
+ contact
39
+ end
40
+
41
+ def unarchive(contact)
42
+ @client.post("/#{collection_name}/#{contact.id}/unarchive", {})
43
+ contact
44
+ end
45
+
46
+ private def raise_invalid_merge_error
47
+ raise Intercom::InvalidMergeError, 'Merging can only be performed on a lead into a user'
48
+ end
26
49
  end
27
50
  end
28
51
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'intercom/service/base_service'
2
4
  require 'intercom/api_operations/find_all'
3
5
  require 'intercom/api_operations/find'
@@ -9,9 +11,11 @@ module Intercom
9
11
  module Service
10
12
  class Conversation < BaseService
11
13
  include ApiOperations::FindAll
14
+ include ApiOperations::List
12
15
  include ApiOperations::Find
13
16
  include ApiOperations::Load
14
17
  include ApiOperations::Save
18
+ include ApiOperations::Search
15
19
 
16
20
  def collection_class
17
21
  Intercom::Conversation
@@ -24,7 +28,13 @@ module Intercom
24
28
  def reply(reply_data)
25
29
  id = reply_data.delete(:id)
26
30
  collection_name = Utils.resource_class_to_collection_name(collection_class)
27
- response = @client.post("/#{collection_name}/#{id}/reply", reply_data.merge(:conversation_id => id))
31
+ response = @client.post("/#{collection_name}/#{id}/reply", reply_data.merge(conversation_id: id))
32
+ collection_class.new.from_response(response)
33
+ end
34
+
35
+ def reply_to_last(reply_data)
36
+ collection_name = Utils.resource_class_to_collection_name(collection_class)
37
+ response = @client.post("/#{collection_name}/last/reply", reply_data)
28
38
  collection_class.new.from_response(response)
29
39
  end
30
40
 
@@ -36,10 +46,21 @@ module Intercom
36
46
  reply reply_data.merge(message_type: 'close', type: 'admin')
37
47
  end
38
48
 
49
+ def snooze(reply_data)
50
+ reply_data.fetch(:snoozed_until) { raise 'snoozed_until field is required' }
51
+ reply reply_data.merge(message_type: 'snoozed', type: 'admin')
52
+ end
53
+
39
54
  def assign(reply_data)
40
- assignee_id = reply_data.fetch(:assignee_id) { fail 'assignee_id is required' }
55
+ assignee_id = reply_data.fetch(:assignee_id) { raise 'assignee_id is required' }
41
56
  reply reply_data.merge(message_type: 'assignment', assignee_id: assignee_id, type: 'admin')
42
57
  end
58
+
59
+ def run_assignment_rules(id)
60
+ collection_name = Utils.resource_class_to_collection_name(collection_class)
61
+ response = @client.post("/#{collection_name}/#{id}/run_assignment_rules", {})
62
+ collection_class.new.from_response(response)
63
+ end
43
64
  end
44
65
  end
45
66
  end
@@ -0,0 +1,20 @@
1
+ require 'intercom/service/base_service'
2
+ require 'intercom/api_operations/load'
3
+ require 'intercom/api_operations/list'
4
+ require 'intercom/api_operations/find_all'
5
+ require 'intercom/api_operations/save'
6
+
7
+ module Intercom
8
+ module Service
9
+ class DataAttribute < BaseService
10
+ include ApiOperations::Load
11
+ include ApiOperations::List
12
+ include ApiOperations::FindAll
13
+ include ApiOperations::Save
14
+
15
+ def collection_class
16
+ Intercom::DataAttribute
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,8 +1,16 @@
1
+ require 'intercom/client_collection_proxy'
1
2
  require 'intercom/service/base_service'
2
3
  require 'intercom/api_operations/save'
3
4
  require 'intercom/api_operations/bulk/submit'
4
5
 
5
6
  module Intercom
7
+ class EventCollectionProxy < ClientCollectionProxy
8
+
9
+ def paging_info_present?(response_hash)
10
+ !!(response_hash['pages'])
11
+ end
12
+ end
13
+
6
14
  module Service
7
15
  class Event < BaseService
8
16
  include ApiOperations::FindAll
@@ -12,6 +20,10 @@ module Intercom
12
20
  def collection_class
13
21
  Intercom::Event
14
22
  end
23
+
24
+ def collection_proxy_class
25
+ Intercom::EventCollectionProxy
26
+ end
15
27
  end
16
28
  end
17
29
  end