messente-rails 0.1.0 → 0.2.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: 54946d4694f6df2962df67f0e7fd47ff32dc6324
4
- data.tar.gz: 3d5608bc4a6b381c96127e3295ff2bda6a3c928e
3
+ metadata.gz: fed9eacb2651c18ac8daae4e11416c0aaf9c98e7
4
+ data.tar.gz: dfac98f867b01dbbb3d5e3062e8daa52a1588d04
5
5
  SHA512:
6
- metadata.gz: 6899f0992094856cc9d74b9d98b6d17c6aaf4bb5462cf35c53475b5e13389fc75d1c0b69d313f5736d2703b313ef6487ae51e45f8c783eade1149c7a36118da9
7
- data.tar.gz: e772cf556ddd73f7541fb1e970b981fac314d40564d3d61378f868cd45a1ff12b459618e8926c11ce8e720f9cd81c94676e52ae9bbe000d2ecc2c3e0e0689ff0
6
+ metadata.gz: f7350cb9f4f555aa09bdacf14bcd12c2c40da263098f9322d23fd0498a72a8fc94197d1444f62f6908ff7c768719fa976a6822f1f660bfa9b2e37f5269c2097e
7
+ data.tar.gz: 216b3364ee404080ea0e804e4cb2c03e97ce61297e2468ece2098b875a31f1c9591496f62a655a73383e7595213b0160433443e75f4b6e34ccedabab3fe2cd86
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ before_install:
3
+ - gem install bundler
4
+ rvm:
5
+ - 2.1.2
6
+ gemfile:
7
+ - Gemfile
8
+ notifications:
9
+ email: false
data/README.md CHANGED
@@ -1,9 +1,14 @@
1
- # Messente::Rails
2
-
3
- Messente.com API wrapper for Rails (non official)
1
+ # messente-rails
4
2
 
3
+ Non-official [Messente.com](https://messente.com) SMS gateway API wrapper for Rails.
5
4
  Original API documentation: [https://messente.com/docs/api/rest/](https://messente.com/docs/api/rest/)
6
5
 
6
+ [![Gem Version](https://badge.fury.io/rb/messente-rails.svg)](http://badge.fury.io/rb/messente-rails)
7
+ [![Build Status](https://travis-ci.org/Gedrovits/messente-rails.svg)](https://travis-ci.org/Gedrovits/messente-rails)
8
+ [![Dependency Status](https://gemnasium.com/Gedrovits/messente-rails.svg)](https://gemnasium.com/Gedrovits/messente-rails)
9
+ [![Code Climate](https://codeclimate.com/github/Gedrovits/messente-rails.png)](https://codeclimate.com/github/Gedrovits/messente-rails)
10
+ [![Inline docs](http://inch-ci.org/github/Gedrovits/messente-rails.png?branch=master)](http://inch-ci.org/github/Gedrovits/messente-rails)
11
+
7
12
  ## Installation
8
13
 
9
14
  Add this line to your application's Gemfile:
@@ -28,10 +33,28 @@ NB! Don't forget to restart server after configuration.
28
33
 
29
34
  ## Usage
30
35
 
31
- Methods from original documentation as is, but only synchronous sending is supported for now.
32
-
33
36
  Original API documentation: [https://messente.com/docs/api/rest/](https://messente.com/docs/api/rest/)
34
37
 
38
+ Idea was to leave original API names intact, so methods and parameters from API are same in gem.
39
+
40
+ So for example to send SMS with generated initializer it's simply as that:
41
+
42
+ $ messente = Messente.new
43
+ $ messente.send_sms(text: 'Message', to: '+000000000')
44
+
45
+ OR alternative way
46
+
47
+ $ Messente.send_sms(text: 'Message', to: '+000000000')
48
+
49
+ This way you can pass in required and optional parameters and use official documentation as manual.
50
+
51
+ $ Messente.prices(country: 'GB', format: 'xml')
52
+
53
+ NB! Be warned about non-ruby like attribute names and pass them as strings.
54
+ For now there is only one parameter like this 'dlr-url'. Please if you need it send it like that:
55
+
56
+ $ Messente.send_sms(text: 'Message', to: '+000000000', 'dlr-url' => 'http://example.com/callback')
57
+
35
58
  ## Contributing
36
59
 
37
60
  1. Fork it ( https://github.com/Gedrovits/messente-rails/fork )
@@ -1,8 +1,15 @@
1
1
  # You can configure messente-rails within this file
2
2
  MessenteRails.configure do |config|
3
3
  ## Messente.com API credentials
4
- #
5
- config.username = <% if ::Rails::VERSION::MAJOR == 4 %>Rails.application.secrets.messente_username<% else %>Rails.env.development? ? 'dev' : 'prod'<% end %>
6
- #
7
- config.password = <% if ::Rails::VERSION::MAJOR == 4 %>Rails.application.secrets.messente_password<% else %>Rails.env.development? ? 'dev' : 'prod'<% end %>
4
+ # API username
5
+ config.username = Rails.application.secrets.messente_username
6
+ # API password
7
+ config.password = Rails.application.secrets.messente_password
8
+
9
+ ## Options
10
+ # Return Messente.com stringified response as is without any special parsing
11
+ config.response_as_is = false
12
+ # Retry with backup Messente.com server on failed response
13
+ # This works only if :response_as_is === false
14
+ config.retry_on_fail = true
8
15
  end
@@ -13,5 +13,11 @@ module MessenteRails
13
13
  mattr_accessor :password
14
14
  @@password = nil
15
15
 
16
+ mattr_accessor :response_as_is
17
+ @@response_as_is = true
18
+
19
+ mattr_accessor :retry_on_fail
20
+ @@retry_on_fail = true
21
+
16
22
  end
17
23
  end
@@ -4,135 +4,136 @@ class Messente
4
4
  include HTTParty
5
5
  base_uri 'api2.messente.com'
6
6
 
7
+ SUPPORTED_METHODS = [:send_sms, :get_dlr_response, :cancel_sms, :get_balance, :prices, :pricelist]
8
+
7
9
  ERROR_101 = 'Access is restricted, wrong credentials. Check username and password values.'
8
10
  ERROR_102 = 'Parameters are wrong or missing. Check that all required parameters are present.'
9
11
  ERROR_103 = 'Invalid IP address. The IP address you made the request from, is not in the API settings whitelist.'
12
+ ERROR_104 = 'Country was not found.'
13
+ ERROR_105 = 'This country is not supported.'
14
+ ERROR_106 = 'Invalid format provided. Only json or xml is allowed.'
15
+ ERROR_107 = 'Could not find message with sms_unique_id.'
10
16
  ERROR_111 = 'Sender parameter "from" is invalid. You have not activated this sender name from Messente.com'
11
17
  FAILED_209 = 'Server failure, try again after a few seconds or try api3.messente.com backup server.'
12
18
 
13
- class << self
14
- # https://messente.com/docs/api/rest/sms/
15
- def send_sms(mobile, message, backup_uri = false)
16
- action = '/send_sms/'
17
- query = credentials.merge({ to: mobile, text: message })
18
- url = backup_uri ? self.backup_uri + action : action
19
-
20
- response = get(url, { query: query })
21
- return false unless ok? response
22
-
23
- case response.parsed_response
24
- when 'ERROR 101' then ERROR_101
25
- when 'ERROR 102' then ERROR_102
26
- when 'ERROR 103' then ERROR_103
27
- when 'ERROR 111' then ERROR_111
28
- when 'FAILED 209' then backup_uri ? false : send_sms(mobile, message, true)
29
- else
30
- # TODO: Should we save somewhere unique SMS ID?
31
- # unique_sms_id = response.parsed_response.split(' ').second
32
- true
33
- end
34
- end
35
-
36
- # https://messente.com/docs/api/rest/delivery-request/sync/
37
- def get_dlr_response(sms_unique_id, backup_uri = false)
38
- action = '/get_dlr_response/'
39
- query = credentials.merge({ sms_unique_id: sms_unique_id })
40
- url = backup_uri ? self.backup_uri + action : action
41
-
42
- response = get(url, { query: query })
43
- return false unless ok? response
19
+ attr_accessor :defaults, :credentials, :use_backup_uri, :current_params
20
+
21
+ def initialize(username = nil, password = nil)
22
+ self.defaults = {
23
+ response_as_is: MessenteRails::Configuration.response_as_is,
24
+ retry_on_fail: MessenteRails::Configuration.retry_on_fail
25
+ }
26
+ self.credentials = {
27
+ username: username || MessenteRails::Configuration.username,
28
+ password: password || MessenteRails::Configuration.password
29
+ }
30
+ end
44
31
 
45
- case response.parsed_response
46
- when 'ERROR 101' then ERROR_101
47
- when 'ERROR 102' then ERROR_102
48
- when 'FAILED 209' then backup_uri ? false : get_dlr_response(sms_unique_id, true)
49
- else response.parsed_response.split(' ').second.downcase
50
- end
51
- end
32
+ # https://messente.com/docs/api/rest/sms/
33
+ # :text, :to, :time_to_send, :from, 'dlr-url', :charset, :autoconvert, :udh
34
+ def send_sms(params)
35
+ self.current_params = params
36
+ response = send_request(params)
37
+ smart_response(response.parsed_response)
38
+ end
52
39
 
53
- # https://messente.com/docs/api/rest/cancel-sms/
54
- def cancel_sms(sms_unique_id, backup_uri = false)
55
- action = '/cancel_sms/'
56
- query = credentials.merge({ sms_unique_id: sms_unique_id })
57
- url = backup_uri ? self.backup_uri + action : action
40
+ # https://messente.com/docs/api/rest/delivery-request/sync/
41
+ # :sms_unique_id
42
+ def get_dlr_response(params)
43
+ self.current_params = params
44
+ response = send_request(params)
45
+ smart_response(response.parsed_response)
46
+ end
58
47
 
59
- response = get(url, { query: query })
60
- return false unless ok? response
48
+ # https://messente.com/docs/api/rest/cancel-sms/
49
+ # :sms_unique_id
50
+ def cancel_sms(params)
51
+ self.current_params = params
52
+ response = send_request(params)
53
+ smart_response(response.parsed_response)
54
+ end
61
55
 
62
- case response.parsed_response
63
- when 'ERROR 107' then 'Could not find message with sms_unique_id.'
64
- when 'FAILED 209' then backup_uri ? false : cancel_sms(sms_unique_id, true)
65
- else true
66
- end
67
- end
56
+ # https://messente.com/docs/api/rest/balance/
57
+ def get_balance
58
+ response = send_request
59
+ smart_response(response.parsed_response)
60
+ end
68
61
 
69
- # https://messente.com/docs/api/rest/balance/
70
- def get_balance(backup_uri = false)
71
- action = '/get_balance/'
72
- url = backup_uri ? self.backup_uri + action : action
62
+ # https://messente.com/docs/api/rest/prices/
63
+ # :country, :format
64
+ def prices(params)
65
+ self.current_params = params
66
+ response = send_request(params)
67
+ smart_response(response.parsed_response)
68
+ end
73
69
 
74
- response = get(url, { query: credentials })
75
- return false unless ok? response
70
+ # https://messente.com/docs/api/rest/full-pricelist/
71
+ def pricelist
72
+ response = send_request
73
+ smart_response(response.parsed_response)
74
+ end
76
75
 
77
- case response.parsed_response
78
- when 'ERROR 101' then ERROR_101
79
- when 'ERROR 102' then ERROR_102
80
- when 'FAILED 209' then backup_uri ? false : get_balance(true)
81
- else response.parsed_response.split(' ').second
82
- end
83
- end
76
+ # Methods below allows us to make all calls above as class methods
77
+ # DRY so we don't need to define all methods again with calling instance from inside
84
78
 
85
- # https://messente.com/docs/api/rest/prices/
86
- def prices(country, format = 'json', backup_uri = false)
87
- action = '/prices/'
88
- query = credentials.merge({ country: country, format: format })
89
- url = backup_uri ? self.backup_uri + action : action
90
-
91
- response = get(url, { query: query })
92
- return false unless ok? response
93
-
94
- case response.parsed_response
95
- when 'ERROR 101' then ERROR_101
96
- when 'ERROR 102' then ERROR_102
97
- when 'ERROR 103' then 'IP address not allowed.'
98
- when 'ERROR 104' then 'Country was not found.'
99
- when 'ERROR 105' then 'This country is not supported.'
100
- when 'ERROR 106' then 'Invalid format provided. Only json or xml is allowed.'
101
- when 'FAILED 209' then backup_uri ? false : prices(country, 'json', true)
102
- else response.parsed_response
103
- end
79
+ def self.method_missing(method_name, *arguments, &block)
80
+ if SUPPORTED_METHODS.include? method_name
81
+ self.new.send(method_name, *arguments, &block)
82
+ else
83
+ super
104
84
  end
85
+ end
105
86
 
106
- # https://messente.com/docs/api/rest/full-pricelist/
107
- def pricelist(backup_uri = false)
108
- action = '/pricelist/'
109
- url = backup_uri ? self.backup_uri + action : action
87
+ def self.respond_to_missing?(method_name, include_private = false)
88
+ SUPPORTED_METHODS.include? method_name || super
89
+ end
110
90
 
111
- response = get(url, { query: credentials })
112
- return false unless ok? response
91
+ private
92
+
93
+ def send_request(query = nil)
94
+ action = caller[0].split('`').pop.gsub('\'', '')
95
+ safe_query = query ? credentials.merge(query) : credentials
96
+ url = if use_backup_uri === true
97
+ self.use_backup_uri = false
98
+ "#{ self.class.base_uri.gsub('api2', 'api3') }/#{ action }/"
99
+ else
100
+ "/#{ action }/"
101
+ end
102
+ self.class.post(url, { query: safe_query })
103
+ end
113
104
 
114
- case response.parsed_response
115
- when 'ERROR 101' then ERROR_101
116
- when 'ERROR 102' then ERROR_102
117
- when 'ERROR 103' then 'IP address not allowed.'
118
- when 'FAILED 209' then backup_uri ? false : pricelist(true)
119
- else response.parsed_response
105
+ def smart_response(response)
106
+ if response_as_is?
107
+ response
108
+ else
109
+ case response.split(' ').first
110
+ when 'ERROR'
111
+ [false, human_readable_error(response)]
112
+ when 'FAILED'
113
+ if retry_on_fail? && use_backup_uri != false
114
+ self.use_backup_uri = true
115
+ method_name = caller[0].split('`').pop.gsub('\'', '').to_sym
116
+ current_params.blank? ? send(method_name) : send(method_name, current_params)
117
+ else
118
+ self.use_backup_uri = nil
119
+ end
120
+ [false, human_readable_error(response)]
121
+ else
122
+ [true, response]
120
123
  end
121
124
  end
125
+ end
122
126
 
123
- private
124
-
125
- def credentials
126
- { username: MessenteRails::Configuration.username,
127
- password: MessenteRails::Configuration.password }
128
- end
127
+ def human_readable_error(error)
128
+ safe_error = error.gsub(' ', '_')
129
+ self.class.const_defined?(safe_error) ? self.class.const_get(safe_error) : "#{error} not defined."
130
+ end
129
131
 
130
- def backup_uri
131
- base_uri.gsub('api2', 'api3')
132
- end
132
+ def response_as_is?
133
+ defaults && defaults[:response_as_is]
134
+ end
133
135
 
134
- def ok?(response)
135
- response.code == 200
136
- end
136
+ def retry_on_fail?
137
+ defaults && defaults[:retry_on_fail]
137
138
  end
138
139
  end
@@ -1,3 +1,3 @@
1
1
  module MessenteRails
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -6,6 +6,7 @@ require 'messente-rails/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'messente-rails'
8
8
  spec.version = MessenteRails::VERSION
9
+ spec.platform = Gem::Platform::RUBY
9
10
  spec.authors = ['Vjatseslav Gedrovits']
10
11
  spec.email = ['vjatseslav.gedrovits@gmail.com']
11
12
  spec.summary = %q{Messente.com API wrapper for Rails}
@@ -22,5 +23,5 @@ Gem::Specification.new do |spec|
22
23
 
23
24
  spec.add_development_dependency 'bundler', '~> 1.6'
24
25
  spec.add_development_dependency 'rake'
25
- spec.add_development_dependency 'rails', '~> 4.1'
26
+ spec.add_development_dependency 'rails', '>= 4.1'
26
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: messente-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vjatseslav Gedrovits
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-13 00:00:00.000000000 Z
11
+ date: 2014-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -56,14 +56,14 @@ dependencies:
56
56
  name: rails
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '4.1'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '4.1'
69
69
  description: Messente.com API wrapper for Rails
@@ -74,6 +74,7 @@ extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
76
  - ".gitignore"
77
+ - ".travis.yml"
77
78
  - Gemfile
78
79
  - LICENSE
79
80
  - README.md