voipfone_client 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a80fbbc197d700cc57e5b9e3cdd6a5aa7bc26e8b
4
+ data.tar.gz: 2a43848c3dd0a881e7594e77217eb93b851f4ec8
5
+ SHA512:
6
+ metadata.gz: 9629390a383c7d49eebf55d33def7806240372dc1ef433666da3c7b4166d76a515ffd2098a9740615259496eafa22c4bfed5cd97d1d081aad755ae8bb76fa7da
7
+ data.tar.gz: d8c2770f668a0a09b710636d89bc69212d4e7e06b195e80f23581146e0ec3a20fc3b542174efe6e8c0c19639be87cee5c1c3db2c0ecd982e748e11b51e44055a
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ voipfone_client
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0-p451
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in voipfone_client.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Error Creative Studio
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,49 @@
1
+ # Voipfone Client
2
+
3
+ A gem to programatically manipulate your [Voipfone](http://www.voipfone.co.uk) account using Ruby.
4
+
5
+ Voipfone is a brilliant SIP VOIP provider with a very neat set of features, but unfortunately no API. So this gem hopefully fills that gap by using the same JSON API their web interface uses.
6
+
7
+ ## Installation
8
+
9
+ This gem is in Rubygems, so you can add this line to your application's Gemfile:
10
+
11
+ gem 'voipfone_client'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or you can manually install the gem using:
18
+
19
+ gem install voipfone_client
20
+
21
+ ##Configuration and Use
22
+
23
+ Before you can instantiate a `VoipfoneClient::Client` object, you need to need to configure it:
24
+
25
+ ```ruby
26
+ VoipfoneClient.configure do |config|
27
+ config.username = "your@email.address"
28
+ config.password = "yourpass"
29
+ end
30
+ ```
31
+
32
+ This approach gives us lots of options for adding more config options in the future.
33
+
34
+ After that you can create a new object to call Voipfone:
35
+
36
+ ```ruby
37
+ c = VoipfoneClient::Client.new
38
+ c.account_balance #will return your balance as a float
39
+ ```
40
+
41
+ ## Contributing
42
+
43
+ We'd love your input!
44
+
45
+ 1. Fork it ( http://github.com/errorstudio/voipfone_client/fork )
46
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
47
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
48
+ 4. Push to the branch (`git push origin my-new-feature`)
49
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,34 @@
1
+ require 'json'
2
+ require 'mechanize'
3
+ require 'voipfone_client/errors'
4
+ require 'voipfone_client/client'
5
+ require 'voipfone_client/account_balance'
6
+ require 'voipfone_client/account_details'
7
+ require 'voipfone_client/diverts'
8
+ require 'voipfone_client/voicemail'
9
+
10
+ module VoipfoneClient
11
+ BASE_URL = "https://www.voipfone.co.uk"
12
+ API_GET_URL = "https://www.voipfone.co.uk/api/srv"
13
+ API_POST_URL = "https://www.voipfone.co.uk/api/upd"
14
+
15
+ class << self
16
+ attr_accessor :configuration
17
+ end
18
+
19
+ # A module method which accepts a block, allowing us to configure the module.
20
+ # @param [Block] the configuration block, containing the configuration variables
21
+ def self.configure
22
+ self.configuration ||= Configuration.new
23
+ yield(configuration)
24
+ end
25
+
26
+ # A configuration class which contains the attributes we want to set in the module method
27
+ class Configuration
28
+ attr_accessor :username, :password, :user_agent_string
29
+
30
+ def initialize
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,8 @@
1
+ class VoipfoneClient::Client
2
+ # Return the balance of the account as a float.
3
+ # @return [Float] Account balance as a float. Should be rounded to 2dp before presentation.
4
+ def account_balance
5
+ request = @browser.get("#{VoipfoneClient::API_GET_URL}?balance&builder")
6
+ parse_response(request)["balance"]
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ class VoipfoneClient::Client
2
+ # Return the basic account details, as stored by Voipfone.
3
+ # @return [Hash] of account details
4
+ def account_details
5
+ request = @browser.get("#{VoipfoneClient::API_GET_URL}?account")
6
+ parse_response(request)
7
+ end
8
+ end
@@ -0,0 +1,35 @@
1
+ module VoipfoneClient
2
+ class Client
3
+ attr_reader :browser
4
+ # Intantiates a new Voipfone client, with username and password from the `VoipfoneClient::Configuration` class
5
+ # @return [VoipfoneClient::Client] the object created
6
+ def initialize()
7
+ if VoipfoneClient.configuration.username.nil? || VoipfoneClient.configuration.password.nil?
8
+ raise LoginCredentialsMissing, "You need to include a username and password to log in."
9
+ end
10
+ username = VoipfoneClient.configuration.username
11
+ password = VoipfoneClient.configuration.password
12
+ @browser = Mechanize.new
13
+ login_url = "#{VoipfoneClient::BASE_URL}/login.php?method=process"
14
+ @browser.post(login_url,{"hash" => "urlHash", "login" => username, "password" => password})
15
+ #We'll do a call to a cheap endpoint (the balance) and if it returns 'authfirst', there's a problem
16
+ #with the username / password. Oddly it still returns 200 OK.
17
+ if account_balance == "authfirst"
18
+ raise NotAuthenticatedError, "Username or Password weren't accepted. You'll need to instantiate a new VoipfoneClient::Client object."
19
+ end
20
+ end
21
+
22
+ private
23
+ # Responses from the private Voipfone API are always in the form ["message", {content}]
24
+ # We will strip the message (hopefully "OK"), raise if not OK, and return the content.
25
+ # @param request [JSON] The raw request response from the Voipfone API
26
+ # @return [Hash] the parsed JSON
27
+ def parse_response(request)
28
+ raw = JSON.parse(request.body)
29
+ unless raw.first == "ok" || raw.first == "OK"
30
+ raise VoipfoneAPIError, raw.first
31
+ end
32
+ raw.last
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,78 @@
1
+ class VoipfoneClient::Client
2
+ # Get a list of phones which can be diverted to. Returns a nested array of name and phone number.
3
+ # @return [Array] of names and phone numbers
4
+ def diverts_list
5
+ request = @browser.get("#{VoipfoneClient::API_GET_URL}?divertsCommon")
6
+ parse_response(request)["divertsCommon"]
7
+ end
8
+
9
+ # Add a new number to the list of numbers which can be diverted to. Requires a name
10
+ # and a phone number, which will have spaces stripped from it. May be in international
11
+ # format.
12
+ # @param name [String] The name which appears in dropdowns in the web interface
13
+ # @param number [String] The number which will be called. Spaces will be stripped. + symbol accepted
14
+ # @return [Boolean] true on success or a failure message (in which case a `VoipfoneAPIError` will be raised)
15
+ def add_to_diverts_list(name: nil, number: nil)
16
+ if name.nil? || number.nil?
17
+ raise ArgumentError, "You need to include a name and number to add to the diverts list"
18
+ end
19
+ number = number.gsub(" ","")
20
+ parameters = {
21
+ "div-list-name" => name,
22
+ "div-list-num" => number
23
+ }
24
+ request = @browser.post("#{VoipfoneClient::API_POST_URL}?setDivertsList", parameters)
25
+ response = parse_response(request)
26
+ if response == [name, number]
27
+ return true
28
+ else
29
+ raise VoipfoneAPIError, "Although Voipfone returned an OK, the data they stored didn't match what you asked for: #{response}"
30
+ end
31
+ end
32
+
33
+
34
+ # Divert calls for different circumstances - at least one option is required. There are 4 supported situations which can be
35
+ # diverted for, namely:
36
+ # - all calls (i.e. no calls will reach the pbx / phones - immediate divert)
37
+ # - when there is a failure in the phone system
38
+ # - when the phone(s) are busy
39
+ # - when there's no answer
40
+ # @param all [String] The number to which all calls will be diverted.
41
+ # @param fail [String] The number to which calls will be diverted in the event of a failure
42
+ # @param busy [String] The number to which calls will be diverted if the phones are busy
43
+ # @param no_answer [String] The number to which calls will be diverted if there's no answer
44
+ # @return [Boolean] true on success, or a failure message (in which case a `VoipfoneAPIError` will be raised)
45
+ def set_diverts(all: nil, fail: nil, busy: nil, no_answer: nil)
46
+ all ||= ""
47
+ fail ||= ""
48
+ busy ||= ""
49
+ no_answer ||= ""
50
+ parameters = {
51
+ "all" => all.gsub(" ",""),
52
+ "chanunavail" => fail.gsub(" ",""),
53
+ "busy" => busy.gsub(" ",""),
54
+ "noanswer" => no_answer.gsub(" ","")
55
+ }
56
+ request = @browser.post("#{VoipfoneClient::API_POST_URL}?divertsMain", parameters)
57
+ response = parse_response(request)
58
+ if response == "ok"
59
+ return true
60
+ else
61
+ raise VoipfoneAPIError, response.first
62
+ end
63
+ end
64
+
65
+ # Diverts all calls to the number passed into this method
66
+ # @param number [String] The number to be diverted to.
67
+ # @return [Boolean] true on success, or an error message (in which case a `VoipfoneAPIError` will be raised)
68
+ def divert_all_calls(number: nil)
69
+ set_diverts(all: number)
70
+ end
71
+
72
+ # Get current diverts
73
+ # @return [Array] A nested set of arrays with divert information for each type of divert currently set
74
+ def get_diverts
75
+ request = @browser.get("#{VoipfoneClient::API_GET_URL}?divertsMain")
76
+ parse_response(request)["divertsMain"]
77
+ end
78
+ end
@@ -0,0 +1,3 @@
1
+ class LoginCredentialsMissing < StandardError; end
2
+ class NotAuthenticatedError < StandardError; end
3
+ class VoipfoneAPIError < StandardError; end
@@ -0,0 +1,3 @@
1
+ module VoipfoneClient
2
+ VERSION = "0.0.4"
3
+ end
@@ -0,0 +1,8 @@
1
+ class VoipfoneClient::Client
2
+ #Return a list of voicemail entries, with details for each
3
+ #@return [Hash] of voicemail information. This includes a reference to a WAV file which isn't accessible (yet?)
4
+ def voicemail
5
+ request = @browser.get("#{VoipfoneClient::API_GET_URL}?vm_view")
6
+ parse_response(request)["vm_view"].first["voicemail"]
7
+ end
8
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'voipfone_client/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "voipfone_client"
8
+ spec.version = VoipfoneClient::VERSION
9
+ spec.authors = ["Error Creative Studio"]
10
+ spec.email = ["hosting@errorstudio.co.uk"]
11
+ spec.summary = %q{A client for voipfone.co.uk, a UK-based SIP provider}
12
+ spec.description = %q{Voipfone are a brilliant SIP provider with loads of features, but no API. This Gem hooks into the API which their web interfaces uses.}
13
+ spec.homepage = "https://github.com/errorstudio/voipfone_client"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake", "~> 10.2"
23
+ spec.add_development_dependency "yard", "~> 0.8"
24
+
25
+ spec.add_dependency "mechanize", "~> 2.7"
26
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: voipfone_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Error Creative Studio
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: yard
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '0.8'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '0.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mechanize
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.7'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '2.7'
69
+ description: Voipfone are a brilliant SIP provider with loads of features, but no
70
+ API. This Gem hooks into the API which their web interfaces uses.
71
+ email:
72
+ - hosting@errorstudio.co.uk
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - .ruby-gemset
79
+ - .ruby-version
80
+ - Gemfile
81
+ - LICENSE.txt
82
+ - README.md
83
+ - Rakefile
84
+ - lib/voipfone_client.rb
85
+ - lib/voipfone_client/account_balance.rb
86
+ - lib/voipfone_client/account_details.rb
87
+ - lib/voipfone_client/client.rb
88
+ - lib/voipfone_client/diverts.rb
89
+ - lib/voipfone_client/errors.rb
90
+ - lib/voipfone_client/version.rb
91
+ - lib/voipfone_client/voicemail.rb
92
+ - voipfone_client.gemspec
93
+ homepage: https://github.com/errorstudio/voipfone_client
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.2.2
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: A client for voipfone.co.uk, a UK-based SIP provider
117
+ test_files: []
118
+ has_rdoc: