sms77 0.0.1 → 0.4.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 +4 -4
- data/.gitignore +2 -2
- data/README.md +26 -6
- data/lib/sms77.rb +0 -1
- data/lib/sms77/client.rb +18 -87
- data/lib/sms77/{contacts_action.rb → contacts.rb} +2 -2
- data/lib/sms77/endpoint.rb +12 -12
- data/lib/sms77/hooks.rb +64 -0
- data/lib/sms77/journal.rb +38 -0
- data/lib/sms77/{lookup_type.rb → lookup.rb} +2 -2
- data/lib/sms77/resource.rb +93 -0
- data/lib/sms77/resources/analytics.rb +16 -0
- data/lib/sms77/resources/balance.rb +16 -0
- data/lib/sms77/resources/contacts.rb +26 -0
- data/lib/sms77/resources/hooks.rb +30 -0
- data/lib/sms77/resources/journal.rb +16 -0
- data/lib/sms77/resources/lookup.rb +30 -0
- data/lib/sms77/resources/pricing.rb +16 -0
- data/lib/sms77/resources/sms.rb +16 -0
- data/lib/sms77/resources/status.rb +16 -0
- data/lib/sms77/resources/validate_for_voice.rb +16 -0
- data/lib/sms77/resources/voice.rb +16 -0
- data/lib/sms77/sms.rb +8 -0
- data/lib/sms77/util.rb +68 -0
- data/lib/sms77/version.rb +1 -1
- data/release.sh +8 -0
- data/sms77.gemspec +13 -16
- data/spec/EnvKeyStore.rb +15 -0
- data/spec/matchers.rb +23 -0
- data/spec/sms77/balance_spec.rb +4 -7
- data/spec/sms77/client_spec.rb +15 -0
- data/spec/sms77/contacts_spec.rb +22 -24
- data/spec/sms77/hooks_spec.rb +106 -0
- data/spec/sms77/instance_spec.rb +20 -0
- data/spec/sms77/journal_spec.rb +86 -0
- data/spec/sms77/lookup_spec.rb +73 -82
- data/spec/sms77/pricing_spec.rb +25 -29
- data/spec/sms77/sms_spec.rb +20 -20
- data/spec/sms77/validate_for_voice_spec.rb +6 -6
- data/spec/sms77/voice_spec.rb +11 -8
- data/spec/sms77_spec.rb +0 -8
- data/spec/spec_helper.rb +31 -34
- metadata +60 -25
- data/lib/sms77/header.rb +0 -7
- data/spec/sms77/http_spec.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5dcd3acfda05ed3752e5d11fdd3218268ff39a9637373548fc7652845738c24c
|
4
|
+
data.tar.gz: f4a42f418594d53610fd89b2494c83555c654cc4401a1ebabf97d1e20feee5a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 310757899c3eb52bbd50122271aada73242b984cbc83fc63361ae183e13ac410c6c9701214ddfc6124e1cb179ca5f2b2b1d075d533066b36b3ef814c015e3393
|
7
|
+
data.tar.gz: f4788dbac05a014e4ba53be45036e7db02f80d78d99fa7b0078779ac34b9349b6185f7c65db929e413f798e374746fe9f4384ce124afe953a36452bad68619eb
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-

|
1
|
+

|
2
2
|
|
3
|
-
# Sms77.io SMS Gateway API
|
3
|
+
# Ruby Client for the Sms77.io SMS Gateway API
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -9,7 +9,27 @@
|
|
9
9
|
### Usage
|
10
10
|
|
11
11
|
```ruby
|
12
|
-
|
13
|
-
|
14
|
-
puts
|
15
|
-
|
12
|
+
require 'sms77'
|
13
|
+
|
14
|
+
puts Sms77::Client.new(Sms77::Resource(ENV['SMS77_API_KEY'])).Balance.retrieve
|
15
|
+
# or
|
16
|
+
puts Sms77::Resources::Balance.new(ENV['SMS77_API_KEY']).retrieve
|
17
|
+
```
|
18
|
+
|
19
|
+
#### Testing
|
20
|
+
|
21
|
+
```shell
|
22
|
+
SMS77_API_KEY=MySms77ApiKey bundle exec rspec
|
23
|
+
```
|
24
|
+
|
25
|
+
*Optional environment variables*
|
26
|
+
|
27
|
+
Setting ```SMS77_DEBUG=1``` prints details to stdout.
|
28
|
+
|
29
|
+
Setting ```SMS77_TEST_HTTP=1``` enables live testing with actual API requests.
|
30
|
+
|
31
|
+
##### Support
|
32
|
+
|
33
|
+
Need help? Feel free to [contact us](https://www.sms77.io/en/company/contact/).
|
34
|
+
|
35
|
+
[](./LICENSE)
|
data/lib/sms77.rb
CHANGED
data/lib/sms77/client.rb
CHANGED
@@ -1,98 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
require 'sms77/
|
7
|
-
require 'sms77/
|
8
|
-
require 'sms77/
|
3
|
+
require 'sms77/resources/analytics'
|
4
|
+
require 'sms77/resources/balance'
|
5
|
+
require 'sms77/resources/contacts'
|
6
|
+
require 'sms77/resources/hooks'
|
7
|
+
require 'sms77/resources/journal'
|
8
|
+
require 'sms77/resources/lookup'
|
9
|
+
require 'sms77/resources/pricing'
|
10
|
+
require 'sms77/resources/sms'
|
11
|
+
require 'sms77/resources/status'
|
12
|
+
require 'sms77/resources/validate_for_voice'
|
13
|
+
require 'sms77/resources/voice'
|
14
|
+
require 'sms77/util'
|
9
15
|
|
10
16
|
module Sms77
|
11
17
|
class Client
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
18
|
+
# @param resource [Sms77::Resource]
|
19
|
+
def initialize(resource)
|
20
|
+
Sms77::Util::get_namespace_classes(Sms77::Resources).each do |cls|
|
21
|
+
name = cls.name.split('::').last
|
16
22
|
|
17
|
-
|
18
|
-
raise 'missing conn in config' unless @conn
|
23
|
+
instance_variable_set("@#{name}", cls.new(resource))
|
19
24
|
|
20
|
-
|
21
|
-
@conn.authorization :Bearer, @api_key
|
22
|
-
end
|
23
|
-
|
24
|
-
BASE_URI = 'https://gateway.sms77.io'
|
25
|
-
API_SUFFIX = '/api/'
|
26
|
-
API_URI = "#{BASE_URI}#{API_SUFFIX}"
|
27
|
-
|
28
|
-
def analytics(params = {})
|
29
|
-
get(Sms77::Endpoint::ANALYTICS, params)
|
30
|
-
end
|
31
|
-
|
32
|
-
def balance
|
33
|
-
get(Sms77::Endpoint::BALANCE)
|
34
|
-
end
|
35
|
-
|
36
|
-
def contacts(params)
|
37
|
-
method(params['action'] == ContactsAction::READ ? 'get' : 'post').call(Sms77::Endpoint::CONTACTS, params)
|
38
|
-
end
|
39
|
-
|
40
|
-
def lookup(params)
|
41
|
-
get(Sms77::Endpoint::LOOKUP, params)
|
42
|
-
end
|
43
|
-
|
44
|
-
def pricing(params = {})
|
45
|
-
get(Sms77::Endpoint::PRICING, params)
|
46
|
-
end
|
47
|
-
|
48
|
-
def sms(params)
|
49
|
-
post(Sms77::Endpoint::SMS, params)
|
50
|
-
end
|
51
|
-
|
52
|
-
def status(params)
|
53
|
-
get(Sms77::Endpoint::STATUS, params)
|
54
|
-
end
|
55
|
-
|
56
|
-
def validate_for_voice(params)
|
57
|
-
get(Sms77::Endpoint::VALIDATE_FOR_VOICE, params)
|
58
|
-
end
|
59
|
-
|
60
|
-
def voice(params)
|
61
|
-
post(Sms77::Endpoint::VOICE, params)
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def get(endpoint, params = {})
|
67
|
-
request(endpoint, 'get', params)
|
68
|
-
end
|
69
|
-
|
70
|
-
def post(endpoint, params)
|
71
|
-
request(endpoint, 'post', params)
|
72
|
-
end
|
73
|
-
|
74
|
-
def request(endpoint, method, params)
|
75
|
-
url = "#{API_SUFFIX}#{endpoint}"
|
76
|
-
|
77
|
-
if ENV['SMS77_DEBUG']
|
78
|
-
puts "requesting url: #{url}"
|
79
|
-
puts "headers: #{@conn.headers.inspect}"
|
25
|
+
singleton_class.instance_eval("attr_reader :#{name}")
|
80
26
|
end
|
81
|
-
|
82
|
-
response = if method == 'get'
|
83
|
-
@conn.get(url, params)
|
84
|
-
else
|
85
|
-
@conn.post do |req|
|
86
|
-
req.path = url
|
87
|
-
req.params = params
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
raise "Error requesting (#{self.class.name}) with code: #{response.status}" if response.status != 200
|
92
|
-
|
93
|
-
puts "received body: #{response.body}" if ENV['SMS77_DEBUG']
|
94
|
-
|
95
|
-
response
|
96
27
|
end
|
97
28
|
end
|
98
29
|
end
|
data/lib/sms77/endpoint.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module Sms77
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
3
|
+
module Sms77::Endpoint
|
4
|
+
ANALYTICS = 'analytics'
|
5
|
+
BALANCE = 'balance'
|
6
|
+
CONTACTS = 'contacts'
|
7
|
+
HOOKS = 'hooks'
|
8
|
+
JOURNAL = 'journal'
|
9
|
+
LOOKUP = 'lookup'
|
10
|
+
PRICING = 'pricing'
|
11
|
+
SMS = 'sms'
|
12
|
+
STATUS = 'status'
|
13
|
+
VALIDATE_FOR_VOICE = 'validate_for_voice'
|
14
|
+
VOICE = 'voice'
|
15
15
|
end
|
data/lib/sms77/hooks.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sms77::Hooks
|
4
|
+
module Action
|
5
|
+
READ = 'read'
|
6
|
+
SUBSCRIBE = 'subscribe'
|
7
|
+
UNSUBSCRIBE = 'unsubscribe'
|
8
|
+
end
|
9
|
+
|
10
|
+
module EventType
|
11
|
+
ALL = 'all'
|
12
|
+
NEW_INBOUND_SMS = 'sms_mo'
|
13
|
+
SMS_STATUS_UPDATE = 'dlr'
|
14
|
+
VOICE_STATUS_UPDATE = 'voice_status'
|
15
|
+
end
|
16
|
+
|
17
|
+
module RequestMethod
|
18
|
+
GET = 'GET'
|
19
|
+
JSON = 'JSON'
|
20
|
+
POST = 'POST'
|
21
|
+
end
|
22
|
+
|
23
|
+
module Validator
|
24
|
+
def self.validate(params)
|
25
|
+
action = params[:action]
|
26
|
+
|
27
|
+
raise "Unknown action #{action}" unless Sms77::Hooks::Validator::is_action?(action)
|
28
|
+
|
29
|
+
if Sms77::Hooks::Action::SUBSCRIBE == action
|
30
|
+
raise 'Parameter validation failed' unless Sms77::Hooks::Validator::subscribe(params)
|
31
|
+
elsif Sms77::Hooks::Action::UNSUBSCRIBE == action
|
32
|
+
raise 'ID must be a positive integer' unless Sms77::Hooks::Validator::unsubscribe(params)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.subscribe(params)
|
37
|
+
{ :request_method => Sms77::Hooks::RequestMethod::POST }.merge!(params)
|
38
|
+
|
39
|
+
self.event_type?(params[:event_type]) &&
|
40
|
+
self.request_method?(params[:request_method]) &&
|
41
|
+
self.target_url?(params[:target_url])
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.unsubscribe(params)
|
45
|
+
Sms77::Util::is_positive_integer?(params[:id])
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.is_action?(str)
|
49
|
+
Sms77::Util::in_module_constants?(str, Sms77::Hooks::Action)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.event_type?(str)
|
53
|
+
Sms77::Util::in_module_constants?(str, Sms77::Hooks::EventType)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.request_method?(str)
|
57
|
+
Sms77::Util::in_module_constants?(str, Sms77::Hooks::RequestMethod)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.target_url?(str)
|
61
|
+
Sms77::Util::is_valid_url?(str)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sms77::Journal
|
4
|
+
module Type
|
5
|
+
INBOUND = 'inbound'
|
6
|
+
OUTBOUND = 'outbound'
|
7
|
+
REPLIES = 'replies'
|
8
|
+
VOICE = 'voice'
|
9
|
+
end
|
10
|
+
|
11
|
+
module Validator
|
12
|
+
def self.validate(params)
|
13
|
+
type = params[:type]
|
14
|
+
date_from = params[:date_from]
|
15
|
+
date_to = params[:date_to]
|
16
|
+
|
17
|
+
raise "Unknown type #{type}" unless Sms77::Journal::Validator::is_type?(type)
|
18
|
+
raise "Wrong date_from #{date_from}" unless Sms77::Journal::Validator::is_date?(date_from)
|
19
|
+
raise "Wrong date_to #{date_to}" unless Sms77::Journal::Validator::is_date?(date_to)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.subscribe(params)
|
23
|
+
{ :request_method => Sms77::Hooks::RequestMethod::POST }.merge!(params)
|
24
|
+
|
25
|
+
self.event_type?(params[:event_type]) &&
|
26
|
+
self.request_method?(params[:request_method]) &&
|
27
|
+
self.target_url?(params[:target_url])
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.is_type?(str)
|
31
|
+
Sms77::Util::in_module_constants?(str, Sms77::Journal::Type)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.is_date?(date)
|
35
|
+
date.is_a?(NilClass) || date.match(/[\d]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][\d]|3[0-1])/)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cgi'
|
4
|
+
require 'json'
|
5
|
+
require 'faraday'
|
6
|
+
require 'sms77/endpoint'
|
7
|
+
|
8
|
+
module Sms77
|
9
|
+
class Resource
|
10
|
+
attr_reader :api_key, :endpoint, :sent_with, :http_methods, :request_methods, :builder, :conn
|
11
|
+
|
12
|
+
BASE_PATH = '/api/'
|
13
|
+
|
14
|
+
def initialize(api_key, sent_with = 'ruby')
|
15
|
+
raise 'missing api_key in config' if api_key.to_s.empty?
|
16
|
+
raise 'missing sent_with in config' if sent_with.to_s.empty?
|
17
|
+
|
18
|
+
@api_key = api_key
|
19
|
+
@sent_with = sent_with
|
20
|
+
@endpoint = self.class.get_endpoint
|
21
|
+
@http_methods = self.class.get_http_methods
|
22
|
+
@conn = Faraday.new("https://gateway.sms77.io#{BASE_PATH}")
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def request(payload = {}, query = {})
|
28
|
+
path = @endpoint
|
29
|
+
http_method = @http_methods[caller_locations.first.label.to_sym]
|
30
|
+
|
31
|
+
if :get == http_method
|
32
|
+
query = payload
|
33
|
+
|
34
|
+
payload = {}
|
35
|
+
end
|
36
|
+
|
37
|
+
query.each do |key, val|
|
38
|
+
query.store(key, Sms77::Util::to_numbered_bool(val))
|
39
|
+
end
|
40
|
+
|
41
|
+
payload.each do |key, val|
|
42
|
+
payload.store(key, Sms77::Util::to_numbered_bool(val))
|
43
|
+
end
|
44
|
+
|
45
|
+
unless query.empty?
|
46
|
+
path = "#{path}?#{URI.encode_www_form(query)}"
|
47
|
+
end
|
48
|
+
|
49
|
+
headers = Hash[
|
50
|
+
Faraday::Request::Authorization::KEY, "Bearer #{@api_key}",
|
51
|
+
'sentWith', @sent_with
|
52
|
+
]
|
53
|
+
|
54
|
+
res = @conn.run_request(http_method, path, payload, headers)
|
55
|
+
|
56
|
+
puts JSON.pretty_generate(res.to_hash.merge({
|
57
|
+
:method => http_method,
|
58
|
+
:path => path,
|
59
|
+
:payload => payload,
|
60
|
+
:req_headers => headers,
|
61
|
+
:query => query,
|
62
|
+
}).compact) if ENV['SMS77_DEBUG']
|
63
|
+
|
64
|
+
raise "Error requesting (#{self.class.name}) with code #{res.status}" unless 200 == res.status
|
65
|
+
|
66
|
+
raise 'Unexpected response' unless res.is_a?(Faraday::Response)
|
67
|
+
|
68
|
+
body = res.body
|
69
|
+
|
70
|
+
if body.is_a?(String)
|
71
|
+
begin
|
72
|
+
body = JSON.parse(body, :symbolize_names => true)
|
73
|
+
rescue StandardError
|
74
|
+
# Ignored
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
body.map! { |hash| hash.transform_keys(&:to_sym) } if body.is_a?(Array)
|
79
|
+
|
80
|
+
body
|
81
|
+
end
|
82
|
+
|
83
|
+
class << self
|
84
|
+
def get_http_methods
|
85
|
+
@http_methods
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_endpoint
|
89
|
+
@endpoint
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sms77/resource'
|
4
|
+
|
5
|
+
module Sms77::Resources
|
6
|
+
class Analytics < Sms77::Resource
|
7
|
+
@endpoint = Sms77::Endpoint::ANALYTICS
|
8
|
+
@http_methods = {
|
9
|
+
:retrieve => :get,
|
10
|
+
}
|
11
|
+
|
12
|
+
def retrieve(params = {})
|
13
|
+
request(params)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|