intercom 1.0.0 → 2.0.0

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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -8
  3. data/Gemfile +3 -0
  4. data/README.md +208 -52
  5. data/changes.txt +3 -0
  6. data/intercom.gemspec +2 -2
  7. data/lib/ext/hash.rb +18 -0
  8. data/lib/intercom.rb +38 -43
  9. data/lib/intercom/api_operations/count.rb +16 -0
  10. data/lib/intercom/api_operations/delete.rb +15 -0
  11. data/lib/intercom/api_operations/find.rb +22 -0
  12. data/lib/intercom/api_operations/find_all.rb +33 -0
  13. data/lib/intercom/api_operations/list.rb +17 -0
  14. data/lib/intercom/api_operations/load.rb +15 -0
  15. data/lib/intercom/api_operations/save.rb +44 -0
  16. data/lib/intercom/collection_proxy.rb +66 -0
  17. data/lib/intercom/company.rb +29 -0
  18. data/lib/intercom/conversation.rb +15 -0
  19. data/lib/intercom/count.rb +21 -0
  20. data/lib/intercom/errors.rb +52 -0
  21. data/lib/intercom/event.rb +4 -101
  22. data/lib/intercom/extended_api_operations/reply.rb +16 -0
  23. data/lib/intercom/extended_api_operations/tags.rb +14 -0
  24. data/lib/intercom/extended_api_operations/users.rb +17 -0
  25. data/lib/intercom/generic_handlers/base_handler.rb +22 -0
  26. data/lib/intercom/generic_handlers/count.rb +59 -0
  27. data/lib/intercom/generic_handlers/tag.rb +71 -0
  28. data/lib/intercom/generic_handlers/tag_find_all.rb +47 -0
  29. data/lib/intercom/lib/dynamic_accessors.rb +59 -0
  30. data/lib/intercom/lib/dynamic_accessors_on_method_missing.rb +53 -0
  31. data/lib/intercom/lib/flat_store.rb +31 -0
  32. data/lib/intercom/lib/typed_json_deserializer.rb +52 -0
  33. data/lib/intercom/message.rb +9 -0
  34. data/lib/intercom/note.rb +14 -42
  35. data/lib/intercom/request.rb +40 -4
  36. data/lib/intercom/segment.rb +14 -0
  37. data/lib/intercom/tag.rb +19 -78
  38. data/lib/intercom/traits/api_resource.rb +120 -0
  39. data/lib/intercom/traits/dirty_tracking.rb +33 -0
  40. data/lib/intercom/traits/generic_handler_binding.rb +29 -0
  41. data/lib/intercom/traits/incrementable_attributes.rb +23 -0
  42. data/lib/intercom/user.rb +25 -361
  43. data/lib/intercom/utils.rb +50 -0
  44. data/lib/intercom/version.rb +1 -1
  45. data/spec/spec_helper.rb +64 -33
  46. data/spec/unit/intercom/collection_proxy_spec.rb +34 -0
  47. data/spec/unit/intercom/event_spec.rb +25 -0
  48. data/spec/unit/intercom/{flat_store_spec.rb → lib/flat_store_spec.rb} +7 -7
  49. data/spec/unit/intercom/note_spec.rb +5 -4
  50. data/spec/unit/intercom/tag_spec.rb +3 -3
  51. data/spec/unit/intercom/traits/api_resource_spec.rb +79 -0
  52. data/spec/unit/intercom/user_spec.rb +101 -119
  53. data/spec/unit/intercom_spec.rb +7 -7
  54. metadata +50 -26
  55. data/lib/intercom/flat_store.rb +0 -27
  56. data/lib/intercom/hashable_object.rb +0 -22
  57. data/lib/intercom/impression.rb +0 -63
  58. data/lib/intercom/message_thread.rb +0 -189
  59. data/lib/intercom/requires_parameters.rb +0 -10
  60. data/lib/intercom/social_profile.rb +0 -24
  61. data/lib/intercom/unix_timestamp_unwrapper.rb +0 -12
  62. data/lib/intercom/user_collection_proxy.rb +0 -52
  63. data/lib/intercom/user_resource.rb +0 -82
  64. data/spec/integration/fixtures/v1-user.json +0 -45
  65. data/spec/integration/fixtures/v1-users-impression.json +0 -3
  66. data/spec/integration/fixtures/v1-users-message_thread.json +0 -44
  67. data/spec/integration/fixtures/v1-users-message_threads.json +0 -46
  68. data/spec/integration/fixtures/v1-users-note.json +0 -49
  69. data/spec/integration/fixtures/v1-users.json +0 -144
  70. data/spec/integration/intercom_api_integration_spec.rb +0 -134
  71. data/spec/unit/intercom/impression_spec.rb +0 -18
  72. data/spec/unit/intercom/message_thread_spec.rb +0 -74
  73. data/spec/unit/intercom/user_collection_proxy_spec.rb +0 -46
  74. data/spec/unit/intercom/user_event_spec.rb +0 -83
  75. data/spec/unit/intercom/user_resource_spec.rb +0 -13
@@ -0,0 +1,16 @@
1
+ module Intercom
2
+ module ApiOperations
3
+ module Count
4
+ module ClassMethods
5
+ def count
6
+ singular_resource_name = Utils.resource_class_to_singular_name(self)
7
+ Intercom::Count.send("#{singular_resource_name}_count")
8
+ end
9
+ end
10
+
11
+ def self.included(base)
12
+ base.extend(ClassMethods)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ require 'intercom/traits/api_resource'
2
+
3
+ module Intercom
4
+ module ApiOperations
5
+ module Delete
6
+
7
+ def delete
8
+ collection_name = Utils.resource_class_to_collection_name(self.class)
9
+ Intercom.delete("/#{collection_name}/#{id}", {})
10
+ self
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ module Intercom
2
+ module ApiOperations
3
+ module Find
4
+ module ClassMethods
5
+ def find(params)
6
+ raise BadRequestError, "#{self}#find takes a hash as it's parameter but you supplied #{params.inspect}" unless params.is_a? Hash
7
+ collection_name = Utils.resource_class_to_collection_name(self)
8
+ if params[:id]
9
+ response = Intercom.get("/#{collection_name}/#{params[:id]}", {})
10
+ else
11
+ response = Intercom.get("/#{collection_name}", params)
12
+ end
13
+ from_api(response)
14
+ end
15
+ end
16
+
17
+ def self.included(base)
18
+ base.extend(ClassMethods)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,33 @@
1
+ require 'intercom/collection_proxy'
2
+
3
+ module Intercom
4
+ module ApiOperations
5
+ module FindAll
6
+ module ClassMethods
7
+ def find_all(params)
8
+ raise BadRequestError, "#{self}#find takes a hash as it's parameter but you supplied #{params.inspect}" unless params.is_a? Hash
9
+ collection_name = Utils.resource_class_to_collection_name(self)
10
+ finder_details = {}
11
+ if params[:id] && !type_switched_finder?(params)
12
+ finder_details[:url] = "/#{collection_name}/#{params[:id]}"
13
+ finder_details[:params] = {}
14
+ else
15
+ finder_details[:url] = "/#{collection_name}"
16
+ finder_details[:params] = params
17
+ end
18
+ CollectionProxy.new(collection_name, finder_details)
19
+ end
20
+
21
+ private
22
+
23
+ def type_switched_finder?(params)
24
+ params.include?(:type)
25
+ end
26
+ end
27
+
28
+ def self.included(base)
29
+ base.extend(ClassMethods)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ require 'intercom/collection_proxy'
2
+
3
+ module Intercom
4
+ module ApiOperations
5
+ module List # TODO: Should we rename to All
6
+ module ClassMethods
7
+ def all
8
+ CollectionProxy.new(Utils.resource_class_to_collection_name(self))
9
+ end
10
+ end
11
+
12
+ def self.included(base)
13
+ base.extend(ClassMethods)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ module Intercom
2
+ module ApiOperations
3
+ module Load
4
+ def load
5
+ collection_name = Utils.resource_class_to_collection_name(self.class)
6
+ if id
7
+ response = Intercom.get("/#{collection_name}/#{id}", {})
8
+ else
9
+ raise "Cannot load #{self.class} as it does not have a valid id."
10
+ end
11
+ from_response(response)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,44 @@
1
+ require 'intercom/traits/api_resource'
2
+
3
+ module Intercom
4
+ module ApiOperations
5
+ module Save
6
+
7
+ module ClassMethods
8
+ def create(params)
9
+ instance = self.new(params)
10
+ instance.mark_fields_as_changed!(params.keys)
11
+ instance.save
12
+ end
13
+ end
14
+
15
+ def self.included(base)
16
+ base.extend(ClassMethods)
17
+ end
18
+
19
+ def save
20
+ collection_name = Utils.resource_class_to_collection_name(self.class)
21
+ if id_present? && !posted_updates?
22
+ response = Intercom.put("/#{collection_name}/#{id}", to_submittable_hash)
23
+ else
24
+ response = Intercom.post("/#{collection_name}", to_submittable_hash.merge(identity_hash))
25
+ end
26
+ from_response(response) if response # may be nil we received back a 202
27
+ end
28
+
29
+ private
30
+
31
+ def id_present?
32
+ id && id.to_s != ''
33
+ end
34
+
35
+ def posted_updates?
36
+ respond_to?(:update_verb) && update_verb == 'post'
37
+ end
38
+
39
+ def identity_hash
40
+ respond_to?(:identity_vars) ? to_hash.slice(*(identity_vars.map(&:to_s))) : {}
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,66 @@
1
+ require "intercom/utils"
2
+ require "ext/hash"
3
+
4
+ module Intercom
5
+ class CollectionProxy
6
+
7
+ attr_reader :resource_name
8
+
9
+ def initialize(resource_name, finder_details = {})
10
+ @resource_name = resource_name
11
+ @resource_class = Utils.constantize_resource_name(resource_name)
12
+ @finder_url = (finder_details[:url] || "/#{@resource_name}")
13
+ @finder_params = (finder_details[:params] || {})
14
+ end
15
+
16
+ def each(&block)
17
+ next_page = nil
18
+ loop do
19
+ if next_page
20
+ response_hash = Intercom.get(next_page, {})
21
+ else
22
+ response_hash = Intercom.get(@finder_url, @finder_params)
23
+ end
24
+ deserialize_response_hash(response_hash, block)
25
+ next_page = extract_next_link(response_hash)
26
+ break if next_page.nil?
27
+ end
28
+ self
29
+ end
30
+
31
+ def [](target_index)
32
+ self.each_with_index do |item, index|
33
+ return item if index == target_index
34
+ end
35
+ nil
36
+ end
37
+
38
+ include Enumerable
39
+
40
+ def count
41
+ raise NoMethodError, "undefined method `count' for #{self.class}. Consider using the dedicated Intercom::Count interface if suitable"
42
+ end
43
+
44
+ private
45
+
46
+ def resource_class; @resource_class; end
47
+
48
+ def deserialize_response_hash(response_hash, block)
49
+ top_level_type = response_hash.delete('type')
50
+ top_level_entity_key = Utils.entity_key_from_type(top_level_type)
51
+ response_hash[top_level_entity_key].each do |object_json|
52
+ block.call Lib::TypedJsonDeserializer.new(object_json).deserialize
53
+ end
54
+ end
55
+
56
+ def paging_info_present?(response_hash)
57
+ !!(response_hash['pages'] && response_hash['pages']['type'])
58
+ end
59
+
60
+ def extract_next_link(response_hash)
61
+ return nil unless paging_info_present?(response_hash)
62
+ paging_info = response_hash.delete('pages')
63
+ paging_info["next"]
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,29 @@
1
+ require 'intercom/api_operations/count'
2
+ require 'intercom/api_operations/list'
3
+ require 'intercom/api_operations/find'
4
+ require 'intercom/api_operations/find_all'
5
+ require 'intercom/api_operations/save'
6
+ require 'intercom/api_operations/load'
7
+ require 'intercom/extended_api_operations/users'
8
+ require 'intercom/extended_api_operations/tags'
9
+ require 'intercom/traits/incrementable_attributes'
10
+ require 'intercom/traits/api_resource'
11
+
12
+ module Intercom
13
+ class Company
14
+ include ApiOperations::Count
15
+ include ApiOperations::List
16
+ include ApiOperations::Find
17
+ include ApiOperations::FindAll
18
+ include ApiOperations::Save
19
+ include ApiOperations::Load
20
+ include ExtendedApiOperations::Users
21
+ include ExtendedApiOperations::Tags
22
+ include Traits::IncrementableAttributes
23
+ include Traits::ApiResource
24
+
25
+ def identity_vars ; [:id, :company_id] ; end
26
+ def flat_store_attributes ; [:custom_attributes] ; end
27
+ def update_verb ; 'post' ; end
28
+ end
29
+ end
@@ -0,0 +1,15 @@
1
+ require 'intercom/extended_api_operations/reply'
2
+ require 'intercom/api_operations/find_all'
3
+ require 'intercom/api_operations/find'
4
+ require 'intercom/api_operations/load'
5
+ require 'intercom/traits/api_resource'
6
+
7
+ module Intercom
8
+ class Conversation
9
+ include ExtendedApiOperations::Reply
10
+ include ApiOperations::FindAll
11
+ include ApiOperations::Find
12
+ include ApiOperations::Load
13
+ include Traits::ApiResource
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ require 'intercom/traits/api_resource'
2
+ require 'intercom/api_operations/find'
3
+ require 'intercom/traits/generic_handler_binding'
4
+ require 'intercom/generic_handlers/count'
5
+
6
+ module Intercom
7
+ class Count
8
+ include ApiOperations::Find
9
+ include Traits::ApiResource
10
+ include Traits::GenericHandlerBinding
11
+ include GenericHandlers::Count
12
+
13
+ def self.fetch_for_app
14
+ Intercom::Count.find({})
15
+ end
16
+
17
+ def self.fetch_broken_down_count(entity_to_count, count_context)
18
+ Intercom::Count.find(:type => entity_to_count, :count => count_context)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,52 @@
1
+ module Intercom
2
+
3
+ # Base class exception from which all public Intercom exceptions will be derived
4
+ class IntercomError < StandardError
5
+ attr_reader :http_code, :application_error_code
6
+ def initialize(message, http_code: nil, application_error_code: application_error_code)
7
+ @http_code = http_code
8
+ @application_error_code = application_error_code
9
+ super(message)
10
+ end
11
+ end
12
+
13
+ # Raised when the credentials you provide don't match a valid account on Intercom.
14
+ # Check that you have set <b>Intercom.app_id=</b> and <b>Intercom.app_api_key=</b> correctly.
15
+ class AuthenticationError < IntercomError; end
16
+
17
+ # Raised when something does wrong on within the Intercom API service.
18
+ class ServerError < IntercomError; end
19
+
20
+ # Raised when we have bad gateway errors.
21
+ class BadGatewayError < IntercomError; end
22
+
23
+ # Raised when we reach socket connect timeout
24
+ class ServiceUnavailableError < IntercomError; end
25
+
26
+ # Raised when requesting resources on behalf of a user that doesn't exist in your application on Intercom.
27
+ class ResourceNotFound < IntercomError; end
28
+
29
+ # Raised when the request has a bad syntax
30
+ class BadRequestError < IntercomError; end
31
+
32
+ # Raised when you have exceed the API rate limit
33
+ class RateLimitExceeded < IntercomError; end
34
+
35
+ # Raised when the request throws an error not accounted for
36
+ class UnexpectedError < IntercomError; end
37
+
38
+ # Raised when you try to call a non-setter method that does not exist on an object
39
+ class Intercom::AttributeNotSetError < IntercomError ; end
40
+
41
+ #
42
+ # Non-public errors (internal to the gem)
43
+ #
44
+
45
+ # Base class exception from which all public Intercom exceptions will be derived
46
+ class IntercomInternalError < StandardError; end
47
+
48
+ # Raised when we attempt to handle a method missing but are unsuccessful
49
+ class Intercom::NoMethodMissingHandler < IntercomInternalError; end
50
+
51
+ class Intercom::DeserializationError < IntercomInternalError; end
52
+ end
@@ -1,106 +1,9 @@
1
- require 'intercom/requires_parameters'
2
- require 'intercom/hashable_object'
3
-
1
+ require 'intercom/api_operations/save'
2
+ require 'intercom/traits/api_resource'
4
3
 
5
4
  module Intercom
6
-
7
- ##
8
- # Represents an Event
9
- #
10
- # An event consists of an event_name and a user the event applies to. The user is identified via email or id.
11
- # Additionally, a created timestamp is required.
12
- #
13
- # == Examples
14
- #
15
- # event = Intercom::Event.create(:event_name => "post", :user => current_user, :created_at => Time.now)
16
- #
17
- # You can also create an user-event and save it like this:
18
- # event = Intercom::Event.new
19
- # event.event_name = "publish-post"
20
- # event.user = current_user
21
- # event.created_at = Time.now
22
- # event.metadata = {
23
- # :title => 'Gravity Review',
24
- # :link => 'https://example.org/posts/22',
25
- # :comments => 'https://example.org/posts/22/comments'
26
- # }
27
- # event.save
28
- #
29
- # == Batch
30
- #
31
- # Events can be created in batches, and sent as one request. To do some, create events
32
- # without calling .create, as follows:
33
- #
34
- # event = Intercom::Event.new
35
- # event.event_name = "publish-post"
36
- # event.user = current_user
37
- #
38
- # Then pass them to the save_batch_events class method, along with an (optional) default user:
39
- #
40
- # Intercom::Event.save_batch_events(events, default_user)
41
- #
42
- # Any events without a user will be assigned to the default_user.
43
- #
44
- # Note: if you do not supply a created time, the current time in UTC will be used. Events that have the same
45
- # user, name, and created time (to second granularity) may be treated as duplicates by the server.
46
-
47
5
  class Event
48
- extend RequiresParameters
49
- include HashableObject
50
-
51
- attr_accessor :event_name, :user, :created_at # required
52
- attr_accessor :metadata, :type
53
-
54
- def initialize(attributes={})
55
- from_hash(attributes)
56
- end
57
-
58
- ##
59
- # Creates a new Event using params and saves it
60
- # @see #save
61
- def self.create(params)
62
- params[:created_at] ||= Time.now
63
- requires_parameters(params, %W(event_name user created_at))
64
- Event.new(params).save
65
- end
66
-
67
- ##
68
- # Save the Event
69
- def save
70
- raise ArgumentError.new("Missing User") if user.nil?
71
- Event.save_batch_events([self])
72
- self
73
- end
74
-
75
- ##
76
- # Save a list of Events, with an optional base_user
77
- def self.save_batch_events(events, base_user=nil)
78
- hash = { :type => 'event.list', :data => []}
79
- hash[:user] = user_hash(base_user) if base_user
80
- events.each do |event|
81
- hash[:data] << event.event_hash
82
- end
83
- post_to_intercom(hash)
84
- end
85
-
86
- def self.user_hash(user)
87
- user.user_id ? { :user_id => user.user_id } : { :email => user.email }
88
- end
89
-
90
- def self.post_to_intercom(hash)
91
- Intercom.post('/events', hash)
92
- end
93
-
94
- def user_hash
95
- Event.user_hash(user)
96
- end
97
-
98
- def event_hash
99
- event = { :event_name => event_name, :created => created_at.nil? ? Time.now.utc.to_i : created_at.to_i }
100
- event[:type] = type.nil? ? 'event' : type
101
- event[:user] = user_hash unless user.nil?
102
- event[:metadata] = metadata unless metadata.nil?
103
- event
104
- end
6
+ include ApiOperations::Save
7
+ include Traits::ApiResource
105
8
  end
106
9
  end