lookout-clickatell 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ doc/*
2
+ website/*
3
+ *.gem
4
+ .bundle
5
+ Gemfile.lock
6
+ pkg/*
7
+ .specification
8
+ rdoc
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source :gemcutter
2
+
3
+ gem 'rake'
4
+
5
+ # Specify your gem's dependencies in clickatell.gemspec
6
+ gemspec
7
+
8
+ group :test do
9
+ gem "rspec"
10
+ gem "mocha"
11
+ end
@@ -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.
@@ -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.
@@ -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.
@@ -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.
@@ -0,0 +1,11 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |spec|
5
+ end
6
+
7
+ task :test do
8
+ puts "No-op for now"
9
+ end
10
+
11
+ task :default => [:spec, :build]
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
@@ -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
@@ -0,0 +1,9 @@
1
+ module Clickatelll end
2
+
3
+ %w( core-ext/hash
4
+ clickatell/api
5
+ clickatell/response
6
+
7
+ ).each do |lib|
8
+ require File.join(File.dirname(__FILE__), lib)
9
+ end
@@ -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