voipfone_client 0.0.4

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.
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: