multiinfo 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ .DS_Store
data/History.txt ADDED
@@ -0,0 +1,9 @@
1
+ 2012-05-24 Version 0.0.7 Piotr Barczuk
2
+ - added support for trusted certificates signing
3
+
4
+ 2009-07-29 Version 0.0.1 Łukasz Łuczak
5
+ - sending sms message
6
+ - receiving smsm message status
7
+ - cancel sending sms
8
+ - config enabled with yml file
9
+ - HTTPclient used for HTTPS with client cert comunication
data/License.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Łukasz Łuczak
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.rdoc ADDED
@@ -0,0 +1,53 @@
1
+ = Polkomtel MultiInfo HTTPS API wrapped into Ruby library
2
+
3
+ This gem is Ruby interface to the Polkomtel's MultiInfo SMS gateway service, based on Luke Redpath's clickatel library
4
+ To use this gem, you will need an access to Polkomtel's MultiInfo service. You need user, password, sercvice_id and certificate for ssl connection.
5
+ Contact Polkomtel sales reps for info how to obtain acces to MultiInfo service.
6
+
7
+ == Basic Usage
8
+
9
+ You will need your Mutliinfo credentials and SSL certificate to use this library.
10
+
11
+ require 'rubygems'
12
+ require 'multiinfo'
13
+
14
+ api = MultiInfo::API.new
15
+
16
+ # Example api calls
17
+ api.send_message('48661351024', 'Hello') # sends sms 'Hello' to 48 661 351 024 and returns message id
18
+ api.message_info('22') # gets info about message with id 22
19
+
20
+
21
+ == Conifguration options
22
+
23
+ Default path for config file and certificate files is $HOME/multiinfo. You should place following files in that directory:
24
+ multiinfo.yml # config file
25
+ multiinfo.crt # certificate
26
+ multiinfo.pem # RSA key
27
+
28
+
29
+ In multiinfo.yml you should specify at least:
30
+ login
31
+ password
32
+ service_id
33
+
34
+ If you want to use different names for certificate files speciify them with FULL PATH in config file under:
35
+
36
+ client_cert
37
+ client_key
38
+
39
+ You will probably also need to add Multiinfo Root Certificate to your trusted certificates chain.
40
+ To mark a certificate as trusted, specify it in your multiinfo.yml file (you can provide either a filename or a directory). You can also use 'default' to let the application use the default certificates path.
41
+
42
+ See example in config_example.yml
43
+
44
+
45
+ To load your custom config file use following code
46
+ require 'rubygems'
47
+ require 'multiinfo'
48
+
49
+ config = MultiInfo::API.load_auth_options(CONFIG_FILE_FULL_PATH)
50
+ api = MultiInfo::API.new(config)
51
+
52
+
53
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.7
@@ -0,0 +1,9 @@
1
+ # example config file for authentication MultiInfo HTTPS API
2
+ login: luka
3
+ password: test
4
+ service_id: 1
5
+
6
+ # Optionally you can specify full path to certificate files
7
+ client_cert: /home/luka/weblify.cert
8
+ client_key: /home/luka/weblify.key
9
+ ca_path: /etc/ssl/certs #or just user default
@@ -0,0 +1,23 @@
1
+ class Hash
2
+ # Returns a new hash containing only the keys specified
3
+ # that exist in the current hash.
4
+ #
5
+ # {:a => '1', :b => '2', :c => '3'}.only(:a, :c)
6
+ # # => {:a => '1', :c => '3'}
7
+ #
8
+ # Keys that do not exist in the original hash are ignored.
9
+ def only(*keys)
10
+ inject( {} ) do |new_hash, (key, value)|
11
+ new_hash[key] = value if keys.include?(key)
12
+ new_hash
13
+ end
14
+ end
15
+
16
+ def symbolize_keys
17
+ inject({}) do |options, (key, value)|
18
+ options[(key.to_sym rescue key) || key] = value
19
+ options
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,9 @@
1
+ class String
2
+ def camelize(first_letter_in_uppercase = true)
3
+ if first_letter_in_uppercase
4
+ self.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
5
+ else
6
+ self[0].chr.downcase + camelize[1..-1]
7
+ end
8
+ end
9
+ end
data/lib/multiinfo.rb ADDED
@@ -0,0 +1,8 @@
1
+ module MultiInfo end
2
+
3
+ %w( core-ext/hash
4
+ core-ext/string
5
+ multiinfo/api
6
+ ).each do |lib|
7
+ require File.join(File.dirname(__FILE__), lib)
8
+ end
@@ -0,0 +1,122 @@
1
+ module MultiInfo
2
+ # This module provides the core implementation of the Clickatell
3
+ # HTTP service.
4
+ class API
5
+ # Defaults for config file location
6
+ DEFAULT_CONFIG_PATH = File.join(ENV['HOME'], 'multiinfo')
7
+ DEFAULT_CONFIG_FILE = 'multiinfo.yml'
8
+
9
+ attr_accessor :auth_options
10
+
11
+ class << self
12
+ # Set to true to enable debugging (off by default)
13
+ attr_accessor :debug_mode
14
+
15
+ # Set to true to test message sending; this will not actually send
16
+ # messages but will collect sent messages in a testable collection.
17
+ # (off by default)
18
+ attr_accessor :test_mode
19
+
20
+ # Load credentials from config file
21
+ def load_auth_options(config_location = nil)
22
+ config_file = File.open(config_location || File.join(DEFAULT_CONFIG_PATH, DEFAULT_CONFIG_FILE))
23
+ auth_options = YAML.load(config_file).symbolize_keys
24
+ raise MultiInfo::API::Error.new(-9999, 'Missing config params') if auth_options.only(:login, :password, :service_id).size != 3
25
+ auth_options
26
+ end
27
+
28
+ end
29
+ self.debug_mode = false
30
+ self.test_mode = false
31
+
32
+ # Creates a new API instance using the specified +auth_options+.
33
+ # +auth_options+ is a hash containing :username, :password, :service_id and
34
+ # optionally :client_cert, :client_key
35
+ #
36
+ def initialize(auth_options = nil)
37
+ @auth_options = auth_options || self.class.load_auth_options
38
+ end
39
+
40
+ # Sends a message +message_text+ to +recipient+. Recipient
41
+ # number should have an international dialing prefix
42
+ def send_message(recipient, message_text, opts={})
43
+ valid_options = opts.only(:valid_to, :deliv_notif_request).merge(service_id)
44
+ response = execute_command( 'sendsms', {:text => message_text, :dest => recipient}.merge(valid_options) )
45
+ parse_response(response)
46
+ end
47
+
48
+
49
+ # Sends a package of messages. Recipient
50
+ # number should have an international dialing prefix
51
+ def send_package
52
+ # todo
53
+ end
54
+
55
+
56
+ # Returns the status of a message. Use sms ID returned
57
+ # from original send_message call.
58
+ def message_info(sms_id)
59
+ response = execute_command('infosms', :sms_id => sms_id)
60
+ parse_response(response)
61
+ end
62
+
63
+ # Returns the status of a package of messages. Use package id returned
64
+ # from original send_package call.
65
+ def package_info(package_id)
66
+ response = execute_command('packageinfo', :package_id => package_id)
67
+ parse_response(response)
68
+ end
69
+
70
+ # Returns the status of a message. Use sms ID returned
71
+ # from original send_message call.
72
+ def cancel_message(sms_id)
73
+ response = execute_command('cancelsms', :sms_id => sms_id)
74
+ parse_response(response)
75
+ end
76
+
77
+ def get_message(opts={})
78
+ valid_options = opts.only(:timeout).merge(service_id)
79
+ response = execute_command('getsms', valid_options)
80
+ parse_response(response)
81
+ end
82
+
83
+ def sms_requests #:nodoc:
84
+ @sms_requests ||= []
85
+ end
86
+
87
+ protected
88
+ def execute_command(command_name, parameters={}) #:nodoc:
89
+ executor = Executor.new(credentials, certificate, self.class.debug_mode, self.class.test_mode)
90
+ result = executor.execute(command_name, parameters)
91
+
92
+ (sms_requests << executor.sms_requests).flatten! if self.class.test_mode
93
+
94
+ result
95
+ end
96
+
97
+ def parse_response(raw_response) #:nodoc:
98
+ Response.parse(raw_response)
99
+ end
100
+
101
+ def credentials #:nodoc:
102
+ @credenitals ||= @auth_options.only(:login, :password)
103
+ end
104
+
105
+ def certificate #:nodoc:
106
+ @certificate ||= @auth_options.only(:client_cert, :client_key, :ca_path)
107
+ end
108
+
109
+ def service_id #:nodoc:
110
+ @service_id ||= @auth_options.only(:service_id)
111
+ end
112
+
113
+ end
114
+ end
115
+
116
+ %w( api/command
117
+ api/error
118
+ api/executor
119
+ api/response
120
+ ).each do |lib|
121
+ require File.join(File.dirname(__FILE__), lib)
122
+ end
@@ -0,0 +1,22 @@
1
+ require "cgi"
2
+ module MultiInfo
3
+ class API
4
+ API_SERVICE_HOST = 'https://www.multiinfo.plus.pl/'
5
+ API_NAME = 'smsapi4'
6
+ API_SCRIPT_TYPE = 'aspx'
7
+
8
+ class Command
9
+
10
+ def initialize(command_name)
11
+ @command_name = command_name
12
+ end
13
+
14
+ def with_params(param_hash)
15
+ param_string = '?' + param_hash.map { |key, value| "#{::CGI.escape(key.to_s.camelize(false))}=#{::CGI.escape(value.to_s)}" }.sort.join('&')
16
+ URI.parse(File.join("#{API_SERVICE_HOST}#{API_NAME}/", "#{@command_name}.#{API_SCRIPT_TYPE}" + param_string))
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ module MultiInfo
2
+ class API
3
+
4
+ # MultiInfo API Error exception.
5
+ class Error < StandardError
6
+ attr_reader :code, :message
7
+
8
+ def initialize(code, message)
9
+ @code, @message = code, message
10
+ end
11
+
12
+ # Creates a new Error from a MultiInfo HTTP response string
13
+ def self.parse(error_arr)
14
+ code, message = error_arr
15
+ self.new(code, message)
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,73 @@
1
+ require "rubygems"
2
+ require 'httpclient'
3
+
4
+
5
+ module MultiInfo
6
+ class API
7
+ DEFAULT_CERT_FILE = 'multiinfo.crt'
8
+ DEFAULT_KEY_FILE = 'multiinfo.pem'
9
+
10
+ class FakeHttpResponse
11
+ "test mode"
12
+ end
13
+
14
+ class Executor
15
+ def initialize(authentication_hash, certificate_hash, debug=false, test_mode=false)
16
+ @authentication_hash = authentication_hash
17
+ @client_cert_file = {
18
+ :cert => certificate_hash[:client_cert] || File.join(DEFAULT_CONFIG_PATH, DEFAULT_CERT_FILE),
19
+ :rsa_key => certificate_hash[:client_key] || File.join(DEFAULT_CONFIG_PATH, DEFAULT_KEY_FILE)
20
+ }
21
+ @client_cert_file[:ca_path] = certificate_hash[:ca_path] unless certificate_hash[:ca_path].blank?
22
+ @debug = debug
23
+ @test_mode = test_mode
24
+
25
+ allow_request_recording if @test_mode
26
+ end
27
+
28
+ def execute(command_name, parameters={})
29
+ request_uri = command(command_name, parameters)
30
+ puts "[debug] Executing command '#{command_name}': #{request_uri}" if @debug
31
+ [command_name, get_response(request_uri)]
32
+ end
33
+
34
+ def in_test_mode?
35
+ @test_mode
36
+ end
37
+
38
+ protected
39
+
40
+ def command(command_name, parameters)
41
+ Command.new(command_name).with_params( parameters.merge(@authentication_hash) )
42
+ end
43
+
44
+ def get_response(uri)
45
+ if in_test_mode?
46
+ sms_requests << uri
47
+ FakeHttpResponse.new
48
+ else
49
+ clnt = HTTPClient.new
50
+ if @client_cert_file[:ca_path] == 'default'
51
+ clnt.ssl_config.set_default_paths
52
+ elsif !@client_cert_file[:ca_path].blank?
53
+ clnt.ssl_config.add_trust_ca @client_cert_file[:ca_path]
54
+ end
55
+ clnt.ssl_config.set_client_cert_file(@client_cert_file[:cert], @client_cert_file[:rsa_key])
56
+ clnt.get_content(uri)
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def allow_request_recording
63
+ class << self
64
+ define_method :sms_requests do
65
+ @sms_requests ||= []
66
+ end
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,86 @@
1
+ module MultiInfo
2
+ class API
3
+
4
+ # Used to parse HTTP responses returned from MultiInfo API calls.
5
+ class Response
6
+ class << self
7
+
8
+ # Returns the HTTP response body data as a hash.
9
+ def parse(response_arr)
10
+ return { :status => 'OK' } if API.test_mode
11
+ command, http_response = response_arr
12
+ response_rows = http_response.split(/\r\n|\n/)
13
+ response_status, response_body = response_rows[0], response_rows[1..-1]
14
+ if response_status.to_i < 0
15
+ raise MultiInfo::API::Error.new(response_status, response_body.first)
16
+ else
17
+ response_hash(command, response_body).merge({:status => response_status})
18
+ end
19
+ end
20
+
21
+ private
22
+ def response_hash(command, response)
23
+ resp_hash = {}
24
+ API_RESPONSES[command].each_with_index { |message_key, i| resp_hash[message_key] = response[i] }
25
+ resp_hash
26
+ end
27
+
28
+ public
29
+ API_RESPONSES = {
30
+ # Hash keys for each response lines.
31
+ # Line no 1 is skipped as it always is 'status'
32
+
33
+ 'sendsms' => [
34
+ :sms_id # 2
35
+ ],
36
+
37
+ 'cancelsms' => [
38
+ :cancel_status # 2
39
+ ],
40
+
41
+ 'infosms' => [
42
+ :sms_id, # 2
43
+ :message_type, # 3
44
+ :message_body, # 4
45
+ :protocol_id, # 5
46
+ :coding_scheme, # 6
47
+ :service_id, # 7
48
+ :conector_id, # 8
49
+ :originator_sms_id, # 9
50
+ :priority, # 10
51
+ :send_date, # 11
52
+ :valid_to, # 12
53
+ :deliv_notif_request, # 13
54
+ :originator, # 14
55
+ :destination, # 15
56
+ :message_status, # 16
57
+ :status_date # 17
58
+ ],
59
+
60
+ 'packageinfo' => [
61
+ :package_id, # 2
62
+ :sent_message_count, # 3
63
+ :waiting_message_count,# 4
64
+ :package_status # 5
65
+ ],
66
+
67
+ 'getsms' => [
68
+ :sms_id, # 2
69
+ :sender, # 3
70
+ :destination, # 4
71
+ :message_type, # 5
72
+ :message_body, # 6
73
+ :protocol_id, # 7
74
+ :coding_scheme, # 8
75
+ :service_id, # 9
76
+ :conector_id, # 9
77
+ :receive_date # 10
78
+ ]
79
+
80
+ }
81
+
82
+ end
83
+
84
+ end
85
+ end
86
+ end
data/multiinfo.gemspec ADDED
@@ -0,0 +1,52 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{multiinfo}
5
+ s.version = "0.0.7"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["\305\201ukasz \305\201uczak", "Piotr Barczuk"]
9
+ s.date = %q{2012-05-24}
10
+ s.description = %q{This gem is Ruby interface to the Polkomtel's MultiInfo SMS gateway service, based on Luke Redpath's clickatel library. To use this gem, you will need an access to Polkomtel's MultiInfo service. You need user, password, sercvice_id and certificate for ssl connection. Contact Polkomtel sales reps for info how to obtain acces to MultiInfo service.}
11
+ s.email = %q{luka@weblify.pl}
12
+ s.extra_rdoc_files = [
13
+ "README.rdoc"
14
+ ]
15
+ s.files = [
16
+ ".gitignore",
17
+ "History.txt",
18
+ "License.txt",
19
+ "README.rdoc",
20
+ "VERSION",
21
+ "config_example.yml",
22
+ "lib/core-ext/hash.rb",
23
+ "lib/core-ext/string.rb",
24
+ "lib/multiinfo.rb",
25
+ "lib/multiinfo/api.rb",
26
+ "lib/multiinfo/api/command.rb",
27
+ "lib/multiinfo/api/error.rb",
28
+ "lib/multiinfo/api/executor.rb",
29
+ "lib/multiinfo/api/response.rb",
30
+ "multiinfo.gemspec",
31
+ "rakefile.rb"
32
+ ]
33
+ s.has_rdoc = true
34
+ s.homepage = %q{http://github.com/luka/multiinfo}
35
+ s.rdoc_options = ["--charset=UTF-8"]
36
+ s.require_paths = ["lib"]
37
+ s.rubygems_version = %q{1.3.1}
38
+ s.summary = %q{Ruby interface to the Polkomtel's MultiInfo SMS gateway service, based on Luke Redpath's clickatel library}
39
+
40
+ if s.respond_to? :specification_version then
41
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
42
+ s.specification_version = 2
43
+
44
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
45
+ s.add_runtime_dependency(%q<httpclient>, [">= 2.2.5"])
46
+ else
47
+ s.add_dependency(%q<httpclient>, [">= 2.2.5"])
48
+ end
49
+ else
50
+ s.add_dependency(%q<httpclient>, [">= 2.2.5"])
51
+ end
52
+ end
data/rakefile.rb ADDED
@@ -0,0 +1,17 @@
1
+ begin
2
+ require 'jeweler'
3
+
4
+ Jeweler::Tasks.new do |gemspec|
5
+ gemspec.name = "multiinfo"
6
+ gemspec.summary = "Ruby interface to the Polkomtel's MultiInfo SMS gateway service, based on Luke Redpath's clickatel library"
7
+ gemspec.description = "This gem is Ruby interface to the Polkomtel's MultiInfo SMS gateway service, based on Luke Redpath's clickatel library.
8
+ To use this gem, you will need an access to Polkomtel's MultiInfo service. You need user, password, sercvice_id and certificate for ssl connection.
9
+ Contact Polkomtel sales reps for info how to obtain acces to MultiInfo service."
10
+ gemspec.email = "luka@weblify.pl"
11
+ gemspec.homepage = "http://github.com/luka/multiinfo"
12
+ gemspec.authors = ["Łukasz Łuczak"]
13
+ gemspec.add_dependency('httpclient', '>= 2.2.5')
14
+ end
15
+ rescue LoadError
16
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
17
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: multiinfo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.7
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Łukasz Łuczak
9
+ - Piotr Barczuk
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-05-24 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: httpclient
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 2.2.5
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: 2.2.5
31
+ description: This gem is Ruby interface to the Polkomtel's MultiInfo SMS gateway service,
32
+ based on Luke Redpath's clickatel library. To use this gem, you will need an access
33
+ to Polkomtel's MultiInfo service. You need user, password, sercvice_id and certificate
34
+ for ssl connection. Contact Polkomtel sales reps for info how to obtain acces to
35
+ MultiInfo service.
36
+ email: luka@weblify.pl
37
+ executables: []
38
+ extensions: []
39
+ extra_rdoc_files:
40
+ - README.rdoc
41
+ files:
42
+ - .gitignore
43
+ - History.txt
44
+ - License.txt
45
+ - README.rdoc
46
+ - VERSION
47
+ - config_example.yml
48
+ - lib/core-ext/hash.rb
49
+ - lib/core-ext/string.rb
50
+ - lib/multiinfo.rb
51
+ - lib/multiinfo/api.rb
52
+ - lib/multiinfo/api/command.rb
53
+ - lib/multiinfo/api/error.rb
54
+ - lib/multiinfo/api/executor.rb
55
+ - lib/multiinfo/api/response.rb
56
+ - multiinfo.gemspec
57
+ - rakefile.rb
58
+ homepage: http://github.com/luka/multiinfo
59
+ licenses: []
60
+ post_install_message:
61
+ rdoc_options:
62
+ - --charset=UTF-8
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 1.8.24
80
+ signing_key:
81
+ specification_version: 2
82
+ summary: Ruby interface to the Polkomtel's MultiInfo SMS gateway service, based on
83
+ Luke Redpath's clickatel library
84
+ test_files: []