clockworksms 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'nokogiri'
4
+ gem 'faraday'
5
+
6
+ group :development do
7
+ gem 'rake'
8
+ gem 'rspec'
9
+ end
@@ -0,0 +1,26 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.3)
5
+ faraday (0.8.0)
6
+ multipart-post (~> 1.1)
7
+ multipart-post (1.1.5)
8
+ nokogiri (1.5.2)
9
+ rake (0.9.2.2)
10
+ rspec (2.10.0)
11
+ rspec-core (~> 2.10.0)
12
+ rspec-expectations (~> 2.10.0)
13
+ rspec-mocks (~> 2.10.0)
14
+ rspec-core (2.10.0)
15
+ rspec-expectations (2.10.0)
16
+ diff-lcs (~> 1.1.3)
17
+ rspec-mocks (2.10.1)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ faraday
24
+ nokogiri
25
+ rake
26
+ rspec
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (C) 2012, Mediaburst Limited <hello@mediaburst.co.uk>
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any
4
+ purpose with or without fee is hereby granted, provided that the above
5
+ copyright notice and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE
@@ -0,0 +1,119 @@
1
+ # Clockwork SMS API Ruby Gem
2
+
3
+ ## Install
4
+
5
+ Just add the following to your Gemfile:
6
+
7
+ gem 'clockworksms'
8
+
9
+ ## Documentation
10
+
11
+ Full documentation is at [http://rubydoc.info/github/mediaburst/clockwork-ruby/master/frames][1]. Alternatively, run `yard doc` and open doc/index.html.
12
+
13
+ ## Usage
14
+
15
+ For more information on the available optional parameters for the API (Clockwork::API), see [here][4].
16
+
17
+ For more information on the available optional parameters for each SMS (Clockwork::SMS), see [here][5]. For more information on the response object returned from each SMS (Clockwork::SMS::Response), see [here][6].
18
+
19
+ ### Send a single SMS message
20
+
21
+ require 'clockwork'
22
+ api = Clockwork::API.new( 'API_KEY_GOES_HERE' )
23
+ message = api.messages.build( :to => '441234123456', :content => 'This is a test message.' )
24
+ response = message.deliver
25
+
26
+ if response.success
27
+ puts response.message_id
28
+ else
29
+ puts response.error_code
30
+ puts response.error_description
31
+ end
32
+
33
+ ### Alternative usage for sending an SMS message
34
+
35
+ require 'clockwork'
36
+ api = Clockwork::API.new( 'API_KEY_GOES_HERE' )
37
+
38
+ message = api.messages.build
39
+ message.to = '441234123456'
40
+ message.content = 'This is a test message.'
41
+ response = message.deliver
42
+
43
+ if response.success
44
+ puts response.message_id
45
+ else
46
+ puts response.error_code
47
+ puts response.error_description
48
+ end
49
+
50
+ ### Send multiple SMS messages (with an optional client ID)
51
+
52
+ You should not use the `Clockwork::Message#deliver` method for each message, but instead use the `Clockwork::API#deliver` method to send multiple messages in the same API request. This will decrease load on the API and ensure your requests are processed significantly faster.
53
+
54
+ messages = [
55
+ { :to => '441234123456', :content => 'This is a test message.', :client_id => '1' },
56
+ { :to => '441234123456', :content => 'This is a test message 2.', :client_id => '2' },
57
+ { :to => '441234123456', :content => 'This is a test message 3.', :client_id => '3' },
58
+ { :to => '441234123456', :content => 'This is a test message 4.', :client_id => '4' },
59
+ { :to => '441234123456', :content => 'This is a test message 5.', :client_id => '5' },
60
+ { :to => '441234123456', :content => 'This is a test message 6.', :client_id => '6' }
61
+ ]
62
+
63
+ require 'clockwork'
64
+ api = Clockwork::API.new( 'API_KEY_GOES_HERE' )
65
+ messages.each do |m|
66
+ api.messages.build(m)
67
+ end
68
+
69
+ responses = api.deliver_messages
70
+ responses.each do |response|
71
+ puts response.client_id
72
+ if response.success
73
+ puts response.message_id
74
+ else
75
+ puts response.error_code
76
+ puts response.error_description
77
+ end
78
+ end
79
+
80
+ ### Check credit
81
+
82
+ require 'clockwork'
83
+ api = Clockwork::API.new( 'API_KEY_GOES_HERE' )
84
+ remaining_messages = Clockwork::API.credit
85
+ puts remaining messages # => 240
86
+
87
+ ## License
88
+
89
+ This project is licensed under the ISC open-source license.
90
+
91
+ A copy of this license can be found in LICENSE.
92
+
93
+ ## Contributing
94
+
95
+ If you have any feedback on this wrapper drop us an email to [hello@clockworksms.com][2].
96
+
97
+ The project is hosted on GitHub at [http://www.github.com/mediaburst/clockwork-ruby][3].
98
+
99
+ If you would like to contribute a bug fix or improvement please fork the project
100
+ and submit a pull request. Please add RSpec tests for your use case.
101
+
102
+ ### Test Setup
103
+
104
+ First, create a file at spec/spec_authentication_details containing the following:
105
+
106
+ 34023ada3ec0d99213f91a12a2329ba932665ed7
107
+ MyLegacyAPIUsername@mydomain.com
108
+ MyPassword
109
+
110
+ Substitute your own API key, username and password on lines 1, 2, and 3 of the file.
111
+
112
+ Then, run `rspec`.
113
+
114
+ [1]: http://rubydoc.info/github/mediaburst/clockwork-ruby/master/frames
115
+ [2]: mailto:hello@clockworksms.com
116
+ [3]: http://www.github.com/mediaburst/clockwork-ruby
117
+ [4]: http://rubydoc.info/github/mediaburst/clockwork-ruby/master/Clockwork/API
118
+ [5]: http://rubydoc.info/github/mediaburst/clockwork-ruby/master/Clockwork/SMS
119
+ [6]: http://rubydoc.info/github/mediaburst/clockwork-ruby/master/Clockwork/SMS/Response
@@ -0,0 +1,14 @@
1
+ lib_dir = File.expand_path(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift lib_dir unless $LOAD_PATH.include?(lib_dir)
3
+
4
+ require 'net/http'
5
+ require 'nokogiri'
6
+
7
+ require 'clockwork/error'
8
+ require 'clockwork/http'
9
+ require 'clockwork/xml/xml'
10
+
11
+ require 'clockwork/message_collection'
12
+ require 'clockwork/api'
13
+ require 'clockwork/sms'
14
+ require 'clockwork/sms/response'
@@ -0,0 +1,133 @@
1
+ # A wrapper around the Clockwork API.
2
+ module Clockwork
3
+
4
+ # Current API wrapper version
5
+ VERSION = '1.0.0'
6
+
7
+ # @author James Inman <james@mediaburst.co.uk>
8
+ # You must create an instance of Clockwork::API to begin using the API.
9
+ class API
10
+
11
+ # URL of the SMS API send action
12
+ SMS_URL = "api.clockworksms.com/xml/send"
13
+ # URL of the SMS API check credit action
14
+ CREDIT_URL = "api.clockworksms.com/xml/credit"
15
+
16
+ # API key provided in Clockwork::API#initialize.
17
+ # @return [string]
18
+ attr_reader :api_key
19
+
20
+ # This is the number of messages to concatenate (join together).
21
+ # @raise ArgumentError - if a value less than 2 or more than 3 is passed
22
+ # @return [symbol] One of +error+, +:replace+, +:remove+
23
+ # @note Defaults to 3 if not set and Clockwork::API#long is set to +true+.
24
+ attr_reader :concat
25
+
26
+ # @!attribute from
27
+ # The from address displayed on a phone when the SMS is received. This can be either a 12 digit number or 11 characters long.
28
+ # @return [string]
29
+ # @note This can be overriden for specific Clockwork::SMS objects; if it is not set your account default will be used.
30
+ attr_accessor :from
31
+
32
+ # What to do with any invalid characters in the message content. +:error+ will raise a Clockwork::InvalidCharacterException, +:replace+ will replace a small number of common invalid characters, such as the smart quotes used by Microsoft Office with a similar match, +:remove+ will remove invalid characters.
33
+ # @raise ArgumentError - if value is not one of +:error+, +:replace+, +:remove+
34
+ # @return [symbol] One of +error+, +:replace+, +:remove+
35
+ # @note This can be overriden for specific Clockwork::SMS objects; if it is not set your account default will be used.
36
+ attr_reader :invalid_char_action
37
+
38
+ # @!attribute long
39
+ # Set to +true+ to enable long SMS. A standard text can contain 160 characters, a long SMS supports up to 459. Each recipient will cost up to 3 message credits.
40
+ # @return [boolean]
41
+ # @note This can be overriden for specific Clockwork::SMS objects; if it is not set your account default will be used.
42
+ attr_accessor :long
43
+
44
+ # @!attribute messages
45
+ # Returns a Clockwork::MessageCollection containing all built SMS messages.
46
+ # @return [Clockwork::MessageCollection]
47
+ attr_reader :messages
48
+
49
+ # Password provided in Clockwork::API#initialize.
50
+ # @return [string]
51
+ # @deprecated Use api_key instead.
52
+ attr_reader :password
53
+
54
+ # @!attribute truncate
55
+ # Set to +true+ to trim the message content to the maximum length if it is too long.
56
+ # @return [boolean]
57
+ # @note This can be overriden for specific Clockwork::SMS objects; if it is not set your account default will be used.
58
+ attr_accessor :truncate
59
+
60
+ # Whether to use SSL when connecting to the API.
61
+ # Defaults to +true+
62
+ # @return [boolean]
63
+ attr_accessor :use_ssl
64
+
65
+ # Username provided in Clockwork::API#initialize.
66
+ # @return [string]
67
+ # @deprecated Use api_key instead.
68
+ attr_reader :username
69
+
70
+ # Alias for Clockwork::API#credit to preserve backwards compatibility with original Mediaburst API.
71
+ # @deprecated Use Clockwork::API#credit. Support for Clockwork::API#get_credit will be removed in a future version of this wrapper.
72
+ def get_credit
73
+ credit
74
+ end
75
+
76
+ def invalid_char_action= symbol
77
+ raise( ArgumentError, "#{symbol} must be one of :error, :replace, :remove" ) unless [:error, :replace, :remove].include?(symbol.to_sym)
78
+ end
79
+
80
+ def concat= number
81
+ raise( ArgumentError, "#{number} must be either 2 or 3" ) unless [2, 3].include?(number.to_i)
82
+ end
83
+
84
+ # @overload initalize(api_key)
85
+ # @param [string] api_key API key, 40-character hexadecimal string
86
+ # @param [hash] options Optional hash of attributes on API
87
+ # @overload initalize(username, password)
88
+ # @param [string] username Your API username
89
+ # @param [string] password Your API password
90
+ # @param [hash] options Optional hash of attributes on API
91
+ # @deprecated Use an API key instead. Support for usernames and passwords will be removed in a future version of this wrapper.
92
+ # @raise ArgumentError - if more than 3 parameters are passed
93
+ # @raise Clockwork::Error::InvalidAPIKey - if API key is invalid
94
+ # Clockwork::API is initialized with an API key, available from http://www.mediaburst.co.uk/api.
95
+ def initialize *args
96
+ if args.size == 1 || ( args.size == 2 && args[1].kind_of?(Hash) )
97
+ raise Clockwork::Error::InvalidAPIKey unless args[0][/^[A-Fa-f0-9]{40}$/]
98
+ @api_key = args[0]
99
+ elsif args.size == 2 || ( args.size == 3 && args[2].kind_of?(Hash) )
100
+ raise ArgumentError, "You must pass both a username and password." if args[0].empty? || args[1].empty?
101
+ @username = args[0]
102
+ @password = args[1]
103
+ else
104
+ raise ArgumentError, "You must pass either an API key OR a username and password."
105
+ end
106
+
107
+ args.last.each { |k, v| instance_variable_set "@#{k}", v } if args.last.kind_of?(Hash)
108
+
109
+ @use_ssl = true if @use_ssl.nil?
110
+ @concat = 3 if @concat.nil? && @long
111
+ @messages ||= Clockwork::MessageCollection.new( :api => self )
112
+ end
113
+
114
+ # Check the remaining credit for this account.
115
+ # @raise Clockwork::Error::Authentication - if API login details are incorrect
116
+ # @return [integer] Number of messages remaining
117
+ def credit
118
+ xml = Clockwork::XML::Credit.build( self )
119
+ response = Clockwork::HTTP.post( Clockwork::API::CREDIT_URL, xml, @use_ssl )
120
+ credit = Clockwork::XML::Credit.parse( response )
121
+ end
122
+
123
+ # Deliver multiple messages created using Clockwork::API#messages.build.
124
+ # @return [array] Array of Clockwork::SMS::Response objects for messages.
125
+ def deliver
126
+ xml = Clockwork::XML::SMS.build_multiple( self.messages )
127
+ http_response = Clockwork::HTTP.post( Clockwork::API::SMS_URL, xml, @use_ssl )
128
+ responses = Clockwork::XML::SMS.parse_multiple( self.messages, http_response )
129
+ end
130
+
131
+ end
132
+
133
+ end
@@ -0,0 +1,28 @@
1
+ module Clockwork
2
+
3
+ # Module containing Clockwork::Error classes, all of which extend StandardError.
4
+ module Error
5
+
6
+ # @author James Inman <james@mediaburst.co.uk>
7
+ # Raised if the entered authentication details (API key or username and password) are incorrect. (Error code: 2)
8
+ class Authentication < StandardError
9
+ end
10
+
11
+ # @author James Inman <james@mediaburst.co.uk>
12
+ # Raised for all error codes not otherwise specified.
13
+ class Generic < StandardError
14
+ end
15
+
16
+ # @author James Inman <james@mediaburst.co.uk>
17
+ # Raised if a HTTP connection to the API fails.
18
+ class HTTP < StandardError
19
+ end
20
+
21
+ # @author James Inman <james@mediaburst.co.uk>
22
+ # Raised if the API key is in an invalid format.
23
+ class InvalidAPIKey < StandardError
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,40 @@
1
+ module Clockwork
2
+
3
+ # @author James Inman <james@mediaburst.co.uk>
4
+ # Wrapper around NET/HTTP
5
+ class HTTP
6
+
7
+ # Build a HTTP POST request.
8
+ # @param [string] url URL to POST to
9
+ # @param [string] data Body of the POST request.
10
+ # @param [boolean] use_ssl Whether to use SSL when making the request.
11
+ # @return [string] XML data
12
+ def self.post url, data = '', use_ssl = true
13
+ if use_ssl
14
+ uri = URI.parse "https://#{url}"
15
+ req = Net::HTTP::Post.new( uri.path )
16
+
17
+ socket = Net::HTTP.new( uri.host, uri.port )
18
+ socket.use_ssl = true
19
+ socket.verify_mode = OpenSSL::SSL::VERIFY_PEER
20
+ else
21
+ uri = URI.parse "http://#{url}"
22
+ req = Net::HTTP::Post.new( uri.path )
23
+
24
+ socket = Net::HTTP.new( uri.host, uri.port )
25
+ end
26
+
27
+ req.content_type = "text/xml"
28
+ req.body = data
29
+ req.add_field "User-Agent", "Clockwork Ruby Wrapper/#{Clockwork::VERSION}"
30
+
31
+ response = socket.start do |http|
32
+ http.request( req )
33
+ end
34
+
35
+ response
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,39 @@
1
+ module Clockwork
2
+
3
+ # @author James Inman <james@mediaburst.co.uk>
4
+ # Use an instance of Clockwork::API#messages.build to create SMS messages.
5
+ class MessageCollection
6
+
7
+ # @!attribute api
8
+ # An instance of Clockwork::API.
9
+ # @return [Clockwork::API]
10
+ attr_accessor :api
11
+
12
+ # @!attribute messages
13
+ # An array of Clockwork::SMS messages.
14
+ # @return [array]
15
+ attr_accessor :messages
16
+
17
+ # @param [hash] options Hash of attributes which must include an instance of Clockwork::API
18
+ # @raise ArgumentError - if a valid instance of API is not passed as :api in options
19
+ # Create a new instance of Clockwork::MessageCollection.
20
+ def initialize options
21
+ @api = options[:api]
22
+ raise ArgumentError, "Clockwork::MessageCollection#new must include an instance of Clockwork::API as :api" unless @api.kind_of?(Clockwork::API)
23
+
24
+ @messages = []
25
+ end
26
+
27
+ # @param [hash] params Hash of parameters as attributes on Clockwork::SMS
28
+ # @see Clockwork::SMS
29
+ # Create a new instance of Clockwork::SMS in this MessageCollection.
30
+ def build params = {}
31
+ sms = Clockwork::SMS.new({ api: @api }.merge(params))
32
+ sms.wrapper_id = @messages.count
33
+ @messages << sms
34
+ sms
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,95 @@
1
+ module Clockwork
2
+
3
+ # @author James Inman <james@mediaburst.co.uk>
4
+ # Create an instance of Clockwork::SMS for each SMS message you want to send.
5
+ class SMS
6
+
7
+ # @!attribute api
8
+ # An instance of Clockwork::API.
9
+ # @return [Clockwork::API]
10
+ attr_accessor :api
11
+
12
+ # @!attribute content
13
+ # *REQUIRED:* The message content to send.
14
+ # @return [string]
15
+ attr_accessor :content
16
+
17
+ # @!attribute client_id
18
+ # An unique message ID specified by the connecting application, for example your database record ID. Maximum length: 50 characters.
19
+ # @return [string]
20
+ attr_accessor :client_id
21
+
22
+ # @!attribute from
23
+ # The from address displayed on a phone when the SMS is received. This can be either a 12 digit number or 11 characters long.
24
+ # @return [string]
25
+ # @note If this option is set it overrides the global option specified in Clockwork::API for this SMS, if neither option is set your account default will be used.
26
+ attr_accessor :from
27
+
28
+ # @!attribute long
29
+ # Set to +true+ to enable long SMS. A standard text can contain 160 characters, a long SMS supports up to 459. Each recipient will cost up to 3 message credits.
30
+ # @return [boolean]
31
+ # @note If this option is set it overrides the global option specified in Clockwork::API for this SMS, if neither option is set your account default will be used.
32
+ attr_accessor :long
33
+
34
+ # @!attribute truncate
35
+ # Set to +true+ to trim the message content to the maximum length if it is too long.
36
+ # @return [boolean]
37
+ # @note If this option is set it overrides the global option specified in Clockwork::API for this SMS, if neither option is set your account default will be used.
38
+ attr_accessor :truncate
39
+
40
+ # What to do with any invalid characters in the message content. +:error+ will raise a Clockwork::InvalidCharacterException, +:replace+ will replace a small number of common invalid characters, such as the smart quotes used by Microsoft Office with a similar match, +:remove+ will remove invalid characters.
41
+ # @raise ArgumentError - if value is not one of +:error+, +:replace+, +:remove+
42
+ # @return [symbol] One of +error+, +:replace+, +:remove+
43
+ # @note If this option is set it overrides the global option specified in Clockwork::API for this SMS, if neither option is set your account default will be used.
44
+ attr_reader :invalid_char_action
45
+
46
+ # @!attribute to
47
+ # *REQUIRED:* The phone number to send the SMS to in international number format (without a leading + or international dialling prefix such as 00, e.g. 441234567890).
48
+ # @return [string]
49
+ attr_accessor :to
50
+
51
+ attr_writer :wrapper_id
52
+
53
+ def invalid_char_action= symbol
54
+ raise( ArgumentError, "#{symbol} must be one of :error, :replace, :remove" ) unless [:error, :replace, :remove].include?(symbol.to_sym)
55
+ end
56
+
57
+ # @param [hash] options Optional hash of attributes on Clockwork::SMS
58
+ # Create a new SMS message.
59
+ def initialize options = {}
60
+ options.each { |k, v| instance_variable_set "@#{k}", v } if options.kind_of?(Hash)
61
+ end
62
+
63
+ # Deliver the SMS message.
64
+ # @return [Clockwork::SMS::Response] An instance of Clockwork::SMS::Response
65
+ def deliver
66
+ xml = Clockwork::XML::SMS.build_single( self )
67
+ http_response = Clockwork::HTTP.post( Clockwork::API::SMS_URL, xml, @api.use_ssl )
68
+ response = Clockwork::XML::SMS.parse_single( self, http_response )
69
+ end
70
+
71
+ # Translate standard variable names to those needed to make an XML request. First, checks if global variables are set in Clockwork::API then overwrites with variables set in Clockwork::SMS instance.
72
+ # @return [hash] Hash of XML keys and values
73
+ def translated_attributes
74
+ attributes = {}
75
+ translations = []
76
+ translations << { :var => 'client_id', :xml_var => 'ClientID' }
77
+ translations << { :var => 'concat', :xml_var => 'Concat' }
78
+ translations << { :var => 'from', :xml_var => 'From' }
79
+ translations << { :var => 'invalid_char_action', :xml_var => 'InvalidCharAction' }
80
+ translations << { :var => 'content', :xml_var => 'Content' }
81
+ translations << { :var => 'to', :xml_var => 'To' }
82
+ translations << { :var => 'truncate', :xml_var => 'Truncate' }
83
+ translations << { :var => 'wrapper_id', :xml_var => 'WrapperID' }
84
+
85
+ translations.each do |t|
86
+ self.instance_variable_set( "@#{t[:var]}", @api.instance_variable_get( "@#{t[:var]}" ) ) if self.instance_variable_get( "@#{t[:var]}" ).nil?
87
+ attributes[ t[:xml_var] ] = self.instance_variable_get( "@#{t[:var]}" ) unless self.instance_variable_get( "@#{t[:var]}" ).nil?
88
+ end
89
+
90
+ attributes
91
+ end
92
+
93
+ end
94
+
95
+ end
@@ -0,0 +1,39 @@
1
+ module Clockwork
2
+ class SMS
3
+
4
+ # @author James Inman <james@mediaburst.co.uk>
5
+ # A Clockwork::SMS::Response is returned for each SMS sent by Clockwork::SMS#deliver.
6
+ class Response
7
+
8
+ # @!attribute error_code
9
+ # The error code returned if the SMS fails.
10
+ # @return [string]
11
+ attr_accessor :error_code
12
+
13
+ # @!attribute error_description
14
+ # The error description returned if the SMS fails.
15
+ # @return [string]
16
+ attr_accessor :error_description
17
+
18
+ # @!attribute message_id
19
+ # The message ID returned if the SMS is sent successfully.
20
+ # @return [string]
21
+ attr_accessor :message_id
22
+
23
+ # @!attribute message
24
+ # The instance of Clockwork::SMS relating to this response.
25
+ # @return [Clockwork::SMS]
26
+ attr_accessor :message
27
+
28
+ # @!attribute success
29
+ # +true+ if the SMS is sent successfully, +false+ otherwise.
30
+ # @return [boolean]
31
+ attr_accessor :success
32
+
33
+ def error_code
34
+ @error_code.to_i unless @error_code.nil?
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,49 @@
1
+ module Clockwork
2
+ module XML
3
+
4
+ # @author James Inman <james@mediaburst.co.uk>
5
+ # XML building and parsing for checking credit.
6
+ class Credit
7
+
8
+ # Build the XML data to check the credit from the XML API.
9
+ # @param [Clockwork::API] api Instance of Clockwork::API
10
+ # @return [string] XML data
11
+ def self.build api
12
+ builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
13
+ xml.Credit {
14
+ if api.api_key
15
+ xml.Key api.api_key
16
+ else
17
+ xml.Username api.username
18
+ xml.Password api.password
19
+ end
20
+ }
21
+ end
22
+ builder.to_xml
23
+ end
24
+
25
+ # Parse the XML response.
26
+ # @param [Net::HTTPResponse] response Instance of Net::HTTPResponse
27
+ # @raise Clockwork:HTTPError - if a connection to the Clockwork API cannot be made
28
+ # @raise Clockwork::Error::Generic - if the API returns an error code other than 2
29
+ # @raise Clockwork::Error::Authentication - if API login details are incorrect
30
+ # @return [string] Number of remaining credits
31
+ def self.parse response
32
+ if response.code.to_i == 200
33
+ doc = Nokogiri.parse( response.body )
34
+ if doc.css('ErrDesc').empty?
35
+ doc.css('Credit').inner_html.to_i
36
+ elsif doc.css('ErrNo').inner_html.to_i == 2
37
+ raise Clockwork::Error::Authentication, doc.css('ErrDesc').inner_html
38
+ else
39
+ raise Clockwork::Error::Generic, doc.css('ErrDesc').inner_html
40
+ end
41
+ else
42
+ raise Clockwork::Error::HTTP, "Could not connect to the Clockwork API to check credit."
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,114 @@
1
+ module Clockwork
2
+ module XML
3
+
4
+ # @author James Inman <james@mediaburst.co.uk>
5
+ # XML building and parsing for sending SMS messages.
6
+ class SMS
7
+
8
+ # Build the XML data to send a single SMS using the XML API.
9
+ # @param [Clockwork::SMS] sms Instance of Clockwork::SMS
10
+ # @return [string] XML data
11
+ def self.build_single sms
12
+ builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
13
+ xml.Message {
14
+ if sms.api.api_key
15
+ xml.Key sms.api.api_key
16
+ else
17
+ xml.Username sms.api.username
18
+ xml.Password sms.api.password
19
+ end
20
+ xml.SMS {
21
+ sms.translated_attributes.each do |k, v|
22
+ xml.send "#{k}", v
23
+ end
24
+ }
25
+ }
26
+ end
27
+ builder.to_xml
28
+ end
29
+
30
+ # Build the XML data to send multiple SMS messages using the XML API.
31
+ # @param [Clockwork::MessageCollection] collection Instance of Clockwork::SMS
32
+ # @return [string] XML data
33
+ def self.build_multiple collection
34
+ builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
35
+ xml.Message {
36
+ if collection.api.api_key
37
+ xml.Key collection.api.api_key
38
+ else
39
+ xml.Username collection.api.username
40
+ xml.Password collection.api.password
41
+ end
42
+ collection.messages.each do |sms|
43
+ xml.SMS {
44
+ sms.translated_attributes.each do |k, v|
45
+ xml.send "#{k}", v
46
+ end
47
+ }
48
+ end
49
+ }
50
+ end
51
+ builder.to_xml
52
+ end
53
+
54
+ # Parse the XML data from a single SMS response from the XML API.
55
+ # @param [Clockwork::SMS] sms Instance of Clockwork::SMS
56
+ # @param [Net::HTTPResponse] http_response Instance of Net:HTTPResponse
57
+ # @raise Clockwork:HTTPError - if a connection to the Clockwork API cannot be made
58
+ # @return [Clockwork::SMS::Response] Instance of Clockwork::SMS::Response for the message
59
+ def self.parse_single sms, http_response
60
+ response = Clockwork::SMS::Response.new
61
+ response.message = sms
62
+
63
+ if http_response.code.to_i == 200
64
+ doc = Nokogiri.parse( http_response.body )
65
+ if doc.css('ErrDesc').empty?
66
+ response.success = true
67
+ response.message_id = doc.css('MessageID').inner_html
68
+ else
69
+ response.success = false
70
+ response.error_code = doc.css('ErrNo').inner_html.to_i
71
+ response.error_description = doc.css('ErrDesc').inner_html
72
+ end
73
+ else
74
+ raise Clockwork::Error::HTTP, "Could not connect to the Clockwork API to send SMS."
75
+ end
76
+
77
+ response
78
+ end
79
+
80
+ # Parse the XML data from a multiple SMS response from the XML API.
81
+ # @param [Clockwork::MessageCollection] collection Instance of Clockwork::SMS
82
+ # @param [Net::HTTPResponse] http_response Instance of Net:HTTPResponse
83
+ # @raise Clockwork:HTTPError - if a connection to the Clockwork API cannot be made
84
+ # @return [array] Array of Clockwork::SMS::Response objects relating to the messages
85
+ def self.parse_multiple collection, http_response
86
+ responses = []
87
+
88
+ if http_response.code.to_i == 200
89
+ doc = Nokogiri.parse( http_response.body )
90
+ else
91
+ raise Clockwork::Error::HTTP, "Could not connect to the Clockwork API to send SMS."
92
+ end
93
+
94
+ doc.css('SMS_Resp').each_with_index do |sms_response, i|
95
+ response = Clockwork::SMS::Response.new
96
+ response.message = collection.messages[i]
97
+ if sms_response.css('ErrDesc').empty?
98
+ response.success = true
99
+ response.message_id = sms_response.css('MessageID').inner_html
100
+ else
101
+ response.success = false
102
+ response.error_code = sms_response.css('ErrNo').inner_html.to_i
103
+ response.error_description = sms_response.css('ErrDesc').inner_html
104
+ end
105
+ responses[sms_response.css('WrapperID').inner_html.to_i] = response
106
+ end
107
+
108
+ responses
109
+ end
110
+
111
+ end
112
+
113
+ end
114
+ end
@@ -0,0 +1,17 @@
1
+ require 'nokogiri'
2
+
3
+ module Clockwork
4
+
5
+ # @author James Inman <james@mediaburst.co.uk>
6
+ # Wrapper for the XML builder/parser
7
+ module XML
8
+ end
9
+
10
+ end
11
+
12
+ # Require everything in this directory
13
+ dir_path = File.dirname(__FILE__)
14
+ Dir["#{dir_path}/*.rb"].each do |file|
15
+ next if file =~ /xml.rb$/
16
+ require file
17
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clockworksms
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mediaburst
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake-compiler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: Ruby Gem for the Clockwork API. Send text messages with the easy to use
47
+ SMS API from Mediaburst.
48
+ email: hello@mediaburst.co.uk
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - lib/clockwork/api.rb
54
+ - lib/clockwork/error.rb
55
+ - lib/clockwork/http.rb
56
+ - lib/clockwork/message_collection.rb
57
+ - lib/clockwork/sms/response.rb
58
+ - lib/clockwork/sms.rb
59
+ - lib/clockwork/xml/credit.rb
60
+ - lib/clockwork/xml/sms.rb
61
+ - lib/clockwork/xml/xml.rb
62
+ - lib/clockwork.rb
63
+ - Gemfile
64
+ - Gemfile.lock
65
+ - LICENSE
66
+ - README.md
67
+ homepage: http://www.clockworksms.com/
68
+ licenses: []
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubyforge_project:
87
+ rubygems_version: 1.8.24
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: Ruby Gem for the Clockwork API.
91
+ test_files: []