nofxx-activesms 0.9.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.
Files changed (56) hide show
  1. data/.autotest +17 -0
  2. data/CHANGELOG +5 -0
  3. data/History.txt +25 -0
  4. data/License.txt +22 -0
  5. data/MIT-LICENSE +22 -0
  6. data/Manifest.txt +56 -0
  7. data/README.txt +54 -0
  8. data/Rakefile +16 -0
  9. data/activesms.gemspec +36 -0
  10. data/config/hoe.rb +78 -0
  11. data/config/requirements.rb +15 -0
  12. the PDU format.webarchive +0 -0
  13. data/generators/sms/USAGE +20 -0
  14. data/generators/sms/sms_generator.rb +35 -0
  15. data/generators/sms/templates/fixture.rhtml +1 -0
  16. data/generators/sms/templates/model.rb +19 -0
  17. data/generators/sms/templates/sms.yml +103 -0
  18. data/generators/sms/templates/unit_test.rb +31 -0
  19. data/init.rb +4 -0
  20. data/lib/activesms.rb +79 -0
  21. data/lib/activesms/adv_attr_accessor.rb +32 -0
  22. data/lib/activesms/base.rb +249 -0
  23. data/lib/activesms/config.rb +20 -0
  24. data/lib/activesms/connection_adapters/abstract_adapter.rb +52 -0
  25. data/lib/activesms/connection_adapters/bulk_sms_adapter.rb +67 -0
  26. data/lib/activesms/connection_adapters/clickatell_adapter.rb +51 -0
  27. data/lib/activesms/connection_adapters/human_adapter.rb +174 -0
  28. data/lib/activesms/connection_adapters/simplewire_adapter.rb +73 -0
  29. data/lib/activesms/connections.rb +63 -0
  30. data/lib/activesms/email.rb +60 -0
  31. data/lib/activesms/exceptions.rb +35 -0
  32. data/lib/activesms/sms.rb +9 -0
  33. data/lib/activesms/sms2email.rb +21 -0
  34. data/lib/activesms/validations.rb +86 -0
  35. data/lib/activesms/version.rb +9 -0
  36. data/lib/activesms/views/active_sms/sms2_email/sms_message.html.erb +1 -0
  37. data/script/console +10 -0
  38. data/script/destroy +14 -0
  39. data/script/generate +14 -0
  40. data/script/txt2html +82 -0
  41. data/setup.rb +1585 -0
  42. data/spec/activesms/base_spec.rb +11 -0
  43. data/spec/activesms/connection_adapters/abstract_adapter_spec.rb +30 -0
  44. data/spec/activesms/connection_adapters/human_adapter_spec.rb +38 -0
  45. data/spec/activesms/connection_adapters/simplewire_spec.rb +75 -0
  46. data/spec/activesms/email_spec.rb +72 -0
  47. data/spec/activesms/sms2email_spec.rb +31 -0
  48. data/spec/activesms/sms_spec.rb +31 -0
  49. data/spec/activesms_spec.rb +15 -0
  50. data/spec/spec.opts +1 -0
  51. data/spec/spec_helper.rb +57 -0
  52. data/tasks/deployment.rake +34 -0
  53. data/tasks/environment.rake +7 -0
  54. data/tasks/rspec.rake +21 -0
  55. data/views/active_sms/base/sms2_email/sms_message.html.erb +1 -0
  56. metadata +130 -0
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../test_helper'
2
+
3
+ class <%= class_name %>Test < Test::Unit::TestCase
4
+ FIXTURES_PATH = File.dirname(__FILE__) + '<%= '/..' * class_nesting_depth %>/../fixtures'
5
+
6
+ def setup
7
+ ActiveSms::Base.delivery_method = :test
8
+ ActiveSms::Base.perform_deliveries = true
9
+ ActiveSms::Base.deliveries = []
10
+
11
+ @expected = ActiveSms::Sms.new
12
+ end
13
+
14
+ <% actions.each do |action| -%>
15
+ def test_<%= action %>
16
+ @expected.recipients = ''
17
+ @expected.from = ''
18
+ @expected.body = read_fixture('<%= action %>')
19
+
20
+ actual = <%= class_name %>.create_<%= action %>
21
+ assert_equal @expected.recipients, actual.recipients
22
+ assert_equal @expected.from, actual.from
23
+ assert_equal @expected.body, actual.body
24
+ end
25
+
26
+ <% end -%>
27
+ private
28
+ def read_fixture(action)
29
+ IO.read("#{FIXTURES_PATH}/<%= file_path %>/#{action}")
30
+ end
31
+ end
data/init.rb ADDED
@@ -0,0 +1,4 @@
1
+ #require 'rubygems'
2
+ require 'activesms'
3
+ #TODO: check out if we are in rails
4
+ ActiveSms::Base.logger = RAILS_DEFAULT_LOGGER rescue nil
@@ -0,0 +1,79 @@
1
+ #
2
+ # Copyright (c) 2008 Robert Cottrell, Brendan G. Lim (brendangl@gmail.com),
3
+ # Marcos Piccinini, Cássio Marques
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ #++
24
+
25
+ $:.unshift(File.dirname(__FILE__)) unless
26
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
27
+
28
+ # Require ActiveSupport for standard Rails extensions.
29
+ unless defined?(ActiveSupport)
30
+ begin
31
+ require 'active_support'
32
+ rescue LoadError
33
+ require 'rubygems'
34
+ require 'activesupport'
35
+ end
36
+ end
37
+
38
+ # Require ActionController for access to UrlWriter in ActiveSms::Base senders.
39
+ unless defined?(ActionController)
40
+ begin
41
+ require 'action_controller'
42
+ rescue LoadError
43
+ require 'rubygems'
44
+ require 'actionpack', '>= 1.12.5'
45
+ end
46
+ end
47
+
48
+ # Require ActionMailer to perform mail gateway deliveries
49
+ unless defined?(ActionMailer)
50
+ begin
51
+ require 'action_mailer'
52
+ rescue LoadError
53
+ require 'rubygems'
54
+ require 'actionmailer', '>= 1.12.5'
55
+ end
56
+ end
57
+
58
+ require 'activesms/config'
59
+ # Email need config first
60
+ require 'activesms/email'
61
+ require 'activesms/base'
62
+ require 'activesms/connections'
63
+ require 'activesms/exceptions'
64
+ require 'activesms/version'
65
+
66
+ # Require the supported gateways connection adapters.
67
+ require 'activesms/connection_adapters/abstract_adapter'
68
+ require 'activesms/connection_adapters/bulk_sms_adapter'
69
+ require 'activesms/connection_adapters/clickatell_adapter'
70
+ require 'activesms/connection_adapters/human_adapter'
71
+
72
+ # # #
73
+ # # Establish a connection if we have yml parameters
74
+ ActiveSms::Base.establish_connection(ActiveSms::GATEWAY) if ActiveSms::GATEWAY
75
+
76
+ # Simplewire requires jruby
77
+ if RUBY_PLATFORM =~ /java/
78
+ require 'activesms/connection_adapters/simplewire_adapter'
79
+ end
@@ -0,0 +1,32 @@
1
+ # module ActiveSms
2
+ # module AdvAttrAccessor #:nodoc:
3
+ # def self.included(base)
4
+ # base.extend(ClassMethods)
5
+ # end
6
+ #
7
+ # module ClassMethods #:nodoc:
8
+ # def adv_attr_accessor(*names)
9
+ # names.each do |name|
10
+ # ivar = "@#{name}"
11
+ #
12
+ # define_method("#{name}=") do |value|
13
+ # instance_variable_set(ivar, value)
14
+ # end
15
+ #
16
+ # define_method(name) do |*parameters|
17
+ # if parameters.length > 1
18
+ # raise ArgumentError, "expected 0 or 1 parameters"
19
+ # end
20
+ # if parameters.empty?
21
+ # if instance_variables.include?(ivar)
22
+ # instance_variable_get(ivar)
23
+ # end
24
+ # else
25
+ # instance_variable_set(ivar, parameters.first)
26
+ # end
27
+ # end
28
+ # end
29
+ # end
30
+ # end
31
+ # end
32
+ # end
@@ -0,0 +1,249 @@
1
+ #require 'activesms/adv_attr_accessor'
2
+ require 'activesms/sms'
3
+ require 'activesms/sms2email'
4
+ require 'net/https'
5
+
6
+ module ActiveSms #:nodoc:
7
+
8
+ # Active SMS allows you to send SMS messages from your application using
9
+ # an SMS model.
10
+ #
11
+ # = SMS models
12
+ #
13
+ # To use Action SMS, you need to create an SMS model.
14
+ #
15
+ # $ script/generate sms Notifier signup
16
+ #
17
+ # The generated model inherits from ActiveSms::Base. SMS messages are
18
+ # defined by creating methods on the model which are then used to set
19
+ # variables to be used in the message or to change options on the message.
20
+ #
21
+ # Examples:
22
+ #
23
+ # class Notifier < ActiveSms::Base
24
+ # def signup
25
+ # delivery = :gateway
26
+ # recipients = "447987654321"
27
+ # from = "447123456789"
28
+ # body = "Your account has been created"
29
+ # end
30
+ # end
31
+ #
32
+ # Sender methods have the following configuration methods available.
33
+ #
34
+ # * <tt>delivery</tt> - Method to use to delivery the SMS.
35
+ # Accept two paramenters: :gateway or :email
36
+ #
37
+ # * <tt>recipients</tt> - Takes one or more destination numbers. These
38
+ # numbers should be formatted in standard international number format.
39
+ #
40
+ # * <tt>from</tt> - Who the SMS message you are sending is from. This
41
+ # may be either a number formatted in standard internation number format,
42
+ # or, if the gateway supports it, an alphanumeric origination.
43
+ #
44
+ # * <tt>body</tt> - The content of the message. This must fit within the
45
+ # length limitation of SMS messages.
46
+ #
47
+ # = Sending SMS messages
48
+ #
49
+ # Once an SMS action is defined, you can deliver you message or create it
50
+ # and save it for delivery later.
51
+ #
52
+ # Notifier.deliver_signup_noification(david) # sends the SMS message
53
+ #
54
+ # sms = Notifier.create_signup_notification(david) # an SMS object
55
+ # Notifier.deliver(sms)
56
+ #
57
+ # You never instantiate your model class. Rather, your delivery instance
58
+ # methods are automatically wrapped in class methods that start with the
59
+ # word <tt>deliver</tt> followed by the name of the SMS method that you
60
+ # would like to deliver. The <tt>signup_notification</tt> method defined
61
+ # above is delivered by invoking <tt>Notifier.deliver_signup_notification</tt>.
62
+ #
63
+ # = Configuration options
64
+ #
65
+ # These options are specified on the class level.
66
+ #
67
+ # * <tt>logger</tt> - The logger is used for generating information about
68
+ # the sending run if available. This can be set to nil for no logging.
69
+ # It is compatible with Ruby's own Logger and Log4r loggers.
70
+ #
71
+ # * <tt>gateway_settings</tt> - Allows detailed configuration of the SMS
72
+ # gateway used to deliver the messages. Some gateways may require
73
+ # additional configuration settings.
74
+ #
75
+ # * <tt>raise_delivery_errors</tt> - Determines whether or not errors should
76
+ # be raised if the SMS fails to be delivered.
77
+ #
78
+ # * <tt>delivery_method</tt> - Defines a delivery method. Possible values
79
+ # are :gateway (default) or :test.
80
+ #
81
+ # * <tt>perform_deliveries</tt> - Determines whether or not deliver_*
82
+ # methods are actually carried out. By default they are, but this can be
83
+ # turned off to help functional testing.
84
+ #
85
+ # * <tt>deliveries</tt> - Keeps an array of all the messages sent out through
86
+ # Active SMS with deliver_method :test. Most useful for unit and functional
87
+ # testing.
88
+ class Base
89
+ include ActionMailer::AdvAttrAccessor
90
+ include ActionController::UrlWriter
91
+ include Email
92
+
93
+ @@logger = nil
94
+ cattr_accessor :logger
95
+
96
+ private_class_method :new #:nodoc:
97
+
98
+ @@raise_delivery_errors = true
99
+ cattr_accessor :raise_delivery_errors
100
+
101
+ @@delivery_method = :gateway
102
+ cattr_accessor :delivery_method
103
+
104
+ @@perform_deliveries = true
105
+ cattr_accessor :perform_deliveries
106
+
107
+ @@deliveries = []
108
+ cattr_accessor :deliveries
109
+
110
+ # Method to deliver :gateway or :email
111
+ adv_attr_accessor :delivery
112
+
113
+ # If email we should have a carrier
114
+ adv_attr_accessor :carrier
115
+
116
+ # The recipient numbers for the message, either as a string (for a single
117
+ # recipient) or an array (for multiple recipientipients).
118
+ adv_attr_accessor :recipients
119
+
120
+ # Specify the from number or identifier for the message.
121
+ adv_attr_accessor :from
122
+
123
+ # Specify the subject of the message.
124
+ adv_attr_accessor :subject
125
+
126
+ # The content of the message.
127
+ adv_attr_accessor :body
128
+
129
+ # The ID of the message.
130
+ adv_attr_accessor :id
131
+
132
+ # Schedule for delivery
133
+ adv_attr_accessor :schedule
134
+
135
+ # The Sms message object instance referenced by this model.
136
+ attr_reader :sms
137
+
138
+ class << self
139
+ def method_missing(method_symbol, *parameters) #:nodoc:
140
+ case method_symbol.id2name
141
+ when /^create_([_a-z]\w+)/ then new($1, *parameters).sms
142
+ when /^deliver_([_a-z]\w+)/ then new($1, *parameters).deliver!
143
+ when "new" then nil
144
+ else super
145
+ end
146
+ end
147
+
148
+ # Receives an SMS message, parses it into an SMS object, instantiates
149
+ # a new model, and passes the message object to the model object's
150
+ # #receive method. If you want your model to be able to process
151
+ # incoming messages, you'll need to implement a #receive method
152
+ # that accepts the SMS object as a parameter.
153
+ #
154
+ # class Notifier < ActionSms::Base
155
+ # def receive(sms)
156
+ # ...
157
+ # end
158
+ # end
159
+ def receive(sms)
160
+ sms = connection.parse(sms)
161
+ new.receive(sms)
162
+ end
163
+
164
+ # Deliver the given Sms message object directly. This can be used to
165
+ # deliver a preconstructed message, like:
166
+ #
167
+ # sms = Notifier.create_signup_notification(parameters)
168
+ # Notifier.deliver(sms)
169
+ def deliver(sms)
170
+ new.deliver!(sms)
171
+ end
172
+
173
+ end
174
+
175
+ # Instantiate a new Active SMS model object. If +method_name+ is not
176
+ # +nil+, the model will be initialized according to the named method.
177
+ # If not, the model will remain uninitialized (useful when you need to
178
+ # invoke the "receive" method, for instance).
179
+ def initialize(method_name = nil, *parameters) #:nodoc:
180
+ create!(method_name, *parameters) if method_name
181
+ end
182
+
183
+ # Initialize the model via the given +method_name+. The body will be
184
+ # rendered and a new Sms object created.
185
+ def create!(method_name, *parameters) #:nodoc:
186
+ initialize_defaults(method_name)
187
+ send(method_name, *parameters)
188
+
189
+ # Build the SMS object itself.
190
+ @sms = create_sms
191
+ end
192
+
193
+ # Delivers an Sms message object. By default, it deliver the cached object
194
+ # (from the #create! method). If no cached object exists, and no
195
+ # alternate has been give as the prameter, this will fail.
196
+ #
197
+ # Mod to enable the user to choose between sending via gateway or email.
198
+ #
199
+ def deliver!(sms = @sms) #:nodoc:
200
+ raise "no SMS object available for delivery!" unless sms
201
+ logger.info "Sending SMS: #{sms} via #{sms.delivery}" unless logger.nil?
202
+
203
+ begin
204
+ send("perform_delivery_#{sms.delivery}", sms) if perform_deliveries
205
+ rescue Exception => e
206
+ raise e if raise_delivery_errors
207
+ end
208
+
209
+ logger.info "SMS Sent!" unless logger.nil?
210
+ return sms
211
+ end
212
+
213
+ private
214
+
215
+ # Set up the default values for the various instance variables of this
216
+ # model. Subclasses may override this method to provide different
217
+ # defaults.
218
+ def initialize_defaults(method_name)
219
+ end
220
+
221
+ def create_sms
222
+ raise SmsException unless body && recipients
223
+ sms = Sms.new
224
+ sms.delivery = delivery
225
+ sms.recipients = recipients
226
+ sms.from = from
227
+ sms.body = body
228
+ sms.id = id if id
229
+ sms.carrier = carrier if carrier
230
+ sms.schedule = schedule if schedule
231
+ @sms = sms
232
+ end
233
+
234
+ def perform_delivery_gateway(sms)
235
+ raise ConnectionNotEstablished unless connection
236
+ connection.deliver(sms)
237
+ end
238
+
239
+ def perform_delivery_email(sms)
240
+ #raise ConnectionNotEstablished unless email
241
+ email_deliver(sms)
242
+ end
243
+
244
+ def perform_delivery_test(sms)
245
+ deliveries << sms
246
+ end
247
+
248
+ end
249
+ end
@@ -0,0 +1,20 @@
1
+ require 'yaml'
2
+
3
+ module ActiveSms #:nodoc#
4
+ # #
5
+ # Check out if we are on rails
6
+ # if not, use default yml with only email
7
+ RAILS_CONFIG_ROOT = defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/config" : "#{File.dirname(__FILE__)}/../../generators/sms/templates" unless defined?(RAILS_CONFIG_ROOT)
8
+ # and load what we have!
9
+ conf_yml ||= YAML::load(File.open("#{RAILS_CONFIG_ROOT}/sms.yml"))
10
+
11
+ # #
12
+ # # Get general parameters
13
+ CONFIG = conf_yml['config']
14
+
15
+ # #
16
+ # Get the configured gateway
17
+ GATEWAY = conf_yml['gateway']
18
+
19
+
20
+ end
@@ -0,0 +1,52 @@
1
+ require 'net/https'
2
+
3
+ module ActiveSms #:nodoc:
4
+ module ConnectionAdapters #:nodoc:
5
+ # All the concrete gateway adapters follow the interface laid down in this
6
+ # class. You can use this interface directly by borrowing the gateway
7
+ # connection from the Base with Base.connection.
8
+ class AbstractAdapter
9
+
10
+ @logger = nil
11
+ attr_accessor :logger
12
+
13
+ def initialize(logger = nil) #:nodoc:
14
+ @logger = logger
15
+ end
16
+
17
+ # Return the human readable name of the gateway adapter.
18
+ def adapter_name
19
+ return 'Abstract'
20
+ end
21
+
22
+ def deliver(sms)
23
+ end
24
+
25
+ def parse(sms)
26
+ nil
27
+ end
28
+
29
+ protected
30
+
31
+ # Helper method to send an HTTP request to +url+ with paramaters
32
+ # specified by the +params+ hash.
33
+ def send_http_request(url, params)
34
+ uri = URI.parse(url)
35
+ req = Net::HTTP::Post.new(uri.path)
36
+ req.set_form_data(params)
37
+
38
+ http = Net::HTTP.new(uri.host, uri.port)
39
+ http.use_ssl = true if uri.scheme == 'https'
40
+ resp = http.start do
41
+ http.request(req)
42
+ end
43
+ @logger.info "Response: #{resp.body}" unless @logger.nil?
44
+
45
+ return resp.body
46
+ rescue Exception => e
47
+ raise e
48
+ end
49
+
50
+ end
51
+ end
52
+ end