commonthread-clickatell 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +37 -0
- data/License.txt +20 -0
- data/Manifest.txt +36 -0
- data/RDOC_README.txt +33 -0
- data/README.textile +33 -0
- data/Rakefile +160 -0
- data/clickatell.gemspec +33 -0
- data/lib/clickatell/api/command.rb +30 -0
- data/lib/clickatell/api/command_executor.rb +41 -0
- data/lib/clickatell/api/error.rb +25 -0
- data/lib/clickatell/api/message_status.rb +26 -0
- data/lib/clickatell/api.rb +129 -0
- data/lib/clickatell/response.rb +22 -0
- data/lib/clickatell/utility/options.rb +107 -0
- data/lib/clickatell/utility.rb +6 -0
- data/lib/clickatell/version.rb +13 -0
- data/lib/clickatell.rb +11 -0
- data/setup.rb +1585 -0
- metadata +75 -0
data/History.txt
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
== 0.5.0
|
2
|
+
* Added support for mobile originated flag (courtesy Dan Weinand)
|
3
|
+
* Added support for WAP push (experimental, courtesy Zhao Lu)
|
4
|
+
* Updated specs to use Mocha instead of the built-in RSpec mocking
|
5
|
+
* Improved specs in general
|
6
|
+
|
7
|
+
== 0.4.1
|
8
|
+
* Custom alphanumeric sender would not always be supported by default unless it was explicitly enabled using the req_feat parameter.
|
9
|
+
|
10
|
+
== 0.4.0
|
11
|
+
|
12
|
+
* Added API debug mode and --debug option to sms utility
|
13
|
+
* Restructured API classes into individual files
|
14
|
+
* Refactored command execution into a separate object (CommandExecutor).
|
15
|
+
* 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.
|
16
|
+
|
17
|
+
== 0.3.0
|
18
|
+
|
19
|
+
* Display proper message status, not just the code
|
20
|
+
* Make it possible to specify custom :from number/name using SMS utility
|
21
|
+
* Added support for custom :from number/name when sending a message.
|
22
|
+
* Added support for checking message status to sms utility
|
23
|
+
* sms utility now returns the id of a successfully sent message.
|
24
|
+
* Capture API KEY errors.
|
25
|
+
* Make sure errors are handled when using sms utility to check balance.
|
26
|
+
|
27
|
+
== 0.2.0
|
28
|
+
|
29
|
+
* Added Clickatell API error handling to API and sms utility.
|
30
|
+
* Handle required/optional arguments for sms utility correctly
|
31
|
+
* Added further sms utility usage information to website
|
32
|
+
* Make sure sms utility gracefully handles missing recipient/message
|
33
|
+
* Added balance query support to API and SMS utility (--check-balance).
|
34
|
+
|
35
|
+
== 0.1.0 2007-08-17
|
36
|
+
|
37
|
+
* 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/Manifest.txt
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
History.txt
|
2
|
+
License.txt
|
3
|
+
Manifest.txt
|
4
|
+
RDOC_README.txt
|
5
|
+
README.textile
|
6
|
+
Rakefile
|
7
|
+
bin/sms
|
8
|
+
lib/clickatell.rb
|
9
|
+
lib/clickatell/api.rb
|
10
|
+
lib/clickatell/api/command.rb
|
11
|
+
lib/clickatell/api/command_executor.rb
|
12
|
+
lib/clickatell/api/error.rb
|
13
|
+
lib/clickatell/api/message_status.rb
|
14
|
+
lib/clickatell/response.rb
|
15
|
+
lib/clickatell/utility.rb
|
16
|
+
lib/clickatell/utility/options.rb
|
17
|
+
lib/clickatell/version.rb
|
18
|
+
lib/core-ext/hash.rb
|
19
|
+
scripts/txt2html
|
20
|
+
setup.rb
|
21
|
+
spec/api_spec.rb
|
22
|
+
spec/hash_ext_spec.rb
|
23
|
+
spec/response_spec.rb
|
24
|
+
spec/spec.opts
|
25
|
+
spec/spec_helper.rb
|
26
|
+
website/images/footer_bg.gif
|
27
|
+
website/index.html
|
28
|
+
website/index.txt
|
29
|
+
website/javascripts/codehighlighter/code_highlighter.js
|
30
|
+
website/javascripts/codehighlighter/ruby.js
|
31
|
+
website/javascripts/rounded_corners_lite.inc.js
|
32
|
+
website/specs.html
|
33
|
+
website/stylesheets/limechoc.css
|
34
|
+
website/stylesheets/rdoc.css
|
35
|
+
website/stylesheets/screen.css
|
36
|
+
website/template.rhtml
|
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,33 @@
|
|
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
|
+
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
|
+
h2. 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/Rakefile
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/packagetask'
|
6
|
+
require 'rake/gempackagetask'
|
7
|
+
require 'rake/rdoctask'
|
8
|
+
require 'rake/contrib/rubyforgepublisher'
|
9
|
+
require 'fileutils'
|
10
|
+
require 'hoe'
|
11
|
+
begin
|
12
|
+
require 'spec/rake/spectask'
|
13
|
+
rescue LoadError
|
14
|
+
puts 'To use rspec for testing you must install rspec gem:'
|
15
|
+
puts '$ sudo gem install rspec'
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
|
19
|
+
include FileUtils
|
20
|
+
require File.join(File.dirname(__FILE__), 'lib', 'clickatell', 'version')
|
21
|
+
|
22
|
+
AUTHOR = 'Luke Redpath'
|
23
|
+
EMAIL = "contact[AT]lukeredpath.co.uk"
|
24
|
+
DESCRIPTION = "Ruby interface to the Clickatell SMS gateway service."
|
25
|
+
GEM_NAME = 'clickatell'
|
26
|
+
|
27
|
+
@config_file = "~/.rubyforge/user-config.yml"
|
28
|
+
@config = nil
|
29
|
+
def rubyforge_username
|
30
|
+
unless @config
|
31
|
+
begin
|
32
|
+
@config = YAML.load(File.read(File.expand_path(@config_file)))
|
33
|
+
rescue
|
34
|
+
puts <<-EOS
|
35
|
+
ERROR: No rubyforge config file found: #{@config_file}"
|
36
|
+
Run 'rubyforge setup' to prepare your env for access to Rubyforge
|
37
|
+
- See http://newgem.rubyforge.org/rubyforge.html for more details
|
38
|
+
EOS
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
end
|
42
|
+
@rubyforge_username ||= @config["username"]
|
43
|
+
end
|
44
|
+
|
45
|
+
RUBYFORGE_PROJECT = 'clickatell' # The unix name for your project
|
46
|
+
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
47
|
+
DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
|
48
|
+
|
49
|
+
NAME = "clickatell"
|
50
|
+
REV = nil
|
51
|
+
VERS = Clickatell::VERSION::STRING + (REV ? ".#{REV}" : "")
|
52
|
+
CLEAN.include ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store']
|
53
|
+
RDOC_OPTS = ['--quiet', '--title', 'clickatell documentation',
|
54
|
+
"--opname", "index.html",
|
55
|
+
"--line-numbers",
|
56
|
+
"--main", "RDOC_README.txt",
|
57
|
+
"--inline-source"]
|
58
|
+
|
59
|
+
class Hoe
|
60
|
+
def extra_deps
|
61
|
+
@extra_deps.reject { |x| Array(x).first == 'hoe' }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Generate all the Rake tasks
|
66
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
67
|
+
hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
68
|
+
p.author = AUTHOR
|
69
|
+
p.description = DESCRIPTION
|
70
|
+
p.email = EMAIL
|
71
|
+
p.summary = DESCRIPTION
|
72
|
+
p.url = HOMEPATH
|
73
|
+
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
74
|
+
p.test_globs = ["test/**/test_*.rb"]
|
75
|
+
p.clean_globs |= CLEAN #An array of file patterns to delete on clean.
|
76
|
+
|
77
|
+
# == Optional
|
78
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
79
|
+
#p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
|
80
|
+
#p.spec_extras = {} # A hash of extra values to set in the gemspec.
|
81
|
+
end
|
82
|
+
|
83
|
+
CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\n\n")
|
84
|
+
PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
|
85
|
+
hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
|
86
|
+
|
87
|
+
desc 'Generate website files'
|
88
|
+
task :website_generate do
|
89
|
+
Dir['website/**/*.txt'].each do |txt|
|
90
|
+
sh %{ ruby scripts/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
|
91
|
+
end
|
92
|
+
sh "rake -s spec:html > website/specs.html"
|
93
|
+
end
|
94
|
+
|
95
|
+
desc 'Upload website files to rubyforge'
|
96
|
+
task :website_upload do
|
97
|
+
host = "#{rubyforge_username}@rubyforge.org"
|
98
|
+
remote_dir = "/var/www/gforge-projects/#{PATH}/"
|
99
|
+
local_dir = 'website'
|
100
|
+
sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}}
|
101
|
+
end
|
102
|
+
|
103
|
+
desc 'Generate and upload website files'
|
104
|
+
task :website => [:website_generate, :website_upload, :publish_docs]
|
105
|
+
|
106
|
+
desc 'Release the website and new gem version'
|
107
|
+
task :deploy => [:check_version, :website, :release] do
|
108
|
+
puts "Remember to create SVN tag:"
|
109
|
+
puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
|
110
|
+
"svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
|
111
|
+
puts "Suggested comment:"
|
112
|
+
puts "Tagging release #{CHANGES}"
|
113
|
+
end
|
114
|
+
|
115
|
+
desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
|
116
|
+
task :local_deploy => [:website_generate, :install_gem]
|
117
|
+
|
118
|
+
task :check_version do
|
119
|
+
unless ENV['VERSION']
|
120
|
+
puts 'Must pass a VERSION=x.y.z release version'
|
121
|
+
exit
|
122
|
+
end
|
123
|
+
unless ENV['VERSION'] == VERS
|
124
|
+
puts "Please update your version.rb to match the release version, currently #{VERS}"
|
125
|
+
exit
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
Rake::RDocTask.new('docs') do |rd|
|
130
|
+
rd.main = 'RDOC_README.txt'
|
131
|
+
rd.rdoc_files.include('RDOC_README.txt', 'History.txt', 'License.txt', 'lib/**/*.rb')
|
132
|
+
rd.rdoc_dir = 'doc'
|
133
|
+
rd.options << '--style=http://clickatell.rubyforge.org/stylesheets/rdoc.css'
|
134
|
+
rd.options << '--tab-width=2'
|
135
|
+
rd.options << '--inline-source'
|
136
|
+
rd.options << '--line-numbers'
|
137
|
+
end
|
138
|
+
|
139
|
+
namespace :spec do
|
140
|
+
desc "Run the specs under spec"
|
141
|
+
Spec::Rake::SpecTask.new('all') do |t|
|
142
|
+
t.spec_opts = ['--options', "spec/spec.opts"]
|
143
|
+
t.spec_files = FileList['spec/*_spec.rb']
|
144
|
+
end
|
145
|
+
|
146
|
+
desc "Run the specs under spec in specdoc format"
|
147
|
+
Spec::Rake::SpecTask.new('doc') do |t|
|
148
|
+
t.spec_opts = ['--format', "specdoc"]
|
149
|
+
t.spec_files = FileList['spec/*_spec.rb']
|
150
|
+
end
|
151
|
+
|
152
|
+
desc "Run the specs in HTML format"
|
153
|
+
Spec::Rake::SpecTask.new('html') do |t|
|
154
|
+
t.spec_files = FileList['spec/*_spec.rb']
|
155
|
+
t.spec_opts = ['--format', "html:website/specs.html"]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
desc "Default task is to run specs"
|
160
|
+
task :default => 'spec:all'
|
data/clickatell.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "clickatell"
|
3
|
+
s.version = "0.5.1"
|
4
|
+
s.date = "2009-03-03"
|
5
|
+
s.summary = "Ruby interface to the Clickatell SMS Gateway API"
|
6
|
+
s.email = "ben@commonthread.com"
|
7
|
+
s.homepage = "http://clickatell.rubyforge.org"
|
8
|
+
s.description = "Ruby interface to the Clickatell SMS Gateway API"
|
9
|
+
s.has_rdoc = true
|
10
|
+
s.authors = ["Luke Redpath", "Ben Wyrosdick", "Anthony Crumley"]
|
11
|
+
s.files = ["README.textile",
|
12
|
+
"RDOC_README.txt",
|
13
|
+
"License.txt",
|
14
|
+
"Manifest.txt",
|
15
|
+
"Rakefile",
|
16
|
+
"History.txt",
|
17
|
+
"clickatell.gemspec",
|
18
|
+
"setup.rb",
|
19
|
+
"lib/clickatell.rb",
|
20
|
+
"lib/clickatell/api.rb",
|
21
|
+
"lib/clickatell/response.rb",
|
22
|
+
"lib/clickatell/utility.rb",
|
23
|
+
"lib/clickatell/version.rb",
|
24
|
+
"lib/clickatell/api/command.rb",
|
25
|
+
"lib/clickatell/api/command_executor.rb",
|
26
|
+
"lib/clickatell/api/error.rb",
|
27
|
+
"lib/clickatell/api/message_status.rb",
|
28
|
+
"lib/clickatell/utility/options.rb",
|
29
|
+
"lib/clickatell/core-ext/hash.rb",
|
30
|
+
"lib/clickatell/core-ext/object.rb"]
|
31
|
+
s.rdoc_options = ["--main", "RDOC_README.txt"]
|
32
|
+
s.extra_rdoc_files = ["RDOC_README.txt"]
|
33
|
+
end
|
@@ -0,0 +1,30 @@
|
|
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, service = 'http', opts={})
|
10
|
+
@command_name = command_name
|
11
|
+
@service = service
|
12
|
+
@options = { :secure => false }.merge(opts)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns a URL for the given parameters (a hash).
|
16
|
+
def with_params(param_hash)
|
17
|
+
param_string = '?' + param_hash.map { |key, value| "#{key}=#{CGI.escape(value)}" }.sort.join('&')
|
18
|
+
return URI.parse(File.join(api_service_uri, @command_name + param_string))
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
def api_service_uri
|
23
|
+
protocol = @options[:secure] ? 'https' : 'http'
|
24
|
+
api_service_host = (Clickatell::API.api_service_host.blank? ? API_SERVICE_HOST : Clickatell::API.api_service_host)
|
25
|
+
return "#{protocol}://#{api_service_host}/#{@service}/"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
|
4
|
+
module Clickatell
|
5
|
+
class API
|
6
|
+
|
7
|
+
# Used to run commands agains the Clickatell gateway.
|
8
|
+
class CommandExecutor
|
9
|
+
def initialize(authentication_hash, secure=false, debug=false)
|
10
|
+
@authentication_hash = authentication_hash
|
11
|
+
@debug = debug
|
12
|
+
@secure = secure
|
13
|
+
end
|
14
|
+
|
15
|
+
# Builds a command object and sends it using HTTP GET.
|
16
|
+
# Will output URLs as they are requested to stdout when
|
17
|
+
# debugging is enabled.
|
18
|
+
def execute(command_name, service, parameters={})
|
19
|
+
request_uri = command(command_name, service, parameters)
|
20
|
+
puts "[debug] Sending request to #{request_uri}" if @debug
|
21
|
+
get_response(request_uri).first
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
def command(command_name, service, parameters) #:nodoc:
|
26
|
+
Command.new(command_name, service, :secure => @secure).with_params(
|
27
|
+
parameters.merge(@authentication_hash)
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_response(uri)
|
32
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
33
|
+
http.use_ssl = (uri.scheme == 'https')
|
34
|
+
http.start do |http|
|
35
|
+
resp, body = http.get([uri.path, uri.query].join('?'))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
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
|
@@ -0,0 +1,129 @@
|
|
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
|
23
|
+
|
24
|
+
# Allow customizing URL
|
25
|
+
attr_accessor :api_service_host
|
26
|
+
end
|
27
|
+
|
28
|
+
# Creates a new API instance using the specified +auth options+.
|
29
|
+
# +auth_options+ is a hash containing either a :session_id or
|
30
|
+
# :username, :password and :api_key.
|
31
|
+
#
|
32
|
+
# Some API calls (authenticate, ping etc.) do not require any
|
33
|
+
# +auth_options+. +auth_options+ can be updated using the accessor methods.
|
34
|
+
def initialize(auth_options={})
|
35
|
+
@auth_options = auth_options
|
36
|
+
end
|
37
|
+
|
38
|
+
# Authenticates using the specified credentials. Returns
|
39
|
+
# a session_id if successful which can be used in subsequent
|
40
|
+
# API calls.
|
41
|
+
def authenticate(api_id, username, password)
|
42
|
+
response = execute_command('auth', 'http',
|
43
|
+
:api_id => api_id,
|
44
|
+
:user => username,
|
45
|
+
:password => password
|
46
|
+
)
|
47
|
+
parse_response(response)['OK']
|
48
|
+
end
|
49
|
+
|
50
|
+
# Pings the service with the specified session_id to keep the
|
51
|
+
# session alive.
|
52
|
+
def ping(session_id)
|
53
|
+
execute_command('ping', 'http', :session_id => session_id)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Sends a message +message_text+ to +recipient+. Recipient
|
57
|
+
# number should have an international dialing prefix and
|
58
|
+
# no leading zeros (unless you have set a default prefix
|
59
|
+
# in your clickatell account centre).
|
60
|
+
#
|
61
|
+
# Additional options:
|
62
|
+
# :from - the from number/name
|
63
|
+
# :set_mobile_originated - mobile originated flag
|
64
|
+
#
|
65
|
+
# Returns a new message ID if successful.
|
66
|
+
def send_message(recipient, message_text, opts={})
|
67
|
+
valid_options = opts.only(:from, :mo)
|
68
|
+
valid_options.merge!(:req_feat => '48') if valid_options[:from]
|
69
|
+
valid_options.merge!(:mo => '1') if opts[:set_mobile_originated]
|
70
|
+
response = execute_command('sendmsg', 'http',
|
71
|
+
{:to => recipient, :text => message_text}.merge(valid_options)
|
72
|
+
)
|
73
|
+
parse_response(response)['ID']
|
74
|
+
end
|
75
|
+
|
76
|
+
def send_wap_push(recipient, media_url, notification_text='', opts={})
|
77
|
+
valid_options = opts.only(:from)
|
78
|
+
valid_options.merge!(:req_feat => '48') if valid_options[:from]
|
79
|
+
response = execute_command('si_push', 'mms',
|
80
|
+
{:to => recipient, :si_url => media_url, :si_text => notification_text, :si_id => 'foo'}.merge(valid_options)
|
81
|
+
)
|
82
|
+
parse_response(response)['ID']
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns the status of a message. Use message ID returned
|
86
|
+
# from original send_message call.
|
87
|
+
def message_status(message_id)
|
88
|
+
response = execute_command('querymsg', 'http', :apimsgid => message_id)
|
89
|
+
parse_response(response)['Status']
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns the number of credits remaining as a float.
|
93
|
+
def account_balance
|
94
|
+
response = execute_command('getbalance', 'http')
|
95
|
+
parse_response(response)['Credit'].to_f
|
96
|
+
end
|
97
|
+
|
98
|
+
protected
|
99
|
+
def execute_command(command_name, service, parameters={}) #:nodoc:
|
100
|
+
CommandExecutor.new(auth_hash, self.class.secure_mode, self.class.debug_mode).execute(command_name, service, parameters)
|
101
|
+
end
|
102
|
+
|
103
|
+
def parse_response(raw_response) #:nodoc:
|
104
|
+
Clickatell::Response.parse(raw_response)
|
105
|
+
end
|
106
|
+
|
107
|
+
def auth_hash #:nodoc:
|
108
|
+
if @auth_options[:session_id]
|
109
|
+
{ :session_id => @auth_options[:session_id] }
|
110
|
+
elsif @auth_options[:api_id]
|
111
|
+
{ :user => @auth_options[:username],
|
112
|
+
:password => @auth_options[:password],
|
113
|
+
:api_id => @auth_options[:api_key] }
|
114
|
+
else
|
115
|
+
{}
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
%w( api/command
|
123
|
+
api/command_executor
|
124
|
+
api/error
|
125
|
+
api/message_status
|
126
|
+
|
127
|
+
).each do |lib|
|
128
|
+
require File.join(File.dirname(__FILE__), lib)
|
129
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Clickatell
|
4
|
+
|
5
|
+
# Used to parse HTTP responses returned from Clickatell API calls.
|
6
|
+
class Response
|
7
|
+
|
8
|
+
class << self
|
9
|
+
PARSE_REGEX = /[A-Za-z0-9]+:.*?(?:(?=[A-Za-z0-9]+:)|$)/
|
10
|
+
|
11
|
+
# Returns the HTTP response body data as a hash.
|
12
|
+
def parse(http_response)
|
13
|
+
if http_response.body.scan(/ERR/).any?
|
14
|
+
raise Clickatell::API::Error.parse(http_response.body)
|
15
|
+
end
|
16
|
+
YAML.load(http_response.body.scan(PARSE_REGEX).join("\n"))
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|