elk 0.0.4 → 0.0.5
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/README.MD +0 -1
- data/lib/elk.rb +42 -6
- data/lib/elk/number.rb +23 -7
- data/lib/elk/sms.rb +12 -4
- data/spec/elk_spec.rb +26 -1
- data/spec/spec.opts +4 -0
- metadata +57 -99
data/README.MD
CHANGED
data/lib/elk.rb
CHANGED
@@ -3,42 +3,70 @@ require 'json/pure'
|
|
3
3
|
require 'open-uri'
|
4
4
|
require 'rest_client'
|
5
5
|
require 'time'
|
6
|
-
# Internal
|
7
|
-
require 'elk/number'
|
8
|
-
require 'elk/sms'
|
9
6
|
|
7
|
+
# Base module
|
8
|
+
# Used for to configure username and password through Elk.configure
|
10
9
|
module Elk
|
10
|
+
# Base domain for 46elks API
|
11
11
|
BASE_DOMAIN = 'api.46elks.com'
|
12
|
+
# API version supported
|
12
13
|
API_VERSION = 'a1'
|
13
|
-
|
14
|
+
# Elk version
|
15
|
+
VERSION = '0.0.5'
|
14
16
|
|
17
|
+
# When the authentication can't be done
|
15
18
|
class AuthError < RuntimeError; end
|
19
|
+
# Raised when the API server isn't working
|
16
20
|
class ServerError < RuntimeError; end
|
21
|
+
# Generic exception when 46elks API gives a response Elk can't parse
|
17
22
|
class BadResponse < RuntimeError; end
|
23
|
+
# Generic exception when Elk calls 46elk API the wrong way
|
18
24
|
class BadRequest < RuntimeError; end
|
25
|
+
# Raised when required paremeters are omitted
|
19
26
|
class MissingParameter < RuntimeError; end
|
20
27
|
|
21
28
|
class << self
|
29
|
+
# API Username from 46elks.com
|
22
30
|
attr_accessor :username
|
31
|
+
# API Password from 46elks.com
|
23
32
|
attr_accessor :password
|
33
|
+
# Defaults to Elk::BASE_DOMAIN, but can be overriden for testing
|
24
34
|
attr_accessor :base_domain
|
25
35
|
|
36
|
+
# Set up authentication credentials, has to be done before using Elk::Number and Elk::SMS
|
37
|
+
#
|
38
|
+
# Elk.configure do |config|
|
39
|
+
# config.username = 'USERNAME'
|
40
|
+
# config.password = 'PASSWORD
|
41
|
+
# end
|
26
42
|
def configure
|
27
43
|
yield self
|
28
44
|
end
|
29
45
|
|
46
|
+
# Base URL used for calling 46elks API
|
30
47
|
def base_url
|
48
|
+
if not username or not password
|
49
|
+
raise AuthError, "API username and password required"
|
50
|
+
end
|
51
|
+
|
31
52
|
"https://#{username}:#{password}@#{(base_domain || BASE_DOMAIN)}/#{API_VERSION}"
|
32
53
|
end
|
33
54
|
|
55
|
+
# Wrapper for Elk.execute(:get)
|
34
56
|
def get(path, parameters = {})
|
35
57
|
execute(:get, path, parameters)
|
36
58
|
end
|
37
59
|
|
60
|
+
# Wrapper for Elk::execute(:post)
|
38
61
|
def post(path, parameters = {})
|
39
62
|
execute(:post, path, parameters)
|
40
63
|
end
|
41
64
|
|
65
|
+
# Wrapper around RestClient::RestClient.execute
|
66
|
+
#
|
67
|
+
# * Sets accept header to json
|
68
|
+
# * Handles some exceptions
|
69
|
+
#
|
42
70
|
def execute(method, path, parameters, headers={:accept => :json}, &block)
|
43
71
|
payload = {}.merge(parameters)
|
44
72
|
url = base_url + path
|
@@ -51,6 +79,7 @@ module Elk
|
|
51
79
|
raise BadRequest, e.http_body
|
52
80
|
end
|
53
81
|
|
82
|
+
# Wrapper around JSON.parse, symbolize names
|
54
83
|
def parse_json(body)
|
55
84
|
JSON.parse(body, :symbolize_names => true)
|
56
85
|
rescue JSON::ParserError
|
@@ -59,10 +88,17 @@ module Elk
|
|
59
88
|
end
|
60
89
|
end
|
61
90
|
|
62
|
-
|
91
|
+
# --
|
92
|
+
# TODO: Not that nice to create methods in Hash
|
93
|
+
# --
|
94
|
+
class Hash #:nodoc: all
|
63
95
|
def require_keys!(required_keys)
|
64
96
|
unless (missing_parameters = required_keys - self.keys).empty?
|
65
97
|
raise Elk::MissingParameter, "Requires #{missing_parameters.collect {|s| ":#{s}"}.join(', ')} parameters"
|
66
98
|
end
|
67
99
|
end
|
68
|
-
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Internal
|
103
|
+
require 'elk/number'
|
104
|
+
require 'elk/sms'
|
data/lib/elk/number.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
module Elk
|
2
|
+
# Allocate and manage numbers used for SMS/MMS/Voice
|
2
3
|
class Number
|
3
|
-
attr_reader :number_id, :number, :capabilities, :loaded_at
|
4
|
-
attr_accessor :country, :sms_url
|
4
|
+
attr_reader :number_id, :number, :capabilities, :loaded_at #:nodoc:
|
5
|
+
attr_accessor :country, :sms_url, :voice_start_url #:nodoc:
|
5
6
|
|
6
|
-
def initialize(parameters)
|
7
|
+
def initialize(parameters) #:nodoc:
|
7
8
|
set_paramaters(parameters)
|
8
9
|
end
|
9
10
|
|
10
|
-
def set_paramaters(parameters)
|
11
|
+
def set_paramaters(parameters) #:nodoc:
|
11
12
|
@country = parameters[:country]
|
12
13
|
@sms_url = parameters[:sms_url]
|
14
|
+
@voice_start_url = parameters[:voice_start_url]
|
13
15
|
@status = parameters[:active]
|
14
16
|
@number_id = parameters[:id]
|
15
17
|
@number = parameters[:number]
|
@@ -17,6 +19,7 @@ module Elk
|
|
17
19
|
@loaded_at = Time.now
|
18
20
|
end
|
19
21
|
|
22
|
+
# Status of a number, if it's :active or :deallocated
|
20
23
|
def status
|
21
24
|
case @status
|
22
25
|
when 'yes'
|
@@ -28,30 +31,43 @@ module Elk
|
|
28
31
|
end
|
29
32
|
end
|
30
33
|
|
34
|
+
# Reloads a number from the API server
|
31
35
|
def reload
|
32
36
|
response = Elk.get("/Numbers/#{self.number_id}")
|
33
37
|
self.set_paramaters(Elk.parse_json(response.body))
|
34
38
|
response.code == 200
|
35
39
|
end
|
36
40
|
|
41
|
+
# Updates or allocates a number
|
37
42
|
def save
|
38
|
-
|
43
|
+
attributes = {:sms_url => self.sms_url, :voice_start => self.voice_start_url}
|
44
|
+
# If new URL, send country, otherwise not
|
45
|
+
if !self.number_id
|
46
|
+
attributes[:country] = self.country
|
47
|
+
end
|
48
|
+
response = Elk.post("/Numbers/#{self.number_id}", attributes)
|
39
49
|
response.code == 200
|
40
50
|
end
|
41
51
|
|
52
|
+
# Deallocates a number, once allocated, a number cannot be used again, ever!
|
42
53
|
def deallocate!
|
43
54
|
response = Elk.post("/Numbers/#{self.number_id}", {:active => 'no'})
|
44
|
-
|
55
|
+
self.set_paramaters(Elk.parse_json(response.body))
|
45
56
|
response.code == 200
|
46
57
|
end
|
47
58
|
|
48
59
|
class << self
|
60
|
+
# Allocates a phone number
|
61
|
+
#
|
62
|
+
# * Required parameters: :country
|
63
|
+
# * Optional parameters: :sms_url, :voice_start_url
|
49
64
|
def allocate(parameters)
|
50
|
-
parameters.require_keys!([:
|
65
|
+
parameters.require_keys!([:country])
|
51
66
|
response = Elk.post('/Numbers', parameters)
|
52
67
|
self.new(Elk.parse_json(response.body))
|
53
68
|
end
|
54
69
|
|
70
|
+
# Returns all Elk::Numbers, regardless of status (allocated/deallocated)
|
55
71
|
def all
|
56
72
|
response = Elk.get('/Numbers')
|
57
73
|
|
data/lib/elk/sms.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
module Elk
|
2
|
+
# Used to send SMS through 46elks SMS-gateway
|
2
3
|
class SMS
|
3
|
-
attr_reader :from, :to, :message, :message_id, :created_at, :loaded_at
|
4
|
+
attr_reader :from, :to, :message, :message_id, :created_at, :loaded_at #:nodoc:
|
4
5
|
|
5
|
-
def initialize(parameters)
|
6
|
+
def initialize(parameters) #:nodoc:
|
6
7
|
set_parameters(parameters)
|
7
8
|
end
|
8
9
|
|
9
|
-
def set_parameters(parameters)
|
10
|
+
def set_parameters(parameters) #:nodoc:
|
10
11
|
@from = parameters[:from]
|
11
12
|
@to = parameters[:to]
|
12
13
|
@message = parameters[:message]
|
@@ -15,6 +16,7 @@ module Elk
|
|
15
16
|
@loaded_at = Time.now
|
16
17
|
end
|
17
18
|
|
19
|
+
# Reloads a SMS from server
|
18
20
|
def reload
|
19
21
|
response = Elk.get("/SMS/#{self.message_id}")
|
20
22
|
self.set_parameters(Elk.parse_json(response.body))
|
@@ -22,6 +24,12 @@ module Elk
|
|
22
24
|
end
|
23
25
|
|
24
26
|
class << self
|
27
|
+
# Send SMS
|
28
|
+
# Required parameters
|
29
|
+
#
|
30
|
+
# * :from - Either the one of the allocated numbers or arbitrary alphanumeric string of at most 11 characters
|
31
|
+
# * :to - Any phone number capable of receiving SMS
|
32
|
+
# * :message - Any UTF-8 text Splitting and joining multi-part SMS messages are automatically handled by the API
|
25
33
|
def send(parameters)
|
26
34
|
parameters.require_keys!([:from, :message, :to])
|
27
35
|
|
@@ -34,13 +42,13 @@ module Elk
|
|
34
42
|
self.new(Elk.parse_json(response.body))
|
35
43
|
end
|
36
44
|
|
45
|
+
# Get sent and received messages. Limited by the API to 100 latest
|
37
46
|
def all
|
38
47
|
response = Elk.get('/SMS')
|
39
48
|
Elk.parse_json(response.body)[:smses].collect do |n|
|
40
49
|
self.new(n)
|
41
50
|
end
|
42
51
|
end
|
43
|
-
|
44
52
|
end
|
45
53
|
end
|
46
54
|
end
|
data/spec/elk_spec.rb
CHANGED
@@ -2,6 +2,31 @@ require 'spec_helper'
|
|
2
2
|
require 'elk'
|
3
3
|
|
4
4
|
describe Elk do
|
5
|
+
it 'should detect missing username and/or password' do
|
6
|
+
expect { Elk.base_url }.to raise_error(Elk::AuthError)
|
7
|
+
|
8
|
+
Elk.configure do |config|
|
9
|
+
config.username = nil
|
10
|
+
config.password = 'PASSWORD'
|
11
|
+
end
|
12
|
+
|
13
|
+
expect { Elk.base_url }.to raise_error(Elk::AuthError)
|
14
|
+
|
15
|
+
Elk.configure do |config|
|
16
|
+
config.username = 'USERNAME'
|
17
|
+
config.password = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
expect { Elk.base_url }.to raise_error(Elk::AuthError)
|
21
|
+
|
22
|
+
Elk.configure do |config|
|
23
|
+
config.username = 'USERNAME'
|
24
|
+
config.password = 'PASSWORD'
|
25
|
+
end
|
26
|
+
|
27
|
+
expect { Elk.base_url }.to_not raise_error(Elk::AuthError)
|
28
|
+
end
|
29
|
+
|
5
30
|
it 'should handle garbage json' do
|
6
31
|
bad_response_body = fixture('bad_response_body.txt').read
|
7
32
|
|
@@ -50,7 +75,7 @@ describe Elk do
|
|
50
75
|
with(:headers => {'Accept'=>'application/json'}).
|
51
76
|
to_return(fixture('gets_allocated_numbers.txt'))
|
52
77
|
stub_request(:post, "https://USERNAME:PASSWORD@api.46elks.com/a1/Numbers/nea19c8e291676fb7003fa1d63bba7899").
|
53
|
-
with(:body => {"
|
78
|
+
with(:body => {"sms_url" => "http://otherhost/receive", "voice_start" => ""},
|
54
79
|
:headers => {'Accept'=>'application/json', 'Content-Type'=>'application/x-www-form-urlencoded'}).
|
55
80
|
to_return(fixture('updates_a_number.txt'))
|
56
81
|
|
data/spec/spec.opts
ADDED
metadata
CHANGED
@@ -1,112 +1,79 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: elk
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 4
|
10
|
-
version: 0.0.4
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.5
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Johan Eckerstroem
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-10-20 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
22
15
|
name: json_pure
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &70113756837920 !ruby/object:Gem::Requirement
|
25
17
|
none: false
|
26
|
-
requirements:
|
18
|
+
requirements:
|
27
19
|
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
hash: 7
|
30
|
-
segments:
|
31
|
-
- 1
|
32
|
-
- 5
|
33
|
-
- 2
|
20
|
+
- !ruby/object:Gem::Version
|
34
21
|
version: 1.5.2
|
35
22
|
type: :runtime
|
36
|
-
version_requirements: *id001
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: rest-client
|
39
23
|
prerelease: false
|
40
|
-
|
24
|
+
version_requirements: *70113756837920
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rest-client
|
27
|
+
requirement: &70113756836920 !ruby/object:Gem::Requirement
|
41
28
|
none: false
|
42
|
-
requirements:
|
29
|
+
requirements:
|
43
30
|
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
hash: 9
|
46
|
-
segments:
|
47
|
-
- 1
|
48
|
-
- 6
|
49
|
-
- 3
|
31
|
+
- !ruby/object:Gem::Version
|
50
32
|
version: 1.6.3
|
51
33
|
type: :runtime
|
52
|
-
version_requirements: *id002
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
name: rake
|
55
34
|
prerelease: false
|
56
|
-
|
35
|
+
version_requirements: *70113756836920
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &70113756836380 !ruby/object:Gem::Requirement
|
57
39
|
none: false
|
58
|
-
requirements:
|
40
|
+
requirements:
|
59
41
|
- - ~>
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
hash: 63
|
62
|
-
segments:
|
63
|
-
- 0
|
64
|
-
- 9
|
65
|
-
- 2
|
42
|
+
- !ruby/object:Gem::Version
|
66
43
|
version: 0.9.2
|
67
44
|
type: :development
|
68
|
-
version_requirements: *id003
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: rspec
|
71
45
|
prerelease: false
|
72
|
-
|
46
|
+
version_requirements: *70113756836380
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rspec
|
49
|
+
requirement: &70113756835800 !ruby/object:Gem::Requirement
|
73
50
|
none: false
|
74
|
-
requirements:
|
51
|
+
requirements:
|
75
52
|
- - ~>
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
hash: 23
|
78
|
-
segments:
|
79
|
-
- 2
|
80
|
-
- 6
|
81
|
-
- 0
|
53
|
+
- !ruby/object:Gem::Version
|
82
54
|
version: 2.6.0
|
83
55
|
type: :development
|
84
|
-
version_requirements: *id004
|
85
|
-
- !ruby/object:Gem::Dependency
|
86
|
-
name: webmock
|
87
56
|
prerelease: false
|
88
|
-
|
57
|
+
version_requirements: *70113756835800
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: webmock
|
60
|
+
requirement: &70113756835100 !ruby/object:Gem::Requirement
|
89
61
|
none: false
|
90
|
-
requirements:
|
62
|
+
requirements:
|
91
63
|
- - ~>
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
hash: 7
|
94
|
-
segments:
|
95
|
-
- 1
|
96
|
-
- 6
|
97
|
-
- 4
|
64
|
+
- !ruby/object:Gem::Version
|
98
65
|
version: 1.6.4
|
99
66
|
type: :development
|
100
|
-
|
101
|
-
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70113756835100
|
69
|
+
description: Elk can be used to allocate a phone numbers, manage the numbers and send
|
70
|
+
SMS through these numbers.
|
102
71
|
email: johan@duh.se
|
103
72
|
executables: []
|
104
|
-
|
105
73
|
extensions: []
|
106
|
-
|
107
|
-
extra_rdoc_files:
|
74
|
+
extra_rdoc_files:
|
108
75
|
- README.MD
|
109
|
-
files:
|
76
|
+
files:
|
110
77
|
- lib/elk/number.rb
|
111
78
|
- lib/elk/sms.rb
|
112
79
|
- lib/elk.rb
|
@@ -125,41 +92,32 @@ files:
|
|
125
92
|
- spec/fixtures/server_error.txt
|
126
93
|
- spec/fixtures/sms_history.txt
|
127
94
|
- spec/fixtures/updates_a_number.txt
|
95
|
+
- spec/spec.opts
|
128
96
|
- spec/spec_helper.rb
|
129
97
|
- README.MD
|
130
|
-
|
131
|
-
homepage:
|
98
|
+
homepage: https://github.com/jage/elk
|
132
99
|
licenses: []
|
133
|
-
|
134
100
|
post_install_message:
|
135
101
|
rdoc_options: []
|
136
|
-
|
137
|
-
require_paths:
|
102
|
+
require_paths:
|
138
103
|
- lib
|
139
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
105
|
none: false
|
141
|
-
requirements:
|
142
|
-
- -
|
143
|
-
- !ruby/object:Gem::Version
|
144
|
-
|
145
|
-
|
146
|
-
- 0
|
147
|
-
version: "0"
|
148
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
111
|
none: false
|
150
|
-
requirements:
|
151
|
-
- -
|
152
|
-
- !ruby/object:Gem::Version
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
version: "0"
|
157
|
-
requirements: []
|
158
|
-
|
112
|
+
requirements:
|
113
|
+
- - ! '>='
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
requirements:
|
117
|
+
- API account at 46elks.com
|
159
118
|
rubyforge_project:
|
160
|
-
rubygems_version: 1.
|
119
|
+
rubygems_version: 1.8.10
|
161
120
|
signing_key:
|
162
121
|
specification_version: 3
|
163
122
|
summary: Client library for 46elks SMS/MMS/Voice service.
|
164
123
|
test_files: []
|
165
|
-
|