Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ spec/reports
test/tmp
test/version_tmp
tmp
# Ignore emacs backups
*~
TAGS
# Based on guidance found at: http://stackoverflow.com/questions/16087120/
.ruby-version
.ruby-gemset
.rvmrc
1 change: 0 additions & 1 deletion .ruby-gemset

This file was deleted.

1 change: 0 additions & 1 deletion .ruby-version

This file was deleted.

116 changes: 91 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,46 +40,36 @@ This approach gives us lots of options for adding more config options in the fut
After you've done that, there are various classes which you can use to access different parts of your Voipfone Account.

### VoipfoneClient::Account
The `Voipfone::Account` class has methods relating to your account:
The `VoipfoneClient::Account` class has methods relating to your account:

* `balance()` returns your balance as a float
* `details` returns a hash of your account details (email, name etc)
* `phone numbers()` returns an array of phone numbers associated with your account
* `extension_numbers()` returns an array of extension numbers associated with your account
* `phone_numbers()` returns an array of phone numbers associated with your account
* `voicemail()` gives you a list of your voicemails, but not (yet) the audio. Pull requests welcome!

### Voipfone::RegisteredMobile
The `Voipfone::RegisteredMobile` class only has one class method at the moment, `Voipfone::RegisteredMobile.all()` which returns an array of `Voipfone::RegisteredMobile` objects. These respond to `number()` and `name()`.

These are particularly useful to know for sending SMS messages, because the 'from' number has to be in this list. You can't send an SMS from an arbitrary number.

```ruby

include VoipfoneClient
mobiles = RegisteredMobile.all #this will be an array
m = mobiles.first
m.name #this will be the name of the mobile
m.number #this will be the number of the mobile
account = VoipfoneClient::Account.new
account.balance # => 123.4567890

```

### Voipfone::SMS
The `Voipfone::SMS` class allows you to send SMS messages from your account.
### VoipfoneClient::Extension
The `VoipfoneClient::Extension` class has methods relating to your extensions:

You need to make sure that you're sending _from_ a number which is in the list of registered mobiles.
* `all()` returns a collection of all extensions associated with your account
* `list()` returns a simple list of the extension numbers associated with your account

``` ruby
include VoipfoneClient
s = SMS.new
s.from = "[sender number]" # a number which is in the list of registered mobiles at voipfone
s.to = "[recipient number]" #your recipient number
s.message = "your message" #message is truncated at 160 chars; UTF-8 not supported.

```
```ruby

Spaces are stripped from phone numbers (which need to be supplied as a string); international format with a + symbol is OK.
VoipfoneClient::Extension.list # => ["200", "201", "202", "203", "204", "205", "206", ... ]

### Voipfone::GlobalDivert
The `Voipfone::GlobalDivert` class handles diverts for your whole account (all extensions).
```

### VoipfoneClient::GlobalDivert
The `VoipfoneClient::GlobalDivert` class handles diverts for your whole account (all extensions).

Diverts are one of four __types__ in Voipfone, which we describe thus:

Expand All @@ -103,6 +93,82 @@ d.save # will return true on success
```
In the Voipfone web interface you have to set up a list of divert recipients (and you can do that in this client too), but you don't _need_ to - you can set any number for a divert. As with all other numbers you set, it should be passed in as a string, spaces will be stripped, the + symbol is allowed.

### VoipfoneClient::RegisteredMobile
The `VoipfoneClient::RegisteredMobile` class only has one class method at the moment, `VoipfoneClient::RegisteredMobile.all()` which returns an array of `VoipfoneClient::RegisteredMobile` objects. These respond to `number()` and `name()`.

These are particularly useful to know for sending SMS messages, because the 'from' number has to be in this list. You can't send an SMS from an arbitrary number.

```ruby

include VoipfoneClient
mobiles = RegisteredMobile.all #this will be an array
m = mobiles.first
m.name #this will be the name of the mobile
m.number #this will be the number of the mobile

```

### VoipfoneClient::Report
The `VoipfoneClient::Report` class allows you to collect call report information for your account:

* `call_records_summary( call_type, date, range, extension_filter)` returns
an an array of call summary data, namely duration, cost and number
of calls per hour or day (depending on chosen range, see below)

* `call_records( call_type, date, range, extension_filter)` returns
an an array of call record hashes containing call details, namely date
and time, to, from, duration and cost

`call_type` is one of three __types__ in Voipfone, which we describe thus:

* `:outgoing` - for reporting on outgoing calls (this is the default)
* `:incoming` - for reporting on incoming calls
* `:missed` - for reporting on incoming calls that were not answered

`date` is a standard Ruby Date class, defaulting to today if not set.

`range` is either :month or :day, defaulting to :month

`extension_filter` is either the extension to report on, or :all for all extensions. This is also the default.


``` ruby
include VoipfoneClient
r = VoipfoneClient::Report.call_records_summary( :missed, Date.today, :day, :all)
# => [{:duration=>0, :pkgMins=>0, :cost=>0.0, :calls=>0, :hour=>0}, {:duration=>0, :pkgMins=>0, :cost=>0.0, :calls=>0, :hour=>1}, ...]


```

Note that missed calls can have a duration if the caller left a voicemail message.


``` ruby
include VoipfoneClient
r = VoipfoneClient::Report.call_records( :outgoing, Date.today, :day, :all)
# => [{:datetime=>#<DateTime: 2015-12-11T19:37:00+00:00 ((2457368j,70620s,0n),+0s,2299161j)>, :from=>"30163517*200", :to=>"004412341234", :duration=>4, :cost=>"0.0120", :package_minutes=>"0"}, ...]

```

Note that a search across all extensions for a month can take a while to download all the records.


### VoipfoneClient::SMS
The `VoipfoneClient::SMS` class allows you to send SMS messages from your account.

You need to make sure that you're sending _from_ a number which is in the list of registered mobiles.

``` ruby
include VoipfoneClient
s = SMS.new
s.from = "[sender number]" # a number which is in the list of registered mobiles at voipfone
s.to = "[recipient number]" #your recipient number
s.message = "your message" #message is truncated at 160 chars; UTF-8 not supported.

```

Spaces are stripped from phone numbers (which need to be supplied as a string); international format with a + symbol is OK.

##To Do

There's quite a list of stuff which would be nice to do. If you feel inclined, we'd love pull requests.
Expand Down
17 changes: 13 additions & 4 deletions lib/voipfone_client/account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Account < Session
# @return [Float] Account balance as a float. Should be rounded to 2dp before presentation.
def balance
request = @browser.get("#{VoipfoneClient::API_GET_URL}?balance&builder")
parse_response(request)["balance"]
parse_response(request)[:balance]
end

def details
Expand All @@ -16,14 +16,23 @@ def details
# @return [Array] Phone numbers as strings.
def phone_numbers
request = @browser.get("#{VoipfoneClient::API_GET_URL}?nums")
parse_response(request)["nums"].collect {|n| n.first}
parse_response(request)[:nums].collect {|n| n.first}
end

# Get a simple list of extensions. Returns a list of extension
# numbers as an array of strings. As this may be required
# multiple times for report generation and other uses, this call
# is cached. See Extension.all for an uncached list.
# @return [Array] of extension numbers
def extension_numbers
Extension.list
end

#Return a list of voicemail entries, with details for each
#@return [Hash] of voicemail information. This includes a reference to a WAV file which isn't accessible (yet?)
def voicemail
request = @browser.get("#{VoipfoneClient::API_GET_URL}?vm_view")
parse_response(request)["vm_view"].first["voicemail"]
parse_response(request)[:vm_view].first[:voicemail]
end
end
end
end
4 changes: 2 additions & 2 deletions lib/voipfone_client/divert_list_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ class << self
def all
d = self.new
request = d.browser.get("#{VoipfoneClient::API_GET_URL}?divertsCommon")
d.parse_response(request)["divertsCommon"].collect do |i|
d.parse_response(request)[:divertsCommon].collect do |i|
DivertListItem.new(name: i.first, number: i.last)
end
end
end
end
end
end
64 changes: 64 additions & 0 deletions lib/voipfone_client/extension.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module VoipfoneClient
class Extension < Session
attr_accessor( :number, :name, :email, :password, :group, :voicemail,
:business_hours, :recording)

# Constructor for {Extension} which accepts the number, email,
# password, group, voicemail, business hours and recording
# settings.

# @param number [String] the number of the phone extension.
# @param name [String] the name of the person at that extension.
# @param email [String] the email address of that person.
# @param password [String] the six-digit password of the phone extension.

# @param group [Boolean] does the extension belong to the default group?
# @param voicemail [Boolean] does the extension have voicemail?
# @param business_hours [Boolean] only available during business hours?
# @param recording [Boolean] are the calls to be recorded?

def initialize( number: nil, name: nil, email: nil, password: nil,
group: false, voicemail: false, business_hours: false,
recording: false)
@number = number
@name = name
@email = email
@password = password
@group = group
@voicemail = voicemail
@business_hours = business_hours
@recording = recording
super()
end

class << self
# Get a list of extensions. Returns a nested array of extensions
# and details.
# @return [Array] of Extensions with numbers, names, passwords, and
# boolean values for group, voicemail, business_hours and recording
# settings

def all
session = self.new
request = session.browser.get("#{VoipfoneClient::API_GET_URL}?ext")
session.parse_response(request)[:ext].collect do |e|
{ number: e[0], name: e[1], email: e[2],
password: e[3], group: e[4], voicemail: e[5],
business_hours: e[6], recording: e[7]}
end
end

# Get a simple list of extensions. Returns a list of extension
# numbers as an array of strings.
# @return [Array] of extension numbers

def list
session = self.new
request = session.browser.get("#{VoipfoneClient::API_GET_URL}?ext")
session.parse_response(request)[:ext].collect do |e|
e[0]
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/voipfone_client/global_divert.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class << self
def all
g = self.new
request = g.browser.get("#{VoipfoneClient::API_GET_URL}?divertsMain")
g.parse_response(request)["divertsMain"].collect do |d|
g.parse_response(request)[:divertsMain].collect do |d|
divert = GlobalDivert.new
divert.number = d[1]
divert.type = VOIPFONE_DIVERT_NAMES[d[2].downcase].to_sym
Expand Down
8 changes: 4 additions & 4 deletions lib/voipfone_client/registered_mobile.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
module VoipfoneClient
class RegisteredMobile < Session
class RegisteredMobile < Session
attr_accessor :number, :name

class << self
def all
r = RegisteredMobile.new
request = r.browser.get("#{VoipfoneClient::API_GET_URL}?registeredMobile")
r.parse_response(request)["registeredMobile"].collect do |m|
r.parse_response(request)[:registeredMobile].collect do |m|
mobile = RegisteredMobile.new
mobile.number = m[0]
mobile.name = m[1]
mobile
end
end
end
end
end
end
end
84 changes: 84 additions & 0 deletions lib/voipfone_client/report.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
module VoipfoneClient
class Report < Session
attr_accessor :type, :date, :range, :extension_filter

class << self
# Retrieves call record summaries according to requested criteria...
#
# @param type can be :incoming, :outgoing or :missed
# @param date as a Date (default is today)
# @param range can be set to :day or :month (defaults to monthly report)
# @param extension_filter is the required ext number or :all (default all)
# @return [Array] of call record summaries by day or by hour (according
# to range)

def call_records_summary( call_type = :outgoing,
date = Date.today,
range = :month,
extension_filter = :all)
if range == :month
query_date = date.strftime('%Y-%m')
response_unit = :days
else
query_date = date.strftime('%Y-%m-%d')
response_unit = :hours
end

session = self.new
query = "callRecordsSummary/#{call_type.to_s}/#{query_date}/#{range}/#{extension_filter}"
request = session.browser.get("#{VoipfoneClient::API_GET_URL}?#{query}")
session.parse_response(request)[ query.to_sym][ response_unit]
end


# Returns call record details according to requested criteria.
# Warning: these can be lengthy...
#
# @param type can be :incoming, :outgoing or :missed
# @param date as a Date (default is today)
# @param range can be set to :day or :month (defaults to daily report)
# @param extension_filter is the required ext number or :all (default all)
# @return [Array] of call record hashes containing date and time, to,
# from, duration and cost.

def call_records( call_type = :outgoing,
date = Date.today,
range = :day,
extension_filter = :all)
page = 1
records = []
query_date = date.strftime('%Y-%m')
day = date.strftime( '%d')

parameters = {
"type" => call_type.to_s,
"day" => day.to_s,
"dateRange" => query_date,
"range" => range.to_s,
"extFilter" => extension_filter.to_s
}

session = self.new
query = "#{VoipfoneClient::API_POST_URL}?callRecordsSearch"

begin
parameters[ "page"] = page.to_s
request = session.browser.post( query, parameters)
raw = JSON.parse( request.body)
records += raw.first.collect do |rec|
{ datetime: DateTime.parse( rec[0]),
from: rec[1],
to: rec[2],
duration: rec[3],
cost: rec[4],
package_minutes: rec[5]
}
end
page += 1
end until raw.empty? || raw.first.empty?

return records
end
end
end
end
Loading