smsified 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Jason Goecke
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.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ smsified
2
+ ========
3
+
4
+ SMSified is a simple API for sending and receiving text messages using regular phone numbers or short codes. SMSified uses a simple REST interface based on the GSMA OneAPI standard and is backed by Voxeo - the worlds largest communications cloud. Ruby lib for consuming the SMSified OneAPI.
5
+
6
+ This is a Ruby gem for consuming the SMSified OneAPI.
7
+
8
+ Installation
9
+ ------------
10
+
11
+ gem install smsified
12
+
13
+ Example
14
+ -------
15
+
16
+ Send an SMS:
17
+
18
+ require 'rubygems'
19
+ require 'smsified'
20
+ oneapi = Smsified::OneAPI.new(:username => 'user', :password => 'bug.fungus24')
21
+ oneapi.send_sms :address => '14155551212', :message => 'Hi there!', :sender_address => '13035551212'
22
+
23
+
24
+ Find a subscription:
25
+
26
+ require 'rubygems'
27
+ require 'smsified'
28
+ subscriptions = Smsified::Subscriptions.new(:username => 'user', :password => 'bug.fungus24')
29
+ subscriptions.inbound_subscriptions('17177455076')
30
+
31
+ Documentation
32
+ -------------
33
+
34
+ May be found at http://tropo.github.com/smsified & http://smsified.com.
35
+
36
+ License
37
+ -------
38
+
39
+ MIT - See LICENSE.txt
@@ -0,0 +1,39 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__), '..', 'lib')
2
+ require 'rubygems'
3
+ require 'smsified'
4
+ require 'yaml'
5
+
6
+ config = YAML.load(File.open('examples/config.yml'))
7
+
8
+ smsified = Smsified::OneAPI.new :username => config['smsified']['username'],
9
+ :password => config['smsified']['password']
10
+
11
+ # Send an SMS to one address
12
+ result = smsified.send_sms :message => 'Hello there!',
13
+ :address => '14157044517',
14
+ :notify_url => config['postbin'],
15
+ :sender_address => '17177455076'
16
+ puts result.data.inspect
17
+ puts result.http.inspect
18
+
19
+ # Send an SMS to multiple addresses
20
+ result = smsified.send_sms :message => 'Hello there!',
21
+ :address => ['14157044517', '14153675082'],
22
+ :notify_url => config['postbin'],
23
+ :sender_address => '17177455076'
24
+ puts result.data.inspect
25
+ puts result.http.inspect
26
+
27
+ # Create in inbound subscription
28
+ result = smsified.create_inbound_subscription '17177455076', :notify_url => config['postbin']
29
+ puts result.data.inspect
30
+ puts result.http.inspect
31
+
32
+ # Get some of your sent SMS details
33
+ result = smsified.search_sms 'startDate=2011-02-14&endDate=2011-02-15'
34
+ puts result.data.inspect
35
+ puts result.data.inspect
36
+
37
+
38
+
39
+
@@ -0,0 +1,33 @@
1
+ module Smsified
2
+ module Helpers
3
+ private
4
+
5
+ ##
6
+ # Camelcases the options
7
+ def camelcase_keys(options)
8
+ options = options.clone
9
+
10
+ if options[:destination_address]
11
+ options[:destinationAddress] = options[:destination_address]
12
+ options.delete(:destination_address)
13
+ end
14
+
15
+ if options[:notify_url]
16
+ options[:notifyURL] = options[:notify_url]
17
+ options.delete(:notify_url)
18
+ end
19
+
20
+ if options[:client_correlator]
21
+ options[:clientCorrelator] = options[:client_correlator]
22
+ options.delete(:client_correlator)
23
+ end
24
+
25
+ if options[:callback_data]
26
+ params[:callbackData] = options[:callback_data]
27
+ options.delete(:callback_data)
28
+ end
29
+
30
+ options
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,107 @@
1
+ module Smsified
2
+ SMSIFIED_ONEAPI_PUBLIC_URI = 'https://api.smsified.com/v1'
3
+ SMSIFIED_HTTP_HEADERS = { 'Content-Type' => 'application/x-www-form-urlencoded' }
4
+
5
+ class OneAPI
6
+ include Helpers
7
+
8
+ include HTTParty
9
+ format :json
10
+
11
+ ##
12
+ # Intantiate a new class to work with OneAPI
13
+ #
14
+ # @param [required, Hash] params to create the user
15
+ # @option params [required, String] :username username to authenticate with
16
+ # @option params [required, String] :password to authenticate with
17
+ # @option params [optional, String] :base_uri of an alternative location of SMSified
18
+ # @option params [optional, String] :destination_address to use with subscriptions
19
+ # @option params [optional, String] :sender_address to use with subscriptions
20
+ # @option params [optional, Boolean] :debug to turn on the HTTparty debugging to stdout
21
+ # @raise [ArgumentError] if :username is not passed as an option
22
+ # @raise [ArgumentError] if :password is not passed as an option
23
+ # @example
24
+ # one_api = OneAPI.new :username => 'user', :password => '123'
25
+ def initialize(options)
26
+ raise ArgumentError, ':username required' if options[:username].nil?
27
+ raise ArgumentError, ':password required' if options[:password].nil?
28
+
29
+ self.class.debug_output $stdout if options[:debug]
30
+ self.class.base_uri options[:base_uri] || SMSIFIED_ONEAPI_PUBLIC_URI
31
+ @auth = { :username => options[:username], :password => options[:password] }
32
+
33
+ @destination_address = options[:destination_address]
34
+ @sender_address = options[:sender_address]
35
+
36
+ @subscriptions = Subscriptions.new(options)
37
+ @reporting = Reporting.new(options)
38
+ end
39
+
40
+ ##
41
+ # Send an SMS to one or more addresses
42
+ #
43
+ # @param [required, Hash] params to send an sms
44
+ # @option params [required, String] :address to send the SMS to
45
+ # @option params [required, String] :message to send with the SMS
46
+ # @option params [optional, String] :sender_address to use with subscriptions, required if not provided on initialization of OneAPI
47
+ # @option params [optional, String] :notify_url to send callbacks to
48
+ # @return [Object] A Response Object with http and data instance methods
49
+ # @raise [ArgumentError] if :sender_address is not passed as an option when not passed on object creation
50
+ # @raise [ArgumentError] if :address is not provided as an option
51
+ # @raise [ArgumentError] if :message is not provided as an option
52
+ # @example
53
+ # one_api.send_sms :address => '14155551212', :message => 'Hi there!', :sender_address => '13035551212'
54
+ # one_api.send_sms :address => ['14155551212', '13035551212'], :message => 'Hi there!', :sender_address => '13035551212'
55
+ def send_sms(options)
56
+ raise ArgumentError, ':sender_address is required' if options[:sender_address].nil? && @sender_address.nil?
57
+ raise ArgumentError, ':address is required' if options[:address].nil?
58
+ raise ArgumentError, ':message is required' if options[:message].nil?
59
+
60
+ options[:sender_address] = options[:sender_address] || @sender_address
61
+ query_options = options.clone
62
+ query_options.delete(:sender_address)
63
+ query_options = camelcase_keys(query_options)
64
+
65
+ Response.new self.class.post("/smsmessaging/outbound/#{options[:sender_address]}/requests",
66
+ :body => build_query_string(query_options),
67
+ :basic_auth => @auth,
68
+ :headers => SMSIFIED_HTTP_HEADERS)
69
+ end
70
+
71
+ ##
72
+ # Dispatches method calls to other objects for subscriptions and reporting
73
+ def method_missing(method, *args)
74
+ if method.to_s.match /subscription/
75
+ if args.size == 2
76
+ @subscriptions.send method, args[0], args[1]
77
+ else
78
+ @subscriptions.send method, args[0]
79
+ end
80
+ else
81
+ if method == :delivery_status || method == :retrieve_sms || method == :search_sms
82
+ @reporting.send method, args[0]
83
+ else
84
+ raise RuntimeError, 'Unknown method'
85
+ end
86
+ end
87
+ end
88
+
89
+ private
90
+
91
+ ##
92
+ # Builds the necessary query string
93
+ def build_query_string(options)
94
+ query = ''
95
+
96
+ options.each do |k,v|
97
+ if k == :address
98
+ v.each { |address| query += "#{ '&' if query != '' }address=#{CGI.escape address}" }
99
+ else
100
+ query += "#{ '&' if query != '' }#{k.to_s}=#{CGI.escape v}"
101
+ end
102
+ end
103
+
104
+ query
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,70 @@
1
+ module Smsified
2
+ class Reporting
3
+ include HTTParty
4
+ format :json
5
+
6
+ ##
7
+ # Intantiate a new class to work with reporting
8
+ #
9
+ # @param [required, Hash] params to create the Reporting object with
10
+ # @option params [required, String] :username username to authenticate with
11
+ # @option params [required, String] :password to authenticate with
12
+ # @option params [optional, String] :base_uri of an alternative location of SMSified
13
+ # @option params [optional, String] :destination_address to use with subscriptions
14
+ # @option params [optional, String] :sender_address to use with subscriptions
15
+ # @option params [optional, Boolean] :debug to turn on the HTTparty debugging to stdout
16
+ # @example
17
+ # subscription = Subscription.new :username => 'user', :password => '123'
18
+ def initialize(options)
19
+ raise ArgumentError, ':username required' if options[:username].nil?
20
+ raise ArgumentError, ':password required' if options[:password].nil?
21
+
22
+ self.class.debug_output $stdout if options[:debug]
23
+ self.class.base_uri options[:base_uri] || SMSIFIED_ONEAPI_PUBLIC_URI
24
+ @auth = { :username => options[:username], :password => options[:password] }
25
+
26
+ @destination_address = options[:destination_address]
27
+ @sender_address = options[:sender_address]
28
+ end
29
+
30
+ ##
31
+ # Get the delivery status of an outstanding SMS request
32
+ #
33
+ # @param [required, Hash] params to get the delivery status
34
+ # @option params [required, String] :request_id to fetch the status for
35
+ # @option params [optional, String] :sender_address used to send the SMS, required if not provided on initialization of OneAPI
36
+ # @return [Object] A Response Object with http and data instance methods
37
+ # @raise [ArgumentError] of :sender_address is not passed here when not passed on instantiating the object
38
+ # @example
39
+ # one_api.delivery_status :request_id => 'f359193765f6a3149ca76a4508e21234', :sender_address => '14155551212'
40
+ def delivery_status(options)
41
+ raise ArgumentError, ':sender_address is required' if options[:sender_address].nil? && @sender_address.nil?
42
+
43
+ options[:sender_address] = options[:sender_address] || @sender_address
44
+
45
+ Response.new self.class.get("/smsmessaging/outbound/#{options[:sender_address]}/requests/#{options[:request_id]}/deliveryInfos", :basic_auth => @auth)
46
+ end
47
+
48
+ ##
49
+ # Retrieve a single SMS
50
+ #
51
+ # @param [required, String] message_id of the message to retrieve
52
+ # @return [Object] A Response Object with http and data instance methods
53
+ # @example
54
+ # reporting.retrieve_sms '74ae6147f915eabf87b35b9ea30c5916'
55
+ def retrieve_sms(message_id)
56
+ Response.new self.class.get("/messages/#{message_id}", :basic_auth => @auth)
57
+ end
58
+
59
+ ##
60
+ # Retrieve multiple SMS messages based on a query string
61
+ #
62
+ # @param [required, String] query_string to search SMS messages for
63
+ # @return [Object] A Response Object with http and data instance methods
64
+ # @example
65
+ # reporting.search_sms 'startDate=2011-02-14&endDate=2011-02-15'
66
+ def search_sms(query_string)
67
+ Response.new self.class.get("/messages?#{query_string}", :basic_auth => @auth)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,14 @@
1
+ module Smsified
2
+ class Response
3
+ attr_reader :data, :http
4
+
5
+ ##
6
+ # Provides the standard response for the library
7
+ #
8
+ # @param [Object] an HTTParty result object
9
+ def initialize(httparty)
10
+ @data = httparty.parsed_response
11
+ @http = httparty.response
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,147 @@
1
+ module Smsified
2
+ class Subscriptions
3
+ include Helpers
4
+
5
+ include HTTParty
6
+ format :json
7
+
8
+ ##
9
+ # Intantiate a new class to work with subscriptions
10
+ #
11
+ # @param [required, Hash] params to create the user
12
+ # @option params [required, String] :username username to authenticate with
13
+ # @option params [required, String] :password to authenticate with
14
+ # @option params [optional, String] :base_uri of an alternative location of SMSified
15
+ # @option params [optional, String] :destination_address to use with subscriptions
16
+ # @option params [optional, String] :sender_address to use with subscriptions
17
+ # @option params [optional, Boolean] :debug to turn on the HTTparty debugging to stdout
18
+ # @example
19
+ # subscription = Subscription.new :username => 'user', :password => '123'
20
+ def initialize(options)
21
+ raise ArgumentError, ':username required' if options[:username].nil?
22
+ raise ArgumentError, ':password required' if options[:password].nil?
23
+
24
+ self.class.debug_output $stdout if options[:debug]
25
+ self.class.base_uri options[:base_uri] || SMSIFIED_ONEAPI_PUBLIC_URI
26
+ @auth = { :username => options[:username], :password => options[:password] }
27
+
28
+ @destination_address = options[:destination_address]
29
+ @sender_address = options[:sender_address]
30
+ end
31
+
32
+ ##
33
+ # Creates an inbound subscription
34
+ #
35
+ # @param [required, String] destination_address to subscribe to
36
+ # @param [required, Hash] params to send an sms
37
+ # @option params [optional, String] :notify_url to send callbacks to
38
+ # @option params [optional, String] :client_correlator to update
39
+ # @option params [optional, String] :callback_data to update
40
+ # @return [Object] A Response Object with http and data instance methods
41
+ # @param [required, String] notify_url to send callbacks to
42
+ # @return [Object] A Response Object with http and data instance methods
43
+ # @example
44
+ # subscriptions.create_inbound_subscription('tel:+14155551212', :notify_url => 'http://foobar.com')
45
+ def create_inbound_subscription(destination_address, options)
46
+ query = options.merge({ :destination_address => destination_address })
47
+
48
+ Response.new self.class.post("/smsmessaging/inbound/subscriptions",
49
+ :basic_auth => @auth,
50
+ :body => camelcase_keys(query))
51
+ end
52
+
53
+ ##
54
+ # Creates an outbound subscription
55
+ #
56
+ # @param [required, String] sender_address to subscribe to
57
+ # @option params [optional, String] :notify_url to send callbacks to
58
+ # @option params [optional, String] :client_correlator to update
59
+ # @option params [optional, String] :callback_data to update
60
+ # @return [Object] A Response Object with http and data instance methods
61
+ # @example
62
+ # subscriptions.create_outbound_subscription('tel:+14155551212', :notify_url => 'http://foobar.com')
63
+ def create_outbound_subscription(sender_address, options)
64
+ Response.new self.class.post("/smsmessaging/outbound/#{sender_address}/subscriptions",
65
+ :basic_auth => @auth,
66
+ :body => camelcase_keys(options))
67
+ end
68
+
69
+ ##
70
+ # Deletes an inbound subscription
71
+ #
72
+ # @param [required, String] subscription_id to delete
73
+ # @return [Object] A Response Object with http and data instance methods
74
+ # @example
75
+ # subscriptions.delete_inbound_subscription('89edd71c1c7f3d349f9a3a4d5d2d410c')
76
+ def delete_inbound_subscription(subscription_id)
77
+ Response.new self.class.delete("/smsmessaging/inbound/subscriptions/#{subscription_id}", :basic_auth => @auth)
78
+ end
79
+
80
+ ##
81
+ # Deletes an outbound subscription
82
+ #
83
+ # @param [required, String] subscription_id to delete
84
+ # @return [Object] A Response Object with http and data instance methods
85
+ # @example
86
+ # subscriptions.delete_outbound_subscription('89edd71c1c7f3d349f9a3a4d5d2d410c')
87
+ def delete_outbound_subscription(sender_address)
88
+ Response.new self.class.delete("/smsmessaging/outbound/subscriptions/#{sender_address}", :basic_auth => @auth)
89
+ end
90
+
91
+ ##
92
+ # Fetches the inbound subscriptions
93
+ #
94
+ # @param [required, String] destination_address to fetch the subscriptions for
95
+ # @return [Object] A Response Object with http and data instance methods
96
+ # @example
97
+ # subscriptions.inbound_subscriptions('tel:+14155551212')
98
+ def inbound_subscriptions(destination_address)
99
+ Response.new self.class.get("/smsmessaging/inbound/subscriptions?destinationAddress=#{destination_address}", :basic_auth => @auth)
100
+ end
101
+
102
+ ##
103
+ # Fetches the outbound subscriptions
104
+ #
105
+ # @param [required, String] sender_address to fetch the subscriptions for
106
+ # @return [Object] A Response Object with http and data instance methods
107
+ # @example
108
+ # subscriptions.outbound_subscriptions('tel:+14155551212')
109
+ def outbound_subscriptions(sender_address)
110
+ Response.new self.class.get("/smsmessaging/outbound/subscriptions?senderAddress=#{sender_address}", :basic_auth => @auth)
111
+ end
112
+
113
+ ##
114
+ # Updates an inbound subscription
115
+ #
116
+ # @option params [required, String] subscription_id updating
117
+ # @param [required, Hash] params to update the inbound subscription with
118
+ # @option params [optional, String] :notify_url to send callbacks to
119
+ # @option params [optional, String] :client_correlator to update
120
+ # @option params [optional, String] :callback_data to update
121
+ # @return [Object] A Response Object with http and data instance methods
122
+ # @example
123
+ # subscriptions.update_inbound_subscription('89edd71c1c7f3d349f9a3a4d5d2d410c', :notify_url => 'foobar')
124
+ def update_inbound_subscription(subscription_id, options)
125
+ Response.new self.class.post("/smsmessaging/inbound/subscriptions/#{subscription_id}",
126
+ :basic_auth => @auth,
127
+ :body => camelcase_keys(options))
128
+ end
129
+
130
+ ##
131
+ # Updates an outbound subscription
132
+ #
133
+ # @option params [required, String] sender_address updating
134
+ # @param [required, Hash] params to update the outbound subscription with
135
+ # @option params [optional, String] :notify_url to send callbacks to
136
+ # @option params [optional, String] :client_correlator to update
137
+ # @option params [optional, String] :callback_data to update
138
+ # @return [Object] A Response Object with http and data instance methods
139
+ # @example
140
+ # subscriptions.update_outbound_subscription('tel:+14155551212', :notify_url => 'foobar')
141
+ def update_outbound_subscription(sender_address, options)
142
+ Response.new self.class.post("/smsmessaging/outbound/#{sender_address}/subscriptions",
143
+ :basic_auth => @auth,
144
+ :body => camelcase_keys(options))
145
+ end
146
+ end
147
+ end
data/lib/smsified.rb ADDED
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ %w(cgi httparty smsified/helpers smsified/oneapi smsified/subscriptions smsified/reporting smsified/response).each { |lib| require lib }
@@ -0,0 +1,416 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ # These tests are all local unit tests
4
+ FakeWeb.allow_net_connect = false
5
+
6
+ describe "Smsified" do
7
+ before(:all) do
8
+ @username = 'user'
9
+ @password = 'pass'
10
+ @address = '14155551212'
11
+ @sender_address = '13035551212'
12
+ end
13
+
14
+ describe "OneAPI" do
15
+ before(:all) do
16
+ @one_api = Smsified::OneAPI.new :username => @username, :password => @password, :debug => true
17
+
18
+ @message_sent = { "resourceReference" => { "resourceURL" => "https://api.smsified.com/v1/smsmessaging/outbound/tel%3A%2B#{@sender_address}/requests/795bd02c8e343b2dfd673b67dd0ee55a" } }
19
+
20
+ FakeWeb.register_uri(:post,
21
+ "https://#{@username}:#{@password}@api.smsified.com/v1/smsmessaging/outbound/#{@sender_address}/requests",
22
+ :status => ["200", "OK"],
23
+ :body => @message_sent.to_json)
24
+ end
25
+
26
+ it "Should get errors if instantiating without all of the right parameters" do
27
+ begin
28
+ Smsified::OneAPI.new 'foobar'
29
+ rescue => e
30
+ e.to_s.should eql ':username required'
31
+ end
32
+
33
+ begin
34
+ Smsified::OneAPI.new(:username => @username)
35
+ rescue => e
36
+ e.to_s.should eql ':password required'
37
+ end
38
+ end
39
+
40
+ it "Should raise an error if no :sender_address specified" do
41
+ begin
42
+ @one_api.send_sms('foobar')
43
+ rescue => e
44
+ e.to_s.should eql ':sender_address is required'
45
+ end
46
+ end
47
+
48
+ it "Should not raise an error if a :sender_address was specified at instantiation" do
49
+ one_api = Smsified::OneAPI.new :username => @username, :password => @password, :debug => true, :sender_address => @sender_address
50
+ response = one_api.send_sms :address => @address, :message => 'Hola from RSpec!'
51
+ response.data.should eql @message_sent
52
+ end
53
+
54
+ it "Should raise an error if all required params are not passed when sending an SMS" do
55
+ begin
56
+ @one_api.send_sms(:message => 'Hola from RSpec!', :sender_address => @sender_address)
57
+ rescue => e
58
+ e.to_s.should eql ':address is required'
59
+ end
60
+
61
+ begin
62
+ @one_api.send_sms(:address => @address, :sender_address => @sender_address)
63
+ rescue => e
64
+ e.to_s.should eql ':message is required'
65
+ end
66
+ end
67
+
68
+ it "Should instantiate a OneAPI object" do
69
+ oneapi = Smsified::OneAPI.new :username => @username, :password => @password, :debug => true
70
+ oneapi.instance_of?(Smsified::OneAPI).should eql true
71
+ end
72
+
73
+ it "Should send an SMS" do
74
+ response = @one_api.send_sms(:address => @address, :message => 'Hola from RSpec!', :sender_address => @sender_address)
75
+ response.data.should eql @message_sent
76
+ end
77
+
78
+ it "Should send an SMS to multiple destinations" do
79
+ response = @one_api.send_sms(:address => ['14155551212', '13035551212'],
80
+ :message => 'Hola from RSpec!',
81
+ :sender_address => @sender_address)
82
+ response.data.should eql @message_sent
83
+ end
84
+
85
+ it "Should raise an error if you pass an unknown method name" do
86
+ begin
87
+ @one_api.foobar
88
+ rescue => e
89
+ e.to_s.should eql "Unknown method"
90
+ end
91
+ end
92
+ end
93
+
94
+ describe 'Subscriptions' do
95
+ before(:all) do
96
+ @subscriptions = Smsified::Subscriptions.new :username => @username, :password => @password, :debug => true
97
+ end
98
+
99
+ it "Should instantiate a Subscriptions object" do
100
+ smsified = Smsified::Subscriptions.new(:username => @username, :password => @password)
101
+ smsified.instance_of?(Smsified::Subscriptions).should eql true
102
+ end
103
+
104
+ it "Should get errors if instantiating without all of the right parameters" do
105
+ begin
106
+ Smsified::Subscriptions.new 'foobar'
107
+ rescue => e
108
+ e.to_s.should eql ':username required'
109
+ end
110
+
111
+ begin
112
+ Smsified::Subscriptions.new(:username => @username)
113
+ rescue => e
114
+ e.to_s.should eql ':password required'
115
+ end
116
+ end
117
+
118
+ describe 'Listing subscriptions' do
119
+ before(:all) do
120
+ @no_subscription = { "inboundSubscriptionList" => { "numberOfSubscriptions" => "0" } }
121
+
122
+ @inbound_subscriptions = {
123
+ "inboundSubscriptionList" => {
124
+ "inboundSubscription" => [
125
+ {
126
+ "resourceURL" => "https://api.smsified.com/v1/smsmessaging/inbound/subscriptions/3cf88f9cfd0dae96cbfdf16f18c07411",
127
+ "subscriptionId" => "3cf88f9cfd0dae96cbfdf16f18c07411",
128
+ "notificationFormat" => "JSON",
129
+ "destinationAddress" => "tel:+17177455076",
130
+ "notifyURL" => "http://98.207.5.162:8080"
131
+ },
132
+ {
133
+ "resourceURL" => "https://api.smsified.com/v1/smsmessaging/inbound/subscriptions/75bb5bef239aed425c2966cbb95f33c9",
134
+ "subscriptionId" => "75bb5bef239aed425c2966cbb95f33c9",
135
+ "notificationFormat" => "JSON",
136
+ "destinationAddress" => "tel:+17177455076",
137
+ "notifyURL" => "http://98.207.5.162:8080"
138
+ }
139
+ ],
140
+ "numberOfSubscriptions" => "2",
141
+ "resourceURL" => "https://api.smsified.com/v1/smsmessaging/inbound/subscriptions"
142
+ }
143
+ }
144
+
145
+ @outbound_subscriptions = {
146
+ "outboundSubscriptionList" => {
147
+ "numberOfSubscriptions" => "2",
148
+ "resourceURL" => "https://api.smsified.com/v1/smsmessaging/outbound/subscriptions",
149
+ "outboundSubscription" => [
150
+ {
151
+ "senderAddress" => "tel:+17177455076",
152
+ "resourceURL" => "https://api.smsified.com/v1/smsmessaging/outbound/subscriptions/68faa512b1c81ee0d33a6b97004d1212",
153
+ "subscriptionId" => "68faa512b1c81ee0d33a6b97004d1212",
154
+ "notificationFormat" => "JSON",
155
+ "notifyURL" => "http://98.207.5.162:8080"
156
+ },
157
+ {
158
+ "senderAddress" => "tel:+17177455076",
159
+ "resourceURL" => "https://api.smsified.com/v1/smsmessaging/outbound/subscriptions/6e64fb72cd2a27b8a9460caccbd4dc53",
160
+ "subscriptionId" => "6e64fb72cd2a27b8a9460caccbd4dc53",
161
+ "notificationFormat" => "JSON",
162
+ "notifyURL" => "http://98.207.5.162:8080"
163
+ }
164
+ ]
165
+ }
166
+ }
167
+
168
+ FakeWeb.register_uri(:get,
169
+ "https://#{@username}:#{@password}@api.smsified.com/v1/smsmessaging/inbound/subscriptions?destinationAddress=#{@address}",
170
+ :status => ["200", "OK"],
171
+ :body => @no_subscription.to_json)
172
+
173
+ FakeWeb.register_uri(:get,
174
+ "https://#{@username}:#{@password}@api.smsified.com/v1/smsmessaging/inbound/subscriptions?destinationAddress=#{@sender_address}",
175
+ :status => ["200", "OK"],
176
+ :body => @inbound_subscriptions.to_json)
177
+
178
+ FakeWeb.register_uri(:get,
179
+ "https://#{@username}:#{@password}@api.smsified.com/v1/smsmessaging/outbound/subscriptions?senderAddress=#{@sender_address}",
180
+ :status => ["200", "OK"],
181
+ :body => @outbound_subscriptions.to_json)
182
+ end
183
+
184
+ it "Should let me instantiate a OneAPI object and call subscription methods" do
185
+ one_api = Smsified::OneAPI.new :username => @username, :password => @password, :debug => true
186
+ inbound_subscriptions = one_api.inbound_subscriptions(@address)
187
+ inbound_subscriptions.data.should eql @no_subscription
188
+ end
189
+
190
+ it "Should find no subscriptions" do
191
+ inbound_subscriptions = @subscriptions.inbound_subscriptions(@address)
192
+ inbound_subscriptions.data.should eql @no_subscription
193
+ end
194
+
195
+ it "Should get a list of inbound subscriptions" do
196
+ inbound_subscriptions = @subscriptions.inbound_subscriptions(@sender_address)
197
+ inbound_subscriptions.http.code.should eql '200'
198
+ inbound_subscriptions.data.should eql @inbound_subscriptions
199
+ end
200
+
201
+ it "Should get a list of outbound subscriptions" do
202
+ outbound_subscriptions = @subscriptions.outbound_subscriptions(@sender_address)
203
+ outbound_subscriptions.http.code.should eql '200'
204
+ outbound_subscriptions.data.should eql @outbound_subscriptions
205
+ end
206
+ end
207
+
208
+ describe 'Create subscriptions' do
209
+ before(:all) do
210
+ @inbound_subscription = { "resourceReference" => { "resourceURL" => "https://api.smsified.com/v1/smsmessaging/inbound/subscriptions/e636368b7fddac0e93e34ae03bad33dd" } }
211
+ @outbound_subscription = { "resourceReference" => { "resourceURL" => "https://api.smsified.com/v1/smsmessaging/outbound/subscriptions/4bc465cd394c9f5e78802af5ad6bb442" } }
212
+
213
+ FakeWeb.register_uri(:post,
214
+ %r|https://#{@username}:#{@password}@api.smsified.com/v1/smsmessaging/inbound/subscriptions?|,
215
+ :status => ["200", "OK"],
216
+ :body => @inbound_subscription.to_json)
217
+
218
+ FakeWeb.register_uri(:post,
219
+ %r|https://#{@username}:#{@password}@api.smsified.com/v1/smsmessaging/outbound/17177455076/subscriptions?|,
220
+ :status => ["200", "OK"],
221
+ :body => @outbound_subscription.to_json)
222
+ end
223
+
224
+ it 'Should create an inbound subscription' do
225
+ result = @subscriptions.create_inbound_subscription('17177455076', :notify_url => 'http://foobar.com')
226
+ result.http.code.should eql '200'
227
+ result.data.should eql @inbound_subscription
228
+ end
229
+
230
+ it 'Should create an outbound subscription' do
231
+ result = @subscriptions.create_outbound_subscription('17177455076', :notify_url => 'http://foobar.com')
232
+ result.http.code.should eql '200'
233
+ result.data.should eql @outbound_subscription
234
+ end
235
+ end
236
+
237
+ describe 'Updated subscriptions' do
238
+ before(:all) do
239
+ @outbound_subscription = { "resourceReference" => { "resourceURL" => "https://api.smsified.com/v1/smsmessaging/outbound/subscriptions/4bc465cd394c9f5e78802af5ad6bb442" } }
240
+
241
+ FakeWeb.register_uri(:post,
242
+ "https://#{@username}:#{@password}@api.smsified.com/v1/smsmessaging/outbound/#{@sender_address}/subscriptions",
243
+ :status => ["200", "OK"],
244
+ :body => @outbound_subscription.to_json)
245
+ end
246
+
247
+ it 'Should update an inbound subscription' do
248
+ pending('udpate resources being deployed')
249
+ result = @subscriptions.update_inbound_subscription('c880c96f161f6220d4977b29b4bfc111', :notify_url => 'http://foobar1.com')
250
+
251
+ result.http.code.should eql '200'
252
+ result.data.should eql nil
253
+ end
254
+
255
+ it 'Should update an outbound subscription' do
256
+ result = @subscriptions.update_outbound_subscription(@sender_address, :notify_url => 'http://foobar.com')
257
+ result.http.code.should eql '200'
258
+ result.data.should eql @outbound_subscription
259
+ end
260
+ end
261
+
262
+ describe 'Deleting subscriptions' do
263
+ before(:all) do
264
+ FakeWeb.register_uri(:delete,
265
+ %r|https://#{@username}:#{@password}@api.smsified.com/v1/smsmessaging/|,
266
+ :status => ["204", "OK"])
267
+ end
268
+
269
+ it "Should delete an inbound subscription" do
270
+ result = @subscriptions.delete_inbound_subscription('3cf88f9cfd0dae96cbfdf16f18c07411')
271
+ result.http.code.should eql '204'
272
+ end
273
+
274
+ it "Should delete an outbound subscription" do
275
+ result = @subscriptions.delete_outbound_subscription('342b61efc3ba9fd2fd992e58903ef050')
276
+ result.http.code.should eql '204'
277
+ end
278
+ end
279
+ end
280
+
281
+ describe "Reporting" do
282
+ before(:all) do
283
+ @reporting = Smsified::Reporting.new :username => @username, :password => @password, :debug => true
284
+
285
+ @delivery_status = {
286
+ "deliveryInfoList" => {
287
+ "deliveryInfo" => [
288
+ {
289
+ "address" => "tel:+14153675082",
290
+ "parts" => "1",
291
+ "senderAddress" => "tel:+17177455076",
292
+ "messageId" => "74ae6147f915eabf87b35b9ea30c5916",
293
+ "code" => "0",
294
+ "createdDateTime" => 'Fri May 13 16:14:50 UTC 2011',
295
+ "sentDateTime" => 'Fri May 13 16:14:53 UTC 2011',
296
+ "deliveryStatus" => "DeliveredToNetwork",
297
+ "message" => "Hola from RSpec!",
298
+ "direction" => "outbound"
299
+ }
300
+ ],
301
+ "resourceURL" => "https://api.smsified.com/v1/smsmessaging/outbound/tel%3A%2B17177455076/requests/795bd02c8e343b2dfd673b67dd0ee55a/deliveryInfos"
302
+ }
303
+ }
304
+
305
+ @message = { "parts" => 1,
306
+ "sent" => "2011-05-13T16:14:50.480+0000",
307
+ "code" => "0",
308
+ "body" => "Hola from RSpec!",
309
+ "messageId" => "74ae6147f915eabf87b35b9ea30c5916",
310
+ "from" => "17177455076",
311
+ "to" => "14153675082",
312
+ "direction" => "out",
313
+ "status" => "success",
314
+ "created" => "2011-05-13T16:14:50.480+0000"}
315
+
316
+ @message_range = [
317
+ {
318
+ "parts" => 1,
319
+ "sent" => "2011-05-13T20:27:56.690+0000",
320
+ "code" => "-1",
321
+ "body" => "foobar9446",
322
+ "messageId" => "d194e91c32de943ae942ad4043b7905b",
323
+ "from" => "17177455076",
324
+ "to" => "14155551",
325
+ "direction" => "out",
326
+ "status" => "fail",
327
+ "created" => "2011-05-13T20:27:56.690+0000"
328
+ },
329
+ {
330
+ "parts" => 1,
331
+ "sent" => "2011-05-13T20:27:53.660+0000",
332
+ "code" => "-1",
333
+ "body" => "foobar4374",
334
+ "messageId" => "4d9237b323618ab164fb6d646882da99",
335
+ "from" => "17177455076",
336
+ "to" => "14155551212",
337
+ "direction" => "out",
338
+ "status" => "fail",
339
+ "created" => "2011-05-13T20:27:53.660+0000"
340
+ }
341
+ ]
342
+
343
+ FakeWeb.register_uri(:get,
344
+ "https://#{@username}:#{@password}@api.smsified.com/v1/messages/74ae6147f915eabf87b35b9ea30c5916",
345
+ :status => ["200", "OK"],
346
+ :body => @message.to_json)
347
+
348
+ FakeWeb.register_uri(:get,
349
+ "https://#{@username}:#{@password}@api.smsified.com/v1/messages?startDate=2011-05-12&endDate=2011-05-12",
350
+ :status => ["200", "OK"],
351
+ :body => @message_range.to_json)
352
+
353
+ FakeWeb.register_uri(:get,
354
+ "https://#{@username}:#{@password}@api.smsified.com/v1/smsmessaging/outbound/#{@sender_address}/requests/795bd02c8e343b2dfd673b67dd0ee55a/deliveryInfos",
355
+ :status => ["200", "OK"],
356
+ :body => @delivery_status.to_json)
357
+ end
358
+
359
+ it "Should instantiate a Reporting object" do
360
+ reporting = Smsified::Reporting.new :username => 'smsified_tester_smsified', :password => 'bug.fungus52', :debug => true
361
+ reporting.instance_of?(Smsified::Reporting).should eql true
362
+ end
363
+
364
+ it "Should get errors if instantiating without all of the right parameters" do
365
+ begin
366
+ Smsified::Reporting.new 'foobar'
367
+ rescue => e
368
+ e.to_s.should eql ':username required'
369
+ end
370
+
371
+ begin
372
+ Smsified::Reporting.new(:username => @username)
373
+ rescue => e
374
+ e.to_s.should eql ':password required'
375
+ end
376
+ end
377
+
378
+ it "Should raise an error if no :sender_address specified" do
379
+ begin
380
+ @reporting.delivery_status('foobar')
381
+ rescue => e
382
+ e.to_s.should eql ':sender_address is required'
383
+ end
384
+ end
385
+
386
+ it "Should not raise an error if a :sender_address was specified at instantiation" do
387
+ reporting = Smsified::Reporting.new :username => @username, :password => @password, :debug => true, :sender_address => @sender_address
388
+ delivery_response = reporting.delivery_status :request_id => '795bd02c8e343b2dfd673b67dd0ee55a'
389
+ delivery_response.data.should == @delivery_status
390
+ end
391
+
392
+ it "Should retrieve an SMS message" do
393
+ response = @reporting.retrieve_sms '74ae6147f915eabf87b35b9ea30c5916'
394
+ response.data.should eql @message
395
+ end
396
+
397
+ it "Should retrieve SMS messages based on a query string" do
398
+ response = @reporting.search_sms 'startDate=2011-05-12&endDate=2011-05-12'
399
+ response.data.should eql @message_range
400
+ end
401
+
402
+ it "Should send an SMS and get the Delivery status" do
403
+ delivery_response = @reporting.delivery_status :request_id => '795bd02c8e343b2dfd673b67dd0ee55a', :sender_address => @sender_address
404
+ delivery_response.data.should == @delivery_status
405
+ end
406
+
407
+ it "Should let me instantiate a OneAPI object and call reporting methods" do
408
+ one_api = Smsified::OneAPI.new :username => @username, :password => @password, :debug => true
409
+ delivery_response = one_api.delivery_status :request_id => '795bd02c8e343b2dfd673b67dd0ee55a', :sender_address => @sender_address
410
+ delivery_response.data.should eql @delivery_status
411
+
412
+ sms_message = one_api.retrieve_sms '74ae6147f915eabf87b35b9ea30c5916'
413
+ sms_message.data.should eql @message
414
+ end
415
+ end
416
+ end
@@ -0,0 +1,15 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'smsified'
5
+ require 'fakeweb'
6
+ require 'awesome_print'
7
+ require 'json'
8
+
9
+ # Requires supporting files with custom matchers and macros, etc,
10
+ # in ./support/ and its subdirectories.
11
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
12
+
13
+ RSpec.configure do |config|
14
+
15
+ end
metadata ADDED
@@ -0,0 +1,213 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smsified
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 3
10
+ version: 0.1.3
11
+ platform: ruby
12
+ authors:
13
+ - Jason Goecke
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-05-20 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ type: :development
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 2
31
+ - 3
32
+ - 0
33
+ version: 2.3.0
34
+ name: rspec
35
+ version_requirements: *id001
36
+ prerelease: false
37
+ - !ruby/object:Gem::Dependency
38
+ type: :development
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 7
45
+ segments:
46
+ - 0
47
+ - 6
48
+ - 0
49
+ version: 0.6.0
50
+ name: yard
51
+ version_requirements: *id002
52
+ prerelease: false
53
+ - !ruby/object:Gem::Dependency
54
+ type: :development
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 23
61
+ segments:
62
+ - 1
63
+ - 0
64
+ - 0
65
+ version: 1.0.0
66
+ name: bundler
67
+ version_requirements: *id003
68
+ prerelease: false
69
+ - !ruby/object:Gem::Dependency
70
+ type: :development
71
+ requirement: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ hash: 7
77
+ segments:
78
+ - 1
79
+ - 5
80
+ - 2
81
+ version: 1.5.2
82
+ name: jeweler
83
+ version_requirements: *id004
84
+ prerelease: false
85
+ - !ruby/object:Gem::Dependency
86
+ type: :development
87
+ requirement: &id005 !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 3
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ name: rcov
97
+ version_requirements: *id005
98
+ prerelease: false
99
+ - !ruby/object:Gem::Dependency
100
+ type: :development
101
+ requirement: &id006 !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ hash: 3
107
+ segments:
108
+ - 0
109
+ version: "0"
110
+ name: fakeweb
111
+ version_requirements: *id006
112
+ prerelease: false
113
+ - !ruby/object:Gem::Dependency
114
+ type: :development
115
+ requirement: &id007 !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ hash: 3
121
+ segments:
122
+ - 0
123
+ version: "0"
124
+ name: awesome_print
125
+ version_requirements: *id007
126
+ prerelease: false
127
+ - !ruby/object:Gem::Dependency
128
+ type: :development
129
+ requirement: &id008 !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ hash: 3
135
+ segments:
136
+ - 0
137
+ version: "0"
138
+ name: json
139
+ version_requirements: *id008
140
+ prerelease: false
141
+ - !ruby/object:Gem::Dependency
142
+ type: :runtime
143
+ requirement: &id009 !ruby/object:Gem::Requirement
144
+ none: false
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ hash: 3
149
+ segments:
150
+ - 0
151
+ version: "0"
152
+ name: httparty
153
+ version_requirements: *id009
154
+ prerelease: false
155
+ description: Gem for consuming the SMSified OneAPI
156
+ email: jsgoecke@voxeo.com
157
+ executables: []
158
+
159
+ extensions: []
160
+
161
+ extra_rdoc_files:
162
+ - LICENSE.txt
163
+ - README.md
164
+ files:
165
+ - README.md
166
+ - lib/smsified.rb
167
+ - lib/smsified/helpers.rb
168
+ - lib/smsified/oneapi.rb
169
+ - lib/smsified/reporting.rb
170
+ - lib/smsified/response.rb
171
+ - lib/smsified/subscriptions.rb
172
+ - LICENSE.txt
173
+ - examples/sending_and_subscribing.rb
174
+ - spec/smsified_spec.rb
175
+ - spec/spec_helper.rb
176
+ has_rdoc: true
177
+ homepage: http://github.com/tropo/smsified-oneapi
178
+ licenses:
179
+ - MIT
180
+ post_install_message:
181
+ rdoc_options: []
182
+
183
+ require_paths:
184
+ - lib
185
+ required_ruby_version: !ruby/object:Gem::Requirement
186
+ none: false
187
+ requirements:
188
+ - - ">="
189
+ - !ruby/object:Gem::Version
190
+ hash: 3
191
+ segments:
192
+ - 0
193
+ version: "0"
194
+ required_rubygems_version: !ruby/object:Gem::Requirement
195
+ none: false
196
+ requirements:
197
+ - - ">="
198
+ - !ruby/object:Gem::Version
199
+ hash: 3
200
+ segments:
201
+ - 0
202
+ version: "0"
203
+ requirements: []
204
+
205
+ rubyforge_project:
206
+ rubygems_version: 1.5.2
207
+ signing_key:
208
+ specification_version: 3
209
+ summary: Gem for consuming the SMSified OneAPI
210
+ test_files:
211
+ - examples/sending_and_subscribing.rb
212
+ - spec/smsified_spec.rb
213
+ - spec/spec_helper.rb