simplesol 0.0.2

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/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rvmrc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in simplesol.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Askar Zinurov
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # Simplesol
2
+ Client gem for sms sending through http://simplesol.ru/.
3
+
4
+ ## Installation
5
+
6
+ Add this line to your application's Gemfile:
7
+
8
+ gem 'simplesol'
9
+
10
+ And then execute:
11
+
12
+ $ bundle
13
+
14
+ Or install it yourself as:
15
+
16
+ $ gem install simplesol
17
+
18
+ ## Usage
19
+ Configure
20
+
21
+ Instantiate Client class with some config:
22
+
23
+ ```ruby
24
+ @client = Simplesol::Client.new do |c|
25
+ c.login = '<your username>'
26
+ c.api_key = '<your api key>'
27
+ end
28
+ ```
29
+ or configure client later:
30
+ ```ruby
31
+ @client = Simplesol::Client.new
32
+ @client.configure do |c|
33
+ c.login = '<your username>'
34
+ c.api_key = '<your api key>'
35
+ end
36
+ ```
37
+ or reset clients settings to defaults via:
38
+ ```ruby
39
+ @client.reset
40
+ ```
41
+ Available commands
42
+
43
+ - Sending message:
44
+
45
+ ```ruby
46
+ @client.send_message(['mobile1', 'mobile2'], 'Привет, как дела', { :sender => 'santa' })
47
+ ```
48
+
49
+ - Get sms message status:
50
+
51
+ ```ruby
52
+ @client.message_status(['message id'])
53
+ ```
54
+
55
+ - Get cost of message:
56
+
57
+ ```ruby
58
+ @client.message_price(['mobile1', 'mobile2'], 'Привет, как дела')
59
+ ```
60
+
61
+ - Check account balance:
62
+
63
+ ```ruby
64
+ @client.balance
65
+ ```
66
+ For futher reading and testing please look at spec/simplesol_spec.rb
67
+
68
+ Tested with ruby-1.8.7-p370 and ruby-1.9.3-p327.
69
+
70
+ ## Contributing
71
+
72
+ 1. Fork it
73
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
74
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
75
+ 4. Push to the branch (`git push origin my-new-feature`)
76
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,67 @@
1
+ require 'hashie'
2
+ require 'digest/md5'
3
+ require 'digest/sha1'
4
+
5
+ module Simplesol
6
+ class Client
7
+ include Configuration
8
+
9
+ attr_reader :connection
10
+
11
+ def initialize
12
+ reset
13
+ configure { yield(self) } if block_given?
14
+
15
+ @connection = Faraday::Connection.new(:url => api_server) do |c|
16
+ c.request :url_encoded
17
+ c.response :rashify
18
+ c.response :dates
19
+ c.response :json
20
+
21
+ c.adapter Faraday.default_adapter
22
+ end
23
+ end
24
+
25
+ def balance
26
+ call('user/balance')
27
+ end
28
+
29
+ # Message Functions
30
+
31
+ # param:recipients is array of mobile phones strings
32
+ # param:message is text of sms message
33
+ # options: {:sender => 'Sender', :test => 0}, :test can be 0, 1
34
+ def send_message(recipients, message, options = {})
35
+ call('message/send', { :recipients => recipients.join(','), :message => message }.merge(options))
36
+ end
37
+
38
+ # param:messages_id array of messages ids
39
+ def message_status(messages_id)
40
+ call('message/status', { :messages_id => messages_id.join(',') })
41
+ end
42
+
43
+ # param:recipients is array of mobile phones strings
44
+ # param:message is text of sms message
45
+ def message_price(recipients, message)
46
+ call('message/price', { :recipients => recipients.join(','), :message => message })
47
+ end
48
+
49
+ private
50
+
51
+ def call(url, params = {})
52
+ raise Simplesol::NotConfiguredError.new unless configured?
53
+ signed_params = params.merge(calculate_sign(params))
54
+ signed_params.merge!(:user => login)
55
+ response = connection.post(url, signed_params).body
56
+ raise Simplesol::Error.parse(response) if response.status == 'error'
57
+ response
58
+ end
59
+
60
+ def calculate_sign(params)
61
+ str = [login]
62
+ params.keys.map(&:to_s).sort.each {|k| str << params[k.to_sym] }
63
+ str << api_key
64
+ { :sign => Digest::MD5.hexdigest(Digest::SHA1.hexdigest(str.compact.join(''))) }
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,35 @@
1
+ require 'digest/md5'
2
+
3
+ module Simplesol
4
+ module Configuration
5
+ VALID_OPTIONS_KEYS = [:login, :api_key, :debug, :api_server]
6
+
7
+ DEFAULT_LOGIN = nil
8
+ DEFAULT_API_KEY = nil
9
+ DEFAULT_DEBUG = true
10
+ DEFAULT_API_SERVER = 'http://api.gosmsinfo.ru/api'
11
+
12
+ attr_accessor *VALID_OPTIONS_KEYS
13
+
14
+ def configured?
15
+ status = login && api_key && api_server
16
+ !(status.nil? || status.empty?)
17
+ end
18
+
19
+ def configure
20
+ yield self
21
+ end
22
+
23
+ def options
24
+ VALID_OPTIONS_KEYS.inject({}) do |option, key|
25
+ option.merge!(key => send(key))
26
+ end
27
+ end
28
+
29
+ def reset
30
+ VALID_OPTIONS_KEYS.each do |key|
31
+ send("#{key}=", Simplesol::Configuration.const_get("default_#{key}".upcase))
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,42 @@
1
+ module Simplesol
2
+ class NotConfiguredError < Exception
3
+ def initialize
4
+ @message = 'You have not provided Simplesol api settings: login or api_key'
5
+ end
6
+ end
7
+
8
+ class Error < Exception
9
+ attr_reader :code
10
+
11
+ def initialize(response)
12
+ @code = response.error
13
+ @message = response.message
14
+ end
15
+
16
+ def self.parse(response)
17
+ if response.error
18
+ Simplesol::ERRORS[response.error-1].new response
19
+ else
20
+ Exception.new('error cannot be parsed')
21
+ end
22
+ end
23
+ end
24
+
25
+ class InvalidUserError < Error
26
+ end
27
+
28
+ class InvalidSignatureError < Error
29
+ end
30
+
31
+ class EmptyMessageError < Error
32
+ end
33
+
34
+ class IncorrectRecipientsListError < Error
35
+ end
36
+
37
+ class NotEnoughMoneyError < Error
38
+ end
39
+
40
+ ERRORS = [InvalidUserError, InvalidSignatureError, EmptyMessageError,
41
+ IncorrectRecipientsListError, NotEnoughMoneyError]
42
+ end
@@ -0,0 +1,3 @@
1
+ module Simplesol
2
+ VERSION = "0.0.2"
3
+ end
data/lib/simplesol.rb ADDED
@@ -0,0 +1,13 @@
1
+ require "faraday"
2
+ require "faraday_middleware"
3
+ require "simplesol/version"
4
+ require "simplesol/errors"
5
+ require "simplesol/configuration"
6
+ require "simplesol/client"
7
+
8
+ module Simplesol
9
+ def debug_message(obj, message)
10
+ p "#{obj.is_a?(Class) ? obj.name : obj.class.name}> #{message}"
11
+ end
12
+ module_function :debug_message
13
+ end
data/simplesol.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'simplesol/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "simplesol"
8
+ gem.version = Simplesol::VERSION
9
+ gem.authors = ["Askar Zinurov"]
10
+ gem.email = ["mail@asktim.ru"]
11
+ gem.description = %q{SimpleSol service client gem}
12
+ gem.summary = %q{Gem for working with sms.simplesol.ru}
13
+ gem.homepage = "https://github.com/AskarZinurov/simplesol"
14
+
15
+ gem.add_development_dependency 'bundler'
16
+ gem.add_development_dependency 'rspec'
17
+ gem.add_development_dependency 'vcr'
18
+ gem.add_development_dependency 'webmock'
19
+ gem.add_runtime_dependency 'faraday'
20
+ gem.add_runtime_dependency 'faraday_middleware'
21
+ gem.add_runtime_dependency 'hashie'
22
+ gem.add_runtime_dependency 'rash'
23
+
24
+ gem.files = `git ls-files`.split($/)
25
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
26
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
27
+ gem.require_paths = ["lib"]
28
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'simplesol'
2
+ require 'rspec'
3
+ require 'vcr'
4
+
5
+ RSpec.configure do |c|
6
+ c.extend VCR::RSpec::Macros
7
+ end
8
+
9
+ VCR.configure do |c|
10
+ c.cassette_library_dir = 'spec/vcr_cassettes'
11
+ c.hook_into :webmock
12
+ c.default_cassette_options = { :record => :new_episodes }
13
+ #c.allow_http_connections_when_no_cassette = true
14
+ end
@@ -0,0 +1,104 @@
1
+ require 'helper'
2
+
3
+ describe Simplesol do
4
+ it 'should be configurable' do
5
+ settings = { :login => 'login', :api_key => 'key', :api_server => 'server.ru' }
6
+ client = Simplesol::Client.new do |c|
7
+ c.login = settings[:login]
8
+ c.api_key = settings[:api_key]
9
+ c.api_server = settings[:api_server]
10
+ end
11
+
12
+ settings.each do |k, v|
13
+ client.send(k).should == v
14
+ end
15
+ end
16
+
17
+ it 'should raise NotConfiguredError' do
18
+ client = Simplesol::Client.new
19
+ expect { client.balance }.to raise_error(Simplesol::NotConfiguredError)
20
+ end
21
+
22
+ it 'can be configured later' do
23
+ client = Simplesol::Client.new
24
+ client.configure do |c|
25
+ c.api_key = 'some'
26
+ c.login = 'settings'
27
+ end
28
+ client.should be_configured
29
+ end
30
+
31
+ it 'can reset settings to defaults' do
32
+ client = Simplesol::Client.new do |c|
33
+ c.login = 'sample login'
34
+ end
35
+ client.reset
36
+ client.login.should == Simplesol::Configuration::DEFAULT_LOGIN
37
+ end
38
+
39
+ context 'in error scope' do
40
+ use_vcr_cassette 'simplesol_errors'
41
+
42
+ before :all do
43
+ @wrong_client = Simplesol::Client.new do |c|
44
+ c.login = '555555'
45
+ c.api_key = 'wrong'
46
+ end
47
+ end
48
+
49
+ it 'raise signature error' do
50
+ expect { @wrong_client.balance }.to raise_error(Simplesol::InvalidSignatureError)
51
+ end
52
+ end
53
+
54
+ # This context actually send requests to api and records them to vcr casette,
55
+ # so you should provide your actual api login and api key to run them properly.
56
+ # Btw this context does not change your balance - all sms sending runs in test mode.
57
+ =begin
58
+ context 'in general' do
59
+ use_vcr_cassette 'simplesol'
60
+
61
+ before :all do
62
+ @test_mobile_number = '<your mobile number>'
63
+ @client = Simplesol::Client.new do |c|
64
+ c.login = '<your login>'
65
+ c.api_key = '<your api key>'
66
+ end
67
+ end
68
+
69
+ it 'can fetch balance' do
70
+ resp = @client.balance
71
+ should_be_success resp
72
+ end
73
+
74
+ it 'can send test message' do
75
+ resp = @client.send_message([@test_mobile_number], 'Привет, как дела?', { :sender => 'santa', :test => 1 })
76
+ should_be_success resp
77
+ %w(balance count messages_id parts price recipients).each do |m|
78
+ resp.should respond_to(m)
79
+ end
80
+ resp.messages_id.should_not be_empty
81
+ end
82
+
83
+ it 'can fetch price' do
84
+ resp = @client.message_price [@test_mobile_number], 'Привет, как дела?'
85
+ %w(balance blocked price parts recipients).each do |m|
86
+ resp.should respond_to(m)
87
+ end
88
+ should_be_success resp
89
+ end
90
+
91
+ it 'can get statuses' do
92
+ resp = @client.message_status [1]
93
+ %w(messages details).each do |m|
94
+ resp.should respond_to(m)
95
+ end
96
+ should_be_success resp
97
+ end
98
+ end
99
+ =end
100
+
101
+ def should_be_success(response)
102
+ response.status.should == 'success'
103
+ end
104
+ end
@@ -0,0 +1,42 @@
1
+ ---
2
+ recorded_with: VCR 2.4.0
3
+ http_interactions:
4
+ - request:
5
+ method: post
6
+ uri: http://api.gosmsinfo.ru/api/user/balance
7
+ body:
8
+ string: sign=a6d969ddce2b9aeff22f403e0d67928a&user=555555
9
+ headers:
10
+ Accept:
11
+ - "*/*"
12
+ Content-Type:
13
+ - application/x-www-form-urlencoded
14
+ response:
15
+ status:
16
+ code: 200
17
+ message: OK
18
+ headers:
19
+ Transfer-Encoding:
20
+ - chunked
21
+ Date:
22
+ - Sat, 23 Feb 2013 10:18:48 GMT
23
+ Pragma:
24
+ - no-cache
25
+ Expires:
26
+ - Thu, 19 Nov 1981 08:52:00 GMT
27
+ Set-Cookie:
28
+ - PHPSESSID=7dmop50sclmndja36gds4gs693; path=/
29
+ Connection:
30
+ - keep-alive
31
+ X-Powered-By:
32
+ - PHP/5.3.10-1ubuntu3.4
33
+ Content-Type:
34
+ - text/html
35
+ Cache-Control:
36
+ - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
37
+ Server:
38
+ - nginx/1.1.19
39
+ body:
40
+ string: " {\"status\":\"error\",\"error\":2,\"message\":\"invalid signature\"}"
41
+ http_version:
42
+ recorded_at: Sat, 23 Feb 2013 10:18:48 GMT
metadata ADDED
@@ -0,0 +1,193 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simplesol
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Askar Zinurov
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2013-02-23 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: bundler
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rspec
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: vcr
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ type: :development
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: webmock
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ type: :development
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: faraday
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ hash: 3
85
+ segments:
86
+ - 0
87
+ version: "0"
88
+ type: :runtime
89
+ version_requirements: *id005
90
+ - !ruby/object:Gem::Dependency
91
+ name: faraday_middleware
92
+ prerelease: false
93
+ requirement: &id006 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ hash: 3
99
+ segments:
100
+ - 0
101
+ version: "0"
102
+ type: :runtime
103
+ version_requirements: *id006
104
+ - !ruby/object:Gem::Dependency
105
+ name: hashie
106
+ prerelease: false
107
+ requirement: &id007 !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ hash: 3
113
+ segments:
114
+ - 0
115
+ version: "0"
116
+ type: :runtime
117
+ version_requirements: *id007
118
+ - !ruby/object:Gem::Dependency
119
+ name: rash
120
+ prerelease: false
121
+ requirement: &id008 !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ hash: 3
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ type: :runtime
131
+ version_requirements: *id008
132
+ description: SimpleSol service client gem
133
+ email:
134
+ - mail@asktim.ru
135
+ executables: []
136
+
137
+ extensions: []
138
+
139
+ extra_rdoc_files: []
140
+
141
+ files:
142
+ - .gitignore
143
+ - .rspec
144
+ - Gemfile
145
+ - LICENSE.txt
146
+ - README.md
147
+ - Rakefile
148
+ - lib/simplesol.rb
149
+ - lib/simplesol/client.rb
150
+ - lib/simplesol/configuration.rb
151
+ - lib/simplesol/errors.rb
152
+ - lib/simplesol/version.rb
153
+ - simplesol.gemspec
154
+ - spec/helper.rb
155
+ - spec/simplesol_spec.rb
156
+ - spec/vcr_cassettes/simplesol_errors.yml
157
+ homepage: https://github.com/AskarZinurov/simplesol
158
+ licenses: []
159
+
160
+ post_install_message:
161
+ rdoc_options: []
162
+
163
+ require_paths:
164
+ - lib
165
+ required_ruby_version: !ruby/object:Gem::Requirement
166
+ none: false
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ hash: 3
171
+ segments:
172
+ - 0
173
+ version: "0"
174
+ required_rubygems_version: !ruby/object:Gem::Requirement
175
+ none: false
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ hash: 3
180
+ segments:
181
+ - 0
182
+ version: "0"
183
+ requirements: []
184
+
185
+ rubyforge_project:
186
+ rubygems_version: 1.8.24
187
+ signing_key:
188
+ specification_version: 3
189
+ summary: Gem for working with sms.simplesol.ru
190
+ test_files:
191
+ - spec/helper.rb
192
+ - spec/simplesol_spec.rb
193
+ - spec/vcr_cassettes/simplesol_errors.yml