sisal 0.0.1

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.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+
3
+ group :test do
4
+ gem "rspec", "~> 2.8"
5
+ end
@@ -0,0 +1,98 @@
1
+ # Sisal - SMS Abstraction Layer
2
+
3
+ Sisal is an abstraction layer to work with SMS. Think something like
4
+ Active Merchant, but instead of payment gateways and credit cards, it
5
+ deals with SMS providers and messages.
6
+
7
+ ## Architecture
8
+
9
+ At this moment Sisal's core is formed by four parts:
10
+
11
+ * Message
12
+ * Response
13
+ * Provider
14
+ * Messenger
15
+
16
+ `Message` and `Response` are the implementations for the message and you
17
+ want send and the response from the provider, respectively. `Provider` is
18
+ interface for all the providers implementations. And `Messenger` is a proxy
19
+ for all your configured providers. Check the examples below.
20
+
21
+ Sisal can send messages via the following providers:
22
+
23
+ * Tropo
24
+ * Twilio
25
+ * Clickatell
26
+
27
+ #### **Please note that Sisal ONLY supports US-ASCII (GSM 7-bit encoding) messages!**
28
+
29
+ ## TODO
30
+
31
+ * Separate providers implementations, e.g. sisal-tropo, sisal-twilio
32
+ * Implement encodings LATIN1 and UCS2
33
+ * Support for binary messages: EMS, Nokia's Smart Messaging and MMS
34
+ * Support for binary Concatenated SMS
35
+ * etc.
36
+
37
+ ## Examples
38
+
39
+ ###### Send SMS using provider
40
+
41
+ ```ruby
42
+ message = Sisal::Message.new('552500', 'Hello MU!')
43
+ provider = Sisal::Providers.tropo(token: '123')
44
+ provider.send(message)
45
+ ```
46
+
47
+ ###### Send SMS using Messenger
48
+
49
+ Assuming you have configured your providers:
50
+
51
+ ```ruby
52
+ config = Sisal.configuration
53
+ config.default_provider = :tropo
54
+ config.provider(:tropo, Sisal::Providers.tropo(token: '123'))
55
+ config.provider(:twilio, Sisal::Providers.twilio(account_id: '123', token: '123', from: '552500'))
56
+ ```
57
+
58
+ You can send messages just as simple as:
59
+
60
+ ```ruby
61
+ messenger = Sisal::Messenger.new
62
+ messenger.send(message)
63
+ ```
64
+
65
+ You can also change your default provider on the fly:
66
+
67
+ ```ruby
68
+ messenger.send(message, provider: 'twilio')
69
+ ```
70
+
71
+ If you need, you can change your providers settings:
72
+
73
+ ```ruby
74
+ config.provider(:tropo) do |p|
75
+ p.token = '312'
76
+ end
77
+ ```
78
+
79
+ ## License
80
+
81
+ Copyright (c) 2012 Vinicius Horewicz
82
+
83
+ Permission is hereby granted, free of charge, to any person obtaining a copy
84
+ of this software and associated documentation files (the "Software"), to deal
85
+ in the Software without restriction, including without limitation the rights
86
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
87
+ copies of the Software, and to permit persons to whom the Software is furnished
88
+ to do so, subject to the following conditions:
89
+
90
+ The above copyright notice and this permission notice shall be included in all
91
+ copies or substantial portions of the Software.
92
+
93
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
94
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
95
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
96
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
97
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
98
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+ desc "Default: run specs."
6
+ task :default => :spec
7
+
8
+ desc "Run specs"
9
+ RSpec::Core::RakeTask.new
@@ -0,0 +1,15 @@
1
+ require_relative "sisal/message"
2
+ require_relative "sisal/response"
3
+ require_relative "sisal/provider"
4
+ require_relative "sisal/messenger"
5
+ require_relative "sisal/configuration"
6
+
7
+ module Sisal
8
+ extend self
9
+
10
+ attr_writer :configuration
11
+
12
+ def configuration
13
+ @configuration ||= Configuration.new
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ module Sisal
2
+ class Configuration
3
+ attr_accessor :providers
4
+ attr_writer :default_provider
5
+
6
+ def initialize
7
+ @providers = {}
8
+ end
9
+
10
+ def provider(name, provider_object = nil)
11
+ name = name.to_s
12
+ @providers[name] = provider_object if provider_object
13
+ yield(@providers[name]) if block_given?
14
+ @providers[name]
15
+ end
16
+
17
+ def default_provider
18
+ @providers[@default_provider.to_s]
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ module Sisal
2
+ class Message
3
+ InvalidPhoneNumber = Class.new(StandardError)
4
+
5
+ PHONE_REGEX = /^\d+$/
6
+ PHONE_LENGTH = [4, 15]
7
+
8
+ attr_accessor :to, :text
9
+
10
+ def initialize(to, text)
11
+ @to, @text = to, text
12
+ end
13
+
14
+ def valid?
15
+ validate_number
16
+ end
17
+
18
+ private
19
+
20
+ def validate_number
21
+ to.length.between?(*PHONE_LENGTH) && to.match(PHONE_REGEX) or
22
+ raise InvalidPhoneNumber.new(to)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,12 @@
1
+ module Sisal
2
+ class Messenger
3
+ UnknownProvider = Class.new(StandardError)
4
+
5
+ def send(message, options = {})
6
+ provider_name = options.delete(:provider).to_s
7
+ provider = Sisal.configuration.providers[provider_name] || Sisal.configuration.default_provider
8
+ raise UnknownProvider unless provider
9
+ provider.send(message, options)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ module Sisal
2
+ class Provider
3
+ def send(message, options = {})
4
+ raise "Provider#send must be implemented in children classes"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ module Sisal
2
+ class Response
3
+ # Since we can't abstract all providers responses,
4
+ # let's use params as a general purpose hash
5
+ attr_accessor :success, :code, :message, :params
6
+
7
+ def initialize(success, code, message, params = {})
8
+ @success, @code, @message, @params = success, code, message, params
9
+ end
10
+
11
+ # The value of @success must be set by the caller object,
12
+ # usually the provider.
13
+ def success?
14
+ @success == true
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module Sisal
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/sisal/version", __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Vinicius Horewicz"]
6
+ gem.email = ["vinicius@horewi.cz"]
7
+ gem.description = %q{Sisal is an abstraction layer to work with SMS. Think something like Active Merchant, but instead of payment gateways and credit cards, it deals with SMS providers and messages.}
8
+ gem.summary = %q{SMS abstraction layer in Ruby}
9
+ gem.homepage = "https://github.com/wicz/sisal"
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {spec,features}/*`.split("\n")
14
+ gem.name = "sisal"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Sisal::VERSION
17
+ end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ describe Sisal::Configuration do
4
+ let(:dummy) { DummyProvider.new }
5
+
6
+ before(:each) do
7
+ Sisal.configuration.provider(:dummy, dummy)
8
+ end
9
+
10
+ it "has a default provider" do
11
+ Sisal.configuration.default_provider = :dummy
12
+ Sisal.configuration.default_provider.should be(dummy)
13
+ end
14
+
15
+ it "has providers" do
16
+ Sisal.configuration.providers.should_not be_empty
17
+ end
18
+
19
+ describe "#provider" do
20
+ it "configures a provider" do
21
+ Sisal.configuration.provider(:dummy) { |p| p.token = "456"}
22
+ Sisal.configuration.providers["dummy"].should be
23
+ Sisal.configuration.providers["dummy"].token.should eq("456")
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+
3
+ describe Sisal::Message do
4
+ let(:message) { Sisal::Message.new("5525800", "") }
5
+
6
+ describe "#valid?" do
7
+ context "raises an error when" do
8
+ it "number has less than 4 digits" do
9
+ message.to = "123"
10
+ expect { message.valid? }.to raise_error(Sisal::Message::InvalidPhoneNumber)
11
+ end
12
+
13
+ it "number has more than 15 digits" do
14
+ message.to = "1" * 20
15
+ expect { message.valid? }.to raise_error(Sisal::Message::InvalidPhoneNumber)
16
+ end
17
+
18
+ it "number has chars other than digits" do
19
+ message.to = "+5525800"
20
+ expect { message.valid? }.to raise_error(Sisal::Message::InvalidPhoneNumber)
21
+ end
22
+ end
23
+
24
+ it "accepts short codes" do
25
+ message.valid?.should be_true
26
+ end
27
+
28
+ it "accepts complete E.164 number" do
29
+ message.to = "230234321324213"
30
+ message.valid?
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,31 @@
1
+ require "spec_helper"
2
+
3
+ describe Sisal::Messenger do
4
+ let(:messenger) { Sisal::Messenger.new }
5
+ let(:message) { Sisal::Message.new("1234", "OHAI!") }
6
+ let(:dummy) { DummyProvider.new }
7
+ let(:dumber) { DummyProvider.new }
8
+
9
+ before(:each) do
10
+ Sisal.configuration.provider(:dummy, dummy)
11
+ Sisal.configuration.provider(:dumber, dumber)
12
+ Sisal.configuration.default_provider = :dummy
13
+ end
14
+
15
+ describe "#send" do
16
+ it "uses the default provider" do
17
+ dummy.should_receive(:send).with(message, {})
18
+ messenger.send(message)
19
+ end
20
+
21
+ it "can have provider overriden in runtime" do
22
+ dumber.should_receive(:send).with(message, {})
23
+ messenger.send(message, provider: "dumber")
24
+ end
25
+
26
+ it "can have extra parameters" do
27
+ dummy.should_receive(:send).with(message, msg_id: 123)
28
+ messenger.send(message, msg_id: 123)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,11 @@
1
+ require "spec_helper"
2
+
3
+ describe Sisal::Provider do
4
+ let(:provider) { Sisal::Provider.new }
5
+
6
+ describe "#send" do
7
+ it "must be implemented by children classes" do
8
+ expect { provider.send(nil, nil) }.to raise_error(RuntimeError)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+
3
+ describe Sisal::Response do
4
+ let(:response) { Sisal::Response.new(true, "200", "Success") }
5
+
6
+ describe "#new" do
7
+ it "initializes with success, code and message" do
8
+ response.success.should be_true
9
+ response.code.should eq("200")
10
+ response.message.should eq("Success")
11
+ end
12
+
13
+ it "can initialize with extra parameters" do
14
+ response = Sisal::Response.new(false, "401", "Error", description: "Access denied")
15
+ response.params.has_key?(:description).should be_true
16
+ response.params[:description].should eq("Access denied")
17
+ end
18
+ end
19
+
20
+ describe "#success?" do
21
+ it "checks if success is true" do
22
+ response.success = true
23
+ response.success?.should be_true
24
+ response.success = false
25
+ response.success?.should be_false
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,7 @@
1
+ require "spec_helper"
2
+
3
+ describe Sisal do
4
+ it "has configuration" do
5
+ Sisal.configuration.should be_a(Sisal::Configuration)
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ $:.unshift File.expand_path('..', __FILE__)
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+
4
+ require "rspec"
5
+
6
+ require_relative "../lib/sisal"
7
+
8
+ DummyProvider = Struct.new(:token)
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sisal
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Vinicius Horewicz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-10 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Sisal is an abstraction layer to work with SMS. Think something like
15
+ Active Merchant, but instead of payment gateways and credit cards, it deals with
16
+ SMS providers and messages.
17
+ email:
18
+ - vinicius@horewi.cz
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - .gitignore
24
+ - Gemfile
25
+ - README.md
26
+ - Rakefile
27
+ - lib/sisal.rb
28
+ - lib/sisal/configuration.rb
29
+ - lib/sisal/message.rb
30
+ - lib/sisal/messenger.rb
31
+ - lib/sisal/provider.rb
32
+ - lib/sisal/response.rb
33
+ - lib/sisal/version.rb
34
+ - sisal.gemspec
35
+ - spec/sisal/configuration_spec.rb
36
+ - spec/sisal/message_spec.rb
37
+ - spec/sisal/messenger_spec.rb
38
+ - spec/sisal/provider_spec.rb
39
+ - spec/sisal/response_spec.rb
40
+ - spec/sisal_spec.rb
41
+ - spec/spec_helper.rb
42
+ homepage: https://github.com/wicz/sisal
43
+ licenses: []
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubyforge_project:
62
+ rubygems_version: 1.8.11
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: SMS abstraction layer in Ruby
66
+ test_files:
67
+ - spec/sisal/configuration_spec.rb
68
+ - spec/sisal/message_spec.rb
69
+ - spec/sisal/messenger_spec.rb
70
+ - spec/sisal/provider_spec.rb
71
+ - spec/sisal/response_spec.rb
72
+ - spec/sisal_spec.rb
73
+ - spec/spec_helper.rb