rumeme 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +9 -0
- data/Rakefile +32 -0
- data/lib/rumeme/configuration.rb +12 -0
- data/lib/rumeme/message_status.rb +11 -0
- data/lib/rumeme/sms_interface.rb +319 -0
- data/lib/rumeme/sms_message.rb +12 -0
- data/lib/rumeme/sms_reply.rb +74 -0
- data/lib/rumeme/validity_period.rb +14 -0
- data/lib/rumeme/version.rb +3 -0
- data/lib/rumeme.rb +17 -0
- metadata +86 -0
data/README.rdoc
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
= RuMeMe
|
2
|
+
Ruby SDK for Message Media SMS Gateway API.
|
3
|
+
Since Message Media doesn't provide any ruby projects support, we decided to port it from available SDKs (mainly from PHP SDK; and some .NET usage).
|
4
|
+
For more information checkout {Message Media SMS APIs}[http://www.message-media.com/sms-gateway.html].
|
5
|
+
|
6
|
+
= To Do
|
7
|
+
* Refactoring to make api more rubyish.
|
8
|
+
* Add unit tests
|
9
|
+
* Extend documentation with Usage section.
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
|
4
|
+
GEM_ROOT = File.dirname(__FILE__).freeze
|
5
|
+
VERSION_FILE = File.join(GEM_ROOT, 'lib', 'rumeme', 'version')
|
6
|
+
|
7
|
+
require VERSION_FILE
|
8
|
+
|
9
|
+
gemspec = Gem::Specification.new do |s|
|
10
|
+
s.name = 'rumeme'
|
11
|
+
s.version = Rumeme::VERSION
|
12
|
+
s.summary = 'Ruby SDK for Message Media SMS Gateway API'
|
13
|
+
|
14
|
+
s.files = FileList['[A-Z]*', 'lib/**/*.rb']
|
15
|
+
s.require_path = 'lib'
|
16
|
+
|
17
|
+
s.extra_rdoc_files = ['README.rdoc']
|
18
|
+
s.rdoc_options = ['--line-numbers', "--main", "README.rdoc"]
|
19
|
+
|
20
|
+
s.add_runtime_dependency('nokogiri', '1.4.1')
|
21
|
+
|
22
|
+
s.authors = ['antlypls']
|
23
|
+
s.email = 'antlypls@gmail.com'
|
24
|
+
s.homepage = 'http://github.com/programmable/rumeme'
|
25
|
+
|
26
|
+
s.platform = Gem::Platform::RUBY
|
27
|
+
end
|
28
|
+
|
29
|
+
Rake::GemPackageTask.new gemspec do |pkg|
|
30
|
+
pkg.need_tar = true
|
31
|
+
pkg.need_zip = true
|
32
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Rumeme
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :username
|
4
|
+
attr_accessor :password
|
5
|
+
attr_accessor :use_message_id
|
6
|
+
attr_accessor :secure
|
7
|
+
#attr_accessor :proxy_settings
|
8
|
+
attr_accessor :allow_splitting
|
9
|
+
attr_accessor :allow_long_messages
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
@@ -0,0 +1,319 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "net/https"
|
3
|
+
require 'rubygems'
|
4
|
+
require 'nokogiri'
|
5
|
+
|
6
|
+
module Rumeme
|
7
|
+
|
8
|
+
# This is the main class used to interface with the M4U SMS messaging server.
|
9
|
+
class SmsInterface
|
10
|
+
# allow_splitting, allow_long_messages, response_code, response_message, username, password, use_message_id, secure, http_connection, server_list, message_list,
|
11
|
+
# http_proxy, http_proxy_port, http_proxy_auth, https_proxy, https_proxy_port, https_proxy_auth, text_buffer,
|
12
|
+
|
13
|
+
# Constructor.
|
14
|
+
#
|
15
|
+
# The allowSplitting parameter determines whether messages over
|
16
|
+
# 160 characters will be split over multiple SMSes or truncated.
|
17
|
+
#
|
18
|
+
# The allowLongMessages parameter enables messages longer than 160
|
19
|
+
# characters to be sent as special concatenated messages. For this
|
20
|
+
# to take effect, the allowSplitting parameter must be set to false.
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
@username = Rumeme.configuration.username
|
24
|
+
@password = Rumeme.configuration.password
|
25
|
+
@use_message_id = Rumeme.configuration.use_message_id
|
26
|
+
@secure = Rumeme.configuration.secure
|
27
|
+
|
28
|
+
@allow_splitting, @allow_long_messages = Rumeme.configuration.allow_splitting, Rumeme.configuration.allow_long_messages
|
29
|
+
|
30
|
+
@response_code = -1
|
31
|
+
@response_message = nil
|
32
|
+
@use_message_id = false
|
33
|
+
@message_list = []
|
34
|
+
@http_connection = nil
|
35
|
+
@http_proxy = nil
|
36
|
+
@http_proxy_port = 80
|
37
|
+
@http_proxy_auth = nil
|
38
|
+
@https_proxy = nil
|
39
|
+
@https_proxy_port = 443;
|
40
|
+
@https_proxy_auth = nil
|
41
|
+
@text_buffer = nil
|
42
|
+
@server_list = ["smsmaster.m4u.com.au", "smsmaster1.m4u.com.au", "smsmaster2.m4u.com.au"]
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
# Set the HTTP proxy server, if one is being used.
|
47
|
+
# Also specify an optional proxy username and password.
|
48
|
+
# only for php version
|
49
|
+
def set_http_proxy proxy, port = 80, username = nil, password = nil
|
50
|
+
@http_proxy, @http_proxy_port = proxy, port
|
51
|
+
@http_proxy_username, @http_proxy_password = username, password
|
52
|
+
@http_proxy_auth = Base64.encode64("#{username}:#{password}").chop unless username.nil? || password.nil?
|
53
|
+
raise 'proxy is not supported'
|
54
|
+
end
|
55
|
+
|
56
|
+
# Set the HTTPS proxy server, if one is being used.
|
57
|
+
# Also specify an optional proxy username and password.
|
58
|
+
# only for php version
|
59
|
+
def set_https_proxy proxy, port = 443, username = nil, password = nil
|
60
|
+
@https_proxy, @https_proxy_port = proxy, port
|
61
|
+
@https_proxy_auth = Base64.encode64("#{username}:#{password}").chop unless username.nil? || password.nil?
|
62
|
+
raise 'proxy is not supported'
|
63
|
+
end
|
64
|
+
|
65
|
+
# Return the response code received from calls to
|
66
|
+
# changePassword, getCreditsRemaining, sendMessages, and
|
67
|
+
# checkReplies.
|
68
|
+
attr_reader :response_code
|
69
|
+
|
70
|
+
# Return the message that was returned with the response code.
|
71
|
+
attr_reader :response_message
|
72
|
+
|
73
|
+
# Add a message to be sent.
|
74
|
+
def add_message phone, message_text, message_id = 0, delay = 0, validity_period = 169, delivery_report = false
|
75
|
+
p 'in add_message '
|
76
|
+
phone = strip_invalid(phone);
|
77
|
+
return if phone.empty?
|
78
|
+
|
79
|
+
if message_text.length <= 160
|
80
|
+
@message_list << SmsMessage.new(phone, message_text, message_id, delay, validity_period, delivery_report)
|
81
|
+
return
|
82
|
+
end
|
83
|
+
|
84
|
+
if (@allow_long_messages) # Use concatenation.
|
85
|
+
@message_list << SmsMessage.new(phone, message_text[0..1071], message_id, delay, validity_period, delivery_report) # 1071??? WTF ??? see php code
|
86
|
+
return
|
87
|
+
end
|
88
|
+
|
89
|
+
if !@allow_splitting
|
90
|
+
@message_list << SmsMessage.new(phone, message_text[0..160], message_id, delay, validity_period, delivery_report)
|
91
|
+
return
|
92
|
+
end
|
93
|
+
|
94
|
+
ml = []
|
95
|
+
maxlen = 152;
|
96
|
+
while message_text.length > maxlen
|
97
|
+
if (pos = message_text[0..maxlen].rindex(" ")) == 0
|
98
|
+
pos = maxlen - 1
|
99
|
+
end
|
100
|
+
|
101
|
+
ml << message_text[0..pos+1]
|
102
|
+
message_text = message_text[pos + 1 .. -1]
|
103
|
+
maxlen = 147;
|
104
|
+
end
|
105
|
+
ml << message_text
|
106
|
+
|
107
|
+
ml.each_index {|i|
|
108
|
+
ni = i + 1
|
109
|
+
if (i == 0)
|
110
|
+
m = ml[i]
|
111
|
+
else
|
112
|
+
m = "(#{ni}/#{ml.size})#{ml[i]}"
|
113
|
+
end
|
114
|
+
|
115
|
+
if (ni != ml.size )
|
116
|
+
m << "...(#{ni}/#{ml.size})"
|
117
|
+
end
|
118
|
+
|
119
|
+
@message_list << SmsMessage.new(phone, m, message_id, delay + 30*i, validity_period, delivery_report)
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
# Clear all the messages from the list.
|
124
|
+
def clear_messages
|
125
|
+
@message_list.clear
|
126
|
+
end
|
127
|
+
|
128
|
+
# Open a connection to the specified server.
|
129
|
+
# proxy is not supported
|
130
|
+
def open_server_connection server, secure
|
131
|
+
p "in open_server_connection: #{server} #{secure}"
|
132
|
+
if secure
|
133
|
+
@http_connection = Net::HTTP.new(server, 443)
|
134
|
+
@http_connection.use_ssl = true
|
135
|
+
|
136
|
+
else
|
137
|
+
@http_connection = Net::HTTP.new(server, 80)
|
138
|
+
end
|
139
|
+
|
140
|
+
p @http_connection.inspect
|
141
|
+
|
142
|
+
@http_connection.nil? ? false : true
|
143
|
+
end
|
144
|
+
|
145
|
+
# 4 php api compatibility, returns response code from latest http flush
|
146
|
+
def read_response_code
|
147
|
+
@latest_response_code
|
148
|
+
end
|
149
|
+
|
150
|
+
# Change the password on the local machine and server.
|
151
|
+
# not implemented
|
152
|
+
def change_password
|
153
|
+
raise 'Not Implemented'
|
154
|
+
end
|
155
|
+
|
156
|
+
# Return the list of replies we have received.
|
157
|
+
def check_replies auto_confirm = true
|
158
|
+
connect
|
159
|
+
p 'in check_replies'
|
160
|
+
return nil if @http_connection.nil?
|
161
|
+
@text_buffer << "CHECKREPLY2.0\r\n.\r\n"
|
162
|
+
|
163
|
+
if (!flush_buffer || read_response_code != 150)
|
164
|
+
close
|
165
|
+
return nil
|
166
|
+
end
|
167
|
+
|
168
|
+
p @response_message
|
169
|
+
|
170
|
+
messages = @response_message.split("\r\n")[1..-2].map{|message_line| SmsReply.parse(message_line, @use_message_id)}
|
171
|
+
|
172
|
+
close
|
173
|
+
|
174
|
+
if auto_confirm && messages.size > 0
|
175
|
+
confirm_replies_received
|
176
|
+
end
|
177
|
+
|
178
|
+
return messages
|
179
|
+
end
|
180
|
+
|
181
|
+
# sends confirmation to server
|
182
|
+
def confirm_replies_received
|
183
|
+
connect
|
184
|
+
p 'in confirm_replies_received'
|
185
|
+
return nil if @http_connection.nil?
|
186
|
+
ok = true
|
187
|
+
|
188
|
+
@text_buffer << "CONFIRM_RECEIVED\r\n.\r\n";
|
189
|
+
if !flush_buffer
|
190
|
+
ok = false
|
191
|
+
end
|
192
|
+
|
193
|
+
close
|
194
|
+
p "result: #{ok}"
|
195
|
+
|
196
|
+
return ok;
|
197
|
+
end
|
198
|
+
|
199
|
+
# Returns the credits remaining (for prepaid users only).
|
200
|
+
def get_credits_remaining
|
201
|
+
connect
|
202
|
+
return -2 if @http_connection.nil?
|
203
|
+
@text_buffer << "MESSAGES\r\n.\r\n"
|
204
|
+
|
205
|
+
if (!flush_buffer)
|
206
|
+
close
|
207
|
+
return -2
|
208
|
+
end
|
209
|
+
|
210
|
+
if response_message =~ /^(\d+)\s+OK\s+(\d+).+/
|
211
|
+
if $1.to_i != 100
|
212
|
+
p 'M4U code is not 100'
|
213
|
+
return -1
|
214
|
+
end
|
215
|
+
return $2.to_i
|
216
|
+
else
|
217
|
+
p "cant parse response: #{response_message}"
|
218
|
+
return -1
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Sends all the messages that have been added with the
|
223
|
+
# add_message command.
|
224
|
+
def send_messages
|
225
|
+
connect
|
226
|
+
return false if @http_connection.nil?
|
227
|
+
@text_buffer << "MESSAGES2.0\r\n"
|
228
|
+
|
229
|
+
@message_list.each {|sm|
|
230
|
+
s = "#{sm.message_id} #{sm.phone_number} #{sm.delay} #{sm.validity_period} "
|
231
|
+
s << (sm.delivery_report ? "1 " : "0 ")
|
232
|
+
s << "#{sm.message}\r\n";
|
233
|
+
@text_buffer << s
|
234
|
+
}
|
235
|
+
|
236
|
+
ok = true
|
237
|
+
@text_buffer << ".\r\n";
|
238
|
+
if (!flush_buffer || (read_response_code / 100) != 1)
|
239
|
+
ok = false;
|
240
|
+
end
|
241
|
+
|
242
|
+
close
|
243
|
+
return ok
|
244
|
+
end
|
245
|
+
|
246
|
+
private
|
247
|
+
|
248
|
+
# Strip invalid characters from the phone number.
|
249
|
+
def strip_invalid phone
|
250
|
+
"+#{phone.gsub(/[^0-9]/, '')}"
|
251
|
+
end
|
252
|
+
|
253
|
+
# Connect to the M4U server
|
254
|
+
def connect
|
255
|
+
p 'in connect'
|
256
|
+
return unless @http_connection.nil?
|
257
|
+
|
258
|
+
@server_list.all? {|server| !open_server_connection(server, @secure)} #unusefull code open_server_connection, do not connetct to server, just creates http object, so we can't check availability of the server
|
259
|
+
|
260
|
+
return if @http_connection.nil?
|
261
|
+
|
262
|
+
@text_buffer = "m4u\r\nUSER=#{@username}"
|
263
|
+
if @use_message_id
|
264
|
+
@text_buffer << "#"
|
265
|
+
end
|
266
|
+
@text_buffer << "\r\nPASSWORD=#{@password}\r\nVER=PHP1.0\r\n";
|
267
|
+
end
|
268
|
+
|
269
|
+
# only 4 php compatibility, just free object reference
|
270
|
+
def close
|
271
|
+
return if @http_connection.nil?
|
272
|
+
#@http_connection.finish
|
273
|
+
@http_connection = nil
|
274
|
+
end
|
275
|
+
|
276
|
+
# Flush the text buffer to the HTTP connection.
|
277
|
+
def flush_buffer
|
278
|
+
p 'in flush_buffer'
|
279
|
+
p "buffer: #{@text_buffer}"
|
280
|
+
headers = {
|
281
|
+
'Content-Length' => @text_buffer.length.to_s
|
282
|
+
}
|
283
|
+
|
284
|
+
path = '/'
|
285
|
+
|
286
|
+
begin
|
287
|
+
resp, data = @http_connection.post(path, @text_buffer, headers)
|
288
|
+
p resp.inspect
|
289
|
+
p data.inspect
|
290
|
+
rescue
|
291
|
+
p "error: #{$!}"
|
292
|
+
return false
|
293
|
+
end
|
294
|
+
|
295
|
+
|
296
|
+
if resp.code.to_i != 200
|
297
|
+
p 'http response code != 200'
|
298
|
+
return false
|
299
|
+
end
|
300
|
+
|
301
|
+
@latest_response_code = @response_code = resp.code.to_i
|
302
|
+
|
303
|
+
doc = Nokogiri::HTML(data)
|
304
|
+
|
305
|
+
return false if doc.xpath('//title').text != "M4U SMSMASTER"
|
306
|
+
|
307
|
+
@response_message = @latest_response = doc.xpath('//body').text.strip
|
308
|
+
if @response_message =~ /^(\d+)\s+/
|
309
|
+
@latest_response_code = @response_code = $1.to_i
|
310
|
+
end
|
311
|
+
|
312
|
+
p "latest response code: #{ @latest_response_code}"
|
313
|
+
p "response #{@response_message.inspect}"
|
314
|
+
|
315
|
+
@text_buffer = ''
|
316
|
+
return true
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Rumeme
|
2
|
+
# This class represents an SMS message.
|
3
|
+
class SmsMessage
|
4
|
+
attr_reader :phone_number, :message, :message_id, :delay, :validity_period, :delivery_report
|
5
|
+
|
6
|
+
# Constructor.
|
7
|
+
def initialize phone_number, message, message_id, delay, validity_period, delivery_report
|
8
|
+
@phone_number, @message, @message_id, @delay, @validity_period, @delivery_report = phone_number, message, message_id, delay, validity_period, delivery_report
|
9
|
+
@message = message.gsub("\n",'\n').gsub("\r",'\r').gsub("\\",'\\\\')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Rumeme
|
2
|
+
# This class represents an SMS reply.
|
3
|
+
class SmsReply
|
4
|
+
#attr_accessor :phone_number, :message, :message_id, :when, :status
|
5
|
+
attr_reader :phone_number, :message, :message_id, :when, :status
|
6
|
+
|
7
|
+
#Constructor.
|
8
|
+
def initialize phone_number, message, message_id, _when, status
|
9
|
+
@phone_number, @message, @message_id, @when, @status = phone_number, message, message_id, _when, status
|
10
|
+
end
|
11
|
+
|
12
|
+
# Unescape any escaped characters in the string.
|
13
|
+
def self.unescape line
|
14
|
+
line.nil? ? nil : line.gsub('\n', "\n").gsub('\r', "\r").gsub('\\\\', "\\")
|
15
|
+
end
|
16
|
+
|
17
|
+
#Parse a reply from a string.
|
18
|
+
# Format is: messageID phone when message
|
19
|
+
# Or if no message ID: phone when message
|
20
|
+
# Or if delivery receipt: messageID messageStatus when
|
21
|
+
# php suxx. reimplement using regex
|
22
|
+
def self.parse line, use_message_id
|
23
|
+
p "parsing line: #{line}. #{use_message_id}."
|
24
|
+
message_id = 0;
|
25
|
+
status = MessageStatus::NONE
|
26
|
+
|
27
|
+
prev_idx = 0;
|
28
|
+
if (idx = line.index(' ')) == nil
|
29
|
+
return nil
|
30
|
+
end
|
31
|
+
|
32
|
+
if (use_message_id)
|
33
|
+
if line[0..idx] =~ /\d+/
|
34
|
+
message_id = line[0..idx].to_i
|
35
|
+
else
|
36
|
+
return nil
|
37
|
+
end
|
38
|
+
|
39
|
+
prev_idx = idx + 1
|
40
|
+
if (idx = line.index(' ', idx + 1)) == nil
|
41
|
+
return nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
phone = line[prev_idx .. idx - 1]
|
46
|
+
|
47
|
+
if phone.length == 1
|
48
|
+
status = case phone # why not use to_i ??
|
49
|
+
when "1"
|
50
|
+
MessageStatus::PENDING
|
51
|
+
when "2"
|
52
|
+
MessageStatus::DELIVERED
|
53
|
+
when "3"
|
54
|
+
MessageStatus::FAILED
|
55
|
+
else
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
phone = ""
|
59
|
+
end
|
60
|
+
|
61
|
+
prev_idx = idx + 1;
|
62
|
+
idx = line.index(' ', idx + 1) || line.length
|
63
|
+
|
64
|
+
if line[prev_idx .. idx-1] =~ /\d+/
|
65
|
+
when_ = $&.to_i
|
66
|
+
else
|
67
|
+
return nil
|
68
|
+
end
|
69
|
+
|
70
|
+
message = (status != MessageStatus::NONE) || (line.length < idx + 2) ? "" : unescape(line[idx + 1 .. -1])
|
71
|
+
return SmsReply.new(phone, message, message_id, when_, status)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Rumeme
|
2
|
+
# This class defines constants used to specify the validity period
|
3
|
+
# of messages injected into the SMS network.
|
4
|
+
class ValidityPeriod
|
5
|
+
MINIMUM = 0
|
6
|
+
ONE_HOUR = 11
|
7
|
+
SIX_HOURS= 71
|
8
|
+
ONE_DAY = 167
|
9
|
+
TWO_DAYS = 168
|
10
|
+
THREE_DAYS = 169
|
11
|
+
ONE_WEEK = 173
|
12
|
+
MAXIMUM = 255
|
13
|
+
end
|
14
|
+
end
|
data/lib/rumeme.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rumeme/configuration"
|
2
|
+
require "rumeme/message_status"
|
3
|
+
require "rumeme/validity_period"
|
4
|
+
require "rumeme/sms_message"
|
5
|
+
require "rumeme/sms_reply"
|
6
|
+
require "rumeme/sms_interface"
|
7
|
+
|
8
|
+
module Rumeme
|
9
|
+
class << self
|
10
|
+
attr_accessor :configuration
|
11
|
+
|
12
|
+
def configure
|
13
|
+
self.configuration ||= Configuration.new
|
14
|
+
yield(configuration)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rumeme
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- antlypls
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-03-09 00:00:00 +04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: nokogiri
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 4
|
30
|
+
- 1
|
31
|
+
version: 1.4.1
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
description:
|
35
|
+
email: antlypls@gmail.com
|
36
|
+
executables: []
|
37
|
+
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files:
|
41
|
+
- README.rdoc
|
42
|
+
files:
|
43
|
+
- README.rdoc
|
44
|
+
- Rakefile
|
45
|
+
- lib/rumeme.rb
|
46
|
+
- lib/rumeme/sms_interface.rb
|
47
|
+
- lib/rumeme/version.rb
|
48
|
+
- lib/rumeme/configuration.rb
|
49
|
+
- lib/rumeme/sms_message.rb
|
50
|
+
- lib/rumeme/message_status.rb
|
51
|
+
- lib/rumeme/sms_reply.rb
|
52
|
+
- lib/rumeme/validity_period.rb
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: http://github.com/programmable/rumeme
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options:
|
59
|
+
- --line-numbers
|
60
|
+
- --main
|
61
|
+
- README.rdoc
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
version: "0"
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
version: "0"
|
78
|
+
requirements: []
|
79
|
+
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 1.3.6
|
82
|
+
signing_key:
|
83
|
+
specification_version: 3
|
84
|
+
summary: Ruby SDK for Message Media SMS Gateway API
|
85
|
+
test_files: []
|
86
|
+
|