lookout-clickatell 0.8.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/Gemfile +11 -0
- data/History.txt +71 -0
- data/License.txt +20 -0
- data/RDOC_README.txt +33 -0
- data/README.textile +73 -0
- data/Rakefile +11 -0
- data/bin/sms +63 -0
- data/clickatell.gemspec +19 -0
- data/lib/clickatell.rb +9 -0
- data/lib/clickatell/api.rb +169 -0
- data/lib/clickatell/api/command.rb +31 -0
- data/lib/clickatell/api/command_executor.rb +91 -0
- data/lib/clickatell/api/error.rb +29 -0
- data/lib/clickatell/api/message_status.rb +26 -0
- data/lib/clickatell/response.rb +32 -0
- data/lib/clickatell/utility.rb +6 -0
- data/lib/clickatell/utility/options.rb +109 -0
- data/lib/clickatell/version.rb +3 -0
- data/lib/core-ext/hash.rb +15 -0
- data/scripts/txt2html +67 -0
- data/spec/api_spec.rb +259 -0
- data/spec/cli_options_spec.rb +30 -0
- data/spec/command_executor_spec.rb +120 -0
- data/spec/hash_ext_spec.rb +14 -0
- data/spec/response_spec.rb +48 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +8 -0
- metadata +98 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/History.txt
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
== 0.9
|
2
|
+
* Added message concatenation support. Messages over 160 characters will be split in to multiple messages and the API concat parameter will be set; the concat parameter can also be set manually (Joshua Sierles, Martin Westin)
|
3
|
+
|
4
|
+
== 0.8.2
|
5
|
+
* Allow numbers to have a leading + when using the CLI
|
6
|
+
|
7
|
+
== 0.8.1
|
8
|
+
* Updated the sms utility error message
|
9
|
+
|
10
|
+
== 0.8
|
11
|
+
|
12
|
+
* Added fix for Ruby 1.9 (Ahmed Al Hafoudh)
|
13
|
+
* Fixed a bug handling error codes above 008 (Sean Kibler)
|
14
|
+
* Added HTTP proxy support (Josh Bassett)
|
15
|
+
|
16
|
+
|
17
|
+
== 0.7.1
|
18
|
+
|
19
|
+
* Fixed broken -b (balance) command
|
20
|
+
|
21
|
+
== 0.7.0
|
22
|
+
|
23
|
+
* Added support for sending SMS to multiple recipients.
|
24
|
+
|
25
|
+
== 0.6.0
|
26
|
+
|
27
|
+
* API host can now be customized (John Gibbons)
|
28
|
+
* Fixed bug with the ampersands in messages, they are now escaped properly (John Brice)
|
29
|
+
* Removed reliance on Object#blank? which was causing some compatibility issues (Greg Bell)
|
30
|
+
* Added :callback option support (Greg Bell)
|
31
|
+
* Added new test mode (Pivotal Labs)
|
32
|
+
|
33
|
+
== 0.5.0
|
34
|
+
|
35
|
+
* Added support for mobile originated flag (courtesy Dan Weinand)
|
36
|
+
* Added support for WAP push (experimental, courtesy Zhao Lu)
|
37
|
+
* Updated specs to use Mocha instead of the built-in RSpec mocking
|
38
|
+
* Improved specs in general
|
39
|
+
|
40
|
+
== 0.4.1
|
41
|
+
|
42
|
+
* Custom alphanumeric sender would not always be supported by default unless it was explicitly enabled using the req_feat parameter.
|
43
|
+
|
44
|
+
== 0.4.0
|
45
|
+
|
46
|
+
* Added API debug mode and --debug option to sms utility
|
47
|
+
* Restructured API classes into individual files
|
48
|
+
* Refactored command execution into a separate object (CommandExecutor).
|
49
|
+
* Major refactoring of API module - converted it to a class with API methods implemented as instance methods. Code is much cleaner and Connection class becomes redundant. See updated documentation.
|
50
|
+
|
51
|
+
== 0.3.0
|
52
|
+
|
53
|
+
* Display proper message status, not just the code
|
54
|
+
* Make it possible to specify custom :from number/name using SMS utility
|
55
|
+
* Added support for custom :from number/name when sending a message.
|
56
|
+
* Added support for checking message status to sms utility
|
57
|
+
* sms utility now returns the id of a successfully sent message.
|
58
|
+
* Capture API KEY errors.
|
59
|
+
* Make sure errors are handled when using sms utility to check balance.
|
60
|
+
|
61
|
+
== 0.2.0
|
62
|
+
|
63
|
+
* Added Clickatell API error handling to API and sms utility.
|
64
|
+
* Handle required/optional arguments for sms utility correctly
|
65
|
+
* Added further sms utility usage information to website
|
66
|
+
* Make sure sms utility gracefully handles missing recipient/message
|
67
|
+
* Added balance query support to API and SMS utility (--check-balance).
|
68
|
+
|
69
|
+
== 0.1.0 2007-08-17
|
70
|
+
|
71
|
+
* Initial release.
|
data/License.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2007 Luke Redpath
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/RDOC_README.txt
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
= Clickatell SMS Library
|
2
|
+
|
3
|
+
To use this gem, you will need sign up for an account at www.clickatell.com. Once you are registered and logged into your account centre, you should add an HTTP API connection to your account. This will give you your API_ID.
|
4
|
+
|
5
|
+
== Basic Usage
|
6
|
+
|
7
|
+
You will need your API_ID as well as your account username and password.
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'clickatell'
|
11
|
+
|
12
|
+
api = Clickatell::API.authenticate('your_api_id', 'your_username', 'your_password')
|
13
|
+
api.send_message('447771234567', 'Hello from clickatell')
|
14
|
+
|
15
|
+
|
16
|
+
== Command-line SMS Utility
|
17
|
+
|
18
|
+
The Clickatell gem also comes with a command-line utility that will allow you to send an SMS directly from the command-line.
|
19
|
+
|
20
|
+
You will need to create a YAML configuration file in your home directory, in a file called .clickatell that resembles the following:
|
21
|
+
|
22
|
+
# ~/.clickatell
|
23
|
+
api_key: your_api_id
|
24
|
+
username: your_username
|
25
|
+
password: your_password
|
26
|
+
|
27
|
+
You can then use the sms utility to send a message to a single recipient:
|
28
|
+
|
29
|
+
sms 447771234567 'Hello from clickatell'
|
30
|
+
|
31
|
+
Alternatively, you can specify the username and password as a command line option. Run +sms+ without any arguments for a full list of options.
|
32
|
+
|
33
|
+
See http://clickatell.rubyforge.org for further instructions.
|
data/README.textile
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
h1. Clickatell SMS Library
|
2
|
+
|
3
|
+
To use this gem, you will need sign up for an account at www.clickatell.com. Once you are registered and logged into your account centre, you should add an HTTP API connection to your account. This will give you your API_ID.
|
4
|
+
|
5
|
+
h2. Basic Usage
|
6
|
+
|
7
|
+
You will need your API_ID as well as your account username and password.
|
8
|
+
|
9
|
+
<pre>
|
10
|
+
<code>
|
11
|
+
require 'rubygems'
|
12
|
+
require 'clickatell'
|
13
|
+
|
14
|
+
api = Clickatell::API.authenticate('your_api_id', 'your_username', 'your_password')
|
15
|
+
api.send_message('447771234567', 'Hello from clickatell')
|
16
|
+
</code>
|
17
|
+
</pre>
|
18
|
+
|
19
|
+
To send a message to multiple recipients, simply pass in an array of numbers.
|
20
|
+
|
21
|
+
<pre>
|
22
|
+
<code>
|
23
|
+
api.send_message(['447771234567', '447771234568'], 'Hello from clickatell')
|
24
|
+
</code>
|
25
|
+
</pre>
|
26
|
+
|
27
|
+
h2. HTTP Proxy
|
28
|
+
|
29
|
+
You can configure the library to use a HTTP proxy when communicating with Clickatell.
|
30
|
+
|
31
|
+
<pre>
|
32
|
+
<code>
|
33
|
+
Clickatell::API.proxy_host = 'my.proxy.com'
|
34
|
+
Clickatell::API.proxy_port = 1234
|
35
|
+
Clickatell::API.proxy_username = 'joeschlub'
|
36
|
+
Clickatell::API.proxy_password = 'secret'
|
37
|
+
</code>
|
38
|
+
</pre>
|
39
|
+
|
40
|
+
h2. Command-line SMS Utility
|
41
|
+
|
42
|
+
The Clickatell gem also comes with a command-line utility that will allow you to send an SMS directly from the command-line.
|
43
|
+
|
44
|
+
You will need to create a YAML configuration file in your home directory, in a file called .clickatell that resembles the following:
|
45
|
+
|
46
|
+
<pre>
|
47
|
+
<code>
|
48
|
+
# ~/.clickatell
|
49
|
+
api_key: your_api_id
|
50
|
+
username: your_username
|
51
|
+
password: your_password
|
52
|
+
</code>
|
53
|
+
</pre>
|
54
|
+
|
55
|
+
You can then use the sms utility to send a message to a single recipient:
|
56
|
+
|
57
|
+
<pre>
|
58
|
+
<code>
|
59
|
+
sms 447771234567 'Hello from clickatell'
|
60
|
+
</code>
|
61
|
+
</pre>
|
62
|
+
|
63
|
+
Alternatively, you can specify the username and password as a command line option. Run +sms+ without any arguments for a full list of options.
|
64
|
+
|
65
|
+
The sms utility also supports multiple, comma-separated recipients (up to 100).
|
66
|
+
|
67
|
+
<pre>
|
68
|
+
<code>
|
69
|
+
sms 447771111111,447772222222 "Hello everyone"
|
70
|
+
</code>
|
71
|
+
</pre>
|
72
|
+
|
73
|
+
See http://clickatell.rubyforge.org for further instructions.
|
data/Rakefile
ADDED
data/bin/sms
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
local_libs = [
|
4
|
+
File.join(File.dirname(__FILE__), *%w[../lib/clickatell]),
|
5
|
+
File.join(File.dirname(__FILE__), *%w[../lib/clickatell/utility])
|
6
|
+
]
|
7
|
+
|
8
|
+
if File.exist?(local_libs.first)
|
9
|
+
local_libs.each { |lib| require lib }
|
10
|
+
else
|
11
|
+
require 'rubygems'
|
12
|
+
require 'clickatell'
|
13
|
+
require 'clickatell/utility'
|
14
|
+
end
|
15
|
+
|
16
|
+
# parse command line options
|
17
|
+
options = Clickatell::Utility::Options.parse(ARGV)
|
18
|
+
|
19
|
+
# authenticate and load the API
|
20
|
+
api = Clickatell::API.authenticate(options.api_key, options.username, options.password)
|
21
|
+
|
22
|
+
begin
|
23
|
+
if options.show_balance
|
24
|
+
puts "Retrieving account balance..."
|
25
|
+
puts "You have #{api.account_balance} credits remaining."
|
26
|
+
exit 0
|
27
|
+
elsif options.show_status
|
28
|
+
puts "Getting status of message ##{options.message_id}."
|
29
|
+
status = api.message_status(options.message_id)
|
30
|
+
puts "Status: #{Clickatell::API::MessageStatus[status]} (##{status})."
|
31
|
+
exit 0
|
32
|
+
else
|
33
|
+
puts "Sending '#{options.message}' to #{[options.recipient].flatten.join(", ")}..."
|
34
|
+
additional_opts = {}
|
35
|
+
additional_opts[:from] = options.from if options.from
|
36
|
+
msg_id = api.send_message(options.recipient, options.message, additional_opts)
|
37
|
+
puts "Message sent successfully (message id: #{[msg_id].flatten.join(", ")})."
|
38
|
+
exit 0
|
39
|
+
end
|
40
|
+
|
41
|
+
rescue Clickatell::API::Error => e
|
42
|
+
case e.code
|
43
|
+
when '001', '002', '003', '005', '108'
|
44
|
+
puts "Authentication failed. Please check your username, password and API key and try again."
|
45
|
+
exit 1
|
46
|
+
when '004'
|
47
|
+
puts "Your account has been frozen. Please contact Clickatell support."
|
48
|
+
exit 1
|
49
|
+
when '007'
|
50
|
+
puts "Requests for this API key are not permitted from this IP address."
|
51
|
+
exit 1
|
52
|
+
else
|
53
|
+
puts "Unexpected error occurred. #{e.message} (error code: #{e.code})."
|
54
|
+
puts "Please file any bugs on GitHub (http://github.com/lukeredpath/clickatell/issues)."
|
55
|
+
puts "A list of Clickatell error codes can be found in their API documentation (http://is.gd/egeS7)."
|
56
|
+
exit 1
|
57
|
+
end
|
58
|
+
|
59
|
+
rescue Timeout::Error
|
60
|
+
puts "The connection the the Clickatell service timed out"
|
61
|
+
puts "Please check your network settings and try again."
|
62
|
+
exit 1
|
63
|
+
end
|
data/clickatell.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "clickatell/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "lookout-clickatell"
|
7
|
+
s.version = Clickatell::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Luke Redpath", 'Kyle Barton', 'R. Tyler Croy']
|
10
|
+
s.email = ["luke@lukeredpath.co.uk", ]
|
11
|
+
s.homepage = "https://github.com/lookout/clickatell"
|
12
|
+
s.summary = %q{Ruby interface to the Clickatell SMS gateway service.}
|
13
|
+
s.description = %q{Ruby interface to the Clickatell SMS gateway service.}
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
end
|
data/lib/clickatell.rb
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
module Clickatell
|
2
|
+
# This module provides the core implementation of the Clickatell
|
3
|
+
# HTTP service.
|
4
|
+
class API
|
5
|
+
attr_accessor :auth_options
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# Authenticates using the given credentials and returns an
|
9
|
+
# API instance with the authentication options set to use the
|
10
|
+
# resulting session_id.
|
11
|
+
def authenticate(api_id, username, password)
|
12
|
+
api = self.new
|
13
|
+
session_id = api.authenticate(api_id, username, password)
|
14
|
+
api.auth_options = { :session_id => session_id }
|
15
|
+
api
|
16
|
+
end
|
17
|
+
|
18
|
+
# Set to true to enable debugging (off by default)
|
19
|
+
attr_accessor :debug_mode
|
20
|
+
|
21
|
+
# Enable secure mode (SSL)
|
22
|
+
attr_accessor :secure_mode, :ca_file, :ca_path
|
23
|
+
|
24
|
+
# Allow customizing URL
|
25
|
+
attr_accessor :api_service_host
|
26
|
+
|
27
|
+
# Set to your HTTP proxy details (off by default)
|
28
|
+
attr_accessor :proxy_host, :proxy_port, :proxy_username, :proxy_password
|
29
|
+
|
30
|
+
# Set to true to test message sending; this will not actually send
|
31
|
+
# messages but will collect sent messages in a testable collection.
|
32
|
+
# (off by default)
|
33
|
+
attr_accessor :test_mode
|
34
|
+
end
|
35
|
+
|
36
|
+
self.debug_mode = false
|
37
|
+
self.secure_mode = false
|
38
|
+
self.ca_path = "/etc/ssl/certs"
|
39
|
+
self.test_mode = false
|
40
|
+
|
41
|
+
# Creates a new API instance using the specified +auth options+.
|
42
|
+
# +auth_options+ is a hash containing either a :session_id or
|
43
|
+
# :username, :password and :api_key.
|
44
|
+
#
|
45
|
+
# Some API calls (authenticate, ping etc.) do not require any
|
46
|
+
# +auth_options+. +auth_options+ can be updated using the accessor methods.
|
47
|
+
def initialize(auth_options={})
|
48
|
+
@auth_options = auth_options
|
49
|
+
end
|
50
|
+
|
51
|
+
# Authenticates using the specified credentials. Returns
|
52
|
+
# a session_id if successful which can be used in subsequent
|
53
|
+
# API calls.
|
54
|
+
def authenticate(api_id, username, password)
|
55
|
+
response = execute_command('auth', 'http',
|
56
|
+
:api_id => api_id,
|
57
|
+
:user => username,
|
58
|
+
:password => password
|
59
|
+
)
|
60
|
+
parse_response(response)['OK']
|
61
|
+
end
|
62
|
+
|
63
|
+
# Pings the service with the specified session_id to keep the
|
64
|
+
# session alive.
|
65
|
+
def ping(session_id)
|
66
|
+
execute_command('ping', 'http', :session_id => session_id)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Sends a message +message_text+ to +recipient+. Recipient
|
70
|
+
# number should have an international dialing prefix and
|
71
|
+
# no leading zeros (unless you have set a default prefix
|
72
|
+
# in your clickatell account centre).
|
73
|
+
#
|
74
|
+
# Messages over 160 characters are split into multiple messages automatically,
|
75
|
+
# and the :concat option will be set, overwriting any manual value of this option.
|
76
|
+
#
|
77
|
+
# You normally wouldn't need to set :concat manually and can rely on the automatica
|
78
|
+
# splitting behaviour.
|
79
|
+
#
|
80
|
+
# Additional options:
|
81
|
+
# :from - the from number/name
|
82
|
+
# :set_mobile_originated - mobile originated flag
|
83
|
+
# :client_message_id - user specified message id that can be used in place of Clickatell issued API message ID for querying message
|
84
|
+
# :concat - number of concatenations allowed. I.E. how long is a message allowed to be.
|
85
|
+
# Returns a new message ID if successful.
|
86
|
+
def send_message(recipient, message_text, opts={})
|
87
|
+
valid_options = opts.only(:from, :mo, :callback, :climsgid, :concat)
|
88
|
+
valid_options.merge!(:req_feat => '48') if valid_options[:from]
|
89
|
+
valid_options.merge!(:mo => '1') if opts[:set_mobile_originated]
|
90
|
+
valid_options.merge!(:climsgid => opts[:client_message_id]) if opts[:client_message_id]
|
91
|
+
if message_text.length > 160
|
92
|
+
valid_options.merge!(:concat => (message_text.length.to_f / 160).ceil)
|
93
|
+
end
|
94
|
+
recipient = recipient.join(",")if recipient.is_a?(Array)
|
95
|
+
response = execute_command('sendmsg', 'http',
|
96
|
+
{:to => recipient, :text => message_text}.merge(valid_options)
|
97
|
+
)
|
98
|
+
response = parse_response(response)
|
99
|
+
response.is_a?(Array) ? response.map { |r| r['ID'] } : response['ID']
|
100
|
+
end
|
101
|
+
|
102
|
+
def send_wap_push(recipient, media_url, notification_text='', opts={})
|
103
|
+
valid_options = opts.only(:from)
|
104
|
+
valid_options.merge!(:req_feat => '48') if valid_options[:from]
|
105
|
+
response = execute_command('si_push', 'mms',
|
106
|
+
{:to => recipient, :si_url => media_url, :si_text => notification_text, :si_id => 'foo'}.merge(valid_options)
|
107
|
+
)
|
108
|
+
parse_response(response)['ID']
|
109
|
+
end
|
110
|
+
|
111
|
+
# Returns the status of a message. Use message ID returned
|
112
|
+
# from original send_message call.
|
113
|
+
def message_status(message_id)
|
114
|
+
response = execute_command('querymsg', 'http', :apimsgid => message_id)
|
115
|
+
parse_response(response)['Status']
|
116
|
+
end
|
117
|
+
|
118
|
+
def message_charge(message_id)
|
119
|
+
response = execute_command('getmsgcharge', 'http', :apimsgid => message_id)
|
120
|
+
parse_response(response)['charge'].to_f
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns the number of credits remaining as a float.
|
124
|
+
def account_balance
|
125
|
+
response = execute_command('getbalance', 'http')
|
126
|
+
parse_response(response)['Credit'].to_f
|
127
|
+
end
|
128
|
+
|
129
|
+
def sms_requests
|
130
|
+
@sms_requests ||= []
|
131
|
+
end
|
132
|
+
|
133
|
+
protected
|
134
|
+
def execute_command(command_name, service, parameters={}) #:nodoc:
|
135
|
+
executor = CommandExecutor.new(auth_hash)
|
136
|
+
result = executor.execute(command_name, service, parameters)
|
137
|
+
|
138
|
+
(sms_requests << executor.sms_requests).flatten! if self.class.test_mode
|
139
|
+
|
140
|
+
result
|
141
|
+
end
|
142
|
+
|
143
|
+
def parse_response(raw_response) #:nodoc:
|
144
|
+
Clickatell::Response.parse(raw_response)
|
145
|
+
end
|
146
|
+
|
147
|
+
def auth_hash #:nodoc:
|
148
|
+
if @auth_options[:session_id]
|
149
|
+
{ :session_id => @auth_options[:session_id] }
|
150
|
+
elsif @auth_options[:api_id]
|
151
|
+
{ :user => @auth_options[:username],
|
152
|
+
:password => @auth_options[:password],
|
153
|
+
:api_id => @auth_options[:api_key] }
|
154
|
+
else
|
155
|
+
{}
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
%w( api/command
|
163
|
+
api/command_executor
|
164
|
+
api/error
|
165
|
+
api/message_status
|
166
|
+
|
167
|
+
).each do |lib|
|
168
|
+
require File.join(File.dirname(__FILE__), lib)
|
169
|
+
end
|