ruby-transmitsms 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.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +49 -0
  4. data/LICENSE +22 -0
  5. data/README.md +62 -0
  6. data/Rakefile +7 -0
  7. data/fixtures/vcr_cassettes/account_api_get_balance.yml +49 -0
  8. data/fixtures/vcr_cassettes/email_sms_api_add_email.yml +49 -0
  9. data/fixtures/vcr_cassettes/email_sms_api_delete_email.yml +49 -0
  10. data/fixtures/vcr_cassettes/keywords_api_add_keyword.yml +49 -0
  11. data/fixtures/vcr_cassettes/keywords_api_edit_keyword.yml +49 -0
  12. data/fixtures/vcr_cassettes/keywords_api_get_keywords.yml +50 -0
  13. data/fixtures/vcr_cassettes/lists_api_add_list.yml +49 -0
  14. data/fixtures/vcr_cassettes/lists_api_add_to_list.yml +50 -0
  15. data/fixtures/vcr_cassettes/lists_api_delete_from_list.yml +49 -0
  16. data/fixtures/vcr_cassettes/lists_api_edit_list_member.yml +50 -0
  17. data/fixtures/vcr_cassettes/lists_api_get_list.yml +60 -0
  18. data/fixtures/vcr_cassettes/lists_api_get_lists.yml +61 -0
  19. data/fixtures/vcr_cassettes/lists_api_optout_list_member.yml +49 -0
  20. data/fixtures/vcr_cassettes/lists_api_remove_list.yml +49 -0
  21. data/fixtures/vcr_cassettes/numbers_api_get_number.yml +49 -0
  22. data/fixtures/vcr_cassettes/numbers_api_get_numbers.yml +49 -0
  23. data/fixtures/vcr_cassettes/numbers_api_lease_number.yml +50 -0
  24. data/fixtures/vcr_cassettes/resellers_api_add_client.yml +49 -0
  25. data/fixtures/vcr_cassettes/resellers_api_edit_client.yml +40 -0
  26. data/fixtures/vcr_cassettes/resellers_api_get_client.yml +50 -0
  27. data/fixtures/vcr_cassettes/resellers_api_get_clients.yml +59 -0
  28. data/fixtures/vcr_cassettes/resellers_api_get_transaction.yml +51 -0
  29. data/fixtures/vcr_cassettes/resellers_api_get_transactions.yml +61 -0
  30. data/fixtures/vcr_cassettes/sms_api_test_cancel_sms.yml +50 -0
  31. data/fixtures/vcr_cassettes/sms_api_test_format_number.yml +49 -0
  32. data/fixtures/vcr_cassettes/sms_api_test_format_number_fail_in_missing_msisdn.yml +50 -0
  33. data/fixtures/vcr_cassettes/sms_api_test_get_message_log.yml +50 -0
  34. data/fixtures/vcr_cassettes/sms_api_test_get_sms_info.yml +49 -0
  35. data/fixtures/vcr_cassettes/sms_api_test_get_sms_info_fail_for_not_existing_message_id.yml +50 -0
  36. data/fixtures/vcr_cassettes/sms_api_test_get_sms_responses.yml +53 -0
  37. data/fixtures/vcr_cassettes/sms_api_test_get_sms_sent.yml +50 -0
  38. data/fixtures/vcr_cassettes/sms_api_test_get_user_sms_responses.yml +49 -0
  39. data/fixtures/vcr_cassettes/sms_api_test_message_reply.yml +49 -0
  40. data/fixtures/vcr_cassettes/sms_api_test_send.yml +49 -0
  41. data/fixtures/vcr_cassettes/sms_api_test_send_missing_to_and_list_id.yml +50 -0
  42. data/fixtures/vcr_cassettes/sms_api_test_send_with_list_id.yml +50 -0
  43. data/geminstall.sh +1 -0
  44. data/lib/account_api.rb +80 -0
  45. data/lib/email_api.rb +137 -0
  46. data/lib/keywords_api.rb +224 -0
  47. data/lib/lists_api.rb +523 -0
  48. data/lib/monkey.rb +90 -0
  49. data/lib/numbers_api.rb +188 -0
  50. data/lib/resellers_api.rb +379 -0
  51. data/lib/ruby-transmitsms.rb +16 -0
  52. data/lib/sms_api.rb +550 -0
  53. data/lib/swagger.rb +84 -0
  54. data/lib/swagger/configuration.rb +22 -0
  55. data/lib/swagger/request.rb +212 -0
  56. data/lib/swagger/response.rb +70 -0
  57. data/lib/swagger/version.rb +4 -0
  58. data/ruby-transmitsms.gemspec +33 -0
  59. data/runtest.sh +8 -0
  60. data/setup.sh +1 -0
  61. data/spec/.resellers_api_spec.rb.swp +0 -0
  62. data/spec/account_api_spec.rb +30 -0
  63. data/spec/email_sms_api_spec.rb +40 -0
  64. data/spec/keywords_api_spec.rb +56 -0
  65. data/spec/lists_api_spec.rb +117 -0
  66. data/spec/numbers_api_spec.rb +53 -0
  67. data/spec/resellers_api_spec.rb +85 -0
  68. data/spec/sms_api_spec.rb +174 -0
  69. data/spec/spec.opts +4 -0
  70. metadata +219 -0
@@ -0,0 +1,84 @@
1
+ require 'monkey'
2
+ require 'swagger/configuration'
3
+ require 'swagger/request'
4
+ require 'swagger/response'
5
+ require 'swagger/version'
6
+ require 'logger'
7
+
8
+ module Swagger
9
+
10
+ class << self
11
+ attr_accessor :logger
12
+
13
+ # A Swagger configuration object. Must act like a hash and return sensible
14
+ # values for all Swagger configuration options. See Swagger::Configuration.
15
+ attr_accessor :configuration
16
+
17
+ attr_accessor :resources
18
+
19
+ # Call this method to modify defaults in your initializers.
20
+ #
21
+ # @example
22
+ # Swagger.configure do |config|
23
+ # config.api_key = '1234567890abcdef' # required
24
+ # config.username = 'wordlover' # optional, but needed for user-related functions
25
+ # config.password = 'i<3words' # optional, but needed for user-related functions
26
+ # config.format = 'json' # optional, defaults to 'json'
27
+ # end
28
+ #
29
+ def configure
30
+ self.configuration ||= Configuration.new
31
+ yield(configuration) if block_given?
32
+
33
+ # Configure logger. Default to use Rails
34
+ self.logger ||= configuration.logger || (defined?(Rails) ? Rails.logger : Logger.new(STDOUT))
35
+
36
+ # remove :// from scheme
37
+ configuration.scheme.sub!(/:\/\//, '')
38
+
39
+ # remove http(s):// and anything after a slash
40
+ configuration.host.sub!(/https?:\/\//, '')
41
+ configuration.host = configuration.host.split('/').first
42
+
43
+ # Add leading and trailing slashes to base_path
44
+ configuration.base_path = "/#{configuration.base_path}".gsub(/\/+/, '/')
45
+ configuration.base_path = "" if configuration.base_path == "/"
46
+ end
47
+
48
+ def authenticated?
49
+ Swagger.configuration.auth_token.present?
50
+ end
51
+
52
+ def de_authenticate
53
+ Swagger.configuration.auth_token = nil
54
+ end
55
+
56
+ def authenticate
57
+ return if Swagger.authenticated?
58
+
59
+ if Swagger.configuration.username.blank? || Swagger.configuration.password.blank?
60
+ raise ClientError, "Username and password are required to authenticate."
61
+ end
62
+
63
+ request = Swagger::Request.new(
64
+ :get,
65
+ "account/authenticate/{username}",
66
+ :params => {
67
+ :username => Swagger.configuration.username,
68
+ :password => Swagger.configuration.password
69
+ }
70
+ )
71
+
72
+ response_body = request.response.body
73
+ Swagger.configuration.auth_token = response_body['token']
74
+ end
75
+
76
+ end
77
+
78
+ end
79
+
80
+ class ServerError < StandardError
81
+ end
82
+
83
+ class ClientError < StandardError
84
+ end
@@ -0,0 +1,22 @@
1
+ module Swagger
2
+
3
+ class Configuration
4
+ require 'swagger/version'
5
+
6
+ attr_accessor :format, :api_key, :username, :password, :auth_token, :scheme, :host, :base_path, :user_agent, :logger, :inject_format, :force_ending_format, :camelize_params, :user_agent
7
+
8
+ # Defaults go in here..
9
+ def initialize
10
+ @format = 'json'
11
+ @scheme = 'http'
12
+ @host = 'petstore.swagger.io'
13
+ @base_path = '/v2'
14
+ @user_agent = "ruby-swagger-#{Swagger::VERSION}"
15
+ @inject_format = false
16
+ @force_ending_format = false
17
+ @camelize_params = true
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,212 @@
1
+ module Swagger
2
+
3
+ class Request
4
+ require 'uri'
5
+ require 'addressable/uri'
6
+ require 'typhoeus'
7
+ require "swagger/version"
8
+
9
+ attr_accessor :host, :path, :format, :params, :body, :http_method, :headers, :form_params
10
+
11
+
12
+ # All requests must have an HTTP method and a path
13
+ # Optionals parameters are :params, :headers, :body, :format, :host
14
+ #
15
+ def initialize(http_method, path, attributes={})
16
+ attributes[:format] ||= Swagger.configuration.format
17
+ attributes[:params] ||= {}
18
+
19
+ # Set default headers
20
+ default_headers = {
21
+ 'Content-Type' => "application/#{attributes[:format].downcase}",
22
+ :api_key => Swagger.configuration.api_key,
23
+ 'User-Agent' => Swagger.configuration.user_agent
24
+ }
25
+
26
+ # api_key from headers hash trumps the default, even if its value is blank
27
+ if attributes[:headers].present? && attributes[:headers].has_key?(:api_key)
28
+ default_headers.delete(:api_key)
29
+ end
30
+
31
+ # api_key from params hash trumps all others (headers and default_headers)
32
+ if attributes[:params].present? && attributes[:params].has_key?(:api_key)
33
+ default_headers.delete(:api_key)
34
+ attributes[:headers].delete(:api_key) if attributes[:headers].present?
35
+ end
36
+
37
+ # Merge argument headers into defaults
38
+ attributes[:headers] = default_headers.merge(attributes[:headers] || {})
39
+
40
+ # Stick in the auth token if there is one
41
+ if Swagger.authenticated?
42
+ attributes[:headers].merge!({:auth_token => Swagger.configuration.auth_token})
43
+ end
44
+
45
+ self.http_method = http_method.to_sym
46
+ self.path = path
47
+ attributes.each do |name, value|
48
+ send("#{name.to_s.underscore.to_sym}=", value)
49
+ end
50
+ end
51
+
52
+ # Construct a base URL
53
+ #
54
+ def url(options = {})
55
+ u = Addressable::URI.new(
56
+ :scheme => Swagger.configuration.scheme,
57
+ :host => Swagger.configuration.host,
58
+ :path => self.interpreted_path,
59
+ :query => self.query_string.sub(/\?/, '')
60
+ ).to_s
61
+
62
+ # Drop trailing question mark, if present
63
+ u.sub! /\?$/, ''
64
+
65
+ # Obfuscate API key?
66
+ u.sub! /api\_key=\w+/, 'api_key=YOUR_API_KEY' if options[:obfuscated]
67
+
68
+ u
69
+ end
70
+
71
+ # Iterate over the params hash, injecting any path values into the path string
72
+ #
73
+ # e.g. /word.{format}/{word}/entries => /word.json/cat/entries
74
+ def interpreted_path
75
+ p = self.path.dup
76
+
77
+ # Stick a .{format} placeholder into the path if there isn't
78
+ # one already or an actual format like json or xml
79
+ # e.g. /words/blah => /words.{format}/blah
80
+ if Swagger.configuration.inject_format
81
+ unless ['.json', '.xml', '{format}'].any? {|s| p.downcase.include? s }
82
+ p = p.sub(/^(\/?\w+)/, "\\1.#{format}")
83
+ end
84
+ end
85
+
86
+ # Stick a .{format} placeholder on the end of the path if there isn't
87
+ # one already or an actual format like json or xml
88
+ # e.g. /words/blah => /words/blah.{format}
89
+ if Swagger.configuration.force_ending_format
90
+ unless ['.json', '.xml', '{format}'].any? {|s| p.downcase.include? s }
91
+ p = "#{p}.#{format}"
92
+ end
93
+ end
94
+
95
+ p = p.sub("{format}", self.format.to_s)
96
+
97
+ URI.encode [Swagger.configuration.base_path, p].join("/").gsub(/\/+/, '/')
98
+ end
99
+
100
+ # Massage the request body into a state of readiness
101
+ # If body is a hash, camelize all keys then convert to a json string
102
+ #
103
+ def body=(value)
104
+ if value.is_a?(Hash)
105
+ value = value.inject({}) do |memo, (k,v)|
106
+ memo[k.to_s.camelize(:lower).to_sym] = v
107
+ memo
108
+ end
109
+ end
110
+ @body = value
111
+ end
112
+
113
+ # If body is an object, JSONify it before making the actual request.
114
+ # For form parameters, remove empty value
115
+ def outgoing_body
116
+ # http form
117
+ if @body.nil? && @form_params && !@form_params.empty?
118
+ data = form_params.dup
119
+ data.each do |key, value|
120
+ data[key] = value.to_s if value && !value.is_a?(File) # remove emtpy form parameter
121
+ end
122
+ data
123
+ else # http body is JSON
124
+ @body.is_a?(String) ? @body : @body.to_json
125
+ end
126
+ end
127
+
128
+ # Construct a query string from the query-string-type params
129
+ def query_string
130
+
131
+ # Iterate over all params,
132
+ # .. removing the ones that are part of the path itself.
133
+ # .. stringifying values so Addressable doesn't blow up.
134
+ query_values = {}
135
+ self.params.each_pair do |key, value|
136
+ next if self.path.include? "{#{key}}" # skip path params
137
+ next if value.blank? && value.class != FalseClass # skip empties
138
+ if Swagger.configuration.camelize_params
139
+ key = key.to_s.camelize(:lower).to_sym unless key.to_sym == :api_key # api_key is not a camelCased param
140
+ end
141
+ query_values[key] = value.to_s
142
+ end
143
+
144
+ # We don't want to end up with '?' as our query string
145
+ # if there aren't really any params
146
+ return "" if query_values.blank?
147
+
148
+ # Addressable requires query_values to be set after initialization..
149
+ qs = Addressable::URI.new
150
+ qs.query_values = query_values
151
+ qs.to_s
152
+ end
153
+
154
+ def make
155
+ #TODO use configuration setting to determine if debugging
156
+ #logger = Logger.new STDOUT
157
+ #logger.debug self.url
158
+ response = case self.http_method.to_sym
159
+ when :get,:GET
160
+ Typhoeus::Request.get(
161
+ self.url,
162
+ :headers => self.headers.stringify_keys,
163
+ )
164
+
165
+ when :post,:POST
166
+ Typhoeus::Request.post(
167
+ self.url,
168
+ :body => self.outgoing_body,
169
+ :headers => self.headers.stringify_keys,
170
+ )
171
+
172
+ when :patch,:PATCH
173
+ Typhoeus::Request.patch(
174
+ self.url,
175
+ :body => self.outgoing_body,
176
+ :headers => self.headers.stringify_keys,
177
+ )
178
+
179
+ when :put,:PUT
180
+ Typhoeus::Request.put(
181
+ self.url,
182
+ :body => self.outgoing_body,
183
+ :headers => self.headers.stringify_keys,
184
+ )
185
+
186
+ when :delete,:DELETE
187
+ Typhoeus::Request.delete(
188
+ self.url,
189
+ :body => self.outgoing_body,
190
+ :headers => self.headers.stringify_keys,
191
+ )
192
+ end
193
+ Response.new(response)
194
+ end
195
+
196
+ def response
197
+ self.make
198
+ end
199
+
200
+ def response_code_pretty
201
+ return unless @response.present?
202
+ @response.code.to_s
203
+ end
204
+
205
+ def response_headers_pretty
206
+ return unless @response.present?
207
+ # JSON.pretty_generate(@response.headers).gsub(/\n/, '<br/>') # <- This was for RestClient
208
+ @response.headers.gsub(/\n/, '<br/>') # <- This is for Typhoeus
209
+ end
210
+
211
+ end
212
+ end
@@ -0,0 +1,70 @@
1
+ module Swagger
2
+
3
+ class Response
4
+ require 'json'
5
+
6
+ attr_accessor :raw
7
+
8
+ def initialize(raw)
9
+ self.raw = raw
10
+
11
+ # case self.code
12
+ # when 500..510 then raise(ServerError, self.error_message)
13
+ # when 299..426 then raise(ClientError, self.error_message)
14
+ # end
15
+ end
16
+
17
+ def code
18
+ raw.code
19
+ end
20
+
21
+ # Account for error messages that take different forms...
22
+ def error_message
23
+ body['message']
24
+ rescue
25
+ body
26
+ end
27
+
28
+ # If body is JSON, parse it
29
+ # Otherwise return raw string
30
+ def body
31
+ JSON.parse raw.body
32
+ rescue
33
+ raw.body
34
+ end
35
+
36
+ # `headers_hash` is a Typhoeus-specific extension of Hash,
37
+ # so simplify it back into a regular old Hash.
38
+ def headers
39
+ h = {}
40
+ raw.headers_hash.each {|k,v| h[k] = v }
41
+ h
42
+ end
43
+
44
+ # Extract the response format from the header hash
45
+ # e.g. {'Content-Type' => 'application/json'}
46
+ def format
47
+ headers['Content-Type'].split("/").last.downcase
48
+ end
49
+
50
+ def json?
51
+ format == 'json'
52
+ end
53
+
54
+ def xml?
55
+ format == 'xml'
56
+ end
57
+
58
+ def pretty_body
59
+ return unless body.present?
60
+ case format
61
+ when 'json' then JSON.pretty_generate(body).gsub(/\n/, '<br/>')
62
+ end
63
+ end
64
+
65
+ def pretty_headers
66
+ JSON.pretty_generate(headers).gsub(/\n/, '<br/>')
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,4 @@
1
+ module Swagger
2
+ VERSION = "4.06.08"
3
+ end
4
+
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #$:.push File.expand_path("../lib", __FILE__)
3
+ #require "swagger/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.metadata["allowed_push_host"] = "https://rubygems.org"
7
+
8
+ s.name = "ruby-transmitsms"
9
+ s.version = "0.0.1"
10
+ s.authors = ["Jeremiah John Macariola"]
11
+ s.email = ["maiah@burstsms.com"]
12
+ s.homepage = "http://burstsms.com.au"
13
+ s.summary = "Ruby SDK"
14
+ s.description = "Ruby gem to easily access TransmitSMS RESTful APIs"
15
+
16
+ s.add_runtime_dependency 'typhoeus', '>=0.2.1'
17
+ s.add_runtime_dependency 'addressable', '>=2.2.4'
18
+ s.add_runtime_dependency 'json', '>=1.4.6'
19
+
20
+ s.add_development_dependency 'rspec', '>=2.5.0'
21
+ s.add_development_dependency 'rspec-mocks'
22
+ s.add_development_dependency 'vcr', '>=2.9.3'
23
+ s.add_development_dependency 'webmock', '>=1.21.0'
24
+ # s.add_development_dependency 'autotest'
25
+ # s.add_development_dependency 'autotest-rails-pure'
26
+ # s.add_development_dependency 'autotest-growl'
27
+ # s.add_development_dependency 'autotest-fsevent'
28
+
29
+ s.files = `find *`.split("\n").uniq.sort.select{|f| !f.empty? }
30
+ s.test_files = `find spec/*`.split("\n")
31
+ s.executables = []
32
+ s.require_paths = ["lib", "models"]
33
+ end
@@ -0,0 +1,8 @@
1
+ #bundle exec rspec
2
+ ruby spec/sms_api_spec.rb
3
+ ruby spec/numbers_api_spec.rb
4
+ ruby spec/email_sms_api_spec.rb
5
+ ruby spec/account_api_spec.rb
6
+ ruby spec/keywords_api_spec.rb
7
+ ruby spec/lists_api_spec.rb
8
+ ruby spec/resellers_api_spec.rb
@@ -0,0 +1 @@
1
+ bundle install
@@ -0,0 +1,30 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+ require "ruby-transmitsms"
4
+ require "test/unit"
5
+ require "vcr"
6
+
7
+ VCR.configure do |c|
8
+ c.cassette_library_dir = "fixtures/vcr_cassettes"
9
+ c.hook_into :webmock
10
+ end
11
+
12
+ class AccountApiTest < Test::Unit::TestCase
13
+
14
+ def setup()
15
+ @api = AccountApi.new("15ad266c538fb36c4d90f01055aef494", "moose")
16
+ end
17
+
18
+ def test_get_balance()
19
+ VCR.use_cassette("account_api_get_balance") do
20
+ response = @api.get_balance()
21
+
22
+ assert response.code == 200
23
+ assert response.body["balance"] > 0.00
24
+ assert response.body["currency"] == "SGD"
25
+ assert response.body["error"]["code"] == "SUCCESS"
26
+ assert response.body["error"]["description"] == "OK"
27
+ end
28
+ end
29
+
30
+ end