telapi 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.gitignore +20 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +22 -0
  4. data/README.md +162 -0
  5. data/Rakefile +1 -0
  6. data/lib/telapi.rb +24 -0
  7. data/lib/telapi/account.rb +14 -0
  8. data/lib/telapi/application.rb +88 -0
  9. data/lib/telapi/available_phone_number.rb +24 -0
  10. data/lib/telapi/call.rb +214 -0
  11. data/lib/telapi/caller_id.rb +16 -0
  12. data/lib/telapi/carrier.rb +16 -0
  13. data/lib/telapi/conference.rb +206 -0
  14. data/lib/telapi/configuration.rb +40 -0
  15. data/lib/telapi/error.rb +22 -0
  16. data/lib/telapi/fraud.rb +79 -0
  17. data/lib/telapi/inbound_xml.rb +36 -0
  18. data/lib/telapi/incoming_phone_number.rb +86 -0
  19. data/lib/telapi/message.rb +47 -0
  20. data/lib/telapi/network.rb +50 -0
  21. data/lib/telapi/notification.rb +29 -0
  22. data/lib/telapi/recording.rb +69 -0
  23. data/lib/telapi/resource.rb +18 -0
  24. data/lib/telapi/resource_collection.rb +38 -0
  25. data/lib/telapi/transcription.rb +44 -0
  26. data/lib/telapi/version.rb +3 -0
  27. data/spec/spec_helper.rb +17 -0
  28. data/spec/support/telapi_helpers.rb +38 -0
  29. data/spec/telapi/account_spec.rb +17 -0
  30. data/spec/telapi/application_spec.rb +69 -0
  31. data/spec/telapi/available_phone_number_spec.rb +27 -0
  32. data/spec/telapi/call_spec.rb +173 -0
  33. data/spec/telapi/caller_id_spec.rb +17 -0
  34. data/spec/telapi/carrier_spec.rb +17 -0
  35. data/spec/telapi/conference_spec.rb +174 -0
  36. data/spec/telapi/configuration_spec.rb +38 -0
  37. data/spec/telapi/error_spec.rb +32 -0
  38. data/spec/telapi/fraud_spec.rb +55 -0
  39. data/spec/telapi/inbound_xml_spec.rb +49 -0
  40. data/spec/telapi/incoming_phone_number_spec.rb +69 -0
  41. data/spec/telapi/message_spec.rb +41 -0
  42. data/spec/telapi/network_spec.rb +80 -0
  43. data/spec/telapi/notification_spec.rb +34 -0
  44. data/spec/telapi/recording_spec.rb +72 -0
  45. data/spec/telapi/resource_collection_spec.rb +64 -0
  46. data/spec/telapi/resource_spec.rb +25 -0
  47. data/spec/telapi/transcription_spec.rb +41 -0
  48. data/telapi-ruby.gemspec +32 -0
  49. 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
@@ -0,0 +1,3 @@
1
+ module Telapi
2
+ VERSION = "1.0.0"
3
+ end
@@ -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