elk 0.0.13 → 0.5.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: f9d07160f26139ffd604d4d542016dfe0911d1a3
4
- data.tar.gz: a0b60c90d7064577049183ef23c1df315210ab3f
3
+ metadata.gz: e3184044f09e7d64a7822c28eaa6e3de56978fc9
4
+ data.tar.gz: db5a2368596d235da746132e3dae9e03dd56adf2
5
5
  SHA512:
6
- metadata.gz: f23acab93fb2c7007d71ca1b9dedf74496f620c597f9660b2acdb04b00d5a90de2b454dad58719c0e5711f30b52a4dfcea44e952654ce2b45ed5d1482b03c6d8
7
- data.tar.gz: 7de8a02ad30e5df2034a445bc6deff74a786cd43a203e86eecb94a06f35aa28fbd83a3968f07e4642f85837056deed5f02bb983b98033f2b0c7f4f318560012c
6
+ metadata.gz: d0ced3eef3b56b1225c8c1d92acf8a8a6f428f5105aa2e4a33e666a37c0db058d0bb0fc4348eea2d28232d4960944563aa1bc028ce1bb4e51f8c0cb60bdb4620
7
+ data.tar.gz: eeeec30f922cc461df8d750621b6c34a62097286848e7477bbef10e490e5af5cedad303355984529971a008a0fb866e72488eaa550da379deec663c4c7ca38c7
data/README.MD CHANGED
@@ -1,12 +1,14 @@
1
1
  # Elk - 46elks API-client
2
2
 
3
+ [![Build Status](https://travis-ci.org/jage/elk.svg?branch=master)](https://travis-ci.org/jage/elk)
4
+ [![Code Climate](https://codeclimate.com/github/jage/elk/badges/gpa.svg)](https://codeclimate.com/github/jage/elk)
5
+
3
6
  Ruby client for 46elks "Voice, SMS & MMS" service. http://46elks.com/
4
7
  At the moment the API only supports sending SMS messages.
5
8
 
6
9
  ## Requirements
7
10
 
8
- This gem is only supported on Ruby 1.9 and 2.0.
9
-
11
+ * Modern Ruby: >= 1.9
10
12
  * API account at 46elks.com
11
13
 
12
14
  ## Install
@@ -21,7 +23,11 @@ The source for Elk is available on Github:
21
23
 
22
24
  https://github.com/jage/elk
23
25
 
24
- elk uses rspec and webmock for testing, do a `bundle install` for all the development requirements.
26
+ Elk uses rspec and webmock for testing, do a `bundle install` for all the development requirements.
27
+
28
+ Test specs with:
29
+
30
+ bundle exec rake spec
25
31
 
26
32
  ## Usage
27
33
 
@@ -32,12 +38,32 @@ elk can be used to allocate a phone numbers, manage the numbers and send/recieve
32
38
  First thing when using elk is to set the authentication parameters
33
39
 
34
40
  ```Ruby
35
- require 'elk'
41
+ require "elk"
36
42
 
37
43
  Elk.configure do |config|
38
- config.username = 'USERNAME'
39
- config.password = 'PASSWORD'
44
+ config.username = "USERNAME"
45
+ config.password = "PASSWORD"
46
+ end
47
+ ```
48
+
49
+ It is possible to avoid the singleton configuration:
50
+
51
+ ```Ruby
52
+ require "elk"
53
+
54
+ client = Elk::Client.new
55
+ client.configure do |config|
56
+ config.username = "USERNAME"
57
+ config.password = "PASSWORD"
40
58
  end
59
+
60
+ # Then pass client to the class methods
61
+ numbers = Elk::Number.all(client: client)
62
+ # => [#<Elk::Number ...>, #<Elk::Number ...>]
63
+
64
+
65
+ Elk::SMS.send(client: client, from: "MyService", to: "+46704508449", message: "Your order #171 has now been sent!")
66
+ # => #<Elk::SMS:0x0000010179d7e8 @client=... @from="MyService", @to="+46704508449", @message="Your order #171 has now been sent!", @message_id="sdc39a7926d37159b6985283e32f43251", @created_at=2011-07-17 16:21:13 +0200, @loaded_at=2011-07-17 16:21:13 +0200>
41
67
  ```
42
68
 
43
69
  ### Numbers
@@ -45,7 +71,7 @@ end
45
71
  To be able to send and recieve messages, a number is needed. Several numbers can be allocated.
46
72
 
47
73
  ```Ruby
48
- number = Elk::Number.allocate(:sms_url => 'http://myservice.se/callback/newsms.php', :country => 'se')
74
+ number = Elk::Number.allocate(sms_url: "http://myservice.se/callback/newsms.php", country: "se")
49
75
  # => #<Elk::Number:0x0000010282aa70 @country="se", @sms_url="http://myservice.se/callback/newsms.php", @status="yes", @number_id="n03e7db70cc06c1ff85e09a2b3f86dd62", @number="+46766861034", @capabilities=[:sms], @loaded_at=2011-07-17 15:23:55 +0200>
50
76
  ```
51
77
 
@@ -59,7 +85,7 @@ numbers = Elk::Number.all
59
85
  Change number settings
60
86
 
61
87
  ```Ruby
62
- number.sms_url = 'http://myservice.se/callback/newsms.php'
88
+ number.sms_url = "http://myservice.se/callback/newsms.php"
63
89
  number.save
64
90
  # => true
65
91
  ```
@@ -79,7 +105,7 @@ number.status
79
105
  Send SMS. Messages can be sent from one of the allocated numbers or an arbitrary alphanumeric string of at most 11 characters.
80
106
 
81
107
  ```Ruby
82
- Elk::SMS.send(:from => 'MyService', :to => '+46704508449', :message => 'Your order #171 has now been sent!')
108
+ Elk::SMS.send(from: "MyService", to: "+46704508449", message: "Your order #171 has now been sent!")
83
109
  # => #<Elk::SMS:0x0000010179d7e8 @from="MyService", @to="+46704508449", @message="Your order #171 has now been sent!", @message_id="sdc39a7926d37159b6985283e32f43251", @created_at=2011-07-17 16:21:13 +0200, @loaded_at=2011-07-17 16:21:13 +0200>
84
110
  ```
85
111
 
@@ -87,8 +113,8 @@ Receiving SMS does not require Elk, but should be of interest anyway.
87
113
  Example with Sinatra:
88
114
 
89
115
  ```Ruby
90
- post '/receive' do
91
- if request.params['message'] == 'Hello'
116
+ post "/receive" do
117
+ if request.params["message"] == "Hello"
92
118
  # Sends a return SMS with message "world!"
93
119
  "world!"
94
120
  end
@@ -104,4 +130,4 @@ Elk::SMS.all
104
130
 
105
131
  ## Copyright
106
132
 
107
- Copyright (c) 2011 Johan Eckerström. See LICENSE for details.
133
+ Copyright (c) 2011 Johan Eckerström. See [MIT-LICENSE](MIT-LICENSE) for details.
data/lib/elk.rb CHANGED
@@ -1,93 +1,49 @@
1
- # External
2
- require 'multi_json'
3
- require 'open-uri'
4
- require 'rest_client'
5
- require 'time'
1
+ require "forwardable"
6
2
 
7
3
  # Base module
8
4
  # Used for to configure username and password through Elk.configure
9
5
  module Elk
10
- # Base domain for 46elks API
11
- BASE_DOMAIN = 'api.46elks.com'
12
- # API version supported
13
- API_VERSION = 'a1'
14
-
15
- # When the authentication can't be done
16
- class AuthError < RuntimeError; end
17
- # Raised when the API server isn't working
18
- class ServerError < RuntimeError; end
19
- # Generic exception when 46elks API gives a response Elk can't parse
20
- class BadResponse < RuntimeError; end
21
- # Generic exception when Elk calls 46elk API the wrong way
22
- class BadRequest < RuntimeError; end
23
- # Raised when required paremeters are omitted
24
- class MissingParameter < RuntimeError; end
25
-
26
6
  class << self
27
- # API Username from 46elks.com
28
- attr_accessor :username
29
- # API Password from 46elks.com
30
- attr_accessor :password
31
- # Defaults to Elk::BASE_DOMAIN, but can be overriden for testing
32
- attr_accessor :base_domain
7
+ extend Forwardable
8
+
9
+ # Delegate methods to client
10
+ delegated_methods = [
11
+ :username,
12
+ :username=,
13
+ :password,
14
+ :password=,
15
+ :base_domain,
16
+ :base_url,
17
+ :get,
18
+ :post,
19
+ :execute,
20
+ ]
21
+
22
+ delegated_methods.each do |method|
23
+ def_delegator :client, method
24
+ end
33
25
 
34
26
  # Set up authentication credentials, has to be done before using Elk::Number and Elk::SMS
35
27
  #
36
28
  # Elk.configure do |config|
37
- # config.username = 'USERNAME'
38
- # config.password = 'PASSWORD
29
+ # config.username = "USERNAME"
30
+ # config.password = "PASSWORD"
39
31
  # end
40
32
  def configure
41
- yield self
42
- end
43
-
44
- # Base URL used for calling 46elks API
45
- def base_url
46
- if not username or not password
47
- raise AuthError, "API username and password required"
48
- end
49
-
50
- "https://#{username}:#{password}@#{(base_domain || BASE_DOMAIN)}/#{API_VERSION}"
51
- end
52
-
53
- # Wrapper for Elk.execute(:get)
54
- def get(path, parameters = {})
55
- execute(:get, path, parameters)
56
- end
57
-
58
- # Wrapper for Elk::execute(:post)
59
- def post(path, parameters = {})
60
- execute(:post, path, parameters)
61
- end
62
-
63
- # Wrapper around RestClient::RestClient.execute
64
- #
65
- # * Sets accept header to json
66
- # * Handles some exceptions
67
- #
68
- def execute(method, path, parameters, headers={:accept => :json}, &block)
69
- payload = {}.merge(parameters)
70
- url = base_url + path
71
- RestClient::Request.execute(:method => method, :url => url, :payload => payload, :headers => headers, &block)
72
- rescue RestClient::Unauthorized
73
- raise AuthError, "Authentication failed"
74
- rescue RestClient::InternalServerError
75
- raise ServerError, "Server error"
76
- rescue RestClient::Forbidden => e
77
- raise BadRequest, e.http_body
33
+ yield client
78
34
  end
79
35
 
80
- # Wrapper around MultiJson.load, symbolize names
81
- def parse_json(body)
82
- MultiJson.load(body, :symbolize_keys => true)
83
- rescue MultiJson::DecodeError
84
- raise BadResponse, "Can't parse JSON"
36
+ # Not thread safe
37
+ def client
38
+ @client ||= Client.new
85
39
  end
86
40
  end
87
41
  end
88
42
 
89
43
  # Internal
90
- require 'elk/util'
91
- require 'elk/version'
92
- require 'elk/number'
93
- require 'elk/sms'
44
+ require_relative "elk/util"
45
+ require_relative "elk/error"
46
+ require_relative "elk/version"
47
+ require_relative "elk/client"
48
+ require_relative "elk/number"
49
+ require_relative "elk/sms"
@@ -0,0 +1,77 @@
1
+ require "rest_client"
2
+
3
+ module Elk
4
+ class Client
5
+ # Base domain for 46elks API
6
+ BASE_DOMAIN = "api.46elks.com"
7
+ # API version supported
8
+ API_VERSION = "a1"
9
+
10
+ # API Username from 46elks.com
11
+ attr_accessor :username
12
+ # API Password from 46elks.com
13
+ attr_accessor :password
14
+ # Used to overrid Elk::BASE_DOMAIN (in tests)
15
+ attr_accessor :base_domain
16
+
17
+ def initialize(parameters = {})
18
+ @username = parameters[:username]
19
+ @password = parameters[:password]
20
+ end
21
+
22
+ # Set authentication credentials
23
+ #
24
+ # client = Elk::Client.new
25
+ # client.configure do |config|
26
+ # config.username = "USERNAME"
27
+ # config.password = "PASSWORD"
28
+ # end
29
+ def configure
30
+ yield self
31
+ end
32
+
33
+ # Base URL used for calling 46elks API
34
+ def base_url
35
+ unless username && password
36
+ raise AuthError, "API username and password required"
37
+ end
38
+
39
+ "https://#{username}:#{password}@#{(base_domain || BASE_DOMAIN)}/#{API_VERSION}"
40
+ end
41
+
42
+ # Wrapper for Elk.execute(:get)
43
+ def get(path, parameters = {})
44
+ execute(:get, path, parameters)
45
+ end
46
+
47
+ # Wrapper for Elk::execute(:post)
48
+ def post(path, parameters = {})
49
+ execute(:post, path, parameters)
50
+ end
51
+
52
+ # Wrapper around RestClient::RestClient.execute
53
+ #
54
+ # * Sets accept header to json
55
+ # * Handles some exceptions
56
+ #
57
+ def execute(method, path, parameters, headers = { accept: :json }, &block)
58
+ payload = {}.merge(parameters)
59
+ url = base_url + path
60
+
61
+ request_arguments = {
62
+ method: method,
63
+ url: url,
64
+ payload: payload,
65
+ headers: headers
66
+ }
67
+
68
+ RestClient::Request.execute(request_arguments, &block)
69
+ rescue RestClient::Unauthorized
70
+ raise AuthError, "Authentication failed"
71
+ rescue RestClient::InternalServerError
72
+ raise ServerError, "Server error"
73
+ rescue RestClient::Forbidden => e
74
+ raise BadRequest, e.http_body
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,16 @@
1
+ module Elk
2
+ # When the authentication can't be done
3
+ class AuthError < RuntimeError; end
4
+
5
+ # Raised when the API server isn't working
6
+ class ServerError < RuntimeError; end
7
+
8
+ # Generic exception when 46elks API gives a response Elk can't parse
9
+ class BadResponse < RuntimeError; end
10
+
11
+ # Generic exception when Elk calls 46elk API the wrong way
12
+ class BadRequest < RuntimeError; end
13
+
14
+ # Raised when required paremeters are omitted
15
+ class MissingParameter < RuntimeError; end
16
+ end
@@ -1,7 +1,9 @@
1
+ require "time"
2
+
1
3
  module Elk
2
4
  # Allocate and manage numbers used for SMS/MMS/Voice
3
5
  class Number
4
- attr_reader :number_id, :number, :capabilities, :loaded_at #:nodoc:
6
+ attr_reader :number_id, :number, :capabilities, :loaded_at, :client #:nodoc:
5
7
  attr_accessor :country, :sms_url, :voice_start_url #:nodoc:
6
8
 
7
9
  def initialize(parameters) #:nodoc:
@@ -15,16 +17,17 @@ module Elk
15
17
  @status = parameters[:active]
16
18
  @number_id = parameters[:id]
17
19
  @number = parameters[:number]
18
- @capabilities = parameters[:capabilities].collect {|c| c.to_sym }
20
+ @capabilities = Array(parameters[:capabilities]).map(&:to_sym)
19
21
  @loaded_at = Time.now
22
+ @client = parameters.fetch(:client) { Elk.client }
20
23
  end
21
24
 
22
25
  # Status of a number, if it's :active or :deallocated
23
26
  def status
24
27
  case @status
25
- when 'yes'
28
+ when "yes"
26
29
  :active
27
- when 'no'
30
+ when "no"
28
31
  :deallocated
29
32
  else
30
33
  nil
@@ -33,26 +36,30 @@ module Elk
33
36
 
34
37
  # Reloads a number from the API server
35
38
  def reload
36
- response = Elk.get("/Numbers/#{self.number_id}")
37
- self.set_paramaters(Elk.parse_json(response.body))
39
+ response = @client.get("/Numbers/#{self.number_id}")
40
+ self.set_paramaters(Elk::Util.parse_json(response.body))
38
41
  response.code == 200
39
42
  end
40
43
 
41
44
  # Updates or allocates a number
42
45
  def save
43
- attributes = {:sms_url => self.sms_url, :voice_start => self.voice_start_url}
46
+ attributes = {
47
+ sms_url: self.sms_url,
48
+ voice_start: self.voice_start_url
49
+ }
50
+
44
51
  # If new URL, send country, otherwise not
45
- if !self.number_id
52
+ unless self.number_id
46
53
  attributes[:country] = self.country
47
54
  end
48
- response = Elk.post("/Numbers/#{self.number_id}", attributes)
55
+ response = @client.post("/Numbers/#{self.number_id}", attributes)
49
56
  response.code == 200
50
57
  end
51
58
 
52
59
  # Deallocates a number, once allocated, a number cannot be used again, ever!
53
60
  def deallocate!
54
- response = Elk.post("/Numbers/#{self.number_id}", {:active => 'no'})
55
- self.set_paramaters(Elk.parse_json(response.body))
61
+ response = @client.post("/Numbers/#{self.number_id}", { active: "no" })
62
+ self.set_paramaters(Elk::Util.parse_json(response.body))
56
63
  response.code == 200
57
64
  end
58
65
 
@@ -62,19 +69,36 @@ module Elk
62
69
  # Allocates a phone number
63
70
  #
64
71
  # * Required parameters: :country
65
- # * Optional parameters: :sms_url, :voice_start_url
72
+ # * Optional parameters: :sms_url, :voice_start_url, :client
66
73
  def allocate(parameters)
67
74
  verify_parameters(parameters, [:country])
68
- response = Elk.post('/Numbers', parameters)
69
- self.new(Elk.parse_json(response.body))
75
+
76
+ client = parameters.fetch(:client) { Elk.client }
77
+
78
+ allowed_arguments = [:country, :sms_url, :voice_start_url]
79
+ arguments = parameters.dup.select do |key, _|
80
+ allowed_arguments.include?(key)
81
+ end
82
+
83
+ response = client.post('/Numbers', arguments)
84
+ self.new(Elk::Util.parse_json(response.body))
70
85
  end
71
86
 
72
87
  # Returns all Elk::Numbers, regardless of status (allocated/deallocated)
73
- def all
74
- response = Elk.get('/Numbers')
88
+ #
89
+ # Optional parameters
90
+ #
91
+ # * :client - Elk::Client instance
92
+ #
93
+ def all(parameters = {})
94
+ client = parameters.fetch(:client) { Elk.client }
95
+
96
+ response = client.get('/Numbers')
75
97
 
76
- Elk.parse_json(response.body)[:data].collect do |n|
77
- self.new(n)
98
+ numbers = Elk::Util.parse_json(response.body).fetch(:data)
99
+ numbers.map do |number|
100
+ number[:client] = client
101
+ self.new(number)
78
102
  end
79
103
  end
80
104
  end