restcomm-ruby 1.2.0
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.
- data/AUTHORS.md +38 -0
- data/CHANGES.md +171 -0
- data/Gemfile +11 -0
- data/LICENSE +662 -0
- data/LICENSE.md +19 -0
- data/Makefile +12 -0
- data/README.md +155 -0
- data/Rakefile +10 -0
- data/conf/cacert.pem +3376 -0
- data/docs/Makefile +130 -0
- data/docs/_themes/LICENSE +45 -0
- data/docs/_themes/README.rst +25 -0
- data/docs/_themes/flask_theme_support.py +86 -0
- data/docs/_themes/kr/layout.html +32 -0
- data/docs/_themes/kr/relations.html +19 -0
- data/docs/_themes/kr/static/flasky.css_t +469 -0
- data/docs/_themes/kr/static/small_flask.css +70 -0
- data/docs/_themes/kr/theme.conf +7 -0
- data/docs/_themes/kr_small/layout.html +22 -0
- data/docs/_themes/kr_small/static/flasky.css_t +287 -0
- data/docs/_themes/kr_small/theme.conf +10 -0
- data/docs/changelog.rst +1 -0
- data/docs/conf.py +266 -0
- data/docs/faq.rst +42 -0
- data/docs/getting-started.rst +100 -0
- data/docs/index.rst +109 -0
- data/docs/make.bat +170 -0
- data/docs/src/pip-delete-this-directory.txt +5 -0
- data/docs/usage/accounts.rst +96 -0
- data/docs/usage/addresses.rst +102 -0
- data/docs/usage/applications.rst +111 -0
- data/docs/usage/basics.rst +120 -0
- data/docs/usage/caller-ids.rst +47 -0
- data/docs/usage/conferences.rst +112 -0
- data/docs/usage/errors.rst +31 -0
- data/docs/usage/messages.rst +142 -0
- data/docs/usage/notifications.rst +72 -0
- data/docs/usage/phone-calls.rst +193 -0
- data/docs/usage/phone-numbers.rst +192 -0
- data/docs/usage/queues.rst +117 -0
- data/docs/usage/recordings.rst +102 -0
- data/docs/usage/sip.rst +108 -0
- data/docs/usage/token-generation.rst +96 -0
- data/docs/usage/transcriptions.rst +34 -0
- data/docs/usage/twiml.rst +69 -0
- data/docs/usage/validation.rst +107 -0
- data/examples/examples.rb +200 -0
- data/examples/print-call-log.rb +25 -0
- data/lib/rack/restcomm_webhook_authentication.rb +47 -0
- data/lib/restcomm-ruby.rb +103 -0
- data/lib/restcomm-ruby/rest/accounts.rb +17 -0
- data/lib/restcomm-ruby/rest/addresses.rb +12 -0
- data/lib/restcomm-ruby/rest/addresses/dependent_phone_numbers.rb +6 -0
- data/lib/restcomm-ruby/rest/applications.rb +6 -0
- data/lib/restcomm-ruby/rest/authorized_connect_apps.rb +6 -0
- data/lib/restcomm-ruby/rest/available_phone_numbers.rb +13 -0
- data/lib/restcomm-ruby/rest/available_phone_numbers/country.rb +10 -0
- data/lib/restcomm-ruby/rest/available_phone_numbers/local.rb +11 -0
- data/lib/restcomm-ruby/rest/available_phone_numbers/mobile.rb +11 -0
- data/lib/restcomm-ruby/rest/available_phone_numbers/toll_free.rb +11 -0
- data/lib/restcomm-ruby/rest/call_feedback.rb +28 -0
- data/lib/restcomm-ruby/rest/call_feedback_summary.rb +13 -0
- data/lib/restcomm-ruby/rest/calls.rb +37 -0
- data/lib/restcomm-ruby/rest/client.rb +555 -0
- data/lib/restcomm-ruby/rest/conferences.rb +12 -0
- data/lib/restcomm-ruby/rest/conferences/participants.rb +23 -0
- data/lib/restcomm-ruby/rest/connect_apps.rb +6 -0
- data/lib/restcomm-ruby/rest/errors.rb +14 -0
- data/lib/restcomm-ruby/rest/incoming_phone_numbers.rb +17 -0
- data/lib/restcomm-ruby/rest/incoming_phone_numbers/local.rb +13 -0
- data/lib/restcomm-ruby/rest/incoming_phone_numbers/mobile.rb +13 -0
- data/lib/restcomm-ruby/rest/incoming_phone_numbers/toll_free.rb +13 -0
- data/lib/restcomm-ruby/rest/instance_resource.rb +88 -0
- data/lib/restcomm-ruby/rest/list_resource.rb +132 -0
- data/lib/restcomm-ruby/rest/media.rb +14 -0
- data/lib/restcomm-ruby/rest/messages.rb +23 -0
- data/lib/restcomm-ruby/rest/next_gen_list_resource.rb +29 -0
- data/lib/restcomm-ruby/rest/notifications.rb +6 -0
- data/lib/restcomm-ruby/rest/outgoing_caller_ids.rb +25 -0
- data/lib/restcomm-ruby/rest/queues.rb +12 -0
- data/lib/restcomm-ruby/rest/queues/members.rb +29 -0
- data/lib/restcomm-ruby/rest/recordings.rb +35 -0
- data/lib/restcomm-ruby/rest/sandbox.rb +5 -0
- data/lib/restcomm-ruby/rest/sip.rb +10 -0
- data/lib/restcomm-ruby/rest/sip/credential_lists.rb +11 -0
- data/lib/restcomm-ruby/rest/sip/credential_lists/credentials.rb +6 -0
- data/lib/restcomm-ruby/rest/sip/domains.rb +12 -0
- data/lib/restcomm-ruby/rest/sip/domains/credential_list_mappings.rb +6 -0
- data/lib/restcomm-ruby/rest/sip/domains/ip_access_control_list_mappings.rb +6 -0
- data/lib/restcomm-ruby/rest/sip/ip_access_control_lists.rb +11 -0
- data/lib/restcomm-ruby/rest/sip/ip_access_control_lists/ip_addresses.rb +6 -0
- data/lib/restcomm-ruby/rest/sms.rb +11 -0
- data/lib/restcomm-ruby/rest/sms/messages.rb +39 -0
- data/lib/restcomm-ruby/rest/sms/short_codes.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/activities.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/events.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/reservations.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/task_queues.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/task_queues_statistics.rb +15 -0
- data/lib/restcomm-ruby/rest/task_router/tasks.rb +15 -0
- data/lib/restcomm-ruby/rest/task_router/workers.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/workers_statistics.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/workflow_statistics.rb +7 -0
- data/lib/restcomm-ruby/rest/task_router/workflows.rb +8 -0
- data/lib/restcomm-ruby/rest/task_router/workspace_statistics.rb +7 -0
- data/lib/restcomm-ruby/rest/task_router/workspaces.rb +15 -0
- data/lib/restcomm-ruby/rest/tokens.rb +7 -0
- data/lib/restcomm-ruby/rest/transcriptions.rb +6 -0
- data/lib/restcomm-ruby/rest/usage.rb +10 -0
- data/lib/restcomm-ruby/rest/usage/records.rb +21 -0
- data/lib/restcomm-ruby/rest/usage/triggers.rb +12 -0
- data/lib/restcomm-ruby/rest/utils.rb +49 -0
- data/lib/restcomm-ruby/task_router.rb +0 -0
- data/lib/restcomm-ruby/task_router/capability.rb +87 -0
- data/lib/restcomm-ruby/twiml/response.rb +16 -0
- data/lib/restcomm-ruby/util.rb +15 -0
- data/lib/restcomm-ruby/util/capability.rb +64 -0
- data/lib/restcomm-ruby/util/configuration.rb +7 -0
- data/lib/restcomm-ruby/util/request_validator.rb +37 -0
- data/lib/restcomm-ruby/version.rb +3 -0
- data/restcomm-ruby.gemspec +34 -0
- data/spec/rack/twilio_webhook_authentication_spec.rb +110 -0
- data/spec/rest/account_spec.rb +89 -0
- data/spec/rest/address_spec.rb +11 -0
- data/spec/rest/call_feedback_spec.rb +12 -0
- data/spec/rest/call_feedback_summary_spec.rb +9 -0
- data/spec/rest/call_spec.rb +22 -0
- data/spec/rest/client_spec.rb +258 -0
- data/spec/rest/conference_spec.rb +11 -0
- data/spec/rest/instance_resource_spec.rb +15 -0
- data/spec/rest/message_spec.rb +12 -0
- data/spec/rest/numbers_spec.rb +58 -0
- data/spec/rest/queue_spec.rb +11 -0
- data/spec/rest/recording_spec.rb +11 -0
- data/spec/rest/sms/message_spec.rb +37 -0
- data/spec/rest/sms/messages_spec.rb +36 -0
- data/spec/rest/task_router/reservation_spec.rb +9 -0
- data/spec/rest/task_router/task_queue_spec.rb +9 -0
- data/spec/rest/token_spec.rb +7 -0
- data/spec/rest/utils_spec.rb +45 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/fakeweb.rb +2 -0
- data/spec/task_router_spec.rb +114 -0
- data/spec/twilio_spec.rb +15 -0
- data/spec/util/capability_spec.rb +186 -0
- data/spec/util/configuration_spec.rb +13 -0
- data/spec/util/request_validator_spec.rb +93 -0
- data/spec/util/url_encode_spec.rb +12 -0
- metadata +298 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
.. _usage-twiml:
|
|
2
|
+
|
|
3
|
+
.. module:: restcomm.twiml
|
|
4
|
+
|
|
5
|
+
==============
|
|
6
|
+
RCML Creation
|
|
7
|
+
==============
|
|
8
|
+
|
|
9
|
+
RCML creation begins with the :class:`Response` verb.
|
|
10
|
+
Each successive verb is created by calling various methods on the response,
|
|
11
|
+
such as :meth:`say` or :meth:`play`.
|
|
12
|
+
These methods return the verbs they create to ease creation of nested RCML.
|
|
13
|
+
To finish, call the :meth:`toxml` method on the :class:`Response`,
|
|
14
|
+
which returns raw RCML.
|
|
15
|
+
|
|
16
|
+
.. code-block:: ruby
|
|
17
|
+
|
|
18
|
+
require 'restcomm-ruby'
|
|
19
|
+
|
|
20
|
+
Restcomm::RCML::Response.new do |r|
|
|
21
|
+
r.Say "Hello"
|
|
22
|
+
end.text
|
|
23
|
+
|
|
24
|
+
.. code-block:: xml
|
|
25
|
+
|
|
26
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
27
|
+
<Response><Say>Hello</Say><Response>
|
|
28
|
+
|
|
29
|
+
The verb methods (outlined in the :doc:`complete reference </api/twiml>`)
|
|
30
|
+
take the body (only text) of the verb as the first argument.
|
|
31
|
+
All attributes are keyword arguments.
|
|
32
|
+
|
|
33
|
+
.. code-block:: ruby
|
|
34
|
+
|
|
35
|
+
require 'restcomm-ruby'
|
|
36
|
+
|
|
37
|
+
Restcomm::RCML::Response.new do |r|
|
|
38
|
+
r.Play "https://api.restcomm.com/cowbell.mp3", loop: 5
|
|
39
|
+
end.text
|
|
40
|
+
|
|
41
|
+
.. code-block:: xml
|
|
42
|
+
|
|
43
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
44
|
+
<Response>
|
|
45
|
+
<Play loop="3">https://SOME_WEBSITE/cowbell.mp3</Play>
|
|
46
|
+
<Response>
|
|
47
|
+
|
|
48
|
+
Any example of nesting nouns in verbs
|
|
49
|
+
|
|
50
|
+
.. code-block:: ruby
|
|
51
|
+
|
|
52
|
+
require 'restcomm-ruby'
|
|
53
|
+
|
|
54
|
+
Restcomm::RCML::Response.new do |r|
|
|
55
|
+
r.Say "hello"
|
|
56
|
+
r.Gather finishOnKey: => 4 do |g|
|
|
57
|
+
g.Say "world"
|
|
58
|
+
end
|
|
59
|
+
end.text
|
|
60
|
+
|
|
61
|
+
which returns the following
|
|
62
|
+
|
|
63
|
+
.. code-block:: xml
|
|
64
|
+
|
|
65
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
66
|
+
<Response>
|
|
67
|
+
<Say>Hello</Say>
|
|
68
|
+
<Gather finishOnKey="4"><Say>World</Say></Gather>
|
|
69
|
+
</Response>
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
.. module:: restcomm.util
|
|
2
|
+
|
|
3
|
+
===========================
|
|
4
|
+
Validate Incoming Requests
|
|
5
|
+
===========================
|
|
6
|
+
|
|
7
|
+
Restcomm requires that your RCML-serving web server be open to the public. This
|
|
8
|
+
is necessary so that Restcomm can retrieve RCML from urls and POST data back to
|
|
9
|
+
your server.
|
|
10
|
+
|
|
11
|
+
However, there may be people out there trying to spoof the Restcomm service.
|
|
12
|
+
Luckily, there's an easy way to validate that incoming requests are from Restcomm
|
|
13
|
+
and Restcomm alone.
|
|
14
|
+
|
|
15
|
+
An in-depth guide to our security features can be `found in our online
|
|
16
|
+
documentation <http://docs.telestax.com/restcomm-pages/>`_.
|
|
17
|
+
|
|
18
|
+
Before you can validate requests, you'll need four pieces of information:
|
|
19
|
+
|
|
20
|
+
* your Restcomm Auth Token (found in your `Dashboard
|
|
21
|
+
<https://www.restcomm.com/user/account>`_)
|
|
22
|
+
* the POST data for the request
|
|
23
|
+
* the requested URL
|
|
24
|
+
* the X-Restcomm-Signature header value
|
|
25
|
+
|
|
26
|
+
Obtaining the last three pieces of information depends on the framework you are
|
|
27
|
+
using to process requests. The below example assumes that you have the POST
|
|
28
|
+
data as a dictionary and the url and X-Restcomm-Signature as strings.
|
|
29
|
+
|
|
30
|
+
The below example will print out a confirmation message if the request is
|
|
31
|
+
actually from Restcomm.
|
|
32
|
+
|
|
33
|
+
.. code-block:: ruby
|
|
34
|
+
|
|
35
|
+
require 'restcomm-ruby'
|
|
36
|
+
|
|
37
|
+
auth_token = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'
|
|
38
|
+
|
|
39
|
+
@validator = Restcomm::Util::RequestValidator.new auth_token
|
|
40
|
+
|
|
41
|
+
# the callback URL you provided to Restcomm
|
|
42
|
+
url = "http://www.example.com/my/callback/url.xml"
|
|
43
|
+
|
|
44
|
+
# the POST variables attached to the request (eg "From", "To")
|
|
45
|
+
post_vars = {}
|
|
46
|
+
|
|
47
|
+
# X-Restcomm-Signature header value
|
|
48
|
+
signature = "HpS7PBa1Agvt4OtO+wZp75IuQa0=" # will look something like that
|
|
49
|
+
|
|
50
|
+
if @validator.validate(url, post_vars, signature)
|
|
51
|
+
puts "Confirmed to have come from Restcomm."
|
|
52
|
+
else
|
|
53
|
+
puts "NOT VALID. It might have been spoofed!"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
Trailing Slashes
|
|
57
|
+
==================
|
|
58
|
+
|
|
59
|
+
If your URL uses an "index" page, such as index.php or index.html to handle
|
|
60
|
+
the request, such as: https://mycompany.com/restcomm where the real page
|
|
61
|
+
is served from https://mycompany.com/restcomm/index.php, then Apache or
|
|
62
|
+
PHP may rewrite that URL a little bit so it's got a trailing slash, such as
|
|
63
|
+
https://mycompany.com/restcomm/ for example.
|
|
64
|
+
|
|
65
|
+
Using the code above, or similar code in another language, you could
|
|
66
|
+
end up with an incorrect hash because Restcomm built the hash using
|
|
67
|
+
https://mycompany.com/restcomm and you may have built the hash using
|
|
68
|
+
https://mycompany.com/restcomm/. More information can be found in our
|
|
69
|
+
documentation on validating requests.
|
|
70
|
+
|
|
71
|
+
Rack Middleware
|
|
72
|
+
===============
|
|
73
|
+
|
|
74
|
+
If you are serving up your site using a Rack based framework, such as Sinatra or
|
|
75
|
+
Rails, you can use the Rack middleware that is included in the gem to protect
|
|
76
|
+
from spoofing attempts.
|
|
77
|
+
|
|
78
|
+
To use the middleware, you need to set it up with your Restcomm Auth Token and a
|
|
79
|
+
set of paths to watch. For example, here is how you would use the middleware in
|
|
80
|
+
a Sinatra application:
|
|
81
|
+
|
|
82
|
+
.. code-block:: ruby
|
|
83
|
+
|
|
84
|
+
require 'sinatra'
|
|
85
|
+
require 'restcomm-ruby'
|
|
86
|
+
|
|
87
|
+
auth_token = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'
|
|
88
|
+
|
|
89
|
+
use Rack::RestcommWebhookAuthentication, auth_token, /\/messages/
|
|
90
|
+
|
|
91
|
+
post '/messages' do
|
|
92
|
+
# response with RCML
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
Now, any POST request to /messages in your application that doesn't validate as
|
|
96
|
+
a Restcomm request, will automatically respond with a 403 status code and your
|
|
97
|
+
action will not be hit.
|
|
98
|
+
|
|
99
|
+
If you use subaccounts and need to validate with different auth tokens, you can pass a block to the middleware instead of an auth token. The block will be passed the Account Sid making the call.
|
|
100
|
+
|
|
101
|
+
.. code-block:: ruby
|
|
102
|
+
|
|
103
|
+
use Rack::RestcommWebhookAuthentication, nil, /\/messages/ do |account_sid|
|
|
104
|
+
# lookup auth_token from account_sid
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
Ensure you pass `nil` for the auth_token when passing a block, otherwise the block will not be called.
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
#Welcomme to Restcomm
|
|
2
|
+
#The examples below will help you get started using Restcomm-ruby wraper
|
|
3
|
+
# examples version 1.2.0
|
|
4
|
+
# You must make sure the @account_sid, @auth_token and @host variables are correctly filled
|
|
5
|
+
#
|
|
6
|
+
#The @host is the IP address on which Restcomm is running (This could be a local install or a remote)
|
|
7
|
+
#
|
|
8
|
+
#
|
|
9
|
+
#
|
|
10
|
+
####### Account Settings #########
|
|
11
|
+
|
|
12
|
+
require 'restcomm-ruby'
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@account_sid = 'ACae6e420f425248d6a26948c17a9e2acf'
|
|
17
|
+
@auth_token = 'YourPassWord' #
|
|
18
|
+
@host = '192.168.1.3' #IP address of your Restcomm instance
|
|
19
|
+
# set up a client
|
|
20
|
+
@client = Restcomm::REST::Client.new(@account_sid, @auth_token, @host)
|
|
21
|
+
|
|
22
|
+
################ ACCOUNTS ################
|
|
23
|
+
|
|
24
|
+
# shortcut to grab your account object (account_sid is inferred from the client's auth credentials)
|
|
25
|
+
@account = @client.account
|
|
26
|
+
|
|
27
|
+
#list of all accounts and (sub)accounts
|
|
28
|
+
@client.accounts.list.each do |x|
|
|
29
|
+
puts "Account name: " + x.friendly_name + " Account Sid: " + x.sid
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# grab an account instance resource of a given account and display the friendly_name
|
|
33
|
+
puts @client.accounts.get(@account_sid).friendly_name
|
|
34
|
+
|
|
35
|
+
# grab an account instance resource of a given account and display the sid
|
|
36
|
+
puts @client.accounts.get(@account_sid).sid
|
|
37
|
+
|
|
38
|
+
# update an account's friendly name
|
|
39
|
+
@client.accounts.get(@account_sid).update(friendly_name: 'A Super Cool Name')
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
################ CALLS ################
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# print a list of calls (without parameters)
|
|
46
|
+
@account.calls.list().each do |x|
|
|
47
|
+
puts "Call Sid " + x.sid + " Call Status: " + x.status
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# print a list of calls (with some optional parameters)
|
|
52
|
+
|
|
53
|
+
@account.calls.list(page: 0, page_size: 1000,).each do |x|
|
|
54
|
+
puts x.sid
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# get a particular call and list its status
|
|
58
|
+
puts @account.calls.get('CAb358e7b349924ece8a968f7089222039').status
|
|
59
|
+
|
|
60
|
+
# get a particular call and list its start time
|
|
61
|
+
puts @account.calls.get('CAb358e7b349924ece8a968f7089222039').start_time
|
|
62
|
+
|
|
63
|
+
# get a particular call and list its recording URI
|
|
64
|
+
puts @account.calls.get('CAb358e7b349924ece8a968f7089222039').subresource_uris["recordings"]
|
|
65
|
+
|
|
66
|
+
#################### RECORDINGS ##################################
|
|
67
|
+
|
|
68
|
+
#get a list of recordings linked to the current account and output the call SID and date created
|
|
69
|
+
@account.recordings.list.each do |x|
|
|
70
|
+
puts "Recording SID: " + x.call_sid + " **** " + "Date Created: " + x.date_created
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
#get a list of recordings URLs with ext .wav
|
|
75
|
+
#use ext .mp3 to get the corresponding mp3 list
|
|
76
|
+
@account.recordings.list.each do |r|
|
|
77
|
+
puts r.wav
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
#################### MAKING CALLS ##################################
|
|
83
|
+
|
|
84
|
+
# make a new outgoing call. returns a call object just like calls.get
|
|
85
|
+
@call = @account.calls.create(
|
|
86
|
+
from: 'sip:+32145687',
|
|
87
|
+
to: 'sip:+1111@192.168.1.3',
|
|
88
|
+
url: 'http://192.168.1.3:8080/restcomm-rvd/services/apps/test/controller'
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# cancel the call if not already in progress
|
|
93
|
+
@account.calls.get(@call.sid).update(status: 'canceled')
|
|
94
|
+
# or equivalently
|
|
95
|
+
@call.update(status: 'canceled')
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
####### Terminate a call that is currently in-progress ########
|
|
100
|
+
|
|
101
|
+
@account.calls.get(@call.sid).update(status: 'completed')
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# redirect and then terminate a call
|
|
106
|
+
|
|
107
|
+
@call.update(url: 'http://192.168.1.3:8080/restcomm/demos/hello-play.xml')
|
|
108
|
+
@call.update(status: 'completed')
|
|
109
|
+
# or, use the aliases...
|
|
110
|
+
@call.redirect_to('http://192.168.1.3:8080/restcomm/demos/hello-play.xml')
|
|
111
|
+
@call.hangup
|
|
112
|
+
|
|
113
|
+
################ SMS MESSAGES ################
|
|
114
|
+
|
|
115
|
+
# print a list of messages
|
|
116
|
+
@account.messages.list(date_sent: '2010-09-01').each do |message|
|
|
117
|
+
puts message.body
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# print a particular sms message
|
|
121
|
+
puts @account.messages.get('SMXXXXXXXX').body
|
|
122
|
+
|
|
123
|
+
# send an sms
|
|
124
|
+
@account.messages.create(
|
|
125
|
+
from: '+14159341234',
|
|
126
|
+
to: '+16105557069',
|
|
127
|
+
body: 'Hey there!'
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# send an mms the from DID should be a number from your DID provider
|
|
131
|
+
@account.messages.create(
|
|
132
|
+
from: '+14159341234',
|
|
133
|
+
to: '+16105557069',
|
|
134
|
+
media_urls: 'http://example.com/media.png'
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
################ PHONE NUMBERS ################
|
|
138
|
+
|
|
139
|
+
# get a list of supported country codes
|
|
140
|
+
@account.available_phone_numbers.list
|
|
141
|
+
|
|
142
|
+
# print some available numbers
|
|
143
|
+
@numbers = @account.available_phone_numbers.get('US').local.list(
|
|
144
|
+
AreaCode: '305'
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
@numbers.each { |num| puts num.phone_number }
|
|
148
|
+
|
|
149
|
+
# buy the first one
|
|
150
|
+
@account.incoming_phone_numbers.create(phone_number: @numbers[0].phone_number)
|
|
151
|
+
|
|
152
|
+
# update an existing phone number's voice url
|
|
153
|
+
number = @account.incoming_phone_numbers.get('PNdba508c5616a7f5e141789f44f022cc3')
|
|
154
|
+
number.update(voice_url: 'http://example.com/voice')
|
|
155
|
+
|
|
156
|
+
# decommission an existing phone number
|
|
157
|
+
numbers = @account.incoming_phone_numbers.list(
|
|
158
|
+
friendly_name: 'A Fabulous Friendly Name'
|
|
159
|
+
)
|
|
160
|
+
numbers[0].delete
|
|
161
|
+
################ CONFERENCES ################
|
|
162
|
+
|
|
163
|
+
# get a particular conference's participants object and stash it
|
|
164
|
+
conference = @account.conferences.get('CFbbe46ff1274e283f7e3ac1df0072ab39')
|
|
165
|
+
@participants = conference.participants
|
|
166
|
+
|
|
167
|
+
# list participants
|
|
168
|
+
@participants.list.each do |p|
|
|
169
|
+
puts p.sid
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# update a conference participant
|
|
173
|
+
@participants.get('CA386025c9bf5d6052a1d1ea42b4d16662').update(muted: 'true')
|
|
174
|
+
# or an easier way
|
|
175
|
+
@participants.get('CA386025c9bf5d6052a1d1ea42b4d16662').mute
|
|
176
|
+
|
|
177
|
+
# and, since we're lazy loading, this would only incur one http request
|
|
178
|
+
@account.conferences.get('CFbbe46ff1274e283f7e3ac1df0072ab39').participants
|
|
179
|
+
.get('CA386025c9bf5d6052a1d1ea42b4d16662').update(muted: 'true')
|
|
180
|
+
|
|
181
|
+
################ QUEUES ###################
|
|
182
|
+
|
|
183
|
+
# create a new queue
|
|
184
|
+
@queue = @account.queues.create(friendly_name: 'MyQueue', max_size: 50)
|
|
185
|
+
|
|
186
|
+
# get a list of queues for this account
|
|
187
|
+
@queues = @account.queues.list
|
|
188
|
+
|
|
189
|
+
# get a particular queue and its members
|
|
190
|
+
@queue = @account.queues.get("QQb6765b0458714964970a73dcaf55efd1")
|
|
191
|
+
@members = @queue.members
|
|
192
|
+
|
|
193
|
+
#list members
|
|
194
|
+
@members.list.each do |m|
|
|
195
|
+
puts m.wait_time
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# dequeue a particular user and run twiml at a specific url
|
|
199
|
+
@member = @members.get('CA386025c9bf5d6052a1d1ea42b4d16662')
|
|
200
|
+
@member.dequeue('http://myapp.com/deque')
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'restcomm-ruby'
|
|
3
|
+
|
|
4
|
+
# print a list of all phone calls, what phone number each was to/from, and how
|
|
5
|
+
# much each one cost.
|
|
6
|
+
|
|
7
|
+
# put your Restcomm credentials here. you can find your AccountSid and AuthToken
|
|
8
|
+
# at the top of your account dashboard page located at:
|
|
9
|
+
#
|
|
10
|
+
account_sid = 'AC043dcf9844e04758bc3a36a84c29761'
|
|
11
|
+
auth_token = '62ea81de3a5b414154eb263595357c69'
|
|
12
|
+
host = 'IP_Address_Restcomm_Instance'
|
|
13
|
+
|
|
14
|
+
# set up a client
|
|
15
|
+
client = Restcomm::REST::Client.new(account_sid, auth_token, host)
|
|
16
|
+
|
|
17
|
+
calls = client.calls.list
|
|
18
|
+
|
|
19
|
+
begin
|
|
20
|
+
calls.each do |call|
|
|
21
|
+
price = call.price || '0.00' # since apparently prices can be nil...
|
|
22
|
+
puts call.sid + "\t" + call.from + "\t" + call.to + "\t" + price
|
|
23
|
+
end
|
|
24
|
+
calls = calls.next_page
|
|
25
|
+
end while not calls.empty?
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Rack
|
|
2
|
+
# Middleware that authenticates webhooks from Restcomm using the request
|
|
3
|
+
# validator.
|
|
4
|
+
#
|
|
5
|
+
# The middleware takes an auth token with which to set up the request
|
|
6
|
+
# validator and any number of paths. When a path matches the incoming request
|
|
7
|
+
# path, the request will be checked for authentication.
|
|
8
|
+
#
|
|
9
|
+
# Example:
|
|
10
|
+
#
|
|
11
|
+
# require 'rack'
|
|
12
|
+
# use Rack::RestcommWebhookAuthentication, ENV['AUTH_TOKEN'], /\/messages/
|
|
13
|
+
#
|
|
14
|
+
# The above appends this middleware to the stack, using an auth token saved in
|
|
15
|
+
# the ENV and only against paths that match /\/messages/. If the request
|
|
16
|
+
# validates then it gets passed on to the action as normal. If the request
|
|
17
|
+
# doesn't validate then the middleware responds immediately with a 403 status.
|
|
18
|
+
|
|
19
|
+
class RestcommWebhookAuthentication
|
|
20
|
+
def initialize(app, auth_token, *paths, &auth_token_lookup)
|
|
21
|
+
@app = app
|
|
22
|
+
@auth_token = auth_token
|
|
23
|
+
define_singleton_method(:get_auth_token, auth_token_lookup) if block_given?
|
|
24
|
+
@path_regex = Regexp.union(paths)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def call(env)
|
|
28
|
+
return @app.call(env) unless env["PATH_INFO"].match(@path_regex)
|
|
29
|
+
request = Rack::Request.new(env)
|
|
30
|
+
original_url = request.url
|
|
31
|
+
params = request.post? ? request.POST : {}
|
|
32
|
+
auth_token = @auth_token || get_auth_token(params['AccountSid'])
|
|
33
|
+
validator = Restcomm::Util::RequestValidator.new(auth_token)
|
|
34
|
+
signature = env['HTTP_X_TWILIO_SIGNATURE'] || ""
|
|
35
|
+
if validator.validate(original_url, params, signature)
|
|
36
|
+
@app.call(env)
|
|
37
|
+
else
|
|
38
|
+
[
|
|
39
|
+
403,
|
|
40
|
+
{'Content-Type' => 'text/plain'},
|
|
41
|
+
["Restcomm Request Validation Failed."]
|
|
42
|
+
]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|