telapi 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +162 -0
- data/Rakefile +1 -0
- data/lib/telapi.rb +24 -0
- data/lib/telapi/account.rb +14 -0
- data/lib/telapi/application.rb +88 -0
- data/lib/telapi/available_phone_number.rb +24 -0
- data/lib/telapi/call.rb +214 -0
- data/lib/telapi/caller_id.rb +16 -0
- data/lib/telapi/carrier.rb +16 -0
- data/lib/telapi/conference.rb +206 -0
- data/lib/telapi/configuration.rb +40 -0
- data/lib/telapi/error.rb +22 -0
- data/lib/telapi/fraud.rb +79 -0
- data/lib/telapi/inbound_xml.rb +36 -0
- data/lib/telapi/incoming_phone_number.rb +86 -0
- data/lib/telapi/message.rb +47 -0
- data/lib/telapi/network.rb +50 -0
- data/lib/telapi/notification.rb +29 -0
- data/lib/telapi/recording.rb +69 -0
- data/lib/telapi/resource.rb +18 -0
- data/lib/telapi/resource_collection.rb +38 -0
- data/lib/telapi/transcription.rb +44 -0
- data/lib/telapi/version.rb +3 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/support/telapi_helpers.rb +38 -0
- data/spec/telapi/account_spec.rb +17 -0
- data/spec/telapi/application_spec.rb +69 -0
- data/spec/telapi/available_phone_number_spec.rb +27 -0
- data/spec/telapi/call_spec.rb +173 -0
- data/spec/telapi/caller_id_spec.rb +17 -0
- data/spec/telapi/carrier_spec.rb +17 -0
- data/spec/telapi/conference_spec.rb +174 -0
- data/spec/telapi/configuration_spec.rb +38 -0
- data/spec/telapi/error_spec.rb +32 -0
- data/spec/telapi/fraud_spec.rb +55 -0
- data/spec/telapi/inbound_xml_spec.rb +49 -0
- data/spec/telapi/incoming_phone_number_spec.rb +69 -0
- data/spec/telapi/message_spec.rb +41 -0
- data/spec/telapi/network_spec.rb +80 -0
- data/spec/telapi/notification_spec.rb +34 -0
- data/spec/telapi/recording_spec.rb +72 -0
- data/spec/telapi/resource_collection_spec.rb +64 -0
- data/spec/telapi/resource_spec.rb +25 -0
- data/spec/telapi/transcription_spec.rb +41 -0
- data/telapi-ruby.gemspec +32 -0
- metadata +227 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
module Telapi
|
2
|
+
# Wraps TelAPI SMS Message functionality
|
3
|
+
class Message < Resource
|
4
|
+
class << self
|
5
|
+
MAX_BODY_LENGTH = 160
|
6
|
+
|
7
|
+
# Returns a resource collection containing Telapi::Message objects
|
8
|
+
# See http://www.telapi.com/docs/api/rest/sms/list/
|
9
|
+
#
|
10
|
+
# Optional params is a hash containing:
|
11
|
+
# +To+:: mobile phone number
|
12
|
+
# +From+:: TelAPI or mobile phone number
|
13
|
+
# +DateSent+:: date in the following format: YYYY-MM-DD
|
14
|
+
# +Page+:: integer greater than 0
|
15
|
+
# +PageSize+:: integer greater than 0
|
16
|
+
def list(optional_params = {})
|
17
|
+
response = Network.get(['SMS', 'Messages'], optional_params)
|
18
|
+
ResourceCollection.new(response, 'sms_messages', self)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns a specific Telapi::Message object given its id
|
22
|
+
# See http://www.telapi.com/docs/api/rest/sms/view/
|
23
|
+
def get(id)
|
24
|
+
response = Network.get(['SMS', 'Messages', id])
|
25
|
+
Message.new(response)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Creates an SMS Message, returning a Telapi::Message object
|
29
|
+
# See http://www.telapi.com/docs/api/rest/sms/send/
|
30
|
+
#
|
31
|
+
# Required params:
|
32
|
+
# +to+:: mobile phone number
|
33
|
+
# +from+:: TelAPI or mobile phone number
|
34
|
+
# +body+:: plain text up to 160 characters in length
|
35
|
+
#
|
36
|
+
# Optional params:
|
37
|
+
# +status_callback+:: valid URL
|
38
|
+
def create(to, from, body, status_callback=nil)
|
39
|
+
raise RangeError, "Body must be between 0 and #{MAX_BODY_LENGTH} characters" if body.length>MAX_BODY_LENGTH || body.length==0
|
40
|
+
opts = { :To => to, :From => from, :Body => body, :StatusCallback => status_callback }
|
41
|
+
response = Network.post(['SMS', 'Messages'], opts)
|
42
|
+
Message.new(response)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module Telapi
|
4
|
+
# Internal object for network operations; wraps HTTParty
|
5
|
+
module Network #:nodoc:
|
6
|
+
include HTTParty
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def get(path_components=[], query=nil)
|
10
|
+
options = default_options.merge(:query => query)
|
11
|
+
handle_response(HTTParty.get api_uri(path_components), options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def post(path_components=[], body)
|
15
|
+
options = default_options.merge(:body => body)
|
16
|
+
handle_response(HTTParty.post api_uri(path_components), options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def delete(path_components=[])
|
20
|
+
handle_response(HTTParty.delete api_uri(path_components), default_options)
|
21
|
+
end
|
22
|
+
|
23
|
+
# path_components is an array of uri fragments, e.g ['Calls', '1234abc']
|
24
|
+
def api_uri(path_components=[])
|
25
|
+
[ Telapi.config.base_uri, 'Accounts', Telapi.config.account_sid, path_components ].flatten.join('/') + response_format
|
26
|
+
end
|
27
|
+
|
28
|
+
def response_format
|
29
|
+
@api_format ||= '.json'
|
30
|
+
end
|
31
|
+
|
32
|
+
def default_options
|
33
|
+
{
|
34
|
+
:basic_auth => {
|
35
|
+
:username => (Telapi.config.account_sid || raise(InvalidConfiguration, 'account_sid')),
|
36
|
+
:password => (Telapi.config.auth_token || raise(InvalidConfiguration, 'auth_token'))
|
37
|
+
},
|
38
|
+
:ssl_ca_path => Telapi.config.ssl_ca_path
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def handle_response(response)
|
45
|
+
raise Telapi::ApiError.new(response.parsed_response) unless response.success?
|
46
|
+
response
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Telapi
|
2
|
+
# Wraps TelAPI Notification functionality
|
3
|
+
class Notification < Resource
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# Returns a resource collection containing Telapi::Notification objects
|
7
|
+
# See http://www.telapi.com/docs/api/rest/notifications/list/
|
8
|
+
#
|
9
|
+
# Also, notifications can be scoped to a call, see Telapi::Call::notifications
|
10
|
+
#
|
11
|
+
# Optional params is a hash containing:
|
12
|
+
# +Log+:: 0 (error), 1 (warning), or 2 (info)
|
13
|
+
# +Page+:: integer greater than 0
|
14
|
+
# +PageSize+:: integer greater than 0
|
15
|
+
def list(optional_params = {})
|
16
|
+
response = Network.get(['Notifications'], optional_params)
|
17
|
+
ResourceCollection.new(response, 'notifications', self)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns a Telapi::Notification object given its id
|
21
|
+
# See http://www.telapi.com/docs/api/rest/notifications/view/
|
22
|
+
def get(id)
|
23
|
+
response = Network.get(['Notifications', id])
|
24
|
+
Notification.new(response)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Telapi
|
2
|
+
# Wraps TelAPI Recording functionality
|
3
|
+
class Recording < Resource
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# Returns a resource collection containing Telapi::Recording objects
|
7
|
+
# See http://www.telapi.com/docs/api/rest/recordings/list/
|
8
|
+
#
|
9
|
+
# Also, recordings can be scoped to a call, see Telapi::Call::recordings
|
10
|
+
#
|
11
|
+
# Optional params is a hash containing:
|
12
|
+
# +DateCreated+:: date in the following format: YYYY-MM-DD
|
13
|
+
# +Page+:: integer greater than 0
|
14
|
+
# +PageSize+:: integer greater than 0
|
15
|
+
def list(optional_params = {})
|
16
|
+
response = Network.get(['Recordings'], optional_params)
|
17
|
+
ResourceCollection.new(response, 'recordings', self)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns a Telapi::Recording object given its id
|
21
|
+
# See http://www.telapi.com/docs/api/rest/recordings/view/
|
22
|
+
def get(id)
|
23
|
+
response = Network.get(['Recordings', id])
|
24
|
+
Recording.new(response)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Transcribes a recording and returns a Telapi::Transcription object
|
28
|
+
# See http://www.telapi.com/docs/api/rest/transcriptions/transcribe-recording/
|
29
|
+
#
|
30
|
+
# Required params:
|
31
|
+
# +id+:: recording id
|
32
|
+
#
|
33
|
+
# Optional params is a hash containing:
|
34
|
+
# +TranscribeCallback+:: valid URL
|
35
|
+
# +CallbackMethod+:: (POST) or GET
|
36
|
+
# +Quality+:: (auto), silver, gold, or platinum
|
37
|
+
def transcribe(id, optional_params = {})
|
38
|
+
response = Network.post(['Recordings', id, 'Transcriptions'], optional_params)
|
39
|
+
Transcription.new(response)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns a resource collection containing Telapi::Transcription objects
|
43
|
+
# See http://www.telapi.com/docs/api/rest/transcriptions/list/
|
44
|
+
#
|
45
|
+
# Required params:
|
46
|
+
# +id+:: recording id
|
47
|
+
#
|
48
|
+
# Optional params is a hash containing:
|
49
|
+
# +Page+:: integer greater than 0
|
50
|
+
# +PageSize+:: integer greater than 0
|
51
|
+
def transcriptions(id, optional_params = {})
|
52
|
+
response = Network.get(['Recordings', id, 'Transcriptions'], optional_params)
|
53
|
+
ResourceCollection.new(response, 'transcriptions', Transcription)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
# See ::transcribe
|
59
|
+
def transcribe(optional_params = {})
|
60
|
+
self.class.transcribe(self.sid, optional_params)
|
61
|
+
end
|
62
|
+
|
63
|
+
# See ::transcriptions
|
64
|
+
def transcriptions(optional_params = {})
|
65
|
+
self.class.transcriptions(self.sid, optional_params)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'recursive_open_struct'
|
2
|
+
|
3
|
+
module Telapi
|
4
|
+
# Base class provides basic behavior for Telapi domain objects
|
5
|
+
# You don't typically instantiate this class directly
|
6
|
+
class Resource < RecursiveOpenStruct
|
7
|
+
include Network
|
8
|
+
|
9
|
+
def initialize(attributes={})
|
10
|
+
super
|
11
|
+
delete_field('subresource_uris') if respond_to?(:subresource_uris)
|
12
|
+
end
|
13
|
+
|
14
|
+
def attributes
|
15
|
+
marshal_dump
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Telapi
|
4
|
+
# This class wraps Resource objects and provides Enumerable functionality.
|
5
|
+
#
|
6
|
+
# Note that TelAPI collections are automatically separated into pages of results,
|
7
|
+
# see http://www.telapi.com/docs/api/rest/overview/response/.
|
8
|
+
#
|
9
|
+
# Currently this container class does not automatically handle the retrieving of
|
10
|
+
# a previous/next page of results. However, all of the Resource classes that provide
|
11
|
+
# a +list+ method allow you to specify the current page and size.
|
12
|
+
class ResourceCollection
|
13
|
+
include Enumerable
|
14
|
+
extend Forwardable
|
15
|
+
|
16
|
+
attr_reader :items, :page, :num_pages, :page_size, :total, :start, :end
|
17
|
+
|
18
|
+
def initialize(attributes, collection_node_name, resource_type)
|
19
|
+
@page = attributes['page']
|
20
|
+
@num_pages = attributes['num_pages']
|
21
|
+
@page_size = attributes['page_size']
|
22
|
+
@total = attributes['total']
|
23
|
+
@start = attributes['start']
|
24
|
+
@end = attributes['end']
|
25
|
+
@items = []
|
26
|
+
|
27
|
+
attributes[collection_node_name].each do |item|
|
28
|
+
@items << resource_type.send(:new, item)
|
29
|
+
end if attributes[collection_node_name]
|
30
|
+
end
|
31
|
+
|
32
|
+
def_delegators :@items, :[], :empty?, :last
|
33
|
+
|
34
|
+
def each
|
35
|
+
@items.each { |i| yield i }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Telapi
|
2
|
+
# Wraps TelAPI Transcription functionality
|
3
|
+
class Transcription < Resource
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# Returns a resource collection containing Telapi::Transcription objects
|
7
|
+
# See http://www.telapi.com/docs/api/rest/transcriptions/list/
|
8
|
+
#
|
9
|
+
# Also, Transcriptions can be scoped to a recording, see Telapi::Recording::transcriptions
|
10
|
+
#
|
11
|
+
# Optional params is a hash containing:
|
12
|
+
# +Page+:: integer greater than 0
|
13
|
+
# +PageSize+:: integer greater than 0
|
14
|
+
def list(optional_params = {})
|
15
|
+
response = Network.get(['Transcriptions'], optional_params)
|
16
|
+
ResourceCollection.new(response, 'transcriptions', self)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns a Telapi::Transcription object given its id
|
20
|
+
# See http://www.telapi.com/docs/api/rest/transcriptions/view/
|
21
|
+
def get(id)
|
22
|
+
response = Network.get(['Transcriptions', id])
|
23
|
+
Transcription.new(response)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Transcribes any audio url, returning a Telapi::Transcription object
|
27
|
+
# See http://www.telapi.com/docs/api/rest/transcriptions/transcribe-audio-url/
|
28
|
+
#
|
29
|
+
# Required params:
|
30
|
+
# +audio_url+:: valid url
|
31
|
+
#
|
32
|
+
# Optional params is a hash containing:
|
33
|
+
# +TranscribeCallback+:: valid URL
|
34
|
+
# +CallbackMethod+:: (POST) or GET
|
35
|
+
# +Quality+:: (auto), silver, gold, or platinum
|
36
|
+
def transcribe_audio(audio_url, optional_params = {})
|
37
|
+
opts = { :AudioUrl => audio_url }.merge(optional_params)
|
38
|
+
response = Network.post(['Transcriptions'], opts)
|
39
|
+
Transcription.new(response)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
|
6
|
+
require 'fakeweb'
|
7
|
+
require 'support/telapi_helpers'
|
8
|
+
require 'telapi'
|
9
|
+
|
10
|
+
FakeWeb.allow_net_connect = false
|
11
|
+
|
12
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
15
|
+
config.run_all_when_everything_filtered = true
|
16
|
+
config.include TelapiHelpers
|
17
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module TelapiHelpers #:nodoc:
|
2
|
+
def klass
|
3
|
+
described_class
|
4
|
+
end
|
5
|
+
|
6
|
+
def stub_telapi_request(body = '{"sid": "a1b2c3"}', opts={})
|
7
|
+
options = {:body => body, :content_type => "application/json"}.merge(opts)
|
8
|
+
FakeWeb.register_uri(:any, /.*telapi.com.*/, options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def stub_telapi_request_with_error_response
|
12
|
+
stub_telapi_request(
|
13
|
+
'{"status": 403,
|
14
|
+
"message": "Invalid credentials supplied",
|
15
|
+
"code": 10004,
|
16
|
+
"more_info": "http://www.telapi.com/docs/api/rest/overview/errors/10004"}',
|
17
|
+
:status => 400
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_account_sid_and_auth_token
|
22
|
+
Telapi.config do |config|
|
23
|
+
config.account_sid = 'a1b2c3'
|
24
|
+
config.auth_token = 'x5y6z7'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def reset_config
|
29
|
+
Telapi.config do |config|
|
30
|
+
config.account_sid = nil
|
31
|
+
config.auth_token = nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def api_should_use(verb_symbol, response={})
|
36
|
+
Telapi::Network.should_receive(verb_symbol).and_return(response)
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Telapi::Account do
|
4
|
+
before do
|
5
|
+
stub_telapi_request
|
6
|
+
set_account_sid_and_auth_token
|
7
|
+
end
|
8
|
+
|
9
|
+
it { should be_kind_of(Telapi::Resource) }
|
10
|
+
|
11
|
+
describe ".get" do
|
12
|
+
it "calls api via http get and returns an Account resource" do
|
13
|
+
api_should_use(:get)
|
14
|
+
klass.get.should be_a(klass)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Telapi::Application do
|
4
|
+
before do
|
5
|
+
stub_telapi_request
|
6
|
+
set_account_sid_and_auth_token
|
7
|
+
end
|
8
|
+
|
9
|
+
it { should be_kind_of(Telapi::Resource) }
|
10
|
+
|
11
|
+
describe ".list" do
|
12
|
+
before { stub_telapi_request('{ "applications": [] }') }
|
13
|
+
|
14
|
+
it "calls api via http get and returns a ResourceCollection" do
|
15
|
+
api_should_use(:get)
|
16
|
+
klass.list.should be_a(Telapi::ResourceCollection)
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when Applications exist" do
|
20
|
+
before { stub_telapi_request('{ "applications": [{ "friendly_name": "ExampleApplication" }] }') }
|
21
|
+
|
22
|
+
it "has a collection of Application objects" do
|
23
|
+
klass.list.first.should be_a(klass)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ".get" do
|
29
|
+
it "calls api via http get and returns an Application resource" do
|
30
|
+
api_should_use(:get)
|
31
|
+
klass.get('abc123').should be_a(klass)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe ".create" do
|
36
|
+
it "calls api via http post and returns an Application resource" do
|
37
|
+
api_should_use(:post)
|
38
|
+
klass.create('My App').should be_a(klass)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe ".update" do
|
43
|
+
it "calls api via http post and returns an Application resource" do
|
44
|
+
api_should_use(:post)
|
45
|
+
klass.update('123', :FriendlyName => 'new name').should be_a(klass)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#update" do
|
50
|
+
it "proxies to Application.update" do
|
51
|
+
klass.should_receive(:update)
|
52
|
+
klass.get('abc123').update(:FriendlyName => 'another name')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe ".delete" do
|
57
|
+
it "calls api via http delete and returns an Application resource" do
|
58
|
+
api_should_use(:delete)
|
59
|
+
klass.delete('123').should be_a(klass)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#delete" do
|
64
|
+
it "proxies to Application.delete" do
|
65
|
+
klass.should_receive(:delete)
|
66
|
+
klass.get('abc123').delete
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|