intercom 0.0.1 → 0.0.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.
- data/.gitignore +3 -0
- data/README.md +27 -8
- data/README.rdoc +1 -0
- data/Rakefile +18 -3
- data/intercom.gemspec +3 -5
- data/lib/data/cacert.pem +3965 -0
- data/lib/intercom.rb +91 -26
- data/lib/intercom/impression.rb +47 -0
- data/lib/intercom/message_thread.rb +128 -0
- data/lib/intercom/shallow_hash.rb +8 -0
- data/lib/intercom/social_profile.rb +43 -0
- data/lib/intercom/unix_timestamp_unwrapper.rb +11 -0
- data/lib/intercom/user.rb +133 -0
- data/lib/intercom/user_resource.rb +75 -0
- data/lib/intercom/version.rb +2 -2
- data/spec/integration/intercom_api_integration_spec.rb +28 -0
- data/spec/unit/intercom/impression_spec.rb +18 -0
- data/spec/unit/intercom/message_thread_spec.rb +74 -0
- data/spec/unit/intercom/user_resource_spec.rb +13 -0
- data/spec/unit/intercom/user_spec.rb +133 -0
- data/spec/unit/intercom_spec.rb +57 -0
- data/spec/unit/spec_helper.rb +80 -0
- metadata +41 -44
- data/Guardfile +0 -5
- data/spec/intercom_spec.rb +0 -36
- data/spec/spec_helper.rb +0 -35
data/lib/intercom.rb
CHANGED
@@ -1,53 +1,118 @@
|
|
1
1
|
require "intercom/version"
|
2
|
+
require "intercom/user_resource"
|
3
|
+
require "intercom/user"
|
4
|
+
require "intercom/message_thread"
|
5
|
+
require "intercom/impression"
|
2
6
|
require "rest_client"
|
3
|
-
require
|
7
|
+
require "json"
|
4
8
|
|
9
|
+
##
|
10
|
+
# Intercom is a customer relationship management and messaging tool for web app owners
|
11
|
+
#
|
12
|
+
# This library provides ruby bindings for the Intercom API (https://api.intercom.io)
|
13
|
+
#
|
14
|
+
# == Basic Usage
|
15
|
+
# === Configure Intercom with your access credentials
|
16
|
+
# Intercom.app_id = "my_app_id"
|
17
|
+
# Intercom.secret_key = "my_secret_key"
|
18
|
+
# === Make requests to the API
|
19
|
+
# Intercom::User.find(:email => "bob@example.com")
|
20
|
+
#
|
5
21
|
module Intercom
|
22
|
+
@hostname = "api.intercom.io"
|
23
|
+
@protocol = "https"
|
24
|
+
@app_id = nil
|
25
|
+
@secret_key = nil
|
26
|
+
|
27
|
+
##
|
28
|
+
# Set the id of the application you want to interact with.
|
29
|
+
# When logged into your intercom console, the app_id is in the url after /apps (eg https://www.intercom.io/apps/<app-id>)
|
6
30
|
def self.app_id=(app_id)
|
7
31
|
@app_id = app_id
|
8
32
|
end
|
9
33
|
|
34
|
+
##
|
35
|
+
# Set the secret key to gain access to your application data.
|
36
|
+
# When logged into your intercom console, you can view/create api keys in the settings menu
|
10
37
|
def self.secret_key=(secret_key)
|
11
38
|
@secret_key = secret_key
|
12
39
|
end
|
13
40
|
|
14
|
-
|
15
|
-
|
41
|
+
|
42
|
+
private
|
43
|
+
def self.url_for_path(path)
|
44
|
+
raise ArgumentError, "You must set both Intercom.app_id and Intercom.secret_key to use this client. See https://github.com/intercom/intercom for usage examples." if [@app_id, @secret_key].any?(&:nil?)
|
45
|
+
"#{protocol}://#{@app_id}:#{@secret_key}@#{hostname}/v1/#{path}"
|
16
46
|
end
|
17
47
|
|
18
|
-
def self.
|
19
|
-
|
48
|
+
def self.post(path, payload_hash)
|
49
|
+
execute_request(:post, path, {}, {:content_type => :json, :accept => :json}, payload_hash)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.put(path, payload_hash)
|
53
|
+
execute_request(:put, path, {}, {:content_type => :json, :accept => :json}, payload_hash)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.get(path, params)
|
57
|
+
execute_request(:get, path, params)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.require_email_or_user_id(params)
|
61
|
+
raise ArgumentError.new("Expected params Hash, got #{params.class}") unless params.is_a?(Hash)
|
62
|
+
raise ArgumentError.new("Either email or user_id must be specified") unless params.keys.any? { |key| %W(email user_id).include?(key.to_s) }
|
20
63
|
end
|
21
64
|
|
22
65
|
def self.execute_request(method, path, params = {}, headers = {}, payload = nil)
|
23
|
-
|
24
|
-
args =
|
66
|
+
method.eql?(:get) ? require_email_or_user_id(params) : require_email_or_user_id(payload)
|
67
|
+
args =rest_client_args(method, path, params, headers, payload)
|
68
|
+
begin
|
69
|
+
response = RestClient::Request.execute(args)
|
70
|
+
JSON.parse(response.body)
|
71
|
+
rescue RestClient::ResourceNotFound
|
72
|
+
raise ResourceNotFound.new
|
73
|
+
rescue RestClient::Unauthorized
|
74
|
+
raise AuthenticationError.new
|
75
|
+
rescue RestClient::InternalServerError
|
76
|
+
raise ServerError.new
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.rest_client_args(method, path, params, headers, payload)
|
81
|
+
url = url_for_path(path)
|
82
|
+
{
|
25
83
|
:method => method,
|
26
84
|
:url => url,
|
27
|
-
:headers => {:params => params}.merge(headers),
|
85
|
+
:headers => {:params => params}.merge(headers).merge(:accept => :json),
|
28
86
|
:open_timeout => 10,
|
29
|
-
:payload => payload,
|
30
|
-
:timeout => 30
|
87
|
+
:payload => payload.nil? ? nil : payload.to_json,
|
88
|
+
:timeout => 30,
|
89
|
+
:verify_ssl => OpenSSL::SSL::VERIFY_PEER,
|
90
|
+
:ssl_ca_file => File.join(File.dirname(__FILE__), 'data/cacert.pem')
|
31
91
|
}
|
32
|
-
RestClient::Request.execute(args)
|
33
92
|
end
|
34
93
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
94
|
+
def self.protocol #nodoc
|
95
|
+
@protocol
|
96
|
+
end
|
39
97
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
98
|
+
def self.protocol=(override)
|
99
|
+
@protocol = override
|
100
|
+
end
|
44
101
|
|
45
|
-
|
46
|
-
|
47
|
-
|
102
|
+
def self.hostname
|
103
|
+
@hostname
|
104
|
+
end
|
48
105
|
|
49
|
-
|
50
|
-
|
51
|
-
|
106
|
+
def self.hostname=(override)
|
107
|
+
@hostname = override
|
108
|
+
end
|
109
|
+
|
110
|
+
class AuthenticationError < StandardError;
|
111
|
+
end
|
112
|
+
|
113
|
+
class ServerError < StandardError;
|
114
|
+
end
|
115
|
+
|
116
|
+
class ResourceNotFound < StandardError;
|
52
117
|
end
|
53
|
-
end
|
118
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'intercom/user_resource'
|
2
|
+
|
3
|
+
module Intercom
|
4
|
+
|
5
|
+
##
|
6
|
+
# Represents a users interaction with your app (eg page view, or using a particular feature)
|
7
|
+
class Impression < UserResource
|
8
|
+
##
|
9
|
+
# Records that a user has interacted with your application, including the 'location' within the app they used
|
10
|
+
def self.create(params)
|
11
|
+
Impression.new(params).save
|
12
|
+
end
|
13
|
+
|
14
|
+
def save
|
15
|
+
response = Intercom.post("users/impressions", to_hash)
|
16
|
+
self.update_from_api_response(response)
|
17
|
+
end
|
18
|
+
|
19
|
+
def user_ip=(user_ip)
|
20
|
+
@attributes["user_ip"] = user_ip
|
21
|
+
end
|
22
|
+
|
23
|
+
def user_ip
|
24
|
+
@attributes["user_ip"]
|
25
|
+
end
|
26
|
+
|
27
|
+
def location=(location)
|
28
|
+
@attributes["location"] = location
|
29
|
+
end
|
30
|
+
|
31
|
+
def location
|
32
|
+
@attributes["location"]
|
33
|
+
end
|
34
|
+
|
35
|
+
def user_agent=(user_agent)
|
36
|
+
@attributes["user_agent"] = user_agent
|
37
|
+
end
|
38
|
+
|
39
|
+
def user_agent
|
40
|
+
@attributes["user_agent"]
|
41
|
+
end
|
42
|
+
|
43
|
+
def unread_messages
|
44
|
+
@attributes["unread_messages"]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'intercom/user_resource'
|
2
|
+
|
3
|
+
module Intercom
|
4
|
+
##
|
5
|
+
# object representing a conversation with a user
|
6
|
+
class MessageThread < UserResource
|
7
|
+
include UnixTimestampUnwrapper
|
8
|
+
|
9
|
+
##
|
10
|
+
# Finds a particular Message identified by thread_id
|
11
|
+
def self.find(params)
|
12
|
+
requires_parameters(params, %W(thread_id))
|
13
|
+
api_response = Intercom.get("users/message_threads", params)
|
14
|
+
MessageThread.from_api(api_response)
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Finds all Messages to show a particular user
|
19
|
+
def self.find_all(params)
|
20
|
+
response = Intercom.get("users/message_threads", params)
|
21
|
+
response.map { |message| MessageThread.from_api(message) }
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Either creates a new message from this user to your application admins, or a comment on an existing one
|
26
|
+
def self.create(params)
|
27
|
+
requires_parameters(params, %W(body))
|
28
|
+
MessageThread.new(params).save
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Marks a message (identified by thread_id) as read
|
33
|
+
def self.mark_as_read(params)
|
34
|
+
requires_parameters(params, %W(thread_id))
|
35
|
+
MessageThread.new({"read" => true}.merge(params)).save(:put)
|
36
|
+
end
|
37
|
+
|
38
|
+
def save(method=:post)
|
39
|
+
response = Intercom.send(method, "users/message_threads", to_hash)
|
40
|
+
self.update_from_api_response(response)
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Set the content of the message. Supports standard markdown syntax
|
45
|
+
def body=(body)
|
46
|
+
@attributes["body"] = body
|
47
|
+
end
|
48
|
+
|
49
|
+
def body
|
50
|
+
@attributes["body"]
|
51
|
+
end
|
52
|
+
|
53
|
+
def created_at
|
54
|
+
time_at("created_at")
|
55
|
+
end
|
56
|
+
|
57
|
+
def updated_at
|
58
|
+
time_at("updated_at")
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def thread_id=(thread_id)
|
63
|
+
@attributes["thread_id"] = thread_id
|
64
|
+
end
|
65
|
+
|
66
|
+
def thread_id
|
67
|
+
@attributes["thread_id"]
|
68
|
+
end
|
69
|
+
|
70
|
+
def read=(read)
|
71
|
+
@attributes["read"] = read
|
72
|
+
end
|
73
|
+
|
74
|
+
def read
|
75
|
+
@attributes["read"]
|
76
|
+
end
|
77
|
+
|
78
|
+
def messages
|
79
|
+
@attributes["messages"].map {|message_hash| Message.new(message_hash)}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Message
|
84
|
+
include UnixTimestampUnwrapper
|
85
|
+
|
86
|
+
def initialize(params)
|
87
|
+
@attributes = params
|
88
|
+
end
|
89
|
+
|
90
|
+
def from
|
91
|
+
MessageAuthor.new(@attributes["from"])
|
92
|
+
end
|
93
|
+
|
94
|
+
def html
|
95
|
+
@attributes["html"]
|
96
|
+
end
|
97
|
+
|
98
|
+
def created_at
|
99
|
+
time_at("created_at")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class MessageAuthor
|
104
|
+
def initialize(params)
|
105
|
+
@attributes = params
|
106
|
+
end
|
107
|
+
|
108
|
+
def admin?
|
109
|
+
@attributes['is_admin']
|
110
|
+
end
|
111
|
+
|
112
|
+
def email
|
113
|
+
@attributes['email']
|
114
|
+
end
|
115
|
+
|
116
|
+
def user_id
|
117
|
+
@attributes['user_id']
|
118
|
+
end
|
119
|
+
|
120
|
+
def avatar_path_50
|
121
|
+
@attributes['avatar_path_50']
|
122
|
+
end
|
123
|
+
|
124
|
+
def name
|
125
|
+
@attributes['name']
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'intercom/user_resource'
|
2
|
+
|
3
|
+
module Intercom
|
4
|
+
##
|
5
|
+
# object representing a social profile for the User (see )http://docs.intercom.io/#SocialProfiles)
|
6
|
+
class SocialProfile < UserResource
|
7
|
+
def for_wire #:nodoc:
|
8
|
+
@attributes
|
9
|
+
end
|
10
|
+
|
11
|
+
def type
|
12
|
+
@attributes["type"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def type=(type)
|
16
|
+
@attributes["type"]=type
|
17
|
+
end
|
18
|
+
|
19
|
+
def id
|
20
|
+
@attributes["id"]
|
21
|
+
end
|
22
|
+
|
23
|
+
def id=(id)
|
24
|
+
@attributes["id"]=id
|
25
|
+
end
|
26
|
+
|
27
|
+
def url
|
28
|
+
@attributes["url"]
|
29
|
+
end
|
30
|
+
|
31
|
+
def url=(url)
|
32
|
+
@attributes["url"]=url
|
33
|
+
end
|
34
|
+
|
35
|
+
def username
|
36
|
+
@attributes["username"]
|
37
|
+
end
|
38
|
+
|
39
|
+
def username=(username)
|
40
|
+
@attributes["username"]=username
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Intercom
|
2
|
+
module UnixTimestampUnwrapper
|
3
|
+
def time_at(attribute_name)
|
4
|
+
Time.at(@attributes[attribute_name]) if @attributes[attribute_name]
|
5
|
+
end
|
6
|
+
|
7
|
+
def set_time_at(attribute_name, time)
|
8
|
+
@attributes[attribute_name.to_s] = time.to_i
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'intercom/user_resource'
|
2
|
+
require 'intercom/shallow_hash'
|
3
|
+
require 'intercom/social_profile'
|
4
|
+
|
5
|
+
module Intercom
|
6
|
+
##
|
7
|
+
# Represents a user of your application on Intercom.
|
8
|
+
class User < UserResource
|
9
|
+
##
|
10
|
+
# Fetches an Intercom::User from our API.
|
11
|
+
#
|
12
|
+
# Calls GET https://api.intercom.io/v1/users
|
13
|
+
#
|
14
|
+
# returns Intercom::User object representing the state on our servers.
|
15
|
+
#
|
16
|
+
def self.find(params)
|
17
|
+
response = Intercom.get("users", params)
|
18
|
+
User.from_api(response)
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Creates (or updates when a user already exists for that email/user_id) a user record on your application.
|
23
|
+
#
|
24
|
+
# Calls POST https://api.intercom.io/v1/users
|
25
|
+
#
|
26
|
+
# returns Intercom::User object representing the state on our servers.
|
27
|
+
#
|
28
|
+
# This operation is idempotent.
|
29
|
+
def self.create(params)
|
30
|
+
User.new(params).save
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# instance method alternative to #create
|
35
|
+
def save
|
36
|
+
response = Intercom.post("users", to_hash)
|
37
|
+
self.update_from_api_response(response)
|
38
|
+
end
|
39
|
+
|
40
|
+
def name
|
41
|
+
@attributes["name"]
|
42
|
+
end
|
43
|
+
|
44
|
+
def name=(name)
|
45
|
+
@attributes["name"]=name
|
46
|
+
end
|
47
|
+
|
48
|
+
def last_seen_ip
|
49
|
+
@attributes["last_seen_ip"]
|
50
|
+
end
|
51
|
+
|
52
|
+
def last_seen_ip=(last_seen_ip)
|
53
|
+
@attributes["last_seen_ip"]=last_seen_ip
|
54
|
+
end
|
55
|
+
|
56
|
+
def last_seen_user_agent
|
57
|
+
@attributes["last_seen_user_agent"]
|
58
|
+
end
|
59
|
+
|
60
|
+
def last_seen_user_agent=(last_seen_user_agent)
|
61
|
+
@attributes["last_seen_user_agent"]=last_seen_user_agent
|
62
|
+
end
|
63
|
+
|
64
|
+
def relationship_score
|
65
|
+
@attributes["relationship_score"]
|
66
|
+
end
|
67
|
+
|
68
|
+
def session_count
|
69
|
+
@attributes["session_count"]
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Get last time this User interacted with your application
|
74
|
+
def last_impression_at
|
75
|
+
time_at("last_impression_at")
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# Get Time at which this User started using your application.
|
80
|
+
def created_at
|
81
|
+
time_at("created_at")
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Get Time at which this User started using your application.
|
86
|
+
def created_at=(time)
|
87
|
+
set_time_at("created_at", time)
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# Get array of Intercom::SocialProfile objects attached to this Intercom::User
|
92
|
+
#
|
93
|
+
# See http://docs.intercom.io/#SocialProfiles for more information
|
94
|
+
def social_profiles
|
95
|
+
@social_profiles ||= [].freeze
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Get hash of location attributes associated with this Intercom::User
|
100
|
+
#
|
101
|
+
# Possible entries: city_name, continent_code, country_code, country_name, latitude, longitude, postal_code, region_name, timezone
|
102
|
+
#
|
103
|
+
# e.g.
|
104
|
+
#
|
105
|
+
# {"city_name"=>"Santiago", "continent_code"=>"SA", "country_code"=>"CHL", "country_name"=>"Chile",
|
106
|
+
# "latitude"=>-33.44999999999999, "longitude"=>-70.6667, "postal_code"=>"", "region_name"=>"12",
|
107
|
+
# "timezone"=>"Chile/Continental"}
|
108
|
+
def location_data
|
109
|
+
@location_data ||= {}.freeze
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Get hash of custom attributes stored for this Intercom::User
|
114
|
+
#
|
115
|
+
# See http://docs.intercom.io/#CustomData for more information
|
116
|
+
def custom_data
|
117
|
+
@attributes["custom_data"] ||= ShallowHash.new
|
118
|
+
end
|
119
|
+
|
120
|
+
protected
|
121
|
+
def social_profiles=(social_profiles) #:nodoc:
|
122
|
+
@social_profiles = social_profiles.map { |account| SocialProfile.new(account) }.freeze
|
123
|
+
end
|
124
|
+
|
125
|
+
def location_data=(hash) #:nodoc:
|
126
|
+
@location_data = hash.freeze
|
127
|
+
end
|
128
|
+
|
129
|
+
def custom_data=(custom_data) #:nodoc:
|
130
|
+
@attributes["custom_data"] = ShallowHash.new.merge(custom_data)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|