intercom 4.1.2 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ebb883bd25fc8d132306baac3a22c43650701dbe42d42b95ada3819bc52cc2d6
4
- data.tar.gz: 8d1158c4d79cf19916c6cc1d413c329588d1ff36b5741517e029415e0f992360
3
+ metadata.gz: d0e11ca3b41ab460f24a33608fb6a4113227bf791cefa9aa9dc9cc31e418faf5
4
+ data.tar.gz: d0379934e0ab635bb042db6ea4840e930f4c5ad56951554193f7d9ec1e7f190d
5
5
  SHA512:
6
- metadata.gz: 0a0ea848ac117043da9707f2f9689504abda06f34e218a077c0591216aa654c3e9ca73f9874f2255e7300cd3329c95ba6440232c30d58364877e7d358bf950d0
7
- data.tar.gz: 95b5ffdd05e7332fcbd53061c08c380d8632bd9f11d09e3673da65ca25b4624377b409116292b41f626a0fc6b4ad3d1c5183e5315533d3b4f94fe285c74041a6
6
+ metadata.gz: 7f77ceb73f95a43cfde87e2e274939c76f3dc023d8836683166bdc22f04de9ea14c58cedca3aecffd116023c3f92897c31f5a07d53d0811db1c958109ba5315a
7
+ data.tar.gz: 6c36c19e9d95c3218b3c4ac5034c252185a1618d62694920ec4fa5576f5152fb5f8eb4634c1cbb3802870195c6f592848269f830eb2060681380e2ba5e68d91c
data/README.md CHANGED
@@ -1,12 +1,26 @@
1
1
  # intercom-ruby
2
2
 
3
- Ruby bindings for the Intercom API (https://developers.intercom.io/reference).
3
+ [![Circle CI](https://circleci.com/gh/intercom/intercom-ruby.png?style=shield)](https://circleci.com/gh/intercom/intercom-ruby)
4
+ [![gem](https://img.shields.io/gem/v/intercom)](https://rubygems.org/gems/intercom)
5
+ ![Intercom API Version](https://img.shields.io/badge/Intercom%20API%20Version-2.6-blue)
6
+
7
+ > Ruby bindings for the [Intercom API](https://developers.intercom.io/reference).
8
+
9
+ ## Project Updates
10
+
11
+ ### Maintenance
12
+
13
+ We're currently building a new team to provide in-depth and dedicated SDK support.
14
+
15
+ In the meantime, we'll be operating on limited capacity, meaning all pull requests will be evaluated on a best effort basis and will be limited to critical issues.
16
+
17
+ We'll communicate all relevant updates as we build this new team and support strategy in the coming months.
4
18
 
5
19
  [API Documentation](https://developers.intercom.io/docs)
6
20
 
7
21
  [Gem Documentation](http://rubydoc.info/github/intercom/intercom-ruby/master/frames)
8
22
 
9
- For generating Intercom JavaScript script tags for Rails, please see https://github.com/intercom/intercom-rails.
23
+ For generating Intercom JavaScript script tags for Rails, please see [intercom/intercom-rails](https://github.com/intercom/intercom-rails)
10
24
 
11
25
  ## Upgrading information
12
26
 
@@ -16,12 +30,15 @@ This version of the gem is compatible with `Ruby 2.1` and above.
16
30
 
17
31
  ## Installation
18
32
 
19
-
20
- gem install intercom
33
+ ```bash
34
+ gem install intercom
35
+ ```
21
36
 
22
37
  Using bundler:
23
38
 
24
- gem 'intercom', '~> 4.1'
39
+ ```bundler
40
+ gem 'intercom', '~> 4.1'
41
+ ```
25
42
 
26
43
  ## Basic Usage
27
44
 
@@ -36,7 +53,7 @@ intercom = Intercom::Client.new(token: 'my_token')
36
53
 
37
54
  ```ruby
38
55
  # With a versioned app:
39
- intercom = Intercom::Client.new(token: 'my_token', api_version: '2.1')
56
+ intercom = Intercom::Client.new(token: 'my_token', api_version: '2.2')
40
57
  ```
41
58
 
42
59
  If you are building a third party application you can get your access_tokens by [setting-up-oauth](https://developers.intercom.io/page/setting-up-oauth) for Intercom.
@@ -46,29 +63,34 @@ You can also use the [omniauth-intercom lib](https://github.com/intercom/omniaut
46
63
 
47
64
  Resources this API supports:
48
65
 
49
- https://api.intercom.io/contacts
50
- https://api.intercom.io/visitors
51
- https://api.intercom.io/companies
52
- https://api.intercom.io/data_attributes
53
- https://api.intercom.io/events
54
- https://api.intercom.io/tags
55
- https://api.intercom.io/notes
56
- https://api.intercom.io/segments
57
- https://api.intercom.io/conversations
58
- https://api.intercom.io/messages
59
- https://api.intercom.io/admins
60
- https://api.intercom.io/teams
61
- https://api.intercom.io/counts
62
- https://api.intercom.io/subscriptions
63
- https://api.intercom.io/jobs
64
- https://api.intercom.io/articles
65
- https://api.intercom.io/help_center/collections
66
- https://api.intercom.io/help_center/sections
67
-
66
+ ```text
67
+ https://api.intercom.io/contacts
68
+ https://api.intercom.io/visitors
69
+ https://api.intercom.io/companies
70
+ https://api.intercom.io/data_attributes
71
+ https://api.intercom.io/events
72
+ https://api.intercom.io/tags
73
+ https://api.intercom.io/notes
74
+ https://api.intercom.io/segments
75
+ https://api.intercom.io/conversations
76
+ https://api.intercom.io/messages
77
+ https://api.intercom.io/admins
78
+ https://api.intercom.io/teams
79
+ https://api.intercom.io/counts
80
+ https://api.intercom.io/subscriptions
81
+ https://api.intercom.io/jobs
82
+ https://api.intercom.io/articles
83
+ https://api.intercom.io/help_center/collections
84
+ https://api.intercom.io/help_center/sections
85
+ https://api.intercom.io/phone_call_redirects
86
+ https://api.intercom.io/subscription_types
87
+ https://api.intercom.io/export/content/data
88
+ ```
68
89
 
69
90
  ### Examples
70
91
 
71
92
  #### Contacts
93
+
72
94
  Note that this is a new resource compatible only with the new [Contacts API](https://developers.intercom.com/intercom-api-reference/reference#contacts-model) released in API v2.0.
73
95
 
74
96
  ```ruby
@@ -95,6 +117,9 @@ intercom.contacts.unarchive(contact)
95
117
  # Delete a contact permanently
96
118
  intercom.contacts.delete(contact)
97
119
 
120
+ # Deletes an archived contact permanently
121
+ intercom.contacts.delete_archived_contact(contact.id)
122
+
98
123
  # List all contacts
99
124
  contacts = intercom.contacts.all
100
125
  contacts.each { |contact| p contact.name }
@@ -143,9 +168,20 @@ contact.remove_company(id: company.id)
143
168
 
144
169
  # List companies for a contact
145
170
  contact.companies.each {|c| p c.name}
171
+
172
+ # attach a subscription_types on a contact
173
+ contact.create_subscription_types(id: subscription_type.id)
174
+
175
+ # List subscription_types for a contact
176
+ contact.subscription_types.each {|n| p n.id}
177
+
178
+ # Remove subscription_types
179
+ contact.remove_subscription_type({ "id": subscription_type.id })
180
+
146
181
  ```
147
182
 
148
183
  #### Visitors
184
+
149
185
  ```ruby
150
186
  # Get and update a visitor
151
187
  visitor = intercom.visitors.find(id: "5dd570e7b1b922452676af23")
@@ -161,6 +197,7 @@ intercom.visitors.convert(visitor, user)
161
197
  ```
162
198
 
163
199
  #### Companies
200
+
164
201
  ```ruby
165
202
  # Find a company by company_id
166
203
  company = intercom.companies.find(company_id: "44")
@@ -188,7 +225,9 @@ intercom.companies.scroll.each { |comp| puts comp.name}
188
225
  ```
189
226
 
190
227
  #### Data Attributes
228
+
191
229
  Data Attributes are a type of metadata used to describe your customer and company models. These include standard and custom attributes.
230
+
192
231
  ```ruby
193
232
  # Create a new custom data attribute
194
233
  intercom.data_attributes.create({ name: "test_attribute", model: "contact", data_type: "string" })
@@ -208,10 +247,11 @@ intercom.data_attributes.save(attribute)
208
247
 
209
248
  # Find all customer attributes including archived
210
249
  customer_attributes_incl_archived = intercom.data_attributes.find_all({"model": "contact", "include_archived": true})
211
- customer_attributes_incl_archived.each { |attr| p attribute.name }
250
+ customer_attributes_incl_archived.each { |attr| p attr.name }
212
251
  ```
213
252
 
214
253
  #### Events
254
+
215
255
  ```ruby
216
256
  intercom.events.create(
217
257
  event_name: "invited-friend",
@@ -233,6 +273,14 @@ intercom.events.create(
233
273
 
234
274
  # Retrieve event list for user with id:'123abc'
235
275
  intercom.events.find_all("type" => "user", "intercom_user_id" => "123abc")
276
+
277
+ # Retrieve the event summary for user with id: 'abc' this will return an event object with the following characteristics:
278
+ # name - name of the event
279
+ # first - time when event first occured.
280
+ # last - time when event last occured
281
+ # count - number of times the event occured
282
+ # description - description of the event
283
+ events = intercom.events.find_all(type: 'user',intercom_user_id: 'abc',summary: true)
236
284
  ```
237
285
 
238
286
  Metadata Objects support a few simple types that Intercom can present on your behalf
@@ -257,7 +305,8 @@ intercom.events.create(
257
305
  )
258
306
  ```
259
307
 
260
- The metadata key values in the example are treated as follows-
308
+ The metadata key values in the example are treated as follows:
309
+
261
310
  - order_date: a Date (key ends with '_date')
262
311
  - stripe_invoice: The identifier of the Stripe invoice (has a 'stripe_invoice' key)
263
312
  - order_number: a Rich Link (value contains 'url' and 'value' keys)
@@ -266,6 +315,7 @@ The metadata key values in the example are treated as follows-
266
315
  *NB:* This version of the gem reserves the field name `type` in Event data.
267
316
 
268
317
  #### Tags
318
+
269
319
  ```ruby
270
320
  # Iterate over all tags
271
321
  intercom.tags.all.each {|tag| "#{tag.id} - #{tag.name}" }
@@ -276,15 +326,24 @@ tag = intercom.tags.tag(name: 'blue', companies: [{company_id: "42ea2f1b93891f6a
276
326
 
277
327
  # Untag Companies
278
328
  tag = intercom.tags.untag(name: 'blue', companies: [{ company_id: "42ea2f1b93891f6a99000427" }])
329
+
330
+
331
+ # Delete Tags
332
+
333
+ # Note : If there any depedent objects for the tag we are trying to delete, then an error TagHasDependentObjects will be thrown.
334
+ tag = intercom.tags.find(id:"123")
335
+ intercom.tags.delete(tag)
279
336
  ```
280
337
 
281
338
  #### Notes
339
+
282
340
  ```ruby
283
341
  # Find a note by id
284
342
  note = intercom.notes.find(id: "123")
285
343
  ```
286
344
 
287
345
  #### Segments
346
+
288
347
  ```ruby
289
348
  # Find a segment
290
349
  segment = intercom.segments.find(id: segment_id)
@@ -294,10 +353,13 @@ intercom.segments.all.each {|segment| puts "id: #{segment.id} name: #{segment.na
294
353
  ```
295
354
 
296
355
  #### Conversations
356
+
297
357
  ```ruby
298
358
  # Iterate over all conversations for your app
299
359
  intercom.conversations.all.each { |convo| ... }
300
360
 
361
+ # The below method of finding conversations by using the find_all method work only for API versions 2.5 and below
362
+
301
363
  # FINDING CONVERSATIONS FOR AN ADMIN
302
364
  # Iterate over all conversations (open and closed) assigned to an admin
303
365
  intercom.conversations.find_all(type: 'admin', id: '7').each {|convo| ... }
@@ -424,6 +486,7 @@ conversation.remove_contact(id: contact.id, admin_id: admin.id)
424
486
  ```
425
487
 
426
488
  #### Full loading of an embedded entity
489
+
427
490
  ```ruby
428
491
  # Given a conversation with a partial contact, load the full contact. This can be
429
492
  # done for any entity
@@ -431,6 +494,7 @@ intercom.contacts.load(conversation.contacts.first)
431
494
  ```
432
495
 
433
496
  #### Sending messages
497
+
434
498
  ```ruby
435
499
 
436
500
  # InApp message from admin to user
@@ -494,9 +558,20 @@ intercom.messages.create({
494
558
  },
495
559
  body: "halp"
496
560
  })
561
+
562
+ #From version 2.6 the type contact is not supported and you would have to use leads to send messages to a lead.
563
+
564
+ intercom.messages.create({
565
+ from: {
566
+ type: "lead",
567
+ id: "536e5643as316c83104c400671"
568
+ },
569
+ body: "halp"
570
+ })
497
571
  ```
498
572
 
499
573
  #### Admins
574
+
500
575
  ```ruby
501
576
  # Find access token owner (only with Personal Access Token and OAuth)
502
577
  intercom.admins.me
@@ -507,6 +582,7 @@ intercom.admins.all.each {|admin| puts admin.email }
507
582
  ```
508
583
 
509
584
  #### Teams
585
+
510
586
  ```ruby
511
587
  # Find a team by id
512
588
  intercom.teams.find(id: team_id)
@@ -543,7 +619,21 @@ intercom.subscriptions.delete(subscription)
543
619
  intercom.subscriptions.all
544
620
  ```
545
621
 
622
+
623
+ #### Subscription Types
624
+
625
+ List all the subscription types that a contact can opt in to
626
+
627
+ ```ruby
628
+
629
+ # fetch a subscription
630
+ intercom.subscription_types.find(id: "1")
631
+
632
+ intercom.subscription_types.all
633
+ ```
634
+
546
635
  #### Articles
636
+
547
637
  ```ruby
548
638
  # Create an article
549
639
  article = intercom.articles.create(title: "New Article", author_id: "123456")
@@ -577,6 +667,7 @@ intercom.articles.delete(article)
577
667
  ```
578
668
 
579
669
  #### Collections
670
+
580
671
  ```ruby
581
672
  # Create a collection
582
673
  collection = intercom.collections.create(name: "New Collection")
@@ -609,6 +700,7 @@ intercom.collections.delete(collection)
609
700
  ```
610
701
 
611
702
  #### Sections
703
+
612
704
  ```ruby
613
705
  # Create a section
614
706
  section = intercom.sections.create(name: "New Section", parent_id: "123456")
@@ -640,6 +732,29 @@ intercom.collections.save(section)
640
732
  intercom.sections.delete(section)
641
733
  ```
642
734
 
735
+ #### Phone Call Redirect (switch)
736
+
737
+ ```ruby
738
+ # Create a redirect
739
+ redirect = intercom.phone_call_redirect.create(phone_number: "+353871234567")
740
+
741
+ ```
742
+
743
+ #### Data Content Export
744
+
745
+ ```ruby
746
+ # Create a data export
747
+ export = intercom.export_content.create(created_at_after: 1667566801, created_at_before: 1668085202)
748
+
749
+
750
+ #View a data export
751
+ export = intercom.export_content.find(id: 'k0e27ohsyvh8ef3m')
752
+
753
+ # Cancel a data export
754
+ export = intercom.export_content.cancel('k0e27ohsyvh8ef3m')
755
+
756
+ ```
757
+
643
758
  ### Errors
644
759
 
645
760
  There are different styles for error handling - some people prefer exceptions; some prefer nil and check; some prefer error objects/codes. Balancing these preferences alongside our wish to provide an idiomatic gem has brought us to use the current mechanism of throwing specific exceptions. Our approach in the client is to propagate errors and signal our failure loudly so that erroneous data does not get propagated through our customers' systems - in other words, if you see a `Intercom::ServiceUnavailableError` you know where the problem is.
@@ -660,6 +775,7 @@ Intercom::RateLimitExceeded
660
775
  Intercom::AttributeNotSetError # Raised when you try to call a getter that does not exist on an object
661
776
  Intercom::MultipleMatchingUsersError
662
777
  Intercom::HttpError # Raised when response object is unexpectedly nil
778
+ Intercom::GatewayTimeoutError
663
779
  ```
664
780
 
665
781
  ### Rate Limiting
@@ -674,7 +790,7 @@ intercom.rate_limit_details
674
790
  You can handle the rate limits yourself but a simple option is to use the handle_rate_limit flag.
675
791
  This will automatically catch the 429 rate limit exceeded error and wait until the reset time to retry. After three retries a rate limit exception will be raised. Encountering this error frequently may require a revisiting of your usage of the API.
676
792
 
677
- ```
793
+ ```ruby
678
794
  intercom = Intercom::Client.new(token: ENV['AT'], handle_rate_limit: true)
679
795
  ```
680
796
 
@@ -700,13 +816,13 @@ intercom = Intercom::Client.new(token: ENV['AT'], handle_rate_limit: true)
700
816
 
701
817
  ```bash
702
818
  # all tests
703
- bundle exec spec
819
+ bundle exec rake spec
704
820
 
705
821
  # unit tests
706
- bundle exec spec:unit
822
+ bundle exec rake spec:unit
707
823
 
708
824
  # integration tests
709
- bundle exec spec:integration
825
+ bundle exec rake spec:integration
710
826
 
711
827
  # single test file
712
828
  bundle exec m spec/unit/intercom/job_spec.rb
data/changes.txt CHANGED
@@ -1,3 +1,15 @@
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
+
1
13
  4.1.1
2
14
  - Fixed bug with deprecated lead resource.
3
15
 
@@ -13,9 +13,7 @@ module Intercom
13
13
  raise ArgumentError, 'operations array required' if operations.nil?
14
14
 
15
15
  resource_url_method = :"#{resource_plural}_url"
16
-
17
16
  resource_name = Utils.resource_class_to_collection_name(self)
18
-
19
17
  define_method(resource_url_method.to_sym) do |id, nested_id = nil|
20
18
  url = "/#{resource_name}/#{id}/#{path}"
21
19
  url += "/#{nested_id}" unless nested_id.nil?
@@ -45,7 +45,11 @@ module Intercom
45
45
  Utils.entity_key_from_type(top_level_type)
46
46
  end
47
47
  response_hash[top_level_entity_key].each do |object_json|
48
- block.call Lib::TypedJsonDeserializer.new(object_json, @client).deserialize
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
49
53
  end
50
54
  end
51
55
 
@@ -58,6 +62,7 @@ module Intercom
58
62
  @params[:starting_after] = paging_next['starting_after']
59
63
  return true
60
64
  else
65
+ @params[:starting_after] = nil
61
66
  return false
62
67
  end
63
68
  end
@@ -84,6 +84,10 @@ module Intercom
84
84
  Intercom::Service::Subscription.new(self)
85
85
  end
86
86
 
87
+ def subscription_types
88
+ Intercom::Service::SubscriptionType.new(self)
89
+ end
90
+
87
91
  def segments
88
92
  Intercom::Service::Segment.new(self)
89
93
  end
@@ -124,6 +128,14 @@ module Intercom
124
128
  Intercom::Service::Collection.new(self)
125
129
  end
126
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
+
127
139
  def get(path, params)
128
140
  execute_request Intercom::Request.get(path, params)
129
141
  end
@@ -12,6 +12,7 @@ module Intercom
12
12
 
13
13
  nested_resource_methods :tag, operations: %i[add delete list]
14
14
  nested_resource_methods :note, operations: %i[create list]
15
+ nested_resource_methods :subscription_type, path: 'subscriptions', operations: %i[create delete list]
15
16
  nested_resource_methods :company, operations: %i[add delete list]
16
17
  nested_resource_methods :segment, operations: %i[list]
17
18
 
@@ -99,6 +99,9 @@ module Intercom
99
99
  # Raised when a merge is invalid
100
100
  class InvalidMergeError < IntercomError; end
101
101
 
102
+ # Raised when a tag has dependent objects
103
+ class TagHasDependentObjects < IntercomError; end
104
+
102
105
  #
103
106
  # Non-public errors (internal to the gem)
104
107
  #
@@ -0,0 +1,7 @@
1
+ require 'intercom/traits/api_resource'
2
+
3
+ module Intercom
4
+ class ExportContent
5
+ include Traits::ApiResource
6
+ end
7
+ end
@@ -5,20 +5,19 @@ module Intercom
5
5
  class << self
6
6
 
7
7
  def define_accessors(attribute, value, object)
8
- klass = object.class
9
8
  if attribute.to_s.end_with?('_at') && attribute.to_s != 'update_last_request_at'
10
- define_date_based_accessors(attribute, value, klass)
9
+ define_date_based_accessors(attribute, value, object)
11
10
  elsif object.flat_store_attribute?(attribute)
12
- define_flat_store_based_accessors(attribute, value, klass)
11
+ define_flat_store_based_accessors(attribute, value, object)
13
12
  else
14
- define_standard_accessors(attribute, value, klass)
13
+ define_standard_accessors(attribute, value, object)
15
14
  end
16
15
  end
17
16
 
18
17
  private
19
18
 
20
- def define_flat_store_based_accessors(attribute, value, klass)
21
- klass.class_eval %Q"
19
+ def define_flat_store_based_accessors(attribute, value, object)
20
+ object.instance_eval %Q"
22
21
  def #{attribute}=(value)
23
22
  mark_field_as_changed!(:#{attribute})
24
23
  @#{attribute} = Intercom::Lib::FlatStore.new(value)
@@ -29,8 +28,8 @@ module Intercom
29
28
  "
30
29
  end
31
30
 
32
- def define_date_based_accessors(attribute, value, klass)
33
- klass.class_eval %Q"
31
+ def define_date_based_accessors(attribute, value, object)
32
+ object.instance_eval %Q"
34
33
  def #{attribute}=(value)
35
34
  mark_field_as_changed!(:#{attribute})
36
35
  @#{attribute} = value.nil? ? nil : value.to_i
@@ -41,8 +40,8 @@ module Intercom
41
40
  "
42
41
  end
43
42
 
44
- def define_standard_accessors(attribute, value, klass)
45
- klass.class_eval %Q"
43
+ def define_standard_accessors(attribute, value, object)
44
+ object.instance_eval %Q"
46
45
  def #{attribute}=(value)
47
46
  mark_field_as_changed!(:#{attribute})
48
47
  @#{attribute} = value
@@ -9,9 +9,10 @@ module Intercom
9
9
  class TypedJsonDeserializer
10
10
  attr_reader :json
11
11
 
12
- def initialize(json, client)
12
+ def initialize(json, client, type = nil)
13
13
  @json = json
14
14
  @client = client
15
+ @type = type
15
16
  end
16
17
 
17
18
  def deserialize
@@ -27,7 +28,7 @@ module Intercom
27
28
  private
28
29
 
29
30
  def blank_object_type?(object_type)
30
- object_type.nil? || object_type == ''
31
+ object_type.nil? || object_type == '' && @type.nil?
31
32
  end
32
33
 
33
34
  def list_object_type?(object_type)
@@ -48,7 +49,11 @@ module Intercom
48
49
  end
49
50
 
50
51
  def object_type
51
- @object_type ||= json['type']
52
+ if !@type.nil?
53
+ @object_type = @type
54
+ else
55
+ @object_type ||= json['type']
56
+ end
52
57
  end
53
58
 
54
59
  def object_entity_key
@@ -0,0 +1,7 @@
1
+ require 'intercom/traits/api_resource'
2
+
3
+ module Intercom
4
+ class PhoneCallRedirect
5
+ include Traits::ApiResource
6
+ end
7
+ end
@@ -222,6 +222,8 @@ module Intercom
222
222
  raise Intercom::ApiVersionInvalid.new(error_details['message'], error_context)
223
223
  when 'scroll_exists'
224
224
  raise Intercom::ScrollAlreadyExistsError.new(error_details['message'], error_context)
225
+ when 'tag_has_dependent_objects'
226
+ raise Intercom::TagHasDependentObjects.new(error_details['message'], error_context)
225
227
  when nil, ''
226
228
  raise Intercom::UnexpectedError.new(message_for_unexpected_error_without_type(error_details, parsed_http_code), error_context)
227
229
  else
@@ -43,6 +43,10 @@ module Intercom
43
43
  contact
44
44
  end
45
45
 
46
+ def delete_archived_contact(id)
47
+ @client.delete("/#{collection_name}/#{id}", {})
48
+ end
49
+
46
50
  private def raise_invalid_merge_error
47
51
  raise Intercom::InvalidMergeError, 'Merging can only be performed on a lead into a user'
48
52
  end
@@ -21,6 +21,10 @@ module Intercom
21
21
  Intercom::Conversation
22
22
  end
23
23
 
24
+ def collection_proxy_class
25
+ Intercom::BaseCollectionProxy
26
+ end
27
+
24
28
  def mark_read(id)
25
29
  @client.put("/conversations/#{id}", read: true)
26
30
  end
@@ -0,0 +1,30 @@
1
+ require 'intercom/service/base_service'
2
+ require 'intercom/api_operations/find'
3
+ require 'intercom/api_operations/list'
4
+ require 'intercom/api_operations/save'
5
+
6
+ module Intercom
7
+ module Service
8
+ class ExportContent < BaseService
9
+ include ApiOperations::Load
10
+ include ApiOperations::List
11
+ include ApiOperations::Find
12
+ include ApiOperations::Save
13
+
14
+ def collection_class
15
+ Intercom::ExportContent
16
+ end
17
+
18
+ def collection_name
19
+ 'export/content/data'
20
+ end
21
+
22
+ def cancel(id)
23
+ response = @client.post("/export/cancel/#{id}", {})
24
+ collection_class.new.from_response(response)
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,15 @@
1
+ require 'intercom/service/base_service'
2
+ require 'intercom/api_operations/save'
3
+
4
+ module Intercom
5
+ module Service
6
+ class PhoneCallRedirect < BaseService
7
+ include ApiOperations::Save
8
+
9
+ def collection_class
10
+ Intercom::PhoneCallRedirect
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ require 'intercom/api_operations/list'
2
+ require 'intercom/api_operations/find_all'
3
+ require 'intercom/api_operations/find'
4
+
5
+ module Intercom
6
+ module Service
7
+ class SubscriptionType < BaseService
8
+ include ApiOperations::List
9
+ include ApiOperations::Find
10
+ include ApiOperations::FindAll
11
+ include ApiOperations::Delete
12
+
13
+ def collection_class
14
+ Intercom::SubscriptionType
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+
2
+ require 'intercom/traits/api_resource'
3
+
4
+ module Intercom
5
+ class SubscriptionType
6
+ include Traits::ApiResource
7
+
8
+ def self.collection_proxy_class
9
+ Intercom::BaseCollectionProxy
10
+ end
11
+ end
12
+ end
@@ -25,6 +25,10 @@ module Intercom
25
25
  constant
26
26
  end
27
27
 
28
+ def camelize(snake_cased_word)
29
+ snake_cased_word.split(/_/).map(&:capitalize).join
30
+ end
31
+
28
32
  def resource_class_to_singular_name(resource_class)
29
33
  resource_name = resource_class.to_s.split('::')[-1]
30
34
  resource_name = maybe_underscore_name(resource_name)
@@ -40,7 +44,7 @@ module Intercom
40
44
  end
41
45
 
42
46
  def constantize_resource_name(resource_name)
43
- class_name = Utils.singularize(resource_name.capitalize)
47
+ class_name = camelize Utils.singularize(resource_name.capitalize)
44
48
  define_lightweight_class(class_name) unless Intercom.const_defined?(class_name, false)
45
49
  namespaced_class_name = "Intercom::#{class_name}"
46
50
  constantize namespaced_class_name
@@ -65,6 +69,7 @@ module Intercom
65
69
 
66
70
  is_list = type.split('.')[1] == 'list'
67
71
  entity_name = type.split('.')[0]
72
+ return Utils.pluralize(entity_name) if entity_name == 'event'
68
73
  is_list ? Utils.pluralize(entity_name) : entity_name
69
74
  end
70
75
  end
@@ -1,3 +1,3 @@
1
1
  module Intercom #:nodoc:
2
- VERSION = "4.1.2"
2
+ VERSION = "4.2.0"
3
3
  end
data/lib/intercom.rb CHANGED
@@ -12,6 +12,7 @@ require 'intercom/service/event'
12
12
  require 'intercom/service/message'
13
13
  require 'intercom/service/note'
14
14
  require 'intercom/service/job'
15
+ require 'intercom/service/subscription_type'
15
16
  require 'intercom/service/subscription'
16
17
  require 'intercom/service/segment'
17
18
  require 'intercom/service/section'
@@ -21,6 +22,8 @@ require 'intercom/service/visitor'
21
22
  require 'intercom/service/user'
22
23
  require 'intercom/service/lead'
23
24
  require 'intercom/deprecated_resources.rb'
25
+ require 'intercom/service/export_content'
26
+ require 'intercom/service/phone_call_redirect'
24
27
  require 'intercom/options'
25
28
  require 'intercom/client'
26
29
  require 'intercom/contact'
@@ -42,10 +45,13 @@ require 'intercom/admin'
42
45
  require 'intercom/article'
43
46
  require 'intercom/request'
44
47
  require 'intercom/subscription'
48
+ require 'intercom/subscription_type'
45
49
  require 'intercom/team'
46
50
  require 'intercom/errors'
47
51
  require 'intercom/visitor'
48
52
  require 'intercom/data_attribute'
53
+ require 'intercom/export_content'
54
+ require 'intercom/phone_call_redirect'
49
55
  require 'json'
50
56
 
51
57
  ##
@@ -4,7 +4,7 @@ describe Intercom::BaseCollectionProxy do
4
4
  let(:client) { Intercom::Client.new(token: 'token') }
5
5
 
6
6
  it "stops iterating if no starting after value" do
7
- client.expects(:get).with("/contacts", {}). returns(page_of_contacts(false))
7
+ client.expects(:get).with("/contacts", {}).returns(page_of_contacts(false))
8
8
  emails = []
9
9
  client.contacts.all.each { |contact| emails << contact.email }
10
10
  _(emails).must_equal %w[test1@example.com test2@example.com test3@example.com]
@@ -15,6 +15,7 @@ describe Intercom::BaseCollectionProxy do
15
15
  client.expects(:get).with('/contacts', { starting_after: "EnCrYpTeDsTrInG" }).returns(page_of_contacts(false))
16
16
  emails = []
17
17
  client.contacts.all.each { |contact| emails << contact.email }
18
+ _(emails).must_equal %w[test1@example.com test2@example.com test3@example.com test1@example.com test2@example.com test3@example.com]
18
19
  end
19
20
 
20
21
  it "supports indexed array access" do
@@ -27,4 +28,20 @@ describe Intercom::BaseCollectionProxy do
27
28
  emails = client.contacts.all.map { |contact| contact.email }
28
29
  _(emails).must_equal %w[test1@example.com test2@example.com test3@example.com]
29
30
  end
31
+
32
+ it "keeps entire collection iterable after first iteration" do
33
+ contacts = client.contacts.all
34
+ emails_iter1 = []
35
+ emails_iter2 = []
36
+ expects_pagination = proc do
37
+ client.expects(:get).with("/contacts", {}).returns(page_of_contacts(true))
38
+ client.expects(:get).with("/contacts", { starting_after: "EnCrYpTeDsTrInG" }).returns(page_of_contacts(false))
39
+ end
40
+
41
+ expects_pagination.call
42
+ contacts.each { |contact| emails_iter1 << contact.email }
43
+ expects_pagination.call
44
+ contacts.each { |contact| emails_iter2 << contact.email }
45
+ _(emails_iter1).must_equal emails_iter2
46
+ end
30
47
  end
@@ -260,6 +260,12 @@ describe Intercom::Contact do
260
260
  client.contacts.unarchive(contact)
261
261
  end
262
262
 
263
+ it 'deletes an archived contact' do
264
+ contact = Intercom::Contact.new('id' => '1','archived' =>true)
265
+ client.expects(:delete).with('/contacts/1', {})
266
+ client.contacts.delete_archived_contact("1")
267
+ end
268
+
263
269
  describe 'merging' do
264
270
  let(:lead) { Intercom::Contact.from_api(external_id: 'contact_id', role: 'lead') }
265
271
  let(:user) { Intercom::Contact.from_api(id: 'external_id', role: 'user') }
@@ -274,7 +280,9 @@ describe Intercom::Contact do
274
280
 
275
281
  describe 'nested resources' do
276
282
  let(:contact) { Intercom::Contact.new(id: '1', client: client) }
283
+ let(:contact_no_tags) { Intercom::Contact.new(id: '2', client: client, tags: []) }
277
284
  let(:company) { Intercom::Company.new(id: '1') }
285
+ let(:subscription) { Intercom::Subscription.new(id: '1', client: client) }
278
286
  let(:tag) { Intercom::Tag.new(id: '1') }
279
287
  let(:note) { Intercom::Note.new(body: "<p>Text for the note</p>") }
280
288
 
@@ -299,6 +307,27 @@ describe Intercom::Contact do
299
307
  _(proxy.resource_class).must_equal Intercom::Tag
300
308
  end
301
309
 
310
+ it 'returns correct tags from differring contacts' do
311
+ client.expects(:get).with('/contacts/1/tags', {}).returns({
312
+ 'type' => 'tag.list',
313
+ 'tags' => [
314
+ {
315
+ 'type' => 'tag',
316
+ 'id' => '1',
317
+ 'name' => 'VIP Customer'
318
+ },
319
+ {
320
+ 'type' => 'tag',
321
+ 'id' => '2',
322
+ 'name' => 'Test tag'
323
+ }
324
+ ]
325
+ })
326
+
327
+ _(contact_no_tags.tags.map{ |t| t.id }).must_equal []
328
+ _(contact.tags.map{ |t| t.id }).must_equal ['1', '2']
329
+ end
330
+
302
331
  it 'returns a collection proxy for listing companies' do
303
332
  proxy = contact.companies
304
333
  _(proxy.resource_name).must_equal 'companies'
@@ -316,6 +345,11 @@ describe Intercom::Contact do
316
345
  contact.add_tag({ "id": tag.id })
317
346
  end
318
347
 
348
+ it 'removes a subscription to a contact' do
349
+ client.expects(:delete).with("/contacts/1/subscriptions/#{subscription.id}", "id": subscription.id).returns(subscription.to_hash)
350
+ contact.remove_subscription_type({ "id": subscription.id })
351
+ end
352
+
319
353
  it 'removes a tag from a contact' do
320
354
  client.expects(:delete).with("/contacts/1/tags/#{tag.id}", "id": tag.id ).returns(tag.to_hash)
321
355
  contact.remove_tag({ "id": tag.id })
@@ -365,6 +399,11 @@ describe Intercom::Contact do
365
399
  contact.create_note({body: note.body})
366
400
  end
367
401
 
402
+ it 'adds a subscription to a contact' do
403
+ client.expects(:post).with('/contacts/1/subscriptions', "id": subscription.id).returns(subscription.to_hash)
404
+ contact.create_subscription_type({ "id": subscription.id })
405
+ end
406
+
368
407
  it 'adds a tag to a contact' do
369
408
  client.expects(:post).with('/contacts/1/tags', "id": tag.id).returns(tag.to_hash)
370
409
  contact.add_tag({ "id": tag.id })
@@ -22,6 +22,13 @@ describe "Intercom::Event" do
22
22
  _(event_names).must_equal %W(invited-friend)
23
23
  end
24
24
 
25
+ it "able to fetch event summary" do
26
+ client.expects(:get).with("/events", type: 'user', email: 'joe@example.com', summary: true).returns(page_of_events(false))
27
+ event_names = []
28
+ client.events.find_all(type: 'user', email: 'joe@example.com',summary: true).each { |event| event_names << event.event_name }
29
+ _(event_names).must_equal %W(invited-friend)
30
+ end
31
+
25
32
  it "keeps iterating if next link" do
26
33
  client.expects(:get).with("/events", type: 'user', email: 'joe@example.com').returns(page_of_events(true))
27
34
  client.expects(:get).with("https://api.intercom.io/events?type=user&intercom_user_id=55a3b&before=144474756550", {}).returns(page_of_events(false))
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Intercom::ExportContent" do
4
+ let(:client) { Intercom::Client.new(token: 'token') }
5
+ let(:job) {
6
+ {
7
+ job_identifier: "k0e27ohsyvh8ef3m",
8
+ status: "no_data",
9
+ download_url: "",
10
+ download_expires_at: 0
11
+ }
12
+ }
13
+
14
+ it "creates an export job" do
15
+ client.expects(:post).with("/export/content/data", {"created_at_after" => 1667566801, "created_at_before" => 1668085202}).returns(job)
16
+ client.export_content.create({"created_at_after" => 1667566801, "created_at_before" => 1668085202})
17
+ end
18
+
19
+ it "can view an export job" do
20
+ client.expects(:get).with("/export/content/data/#{job[:job_identifier]}", {}).returns(job)
21
+ client.export_content.find(id: job[:job_identifier])
22
+ end
23
+
24
+ it "Cancels a export job redirect" do
25
+ client.expects(:post).with("/export/cancel/#{job[:job_identifier]}", {}).returns(job)
26
+ client.export_content.cancel(job[:job_identifier])
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Intercom::PhoneCallRedirect" do
4
+ let(:client) { Intercom::Client.new(token: 'token') }
5
+
6
+ it "creates a phone redirect" do
7
+
8
+ client.expects(:post).with("/phone_call_redirect", {phone_number: "+353871234567"})
9
+ client.phone_call_redirect.create(phone_number: "+353871234567")
10
+ end
11
+
12
+ end
@@ -124,6 +124,9 @@ describe 'Intercom::Request', '#execute' do
124
124
  let(:uri) {"https://api.intercom.io/conversations/reply"}
125
125
  let(:req) { Intercom::Request.put(uri, {}) }
126
126
 
127
+ let(:tag_uri) {"https://api.intercom.io/tags/"}
128
+ let(:del_req) { Intercom::Request.delete(tag_uri, {}) }
129
+
127
130
  it 'should raise ResourceNotUniqueError error on resource_conflict code' do
128
131
  stub_request(:put, uri).to_return(
129
132
  status: [409, "Resource Already Exists"],
@@ -153,5 +156,15 @@ describe 'Intercom::Request', '#execute' do
153
156
 
154
157
  expect { execute! }.must_raise(Intercom::ResourceNotFound)
155
158
  end
159
+
160
+ it 'should raise TagHasDependentObjects error on tag_has_dependent_objects code' do
161
+ stub_request(:delete, tag_uri).to_return(
162
+ status: [400, "Bad Request"],
163
+ headers: { 'X-RateLimit-Reset' => (Time.now.utc + 10).to_i.to_s },
164
+ body: { type: "error.list", errors: [ code: "tag_has_dependent_objects" ] }.to_json
165
+ )
166
+
167
+ expect { del_req.execute(tag_uri, token: 'test-token') }.must_raise(Intercom::TagHasDependentObjects)
168
+ end
156
169
  end
157
170
  end
@@ -28,4 +28,10 @@ describe 'Intercom::Tag' do
28
28
  client.expects(:post).with('/tags', 'name' => 'Test Tag', 'companies' => [{ company_id: 'abc123', untag: true }, { company_id: 'def456', untag: true }], 'tag_or_untag' => 'untag').returns(test_tag)
29
29
  client.tags.untag(name: 'Test Tag', companies: [{ company_id: 'abc123' }, { company_id: 'def456' }])
30
30
  end
31
+
32
+ it 'delete tags' do
33
+ tag = Intercom::Tag.new('id' => '1')
34
+ client.expects(:delete).with('/tags/1', {}).returns(tag)
35
+ client.tags.delete(tag)
36
+ end
31
37
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: intercom
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.2
4
+ version: 4.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben McRedmond
@@ -15,7 +15,7 @@ authors:
15
15
  autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
- date: 2020-10-30 00:00:00.000000000 Z
18
+ date: 2022-12-08 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: minitest
@@ -174,6 +174,7 @@ files:
174
174
  - lib/intercom/deprecated_resources.rb
175
175
  - lib/intercom/errors.rb
176
176
  - lib/intercom/event.rb
177
+ - lib/intercom/export_content.rb
177
178
  - lib/intercom/extended_api_operations/segments.rb
178
179
  - lib/intercom/extended_api_operations/tags.rb
179
180
  - lib/intercom/job.rb
@@ -185,6 +186,7 @@ files:
185
186
  - lib/intercom/message.rb
186
187
  - lib/intercom/note.rb
187
188
  - lib/intercom/options.rb
189
+ - lib/intercom/phone_call_redirect.rb
188
190
  - lib/intercom/request.rb
189
191
  - lib/intercom/scroll_collection_proxy.rb
190
192
  - lib/intercom/search_collection_proxy.rb
@@ -200,18 +202,22 @@ files:
200
202
  - lib/intercom/service/count.rb
201
203
  - lib/intercom/service/data_attribute.rb
202
204
  - lib/intercom/service/event.rb
205
+ - lib/intercom/service/export_content.rb
203
206
  - lib/intercom/service/job.rb
204
207
  - lib/intercom/service/lead.rb
205
208
  - lib/intercom/service/message.rb
206
209
  - lib/intercom/service/note.rb
210
+ - lib/intercom/service/phone_call_redirect.rb
207
211
  - lib/intercom/service/section.rb
208
212
  - lib/intercom/service/segment.rb
209
213
  - lib/intercom/service/subscription.rb
214
+ - lib/intercom/service/subscription_type.rb
210
215
  - lib/intercom/service/tag.rb
211
216
  - lib/intercom/service/team.rb
212
217
  - lib/intercom/service/user.rb
213
218
  - lib/intercom/service/visitor.rb
214
219
  - lib/intercom/subscription.rb
220
+ - lib/intercom/subscription_type.rb
215
221
  - lib/intercom/tag.rb
216
222
  - lib/intercom/team.rb
217
223
  - lib/intercom/traits/api_resource.rb
@@ -235,11 +241,13 @@ files:
235
241
  - spec/unit/intercom/data_attribute_spec.rb
236
242
  - spec/unit/intercom/deprecated_leads_collection_proxy_spec.rb
237
243
  - spec/unit/intercom/event_spec.rb
244
+ - spec/unit/intercom/export_content_spec.rb
238
245
  - spec/unit/intercom/job_spec.rb
239
246
  - spec/unit/intercom/lead_spec.rb
240
247
  - spec/unit/intercom/lib/flat_store_spec.rb
241
248
  - spec/unit/intercom/message_spec.rb
242
249
  - spec/unit/intercom/note_spec.rb
250
+ - spec/unit/intercom/phone_call_redirect.rb
243
251
  - spec/unit/intercom/request_spec.rb
244
252
  - spec/unit/intercom/scroll_collection_proxy_spec.rb
245
253
  - spec/unit/intercom/search_collection_proxy_spec.rb
@@ -271,7 +279,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
271
279
  - !ruby/object:Gem::Version
272
280
  version: '0'
273
281
  requirements: []
274
- rubygems_version: 3.0.3
282
+ rubygems_version: 3.3.7
275
283
  signing_key:
276
284
  specification_version: 4
277
285
  summary: Ruby bindings for the Intercom API
@@ -290,11 +298,13 @@ test_files:
290
298
  - spec/unit/intercom/data_attribute_spec.rb
291
299
  - spec/unit/intercom/deprecated_leads_collection_proxy_spec.rb
292
300
  - spec/unit/intercom/event_spec.rb
301
+ - spec/unit/intercom/export_content_spec.rb
293
302
  - spec/unit/intercom/job_spec.rb
294
303
  - spec/unit/intercom/lead_spec.rb
295
304
  - spec/unit/intercom/lib/flat_store_spec.rb
296
305
  - spec/unit/intercom/message_spec.rb
297
306
  - spec/unit/intercom/note_spec.rb
307
+ - spec/unit/intercom/phone_call_redirect.rb
298
308
  - spec/unit/intercom/request_spec.rb
299
309
  - spec/unit/intercom/scroll_collection_proxy_spec.rb
300
310
  - spec/unit/intercom/search_collection_proxy_spec.rb