clickatell-ruby19 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ doc/*
2
+ website/*
3
+ pkg/*
4
+ .specification
5
+ pkg
6
+ rdoc
data/History.txt ADDED
@@ -0,0 +1,55 @@
1
+ == 0.7.1
2
+
3
+ * Fixed broken -b (balance) command
4
+
5
+ == 0.7.0
6
+
7
+ * Added support for sending SMS to multiple recipients.
8
+
9
+ == 0.6.0
10
+
11
+ * API host can now be customized (John Gibbons)
12
+ * Fixed bug with the ampersands in messages, they are now escaped properly (John Brice)
13
+ * Removed reliance on Object#blank? which was causing some compatibility issues (Greg Bell)
14
+ * Added :callback option support (Greg Bell)
15
+ * Added new test mode (Pivotal Labs)
16
+
17
+ == 0.5.0
18
+
19
+ * Added support for mobile originated flag (courtesy Dan Weinand)
20
+ * Added support for WAP push (experimental, courtesy Zhao Lu)
21
+ * Updated specs to use Mocha instead of the built-in RSpec mocking
22
+ * Improved specs in general
23
+
24
+ == 0.4.1
25
+
26
+ * Custom alphanumeric sender would not always be supported by default unless it was explicitly enabled using the req_feat parameter.
27
+
28
+ == 0.4.0
29
+
30
+ * Added API debug mode and --debug option to sms utility
31
+ * Restructured API classes into individual files
32
+ * Refactored command execution into a separate object (CommandExecutor).
33
+ * 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.
34
+
35
+ == 0.3.0
36
+
37
+ * Display proper message status, not just the code
38
+ * Make it possible to specify custom :from number/name using SMS utility
39
+ * Added support for custom :from number/name when sending a message.
40
+ * Added support for checking message status to sms utility
41
+ * sms utility now returns the id of a successfully sent message.
42
+ * Capture API KEY errors.
43
+ * Make sure errors are handled when using sms utility to check balance.
44
+
45
+ == 0.2.0
46
+
47
+ * Added Clickatell API error handling to API and sms utility.
48
+ * Handle required/optional arguments for sms utility correctly
49
+ * Added further sms utility usage information to website
50
+ * Make sure sms utility gracefully handles missing recipient/message
51
+ * Added balance query support to API and SMS utility (--check-balance).
52
+
53
+ == 0.1.0 2007-08-17
54
+
55
+ * 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,40 @@
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
+ To send a message to multiple recipients, simply pass in an array of numbers.
16
+
17
+ api.send_message(['447771234567', '447771234568'], 'Hello from clickatell')
18
+
19
+ h2. Command-line SMS Utility
20
+
21
+ The Clickatell gem also comes with a command-line utility that will allow you to send an SMS directly from the command-line.
22
+
23
+ You will need to create a YAML configuration file in your home directory, in a file called .clickatell that resembles the following:
24
+
25
+ # ~/.clickatell
26
+ api_key: your_api_id
27
+ username: your_username
28
+ password: your_password
29
+
30
+ You can then use the sms utility to send a message to a single recipient:
31
+
32
+ sms 447771234567 'Hello from clickatell'
33
+
34
+ Alternatively, you can specify the username and password as a command line option. Run +sms+ without any arguments for a full list of options.
35
+
36
+ The sms utility also supports multiple, comma-separated recipients (up to 100).
37
+
38
+ sms 447771111111,447772222222 "Hello everyone"
39
+
40
+ See http://clickatell.rubyforge.org for further instructions.
data/Rakefile ADDED
@@ -0,0 +1,95 @@
1
+ require "rubygems"
2
+ require "rake/rdoctask"
3
+ require File.join(File.dirname(__FILE__), *%w[lib clickatell version])
4
+
5
+ begin
6
+ require 'jeweler'
7
+
8
+ Jeweler::Tasks.new do |gemspec|
9
+ gemspec.name = "clickatell-ruby19"
10
+ gemspec.summary = "Ruby interface to the Clickatell SMS gateway service."
11
+ gemspec.email = "luke@lukeredpath.co.uk"
12
+ gemspec.homepage = "http://clickatell.rubyforge.org"
13
+ gemspec.authors = ["Luke Redpath", "Ahmed Al Hafoudh"]
14
+ gemspec.executables = %w{sms}
15
+ gemspec.extra_rdoc_files = %w{RDOC_README.txt History.txt License.txt}
16
+ gemspec.has_rdoc = true
17
+ gemspec.rdoc_options = %w{--main RDOC_README.txt}
18
+ gemspec.version = Clickatell::VERSION
19
+ end
20
+
21
+ Jeweler::GemcutterTasks.new
22
+
23
+ rescue LoadError
24
+ puts "Jeweler not available. Install it with: gem install jeweler"
25
+ end
26
+
27
+ task :default => :spec
28
+
29
+ require "spec"
30
+ require "spec/rake/spectask"
31
+
32
+ Spec::Rake::SpecTask.new do |t|
33
+ t.spec_opts = %w(--format specdoc --colour)
34
+ t.libs = ["spec"]
35
+ end
36
+
37
+ Spec::Rake::SpecTask.new("spec_html") do |t|
38
+ t.spec_opts = %w(--format html)
39
+ t.libs = ["spec"]
40
+ end
41
+
42
+ # Rake::RDocTask.new do |rd|
43
+ # rd.main = "RDOC_README.txt"
44
+ # rd.rdoc_files.include("lib/**/*.rb", *$gemspec.extra_rdoc_files)
45
+ # rd.rdoc_dir = "rdoc"
46
+ # end
47
+
48
+ desc 'Generate website files'
49
+ task :website do
50
+ Dir['website/**/*.txt'].each do |txt|
51
+ sh %{ ruby scripts/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
52
+ end
53
+ sh "rake -s spec_html > website/specs.html"
54
+ end
55
+
56
+ desc 'Clear out RDoc and generated packages'
57
+ task :clean => [:clobber_rdoc, :clobber_package]
58
+
59
+ begin
60
+ require "rake/contrib/sshpublisher"
61
+ namespace :rubyforge do
62
+
63
+ desc "Release gem and RDoc documentation to RubyForge"
64
+ task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
65
+
66
+ namespace :release do
67
+ desc "Release a new version of this gem"
68
+ task :gem => [:package] do
69
+ require 'rubyforge'
70
+ rubyforge = RubyForge.new
71
+ rubyforge.configure
72
+ rubyforge.login
73
+ rubyforge.userconfig['release_notes'] = $gemspec.summary
74
+ path_to_gem = File.join(File.dirname(__FILE__), "pkg", "#{$gemspec.name}-#{$gemspec.version}.gem")
75
+ puts "Publishing #{$gemspec.name}-#{$gemspec.version.to_s} to Rubyforge..."
76
+ rubyforge.add_release($gemspec.rubyforge_project, $gemspec.name, $gemspec.version.to_s, path_to_gem)
77
+ end
78
+
79
+ desc "Publish RDoc to RubyForge."
80
+ task :docs => [:rdoc, :website] do
81
+ config = YAML.load(
82
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
83
+ )
84
+
85
+ host = "#{config['username']}@rubyforge.org"
86
+ remote_dir = "/var/www/gforge-projects/clickatell/"
87
+
88
+ Rake::SshDirPublisher.new(host, remote_dir, 'website').upload
89
+ Rake::SshDirPublisher.new(host, File.join(remote_dir, 'rdoc'), 'rdoc').upload
90
+ end
91
+ end
92
+ end
93
+ rescue LoadError
94
+ puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
95
+ end
data/bin/sms ADDED
@@ -0,0 +1,62 @@
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 contact the author (contact@lukeredpath.co.uk) with the above error."
55
+ exit 1
56
+ end
57
+
58
+ rescue Timeout::Error
59
+ puts "The connection the the Clickatell service timed out"
60
+ puts "Please check your network settings and try again."
61
+ exit 1
62
+ end
@@ -0,0 +1,82 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{clickatell-ruby19}
8
+ s.version = "0.7.1.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Luke Redpath","Ahmed Al Hafoudh"]
12
+ s.date = %q{2009-12-01}
13
+ s.default_executable = %q{sms}
14
+ s.email = %q{luke@lukeredpath.co.uk}
15
+ s.executables = ["sms"]
16
+ s.extra_rdoc_files = [
17
+ "History.txt",
18
+ "License.txt",
19
+ "RDOC_README.txt"
20
+ ]
21
+ s.files = [
22
+ ".gitignore",
23
+ "History.txt",
24
+ "License.txt",
25
+ "RDOC_README.txt",
26
+ "README.textile",
27
+ "Rakefile",
28
+ "bin/sms",
29
+ "lib/clickatell.rb",
30
+ "lib/clickatell/api.rb",
31
+ "lib/clickatell/api/command.rb",
32
+ "lib/clickatell/api/command_executor.rb",
33
+ "lib/clickatell/api/error.rb",
34
+ "lib/clickatell/api/message_status.rb",
35
+ "lib/clickatell/response.rb",
36
+ "lib/clickatell/utility.rb",
37
+ "lib/clickatell/utility/options.rb",
38
+ "lib/clickatell/version.rb",
39
+ "lib/core-ext/hash.rb",
40
+ "scripts/txt2html",
41
+ "spec/api_spec.rb",
42
+ "spec/cli_options_test.rb",
43
+ "spec/command_executor_spec.rb",
44
+ "spec/hash_ext_spec.rb",
45
+ "spec/response_spec.rb",
46
+ "spec/spec.opts",
47
+ "spec/spec_helper.rb",
48
+ "website/images/footer_bg.gif",
49
+ "website/index.txt",
50
+ "website/javascripts/codehighlighter/code_highlighter.js",
51
+ "website/javascripts/codehighlighter/ruby.js",
52
+ "website/javascripts/rounded_corners_lite.inc.js",
53
+ "website/stylesheets/limechoc.css",
54
+ "website/stylesheets/rdoc.css",
55
+ "website/stylesheets/screen.css",
56
+ "website/template.rhtml"
57
+ ]
58
+ s.homepage = %q{http://clickatell.rubyforge.org}
59
+ s.rdoc_options = ["--main", "RDOC_README.txt"]
60
+ s.require_paths = ["lib"]
61
+ s.rubygems_version = %q{1.3.5}
62
+ s.summary = %q{Ruby 1.9 compatible interface to the Clickatell SMS gateway service. }
63
+ s.test_files = [
64
+ "spec/api_spec.rb",
65
+ "spec/cli_options_test.rb",
66
+ "spec/command_executor_spec.rb",
67
+ "spec/hash_ext_spec.rb",
68
+ "spec/response_spec.rb",
69
+ "spec/spec_helper.rb"
70
+ ]
71
+
72
+ if s.respond_to? :specification_version then
73
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
74
+ s.specification_version = 3
75
+
76
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
77
+ else
78
+ end
79
+ else
80
+ end
81
+ end
82
+
data/lib/clickatell.rb ADDED
@@ -0,0 +1,10 @@
1
+ module Clickatelll end
2
+
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
@@ -0,0 +1,153 @@
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
+
27
+ # Set to true to test message sending; this will not actually send
28
+ # messages but will collect sent messages in a testable collection.
29
+ # (off by default)
30
+ attr_accessor :test_mode
31
+ end
32
+ self.debug_mode = false
33
+ self.secure_mode = false
34
+ self.test_mode = false
35
+
36
+ # Creates a new API instance using the specified +auth options+.
37
+ # +auth_options+ is a hash containing either a :session_id or
38
+ # :username, :password and :api_key.
39
+ #
40
+ # Some API calls (authenticate, ping etc.) do not require any
41
+ # +auth_options+. +auth_options+ can be updated using the accessor methods.
42
+ def initialize(auth_options={})
43
+ @auth_options = auth_options
44
+ end
45
+
46
+ # Authenticates using the specified credentials. Returns
47
+ # a session_id if successful which can be used in subsequent
48
+ # API calls.
49
+ def authenticate(api_id, username, password)
50
+ response = execute_command('auth', 'http',
51
+ :api_id => api_id,
52
+ :user => username,
53
+ :password => password
54
+ )
55
+ parse_response(response)['OK']
56
+ end
57
+
58
+ # Pings the service with the specified session_id to keep the
59
+ # session alive.
60
+ def ping(session_id)
61
+ execute_command('ping', 'http', :session_id => session_id)
62
+ end
63
+
64
+ # Sends a message +message_text+ to +recipient+. Recipient
65
+ # number should have an international dialing prefix and
66
+ # no leading zeros (unless you have set a default prefix
67
+ # in your clickatell account centre).
68
+ #
69
+ # Additional options:
70
+ # :from - the from number/name
71
+ # :set_mobile_originated - mobile originated flag
72
+ #
73
+ # Returns a new message ID if successful.
74
+ def send_message(recipient, message_text, opts={})
75
+ valid_options = opts.only(:from, :mo, :callback)
76
+ valid_options.merge!(:req_feat => '48') if valid_options[:from]
77
+ valid_options.merge!(:mo => '1') if opts[:set_mobile_originated]
78
+ recipient = recipient.join(",")if recipient.is_a?(Array)
79
+ response = execute_command('sendmsg', 'http',
80
+ {:to => recipient, :text => message_text}.merge(valid_options)
81
+ )
82
+ response = parse_response(response)
83
+ response.is_a?(Array) ? response.map { |r| r['ID'] } : response['ID']
84
+ end
85
+
86
+ def send_wap_push(recipient, media_url, notification_text='', opts={})
87
+ valid_options = opts.only(:from)
88
+ valid_options.merge!(:req_feat => '48') if valid_options[:from]
89
+ response = execute_command('si_push', 'mms',
90
+ {:to => recipient, :si_url => media_url, :si_text => notification_text, :si_id => 'foo'}.merge(valid_options)
91
+ )
92
+ parse_response(response)['ID']
93
+ end
94
+
95
+ # Returns the status of a message. Use message ID returned
96
+ # from original send_message call.
97
+ def message_status(message_id)
98
+ response = execute_command('querymsg', 'http', :apimsgid => message_id)
99
+ parse_response(response)['Status']
100
+ end
101
+
102
+ def message_charge(message_id)
103
+ response = execute_command('getmsgcharge', 'http', :apimsgid => message_id)
104
+ parse_response(response)['charge'].to_f
105
+ end
106
+
107
+ # Returns the number of credits remaining as a float.
108
+ def account_balance
109
+ response = execute_command('getbalance', 'http')
110
+ parse_response(response)['Credit'].to_f
111
+ end
112
+
113
+ def sms_requests
114
+ @sms_requests ||= []
115
+ end
116
+
117
+ protected
118
+ def execute_command(command_name, service, parameters={}) #:nodoc:
119
+ executor = CommandExecutor.new(auth_hash, self.class.secure_mode, self.class.debug_mode, self.class.test_mode)
120
+ result = executor.execute(command_name, service, parameters)
121
+
122
+ (sms_requests << executor.sms_requests).flatten! if self.class.test_mode
123
+
124
+ result
125
+ end
126
+
127
+ def parse_response(raw_response) #:nodoc:
128
+ Clickatell::Response.parse(raw_response)
129
+ end
130
+
131
+ def auth_hash #:nodoc:
132
+ if @auth_options[:session_id]
133
+ { :session_id => @auth_options[:session_id] }
134
+ elsif @auth_options[:api_id]
135
+ { :user => @auth_options[:username],
136
+ :password => @auth_options[:password],
137
+ :api_id => @auth_options[:api_key] }
138
+ else
139
+ {}
140
+ end
141
+ end
142
+
143
+ end
144
+ end
145
+
146
+ %w( api/command
147
+ api/command_executor
148
+ api/error
149
+ api/message_status
150
+
151
+ ).each do |lib|
152
+ require File.join(File.dirname(__FILE__), lib)
153
+ end