elk 0.0.13 → 0.5.0

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.
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