simple_desk 0.4.0 → 1.0.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
  SHA1:
3
- metadata.gz: d55b96c5dfbfdddf6b0820c5007009fb9bc6a78f
4
- data.tar.gz: 84d1f3dd5cb416637b9bb1d04c50fd4d2941c900
3
+ metadata.gz: 09f1cada1f5f25fab3fc15174dba6053f6163470
4
+ data.tar.gz: 663bfb4bd57a06391d803ffe37ccee1a7287e4cb
5
5
  SHA512:
6
- metadata.gz: 0bd834ffbd274617379cabed8bc9d17f15063dac68299fbc2f15f9b51f1d4720de2393d67d1168259c666f87fc8331538beb2cf6008cc700474aa05214f7e52d
7
- data.tar.gz: 7a9b3a41b9d5441b2b250377fa26456aa6dfa3990759fcb9e78314a1e3b96180156c3cef159ed25bdd37b535a09bb0293545d1c5f29f28e221b5c9b2d7e9b847
6
+ metadata.gz: f97b3efc33a63428221a2ad789fe1376ca486fc920478ead81ed461125762c3ed427d985c207b8132683377eb40be0056b3f1d81c7b4e992835a892a115a641d
7
+ data.tar.gz: abc282a27a6c8124cf7a6eec42ada7234928d864201e6a6cb0b92033c50dd8a517030e3080b8cde616eeaccfd21f98949f2784d3f3d3bd83c44f1074079ca087
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 Elijah Murray
1
+ Copyright (c) 2014 John Gesimondo and Elijah Murray
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Build Status](https://travis-ci.org/getsimpledesk/simple_desk_gem.svg)](https://travis-ci.org/getsimpledesk/simple_desk_gem)
2
+
1
3
  # SimpleDesk
2
4
 
3
5
  [Simple Desk](https://www.getsimpledesk.com) is an SMS customer engagement platform that allows companies to have 2-way conversations with their customers over SMS - whether it's for sales, customer service, funnel abandonment, or transactional messages.
@@ -6,64 +8,102 @@
6
8
 
7
9
  Add this line to your application's Gemfile:
8
10
 
9
- gem 'simple_desk'
11
+ ```ruby
12
+ gem 'simple_desk'
13
+ ```
10
14
 
11
15
  And then execute:
12
16
 
13
17
  $ bundle
14
18
 
15
- Or install it yourself as:
19
+ ## Compatibility
20
+ Works with Ruby 1.9.1 or greater
21
+
22
+ ## Changes
23
+ See RELEASE.md
24
+
25
+ * Configuration is now done through an initializer
26
+ * Support for sandbox server
27
+ * When creating a customer, properties is no longer a separate param (see readme)
28
+
29
+
30
+ ## Setup
31
+ Initialize the gem by creating an initializer.
32
+
33
+ * Your production token can be found at https://www.getsimpledesk.com/api_info.
34
+ * Your sandbox token can be found at https://sandbox.getsimpledesk.com/api_info
16
35
 
17
- $ gem install simple_desk
36
+ ```ruby
37
+ # config/initializers/simple_desk.rb
38
+
39
+ SimpleDesk.configure do |config|
40
+ if Rails.env.production?
41
+ config.env = :live
42
+ config.token = ENV['SIMPLEDESK_PRODUCTION_TOKEN'] || 'YOUR_PRODUCTION_TOKEN'
43
+
44
+ elsif Rails.env.staging?
45
+ config.env = :sandbox
46
+ config.token = ENV['SIMPLEDESK_SANDBOX_TOKEN'] || 'YOUR_PRODUCTION_TOKEN'
47
+ end
48
+ end
49
+ ```
18
50
 
19
- Then add your API token to your `application_root/.env` file, or create one if you don't have it.
20
51
 
21
- SIMPLE_DESK_TOKEN=MY_TOKEN
22
52
 
23
53
  ## Usage
24
54
 
25
- ###**Adding Customers**
26
- To get started and add a new customer, run:
27
- SimpleDesk.add_customer({phone_number: "1231231232"})
28
-
29
- While `phone_number` is required, you can pass additional properties in:
30
- - phone_number (required)
31
- - email (optional)
32
- - first_name (optional)
33
- - last_name (optional)
34
-
35
- Like this:
36
-
37
- params = {phone_number: "1231231232", email: "elijah@example.com", first_name: "Elijah", last_name: "Murray"}
38
- SimpleDesk.add_customer(params)
39
-
40
- You can also add any amount of additional properties like so (using phone_number as the identifier):
41
-
42
- properties = {revenue_amount: "$100", location: "San Francisco"}
43
- SimpleDesk.add_customer({phone_number: "1231231232"}, properties)
44
-
45
- The gem will turn the properties into a Base64 encoded json object automatically.
46
-
47
- You can use params and properties in the same add_customer call too!
48
-
49
- ###**Messaging**
50
- To message a user the format is similar
51
- Note: They do not have to be existing in the system to message. You'll automatically create a new user if you message a new phone number
52
-
53
- message_and_phone_number = {to: 5551231234, text: "Howdy partner!"}
54
- SimpleDesk.message_customer(message_and_phone_number)
55
-
56
- ## To Do List
57
-
58
- Features that still need to be implemented
59
-
60
- - Add ability to pass in properties and convert to base 64
61
- - Add auto capitalization for names
62
- - Parse formatting for phone number
63
- - Update readme to explain setting up [IFTTT](https://ifttt.com/recipes/1110-send-an-sms-when-a-new-gmail-is-from-a-specific-email-address)
55
+ The API currently allows sending messages and adding customers.
56
+
57
+ **Sending Messages**
58
+
59
+ ```ruby
60
+ SimpleDesk.message_customer(text: 'message text', to: '1234567890')
61
+ ```
62
+ The response is a `SimpleDesk::Message` object with the following accessors:
63
+
64
+ * to (phone number as string)
65
+ * text
66
+ * status
67
+
68
+ Status is one of "queued" or "unsubscribed". Messages with "queued" status are usually sent within seconds. Messages with "unsubscribed" status will not be sent, as customer has previously unsubscribed from API messages.
69
+
70
+ If you send a message to a new phone number the API will automatically create a new user.
71
+
72
+ #<SimpleDesk::Message to="1234567890", text="content!", status="queued">
73
+
74
+ **Adding Customers**
75
+
76
+ If a customer already exists with the given phone number, that customer will be updated.
77
+
78
+ ```ruby
79
+ SimpleDesk.add_customer(
80
+ phone_number: "5555555555",
81
+ email: "user@example.com",
82
+ first_name: "john",
83
+ last_name: "doe",
84
+ properties: { great_customer: "true" }
85
+ )
86
+ ```
87
+ You can send an unlimited number of properties with arbitrary keys and values.
88
+
89
+ The response is a `SimpleDesk::Customer` object with the following accessors:
90
+
91
+ * id
92
+ * phone_number (string)
93
+ * email
94
+ * first_name
95
+ * last_name
96
+ * subscribed (boolean)
97
+ * properties (hash)
98
+
99
+
100
+ ## Support
101
+ Email api-help@getsimpledesk.com if you are having issues with the gem or service.
64
102
 
65
103
  ## Contributing
66
104
 
105
+ Please file an issue on Github and have a conversation with us before creating a pull request
106
+
67
107
  1. Fork it ( https://github.com/[my-github-username]/simple_desk/fork )
68
108
  2. Create your feature branch (`git checkout -b my-new-feature`)
69
109
  3. Commit your changes (`git commit -am 'Add some feature'`)
data/RELEASE.md CHANGED
@@ -1,3 +1,9 @@
1
+ v 1.0.0
2
+ -------
3
+ Configuration is now done through an initializer
4
+ Support for sandbox server
5
+ When creating a customer, properties is no longer a separate param (see readme)
6
+
1
7
  v 0.3.4
2
8
  -------
3
9
  Added ability to send properties
data/Rakefile CHANGED
@@ -1,2 +1,7 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
2
3
 
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
7
+ task :test => :spec
@@ -0,0 +1,24 @@
1
+ module SimpleDesk
2
+ module Client
3
+ def self.post(url, payload, headers={}, &block)
4
+ RestClient::Request.execute(method: :post, url: url, payload: payload, headers: headers,
5
+ open_timeout: 2, timeout: 4, &block)
6
+
7
+ rescue Errno::ECONNREFUSED => e
8
+ raise ConnectionRefused.new(e)
9
+
10
+ rescue RestClient::RequestTimeout => e
11
+ raise RequestTimeout.new(e)
12
+
13
+ rescue RestClient::Exception => e
14
+ if e.http_code == 400
15
+ raise BadRequest.new(e)
16
+ else
17
+ response = e.response && JSON.parse(e.response) || {}
18
+ error = response["error"]
19
+ exception = error && Exceptions::EXCEPTIONS_MAP[error].new(e) || Exception::UnknownRequestError.new(e)
20
+ raise exception
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,32 @@
1
+ require "yaml"
2
+
3
+ module SimpleDesk
4
+ class Configuration
5
+ ENV_URLS = YAML.load_file(File.expand_path('../endpoints.yml', __FILE__))
6
+ ALLOWED_ENVS = ENV_URLS.keys
7
+
8
+ attr_writer :token
9
+
10
+ def env
11
+ @env || :sandbox
12
+ end
13
+
14
+ def token
15
+ @token || raise(SimpleDesk::ConfigurationError.new('You need to set your token, see SimpleDesk Readme'))
16
+ end
17
+
18
+ def env=(env_sym)
19
+ if ALLOWED_ENVS.include?(env_sym.to_s)
20
+ @env = env_sym.to_s
21
+ else
22
+ raise SimpleDesk::ConfigurationError.new("You attempted to set Simpledesk env to #{env_sym}. Should be one of #{env_choices}")
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def env_choices
29
+ (ALLOWED_ENVS - ['local']).join(', ')
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,11 @@
1
+ local:
2
+ messages: http://localhost:3000/api/v1/messages
3
+ customers: http://localhost:3000/api/v1/customers
4
+
5
+ sandbox:
6
+ messages: https://sandbox.getsimpledesk.com/api/v1/messages
7
+ customers: https://sandbox.getsimpledesk.com/api/v1/customers
8
+
9
+ live:
10
+ messages: https://www.getsimpledesk.com/api/v1/messages
11
+ customers: https://www.getsimpledesk.com/api/v1/customers
@@ -0,0 +1,52 @@
1
+ require 'ostruct'
2
+
3
+ module SimpleDesk
4
+ class Exception < RuntimeError;end
5
+ class ConfigurationError < Exception; end
6
+
7
+ class RequestException < Exception
8
+ def initialize(original_exception)
9
+ @original_exception = original_exception
10
+ end
11
+
12
+ def inspect
13
+ self.class.name
14
+ end
15
+
16
+ def to_s
17
+ inspect
18
+ end
19
+ end
20
+
21
+ class BadRequest < RequestException
22
+ def initialize(original_exception)
23
+ @original_exception = original_exception
24
+ end
25
+
26
+ def inspect
27
+ @original_exception.inspect
28
+ end
29
+
30
+ def to_s
31
+ inspect
32
+ end
33
+ end
34
+
35
+ class BadToken < RequestException; end
36
+ class NoActiveSubscription < RequestException; end
37
+ class ApiDisabledForCompany < RequestException; end
38
+ class UnknownRequestError < RequestException; end
39
+ class RequestTimeout < RequestException; end
40
+ class ConnectionRefused < RequestException; end
41
+
42
+ class Customer < OpenStruct; end
43
+ class Message < OpenStruct; end
44
+
45
+ module Exceptions
46
+ EXCEPTIONS_MAP = {
47
+ "Bad Token" => BadToken,
48
+ "No Active Subscription" => NoActiveSubscription,
49
+ "Api Disabled For Company" => ApiDisabledForCompany
50
+ }
51
+ end
52
+ end
@@ -1,3 +1,3 @@
1
1
  module SimpleDesk
2
- VERSION = "0.4.0"
2
+ VERSION = "1.0.0"
3
3
  end
data/lib/simple_desk.rb CHANGED
@@ -1,64 +1,38 @@
1
1
  require "simple_desk/version"
2
- require "net/http"
3
- require "uri"
2
+ require "simple_desk/configuration"
3
+ require "simple_desk/exceptions"
4
+ require "simple_desk/client"
5
+ require "rest_client"
6
+ require "ostruct"
7
+ require "json"
4
8
 
5
9
  module SimpleDesk
6
- BASE_URL = "https://www.getsimpledesk.com"
10
+ extend self
7
11
 
8
- def self.add_customer(params, customer_properties)
9
- unless customer_properties.blank?
10
- props = Base64.urlsafe_encode64(customer_properties.to_json)
11
- params.merge(properties: props)
12
- end
13
- url = URI.parse(post_url("add_customer"))
14
- req = Net::HTTP::Post.new(url.request_uri)
15
- req.set_form_data(params)
16
- http = Net::HTTP.new(url.host, url.port)
17
- http.use_ssl = true
18
- response = http.request(req)
19
- end
20
- # alias_method :update_customer, :add_customer
12
+ def configure
13
+ yield @config ||= Configuration.new
14
+ end
21
15
 
22
- def self.message_customer(message_and_phone_number)
23
- url = URI.parse(post_url("message_customer"))
24
- req = Net::HTTP::Post.new(url.request_uri)
25
- req.set_form_data(message_and_phone_number)
26
- http = Net::HTTP.new(url.host, url.port)
27
- http.use_ssl = true
28
- response = http.request(req)
29
- end
16
+ def add_customer(params)
17
+ resp = Client.post url_for(:customers), params, headers
18
+ Customer.new(JSON.parse(resp))
19
+ end
30
20
 
31
- def self.message_customer(message_and_phone_number)
32
- url = URI.parse(post_url("message_customer"))
33
- req = Net::HTTP::Post.new(url.request_uri)
34
- req.set_form_data(message_and_phone_number)
35
- http = Net::HTTP.new(url.host, url.port)
36
- http.use_ssl = true
37
- response = http.request(req)
21
+ def message_customer(params)
22
+ resp = Client.post url_for(:messages), params, headers
23
+ Message.new(JSON.parse(resp))
38
24
  end
39
25
 
40
26
  private
41
- def self.build_url(post_type = nil, params=nil)
42
- url = post_url(post_type)
43
-
44
- url << string
45
- url = url[0...-1] if (url[-1] == '&')
46
- end
47
27
 
48
- return url
49
- end
28
+ attr_reader :config
50
29
 
51
- def self.post_url(post_type)
52
- if post_type == nil
53
- "#{BASE_URL}?token=#{ENV['SIMPLE_DESK_TOKEN'] || CONFIG['simple_desk_token']}"
54
- else
55
- case post_type
56
- when "message_customer"
57
- "#{BASE_URL}/api_send_message?token=#{ENV['SIMPLE_DESK_TOKEN'] || CONFIG['simple_desk_token']}"
58
- when "add_customer" || "update_customer"
59
- "#{BASE_URL}/api_add_customer?token=#{ENV['SIMPLE_DESK_TOKEN'] || CONFIG['simple_desk_token']}"
60
- end
61
- end
62
- end
30
+ def headers
31
+ { token: config.token, client: "rubygem #{SimpleDesk::VERSION}" }
32
+ end
63
33
 
34
+ def url_for(key)
35
+ Configuration::ENV_URLS[config.env.to_s][key.to_s]
36
+ end
64
37
  end
38
+
data/simple_desk.gemspec CHANGED
@@ -6,11 +6,11 @@ require 'simple_desk/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "simple_desk"
8
8
  spec.version = SimpleDesk::VERSION
9
- spec.authors = ["Elijah Murray"]
10
- spec.email = ["elijah@bluefantail.com"]
11
- spec.summary = %q{Provides a clean and simple gem to connect to Simple Desk}
12
- spec.description = %q{}
13
- spec.homepage = "http://elijahish.com"
9
+ spec.authors = ["John Gesimondo", "Elijah Murray"]
10
+ spec.email = ["john@jmondo.com", "elijah@bluefantail.com"]
11
+ spec.summary = %q{Provides a clean and simple gem to connect to Simpledesk}
12
+ spec.description = ""
13
+ spec.homepage = "http://github.com/getsimpledesk/simple_desk_gem"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
@@ -18,8 +18,11 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "rspec"
22
- spec.add_development_dependency "pry"
23
- spec.add_development_dependency "bundler", "~> 1.6"
24
- spec.add_development_dependency "rake"
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", "~> 3.0"
24
+ spec.add_development_dependency "vcr", "~> 2.6"
25
+ spec.add_development_dependency "webmock", "~> 1.1"
26
+
27
+ spec.add_runtime_dependency "rest-client", '~> 1.7'
25
28
  end
@@ -0,0 +1,167 @@
1
+ require 'spec_helper'
2
+ require 'vcr'
3
+
4
+ VCR.configure do |c|
5
+ c.cassette_library_dir = 'spec/vcr_cassettes'
6
+ c.hook_into :webmock # or :fakeweb
7
+ end
8
+
9
+ describe 'SimpleDesk' do
10
+ describe '.configure' do
11
+ context 'token' do
12
+ it 'has a setter' do
13
+ SimpleDesk.configure do |config|
14
+ config.token = 'YOUR_PRODUCTION_TOKEN'
15
+ end
16
+ end
17
+ end
18
+
19
+ context 'env' do
20
+ it 'has a setter' do
21
+ SimpleDesk.configure do |config|
22
+ config.env = :live
23
+ end
24
+ end
25
+
26
+ it 'raises an error if not an allowed option' do
27
+ expect { SimpleDesk.configure do |config|
28
+ config.env = :bogus_env
29
+ end }.to raise_error(SimpleDesk::ConfigurationError)
30
+ end
31
+ end
32
+ end
33
+
34
+ shared_examples "a mature, error handling gem" do |context|
35
+ context 'with an invalid token' do
36
+ let(:token) { 'FAKE_TOKEN' }
37
+
38
+ it 'raises a BadToken error' do
39
+ VCR.use_cassette("#{cassette_group}_bad_token") do
40
+ expect { response }.to raise_error(SimpleDesk::BadToken, 'SimpleDesk::BadToken')
41
+ end
42
+ end
43
+ end
44
+
45
+ context 'with an inactive subscription' do
46
+ let(:token) { 'tKux9Vwkt0UuTVJqGUO80MGJHCAeebpe' }
47
+
48
+ it 'raises a BadToken error' do
49
+ VCR.use_cassette("#{cassette_group}_no_subscription") do
50
+ expect { response }.to raise_error(SimpleDesk::NoActiveSubscription, 'SimpleDesk::NoActiveSubscription')
51
+ end
52
+ end
53
+ end
54
+
55
+ context 'with disabled API' do
56
+ let(:token) { 'ts9mOO_O5Dc7TOBaEAQym-00RGEl3Uel' }
57
+
58
+ it 'raises a BadToken error' do
59
+ VCR.use_cassette("#{cassette_group}_api_disabled") do
60
+ expect { response }.to raise_error(SimpleDesk::ApiDisabledForCompany, 'SimpleDesk::ApiDisabledForCompany')
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ describe '.add_customer' do
67
+ before do
68
+ SimpleDesk.configure do |config|
69
+ config.token = token
70
+ config.env = :local
71
+ end
72
+ end
73
+
74
+ let(:cassette_group) { "add_customer" }
75
+ let(:response) { SimpleDesk.add_customer(params) }
76
+ let(:token) { '3Z9L8xFjeNmXL7Yn-pFJUBoxkVWBbl5o' }
77
+ let(:params) do
78
+ { phone_number: "5555555557",
79
+ email: "user@example.com",
80
+ first_name: "john",
81
+ last_name: "doe",
82
+ properties: { great_customer: "true" } }
83
+ end
84
+
85
+ it_behaves_like "a mature, error handling gem"
86
+
87
+ context 'with invalid params' do
88
+ let(:params) do
89
+ { phone_numbah: "5555555558" }
90
+ end
91
+
92
+ it 'raises a BadRequest error with hint' do
93
+ VCR.use_cassette("add_customer_bad_params") do
94
+ expect { response }.to raise_error(SimpleDesk::BadRequest,
95
+ '400 Bad Request: {"error":"phone_number is missing"}')
96
+ end
97
+ end
98
+ end
99
+
100
+ context 'with proper params, active subscription' do
101
+ it 'returns a new customer' do
102
+ VCR.use_cassette('add_customer') do
103
+ expect(response).to be_a(SimpleDesk::Customer)
104
+ end
105
+ end
106
+
107
+ it 'includes the expected attributes' do
108
+ VCR.use_cassette('add_customer') do
109
+ customer = response
110
+ expect(customer.phone_number).to eq("5555555557")
111
+ expect(customer.email).to eq("user@example.com")
112
+ expect(customer.first_name).to eq("john")
113
+ expect(customer.last_name).to eq("doe")
114
+ expect(customer.properties).to eq({ "great_customer" => "true" })
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ describe '.message_customer' do
121
+ before do
122
+ SimpleDesk.configure do |config|
123
+ config.token = token
124
+ config.env = :local
125
+ end
126
+ end
127
+
128
+ let(:cassette_group) { "message_customer" }
129
+ let(:response) { SimpleDesk.message_customer(params) }
130
+ let(:token) { '3Z9L8xFjeNmXL7Yn-pFJUBoxkVWBbl5o' }
131
+ let(:params) do
132
+ { to: "5555555557", text: "this is the message text" }
133
+ end
134
+
135
+ it_behaves_like "a mature, error handling gem"
136
+
137
+ context 'with invalid params' do
138
+ let(:params) do
139
+ { toz: "5555555558" }
140
+ end
141
+
142
+ it 'raises a BadRequest error with hint' do
143
+ VCR.use_cassette("message_customer_bad_params") do
144
+ expect { response }.to raise_error(SimpleDesk::BadRequest,
145
+ '400 Bad Request: {"error":"text is missing, to is missing"}')
146
+ end
147
+ end
148
+ end
149
+
150
+ context 'with proper params, active subscription' do
151
+ it 'returns a new customer' do
152
+ VCR.use_cassette('message_customer') do
153
+ expect(response).to be_a(SimpleDesk::Message)
154
+ end
155
+ end
156
+
157
+ it 'includes the expected attributes' do
158
+ VCR.use_cassette('message_customer') do
159
+ message = response
160
+ expect(message.to).to eq("5555555557")
161
+ expect(message.text).to eq("this is the message text")
162
+ expect(message.status).to eq("queued")
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,11 @@
1
- require 'bundler/setup'
2
- Bundler.setup
3
-
4
- require 'simple_desk' # and any other gems you need
5
- require 'pry'
1
+ require 'simple_desk'
6
2
 
7
3
  RSpec.configure do |config|
8
- # some (optional) config here
9
- end
4
+ config.expect_with :rspec do |expectations|
5
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
6
+ end
7
+
8
+ config.mock_with :rspec do |mocks|
9
+ mocks.verify_partial_doubles = true
10
+ end
11
+ end