ringcentral 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Todd Eichel
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.
@@ -0,0 +1,178 @@
1
+ [ringcentral](http://github.com/tfe/ringcentral/)
2
+ ========
3
+
4
+ A Ruby library for interacting with the RingCentral [RingOut API](https://service.ringcentral.com/ringoutapi/) and (coming soon) [FaxOut API](https://service.ringcentral.com/faxoutapi/).
5
+
6
+ Currently it is a very thin wrapper around the native RingCentral HTTP API. Eventually I would like to document and abstract away as many of the idiosyncrasies of the native API as possible.
7
+
8
+ All four RingOut commands are supported (see "Usage" below).
9
+
10
+
11
+ Installation
12
+ ------------
13
+
14
+ Install the gem:
15
+
16
+ sudo gem install ringcentral
17
+
18
+ And if you're using Rails (not required), add it to your environment.rb configuration as a gem dependency:
19
+
20
+ config.gem 'ringcentral'
21
+
22
+ I highly recommend requiring a specific version (with the `:version` argument to `config.gem`) from your app, because this gem is young and the API *will* change.
23
+
24
+
25
+
26
+ Usage
27
+ -----
28
+
29
+ ### RingOut
30
+
31
+ When calling `list` and `call`, you will always need to supply the RingCentral account credentials as the first three arguments to the methods:
32
+
33
+ * **Username**: your main RingCentral account phone number
34
+ * **Password**: password for an individual user on your RingCentral account
35
+ * **Extension**: extension number for an individual user on your RingCentral account
36
+
37
+ For `status` and `cancel`, no credentials are required by RingCentral, just a session ID returned by the `call` method.
38
+
39
+ *Errata*
40
+
41
+ * RingCentral returns a "Call Completed" response for every session ID that's not attached to a call currently in progress.
42
+ * The "WS" parameter is returned when placing a call and is accepted as a parameter to the `status` and `cancel` methods, but as far as I can tell it doesn't do anything. RingCentral support didn't know either.
43
+
44
+
45
+ #### List
46
+
47
+ RingCentral::Phone.list(username, password, extension)
48
+
49
+ Gets a hash of the numbers associated with the provided RingCentral credentials (output formatted for readability). Example:
50
+
51
+ >> RingCentral::Phone.list('8889363711', '1234', '101')
52
+ => {
53
+ "Home" => "6505553711",
54
+ "Mobile" => "6505551233",
55
+ "Business" => "6505551550"
56
+ }
57
+
58
+
59
+
60
+ #### Call
61
+
62
+ RingCentral::Phone.call(username, password, extension, to, from, caller_id, prompt = 1)
63
+
64
+ Place a RingOut call to the `to` number, from the `from` number, and with the specified `caller_id`. Set `prompt` to `0` to avoid the "Press 1 to connect this call" prompt (default is to leave the prompt on).
65
+
66
+ The response is a session ID (which you can use to get call status or cancel the call later) and a "WS" field (see "Errata" above).
67
+
68
+ >> RingCentral::Phone.call('8889363711', '1234', '101', '6505551230', '6505551231', '8889363711')
69
+ => {
70
+ :session_id => "20",
71
+ :ws => ".62"
72
+ }
73
+
74
+
75
+ #### Status
76
+
77
+ RingCentral::Phone.status(session_id, ws = nil)
78
+
79
+ Check the status of the RingOut call with a given `session_id` in progress (or completed). The `ws` parameter appears to be unused, so it defaults to `nil`.
80
+
81
+ The response is a hash of status information: for the call as a whole, and the status for each of the numbers (callback, the originating number; and destination, the number being called). Possible values for the status are as follows:
82
+
83
+ * **Success**: picked up, line open (gets set for the callback number before the destination)
84
+ * **In Progress**: ringing (or waiting to be rung if it's the destination number)
85
+ * **Busy**: appears in the "general call status" field after call has completed
86
+ * **No Answer**
87
+ * **Rejected**: party hung up, line closed
88
+ * **Generic Error**
89
+ * **Finished**: other party hung up, line closed
90
+ * **International calls disabled**
91
+ * **Destination number prohibited**
92
+
93
+ In general, this is how I've observed call statuses to proceed over the course of the RingOut procedure:
94
+
95
+ When the call is initiated, the callback number is called. All statuses are "In Progress."
96
+
97
+ >> RingCentral::Phone.status(3)
98
+ => {
99
+ :general => "In Progress",
100
+ :callback => "In Progress",
101
+ :destination => "In Progress"
102
+ }
103
+
104
+ When the call to the callback number is picked up, that status goes to "Success." It will remain this way during the time it takes for the operator to respond to the call connection prompt, if you did not skip it.
105
+
106
+ >> RingCentral::Phone.status(3)
107
+ => {
108
+ :general => "In Progress",
109
+ :callback => "Success",
110
+ :destination => "In Progress"
111
+ }
112
+
113
+ When the destination number is picked up, all statuses go to "Success." They will remain this way while the call is in progress.
114
+
115
+ >> RingCentral::Phone.status(3)
116
+ => {
117
+ :general => "Success",
118
+ :callback => "Success",
119
+ :destination => "Success"
120
+ }
121
+
122
+ When both calls (to the callback and the destination numbers) have completed, the final statuses are "Call Completed." They will remain this way for a couple seconds.
123
+
124
+ >> RingCentral::Phone.status(3)
125
+ => {
126
+ :general => "Call Completed",
127
+ :callback => "Call Completed",
128
+ :destination => "Call Completed"
129
+ }
130
+
131
+ Edge cases: I haven't experimented with many cases, but as an example this is the status returned when the callback number rejects the call.
132
+
133
+ >> RingCentral::Phone.status(6)
134
+ => {
135
+ :general => "Busy",
136
+ :callback => "Rejected",
137
+ :destination => "Generic Error"
138
+ }
139
+
140
+
141
+ #### Cancel
142
+
143
+ RingCentral::Phone.cancel(session_id, ws = nil)
144
+
145
+ Cancel a RingOut call with a given `session_id`. It seems like you can only cancel while one of the numbers is still ringing, or perhaps only when the callback number is being rung. You cannot cancel a call that has been picked up and is running.
146
+
147
+ The response is simply the session ID in a hash. The same response is given no matter what the result of the API call was. Essentially this method could be considered to make a "best effort" attempt to cancel your call, but don't rely on it.
148
+
149
+ >> RingCentral::Phone.cancel(242323)
150
+ => { :session_id => "242323" }
151
+
152
+
153
+ ### FaxOut
154
+
155
+ To be implemented.
156
+
157
+
158
+ Todo
159
+ ----
160
+
161
+ * Be able to supply RingCentral account credentials once, up-front, rather than supplying with each API call.
162
+ * Wrap up the call, status, and cancel into a Call object which maintains its state.
163
+ * Set Call command arguments using response from the List command, perhaps so a user could do `call(:from => :mobile)`
164
+ * Determine how accepting the RingCentral APIs are of formatted or malformed input.
165
+ * Implement the FaxOut API.
166
+ * Write tests.
167
+
168
+
169
+ Contact
170
+ -------
171
+
172
+ Problems, comments, and pull requests all welcome. [Find me on GitHub.](http://github.com/tfe/)
173
+
174
+
175
+ Copyright
176
+ -------
177
+
178
+ Copyright © 2010 [Todd Eichel](http://toddeichel.com/) for [Fooala, Inc.](http://opensource.fooala.com/).
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "ringcentral"
8
+ gem.summary = %Q{A Ruby library for interacting with the RingCentral RingOut API and (coming soon) FaxOut API.}
9
+ gem.description = %Q{A Ruby library for interacting with the RingCentral RingOut API and (coming soon) FaxOut API.}
10
+ gem.email = "todd@toddeichel.com"
11
+ gem.homepage = "http://github.com/tfe/ringcentral"
12
+ gem.authors = ["Todd Eichel"]
13
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ begin
29
+ require 'rcov/rcovtask'
30
+ Rcov::RcovTask.new do |test|
31
+ test.libs << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+ rescue LoadError
36
+ task :rcov do
37
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ end
39
+ end
40
+
41
+ task :test => :check_dependencies
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "ringcentral #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,136 @@
1
+ require 'rest_client'
2
+
3
+ module RingCentral
4
+
5
+ URL = 'https://service.ringcentral.com'
6
+
7
+ class Fax
8
+
9
+ PATH = 'faxapi.asp'
10
+ URL = [RingCentral::URL, PATH].join('/')
11
+
12
+ end
13
+
14
+ class Phone
15
+
16
+ PATH = 'ringout.asp'
17
+ URL = [RingCentral::URL, PATH].join('/')
18
+ SuccessResponse = 'OK'
19
+
20
+ STATUS_CODES = {
21
+ 0 => 'Success', # picked up, line open (gets set for the callback number before the destination)
22
+ 1 => 'In Progress', # ringing (or waiting to be rung if it's the destination number)
23
+ 2 => 'Busy', # appears in the "general call status" field after call has completed
24
+ 3 => 'No Answer',
25
+ 4 => 'Rejected', # party hung up, line closed
26
+ 5 => 'Generic Error',
27
+ 6 => 'Finished', # other party hung up, line closed
28
+ 7 => 'International calls disabled',
29
+ 8 => 'Destination number prohibited'
30
+ }
31
+
32
+
33
+ def self.list(username, password, extension)
34
+
35
+ params = { :cmd => :list }
36
+ response = RestClient.post(URL, params.merge(RingCentral.credentials_hash(username, password, extension)))
37
+ body = response.body
38
+
39
+ if body[0..1] == SuccessResponse # sucessful responses start with "OK "
40
+ data = body[3..-1]
41
+ return Hash[*data.split(';')].invert
42
+ else
43
+ raise "RingCentral response: #{body}"
44
+ end
45
+ end
46
+
47
+
48
+ def self.call(username, password, extension, to, from, caller_id, prompt = 1)
49
+
50
+ params = {
51
+ :cmd => :call,
52
+ :to => to,
53
+ :from => from,
54
+ :clid => caller_id,
55
+ :prompt => prompt
56
+ }
57
+ response = RestClient.post(URL, params.merge(RingCentral.credentials_hash(username, password, extension)))
58
+ body = response.body
59
+
60
+ if body[0..1] == SuccessResponse # sucessful responses start with "OK "
61
+ session_id, ws = body[3..-1].split(' ')
62
+ return { :session_id => session_id, :ws => ws }
63
+ else
64
+ raise "RingCentral response: #{body}"
65
+ end
66
+ end
67
+
68
+
69
+ # Notes:
70
+ # - WS param doesn't seem to do anything or even be required
71
+ # - API always gives the "completed call" response regardless of whether the session ID is valid
72
+ # - while call is running (and for a few seconds after it is disconnected), status string with both callback
73
+ # and destination number are given, with statuses for both; after that, only the session ID is given
74
+ def self.status(session_id, ws = nil)
75
+
76
+ params = {
77
+ :cmd => :status,
78
+ :sessionid => session_id,
79
+ :ws => ws
80
+ }
81
+ response = RestClient.post(URL, params)
82
+ body = response.body
83
+
84
+ if body[0..1] == SuccessResponse # sucessful responses start with "OK "
85
+ session_id, statuses = body[3..-1].split(' ')
86
+ if statuses
87
+ statuses = statuses.split(';')
88
+ return {
89
+ :general => STATUS_CODES[statuses[0].to_i],
90
+ :destination => STATUS_CODES[statuses[2].to_i],
91
+ :callback => STATUS_CODES[statuses[4].to_i]
92
+ }
93
+ else
94
+ return {
95
+ :general => "Call Completed",
96
+ :destination => "Call Completed",
97
+ :callback => "Call Completed"
98
+ }
99
+ end
100
+ else
101
+ raise "RingCentral response: #{body}"
102
+ end
103
+ end
104
+
105
+
106
+ def self.cancel(session_id, ws = nil)
107
+
108
+ params = {
109
+ :cmd => :cancel,
110
+ :sessionid => session_id,
111
+ :ws => ws
112
+ }
113
+ response = RestClient.post(URL, params)
114
+ body = response.body
115
+
116
+ if body[0..1] == SuccessResponse # sucessful responses start with "OK "
117
+ session_id = body[3..-1]
118
+ return { :session_id => session_id }
119
+ else
120
+ raise "RingCentral response: #{body}"
121
+ end
122
+ end
123
+ end
124
+
125
+
126
+ private
127
+
128
+ def self.credentials_hash(username, password, extension = nil)
129
+ {
130
+ :username => username,
131
+ :password => password,
132
+ :ext => extension
133
+ }
134
+ end
135
+
136
+ end
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. lib ringcentral])
@@ -0,0 +1,55 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{ringcentral}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Todd Eichel"]
12
+ s.date = %q{2010-07-31}
13
+ s.description = %q{A Ruby library for interacting with the RingCentral RingOut API and (coming soon) FaxOut API.}
14
+ s.email = %q{todd@toddeichel.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.md",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/ringcentral.rb",
27
+ "rails/init.rb",
28
+ "ringcentral.gemspec",
29
+ "test/helper.rb",
30
+ "test/test_ringcentral.rb"
31
+ ]
32
+ s.homepage = %q{http://github.com/tfe/ringcentral}
33
+ s.rdoc_options = ["--charset=UTF-8"]
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = %q{1.3.6}
36
+ s.summary = %q{A Ruby library for interacting with the RingCentral RingOut API and (coming soon) FaxOut API.}
37
+ s.test_files = [
38
+ "test/helper.rb",
39
+ "test/test_ringcentral.rb"
40
+ ]
41
+
42
+ if s.respond_to? :specification_version then
43
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
47
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
48
+ else
49
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
50
+ end
51
+ else
52
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
53
+ end
54
+ end
55
+
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'ringcentral'
8
+
9
+ class Test::Unit::TestCase
10
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestRingcentral < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ringcentral
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Todd Eichel
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-07-31 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: thoughtbot-shoulda
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :development
31
+ version_requirements: *id001
32
+ description: A Ruby library for interacting with the RingCentral RingOut API and (coming soon) FaxOut API.
33
+ email: todd@toddeichel.com
34
+ executables: []
35
+
36
+ extensions: []
37
+
38
+ extra_rdoc_files:
39
+ - LICENSE
40
+ - README.md
41
+ files:
42
+ - .document
43
+ - .gitignore
44
+ - LICENSE
45
+ - README.md
46
+ - Rakefile
47
+ - VERSION
48
+ - lib/ringcentral.rb
49
+ - rails/init.rb
50
+ - ringcentral.gemspec
51
+ - test/helper.rb
52
+ - test/test_ringcentral.rb
53
+ has_rdoc: true
54
+ homepage: http://github.com/tfe/ringcentral
55
+ licenses: []
56
+
57
+ post_install_message:
58
+ rdoc_options:
59
+ - --charset=UTF-8
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.6
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: A Ruby library for interacting with the RingCentral RingOut API and (coming soon) FaxOut API.
83
+ test_files:
84
+ - test/helper.rb
85
+ - test/test_ringcentral.rb