clickatell 0.3.0 → 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/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/connection.rb
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
- connection = Clickatell::Connection.new(
14
- 'your_api_id',
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
- connection = Clickatell::Connection.new(options.api_key, options.username, options.password)
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 #{connection.account_balance} credits remaining."
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 = connection.message_status(options.message_id)
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 = connection.send_message(options.recipient, options.message, additional_opts)
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 Clickatell
2
- end
1
+ module Clickatelll end
3
2
 
4
- require File.join(File.dirname(__FILE__), *%w[core-ext/hash])
5
- require File.join(File.dirname(__FILE__), *%w[clickatell/version])
6
- require File.join(File.dirname(__FILE__), *%w[clickatell/api])
7
- require File.join(File.dirname(__FILE__), *%w[clickatell/response])
8
- require File.join(File.dirname(__FILE__), *%w[clickatell/connection])
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
@@ -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
- module API
4
+ class API
5
+ attr_accessor :auth_options
7
6
 
8
7
  class << self
9
-
10
- # Authenticates using the specified credentials. Returns
11
- # a session_id if successful which can be used in subsequent
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
- response = execute_command('auth',
15
- :api_id => api_id,
16
- :user => username,
17
- :password => password
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
- # Represents a Clickatell HTTP gateway command in the form
96
- # of a complete URL (the raw, low-level request).
97
- class Command
98
- API_SERVICE_HOST = 'api.clickatell.com'
99
-
100
- def initialize(command_name, opts={})
101
- @command_name = command_name
102
- @options = { :secure => false }.merge(opts)
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
- # Clickatell API Error exception.
119
- class Error < StandardError
120
- attr_reader :code, :message
121
-
122
- def initialize(code, message)
123
- @code, @message = code, message
124
- end
125
-
126
- # Creates a new Error from a Clickatell HTTP response string
127
- # e.g.:
128
- #
129
- # Error.parse("ERR: 001, Authentication error")
130
- # # => #<Clickatell::API::Error code='001' message='Authentication error'>
131
- def self.parse(error_string)
132
- error_details = error_string.split(':').last.strip
133
- code, message = error_details.split(',').map { |s| s.strip }
134
- self.new(code, message)
135
- end
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
- class MessageStatus
139
- STATUS_MAP = {
140
- 1 => 'Message unknown',
141
- 2 => 'Message queued',
142
- 3 => 'Delivered to gateway',
143
- 4 => 'Received by recipient',
144
- 5 => 'Error with message',
145
- 6 => 'User cancelled messaged delivery',
146
- 7 => 'Error delivering message',
147
- 8 => 'OK',
148
- 9 => 'Routing error',
149
- 10 => 'Message expired',
150
- 11 => 'Message queued for later delivery',
151
- 12 => 'Out of credit'
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 self.[](code)
155
- STATUS_MAP[code]
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
@@ -43,6 +43,10 @@ module Clickatell
43
43
  @options.message_id = message_id
44
44
  @options.show_status = true
45
45
  end
46
+
47
+ opts.on('-d', '--debug') do
48
+ @options.debugging_enabled = true
49
+ end
46
50
 
47
51
  opts.on_tail('-h', '--help', "Show this message") do
48
52
  puts opts
@@ -1,7 +1,7 @@
1
1
  module Clickatell #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 3
4
+ MINOR = 4
5
5
  TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
data/lib/core-ext/hash.rb CHANGED
@@ -7,7 +7,7 @@ class Hash
7
7
  #
8
8
  # Keys that do not exist in the original hash are ignored.
9
9
  def only(*keys)
10
- self.inject({}) do |new_hash, (key, value)|
10
+ inject( {} ) do |new_hash, (key, value)|
11
11
  new_hash[key] = value if keys.include?(key)
12
12
  new_hash
13
13
  end
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
- API.send(:execute_command, 'cmdname', :param_one => 'foo').should == raw_response
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
- API.should_receive(:execute_command).with('auth',
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
- API.authenticate('1234', 'joebloggs', 'superpass').should == 'new_session_id'
57
+ @api.authenticate('1234', 'joebloggs', 'superpass').should == 'new_session_id'
51
58
  end
52
59
 
53
60
  it "should support ping" do
54
- API.should_receive(:execute_command).with('ping', :session_id => 'abcdefg').and_return(response=mock('response'))
55
- API.ping('abcdefg').should == response
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 with authentication, returning the message id" do
59
- API.should_receive(:execute_command).with('sendmsg',
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
- API.send_message('4477791234567', 'hello world',
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
- API.should_receive(:execute_command).with('sendmsg',
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
- API.send_message('4477791234567', 'hello world', {:session_id => 'abcde'}, :from => 'LUKE')
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
- API.should_receive(:execute_command).with('sendmsg',
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
- API.send_message('4477791234567', 'hello world', {:session_id => 'abcde'}, :from => 'LUKE', :any_old_param => 'test')
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 with authentication, returning message status" do
105
- API.should_receive(:execute_command).with('querymsg',
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
- API.message_status('messageid', :session_id => 'abcde').should == 'message_status'
99
+ @api.message_status('messageid').should == 'message_status'
124
100
  end
125
101
 
126
- it "should support balance query with authentication, returning number of credits as a float" do
127
- API.should_receive(:execute_command).with('getbalance',
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
- API.account_balance(:username => 'joebloggs', :password => 'superpass', :api_key => '1234').should == 10.0
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
- API.stub!(:execute_command)
109
+ @executor.stub!(:execute)
146
110
  Response.stub!(:parse).and_raise(Clickatell::API::Error.new('', ''))
147
- proc { API.account_balance({}) }.should raise_error(Clickatell::API::Error)
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
- connection = Clickatell::Connection.new('your_api_id', 'your_username', 'your_password')
33
- connection.send_message('447771234567', 'Hello from clickatell')
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.3.0
7
- date: 2007-08-23 00:00:00 +01:00
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/connection.rb
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
@@ -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