actionsms 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f711e9e7d3ed8064ea278d3bdb378005edde4af7
4
+ data.tar.gz: 4de6283fc43d1a7422cf4ad0d8beb40150e2c1b1
5
+ SHA512:
6
+ metadata.gz: 7a5cf86cd25de6c9033df1bdd51014461580a7ab250ea7b2a82dd3dc2aebdc181bffb477961fb825b45ed80706e11da0512e29f9a05eb6939a92f9d7c41c23f3
7
+ data.tar.gz: 67d0492a4e5bf4b7ee048d0be74ae7237a8de18bfd978f5138c5e57db6fba015c90bebed749027938e7adccb93b4d51e3a83e9ced1c8c16a337e15d5a70ec134
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "activesupport", ">= 3.2"
4
+
5
+ group :development do
6
+ gem 'rspec', '~>3.2.0'
7
+ gem 'rdoc'
8
+ gem 'bundler'
9
+ gem 'jeweler'
10
+ end
11
+
12
+ group :test do
13
+ gem 'webmock'
14
+ end
@@ -0,0 +1,88 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (4.2.1)
5
+ i18n (~> 0.7)
6
+ json (~> 1.7, >= 1.7.7)
7
+ minitest (~> 5.1)
8
+ thread_safe (~> 0.3, >= 0.3.4)
9
+ tzinfo (~> 1.1)
10
+ addressable (2.3.8)
11
+ builder (3.2.2)
12
+ crack (0.4.2)
13
+ safe_yaml (~> 1.0.0)
14
+ descendants_tracker (0.0.4)
15
+ thread_safe (~> 0.3, >= 0.3.1)
16
+ diff-lcs (1.2.5)
17
+ faraday (0.9.1)
18
+ multipart-post (>= 1.2, < 3)
19
+ git (1.2.9.1)
20
+ github_api (0.12.3)
21
+ addressable (~> 2.3)
22
+ descendants_tracker (~> 0.0.4)
23
+ faraday (~> 0.8, < 0.10)
24
+ hashie (>= 3.3)
25
+ multi_json (>= 1.7.5, < 2.0)
26
+ nokogiri (~> 1.6.3)
27
+ oauth2
28
+ hashie (3.4.1)
29
+ highline (1.7.1)
30
+ i18n (0.7.0)
31
+ jeweler (2.0.1)
32
+ builder
33
+ bundler (>= 1.0)
34
+ git (>= 1.2.5)
35
+ github_api
36
+ highline (>= 1.6.15)
37
+ nokogiri (>= 1.5.10)
38
+ rake
39
+ rdoc
40
+ json (1.8.2)
41
+ jwt (1.4.1)
42
+ mini_portile (0.6.2)
43
+ minitest (5.5.1)
44
+ multi_json (1.11.0)
45
+ multi_xml (0.5.5)
46
+ multipart-post (2.0.0)
47
+ nokogiri (1.6.6.2)
48
+ mini_portile (~> 0.6.0)
49
+ oauth2 (1.0.0)
50
+ faraday (>= 0.8, < 0.10)
51
+ jwt (~> 1.0)
52
+ multi_json (~> 1.3)
53
+ multi_xml (~> 0.5)
54
+ rack (~> 1.2)
55
+ rack (1.6.0)
56
+ rake (10.4.2)
57
+ rdoc (4.2.0)
58
+ rspec (3.2.0)
59
+ rspec-core (~> 3.2.0)
60
+ rspec-expectations (~> 3.2.0)
61
+ rspec-mocks (~> 3.2.0)
62
+ rspec-core (3.2.3)
63
+ rspec-support (~> 3.2.0)
64
+ rspec-expectations (3.2.1)
65
+ diff-lcs (>= 1.2.0, < 2.0)
66
+ rspec-support (~> 3.2.0)
67
+ rspec-mocks (3.2.1)
68
+ diff-lcs (>= 1.2.0, < 2.0)
69
+ rspec-support (~> 3.2.0)
70
+ rspec-support (3.2.2)
71
+ safe_yaml (1.0.4)
72
+ thread_safe (0.3.5)
73
+ tzinfo (1.2.2)
74
+ thread_safe (~> 0.1)
75
+ webmock (1.21.0)
76
+ addressable (>= 2.3.6)
77
+ crack (>= 0.3.2)
78
+
79
+ PLATFORMS
80
+ ruby
81
+
82
+ DEPENDENCIES
83
+ activesupport (>= 3.2)
84
+ bundler
85
+ jeweler
86
+ rdoc
87
+ rspec (~> 3.2.0)
88
+ webmock
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014 Roman Shterenzon
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,50 @@
1
+ # ActionSMS
2
+
3
+ ActionSMS was inspired by ActionMailer and it aims to provide a unified interface for using an SMS provider.
4
+
5
+ ## Synopsis
6
+
7
+ ```ruby
8
+ # config/initializers/sms.rb
9
+ require 'sms/method/twilio'
10
+ Sms.delivery_method = Sms::Method::Twilio.new(account_sid, auth_token, default_from)
11
+
12
+ ```
13
+
14
+ ```ruby
15
+ # app/models/user.rb
16
+ require 'actionsms'
17
+ after_create do
18
+ message = Sms::Message.new(from: '123', to: phone, text: 'Thanks for signing up!')
19
+ message.deliver
20
+ end
21
+ ```
22
+
23
+ Example controller receiving SMS:
24
+ ```ruby
25
+ require 'sms'
26
+
27
+ class SmsController < ActionController::Metal
28
+ def receive
29
+ self.content_type = 'text/plain'
30
+ unless %w[from to text].all? { |key| params.key?(key) }
31
+ self.status = 400
32
+ self.response_body = "Invalid Request\n"
33
+ return
34
+ end
35
+ SmsReceiver.receive(params)
36
+ self.response_body = ''
37
+ end
38
+ end
39
+
40
+ class SmsReceiver < Sms
41
+ def receive(sms)
42
+ Rails.logger.info "SMS: #{sms.inspect}"
43
+ end
44
+ end
45
+ ```
46
+
47
+ ## TODO
48
+
49
+ * Railtie for doing things like config.action\_sms.delivery_method = :file
50
+ * Configurable place for the file
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "actionsms"
18
+ gem.homepage = "http://github.com/romanbsd/actionsms"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Like ActionMailer, but for SMS}
21
+ gem.description = gem.summary
22
+ gem.email = "romanbsd@yahoo.com"
23
+ gem.authors = ["Roman Shterenzon"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :default => :spec
40
+
41
+ require 'rdoc/task'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "actionsms #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,73 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: actionsms 0.0.2 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "actionsms"
9
+ s.version = "0.0.2"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Roman Shterenzon"]
14
+ s.date = "2015-04-12"
15
+ s.description = "Like ActionMailer, but for SMS"
16
+ s.email = "romanbsd@yahoo.com"
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".rspec",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE.txt",
26
+ "README.md",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "actionsms.gemspec",
30
+ "lib/actionsms.rb",
31
+ "lib/sms.rb",
32
+ "lib/sms/log_subscriber.rb",
33
+ "lib/sms/message.rb",
34
+ "lib/sms/method/bezeq.rb",
35
+ "lib/sms/method/file.rb",
36
+ "lib/sms/method/gsm.rb",
37
+ "lib/sms/method/kannel.rb",
38
+ "lib/sms/method/twilio.rb",
39
+ "spec/sms/message_spec.rb",
40
+ "spec/sms/method/bezeq_spec.rb",
41
+ "spec/sms_spec.rb",
42
+ "spec/spec_helper.rb"
43
+ ]
44
+ s.homepage = "http://github.com/romanbsd/actionsms"
45
+ s.licenses = ["MIT"]
46
+ s.rubygems_version = "2.4.6"
47
+ s.summary = "Like ActionMailer, but for SMS"
48
+
49
+ if s.respond_to? :specification_version then
50
+ s.specification_version = 4
51
+
52
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
53
+ s.add_runtime_dependency(%q<activesupport>, [">= 3.2"])
54
+ s.add_development_dependency(%q<rspec>, ["~> 3.2.0"])
55
+ s.add_development_dependency(%q<rdoc>, [">= 0"])
56
+ s.add_development_dependency(%q<bundler>, [">= 0"])
57
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
58
+ else
59
+ s.add_dependency(%q<activesupport>, [">= 3.2"])
60
+ s.add_dependency(%q<rspec>, ["~> 3.2.0"])
61
+ s.add_dependency(%q<rdoc>, [">= 0"])
62
+ s.add_dependency(%q<bundler>, [">= 0"])
63
+ s.add_dependency(%q<jeweler>, [">= 0"])
64
+ end
65
+ else
66
+ s.add_dependency(%q<activesupport>, [">= 3.2"])
67
+ s.add_dependency(%q<rspec>, ["~> 3.2.0"])
68
+ s.add_dependency(%q<rdoc>, [">= 0"])
69
+ s.add_dependency(%q<bundler>, [">= 0"])
70
+ s.add_dependency(%q<jeweler>, [">= 0"])
71
+ end
72
+ end
73
+
@@ -0,0 +1 @@
1
+ require 'sms'
@@ -0,0 +1,83 @@
1
+ class Sms
2
+
3
+ # Subclasses need to implement this method in order to handle incoming SMS.
4
+ # It should return the received message.
5
+ #
6
+ # @abstract
7
+ # @param [Sms::Message] sms
8
+ def receive(sms)
9
+ raise NotImplementedError.new('Need to subclass and implement')
10
+ end
11
+
12
+ @@delivery_notification_observers = []
13
+
14
+ class << self
15
+ def delivery_method=(obj)
16
+ @@delivery_method = obj
17
+ end
18
+
19
+ def delivery_method
20
+ @@delivery_method
21
+ end
22
+
23
+ # The observer needs to respond to a single method #delivered_sms(sms)
24
+ # which receives the sms that is sent.
25
+ def register_observer(observer)
26
+ unless @@delivery_notification_observers.include?(observer)
27
+ @@delivery_notification_observers << observer
28
+ end
29
+ end
30
+
31
+ def unregister_observer(observer)
32
+ @@delivery_notification_observers.delete(observer)
33
+ end
34
+
35
+ # Called when delivery is taking place
36
+ #
37
+ # @param [Sms::Message] sms
38
+ def inform_observers(sms)
39
+ @@delivery_notification_observers.each do |observer|
40
+ observer.delivered_sms(sms)
41
+ end
42
+ end
43
+
44
+ def deliver_sms(sms) #:nodoc:
45
+ ActiveSupport::Notifications.instrument("deliver.sms") do |payload|
46
+ set_payload_for_sms(payload, sms)
47
+ yield # Let Sms do the delivery actions
48
+ end
49
+ end
50
+
51
+ # Receive an SMS
52
+ #
53
+ # @param [Hash] params
54
+ # @option params [String] :from
55
+ # @option params [String] :to
56
+ # @option params [String] :text
57
+ def receive(params)
58
+ ActiveSupport::Notifications.instrument("receive.sms") do |payload|
59
+ sms = Sms::Message.new(params)
60
+ set_payload_for_sms(payload, sms)
61
+ new.receive(sms)
62
+ end
63
+ end
64
+
65
+ def set_payload_for_sms(payload, sms) #:nodoc:
66
+ payload[:from] = sms.from
67
+ payload[:to] = sms.to
68
+ payload[:text] = sms.text
69
+ end
70
+
71
+ end
72
+
73
+ class DeliveryError < StandardError
74
+ attr_reader :code
75
+ def initialize(msg, code = nil)
76
+ @code = code.to_i if code
77
+ super(msg)
78
+ end
79
+ end
80
+ end
81
+
82
+ require 'sms/message'
83
+ require 'sms/log_subscriber'
@@ -0,0 +1,21 @@
1
+ require 'securerandom'
2
+ require 'active_support/log_subscriber'
3
+ require 'active_support/notifications'
4
+
5
+ class Sms
6
+ class LogSubscriber < ActiveSupport::LogSubscriber
7
+ def deliver(event)
8
+ recipient = event.payload[:to]
9
+ info("Sent sms to #{recipient} (%1.fms)" % event.duration)
10
+ debug(event.payload[:text])
11
+ end
12
+
13
+ def receive(event)
14
+ sender = event.payload[:from]
15
+ info("Received sms from #{sender} (%1.fms)" % event.duration)
16
+ debug(event.payload[:text])
17
+ end
18
+ end
19
+ end
20
+
21
+ Sms::LogSubscriber.attach_to :sms
@@ -0,0 +1,63 @@
1
+ class Sms
2
+ class Message
3
+
4
+ # Default: true
5
+ attr_accessor :perform_deliveries
6
+
7
+ # Default: true
8
+ attr_accessor :raise_delivery_errors
9
+
10
+ # Default: Sms
11
+ # Should respond_to :deliver_sms
12
+ attr_accessor :delivery_handler
13
+
14
+ attr_reader :from, :to, :text
15
+ def initialize(args = {})
16
+ @delivery_handler = Sms
17
+ @perform_deliveries = true
18
+ @raise_delivery_errors = true
19
+ @from, @to, @text = args[:from], args[:to], args[:text]
20
+ end
21
+
22
+ # Hash representing the message
23
+ #
24
+ # @return [Hash] message
25
+ def serializable_hash
26
+ {to: to, text: text}.tap {|hash| hash[:from] = from if from}
27
+ end
28
+
29
+ # Perform the delivery of this message
30
+ #
31
+ # @return [Sms::Message] self
32
+ def deliver
33
+ #inform_interceptors
34
+ if delivery_handler
35
+ delivery_handler.deliver_sms(self) { do_delivery }
36
+ else
37
+ do_delivery
38
+ end
39
+ inform_observers
40
+ self
41
+ end
42
+
43
+ private
44
+ def do_delivery
45
+ begin
46
+ if perform_deliveries
47
+ delivery_method.deliver!(self)
48
+ end
49
+ rescue Exception => e
50
+ raise e if raise_delivery_errors
51
+ end
52
+ end
53
+
54
+ def delivery_method
55
+ Sms.delivery_method
56
+ end
57
+
58
+ def inform_observers
59
+ Sms.inform_observers(self)
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,49 @@
1
+ require 'net/https'
2
+
3
+ class Sms
4
+ module Method
5
+ class Bezeq
6
+ URL = URI.parse('https://vast.bezeq.co.il/imsc/interfaces/largeaccount/la3.sms')
7
+
8
+ # New instance of Bezeq delivery method
9
+ #
10
+ # @param [Hash] config
11
+ # @option config [String] :account
12
+ # @option config [String] :user
13
+ # @option config [String] :pass
14
+ # @option config [String] :from
15
+ # @option config [String] :port
16
+ def initialize(config)
17
+ @config = config.dup
18
+ end
19
+
20
+ # Send an MT message
21
+ # https://vast.bezeq.co.il/imsc/interfaces/largeaccount/la3.sms?account=myaccount&
22
+ # user=smsuser&pass=mypass&from=1234&to=972541234567&port=0&text=Hello+world
23
+ #
24
+ # @param [Sms::Message] sms
25
+ def deliver!(sms)
26
+ req = Net::HTTP::Post.new(URL.path)
27
+ hash = sms.serializable_hash
28
+ if hash[:to].is_a?(Array)
29
+ to = hash.delete(:to)
30
+ hash['to[]'] = to
31
+ end
32
+
33
+ req.form_data = @config.merge(hash)
34
+
35
+ res = Net::HTTP.start(URL.host, URL.port) do |http|
36
+ http.request(req)
37
+ end
38
+
39
+ case res
40
+ when Net::HTTPSuccess
41
+ true
42
+ else
43
+ raise DeliveryError.new(res.body, res.code)
44
+ end
45
+
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,16 @@
1
+ require 'csv'
2
+ class Sms
3
+ module Method
4
+ class File
5
+ def initialize
6
+ @file = ::File.open('/tmp/sms.csv', 'w')
7
+ @file.sync = true
8
+ @file.write("from,to,text\n")
9
+ end
10
+
11
+ def deliver!(sms)
12
+ @file.write([sms.from, sms.to, sms.text].to_csv)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,50 @@
1
+ require 'serialport'
2
+ require 'time'
3
+
4
+ class Sms
5
+ module Method
6
+ class GSM
7
+
8
+ def initialize(options = {})
9
+ raise ArgumentError.new('No :smsc was provided') unless options[:smsc]
10
+ @port = SerialPort.new(options[:port] || 3, options[:baud] || 38400, options[:bits] || 8, options[:stop] || 1, SerialPort::NONE)
11
+ @debug = options[:debug]
12
+ cmd("AT")
13
+ # Set to text mode
14
+ cmd("AT+CMGF=1")
15
+ # Set SMSC number
16
+ cmd(%Q{AT+CSCA="#{options[:smsc]}"})
17
+ end
18
+
19
+ def close
20
+ @port.close
21
+ end
22
+
23
+ private
24
+ def cmd(cmd)
25
+ @port.write(cmd + "\r")
26
+ wait
27
+ end
28
+
29
+ def wait
30
+ buffer = ''
31
+ while IO.select([@port], [], [], 0.25)
32
+ chr = @port.getc.chr
33
+ print chr if @debug
34
+ buffer += chr
35
+ end
36
+ buffer
37
+ end
38
+
39
+ def deliver!(sms)
40
+ cmd(%Q{AT+CMGS="#{sms.to}"})
41
+ cmd("#{sms.text[0..140]}#{26.chr}\r\r")
42
+ sleep 1
43
+ wait
44
+ cmd("AT")
45
+ end
46
+ end
47
+
48
+ Gsm = GSM
49
+ end
50
+ end
@@ -0,0 +1,12 @@
1
+ class Sms
2
+ module Method
3
+ class Kannel
4
+ def deliver!(sms)
5
+ args = {}
6
+ args[:from] = sms.from if sms.from
7
+ sms = ::Kannel::Sms.new(sms.to, sms.text, args)
8
+ sms.send!
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'twilio-ruby'
3
+
4
+ class Sms
5
+ module Method
6
+ # POST /2010-04-01/Accounts/[AccountSid]/SMS/Messages.json with
7
+ # From, To, Body
8
+ class Twilio
9
+ def initialize(account_sid, auth_token, default_from = nil)
10
+ @account_sid = account_sid
11
+ @auth_token = auth_token
12
+ @from = default_from
13
+ end
14
+
15
+ # @param [Sms::Message] sms
16
+ def deliver!(sms)
17
+ from = sms.from || @from
18
+ client.account.messages.create(from: from, to: sms.to, body: sms.text)
19
+ end
20
+
21
+ private
22
+ # Set up a client to talk to the Twilio REST API
23
+ def client
24
+ @client ||= ::Twilio::REST::Client.new(@account_sid, @auth_token)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,45 @@
1
+ require 'sms'
2
+
3
+ describe Sms::Message do
4
+ it 'serializes with from' do
5
+ h = {from: '123', to: '234', text: 'test'}
6
+ msg = Sms::Message.new(h)
7
+ expect(msg.serializable_hash).to eq(h)
8
+ end
9
+
10
+ it 'serializes without from' do
11
+ h = {to: '234', text: 'test'}
12
+ msg = Sms::Message.new(h)
13
+ expect(msg.serializable_hash).to eq(h)
14
+ end
15
+
16
+ context 'Deliveries' do
17
+ let(:message) { Sms::Message.new(from: '123', to: '234', text: 'test') }
18
+
19
+ before do
20
+ delivery = double('delivery')
21
+ Sms.delivery_method = delivery
22
+ expect(delivery).to receive(:deliver!).with(message)
23
+ end
24
+
25
+ it 'delivers' do
26
+ message.deliver
27
+ end
28
+
29
+ it 'uses delivery handler' do
30
+ handler = double('handler')
31
+ message.delivery_handler = handler
32
+ expect(handler).to receive(:deliver_sms).with(message).and_yield
33
+ message.deliver
34
+ end
35
+
36
+ it 'notifies observers' do
37
+ observer = double('observer')
38
+ expect(observer).to receive(:delivered_sms).with(message)
39
+ Sms.register_observer(observer)
40
+ message.deliver
41
+ Sms.unregister_observer(observer)
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,53 @@
1
+ require 'sms'
2
+ require 'sms/method/bezeq'
3
+ require 'sms/method/file'
4
+ require 'webmock/rspec'
5
+
6
+ describe Sms::Method::Bezeq do
7
+ let(:url) { "http://vast.bezeq.co.il:443/imsc/interfaces/largeaccount/la3.sms" }
8
+ let(:delivery_method) { Sms::Method::Bezeq.new(account: 'a', user: 'u', pass: 'p', from: '222') }
9
+
10
+ let(:message) { Sms::Message.new(:to => '123', :text => 'test') }
11
+ let(:body) do
12
+ {"account"=>"a", "user"=>"u", "pass"=>"p", "from"=>"222", "to"=>"123", "text"=>"test" }
13
+ end
14
+
15
+ before do
16
+ Sms.delivery_method = delivery_method
17
+ end
18
+
19
+ context 'Multiple recipients' do
20
+ let(:message) { Sms::Message.new(:to => %w[num1 num2 num3], :text => 'test') }
21
+ let(:body) do
22
+ {"account"=>"a", "user"=>"u", "pass"=>"p", "from"=>"222", "to"=>%w[num1 num2 num3], "text"=>"test"}
23
+ end
24
+
25
+ it 'handles multiple recipients' do
26
+ stub_request(:post, url).
27
+ with(body: body, headers: {'Accept'=>'*/*', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Ruby'}).
28
+ to_return(status: 200, body: "OK", headers: {})
29
+ message.deliver
30
+ end
31
+
32
+ end
33
+
34
+ it "issues POST" do
35
+ stub_request(:post, url).
36
+ with(body: body, headers: {'Accept'=>'*/*', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Ruby'}).
37
+ to_return(status: 200, body: "OK", headers: {})
38
+ message.deliver
39
+ end
40
+
41
+ it 'handles errors' do
42
+ stub_request(:post, url).with(body: body).
43
+ to_return(status: 400, body: 'Malformed Request', headers: {})
44
+
45
+ expect {message.deliver}.to raise_error(Sms::DeliveryError)
46
+ begin
47
+ message.deliver
48
+ rescue Sms::DeliveryError => e
49
+ expect(e.code).to eq(400)
50
+ expect(e.message).to eq('Malformed Request')
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,52 @@
1
+ require 'sms'
2
+
3
+ describe Sms do
4
+ let(:hash) do
5
+ {from: '123', to: '234', text: 'test'}
6
+ end
7
+
8
+ let(:message) { Sms::Message.new(hash) }
9
+
10
+ context 'Delivering SMS' do
11
+
12
+ it 'notifies the listeners' do
13
+ listener = double('listener')
14
+ expect(listener).to receive(:call) do |*params|
15
+ expect(params.first).to eq('deliver.sms')
16
+ expect(params.last).to eq(hash)
17
+ end
18
+ subscriber = ActiveSupport::Notifications.subscribe('deliver.sms', listener)
19
+ Sms.deliver_sms(message) {}
20
+ ActiveSupport::Notifications.unsubscribe(subscriber)
21
+ end
22
+
23
+ end
24
+
25
+ context 'Receiving SMS' do
26
+
27
+ class Receiver < Sms
28
+ def receive(sms)
29
+ end
30
+ end
31
+
32
+ it 'receives messages' do
33
+ receiver = double('receiver').tap do |m|
34
+ expect(m).to receive(:receive) {|msg| expect(msg.serializable_hash).to eq(hash)}
35
+ end
36
+ expect(Receiver).to receive(:new).and_return(receiver)
37
+ Receiver.receive(hash)
38
+ end
39
+
40
+ it 'notifies the listeners' do
41
+ listener = double('listener')
42
+ expect(listener).to receive(:call) do |*params|
43
+ expect(params.first).to eq('receive.sms')
44
+ expect(params.last).to eq(hash)
45
+ end
46
+ subscriber = ActiveSupport::Notifications.subscribe('receive.sms', listener)
47
+ Receiver.receive(hash)
48
+ ActiveSupport::Notifications.unsubscribe(subscriber)
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,13 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'webmock/rspec'
5
+ require 'actionsms'
6
+
7
+ # Requires supporting files with custom matchers and macros, etc,
8
+ # in ./support/ and its subdirectories.
9
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
10
+
11
+ RSpec.configure do |config|
12
+
13
+ end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: actionsms
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Roman Shterenzon
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 3.2.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 3.2.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rdoc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: jeweler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Like ActionMailer, but for SMS
84
+ email: romanbsd@yahoo.com
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files:
88
+ - LICENSE.txt
89
+ - README.md
90
+ files:
91
+ - ".rspec"
92
+ - Gemfile
93
+ - Gemfile.lock
94
+ - LICENSE.txt
95
+ - README.md
96
+ - Rakefile
97
+ - VERSION
98
+ - actionsms.gemspec
99
+ - lib/actionsms.rb
100
+ - lib/sms.rb
101
+ - lib/sms/log_subscriber.rb
102
+ - lib/sms/message.rb
103
+ - lib/sms/method/bezeq.rb
104
+ - lib/sms/method/file.rb
105
+ - lib/sms/method/gsm.rb
106
+ - lib/sms/method/kannel.rb
107
+ - lib/sms/method/twilio.rb
108
+ - spec/sms/message_spec.rb
109
+ - spec/sms/method/bezeq_spec.rb
110
+ - spec/sms_spec.rb
111
+ - spec/spec_helper.rb
112
+ homepage: http://github.com/romanbsd/actionsms
113
+ licenses:
114
+ - MIT
115
+ metadata: {}
116
+ post_install_message:
117
+ rdoc_options: []
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ requirements: []
131
+ rubyforge_project:
132
+ rubygems_version: 2.4.6
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: Like ActionMailer, but for SMS
136
+ test_files: []