rumeme 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,14 @@
1
+ Version 0.1.3 - 2010-03-11
2
+ ===============================================================================
3
+
4
+ antlypls (5):
5
+ fix rake file
6
+ change long messages settings
7
+ minor code cleanup
8
+ refactor internals
9
+ code cleanup
10
+
11
+
1
12
  Version 0.1.2 - 2010-03-11
2
13
  ===============================================================================
3
14
 
@@ -21,3 +32,4 @@ antlypls (5):
21
32
 
22
33
 
23
34
 
35
+
data/Rakefile CHANGED
@@ -132,12 +132,12 @@ task :push_gem do
132
132
  system "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
133
133
  end
134
134
 
135
- desc 'release gem'
136
- task :release, :part do |t, args|
135
+ desc 'Preparing release'
136
+ task :prepare_release, :part do |t, args|
137
137
  Rake::Task['bump'].invoke(args[:part])
138
138
  Rake::Task['change'].invoke
139
139
  Rake::Task['push'].invoke
140
- Rake::Task['gem'].invoke
141
- Rake::Task['push_gem'].invoke
142
140
  end
143
141
 
142
+ desc 'Building and publishing gem'
143
+ task :publish_release => [:gem, :push_gem]
@@ -1,11 +1,17 @@
1
1
  module Rumeme
2
+ # Holds configuration attributes for sms interface
2
3
  class Configuration
3
4
  attr_accessor :username
4
5
  attr_accessor :password
5
6
  attr_accessor :use_message_id
6
7
  attr_accessor :secure
7
- attr_accessor :allow_splitting
8
- attr_accessor :allow_long_messages
8
+
9
+ #
10
+ # possible values
11
+ # :send - sends messages as is without any modification
12
+ # :split - splits messages into small (less than 160 ch) messages
13
+ # :cut - sends only first 160 symbols
14
+ attr_accessor :long_messages_strategy
9
15
  end
10
16
  end
11
17
 
@@ -7,6 +7,7 @@ module Rumeme
7
7
 
8
8
  # This is the main class used to interface with the M4U SMS messaging server.
9
9
  class SmsInterface
10
+
10
11
  # allow_splitting, allow_long_messages, response_code, response_message, username, password, use_message_id, secure, http_connection, server_list, message_list,
11
12
  # http_proxy, http_proxy_port, http_proxy_auth, https_proxy, https_proxy_port, https_proxy_auth, text_buffer,
12
13
 
@@ -18,24 +19,21 @@ module Rumeme
18
19
  # The allowLongMessages parameter enables messages longer than 160
19
20
  # characters to be sent as special concatenated messages. For this
20
21
  # to take effect, the allowSplitting parameter must be set to false.
21
-
22
22
  def initialize
23
23
  @username = Rumeme.configuration.username
24
24
  @password = Rumeme.configuration.password
25
25
  @use_message_id = Rumeme.configuration.use_message_id
26
26
  @secure = Rumeme.configuration.secure
27
+ @long_messages_strategy = Rumeme.configuration.long_messages_strategy
27
28
 
28
- @allow_splitting, @allow_long_messages = Rumeme.configuration.allow_splitting, Rumeme.configuration.allow_long_messages
29
-
30
29
  @response_code = -1
31
30
  @response_message = nil
32
31
  @message_list = []
33
- @http_connection = nil
34
32
  @http_proxy = nil
35
33
  @http_proxy_port = 80
36
34
  @http_proxy_auth = nil
37
35
  @https_proxy = nil
38
- @https_proxy_port = 443;
36
+ @https_proxy_port = 443
39
37
  @https_proxy_auth = nil
40
38
  @text_buffer = nil
41
39
  @server_list = ["smsmaster.m4u.com.au", "smsmaster1.m4u.com.au", "smsmaster2.m4u.com.au"]
@@ -61,67 +59,16 @@ module Rumeme
61
59
  raise 'proxy is not supported'
62
60
  end
63
61
 
64
- # Return the response code received from calls to
65
- # changePassword, getCreditsRemaining, sendMessages, and
66
- # checkReplies.
67
- attr_reader :response_code
68
-
69
- # Return the message that was returned with the response code.
70
- attr_reader :response_message
71
-
72
62
  # Add a message to be sent.
73
- def add_message args
74
- p 'in add_message '
63
+ def add_message args
64
+ p 'in add_message '
75
65
  args[:phone_number] = strip_invalid(args[:phone_number]) #not good idea, modifying original args, from outer scope (antlypls)
76
66
 
77
67
  raise ArgumentError.new("phone_number is empty") if args[:phone_number].nil? || args[:phone_number].empty?
78
68
  raise ArgumentError.new("message is empty") if args[:message].nil? || args[:message].empty?
79
69
 
80
- if args[:message].length <= 160
81
- @message_list << SmsMessage.new(args)
82
- return
83
- end
84
-
85
- if (@allow_long_messages) # Use concatenation.
86
- args[:message] = args[:message][0..1071] # 1071??? WTF ??? see php code (antlypls)
87
- @message_list << SmsMessage.new(args)
88
- return
89
- end
90
-
91
- if !@allow_splitting
92
- args[:message] = args[:message][0..160] # maybe 159 ? (antlypls)
93
- @message_list << SmsMessage.new(args)
94
- return
95
- end
96
-
97
- ml = []
98
- maxlen = 152
99
- message_text = args[:message]
100
- while message_text.length > maxlen
101
- if (pos = message_text[0..maxlen].rindex(" ")) == 0
102
- pos = maxlen - 1
103
- end
104
-
105
- ml << message_text[0..pos+1]
106
- message_text = message_text[pos + 1 .. -1]
107
- maxlen = 147;
108
- end
109
- ml << message_text
110
-
111
- ml.each_index {|i|
112
- ni = i + 1
113
- if (i == 0)
114
- m = ml[i]
115
- else
116
- m = "(#{ni}/#{ml.size})#{ml[i]}"
117
- end
118
-
119
- if (ni != ml.size )
120
- m << "...(#{ni}/#{ml.size})"
121
- end
122
-
123
- @message_list << SmsMessage.new(args.merge({:message => m, :delay => args[:delay] + 30*i}))
124
- }
70
+ messages = process_long_message(args[:message])
71
+ @message_list.concat(messages.map{|m| SmsMessage.new(args.merge({:message => m}))})
125
72
  end
126
73
 
127
74
  # Clear all the messages from the list.
@@ -129,26 +76,13 @@ module Rumeme
129
76
  @message_list.clear
130
77
  end
131
78
 
132
- # Open a connection to the specified server.
133
- # proxy is not supported
134
79
  def open_server_connection server, secure
135
- p "in open_server_connection: #{server} #{secure}"
136
- if secure
137
- @http_connection = Net::HTTP.new(server, 443)
138
- @http_connection.use_ssl = true
139
-
140
- else
141
- @http_connection = Net::HTTP.new(server, 80)
142
- end
80
+ port, use_ssl = secure ? [443, true] : [80, false]
143
81
 
144
- p @http_connection.inspect
145
-
146
- @http_connection.nil? ? false : true
147
- end
148
-
149
- # 4 php api compatibility, returns response code from latest http flush
150
- def read_response_code
151
- @latest_response_code
82
+ http_connection = Net::HTTP.new(server, port)
83
+ http_connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
84
+ http_connection.use_ssl = use_ssl
85
+ http_connection
152
86
  end
153
87
 
154
88
  # Change the password on the local machine and server.
@@ -159,60 +93,31 @@ module Rumeme
159
93
 
160
94
  # Return the list of replies we have received.
161
95
  def check_replies auto_confirm = true
162
- connect
163
96
  p 'in check_replies'
164
- return nil if @http_connection.nil?
165
- @text_buffer << "CHECKREPLY2.0\r\n.\r\n"
166
-
167
- if (!flush_buffer || read_response_code != 150)
168
- close
169
- return nil
170
- end
171
97
 
172
- p @response_message
98
+ response_message, response_code = post_data_to_server("CHECKREPLY2.0\r\n.\r\n")
99
+ return if response_code != 150
173
100
 
174
- messages = @response_message.split("\r\n")[1..-2].map{|message_line| SmsReply.parse(message_line, @use_message_id)}
175
-
176
- close
177
-
178
- if auto_confirm && messages.size > 0
179
- confirm_replies_received
180
- end
101
+ messages = response_message.split("\r\n")[1..-2].map{|message_line| SmsReply.parse(message_line, @use_message_id)}
102
+ confirm_replies_received if auto_confirm && messages.size > 0
181
103
 
182
104
  return messages
183
105
  end
184
106
 
185
107
  # sends confirmation to server
186
108
  def confirm_replies_received
187
- connect
188
109
  p 'in confirm_replies_received'
189
- return nil if @http_connection.nil?
190
- ok = true
191
-
192
- @text_buffer << "CONFIRM_RECEIVED\r\n.\r\n";
193
- if !flush_buffer
194
- ok = false
195
- end
196
-
197
- close
198
- p "result: #{ok}"
199
-
200
- return ok;
110
+ post_data_to_server "CONFIRM_RECEIVED\r\n.\r\n"
201
111
  end
202
112
 
203
113
  # Returns the credits remaining (for prepaid users only).
204
114
  def get_credits_remaining
205
- connect
206
- return -2 if @http_connection.nil?
207
- @text_buffer << "MESSAGES\r\n.\r\n"
115
+ p 'in get_credits_remaining'
208
116
 
209
- if (!flush_buffer)
210
- close
211
- return -2
212
- end
117
+ response_message, response_code = post_data_to_server("MESSAGES\r\n.\r\n")
213
118
 
214
119
  if response_message =~ /^(\d+)\s+OK\s+(\d+).+/
215
- if $1.to_i != 100
120
+ if response_code != 100
216
121
  p 'M4U code is not 100'
217
122
  return -1
218
123
  end
@@ -226,70 +131,90 @@ module Rumeme
226
131
  # Sends all the messages that have been added with the
227
132
  # add_message command.
228
133
  def send_messages
229
- connect
230
- return false if @http_connection.nil?
231
- @text_buffer << "MESSAGES2.0\r\n"
134
+ text_buffer = "MESSAGES2.0\r\n"
232
135
 
233
136
  @message_list.each {|sm|
234
137
  s = "#{sm.message_id} #{sm.phone_number} #{sm.delay} #{sm.validity_period} "
235
138
  s << (sm.delivery_report ? "1 " : "0 ")
236
- s << "#{sm.message}\r\n";
237
- @text_buffer << s
139
+ s << "#{sm.message}\r\n"
140
+ text_buffer << s
238
141
  }
142
+ text_buffer << ".\r\n"
239
143
 
240
- ok = true
241
- @text_buffer << ".\r\n";
242
- if (!flush_buffer || (read_response_code / 100) != 1)
243
- ok = false;
244
- end
144
+ response_message, response_code = post_data_to_server(text_buffer)
245
145
 
246
- close
247
- return ok
146
+ return response_code == 100 ? true : false
248
147
  end
249
148
 
250
149
  private
251
150
 
151
+ def process_long_message message
152
+ return [message] if message.length <= 160
153
+ case @long_messages_strategy
154
+ when :send
155
+ [message]
156
+ when :cut
157
+ [message[0..160]]
158
+ when :split
159
+ SmsInterface.split_message message
160
+ else
161
+ raise 'unknown long_messages_strategy'
162
+ end
163
+ end
164
+
165
+ def self.split_message message
166
+ messages = split_message_internal message
167
+ i = 1
168
+ ["#{messages[0]}...(1/#{messages.size})"].concat(messages[1..-1].map {|m| "(#{i+=1}/#{messages.size})#{m}"})
169
+ end
170
+
171
+ def self.split_message_internal message
172
+ list =[]
173
+
174
+ head, message = head_tail_split(message, 152)
175
+ list << head
176
+
177
+ while !message.nil? do
178
+ head, message = head_tail_split(message, 155)
179
+ list << head
180
+ end
181
+
182
+ list
183
+ end
184
+
185
+ def self.head_tail_split message, max_len
186
+ return [message, nil] if message.length < max_len
187
+ pattern = /\s\.,!;:-\)/
188
+ index = message[0..max_len].rindex(pattern) || max_len
189
+ [message[0..index], message[index+1 .. -1]]
190
+ end
191
+
252
192
  # Strip invalid characters from the phone number.
253
193
  def strip_invalid phone
254
194
  return if phone.nil?
255
195
  "+#{phone.gsub(/[^0-9]/, '')}"
256
196
  end
257
197
 
258
- # Connect to the M4U server
259
- def connect
260
- p 'in connect'
261
- return unless @http_connection.nil?
262
-
263
- @server_list.all? {|server| !open_server_connection(server, @secure)} # unusefull code open_server_connection,
264
- # does not connect to server, just creates http object,
265
- # so we can't check availability of the server at this moment (antlypls)
198
+ def post_data_to_server data
199
+ p 'post_data_to_server'
266
200
 
267
- return if @http_connection.nil?
201
+ http_connection = open_server_connection(@server_list[0], @secure)
268
202
 
269
- @text_buffer = "m4u\r\nUSER=#{@username}"
203
+ text_buffer = "m4u\r\nUSER=#{@username}"
270
204
  if @use_message_id
271
- @text_buffer << "#"
205
+ text_buffer << "#"
272
206
  end
273
- @text_buffer << "\r\nPASSWORD=#{@password}\r\nVER=PHP1.0\r\n";
274
- end
207
+ text_buffer << "\r\nPASSWORD=#{@password}\r\nVER=PHP1.0\r\n"
275
208
 
276
- # only for php compatibility, just free object reference
277
- def close
278
- @http_connection = nil unless @http_connection.nil?
279
- end
209
+ text_buffer << data
280
210
 
281
- # Flush the text buffer to the HTTP connection.
282
- def flush_buffer
283
- p 'in flush_buffer'
284
- p "buffer: #{@text_buffer}"
285
- headers = {
286
- 'Content-Length' => @text_buffer.length.to_s
287
- }
211
+ p "buffer: #{text_buffer}"
212
+ headers = {'Content-Length' => text_buffer.length.to_s}
288
213
 
289
214
  path = '/'
290
215
 
291
216
  begin
292
- resp, data = @http_connection.post(path, @text_buffer, headers)
217
+ resp, data = http_connection.post(path, text_buffer, headers)
293
218
  p resp.inspect
294
219
  p data.inspect
295
220
  rescue
@@ -297,28 +222,25 @@ module Rumeme
297
222
  return false
298
223
  end
299
224
 
300
-
301
225
  if resp.code.to_i != 200
302
226
  p 'http response code != 200'
303
227
  return false
304
228
  end
305
229
 
306
- @latest_response_code = @response_code = resp.code.to_i
307
-
308
230
  doc = Nokogiri::HTML(data)
309
231
 
310
232
  return false if doc.xpath('//title').text != "M4U SMSMASTER"
311
233
 
312
- @response_message = @latest_response = doc.xpath('//body').text.strip
313
- if @response_message =~ /^(\d+)\s+/
314
- @latest_response_code = @response_code = $1.to_i
234
+ response_message = doc.xpath('//body').text.strip
235
+ response_code = nil
236
+ if response_message =~ /^(\d+)\s+/
237
+ response_code = $1.to_i
315
238
  end
316
239
 
317
- p "latest response code: #{ @latest_response_code}"
318
- p "response #{@response_message.inspect}"
240
+ p "latest response code: #{response_code}"
241
+ p "response #{response_message }"
319
242
 
320
- @text_buffer = ''
321
- return true
243
+ [response_message, response_code]
322
244
  end
323
245
  end
324
246
  end
@@ -1,3 +1,3 @@
1
1
  module Rumeme
2
- VERSION = "0.1.2".freeze
2
+ VERSION = "0.1.3".freeze
3
3
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 2
9
- version: 0.1.2
8
+ - 3
9
+ version: 0.1.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - antlypls