smshelper 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,17 +1,14 @@
1
1
  source "http://rubygems.org"
2
- # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
5
2
 
6
- # Add dependencies to develop your gem here.
7
- # Include everything needed to run rake, tests, features, etc.
8
3
  gem 'api_smith'
9
4
  gem 'savon'
10
5
  gem 'nokogiri'
6
+
11
7
  gem 'textmagic'
12
8
 
13
9
  gem 'uuid'
14
10
  gem 'digest-crc'
11
+ gem 'virtus'
15
12
 
16
13
  group :development do
17
14
  gem "pry"
data/README.md ADDED
@@ -0,0 +1,122 @@
1
+ Smshelper
2
+ ---------
3
+
4
+ __THE lib for SMS-MT / HLR-Lookups.__
5
+
6
+ One day i was asked to connect a crm to correspond in SMS with call
7
+ center customers. Chose at random one of the operators, wrote a few
8
+ lines of code and there it was - SMS inbound/outbound.
9
+
10
+ > "Some of our messages aren't being delivered on time, some are being
11
+ > lost altogether, some arrive multiple times, some arrive after more
12
+ > then 24 hours from being sent"
13
+
14
+ > _--Your faithful customer_
15
+
16
+ I kept adding operators and here are the results...
17
+
18
+ __Currently supported:__
19
+
20
+ * __Unicode:__ across all operators
21
+ <table>
22
+ <tr>
23
+ <th>Operator</th><th>#send_message</th><th>#get_balance</th><th>#get_status</th><th>#get_callback_response</th><th>#hlr_lookup</th>
24
+ </tr>
25
+ <tr>
26
+ <td>Aql</td><td>X</td><td>X</td><td>_</td><td>X</td><td>_</td>
27
+ </tr>
28
+ <tr>
29
+ <td>Bulksms</td><td>X</td><td>X</td><td>X</td><td>X</td><td>_</td>
30
+ </tr>
31
+ <tr>
32
+ <td>Clickatell</td><td>X</td><td>X</td><td>X</td><td>_</td><td>_</td>
33
+ </tr>
34
+ <tr>
35
+ <td>Esendex</td><td>X</td><td>X</td><td>X</td><td>X</td><td>_</td>
36
+ </tr>
37
+ <tr>
38
+ <td>Mediaburst</td><td>X</td><td>X</td><td>_</td><td>X</td><td>_</td>
39
+ </tr>
40
+ <tr>
41
+ <td>Mycoolsms</td><td>X</td><td>X</td><td>_</td><td>X</td><td>X</td>
42
+ </tr>
43
+ <tr>
44
+ <td>Nexmo</td><td>X</td><td>X</td><td>_</td><td>X</td><td>_</td>
45
+ </tr>
46
+ <tr>
47
+ <td>Routomessaging</td><td>X</td><td>X</td><td>_</td><td>X</td><td>X**</td>
48
+ </tr>
49
+ <tr>
50
+ <td>Smstrade</td><td>X</td><td>X</td><td>_</td><td>X</td><td>_</td>
51
+ </tr>
52
+ <tr>
53
+ <td>Textmagic</td><td>X</td><td>X</td><td>_</td><td>X</td><td>_</td>
54
+ </tr>
55
+ <tr>
56
+ <td>Traitel</td><td>X</td><td>X</td><td>_</td><td>_</td><td>_</td>
57
+ </tr>
58
+ <tr>
59
+ <td>Vianett</td><td>X</td><td>X</td><td>_</td><td>X</td><td>X</td>
60
+ </tr>
61
+ <tr>
62
+ <td>Webtext</td><td>X</td><td>X</td><td>_</td><td>_</td><td>_</td>
63
+ </tr>
64
+ </table>
65
+
66
+ <!-- <iframe width='561' height='300' frameborder='0' src='https://docs.google.com/spreadsheet/pub?key=0AvGdwcIrVUI9dDNOUkE5Mlo0VnJEcmJaYlRJRkg1aEE&single=true&gid=0&output=html&widget=true'></iframe> -->
67
+ ** _Does_ __NOT__ _provide handset network status, so you can't check if a
68
+ subscriber is in reception zone with a switched-on handset._
69
+
70
+ __Installation__
71
+
72
+ gem install smshelper
73
+
74
+ __Usage__
75
+
76
+ ```ruby
77
+ require 'smshelper'
78
+ config = Smshelper::Config.new(
79
+ :webtext => {:uname => '', :passwd => ''},
80
+ :bulksms => {:uname => '', :passwd => ''},
81
+ :clickatell => {:api_key => '',:uname => '', :passwd => ''},
82
+ :textmagic => {:uname => '', :passwd => ''},
83
+ :smstrade => {:api_key => ''},
84
+ :esendex => {:uname => '', :passwd => '', :acc => ''},
85
+ :mediaburst => {:uname => '', :passwd => ''},
86
+ :nexmo => {:uname => '', :passwd => ''}
87
+ )
88
+
89
+ service0 = Smshelper::Api::Bulksms.new config
90
+ service1 = Smshelper::Api::Webtext.new config
91
+ service2 = Smshelper::Api::Clickatell.new config
92
+ service3 = Smshelper::Api::Textmagic.new config
93
+ service4 = Smshelper::Api::Smstrade.new config, :route => 'gold'
94
+ service5 = Smshelper::Api::Esendex.new config, 'com:validityperiod' => '1'
95
+ service6 = Smshelper::Api::MediaBurst.new config
96
+ service7 = Smshelper::Api::Nexmo.new config, :ttl => '60000'
97
+
98
+ message = Smshelper::Message.new(
99
+ :recipient => '14128765432',
100
+ :text => "The balance on
101
+ #{serviceX.class.name} is
102
+ #{serviceX.get_balance}",
103
+ :sender => '33765432132')
104
+
105
+ serviceX.send_message message
106
+
107
+ ```
108
+
109
+ ### Is It "Production Ready™"?
110
+
111
+ Most likely not, there are no tests yet and the API is going
112
+ to change a bit until v1.0.0 release
113
+
114
+ __TODO:__
115
+
116
+ * TESTs
117
+ * introduce plugin infrastructure
118
+ * handle sms of any size (_currently smshelper tries to use concat
119
+ setts, operator permitting_)
120
+ * add support for www.totext.net, www.world-text.com, www.mpulse.eu, www.clicksms.co.uk, www.tellustalk.com, www.tm4b.com, www.txtnation.com, www.smsextrapro.com, www.truesenses.com
121
+
122
+ ### I welcome pull requests!
data/Rakefile CHANGED
@@ -17,8 +17,8 @@ Jeweler::Tasks.new do |gem|
17
17
  gem.name = "smshelper"
18
18
  gem.homepage = "http://github.com/voipscout/smshelper"
19
19
  gem.license = "MIT"
20
- gem.summary = %Q{send sms with: www.bulksms.com, www.webtext.com, www.clickatell.com, www.textmagic.com, www.smstrade.eu, www.esendex.com, www.mediaburst.co.uk, www.nexmo.com, www.vianett.com, www.traitel.com.au, www.my-cool-sms.com, www.aql.com}
21
- gem.description = %Q{works www.bulksms.com, www.webtext.com, www.clickatell.com, www.textmagic.com, www.smstrade.eu, www.esendex.com, www.mediaburst.co.uk, www.nexmo.com, www.vianett.com, www.traitel.com.au, www.my-cool-sms.com, www.aql.com}
20
+ gem.summary = %Q{send sms with 10+ gateways}
21
+ gem.description = %Q{send sms with multiple gateways, like esendex, bulksms, clickatell etc..}
22
22
  gem.email = "voipscout@gmail.com"
23
23
  gem.authors = ["Voip Scout"]
24
24
  # dependencies defined in Gemfile
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.5
1
+ 0.4.6
data/lib/smshelper/api.rb CHANGED
@@ -1,26 +1,31 @@
1
- require 'hashie'
1
+ require 'virtus'
2
2
 
3
3
  module Smshelper
4
4
  module Api
5
5
  path = (File.dirname File.expand_path(__FILE__))
6
- VERSION = '0.0.1'#File.read('blahblah')
6
+ VERSION = '0.0.2'#File.read('blahblah')
7
7
 
8
8
  autoload :Base, "#{path}/api/base"
9
9
  autoload :ResponseCodes, "#{path}/api/response_codes"
10
- autoload :Webtext, "#{path}/api/webtext"
10
+
11
11
  autoload :Bulksms, "#{path}/api/bulksms"
12
- autoload :Clickatell, "#{path}/api/clickatell"
13
12
  autoload :Textmagic, "#{path}/api/textmagic"
14
13
  autoload :Smstrade, "#{path}/api/smstrade"
15
14
  autoload :Esendex, "#{path}/api/esendex"
16
15
  autoload :Mediaburst, "#{path}/api/mediaburst"
17
16
  autoload :Nexmo, "#{path}/api/nexmo"
18
- autoload :Traitel, "#{path}/api/traitel"
19
-
20
17
  autoload :Aql, "#{path}/api/aql"
21
18
  autoload :Vianett, "#{path}/api/vianett"
22
- autoload :Txtnation, "#{path}/api/txtnation"
23
- autoload :Totext, "#{path}/api/totext"
24
19
  autoload :Mycoolsms, "#{path}/api/mycoolsms"
20
+ autoload :Routomessaging, "#{path}/api/routomessaging"
21
+ # Still no support for get_callback_response
22
+
23
+ autoload :Traitel, "#{path}/api/traitel"
24
+ autoload :Clickatell, "#{path}/api/clickatell"
25
+ autoload :Webtext, "#{path}/api/webtext"
26
+ #TODO:
27
+ #autoload :Txtnation, "#{path}/api/txtnation"
28
+ #autoload :Totext, "#{path}/api/totext"
29
+ #autoload :Smswarehouse, "#{path}/api/smswarehouse"
25
30
  end
26
31
  end
@@ -9,9 +9,9 @@ module Smshelper
9
9
  def initialize(*args)
10
10
  @sent_message_ids, @sent_message_statuses = Array.new, Hash.new
11
11
  @response_code = ResponseCodes.new
12
- @extra_options = args.shift
12
+ @extra_options = (args.empty? ? {} : args.shift)
13
13
  @uuid = UUID.new
14
- class_factory 'DeliveryReport', 'InboundMessage', 'UnknownReply'
14
+ class_factory 'DeliveryReport', 'InboundMessage', 'UnknownReply', 'HlrReport'
15
15
  end
16
16
 
17
17
  protected
@@ -19,31 +19,52 @@ module Smshelper
19
19
  names.each do |name|
20
20
  klass = self.class.const_set(name, Class.new)
21
21
  klass.class_eval do
22
- attr_reader :uuid, :service
22
+ include Virtus
23
23
 
24
24
  define_method(:initialize) do |args = {}|
25
25
  args.each do |k,v|
26
+ # Sinatra params has splat, captures
26
27
  unless k.to_s =~ (/splat/ || /captures/)
27
- self.class.send(:define_method, k.to_sym) {v}
28
- instance_variable_set("@"+k.to_s, v)
28
+ self.class.attribute(k, v.class, :default => v)
29
29
  end
30
30
  end
31
- instance_variable_set("@uuid", UUID.generate)
32
- instance_variable_set("@service", self.class.name.split('::')[2])
33
- end
34
-
35
- #TODO: Find out why is this needed!
36
- define_method("_dump".to_sym) do |level|
37
- self.to_yaml
38
- end
39
-
40
- def self._load(str)
41
- YAML.load str
31
+ self.class.attribute(:uuid, String, :default => UUID.generate)
32
+ self.class.attribute(:service, String, :default => self.class.name.split('::')[2])
42
33
  end
43
34
 
44
35
  end
45
36
  end
46
37
  end
47
- end
48
- end
49
- end
38
+
39
+ # def class_factory(*names)
40
+ # names.each do |name|
41
+ # klass = self.class.const_set(name, Class.new)
42
+ # klass.class_eval do
43
+ # attr_reader :uuid, :service
44
+
45
+ # define_method(:initialize) do |args = {}|
46
+ # args.each do |k,v|
47
+ # unless k.to_s =~ (/splat/ || /captures/)
48
+ # self.class.send(:define_method, k.to_sym) {v}
49
+ # instance_variable_set("@"+k.to_s, v)
50
+ # end
51
+ # end
52
+ # instance_variable_set("@uuid", UUID.generate)
53
+ # instance_variable_set("@service", self.class.name.split('::')[2])
54
+ # end
55
+
56
+ # define_method("_dump".to_sym) do |level|
57
+ # self.to_yaml
58
+ # end
59
+
60
+ # def self._load(str)
61
+ # YAML.load str
62
+ # end
63
+
64
+ # end
65
+ # end
66
+ # end
67
+
68
+ end # class Base
69
+ end # module Api
70
+ end # module Smshelper
@@ -21,7 +21,7 @@ module Smshelper
21
21
  :msisdn => message.recipient,
22
22
  :message => message.text,
23
23
  :sender => message.sender}
24
- options = options.merge(@extra_options) unless @extra_options.nil?
24
+ options.merge!(@extra_options) unless @extra_options.nil?
25
25
  resp = (post 'eapi/submission/send_sms/2/2.0', :extra_query => options.merge(q)).split('|')
26
26
  process_response_code(resp.first) ? (@sent_message_ids << resp.last.strip; resp.last.strip) : (raise ErrorDuringSend, @response_code.bulksms(resp.first))
27
27
  end
@@ -24,6 +24,10 @@ module Smshelper
24
24
  {'EUR' => JSON.parse(post 'api-socket.php', :extra_query => {:function => 'getBalance'})['balance']}
25
25
  end
26
26
 
27
+ def get_status
28
+ raise NotImplementedError, "Sms status checks unsupported by #{self.class.name}"
29
+ end
30
+
27
31
  def hlr_lookup(number)
28
32
  JSON.parse(post 'api-socket.php', :extra_query => {:function => 'doHlrLookup', :number => number})
29
33
  end
@@ -30,6 +30,7 @@ module Smshelper
30
30
  end
31
31
 
32
32
  def get_status(message_id)
33
+ raise NotImplementedError, "Sms status checks unsupported by #{self.class.name}"
33
34
  end
34
35
 
35
36
  def get_callback_response(args = {})
@@ -174,6 +174,69 @@ module Smshelper
174
174
 
175
175
  AQL = {}
176
176
 
177
+ ROUTO = {
178
+ '0' => 'Delivered',
179
+ '1' => 'Rejected: Message length is invalid',
180
+ '2' => 'Subscriber absent',
181
+ '3' => 'Device memory capacity exceeded',
182
+ '4' => 'Equipment protocol error',
183
+ '5' => 'Equipment not supported',
184
+ '6' => 'Equipment not SM equipped',
185
+ '7' => 'Unknown service centre',
186
+ '8' => 'Service centre congestion',
187
+ '9' => 'Undeliverable',
188
+ '10' => 'Rejected: Invalid source address',
189
+ '11' => 'Invalid destination address',
190
+ '12' => 'Illegal subscriber',
191
+ '13' => 'Teleservice not provisioned',
192
+ '14' => 'Illegal equipment',
193
+ '15' => 'Call barred',
194
+ '16' => 'Facility not supported',
195
+ '17' => 'Subscriber busy for SM',
196
+ '18' => 'System failure',
197
+ '19' => 'Message waiting, list full',
198
+ '20' => 'Data missing',
199
+ '21' => 'Unexpected data value',
200
+ '22' => 'Resource limitation',
201
+ '23' => 'Initiating release',
202
+ '24' => 'Unknown alphabet',
203
+ '25' => 'USSD busy',
204
+ '26' => 'Duplicated invoke ID',
205
+ '27' => 'No supported service',
206
+ '28' => 'Mistyped parameter',
207
+ '29' => 'Unexpected response from peer',
208
+ '30' => 'Service completion failure',
209
+ '31' => 'No response from peer',
210
+ '32' => 'Invalid response received',
211
+ '34' => 'Invalid destination',
212
+ '49' => 'Message type not supported',
213
+ '50' => 'Destination blocked for sending',
214
+ '51' => 'Not enough money',
215
+ '52' => 'No price',
216
+ '67' => 'Invalid esm_class field data',
217
+ '69' => 'Rejected by SMSC',
218
+ '72' => 'Rejected: Invalid source address TON',
219
+ '73' => 'Rejected: Invalid source address NPI',
220
+ '80' => 'Rejected: Invalid destination address TON',
221
+ '81' => 'Rejected: Invalid destination address NPI',
222
+ '88' => 'Throttling error',
223
+ '97' => 'Rejected: Invalid scheduled delivery time',
224
+ '100' => 'Error sending message',
225
+ '247' => 'Sent',
226
+ '248' => 'Sent',
227
+ '249' => 'Rejected',
228
+ '250' => 'Accepted',
229
+ '251' => 'Undeliverable',
230
+ '252' => 'Deleted',
231
+ '253' => 'Expired',
232
+ '254' => 'Roaming level not supported',
233
+ '255' => 'Unknown error'
234
+ }
235
+ def routomessaging(code)
236
+ # Those are delivery callback status codes
237
+ ROUTO[code]
238
+ end
239
+
177
240
  def webtext(code)
178
241
  WEBTEXT[code]
179
242
  end
@@ -1,30 +1,67 @@
1
1
  #TODO: different base_uri's for get_balance and send_message
2
- module SmsTools
3
- class Routomessaging < Base
4
- base_uri "http://smsc5.routotelecom.com"
2
+ module Smshelper
3
+ module Api
4
+ class Routomessaging < Base
5
5
 
6
- def initialize(*args)
7
- @uname, @passwd = args.shift, args.shift
8
- end
6
+ def initialize(*args)
7
+ config = args.shift
8
+ @uname, @passwd = config.routomessaging[:uname], config.routomessaging[:passwd]
9
+ add_request_options! :skip_endpoint => true
10
+ super
11
+ end
9
12
 
10
- #send_message TO, MESSAGE, FROM
11
- def send_message(*args)
12
- add_query_options! :user => @uname, :pass => @passwd, :type => 'LongSMS'
13
+ #send_message TO, MESSAGE, FROM
14
+ def send_message(message)
15
+ uuid = (Digest::CRC32.hexdigest @uuid.generate).unpack('U*').collect {|x| sprintf '%02X', x}.join
13
16
 
14
- (post 'SMSsend', :extra_query => {
15
- :number => args.shift,
16
- :message => args.shift,
17
- :ownnum => args.shift})
18
- end
17
+ if message.utf_8
18
+ message.to_hex_be
19
+ q = {:type => 'longunicode'}
20
+ else
21
+ q = {:type => 'LongSMS'}
22
+ end
23
+
24
+ options = {
25
+ :number => message.recipient,
26
+ :message => message.text,
27
+ :ownnum => message.sender
28
+ }
29
+ options.merge!(@extra_options) unless @extra_options.nil?
30
+ options.merge!(:mess_id => uuid) if options[:delivery]
31
+ options.merge!(:user => @uname, :pass => @passwd)
32
+
33
+ resp = (post 'http://smsc5.routotelecom.com/NewSMSsend', :extra_query => options.merge(q))
34
+ process_response_code(resp) ? (@sent_message_ids << uuid; uuid) : (raise ErrorDuringSend, 'error response processing not implemented yet')
35
+ end
19
36
 
20
- def get_balance
21
- # TODO: change base_uri before executing the query
22
- # self.base_uri 'http://smsc6.routotelecom.com'
23
- add_query_options! :username => @uname, :password => @passwd, :base_uri => 'http://smsc6.routotelecom.com'
37
+ def get_balance
38
+ opts = {:username => @uname, :password => @passwd}
39
+ {'EUR' => (post 'http://smsc6.routotelecom.com/balance.php', :extra_query => opts).gsub("\n", '').to_f.round(4)}
40
+ end
24
41
 
25
- (post 'balance.php').to_s.chomp
42
+ def hlr_lookup(number)
43
+ opts = {:number => number, :user => @uname, :pass => @passwd}
44
+ (get 'http://hlr.routotelecom.com', :extra_query => opts)
45
+ end
46
+
47
+ def get_callback_response(args = {})
48
+ DeliveryReport.new(
49
+ :message_id => args['mess_id'],
50
+ :timestamp => Time.now,
51
+ :delivered => ((args['status'] == '0') ? true : false),
52
+ :status => @response_code.routomessaging(args['status']),
53
+ :original_params => args
54
+ )
55
+ end
56
+
57
+ def get_status
58
+ raise NotImplementedError, "Sms status checks unsupported by #{self.class.name}"
59
+ end
60
+
61
+ private
62
+ def process_response_code(code)
63
+ (code.gsub!("\n", '') == 'success') ? true : false
64
+ end
26
65
  end
27
66
  end
28
67
  end
29
-
30
- #
@@ -1,22 +1,25 @@
1
1
  module Smshelper
2
2
  module Api
3
3
  class Smswarehouse < Base
4
- base_uri "http://websms.smswarehouse.com:7800"
5
- endpoint "websms"
4
+ # base_uri "http://websms.smswarehouse.com:7800"
5
+ # endpoint "websms"
6
6
 
7
- def initialize(config)
7
+ def initialize(*args)
8
+ config = args.shift
8
9
  @uname, @passwd = config.smswarehouse[:uname], config.smswarehouse[:passwd]
10
+ add_request_options! :skip_endpoint => true
9
11
  super
10
12
  end
11
13
 
12
14
  def send_message(message)
13
15
 
14
16
  if message.utf_8
15
- message.to_hex
16
- @q = {:type => '0', :esm => '64', :dcs => '8'}
17
+ message.to_hex_be
18
+ q = {:type => '0', :esm => '64', :dcs => '8'}
17
19
  # raise NotImplementedError, "UTF-8 unsupported by #{self.class.name}"
18
20
  else
19
- @q = {:type => '5', :esm => '64', :dcs => '0'}
21
+ #q = {:type => '5', :esm => '64', :dcs => '0'}
22
+ q = {:type => '1', :esm => '0', :dcs => '0'}
20
23
  end
21
24
 
22
25
  options = {
@@ -26,19 +29,25 @@ module Smshelper
26
29
  :text => message.text,
27
30
  :sid => message.sender}
28
31
 
29
- resp = (post "webmsg", :extra_query => @q.merge(options)).split('::').last.strip
32
+ options.merge!(@extra_options) unless @extra_options.nil?
33
+
34
+ url = 'http://websms.smswarehouse.com:7800/websms/webmsg'
35
+ resp = (post url, :extra_query => q.merge(options)) #.split('::').last.strip
30
36
  @sent_message_ids << resp
37
+ pp resp
31
38
  resp
32
39
  end
33
40
 
34
41
  def get_balance
35
- @q = {:userid => @uname, :password => @passwd}
36
- {'EUR' => (post "balanceReport", :extra_query => @q).split(/\n/).last.split('::').last.strip}
42
+ opts = {:userid => @uname, :password => @passwd}
43
+ url = 'http://websms.smswarehouse.com:7800/websms/balanceReport'
44
+ {'EUR' => (post url, :extra_query => opts).split(/\n/).last.split('::').last.strip}
37
45
  end
38
46
 
39
47
  def get_status(message_id)
48
+ url = 'http://websms.smswarehouse.com:7800/websms/websmsstatus'
40
49
  options = {:userid => @uname, :password => @passwd}
41
- resp = (post 'websmsstatus', :extra_query => {:respid => message_id.to_s}.merge(options)).split('-')[1].strip
50
+ resp = (post url, :extra_query => {:respid => message_id.to_s}.merge(options)).split('-')[1].strip
42
51
  @sent_message_statuses[message_id] = []
43
52
  [resp].each_with_index do |status, index|
44
53
  @sent_message_statuses[message_id] << {"part #{index}" => resp}
@@ -46,6 +55,28 @@ module Smshelper
46
55
  {message_id => @sent_message_statuses[message_id]}
47
56
  end
48
57
 
58
+ def get_callback_response(args = {})
59
+ if args['notificationType'] == 'MessageReceived'
60
+ InboundMessage.new(
61
+ :message_id => args['id'],
62
+ :sender => args['originator'],
63
+ :recipient => args['recipient'],
64
+ :text => args['body'],
65
+ :timestamp => Time.now,
66
+ :original_params => args
67
+ )
68
+ elsif args['notificationType'] == 'MessageEvent'
69
+ DeliveryReport.new(
70
+ :message_id => args['id'],
71
+ :timestamp => Time.now,
72
+ :delivered => ((args['eventType'] == 'Delivered') ? true : false),
73
+ :original_params => args
74
+ )
75
+ else
76
+ UnknownReply.new(args)
77
+ end
78
+ end
79
+
49
80
  private
50
81
  def process_response_code(code)
51
82
  (code == 'DELIVRD') ? true : false
@@ -21,9 +21,7 @@ module Smshelper
21
21
  end
22
22
 
23
23
  def get_status(message_id)
24
- @sent_message_statuses[message_id] = []
25
- @sent_message_statuses[message_id] << {"Part 01" => @api.message_status(message_id)}
26
- {message_id => @sent_message_statuses[message_id]}
24
+ raise NotImplementedError, "Sms status checks unsupported by #{self.class.name}"
27
25
  end
28
26
 
29
27
  def get_callback_response(args = {})
@@ -23,7 +23,7 @@ module Smshelper
23
23
  :output => :verbose,
24
24
  :concatenate => true
25
25
  }
26
- options = options.merge(@extra_options) unless @extra_options.nil?
26
+ options.merge!(@extra_options) unless @extra_options.nil?
27
27
  resp = (get 'smsgateway.pl', :extra_query => options.merge(q))
28
28
  process_response_code(resp) ? (@sent_message_ids << resp.split(',')[2]; resp.split(',')[2]) : (raise ErrorDuringSend "Could not deliver")
29
29
  end
@@ -36,6 +36,15 @@ module Smshelper
36
36
  raise NotImplementedError, "Sms status checks unsupported by #{self.class.name}"
37
37
  end
38
38
 
39
+ def get_callback_response(args = {})
40
+ DeliveryReport.new(
41
+ :message_id => args['tt_id'],
42
+ :timestamp => Time.now,
43
+ :delivered => ((args['code'] == '0') ? true : false),
44
+ :original_params => args
45
+ )
46
+ end
47
+
39
48
  private
40
49
  def process_response_code(code)
41
50
  code =~ /accepted/ ? true : false
@@ -1,11 +1,11 @@
1
1
  module Smshelper
2
2
  module Api
3
3
  class Vianett < Base
4
- base_uri 'http://smsc.vianett.no/V3/CPA/MT'
5
4
 
6
5
  def initialize(*args)
7
6
  config = args.shift
8
7
  add_query_options! :username => config.vianett[:uname], :password => config.vianett[:passwd]
8
+ add_request_options! :skip_endpoint => true
9
9
  super
10
10
  end
11
11
 
@@ -13,28 +13,50 @@ module Smshelper
13
13
  uuid = (Digest::CRC32.hexdigest @uuid.generate).unpack('U*').collect {|x| sprintf '%02X', x}.join
14
14
 
15
15
  options = {
16
- :destinationaddr => message.recipient,
17
- :message => message.text,
18
- :sourceaddr => message.sender,
16
+ :tel => message.recipient,
17
+ :msg => message.text,
18
+ :senderaddress => message.sender,
19
+ :senderaddresstype => '1',
20
+ :nrq => '1',
19
21
  # :refno => '1',
20
22
  :msgid => uuid}
21
- options = options.merge(@extra_options) unless @extra_options.nil?
22
- resp = (post 'MT.ashx', :extra_query => options)
23
- process_response_code(resp['ack']) ? (@sent_message_ids << uuid; uuid) : (raise ErrorDuringSend, "#{self.class.name} does not implement detailed errors")
23
+ binding.pry
24
+ options.merge!(@extra_options) unless @extra_options.nil?
25
+ resp = (post 'http://smsc.vianett.no/V3/CPA/MT/MT.ashx', :extra_query => options)
26
+ process_response_code(resp) ? (@sent_message_ids << uuid; uuid) : (raise ErrorDuringSend, "#{self.class.name} does not implement detailed error reporting - #{resp}")
24
27
  end
25
28
 
26
29
  def get_balance
27
- {:fake => :value}
30
+ {'EUR' => (post 'http://oldsms.vianett.com/files/balancelimit_check.asp').split('|').last}
28
31
  end
29
32
 
33
+ # Vianett provides async lookup as well with callbacks
34
+ def hlr_lookup_synchronous(number)
35
+ opts = {:phonenumber => number}
36
+ (get 'http://smsc.vianett.no/v3/cpa/cpawebservice.asmx/SubmitHLR2', :extra_query => opts )['SubmitHLRResponse']
37
+ end
38
+ alias_method :hlr_lookup, :hlr_lookup_synchronous
39
+
30
40
  def get_status(message_id)
31
41
  raise NotImplementedError, "Sms status checks unsupported by #{self.class.name}"
32
42
  end
33
43
 
34
- private
44
+ def get_callback_response(args = {})
45
+ if args['requesttype'] == 'notificationstatus'
46
+ DeliveryReport.new(
47
+ :message_id => args['refno'],
48
+ :timestamp => Time.parse(args['now']),
49
+ :delivered => ((args['Status'] == 'DELIVRD') ? true : false),
50
+ :original_params => args
51
+ )
52
+ else
53
+ UnknownReply.new(args)
54
+ end
55
+ end
35
56
 
57
+ private
36
58
  def process_response_code(code)
37
- (code == 'OK') ? true : false
59
+ (code['ack']['__content__'] == 'OK') ? true : false
38
60
  end
39
61
 
40
62
  end
data/smshelper.gemspec CHANGED
@@ -5,23 +5,23 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "smshelper"
8
- s.version = "0.4.5"
8
+ s.version = "0.4.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Voip Scout"]
12
- s.date = "2012-05-26"
13
- s.description = "works www.bulksms.com, www.webtext.com, www.clickatell.com, www.textmagic.com, www.smstrade.eu, www.esendex.com, www.mediaburst.co.uk, www.nexmo.com, www.vianett.com, www.traitel.com.au, www.my-cool-sms.com, www.aql.com"
12
+ s.date = "2012-05-31"
13
+ s.description = "send sms with multiple gateways, like esendex, bulksms, clickatell etc.."
14
14
  s.email = "voipscout@gmail.com"
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE.txt",
17
- "README.rdoc"
17
+ "README.md"
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
21
21
  ".rspec",
22
22
  "Gemfile",
23
23
  "LICENSE.txt",
24
- "README.rdoc",
24
+ "README.md",
25
25
  "Rakefile",
26
26
  "VERSION",
27
27
  "lib/smshelper.rb",
@@ -55,7 +55,7 @@ Gem::Specification.new do |s|
55
55
  s.licenses = ["MIT"]
56
56
  s.require_paths = ["lib"]
57
57
  s.rubygems_version = "1.8.24"
58
- s.summary = "send sms with: www.bulksms.com, www.webtext.com, www.clickatell.com, www.textmagic.com, www.smstrade.eu, www.esendex.com, www.mediaburst.co.uk, www.nexmo.com, www.vianett.com, www.traitel.com.au, www.my-cool-sms.com, www.aql.com"
58
+ s.summary = "send sms with 10+ gateways"
59
59
 
60
60
  if s.respond_to? :specification_version then
61
61
  s.specification_version = 3
@@ -67,6 +67,7 @@ Gem::Specification.new do |s|
67
67
  s.add_runtime_dependency(%q<textmagic>, [">= 0"])
68
68
  s.add_runtime_dependency(%q<uuid>, [">= 0"])
69
69
  s.add_runtime_dependency(%q<digest-crc>, [">= 0"])
70
+ s.add_runtime_dependency(%q<virtus>, [">= 0"])
70
71
  s.add_development_dependency(%q<pry>, [">= 0"])
71
72
  s.add_development_dependency(%q<rspec>, [">= 0"])
72
73
  s.add_development_dependency(%q<rdoc>, [">= 0"])
@@ -80,6 +81,7 @@ Gem::Specification.new do |s|
80
81
  s.add_dependency(%q<textmagic>, [">= 0"])
81
82
  s.add_dependency(%q<uuid>, [">= 0"])
82
83
  s.add_dependency(%q<digest-crc>, [">= 0"])
84
+ s.add_dependency(%q<virtus>, [">= 0"])
83
85
  s.add_dependency(%q<pry>, [">= 0"])
84
86
  s.add_dependency(%q<rspec>, [">= 0"])
85
87
  s.add_dependency(%q<rdoc>, [">= 0"])
@@ -94,6 +96,7 @@ Gem::Specification.new do |s|
94
96
  s.add_dependency(%q<textmagic>, [">= 0"])
95
97
  s.add_dependency(%q<uuid>, [">= 0"])
96
98
  s.add_dependency(%q<digest-crc>, [">= 0"])
99
+ s.add_dependency(%q<virtus>, [">= 0"])
97
100
  s.add_dependency(%q<pry>, [">= 0"])
98
101
  s.add_dependency(%q<rspec>, [">= 0"])
99
102
  s.add_dependency(%q<rdoc>, [">= 0"])
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smshelper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-26 00:00:00.000000000 Z
12
+ date: 2012-05-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: api_smith
@@ -107,6 +107,22 @@ dependencies:
107
107
  - - ! '>='
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: virtus
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
110
126
  - !ruby/object:Gem::Dependency
111
127
  name: pry
112
128
  requirement: !ruby/object:Gem::Requirement
@@ -203,21 +219,19 @@ dependencies:
203
219
  - - ! '>='
204
220
  - !ruby/object:Gem::Version
205
221
  version: '0'
206
- description: works www.bulksms.com, www.webtext.com, www.clickatell.com, www.textmagic.com,
207
- www.smstrade.eu, www.esendex.com, www.mediaburst.co.uk, www.nexmo.com, www.vianett.com,
208
- www.traitel.com.au, www.my-cool-sms.com, www.aql.com
222
+ description: send sms with multiple gateways, like esendex, bulksms, clickatell etc..
209
223
  email: voipscout@gmail.com
210
224
  executables: []
211
225
  extensions: []
212
226
  extra_rdoc_files:
213
227
  - LICENSE.txt
214
- - README.rdoc
228
+ - README.md
215
229
  files:
216
230
  - .document
217
231
  - .rspec
218
232
  - Gemfile
219
233
  - LICENSE.txt
220
- - README.rdoc
234
+ - README.md
221
235
  - Rakefile
222
236
  - VERSION
223
237
  - lib/smshelper.rb
@@ -261,7 +275,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
261
275
  version: '0'
262
276
  segments:
263
277
  - 0
264
- hash: 2671716086035374482
278
+ hash: 2305576144060548028
265
279
  required_rubygems_version: !ruby/object:Gem::Requirement
266
280
  none: false
267
281
  requirements:
@@ -273,7 +287,5 @@ rubyforge_project:
273
287
  rubygems_version: 1.8.24
274
288
  signing_key:
275
289
  specification_version: 3
276
- summary: ! 'send sms with: www.bulksms.com, www.webtext.com, www.clickatell.com, www.textmagic.com,
277
- www.smstrade.eu, www.esendex.com, www.mediaburst.co.uk, www.nexmo.com, www.vianett.com,
278
- www.traitel.com.au, www.my-cool-sms.com, www.aql.com'
290
+ summary: send sms with 10+ gateways
279
291
  test_files: []
data/README.rdoc DELETED
@@ -1,71 +0,0 @@
1
- = smshelper
2
- A utility library to do SMS-MT
3
-
4
- == Currently supported providers:
5
-
6
- * www.bulksms.com
7
- * www.webtext.com
8
- * www.clickatell.com
9
- * www.textmagic.com
10
- * www.smstrade.eu
11
- * www.esendex.com
12
- * www.mediaburst.co.uk
13
- * www.nexmo.com
14
- * www.vianett.com
15
- * www.traitel.com.au
16
- * www.my-cool-sms.com
17
- * www.aql.com
18
- == Features
19
-
20
- * NEW HLR lookup support via my-cool-sms
21
- * unicode support - all operators
22
- * send message
23
- * check balance, all except vianett
24
- * check sent message status - select operators only
25
- == Installation
26
-
27
- gem install smshelper
28
- == Usage
29
-
30
- require 'smshelper'
31
- config = Smshelper::Config.new(
32
- :webtext => {:uname => '', :passwd => ''},
33
- :bulksms => {:uname => '', :passwd => ''},
34
- :clickatell => {:api_key => '',:uname => '', :passwd => ''},
35
- :textmagic => {:uname => '', :passwd => ''},
36
- :smstrade => {:api_key => ''},
37
- :esendex => {:uname => '', :passwd => '', :acc => ''},
38
- :mediaburst => {:uname => '', :passwd => ''},
39
- :nexmo => {:uname => '', :passwd => ''}
40
- )
41
-
42
- service0 = Smshelper::Api::Bulksms.new config
43
- service1 = Smshelper::Api::Webtext.new config
44
- service2 = Smshelper::Api::Clickatell.new config
45
- service3 = Smshelper::Api::Textmagic.new config
46
- service4 = Smshelper::Api::Smstrade.new config, :route => 'gold'
47
- service5 = Smshelper::Api::Esendex.new config, 'com:validityperiod' => '1'
48
- service6 = Smshelper::Api::MediaBurst.new config
49
- service7 = Smshelper::Api::Nexmo.new config, :ttl => '60000'
50
-
51
- message = Smshelper::Message.new(:recipient => '14128765432', :text => "The balance on #{serviceX.class.to_s} is #{serviceX.get_balance}", :sender => '33765432132')
52
- serviceX.send_message message
53
- == TODO:
54
-
55
- * create tests
56
- * refactor / rewrite class factories as modules
57
- * handle sms of any size - operator specific settings
58
- * add support for www.totext.net, www.world-text.com, www.mpulse.eu, www.clicksms.co.uk, www.tellustalk.com, www.tm4b.com, www.txtnation.com, www.smsextrapro.com, www.truesenses.com, www.routomessaging.net
59
- == Contributing to smshelper
60
-
61
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
62
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
63
- * Fork the project.
64
- * Start a feature/bugfix branch.
65
- * Commit and push until you are happy with your contribution.
66
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
67
- * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
68
-
69
- == Copyright
70
-
71
- Copyright (c) 2012 Voip Scout.