clickatell 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +9 -0
- data/Manifest.txt +4 -2
- data/README.txt +2 -6
- data/bin/sms +15 -4
- data/lib/clickatell.rb +9 -7
- data/lib/clickatell/api.rb +93 -142
- data/lib/clickatell/api/command.rb +28 -0
- data/lib/clickatell/api/command_executor.rb +31 -0
- data/lib/clickatell/api/error.rb +25 -0
- data/lib/clickatell/api/message_status.rb +26 -0
- data/lib/clickatell/utility/options.rb +4 -0
- data/lib/clickatell/version.rb +1 -1
- data/lib/core-ext/hash.rb +1 -1
- data/spec/api_spec.rb +48 -65
- data/website/index.txt +8 -2
- metadata +6 -4
- data/lib/clickatell/connection.rb +0 -62
- data/spec/connection_spec.rb +0 -33
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 0.4.0
|
2
|
+
|
3
|
+
* Added API debug mode and --debug option to sms utility
|
4
|
+
* Restructured API classes into individual files
|
5
|
+
* Refactored command execution into a separate object (CommandExecutor).
|
6
|
+
* Major refactoring of API module - converted it to a class with API methods
|
7
|
+
implemented as instance methods. Code is much cleaner and Connection class
|
8
|
+
becomes redundant. See updated documentation.
|
9
|
+
|
1
10
|
== 0.3.0
|
2
11
|
|
3
12
|
* Display proper message status, not just the code
|
data/Manifest.txt
CHANGED
@@ -6,7 +6,10 @@ Rakefile
|
|
6
6
|
bin/sms
|
7
7
|
lib/clickatell.rb
|
8
8
|
lib/clickatell/api.rb
|
9
|
-
lib/clickatell/
|
9
|
+
lib/clickatell/api/command.rb
|
10
|
+
lib/clickatell/api/command_executor.rb
|
11
|
+
lib/clickatell/api/error.rb
|
12
|
+
lib/clickatell/api/message_status.rb
|
10
13
|
lib/clickatell/response.rb
|
11
14
|
lib/clickatell/utility.rb
|
12
15
|
lib/clickatell/utility/options.rb
|
@@ -15,7 +18,6 @@ lib/core-ext/hash.rb
|
|
15
18
|
scripts/txt2html
|
16
19
|
setup.rb
|
17
20
|
spec/api_spec.rb
|
18
|
-
spec/connection_spec.rb
|
19
21
|
spec/hash_ext_spec.rb
|
20
22
|
spec/response_spec.rb
|
21
23
|
spec/spec.opts
|
data/README.txt
CHANGED
@@ -10,12 +10,8 @@ account username and password.
|
|
10
10
|
require 'rubygems'
|
11
11
|
require 'clickatell'
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
'your_username',
|
16
|
-
'your_password'
|
17
|
-
)
|
18
|
-
connection.send_message('447771234567', 'Hello from clickatell')
|
13
|
+
api = Clickatell::API.authenticate('your_api_id', 'your_username', 'your_password')
|
14
|
+
api.send_message('447771234567', 'Hello from clickatell')
|
19
15
|
|
20
16
|
|
21
17
|
== Command-line SMS Utility
|
data/bin/sms
CHANGED
@@ -13,24 +13,30 @@ else
|
|
13
13
|
require 'clickatell/utility'
|
14
14
|
end
|
15
15
|
|
16
|
+
# parse command line options
|
16
17
|
options = Clickatell::Utility::Options.parse(ARGV)
|
17
|
-
|
18
|
+
|
19
|
+
# enable debugging if specified
|
20
|
+
Clickatell::API.debug_mode = true if options.debugging_enabled
|
21
|
+
|
22
|
+
# authenticate and load the API
|
23
|
+
api = Clickatell::API.authenticate(options.api_key, options.username, options.password)
|
18
24
|
|
19
25
|
begin
|
20
26
|
if options.show_balance
|
21
27
|
puts "Retrieving account balance..."
|
22
|
-
puts "You have #{
|
28
|
+
puts "You have #{api.account_balance} credits remaining."
|
23
29
|
exit 0
|
24
30
|
elsif options.show_status
|
25
31
|
puts "Getting status of message ##{options.message_id}."
|
26
|
-
status =
|
32
|
+
status = api.message_status(options.message_id)
|
27
33
|
puts "Status: #{Clickatell::API::MessageStatus[status]} (##{status})."
|
28
34
|
exit 0
|
29
35
|
else
|
30
36
|
puts "Sending '#{options.message}' to #{options.recipient}..."
|
31
37
|
additional_opts = {}
|
32
38
|
additional_opts[:from] = options.from if options.from
|
33
|
-
msg_id =
|
39
|
+
msg_id = api.send_message(options.recipient, options.message, additional_opts)
|
34
40
|
puts "Message sent successfully (message id: #{msg_id})."
|
35
41
|
exit 0
|
36
42
|
end
|
@@ -51,4 +57,9 @@ rescue Clickatell::API::Error => e
|
|
51
57
|
puts "Please contact the author (contact@lukeredpath.co.uk) with the above error."
|
52
58
|
exit 1
|
53
59
|
end
|
60
|
+
|
61
|
+
rescue Timeout::Error
|
62
|
+
puts "The connection the the Clickatell service timed out"
|
63
|
+
puts "Please check your network settings and try again."
|
64
|
+
exit 1
|
54
65
|
end
|
data/lib/clickatell.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
module
|
2
|
-
end
|
1
|
+
module Clickatelll end
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
%w( core-ext/hash
|
4
|
+
clickatell/version
|
5
|
+
clickatell/api
|
6
|
+
clickatell/response
|
7
|
+
|
8
|
+
).each do |lib|
|
9
|
+
require File.join(File.dirname(__FILE__), lib)
|
10
|
+
end
|
data/lib/clickatell/api.rb
CHANGED
@@ -1,160 +1,111 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
|
3
1
|
module Clickatell
|
4
|
-
# This module provides the core implementation of the Clickatell
|
2
|
+
# This module provides the core implementation of the Clickatell
|
5
3
|
# HTTP service.
|
6
|
-
|
4
|
+
class API
|
5
|
+
attr_accessor :auth_options
|
7
6
|
|
8
7
|
class << self
|
9
|
-
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# API calls.
|
8
|
+
# Authenticates using the given credentials and returns an
|
9
|
+
# API instance with the authentication options set to use the
|
10
|
+
# resulting session_id.
|
13
11
|
def authenticate(api_id, username, password)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
)
|
19
|
-
parse_response(response)['OK']
|
20
|
-
end
|
21
|
-
|
22
|
-
# Pings the service with the specified session_id to keep the
|
23
|
-
# session alive.
|
24
|
-
def ping(session_id)
|
25
|
-
execute_command('ping', :session_id => session_id)
|
26
|
-
end
|
27
|
-
|
28
|
-
# Sends a message +message_text+ to +recipient+. Recipient
|
29
|
-
# number should have an international dialing prefix and
|
30
|
-
# no leading zeros (unless you have set a default prefix
|
31
|
-
# in your clickatell account centre).
|
32
|
-
#
|
33
|
-
# Takes a hash of auth_options to be used in this
|
34
|
-
# API call. Either api_id/username/password or session_id
|
35
|
-
# for an existing authenticated session.
|
36
|
-
#
|
37
|
-
# Additional options:
|
38
|
-
# :from - the from number/name
|
39
|
-
#
|
40
|
-
# Returns a new message ID if successful.
|
41
|
-
def send_message(recipient, message_text, auth_options, opts={})
|
42
|
-
valid_options = opts.only(:from)
|
43
|
-
response = execute_command('sendmsg', {
|
44
|
-
:to => recipient,
|
45
|
-
:text => message_text
|
46
|
-
}.merge(auth_hash(auth_options)).merge(valid_options))
|
47
|
-
parse_response(response)['ID']
|
48
|
-
end
|
49
|
-
|
50
|
-
# Returns the status of a message. Use message ID returned
|
51
|
-
# from original send_message call. See send_message() for
|
52
|
-
# auth_options.
|
53
|
-
def message_status(message_id, auth_options)
|
54
|
-
response = execute_command('querymsg', {
|
55
|
-
:apimsgid => message_id
|
56
|
-
}.merge( auth_hash(auth_options) ))
|
57
|
-
parse_response(response)['Status']
|
58
|
-
end
|
59
|
-
|
60
|
-
# Returns the number of credits remaining as a float.
|
61
|
-
# See send_message() for auth_options.
|
62
|
-
def account_balance(auth_options)
|
63
|
-
response = execute_command('getbalance', auth_hash(auth_options))
|
64
|
-
parse_response(response)['Credit'].to_f
|
65
|
-
end
|
66
|
-
|
67
|
-
protected
|
68
|
-
# Builds a command and sends it via HTTP GET.
|
69
|
-
def execute_command(command_name, parameters)
|
70
|
-
Net::HTTP.get_response(
|
71
|
-
Command.new(command_name).with_params(parameters)
|
72
|
-
)
|
73
|
-
end
|
74
|
-
|
75
|
-
def parse_response(raw_response) #:nodoc:
|
76
|
-
Clickatell::Response.parse(raw_response)
|
77
|
-
end
|
78
|
-
|
79
|
-
def auth_hash(options) #:nodoc:
|
80
|
-
if options[:session_id]
|
81
|
-
return {
|
82
|
-
:session_id => options[:session_id]
|
83
|
-
}
|
84
|
-
else
|
85
|
-
return {
|
86
|
-
:user => options[:username],
|
87
|
-
:password => options[:password],
|
88
|
-
:api_id => options[:api_key]
|
89
|
-
}
|
90
|
-
end
|
12
|
+
api = self.new
|
13
|
+
session_id = api.authenticate(api_id, username, password)
|
14
|
+
api.auth_options = { :session_id => session_id }
|
15
|
+
api
|
91
16
|
end
|
92
17
|
|
18
|
+
# Set to true to enable debugging (off by default)
|
19
|
+
attr_accessor :debug_mode
|
93
20
|
end
|
94
21
|
|
95
|
-
#
|
96
|
-
#
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
end
|
104
|
-
|
105
|
-
# Returns a URL for the given parameters (a hash).
|
106
|
-
def with_params(param_hash)
|
107
|
-
param_string = '?' + param_hash.map { |key, value| "#{key}=#{value}" }.sort.join('&')
|
108
|
-
return URI.parse(File.join(api_service_uri, @command_name + URI.encode(param_string)))
|
109
|
-
end
|
110
|
-
|
111
|
-
protected
|
112
|
-
def api_service_uri
|
113
|
-
protocol = @options[:secure] ? 'https' : 'http'
|
114
|
-
return "#{protocol}://#{API_SERVICE_HOST}/http/"
|
115
|
-
end
|
22
|
+
# Creates a new API instance using the specified +auth options+.
|
23
|
+
# +auth_options+ is a hash containing either a :session_id or
|
24
|
+
# :username, :password and :api_key.
|
25
|
+
#
|
26
|
+
# Some API calls (authenticate, ping etc.) do not require any
|
27
|
+
# +auth_options+. +auth_options+ can be updated using the accessor methods.
|
28
|
+
def initialize(auth_options={})
|
29
|
+
@auth_options = auth_options
|
116
30
|
end
|
117
31
|
|
118
|
-
#
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
32
|
+
# Authenticates using the specified credentials. Returns
|
33
|
+
# a session_id if successful which can be used in subsequent
|
34
|
+
# API calls.
|
35
|
+
def authenticate(api_id, username, password)
|
36
|
+
response = execute_command('auth',
|
37
|
+
:api_id => api_id,
|
38
|
+
:user => username,
|
39
|
+
:password => password
|
40
|
+
)
|
41
|
+
parse_response(response)['OK']
|
42
|
+
end
|
43
|
+
|
44
|
+
# Pings the service with the specified session_id to keep the
|
45
|
+
# session alive.
|
46
|
+
def ping(session_id)
|
47
|
+
execute_command('ping', :session_id => session_id)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Sends a message +message_text+ to +recipient+. Recipient
|
51
|
+
# number should have an international dialing prefix and
|
52
|
+
# no leading zeros (unless you have set a default prefix
|
53
|
+
# in your clickatell account centre).
|
54
|
+
#
|
55
|
+
# Additional options:
|
56
|
+
# :from - the from number/name
|
57
|
+
#
|
58
|
+
# Returns a new message ID if successful.
|
59
|
+
def send_message(recipient, message_text, opts={})
|
60
|
+
valid_options = opts.only(:from)
|
61
|
+
response = execute_command('sendmsg',
|
62
|
+
{:to => recipient, :text => message_text}.merge(valid_options)
|
63
|
+
)
|
64
|
+
parse_response(response)['ID']
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns the status of a message. Use message ID returned
|
68
|
+
# from original send_message call.
|
69
|
+
def message_status(message_id)
|
70
|
+
response = execute_command('querymsg', :apimsgid => message_id)
|
71
|
+
parse_response(response)['Status']
|
136
72
|
end
|
137
73
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
}
|
74
|
+
# Returns the number of credits remaining as a float.
|
75
|
+
def account_balance
|
76
|
+
response = execute_command('getbalance')
|
77
|
+
parse_response(response)['Credit'].to_f
|
78
|
+
end
|
79
|
+
|
80
|
+
protected
|
81
|
+
def execute_command(command_name, parameters={}) #:nodoc:
|
82
|
+
CommandExecutor.new(auth_hash, self.class.debug_mode).execute(command_name, parameters)
|
83
|
+
end
|
84
|
+
|
85
|
+
def parse_response(raw_response) #:nodoc:
|
86
|
+
Clickatell::Response.parse(raw_response)
|
87
|
+
end
|
153
88
|
|
154
|
-
def
|
155
|
-
|
89
|
+
def auth_hash #:nodoc:
|
90
|
+
if @auth_options[:session_id]
|
91
|
+
{ :session_id => @auth_options[:session_id] }
|
92
|
+
elsif @auth_options[:api_id]
|
93
|
+
{ :user => @auth_options[:username],
|
94
|
+
:password => @auth_options[:password],
|
95
|
+
:api_id => @auth_options[:api_key] }
|
96
|
+
else
|
97
|
+
{}
|
98
|
+
end
|
156
99
|
end
|
157
|
-
end
|
158
100
|
|
159
101
|
end
|
102
|
+
end
|
103
|
+
|
104
|
+
%w( api/command
|
105
|
+
api/command_executor
|
106
|
+
api/error
|
107
|
+
api/message_status
|
108
|
+
|
109
|
+
).each do |lib|
|
110
|
+
require File.join(File.dirname(__FILE__), lib)
|
160
111
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Clickatell
|
2
|
+
class API
|
3
|
+
|
4
|
+
# Represents a Clickatell HTTP gateway command in the form
|
5
|
+
# of a complete URL (the raw, low-level request).
|
6
|
+
class Command
|
7
|
+
API_SERVICE_HOST = 'api.clickatell.com'
|
8
|
+
|
9
|
+
def initialize(command_name, opts={})
|
10
|
+
@command_name = command_name
|
11
|
+
@options = { :secure => false }.merge(opts)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns a URL for the given parameters (a hash).
|
15
|
+
def with_params(param_hash)
|
16
|
+
param_string = '?' + param_hash.map { |key, value| "#{key}=#{value}" }.sort.join('&')
|
17
|
+
return URI.parse(File.join(api_service_uri, @command_name + URI.encode(param_string)))
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
def api_service_uri
|
22
|
+
protocol = @options[:secure] ? 'https' : 'http'
|
23
|
+
return "#{protocol}://#{API_SERVICE_HOST}/http/"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module Clickatell
|
4
|
+
class API
|
5
|
+
|
6
|
+
# Used to run commands agains the Clickatell gateway.
|
7
|
+
class CommandExecutor
|
8
|
+
def initialize(authentication_hash, debug=false)
|
9
|
+
@authentication_hash = authentication_hash
|
10
|
+
@debug = debug
|
11
|
+
end
|
12
|
+
|
13
|
+
# Builds a command object and sends it using HTTP GET.
|
14
|
+
# Will output URLs as they are requested to stdout when
|
15
|
+
# debugging is enabled.
|
16
|
+
def execute(command_name, parameters={})
|
17
|
+
request_uri = command(command_name, parameters)
|
18
|
+
puts "[debug] Sending request to #{request_uri}" if @debug
|
19
|
+
Net::HTTP.get_response(request_uri)
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
def command(command_name, parameters) #:nodoc:
|
24
|
+
Command.new(command_name).with_params(
|
25
|
+
parameters.merge(@authentication_hash)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Clickatell
|
2
|
+
class API
|
3
|
+
|
4
|
+
# Clickatell API Error exception.
|
5
|
+
class Error < StandardError
|
6
|
+
attr_reader :code, :message
|
7
|
+
|
8
|
+
def initialize(code, message)
|
9
|
+
@code, @message = code, message
|
10
|
+
end
|
11
|
+
|
12
|
+
# Creates a new Error from a Clickatell HTTP response string
|
13
|
+
# e.g.:
|
14
|
+
#
|
15
|
+
# Error.parse("ERR: 001, Authentication error")
|
16
|
+
# # => #<Clickatell::API::Error code='001' message='Authentication error'>
|
17
|
+
def self.parse(error_string)
|
18
|
+
error_details = error_string.split(':').last.strip
|
19
|
+
code, message = error_details.split(',').map { |s| s.strip }
|
20
|
+
self.new(code, message)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Clickatell
|
2
|
+
class API
|
3
|
+
|
4
|
+
class MessageStatus
|
5
|
+
STATUS_MAP = {
|
6
|
+
1 => 'Message unknown',
|
7
|
+
2 => 'Message queued',
|
8
|
+
3 => 'Delivered to gateway',
|
9
|
+
4 => 'Received by recipient',
|
10
|
+
5 => 'Error with message',
|
11
|
+
6 => 'User cancelled messaged delivery',
|
12
|
+
7 => 'Error delivering message',
|
13
|
+
8 => 'OK',
|
14
|
+
9 => 'Routing error',
|
15
|
+
10 => 'Message expired',
|
16
|
+
11 => 'Message queued for later delivery',
|
17
|
+
12 => 'Out of credit'
|
18
|
+
}
|
19
|
+
|
20
|
+
def self.[](code)
|
21
|
+
STATUS_MAP[code]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
data/lib/clickatell/version.rb
CHANGED
data/lib/core-ext/hash.rb
CHANGED
data/spec/api_spec.rb
CHANGED
@@ -31,120 +31,103 @@ module Clickatell
|
|
31
31
|
end
|
32
32
|
|
33
33
|
describe "Command executor" do
|
34
|
-
it "should create an API command and send it via HTTP get, returning the raw http response" do
|
34
|
+
it "should create an API command with auth params and send it via HTTP get, returning the raw http response" do
|
35
|
+
executor = API::CommandExecutor.new(:session_id => '12345')
|
35
36
|
API::Command.should_receive(:new).with('cmdname').and_return(cmd=mock('command'))
|
36
|
-
cmd.should_receive(:with_params).with(:param_one => 'foo').and_return(uri=mock('uri'))
|
37
|
+
cmd.should_receive(:with_params).with(:param_one => 'foo', :session_id => '12345').and_return(uri=mock('uri'))
|
37
38
|
Net::HTTP.should_receive(:get_response).with(uri).and_return(raw_response=mock('http response'))
|
38
|
-
|
39
|
+
executor.execute('cmdname', :param_one => 'foo').should == raw_response
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
42
43
|
describe "API" do
|
44
|
+
before do
|
45
|
+
API.debug_mode = false
|
46
|
+
API::CommandExecutor.should_receive(:new).with({:session_id => '1234'}, false).and_return(@executor = mock('command executor'))
|
47
|
+
@api = API.new(:session_id => '1234')
|
48
|
+
end
|
49
|
+
|
43
50
|
it "should return session_id for successful authentication" do
|
44
|
-
|
51
|
+
@executor.should_receive(:execute).with('auth',
|
45
52
|
:api_id => '1234',
|
46
53
|
:user => 'joebloggs',
|
47
54
|
:password => 'superpass'
|
48
55
|
).and_return(response=mock('response'))
|
49
56
|
Response.should_receive(:parse).with(response).and_return('OK' => 'new_session_id')
|
50
|
-
|
57
|
+
@api.authenticate('1234', 'joebloggs', 'superpass').should == 'new_session_id'
|
51
58
|
end
|
52
59
|
|
53
60
|
it "should support ping" do
|
54
|
-
|
55
|
-
|
61
|
+
@executor.should_receive(:execute).with('ping', :session_id => 'abcdefg').and_return(response=mock('response'))
|
62
|
+
@api.ping('abcdefg').should == response
|
56
63
|
end
|
57
64
|
|
58
|
-
it "should support sending messages
|
59
|
-
|
60
|
-
:api_id => '1234',
|
61
|
-
:user => 'joebloggs',
|
62
|
-
:password => 'superpass',
|
65
|
+
it "should support sending messages, returning the message id" do
|
66
|
+
@executor.should_receive(:execute).with('sendmsg',
|
63
67
|
:to => '4477791234567',
|
64
68
|
:text => 'hello world'
|
65
69
|
).and_return(response=mock('response'))
|
66
70
|
Response.should_receive(:parse).with(response).and_return('ID' => 'message_id')
|
67
|
-
|
68
|
-
:username => 'joebloggs', :password => 'superpass', :api_key => '1234'
|
69
|
-
).should == 'message_id'
|
70
|
-
end
|
71
|
-
|
72
|
-
it "should support sending messages with pre-auth, returning the message id" do
|
73
|
-
API.should_receive(:execute_command).with('sendmsg',
|
74
|
-
:session_id => 'abcde',
|
75
|
-
:to => '4477791234567',
|
76
|
-
:text => 'hello world'
|
77
|
-
).and_return(response=mock('response'))
|
78
|
-
Response.should_receive(:parse).with(response).and_return('ID' => 'message_id')
|
79
|
-
API.send_message('4477791234567', 'hello world', :session_id => 'abcde').should == 'message_id'
|
71
|
+
@api.send_message('4477791234567', 'hello world').should == 'message_id'
|
80
72
|
end
|
81
73
|
|
82
74
|
it "should support sending messages with custom from number, returning the message id" do
|
83
|
-
|
84
|
-
:session_id => 'abcde',
|
75
|
+
@executor.should_receive(:execute).with('sendmsg',
|
85
76
|
:to => '4477791234567',
|
86
77
|
:text => 'hello world',
|
87
78
|
:from => 'LUKE'
|
88
79
|
).and_return(response=mock('response'))
|
89
80
|
Response.should_receive(:parse).with(response).and_return('ID' => 'message_id')
|
90
|
-
|
81
|
+
@api.send_message('4477791234567', 'hello world', :from => 'LUKE')
|
91
82
|
end
|
92
83
|
|
93
84
|
it "should ignore any invalid parameters when sending message" do
|
94
|
-
|
95
|
-
:session_id => 'abcde',
|
85
|
+
@executor.should_receive(:execute).with('sendmsg',
|
96
86
|
:to => '4477791234567',
|
97
87
|
:text => 'hello world',
|
98
88
|
:from => 'LUKE'
|
99
89
|
).and_return(response=mock('response'))
|
100
90
|
Response.stub!(:parse).and_return('ID' => 'foo')
|
101
|
-
|
91
|
+
@api.send_message('4477791234567', 'hello world', :from => 'LUKE', :any_old_param => 'test')
|
102
92
|
end
|
103
93
|
|
104
|
-
it "should support message status query
|
105
|
-
|
106
|
-
:api_id => '1234',
|
107
|
-
:user => 'joebloggs',
|
108
|
-
:password => 'superpass',
|
109
|
-
:apimsgid => 'messageid'
|
110
|
-
).and_return(response=mock('response'))
|
111
|
-
Response.should_receive(:parse).with(response).and_return('ID' => 'message_id', 'Status' => 'message_status')
|
112
|
-
API.message_status('messageid',
|
113
|
-
:username => 'joebloggs', :password => 'superpass', :api_key => '1234'
|
114
|
-
).should == 'message_status'
|
115
|
-
end
|
116
|
-
|
117
|
-
it "should support message status query with pre-auth" do
|
118
|
-
API.should_receive(:execute_command).with('querymsg',
|
119
|
-
:session_id => 'abcde',
|
94
|
+
it "should support message status query, returning message status" do
|
95
|
+
@executor.should_receive(:execute).with('querymsg',
|
120
96
|
:apimsgid => 'messageid'
|
121
97
|
).and_return(response=mock('response'))
|
122
98
|
Response.should_receive(:parse).with(response).and_return('ID' => 'message_id', 'Status' => 'message_status')
|
123
|
-
|
99
|
+
@api.message_status('messageid').should == 'message_status'
|
124
100
|
end
|
125
101
|
|
126
|
-
it "should support balance query
|
127
|
-
|
128
|
-
:api_id => '1234',
|
129
|
-
:user => 'joebloggs',
|
130
|
-
:password => 'superpass'
|
131
|
-
).and_return(response=mock('response'))
|
102
|
+
it "should support balance query, returning number of credits as a float" do
|
103
|
+
@executor.should_receive(:execute).with('getbalance', {}).and_return(response=mock('response'))
|
132
104
|
Response.should_receive(:parse).with(response).and_return('Credit' => '10.0')
|
133
|
-
|
134
|
-
end
|
135
|
-
|
136
|
-
it "should support balance query with pre-auth, returning number of credits as a float" do
|
137
|
-
API.should_receive(:execute_command).with('getbalance',
|
138
|
-
:session_id => 'abcde'
|
139
|
-
).and_return(response=mock('response'))
|
140
|
-
Response.should_receive(:parse).with(response).and_return('Credit' => '10.0')
|
141
|
-
API.account_balance(:session_id => 'abcde').should == 10.0
|
105
|
+
@api.account_balance.should == 10.0
|
142
106
|
end
|
143
107
|
|
144
108
|
it "should raise an API::Error if the response parser raises" do
|
145
|
-
|
109
|
+
@executor.stub!(:execute)
|
146
110
|
Response.stub!(:parse).and_raise(Clickatell::API::Error.new('', ''))
|
147
|
-
proc {
|
111
|
+
proc { @api.account_balance }.should raise_error(Clickatell::API::Error)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe API, ' when authenticating' do
|
116
|
+
it "should authenticate to retrieve a session_id and return a new API instance using that session id" do
|
117
|
+
API.stub!(:new).and_return(api=mock('api'))
|
118
|
+
api.should_receive(:authenticate).with('my_api_key', 'joebloggs', 'mypassword').and_return('new_session_id')
|
119
|
+
api.should_receive(:auth_options=).with(:session_id => 'new_session_id')
|
120
|
+
API.authenticate('my_api_key', 'joebloggs', 'mypassword')
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe API, ' with no authentication options set' do
|
125
|
+
it "should build commands with no authentication options" do
|
126
|
+
API.debug_mode = false
|
127
|
+
api = API.new
|
128
|
+
API::CommandExecutor.should_receive(:new).with({}, false).and_return(executor=mock('command executor'))
|
129
|
+
executor.stub!(:execute)
|
130
|
+
api.ping('1234')
|
148
131
|
end
|
149
132
|
end
|
150
133
|
|
data/website/index.txt
CHANGED
@@ -29,11 +29,17 @@ account username and password.
|
|
29
29
|
require 'rubygems'
|
30
30
|
require 'clickatell'
|
31
31
|
|
32
|
-
|
33
|
-
|
32
|
+
api = Clickatell::API.authenticate('your_api_id', 'your_username', 'your_password')
|
33
|
+
api.send_message('447771234567', 'Hello from clickatell')
|
34
34
|
</code></pre>
|
35
35
|
|
36
36
|
Full documentation for the API is available in the <a href="rdoc/">RDocs</a>.
|
37
|
+
|
38
|
+
For debugging purposes, the API allows you to view gateway URIs as they are requested, printed to $stdout. You can enable this by turning on +debug_mode+.
|
39
|
+
|
40
|
+
<pre><code class="ruby">
|
41
|
+
Clickatell::API.debug_mode = true
|
42
|
+
</code></pre>
|
37
43
|
|
38
44
|
h4. Command-line SMS Utility
|
39
45
|
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: clickatell
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-08-
|
6
|
+
version: 0.4.0
|
7
|
+
date: 2007-08-29 00:00:00 +01:00
|
8
8
|
summary: Ruby interface to the Clickatell SMS gateway service.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -37,7 +37,10 @@ files:
|
|
37
37
|
- bin/sms
|
38
38
|
- lib/clickatell.rb
|
39
39
|
- lib/clickatell/api.rb
|
40
|
-
- lib/clickatell/
|
40
|
+
- lib/clickatell/api/command.rb
|
41
|
+
- lib/clickatell/api/command_executor.rb
|
42
|
+
- lib/clickatell/api/error.rb
|
43
|
+
- lib/clickatell/api/message_status.rb
|
41
44
|
- lib/clickatell/response.rb
|
42
45
|
- lib/clickatell/utility.rb
|
43
46
|
- lib/clickatell/utility/options.rb
|
@@ -46,7 +49,6 @@ files:
|
|
46
49
|
- scripts/txt2html
|
47
50
|
- setup.rb
|
48
51
|
- spec/api_spec.rb
|
49
|
-
- spec/connection_spec.rb
|
50
52
|
- spec/hash_ext_spec.rb
|
51
53
|
- spec/response_spec.rb
|
52
54
|
- spec/spec.opts
|
@@ -1,62 +0,0 @@
|
|
1
|
-
module Clickatell
|
2
|
-
|
3
|
-
# The Connection object provides a high-level interface to the
|
4
|
-
# Clickatell API, handling authentication across multiple API
|
5
|
-
# requests.
|
6
|
-
#
|
7
|
-
# Example:
|
8
|
-
# conn = Clickatell::Connection.new('your_api_key', 'joebloggs', 'secret')
|
9
|
-
# message_id = conn.send_message('44777123456', 'This is a test message')
|
10
|
-
# status = conn.message_status(message_id)
|
11
|
-
#
|
12
|
-
# The Connection object provides all of the public methods implemented in
|
13
|
-
# Clickatell::API but handles the passing of authentication options
|
14
|
-
# automatically so it is not required to pass any authentication_option hashes
|
15
|
-
# into API methods that require them.
|
16
|
-
class Connection
|
17
|
-
|
18
|
-
# Returns the current Clickatell session ID.
|
19
|
-
attr_reader :session_id
|
20
|
-
|
21
|
-
# +api_key+: Your Clickatell API ID/key.
|
22
|
-
# +username+: Your Clickatell account username.
|
23
|
-
# +password+: Your Clickatell account password.
|
24
|
-
def initialize(api_key, username, password)
|
25
|
-
@api_key = api_key
|
26
|
-
@username = username
|
27
|
-
@password = password
|
28
|
-
end
|
29
|
-
|
30
|
-
# Manual authentication. Will create a new Clickatell session
|
31
|
-
# and store the session ID.
|
32
|
-
def authenticate!
|
33
|
-
@session_id = API.authenticate(@api_key, @username, @password)
|
34
|
-
end
|
35
|
-
|
36
|
-
protected
|
37
|
-
# Executes the given +api_method+ by delegating to the API
|
38
|
-
# module, using the current session_id for authentication.
|
39
|
-
def execute_api_call(api_method, params, additional_options)
|
40
|
-
params << {:session_id => current_session_id}
|
41
|
-
params << additional_options if additional_options
|
42
|
-
API.send(api_method, *params)
|
43
|
-
end
|
44
|
-
|
45
|
-
# Returns the current_session_id, authenticating if one doesn't exist
|
46
|
-
def current_session_id
|
47
|
-
authenticate! if session_id.nil?
|
48
|
-
session_id
|
49
|
-
end
|
50
|
-
|
51
|
-
# Dispatch any API methods to the API module.
|
52
|
-
def method_missing(method, *args, &block)
|
53
|
-
if API.respond_to?(method)
|
54
|
-
additional_options = args.pop if args.last.is_a?(Hash)
|
55
|
-
execute_api_call(method, args, additional_options)
|
56
|
-
else
|
57
|
-
super(method, args, &block)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
data/spec/connection_spec.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
-
require File.dirname(__FILE__) + '/../lib/clickatell'
|
3
|
-
|
4
|
-
module Clickatell
|
5
|
-
|
6
|
-
describe Connection, ' when unauthenticated' do
|
7
|
-
it "should authenticate and store session_id before sending command" do
|
8
|
-
connection = Connection.new('my_api_key', 'myusername', 'mypassword')
|
9
|
-
API.should_receive(:authenticate).with('my_api_key', 'myusername', 'mypassword').and_return('new_session_id')
|
10
|
-
API.should_receive(:send_message).with('4477791234567', 'hello world', :session_id => 'new_session_id')
|
11
|
-
connection.send_message('4477791234567', 'hello world')
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
describe Connection, ' when authenticated' do
|
16
|
-
before do
|
17
|
-
@connection = Connection.new('my_api_key', 'myusername', 'mypassword')
|
18
|
-
@connection.stub!(:session_id).and_return('session_id')
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should send command with session_id without re-authenticating" do
|
22
|
-
API.should_receive(:authenticate).never
|
23
|
-
API.should_receive(:send_message).with('4477791234567', 'hello world', :session_id => 'session_id')
|
24
|
-
@connection.send_message('4477791234567', 'hello world')
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should support API calls with additional opts, passing them after auth options" do
|
28
|
-
API.should_receive(:send_message).with('4477791234567', 'hello world', {:session_id => 'session_id'}, :from => 'LUKE')
|
29
|
-
@connection.send_message('4477791234567', 'hello world', {:from => 'LUKE'})
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|