textmagic 0.3.3 → 0.4.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/.gitignore +1 -0
- data/README.rdoc +2 -2
- data/Rakefile +22 -21
- data/VERSION.yml +3 -2
- data/lib/api.rb +52 -52
- data/lib/charset.rb +3 -1
- data/lib/error.rb +2 -2
- data/lib/executor.rb +6 -6
- data/lib/response.rb +20 -20
- data/lib/textmagic.rb +3 -3
- data/test/test_api.rb +69 -67
- data/test/test_charset.rb +16 -15
- data/test/test_error.rb +5 -5
- data/test/test_executor.rb +17 -18
- data/test/test_helper.rb +8 -12
- data/test/test_response.rb +75 -75
- data/test/test_validation.rb +26 -27
- data/textmagic.gemspec +24 -17
- metadata +77 -25
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
@@ -145,8 +145,8 @@ to all of the gem's features. Run
|
|
145
145
|
|
146
146
|
from your console to see help on its usage.
|
147
147
|
|
148
|
-
<i>Note: This has only been tested on a Mac. If you have any troubles
|
149
|
-
|
148
|
+
<i>Note: This has only been tested on a Mac with Ruby 1.8.7 and 1.9.1. If you have any troubles
|
149
|
+
using this gem, contact the author (or submit a patch).</i>
|
150
150
|
|
151
151
|
== Copyright
|
152
152
|
|
data/Rakefile
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "rake"
|
5
|
+
require "yaml"
|
6
|
+
require "rake/testtask"
|
7
|
+
require "rake/rdoctask"
|
4
8
|
|
5
9
|
begin
|
6
|
-
require
|
10
|
+
require "jeweler"
|
7
11
|
Jeweler::Tasks.new do |gem|
|
8
12
|
gem.name = "textmagic"
|
9
13
|
gem.summary = %Q{Ruby interface to the TextMagic's Bulk SMS Gateway}
|
@@ -17,10 +21,11 @@ begin
|
|
17
21
|
gem.homepage = "http://github.com/bobes/textmagic"
|
18
22
|
gem.authors = ["Vladimír Bobeš Tužinský"]
|
19
23
|
gem.rubyforge_project = "textmagic"
|
20
|
-
gem.add_runtime_dependency "httparty", ">= 0.
|
21
|
-
gem.add_development_dependency "mocha", ">= 0.9.
|
22
|
-
gem.add_development_dependency "
|
23
|
-
gem.add_development_dependency "
|
24
|
+
gem.add_runtime_dependency "httparty", ">= 0.5.2"
|
25
|
+
gem.add_development_dependency "mocha", ">= 0.9.8"
|
26
|
+
gem.add_development_dependency "shoulda", ">= 2.10.3"
|
27
|
+
gem.add_development_dependency "fakeweb", ">= 1.2.8"
|
28
|
+
gem.add_development_dependency "mcmire-matchy", ">= 0.5.2"
|
24
29
|
end
|
25
30
|
|
26
31
|
Jeweler::RubyforgeTasks.new
|
@@ -28,18 +33,18 @@ rescue LoadError
|
|
28
33
|
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
29
34
|
end
|
30
35
|
|
31
|
-
require 'rake/testtask'
|
32
36
|
Rake::TestTask.new(:test) do |test|
|
33
|
-
test.libs <<
|
34
|
-
test.pattern =
|
37
|
+
test.libs << "lib" << "test"
|
38
|
+
test.pattern = "test/**/test_*.rb"
|
35
39
|
test.verbose = true
|
36
40
|
end
|
41
|
+
task :default => :test
|
37
42
|
|
38
43
|
begin
|
39
|
-
require
|
44
|
+
require "rcov/rcovtask"
|
40
45
|
Rcov::RcovTask.new do |test|
|
41
|
-
test.libs <<
|
42
|
-
test.pattern =
|
46
|
+
test.libs << "test"
|
47
|
+
test.pattern = "test/**/test_*.rb"
|
43
48
|
test.verbose = true
|
44
49
|
end
|
45
50
|
rescue LoadError
|
@@ -48,13 +53,9 @@ rescue LoadError
|
|
48
53
|
end
|
49
54
|
end
|
50
55
|
|
51
|
-
|
52
|
-
task :default => :test
|
53
|
-
|
54
|
-
require 'rake/rdoctask'
|
55
56
|
Rake::RDocTask.new do |rdoc|
|
56
|
-
if File.exist?(
|
57
|
-
config = YAML.load(File.read(
|
57
|
+
if File.exist?("VERSION.yml")
|
58
|
+
config = YAML.load(File.read("VERSION.yml"))
|
58
59
|
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
59
60
|
else
|
60
61
|
version = ""
|
@@ -88,7 +89,7 @@ task :doc => :rerdoc do
|
|
88
89
|
git push origin gh-pages
|
89
90
|
EOS
|
90
91
|
|
91
|
-
system cmd.split(/\n\s*/).join(
|
92
|
+
system cmd.split(/\n\s*/).join(" && ")
|
92
93
|
|
93
94
|
system <<-EOS
|
94
95
|
echo 'Checking out master'
|
data/VERSION.yml
CHANGED
data/lib/api.rb
CHANGED
@@ -12,7 +12,7 @@ module TextMagic
|
|
12
12
|
#
|
13
13
|
# Example usage:
|
14
14
|
#
|
15
|
-
# api = TextMagic::API.new(
|
15
|
+
# api = TextMagic::API.new("fred", "secret")
|
16
16
|
def initialize(username, password)
|
17
17
|
@username = username
|
18
18
|
@password = password
|
@@ -30,7 +30,7 @@ module TextMagic
|
|
30
30
|
# api.account.balance
|
31
31
|
# # => 314.15
|
32
32
|
def account
|
33
|
-
hash = Executor.execute(
|
33
|
+
hash = Executor.execute("account", @username, @password)
|
34
34
|
TextMagic::API::Response.account(hash)
|
35
35
|
end
|
36
36
|
|
@@ -58,43 +58,43 @@ module TextMagic
|
|
58
58
|
#
|
59
59
|
# Example usage:
|
60
60
|
#
|
61
|
-
# api.send(
|
62
|
-
# # =>
|
63
|
-
# response = api.send(
|
64
|
-
# # => {
|
61
|
+
# api.send("Hi Wilma", "999314159265")
|
62
|
+
# # => "141421"
|
63
|
+
# response = api.send("Hello everybody", "999314159265", "999271828182", :max_length => 2)
|
64
|
+
# # => { "999314159265" => "141421", "999271828182" => "173205" }
|
65
65
|
# response.parts_count
|
66
66
|
# # => 1
|
67
67
|
#
|
68
68
|
# Multiple phone numbers can be supplied as an array or as a list of arguments:
|
69
69
|
#
|
70
|
-
# api.send(
|
71
|
-
# api.send(
|
70
|
+
# api.send("Hello everybody", ["999314159265", "999271828182"])
|
71
|
+
# api.send("Hello everybody", "999314159265", "999271828182")
|
72
72
|
#
|
73
73
|
# If you want to send a message to a single phone number but still
|
74
74
|
# want to get a hash response, put the phone number in an array:
|
75
75
|
#
|
76
|
-
# api.send(
|
76
|
+
# api.send("Hi Barney", ["999271828182"])
|
77
77
|
#
|
78
78
|
# Postponed sending:
|
79
79
|
#
|
80
|
-
# api.send(
|
80
|
+
# api.send("Two hours later", "999314159265", :send_time => Time.now.to_i + 7200)
|
81
81
|
def send(text, *args)
|
82
|
-
raise Error.new(1,
|
82
|
+
raise Error.new(1, "Message text is empty") if text.nil? || text.blank?
|
83
83
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
84
84
|
unicode = API.is_unicode(text)
|
85
85
|
options[:unicode] = case options[:unicode]
|
86
|
-
when 1, true
|
87
|
-
when 0, false
|
88
|
-
when nil
|
86
|
+
when 1, true then 1
|
87
|
+
when 0, false then 0
|
88
|
+
when nil then unicode ? 1 : 0
|
89
89
|
else raise Error.new(10, "Wrong parameter value #{options[:unicode]} for parameter unicode")
|
90
90
|
end
|
91
|
-
raise Error.new(6,
|
92
|
-
raise Error.new(7,
|
91
|
+
raise Error.new(6, "Message contains invalid characters") if unicode && options[:unicode] == 0
|
92
|
+
raise Error.new(7, "Message too long") unless API.validate_text_length(text, unicode)
|
93
93
|
single = args.size == 1 && args.first.is_a?(String)
|
94
94
|
phones = args.flatten
|
95
|
-
raise Error.new(9,
|
95
|
+
raise Error.new(9, "Invalid phone number format") unless API.validate_phones(phones)
|
96
96
|
options[:send_time] = options[:send_time].to_i if options[:send_time]
|
97
|
-
hash = Executor.execute(
|
97
|
+
hash = Executor.execute("send", @username, @password, options.merge(:text => text, :phone => phones.join(",")))
|
98
98
|
TextMagic::API::Response.send(hash, single)
|
99
99
|
end
|
100
100
|
|
@@ -111,37 +111,37 @@ module TextMagic
|
|
111
111
|
#
|
112
112
|
# Example usage:
|
113
113
|
#
|
114
|
-
# status = api.message_status(
|
115
|
-
# # =>
|
114
|
+
# status = api.message_status("141421")
|
115
|
+
# # => "d"
|
116
116
|
# status.completed_time
|
117
117
|
# # => Fri May 22 10:10:18 +0200 2009
|
118
118
|
#
|
119
119
|
# Example with multiple ids:
|
120
120
|
#
|
121
|
-
# statuses = api.message_status(
|
122
|
-
# # => {
|
123
|
-
# statuses[
|
124
|
-
# # =>
|
125
|
-
# statuses[
|
121
|
+
# statuses = api.message_status("141421", "173205")
|
122
|
+
# # => { "141421" => "r", "173205" => "d" }
|
123
|
+
# statuses["141421"].text
|
124
|
+
# # => "Hi Wilma"
|
125
|
+
# statuses["173205"].created_time
|
126
126
|
# # => Thu May 28 16:41:45 +0200 2009
|
127
127
|
#
|
128
128
|
# Multiple ids can be supplied as an array or as a list of arguments:
|
129
129
|
#
|
130
|
-
# api.send(
|
131
|
-
# api.send(
|
130
|
+
# api.send("Hello everybody", ["999314159265", "999271828182"])
|
131
|
+
# api.send("Hello everybody", "999314159265", "999271828182")
|
132
132
|
#
|
133
133
|
# If you want to request status for a single message but still want to get
|
134
134
|
# a hash response, put the id in an array:
|
135
135
|
#
|
136
|
-
# api.message_status([
|
136
|
+
# api.message_status(["141421"])
|
137
137
|
#
|
138
138
|
# <b>It is strongly encouraged to setup callbacks to receive updates on message status
|
139
139
|
# instead of using this method.</b>
|
140
140
|
def message_status(*ids)
|
141
141
|
single = ids.size == 1 && ids.first.is_a?(String)
|
142
142
|
ids.flatten!
|
143
|
-
raise TextMagic::API::Error.new(4,
|
144
|
-
hash = Executor.execute(
|
143
|
+
raise TextMagic::API::Error.new(4, "Insufficient parameters") if ids.empty?
|
144
|
+
hash = Executor.execute("message_status", @username, @password, :ids => ids.join(","))
|
145
145
|
TextMagic::API::Response.message_status(hash, single)
|
146
146
|
end
|
147
147
|
alias :status :message_status
|
@@ -162,20 +162,20 @@ module TextMagic
|
|
162
162
|
# Example usage:
|
163
163
|
#
|
164
164
|
# replies = api.receive
|
165
|
-
# # => [
|
165
|
+
# # => ["999271828182: Hello Fred", "999314159265: Good day"]
|
166
166
|
# replies.first.text
|
167
|
-
# # =>
|
167
|
+
# # => "Hello Fred"
|
168
168
|
# replies.first.from
|
169
|
-
# # =>
|
169
|
+
# # => "999314159265"
|
170
170
|
# replies.last.message_id
|
171
|
-
# # =>
|
172
|
-
# api.receive
|
171
|
+
# # => "223606"
|
172
|
+
# api.receive "223606"
|
173
173
|
# # => []
|
174
174
|
#
|
175
175
|
# <b>It is strongly encouraged to setup callbacks to receive replies instead of
|
176
176
|
# using this method.</b>
|
177
177
|
def receive(last_retrieved_id = nil)
|
178
|
-
hash = Executor.execute(
|
178
|
+
hash = Executor.execute("receive", @username, @password, :last_retrieved_id => last_retrieved_id)
|
179
179
|
TextMagic::API::Response.receive(hash)
|
180
180
|
end
|
181
181
|
|
@@ -188,14 +188,14 @@ module TextMagic
|
|
188
188
|
#
|
189
189
|
# Example usage:
|
190
190
|
#
|
191
|
-
# api.delete_reply(
|
192
|
-
# api.delete_reply(
|
193
|
-
# api.delete_reply([
|
191
|
+
# api.delete_reply("141421")
|
192
|
+
# api.delete_reply("173205", "223606")
|
193
|
+
# api.delete_reply(["244948", "264575"])
|
194
194
|
def delete_reply(*ids)
|
195
195
|
single = ids.size == 1 && ids.first.is_a?(String)
|
196
196
|
ids.flatten!
|
197
|
-
raise TextMagic::API::Error.new(4,
|
198
|
-
Executor.execute(
|
197
|
+
raise TextMagic::API::Error.new(4, "Insufficient parameters") if ids.empty?
|
198
|
+
Executor.execute("delete_reply", @username, @password, :ids => ids.join(","))
|
199
199
|
true
|
200
200
|
end
|
201
201
|
alias :delete :delete_reply
|
@@ -212,34 +212,34 @@ module TextMagic
|
|
212
212
|
#
|
213
213
|
# Example usage:
|
214
214
|
#
|
215
|
-
# check = api.check_number(
|
215
|
+
# check = api.check_number("447624800500")
|
216
216
|
# check.price
|
217
217
|
# # => 0.8
|
218
218
|
# check.country
|
219
|
-
# # =>
|
219
|
+
# # => "GB"
|
220
220
|
#
|
221
221
|
# Example with multiple phone numbers:
|
222
222
|
#
|
223
|
-
# check = api.check_number(
|
224
|
-
# check[
|
223
|
+
# check = api.check_number("447624800500", "61428102137")
|
224
|
+
# check["447624800500"].price
|
225
225
|
# # => 0.8
|
226
|
-
# check[
|
227
|
-
# # =>
|
226
|
+
# check["61428102137"].country
|
227
|
+
# # => "AU"
|
228
228
|
#
|
229
229
|
# Multiple phone number can be supplied as an array or as a list of arguments:
|
230
230
|
#
|
231
|
-
# api.check_number([
|
232
|
-
# api.check_number(
|
231
|
+
# api.check_number(["447624800500", "61428102137"])
|
232
|
+
# api.check_number("447624800500", "61428102137")
|
233
233
|
#
|
234
234
|
# If you want to check a single phone number but still want to get
|
235
235
|
# a hash response, put the number in an array:
|
236
236
|
#
|
237
|
-
# api.check_number([
|
237
|
+
# api.check_number(["447624800500"])
|
238
238
|
def check_number(*phones)
|
239
239
|
single = phones.size == 1 && phones.first.is_a?(String)
|
240
240
|
phones.flatten!
|
241
|
-
raise TextMagic::API::Error.new(4,
|
242
|
-
hash = Executor.execute(
|
241
|
+
raise TextMagic::API::Error.new(4, "Insufficient parameters") if phones.empty?
|
242
|
+
hash = Executor.execute("check_number", @username, @password, :phone => phones.join(","))
|
243
243
|
TextMagic::API::Response.check_number(hash, single)
|
244
244
|
end
|
245
245
|
alias :check :check_number
|
data/lib/charset.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module TextMagic
|
2
4
|
|
3
5
|
class API
|
@@ -21,7 +23,7 @@ module TextMagic
|
|
21
23
|
end
|
22
24
|
|
23
25
|
def real_length(text, unicode)
|
24
|
-
text.size + (unicode ? 0 : text.scan(/[\{\}
|
26
|
+
text.size + (unicode ? 0 : text.scan(/[\{\}\\~\[\]\|€]/).size)
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
data/lib/error.rb
CHANGED
@@ -10,10 +10,10 @@ module TextMagic
|
|
10
10
|
# can be supplied as arguments or in a hash.
|
11
11
|
#
|
12
12
|
# TextMagic::API::Error.new(code, message)
|
13
|
-
# TextMagic::API::Error.new(
|
13
|
+
# TextMagic::API::Error.new("error_code" => code, "error_message" => message)
|
14
14
|
def initialize(*args)
|
15
15
|
if args.first.is_a?(Hash)
|
16
|
-
@code, @message = args.first[
|
16
|
+
@code, @message = args.first["error_code"], args.first["error_message"]
|
17
17
|
else
|
18
18
|
@code, @message = args
|
19
19
|
end
|
data/lib/executor.rb
CHANGED
@@ -13,21 +13,21 @@ module TextMagic
|
|
13
13
|
# directly.
|
14
14
|
#
|
15
15
|
# Parameters specified in the +options+ hash will be added to the
|
16
|
-
# HTTP POST request
|
16
|
+
# HTTP POST request"s body together with command, username and
|
17
17
|
# password.
|
18
18
|
#
|
19
|
-
# Returns a hash with values parsed from the server
|
19
|
+
# Returns a hash with values parsed from the server"s response if
|
20
20
|
# the command was successfully executed. In case the server replies
|
21
21
|
# with error, this method raises a TextMagic::API::Error.
|
22
22
|
def self.execute(command, username, password, options = {})
|
23
|
-
raise TextMagic::API::Error.new(3,
|
23
|
+
raise TextMagic::API::Error.new(3, "Command is undefined") if command.nil? || command.blank?
|
24
24
|
if username.nil? || username.blank? || password.nil? || password.blank?
|
25
|
-
raise TextMagic::API::Error.new(5,
|
25
|
+
raise TextMagic::API::Error.new(5, "Invalid username & password combination")
|
26
26
|
end
|
27
27
|
options.merge!(:username => username, :password => password, :cmd => command)
|
28
28
|
options.delete_if { |key, value| key.nil? || key.to_s.blank? || value.nil? || value.to_s.blank? }
|
29
|
-
response = self.post(
|
30
|
-
raise Error.new(response) if response && response[
|
29
|
+
response = self.post("/api", :body => options, :format => :json)
|
30
|
+
raise Error.new(response) if response && response["error_code"]
|
31
31
|
response
|
32
32
|
end
|
33
33
|
end
|
data/lib/response.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "ostruct"
|
2
2
|
|
3
3
|
module TextMagic
|
4
4
|
|
@@ -16,49 +16,49 @@ module TextMagic
|
|
16
16
|
def self.send(hash, single)
|
17
17
|
response = nil
|
18
18
|
if single
|
19
|
-
response = hash[
|
19
|
+
response = hash["message_id"].keys.first.dup
|
20
20
|
else
|
21
|
-
response = hash[
|
21
|
+
response = hash["message_id"].invert
|
22
22
|
end
|
23
23
|
metaclass = class << response; self; end
|
24
24
|
metaclass.send :attr_accessor, :sent_text, :parts_count, :message_id
|
25
|
-
response.sent_text = hash[
|
26
|
-
response.parts_count = hash[
|
27
|
-
response.message_id = hash[
|
25
|
+
response.sent_text = hash["sent_text"]
|
26
|
+
response.parts_count = hash["parts_count"]
|
27
|
+
response.message_id = hash["message_id"]
|
28
28
|
response
|
29
29
|
end
|
30
30
|
|
31
31
|
def self.message_status(hash, single)
|
32
32
|
response = {}
|
33
33
|
hash.each do |message_id, message_hash|
|
34
|
-
status = message_hash[
|
34
|
+
status = message_hash["status"].dup
|
35
35
|
metaclass = class << status; self; end
|
36
36
|
metaclass.send :attr_accessor, :text, :credits_cost, :reply_number, :message_status, :created_time, :completed_time
|
37
|
-
status.text = message_hash[
|
38
|
-
status.credits_cost = message_hash[
|
39
|
-
status.reply_number = message_hash[
|
40
|
-
status.message_status = message_hash[
|
41
|
-
status.created_time = Time.at(message_hash[
|
42
|
-
status.completed_time = Time.at(message_hash[
|
37
|
+
status.text = message_hash["text"]
|
38
|
+
status.credits_cost = message_hash["credits_cost"]
|
39
|
+
status.reply_number = message_hash["reply_number"]
|
40
|
+
status.message_status = message_hash["message_status"]
|
41
|
+
status.created_time = Time.at(message_hash["created_time"].to_i) if message_hash["created_time"]
|
42
|
+
status.completed_time = Time.at(message_hash["completed_time"].to_i) if message_hash["completed_time"]
|
43
43
|
response[message_id] = status
|
44
44
|
end
|
45
45
|
single ? response.values.first : response
|
46
46
|
end
|
47
47
|
|
48
48
|
def self.receive(hash)
|
49
|
-
response = hash[
|
50
|
-
message = "#{message_hash[
|
49
|
+
response = hash["messages"].collect do |message_hash|
|
50
|
+
message = "#{message_hash["from"]}: #{message_hash["text"]}"
|
51
51
|
metaclass = class << message; self; end
|
52
52
|
metaclass.send :attr_accessor, :timestamp, :message_id, :text, :from
|
53
|
-
message.text = message_hash[
|
54
|
-
message.from = message_hash[
|
55
|
-
message.message_id = message_hash[
|
56
|
-
message.timestamp = Time.at(message_hash[
|
53
|
+
message.text = message_hash["text"]
|
54
|
+
message.from = message_hash["from"]
|
55
|
+
message.message_id = message_hash["message_id"]
|
56
|
+
message.timestamp = Time.at(message_hash["timestamp"].to_i)
|
57
57
|
message
|
58
58
|
end
|
59
59
|
metaclass = class << response; self; end
|
60
60
|
metaclass.send :attr_accessor, :unread
|
61
|
-
response.unread = hash[
|
61
|
+
response.unread = hash["unread"]
|
62
62
|
response
|
63
63
|
end
|
64
64
|
|