rumeme 0.1.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.
- 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
|
+
|