Skip to content

Commit a412ea8

Browse files
Merge branch 'master' into ak/add-hard-delete-request
2 parents d80935a + 5905676 commit a412ea8

File tree

17 files changed

+250
-71
lines changed

17 files changed

+250
-71
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#### Why?
2+
Why are you making this change?
3+
4+
#### How?
5+
Technical details on your change

.travis.yml

Lines changed: 0 additions & 10 deletions
This file was deleted.

Gemfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ gemspec
55

66
group :development, :test do
77
platforms :jruby do
8-
gem 'json-jruby'
98
gem 'jruby-openssl'
109
end
1110
end

README.md

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ This version of the gem is compatible with `Ruby 2.1` and above.
2222

2323
Using bundler:
2424

25-
gem 'intercom', '~> 3.5.25'
25+
gem 'intercom', '~> 3.6.2'
2626

2727
## Basic Usage
2828

@@ -132,8 +132,10 @@ intercom.companies.save(company)
132132
# Iterate over all companies
133133
intercom.companies.all.each {|company| puts %Q(#{company.name} - #{company.custom_attributes["referral_source"]}) }
134134
intercom.companies.all.map {|company| company.name }
135-
# Get a list of users in a company
136-
intercom.companies.users(company.id)
135+
# Get a list of users in a company by Intercom Company ID
136+
intercom.companies.users_by_intercom_company_id(company.id)
137+
# Get a list of users in a company by external company_id
138+
intercom.companies.users_by_company_id(company.company_id)
137139
# Get a large list of companies using scroll
138140
intercom.companies.scroll.each { |comp| puts comp.name}
139141
# Please see users scroll for more details of how to use scroll
@@ -149,7 +151,7 @@ intercom.tags.untag(name: 'blue', users: [{user_id: "42ea2f1b93891f6a99000427"}
149151
intercom.tags.all.each {|tag| "#{tag.id} - #{tag.name}" }
150152
intercom.tags.all.map {|tag| tag.name }
151153
# Tag companies
152-
tag = intercom.tags.tag(name: 'blue', companies: [{id: "42ea2f1b93891f6a99000427"}])
154+
tag = intercom.tags.tag(name: 'blue', companies: [{company_id: "42ea2f1b93891f6a99000427"}])
153155
```
154156

155157
#### Segments
@@ -174,6 +176,9 @@ intercom.notes.find_all(user_id: '123').each {|note| puts note.body}
174176

175177
#### Conversations
176178
```ruby
179+
# Iterate over all conversations for your app
180+
intercom.conversations.all.each { |convo| ... }
181+
177182
# FINDING CONVERSATIONS FOR AN ADMIN
178183
# Iterate over all conversations (open and closed) assigned to an admin
179184
intercom.conversations.find_all(type: 'admin', id: '7').each {|convo| ... }
@@ -191,6 +196,11 @@ intercom.conversations.find_all(email: '[email protected]', type: 'user').each {|c
191196
intercom.conversations.find_all(email: '[email protected]', type: 'user', unread: false).each {|convo| ... }
192197
# Iterate over all unread conversations with a user based on the users email
193198
intercom.conversations.find_all(email: '[email protected]', type: 'user', unread: true).each {|convo| ... }
199+
# Iterate over all conversations for a user with their Intercom user ID
200+
intercom.conversations.find_all(intercom_user_id: '536e564f316c83104c000020', type: 'user').each {|convo| ... }
201+
# Iterate over all conversations for a lead
202+
# NOTE: to iterate over a lead's conversations you MUST use their Intercom User ID and type User
203+
intercom.conversations.find_all(intercom_user_id: lead.id, type: 'user').each {|convo| ... }
194204

195205
# FINDING A SINGLE CONVERSATION
196206
conversation = intercom.conversations.find(id: '1')
@@ -218,8 +228,13 @@ intercom.conversations.open(id: conversation.id, admin_id: '123')
218228
intercom.conversations.close(id: conversation.id, admin_id: '123')
219229

220230
# Assign
231+
# Note: Conversations can be assigned to teams. However, the entity that performs the operation of assigning the conversation has to be an existing teammate.
232+
# You can use `intercom.admins.all.each {|a| puts a.inspect if a.type == 'admin' }` to list all of your teammates.
221233
intercom.conversations.assign(id: conversation.id, admin_id: '123', assignee_id: '124')
222234

235+
# Snooze
236+
intercom.conversations.snooze(id: conversation.id, admin_id: '123', snoozed_until: 9999999999)
237+
223238
# Reply and Open
224239
intercom.conversations.reply(id: conversation.id, type: 'admin', admin_id: '123', message_type: 'open', body: 'bar')
225240

@@ -357,20 +372,50 @@ The metadata key values in the example are treated as follows-
357372
### Contacts
358373

359374
`Contacts` represent logged out users of your application.
375+
Note that `contacts` are referred to as `leads` in the [Intercom](https://developers.intercom.com/intercom-api-reference/reference#leads)
360376

361377
```ruby
362378
# Create a contact
363379
contact = intercom.contacts.create(email: "[email protected]")
364380

365-
# Update a contact
381+
# Update a contact (via create method)
382+
# You can update a contact by calling the create method but you MUST provide an id or user_id
383+
# If you just provide an email, for example, it will create a new contact
384+
# See https://developers.intercom.com/intercom-api-reference/reference#update-lead for more detail
385+
contact = intercom.contacts.create(email: "[email protected]", id: "3be0398668071a6bc6850413", name:"update_contact")
386+
387+
# Update a contact (via contact object)
366388
contact.custom_attributes['foo'] = 'bar'
367389
intercom.contacts.save(contact)
368390

369391
# Find contacts by email
370392
contacts = intercom.contacts.find_all(email: "[email protected]")
371393

394+
# Using find to search for contacts by email
395+
contact_list = intercom.contacts.find(email: "[email protected]")
396+
# This returns a Contact object with type contact.list
397+
# Note: Multiple contacts can be returned in this list if there are multiple matching contacts found
398+
# #<Intercom::Contact:0x00007ff3a80789f8
399+
# @changed_fields=#<Set: {}>,
400+
# @contacts=
401+
# [{"type"=>"contact",
402+
# "id"=>"5b7fd9b683681ac52274b9c7",
403+
# "user_id"=>"05bc4d17-72cc-433e-88ae-0bf88db5d0e6",
404+
# "anonymous"=>true,
405+
# "email"=>"[email protected]",
406+
# ...}],
407+
# @custom_attributes={},
408+
# @limited=false,
409+
# @pages=#<Intercom::Pages:0x00007ff3a7413c58 @changed_fields=#<Set: {}>, @next=nil, @page=1, @per_page=50, @total_pages=1, @type="pages">,
410+
# @total_count=1,
411+
# @type="contact.list">
412+
# Access the contact's data
413+
contact_list.contacts.first
414+
372415
# Convert a contact into a user
373-
intercom.contacts.convert(contact, user)
416+
contact = intercom.contacts.find(id: "536e564f316c83104c000020")
417+
intercom.contacts.convert(contact, Intercom::User.new(email: email))
418+
# Using find with email will not work here. See https://github.com/intercom/intercom-ruby/issues/419 for more information
374419

375420
# Delete a contact
376421
intercom.contacts.delete(contact)
@@ -441,7 +486,7 @@ intercom.rate_limit_details
441486
```
442487

443488
You can handle the rate limits yourself but a simple option is to use the handle_rate_limit flag.
444-
This will automatically catch the 429 rate limit exceeded error and wait until the reset time to retry.
489+
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.
445490

446491
```
447492
intercom = Intercom::Client.new(token: ENV['AT'], handle_rate_limit: true)

changes.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,30 @@
1+
3.6.2
2+
#384 Add ability to snooze conversation
3+
You can now snooze conversations in your app via:
4+
intercom.conversations.snooze(...)
5+
6+
3.6.1
7+
#430 Allow all conversations to be listed
8+
You can now iterate over all conversations for your app via:
9+
intercom.conversations.all.each { |convo| ... }
10+
11+
3.6.0
12+
BREAKING CHANGE companies
13+
We updated companies to be able to list users via company_id as well as id (#428 )
14+
Note that this is a breaking change as we had to remove the old way of listing users via company.
15+
16+
Previously it was:
17+
intercom.companies.users(company.id)
18+
19+
Now you get a list of users in a company by Intercom Company ID
20+
intercom.companies.users_by_intercom_company_id(company.id)
21+
22+
Now you get a list of users in a company by external company_id
23+
intercom.companies.users_by_company_id(company.company_id)
24+
25+
Rate limit handling
26+
We also improved the way we handle rate limits in PR #409 which was related to issue #405
27+
128
3.5.23
229
- New type of error (ResourceNotUniqueError). Thrown when trying to create a resource that already exists in Intercom
330

intercom.gemspec

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ Gem::Specification.new do |spec|
2525
spec.add_development_dependency "fakeweb", ["~> 1.3"]
2626
spec.add_development_dependency "pry"
2727

28-
spec.add_dependency 'json', '>= 1.8'
2928
spec.required_ruby_version = '>= 2.1.0'
3029
spec.add_development_dependency 'gem-release'
3130
end

lib/intercom/client.rb

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module Intercom
22
class MisconfiguredClientError < StandardError; end
33
class Client
44
include Options
5-
attr_reader :base_url, :rate_limit_details, :username_part, :password_part, :handle_rate_limit
5+
attr_reader :base_url, :rate_limit_details, :username_part, :password_part, :handle_rate_limit, :timeouts
66

77
class << self
88
def set_base_url(base_url)
@@ -12,6 +12,17 @@ def set_base_url(base_url)
1212
Proc.new { |obj| set_base_url(old_url).call(o) }
1313
end
1414
end
15+
16+
def set_timeouts(open_timeout: nil, read_timeout: nil)
17+
return Proc.new do |o|
18+
old_timeouts = o.timeouts
19+
timeouts = {}
20+
timeouts[:open_timeout] = open_timeout if open_timeout
21+
timeouts[:read_timeout] = read_timeout if read_timeout
22+
o.send(:timeouts=, timeouts)
23+
Proc.new { |obj| set_timeouts(old_timeouts).call(o) }
24+
end
25+
end
1526
end
1627

1728
def initialize(app_id: 'my_app_id', api_key: 'my_api_key', token: nil, base_url:'https://api.intercom.io', handle_rate_limit: false)
@@ -27,6 +38,10 @@ def initialize(app_id: 'my_app_id', api_key: 'my_api_key', token: nil, base_url:
2738
@base_url = base_url
2839
@rate_limit_details = {}
2940
@handle_rate_limit = handle_rate_limit
41+
@timeouts = {
42+
open_timeout: 30,
43+
read_timeout: 90
44+
}
3045
end
3146

3247
def admins
@@ -110,13 +125,17 @@ def validate_credentials!
110125

111126
def execute_request(request)
112127
request.handle_rate_limit = handle_rate_limit
113-
request.execute(@base_url, username: @username_part, secret: @password_part)
128+
request.execute(@base_url, username: @username_part, secret: @password_part, **timeouts)
114129
ensure
115130
@rate_limit_details = request.rate_limit_details
116131
end
117132

118133
def base_url=(new_url)
119134
@base_url = new_url
120135
end
136+
137+
def timeouts=(timeouts)
138+
@timeouts = @timeouts.merge(timeouts)
139+
end
121140
end
122141
end

lib/intercom/extended_api_operations/users.rb

Lines changed: 0 additions & 16 deletions
This file was deleted.

lib/intercom/request.rb

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,25 +46,25 @@ def self.default_headers
4646
{'Accept-Encoding' => 'gzip, deflate', 'Accept' => 'application/vnd.intercom.3+json', 'User-Agent' => "Intercom-Ruby/#{Intercom::VERSION}"}
4747
end
4848

49-
def client(uri)
49+
def client(uri, read_timeout:, open_timeout:)
5050
net = Net::HTTP.new(uri.host, uri.port)
5151
if uri.is_a?(URI::HTTPS)
5252
net.use_ssl = true
5353
net.verify_mode = OpenSSL::SSL::VERIFY_PEER
5454
net.ca_file = File.join(File.dirname(__FILE__), '../data/cacert.pem')
5555
end
56-
net.read_timeout = 90
57-
net.open_timeout = 30
56+
net.read_timeout = read_timeout
57+
net.open_timeout = open_timeout
5858
net
5959
end
6060

61-
def execute(target_base_url=nil, username:, secret: nil)
61+
def execute(target_base_url=nil, username:, secret: nil, read_timeout: 90, open_timeout: 30)
6262
retries = 3
6363
base_uri = URI.parse(target_base_url)
6464
set_common_headers(net_http_method, base_uri)
6565
set_basic_auth(net_http_method, username, secret)
6666
begin
67-
client(base_uri).start do |http|
67+
client(base_uri, read_timeout: read_timeout, open_timeout: open_timeout).start do |http|
6868
begin
6969
response = http.request(net_http_method)
7070
set_rate_limit_details(response)
@@ -75,8 +75,12 @@ def execute(target_base_url=nil, username:, secret: nil)
7575
rescue Intercom::RateLimitExceeded => e
7676
if @handle_rate_limit
7777
seconds_to_retry = (@rate_limit_details[:reset_at] - Time.now.utc).ceil
78-
sleep seconds_to_retry unless seconds_to_retry < 0
79-
retry unless (retries -=1).zero?
78+
if (retries -= 1) < 0
79+
raise Intercom::RateLimitExceeded.new('Rate limit retries exceeded. Please examine current API Usage.')
80+
else
81+
sleep seconds_to_retry unless seconds_to_retry < 0
82+
retry
83+
end
8084
else
8185
raise e
8286
end

lib/intercom/service/company.rb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
require 'intercom/api_operations/find_all'
66
require 'intercom/api_operations/save'
77
require 'intercom/api_operations/load'
8-
require 'intercom/extended_api_operations/users'
98
require 'intercom/extended_api_operations/tags'
109
require 'intercom/extended_api_operations/segments'
1110

@@ -18,13 +17,24 @@ class Company < BaseService
1817
include ApiOperations::List
1918
include ApiOperations::Scroll
2019
include ApiOperations::Save
21-
include ExtendedApiOperations::Users
2220
include ExtendedApiOperations::Tags
2321
include ExtendedApiOperations::Segments
2422

2523
def collection_class
2624
Intercom::Company
2725
end
26+
27+
def users_by_intercom_company_id(id)
28+
get_users(url: "/companies/#{id}/users")
29+
end
30+
31+
def users_by_company_id(id)
32+
get_users(url: "/companies", params: { company_id: id, type: "user" })
33+
end
34+
35+
private def get_users(url:, params: {})
36+
ClientCollectionProxy.new("users", finder_details: { url: url, params: params }, client: @client)
37+
end
2838
end
2939
end
3040
end

0 commit comments

Comments
 (0)