action_sms_gateways 0.0.6 → 0.0.7
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.
- data/README.markdown +143 -8
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/action_sms_gateways.gemspec +8 -2
- data/lib/action_sms_gateways/connection_adapters/sms_global.rb +19 -7
- data/lib/action_sms_gateways/connection_adapters/test_helpers/sms_global.rb +40 -0
- data/lib/action_sms_gateways/connection_adapters/test_helpers/tropo.rb +68 -0
- data/lib/action_sms_gateways/connection_adapters/tropo.rb +82 -0
- metadata +22 -5
data/README.markdown
CHANGED
@@ -1,22 +1,157 @@
|
|
1
1
|
# action_sms_gateways
|
2
|
+
|
2
3
|
A collection of SMS Gateway Adapters for [action_sms](http://github.com/dwilkie/action_sms)
|
3
4
|
|
4
5
|
## Current SMS Adapters
|
6
|
+
|
5
7
|
* [SMSGlobal](http://www.smsglobal.com)
|
8
|
+
* [Tropo](http://www.tropo.com)
|
9
|
+
|
10
|
+
## Configuration
|
11
|
+
|
12
|
+
* [SMSGlobal](http://github.com/dwilkie/action_sms_gateways/wiki/SMSGlobal)
|
13
|
+
* [Tropo](http://github.com/dwilkie/action_sms_gateways/wiki/Tropo)
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
### Send an SMS and check if it was successful
|
18
|
+
|
19
|
+
class SMS
|
20
|
+
def recipient
|
21
|
+
"617198378843"
|
22
|
+
end
|
23
|
+
|
24
|
+
def body
|
25
|
+
"Hello world"
|
26
|
+
end
|
27
|
+
|
28
|
+
def from
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
sms_gateway = ActionSms::Base.connection
|
33
|
+
response = sms_gateway.deliver(SMS.new)
|
34
|
+
success = sms_gateway.delivery_request_successful?(response)
|
35
|
+
|
36
|
+
### Receive an SMS
|
37
|
+
|
38
|
+
# Assume 'params' has the data posted back to your server
|
39
|
+
|
40
|
+
sms_gateway = ActionSms::Base.connection
|
41
|
+
|
42
|
+
# get sender
|
43
|
+
sender = sms_gateway.sender(params)
|
44
|
+
|
45
|
+
# get message text
|
46
|
+
message_text = sms_gateway.message_text(params)
|
47
|
+
|
48
|
+
### Delivery receipts
|
49
|
+
|
50
|
+
# Assume 'receipt' has the data posted back to your server as the delivery receipt
|
51
|
+
|
52
|
+
sms_gateway = ActionSms::Base.connection
|
53
|
+
|
54
|
+
# get status
|
55
|
+
status = sms_gateway.status(receipt)
|
56
|
+
|
57
|
+
# get message id
|
58
|
+
message_id = sms_gateway.message_id(receipt)
|
59
|
+
|
60
|
+
### Authentication
|
61
|
+
|
62
|
+
ActionSms::Base.establish_connection(
|
63
|
+
:authentication_key => "my secret",
|
64
|
+
:use_ssl => true
|
65
|
+
)
|
66
|
+
|
67
|
+
If you set up an: `authentication_key` in the configuration, your key will be passed back to your listener url. Using an authentication key in conjunction with a secure connection `use_ssl => true` helps protect you against someone faking incoming messages to your server. You can authenticate an incoming message as follows:
|
6
68
|
|
7
|
-
|
8
|
-
Take a look at the source under `lib/action_sms_gateways/connection_adapters/sms_global.rb` and use it as a template for your own adapter. Then why not share it for all to use...
|
69
|
+
# Assume 'params' has the data posted back to your server
|
9
70
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
71
|
+
sms_gateway = ActionSms::Base.connection
|
72
|
+
|
73
|
+
# Removes the authentication key from 'params' and returns true or false
|
74
|
+
sms_gateway.authenticate(params)
|
75
|
+
|
76
|
+
### Service url
|
77
|
+
|
78
|
+
# gets the gateway's api url
|
79
|
+
# ActionSms::Base.connection.service_url
|
80
|
+
|
81
|
+
## Testing
|
82
|
+
|
83
|
+
When you set: `:environment => "test"` in your configuration, you get some additional test helpers.
|
84
|
+
|
85
|
+
ActionSms::Base.establish_connection(
|
86
|
+
:environment => "test"
|
87
|
+
)
|
88
|
+
|
89
|
+
sms_gateway = ActionSms::Base.connection
|
90
|
+
|
91
|
+
# get sample incoming SMS params
|
92
|
+
sms_gateway.sample_incoming_sms
|
93
|
+
|
94
|
+
# get customized sample incoming SMS
|
95
|
+
sms_gateway.sample_incoming_sms(
|
96
|
+
:message => "hello",
|
97
|
+
:to => "6128392323",
|
98
|
+
:from => "61289339432",
|
99
|
+
:date => Time.now,
|
100
|
+
:authentic => false # see configuration
|
101
|
+
)
|
102
|
+
|
103
|
+
# get sample delivery response
|
104
|
+
sms_gateway.sample_delivery_response
|
105
|
+
|
106
|
+
# get sample delivery response (failed)
|
107
|
+
sms_gateway.sample_delivery_response(:failed => true)
|
108
|
+
|
109
|
+
# get sample message id
|
110
|
+
sms_gateway.sample_message_id
|
111
|
+
|
112
|
+
# get sample delivery receipt
|
113
|
+
sms_gateway.sample_delivery_receipt
|
114
|
+
|
115
|
+
# get customized sample delivery receipt
|
116
|
+
sms_gateway.sample_delivery_receipt(
|
117
|
+
:message_id => "12345",
|
118
|
+
:status => "delivered",
|
119
|
+
:error => "some error",
|
120
|
+
:date => Time.now
|
121
|
+
)
|
122
|
+
|
123
|
+
## Creating your own adapter
|
124
|
+
|
125
|
+
To create your own adapter all you need to do is open up the ActionSms::Base class
|
126
|
+
and add a class method named: `my_adapter_connection` which takes a single hash argument of configuration details and returns an instance of your adapter class. For example, let's create an adapter for clickatell:
|
127
|
+
|
128
|
+
# clickatell.rb
|
129
|
+
require 'action_sms/connection_adapters/abstract_adapter'
|
130
|
+
|
131
|
+
module ActionSms
|
132
|
+
class Base
|
133
|
+
def self.clickatell_connection(config)
|
134
|
+
ConnectionAdapters::ClickatellAdapter.new(config)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
module ConnectionAdapters
|
140
|
+
class ClickatellAdapter < AbstractAdapter
|
141
|
+
# define your adapter here ...
|
142
|
+
def initialize(config)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
Take a look at the [source](http://github.com/dwilkie/action_sms_gateways/tree/master/lib/action_sms_gateways/connection_adapters/) for more details
|
16
148
|
|
17
149
|
## Installation
|
150
|
+
|
18
151
|
gem install action_sms_gateways
|
152
|
+
|
19
153
|
### Rails
|
154
|
+
|
20
155
|
Place the following in your Gemfile:
|
21
156
|
|
22
157
|
gem action_sms_gateways
|
data/Rakefile
CHANGED
@@ -22,6 +22,7 @@ begin
|
|
22
22
|
gemspec.email = "dwilkie@gmail.com"
|
23
23
|
gemspec.homepage = "http://github.com/dwilkie/action_sms_gateways"
|
24
24
|
gemspec.authors = ["David Wilkie"]
|
25
|
+
gemspec.add_runtime_dependency "tropo_message", ">=0.0.4"
|
25
26
|
end
|
26
27
|
rescue LoadError
|
27
28
|
puts "Jeweler not available. Install it with: gem install jeweler"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.7
|
data/action_sms_gateways.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{action_sms_gateways}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["David Wilkie"]
|
12
|
-
s.date = %q{2010-10-
|
12
|
+
s.date = %q{2010-10-14}
|
13
13
|
s.email = %q{dwilkie@gmail.com}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"README.markdown"
|
@@ -24,6 +24,9 @@ Gem::Specification.new do |s|
|
|
24
24
|
"lib/action_sms_gateways.rb",
|
25
25
|
"lib/action_sms_gateways/connection_adapters.rb",
|
26
26
|
"lib/action_sms_gateways/connection_adapters/sms_global.rb",
|
27
|
+
"lib/action_sms_gateways/connection_adapters/test_helpers/sms_global.rb",
|
28
|
+
"lib/action_sms_gateways/connection_adapters/test_helpers/tropo.rb",
|
29
|
+
"lib/action_sms_gateways/connection_adapters/tropo.rb",
|
27
30
|
"todo"
|
28
31
|
]
|
29
32
|
s.homepage = %q{http://github.com/dwilkie/action_sms_gateways}
|
@@ -37,9 +40,12 @@ Gem::Specification.new do |s|
|
|
37
40
|
s.specification_version = 3
|
38
41
|
|
39
42
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
43
|
+
s.add_runtime_dependency(%q<tropo_message>, [">= 0.0.4"])
|
40
44
|
else
|
45
|
+
s.add_dependency(%q<tropo_message>, [">= 0.0.4"])
|
41
46
|
end
|
42
47
|
else
|
48
|
+
s.add_dependency(%q<tropo_message>, [">= 0.0.4"])
|
43
49
|
end
|
44
50
|
end
|
45
51
|
|
@@ -1,10 +1,18 @@
|
|
1
1
|
require 'action_sms/connection_adapters/abstract_adapter'
|
2
|
-
require 'uri'
|
3
2
|
|
4
3
|
module ActionSms
|
5
4
|
class Base
|
6
5
|
def self.sms_global_connection(config) #:nodoc:
|
7
|
-
|
6
|
+
if config[:environment].to_s == "test"
|
7
|
+
test_helper = File.expand_path(File.dirname(__FILE__) + '/test_helpers/sms_global')
|
8
|
+
if File.exists?("#{test_helper}.rb")
|
9
|
+
require test_helper
|
10
|
+
ConnectionAdapters::SMSGlobalAdapter.class_eval do
|
11
|
+
include TestHelpers::SMSGlobal
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
ConnectionAdapters::SMSGlobalAdapter.new(config)
|
8
16
|
end
|
9
17
|
end
|
10
18
|
|
@@ -13,14 +21,18 @@ module ActionSms
|
|
13
21
|
# class. You can use this interface directly by borrowing the gateway
|
14
22
|
# connection from the Base with Base.connection.
|
15
23
|
class SMSGlobalAdapter < AbstractAdapter
|
24
|
+
require 'uri'
|
25
|
+
|
16
26
|
SERVICE_HOST = "http://smsglobal.com.au"
|
17
27
|
SERVICE_PATH = "http-api.php"
|
18
28
|
|
19
|
-
|
20
|
-
|
29
|
+
attr_reader :service_url
|
30
|
+
|
31
|
+
def initialize(config = {}) #:nodoc:
|
21
32
|
@config = config.dup
|
22
|
-
|
23
|
-
|
33
|
+
service_uri = URI.join(SERVICE_HOST, SERVICE_PATH)
|
34
|
+
service_uri.scheme = config[:use_ssl] ? "https" : "http"
|
35
|
+
@service_url = service_uri.to_s
|
24
36
|
end
|
25
37
|
|
26
38
|
def message_id(data)
|
@@ -72,7 +84,7 @@ module ActionSms
|
|
72
84
|
params.merge!(
|
73
85
|
:userfield => userfield
|
74
86
|
) if userfield
|
75
|
-
send_http_request(@service_url
|
87
|
+
send_http_request(@service_url, params)
|
76
88
|
end
|
77
89
|
end
|
78
90
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module TestHelpers
|
2
|
+
module SMSGlobal
|
3
|
+
def sample_incoming_sms(options = {})
|
4
|
+
options[:message] ||= "Endia kasdf ofeao"
|
5
|
+
options[:to] ||= "61447100308"
|
6
|
+
options[:from] ||= "61447100399"
|
7
|
+
options[:date] ||= "2010-05-13 23:59:11"
|
8
|
+
params = {
|
9
|
+
"to" => options[:to],
|
10
|
+
"from" => options[:from],
|
11
|
+
"msg"=> options[:message],
|
12
|
+
"date" => options[:date]
|
13
|
+
}
|
14
|
+
params.merge!("userfield" => @config[:authentication_key]) unless options[:authentic] == false
|
15
|
+
params
|
16
|
+
end
|
17
|
+
|
18
|
+
def sample_delivery_response(options = {})
|
19
|
+
options[:failed] ? "ERROR: No action requested" : "OK: 0; Sent queued message ID: 86b1a945370734f4 SMSGlobalMsgID:6942744494999745"
|
20
|
+
end
|
21
|
+
|
22
|
+
def sample_message_id
|
23
|
+
"SMSGlobalMsgID:6942744494999745"
|
24
|
+
end
|
25
|
+
|
26
|
+
def sample_delivery_receipt(options = {})
|
27
|
+
options[:message_id] ||= "6942744494999745"
|
28
|
+
options[:status] ||= "DELIVRD"
|
29
|
+
options[:error] ||= "000"
|
30
|
+
options[:date] ||= "1005132312"
|
31
|
+
{
|
32
|
+
"msgid"=> options[:message_id],
|
33
|
+
"dlrstatus"=> options[:status],
|
34
|
+
"dlr_err"=> options[:error],
|
35
|
+
"donedate"=> options[:date]
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module TestHelpers
|
2
|
+
module Tropo
|
3
|
+
def sample_incoming_sms(options = {})
|
4
|
+
options[:message] ||= "Endia kasdf ofeao"
|
5
|
+
options[:to] ||= "61447100308"
|
6
|
+
options[:from] ||= "61447100399"
|
7
|
+
options[:date] ||= "Mon Oct 11 09:21:38 UTC 2010"
|
8
|
+
params = {
|
9
|
+
"session" => {
|
10
|
+
"id"=>"12349516546e59746d6a89a990466789",
|
11
|
+
"account_id"=>"12345",
|
12
|
+
"timestamp"=> options[:date],
|
13
|
+
"user_type"=>"HUMAN",
|
14
|
+
"initial_text"=> options[:message],
|
15
|
+
"call_id"=>"123e71195545ad204bdd99f2070a7d86",
|
16
|
+
"to"=>{
|
17
|
+
"id"=> options[:to],
|
18
|
+
"name"=>"unknown",
|
19
|
+
"channel"=>"TEXT",
|
20
|
+
"network"=>"SMS"
|
21
|
+
},
|
22
|
+
"from" => {
|
23
|
+
"id"=> options[:from],
|
24
|
+
"name"=>"unknown",
|
25
|
+
"channel"=>"TEXT",
|
26
|
+
"network"=>"SMS"
|
27
|
+
},
|
28
|
+
"headers" => {
|
29
|
+
"_max-_forwards"=>"70",
|
30
|
+
"_content-_length"=>"124",
|
31
|
+
"_contact"=>"<sip:11.8.93.101:5066;transport=udp>",
|
32
|
+
"_to"=>"<sip:1231454582@10.6.69.203:5061;to=#{options[:to]}>",
|
33
|
+
"_c_seq"=>"1 INVITE",
|
34
|
+
"_via"=>"SIP/2.0/UDP 11.8.93.101:5066;branch=h0hG4bKk5sy1e",
|
35
|
+
"_call-_i_d"=>"ieeg18",
|
36
|
+
"_content-_type"=>"application/sdp",
|
37
|
+
|
38
|
+
"_from"=>"<sip:15EB6BAB-99DF-44C2-871DFBA75C319776@11.8.93.201;channel=private;user=#{options[:to]};msg=#{options[:message]};network=SMS;step=1>;tag=zm13kt"
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
params.merge!("authentication_key" => @config[:authentication_key]) unless options[:authentic] == false
|
43
|
+
params
|
44
|
+
end
|
45
|
+
|
46
|
+
def sample_delivery_response(options = {})
|
47
|
+
options[:failure] ? "<session><success>false</success><token></token><reason>FAILED TO ROUTE TOKEN</reason></session>" : "<session><success>true</success></session>"
|
48
|
+
end
|
49
|
+
|
50
|
+
def sample_message_id
|
51
|
+
"123e71195545ad204bdd99f2070a7d86"
|
52
|
+
end
|
53
|
+
|
54
|
+
# This is here simply so the current tests pass
|
55
|
+
# Tropo does not *yet* send delivery receipts
|
56
|
+
def sample_delivery_receipt(options = {})
|
57
|
+
options[:message_id] ||= "123e71195545ad204bdd99f2070a7d86"
|
58
|
+
options[:status] ||= "delivered"
|
59
|
+
options[:date] ||= "Mon Oct 11 09:21:38 UTC 2010"
|
60
|
+
{
|
61
|
+
"message_id"=> options[:message_id],
|
62
|
+
"status"=> options[:status],
|
63
|
+
"delivered_at"=> options[:date]
|
64
|
+
}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'action_sms/connection_adapters/abstract_adapter'
|
2
|
+
|
3
|
+
module ActionSms
|
4
|
+
class Base
|
5
|
+
def self.tropo_connection(config) #:nodoc:
|
6
|
+
if config[:environment].to_s == "test"
|
7
|
+
test_helper = File.expand_path(File.dirname(__FILE__) + '/test_helpers/tropo')
|
8
|
+
if File.exists?("#{test_helper}.rb")
|
9
|
+
require test_helper
|
10
|
+
ConnectionAdapters::TropoAdapter.class_eval do
|
11
|
+
include TestHelpers::Tropo
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
ConnectionAdapters::TropoAdapter.new(config)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ConnectionAdapters
|
20
|
+
# All the concrete gateway adapters follow the interface laid down in this
|
21
|
+
# class. You can use this interface directly by borrowing the gateway
|
22
|
+
# connection from the Base with Base.connection.
|
23
|
+
class TropoAdapter < AbstractAdapter
|
24
|
+
require 'uri'
|
25
|
+
require 'tropo_message'
|
26
|
+
|
27
|
+
attr_reader :service_url
|
28
|
+
|
29
|
+
SERVICE_HOST = "http://api.tropo.com/1.0"
|
30
|
+
SERVICE_PATH = "sessions"
|
31
|
+
|
32
|
+
def initialize(config = {}) #:nodoc:
|
33
|
+
@config = config.dup
|
34
|
+
service_uri = URI.join(SERVICE_HOST, SERVICE_PATH)
|
35
|
+
service_uri.scheme = config[:use_ssl] ? "https" : "http"
|
36
|
+
@service_url = service_uri.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
# message_id and status are for text message delivery receipts only
|
40
|
+
# Tropo does not *yet* send text message delivery receipts, so these
|
41
|
+
# two methods are here for testing purposes
|
42
|
+
def message_id(data)
|
43
|
+
data.is_a?(Hash) ? data["message_id"] : data
|
44
|
+
end
|
45
|
+
|
46
|
+
def status(delivery_receipt)
|
47
|
+
delivery_receipt["status"]
|
48
|
+
end
|
49
|
+
|
50
|
+
def delivery_request_successful?(gateway_response)
|
51
|
+
gateway_response =~ /\<success\>true\<\/success\>/
|
52
|
+
end
|
53
|
+
|
54
|
+
def message_text(params)
|
55
|
+
session(params)["initial_text"]
|
56
|
+
end
|
57
|
+
|
58
|
+
def sender(params)
|
59
|
+
session(params)["from"]["id"]
|
60
|
+
end
|
61
|
+
|
62
|
+
def authenticate(params)
|
63
|
+
params.delete("authentication_key") == @config[:authentication_key]
|
64
|
+
end
|
65
|
+
|
66
|
+
def deliver(sms)
|
67
|
+
tropo_message = Tropo::Message.new
|
68
|
+
tropo_message.to = sms.recipient
|
69
|
+
tropo_message.text = sms.body || ""
|
70
|
+
tropo_message.from = sms.from if sms.respond_to?(:from)
|
71
|
+
tropo_message.token = @config[:outgoing_token]
|
72
|
+
send_http_request(@service_url, tropo_message.request_xml)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def session(params)
|
77
|
+
params["session"]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 7
|
9
|
+
version: 0.0.7
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- David Wilkie
|
@@ -14,10 +14,24 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-14 00:00:00 +07:00
|
18
18
|
default_executable:
|
19
|
-
dependencies:
|
20
|
-
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: tropo_message
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 0
|
31
|
+
- 4
|
32
|
+
version: 0.0.4
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
21
35
|
description:
|
22
36
|
email: dwilkie@gmail.com
|
23
37
|
executables: []
|
@@ -36,6 +50,9 @@ files:
|
|
36
50
|
- lib/action_sms_gateways.rb
|
37
51
|
- lib/action_sms_gateways/connection_adapters.rb
|
38
52
|
- lib/action_sms_gateways/connection_adapters/sms_global.rb
|
53
|
+
- lib/action_sms_gateways/connection_adapters/test_helpers/sms_global.rb
|
54
|
+
- lib/action_sms_gateways/connection_adapters/test_helpers/tropo.rb
|
55
|
+
- lib/action_sms_gateways/connection_adapters/tropo.rb
|
39
56
|
- todo
|
40
57
|
has_rdoc: true
|
41
58
|
homepage: http://github.com/dwilkie/action_sms_gateways
|