├── .dockerignore
├── .env.example
├── .env.example.ps1
├── .github
└── workflows
│ └── flask.yml
├── .gitignore
├── .mergify.yml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── app.py
├── docker-compose.yml
├── requirements.txt
├── screenshots
├── BrowserToBrowserCall.png
├── ConfigurePhoneNumber.png
├── ConfigurePhoneNumberWithTwiMLApps.png
├── Homepage.png
├── InitializeDevice.png
├── UnknownDevices.png
└── UpdateRequestURL.png
├── static
├── index.html
├── package-lock.json
├── package.json
├── quickstart.js
├── site.css
└── twilio.min.js
└── tests
├── conftest.py
└── test_routes.py
/.dockerignore:
--------------------------------------------------------------------------------
1 | venv/
2 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | TWILIO_ACCOUNT_SID=ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2 |
3 | # The Twilio number for making outbound and receiving inbound calls
4 | # Purchase a Twilio phone number in the console
5 | # https://www.twilio.com/console/phone-numbers/search
6 | TWILIO_CALLER_ID=+1XXXYYYZZZZ
7 |
8 | # SID of your TwiML Application
9 | # Create a new TwiML app in the console
10 | # https://www.twilio.com/console/voice/twiml/apps
11 | # OR with the Twilio CLI
12 | # twilio api:core:applications:create --friendly-name=voice-client-javascript
13 | TWILIO_TWIML_APP_SID=APXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
14 |
15 | # Your REST API Key information
16 | # Create a new key in the console and copy the SID and secret.
17 | # https://www.twilio.com/console/project/api-keys
18 | # NOTE: Make sure to copy the secret, it will only be displayed once
19 | API_KEY=SKXXXXXXXXXXXX # the SID of the key
20 | API_SECRET=XXXXXXXXXXXXXX
21 |
--------------------------------------------------------------------------------
/.env.example.ps1:
--------------------------------------------------------------------------------
1 | $Env:TWILIO_ACCOUNT_SID = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
2 | $Env:TWILIO_TWIML_APP_SID = "APXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
3 | $Env:TWILIO_CALLER_ID = "+1XXXYYYZZZZ"
4 | $Env:API_KEY = "SKXXXXXXXXXXXX"
5 | $Env:API_SECRET = "XXXXXXXXXXXXXX"
6 |
7 | # Uncomment the following if you'd like the environment variables
8 | # to be permanently set on your user account for this machine.
9 |
10 | <#
11 |
12 | [Environment]::SetEnvironmentVariable("TWILIO_ACCOUNT_SID", $Env:TWILIO_ACCOUNT_SID, "User")
13 | [Environment]::SetEnvironmentVariable("TWILIO_TWIML_APP_SID", $Env:TWILIO_TWIML_APP_SID, "User")
14 | [Environment]::SetEnvironmentVariable("TWILIO_CALLER_ID", $Env:TWILIO_CALLER_ID, "User")
15 | [Environment]::SetEnvironmentVariable("API_KEY", $Env:API_KEY, "User")
16 | [Environment]::SetEnvironmentVariable("API_SECRET", $Env:API_SECRET, "User")
17 |
18 | #>
--------------------------------------------------------------------------------
/.github/workflows/flask.yml:
--------------------------------------------------------------------------------
1 | name: Flask
2 |
3 | on:
4 | push:
5 | branches: [ master, next ]
6 | pull_request:
7 | branches: [ master, next ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ${{ matrix.platform }}
13 | strategy:
14 | max-parallel: 4
15 | matrix:
16 | python-version: [3.6, 3.7, 3.8]
17 | platform: [windows-latest, macos-latest, ubuntu-latest]
18 |
19 | steps:
20 | - uses: actions/checkout@v2
21 | - name: Set up Python ${{ matrix.python-version }}
22 | uses: actions/setup-python@v1
23 | with:
24 | python-version: ${{ matrix.python-version }}
25 | - name: Install Dependencies
26 | run: |
27 | python -m pip install --upgrade pip
28 | pip install -r requirements.txt
29 | - name: Run Tests
30 | run: |
31 | python -m pytest
32 | env:
33 | TWILIO_ACCOUNT_SID: ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
34 | TWILIO_CALLER_ID: +1XXXYYYZZZZ
35 | TWILIO_TWIML_APP_SID: APXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
36 | API_KEY: SKXXXXXXXXXXXX
37 | API_SECRET: XXXXXXXXXXXXXX
38 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.pyc
3 | *.pyo
4 | env
5 | env*
6 | dist
7 | build
8 | *.egg
9 | *.egg-info
10 | _mailinglist
11 | .tox
12 | .env
13 | .env.ps1
14 | venv
15 | .vscode
16 | __pycache__
17 | .pytest_cache
18 | .tool-versions
19 | node_modules/
20 |
--------------------------------------------------------------------------------
/.mergify.yml:
--------------------------------------------------------------------------------
1 | pull_request_rules:
2 | - name: automatic merge for Dependabot pull requests
3 | conditions:
4 | - author=dependabot-preview[bot]
5 | - status-success=build (3.6, macos-latest)
6 | - status-success=build (3.7, macos-latest)
7 | - status-success=build (3.8, macos-latest)
8 | - status-success=build (3.6, windows-latest)
9 | - status-success=build (3.7, windows-latest)
10 | - status-success=build (3.8, windows-latest)
11 | - status-success=build (3.6, ubuntu-latest)
12 | - status-success=build (3.7, ubuntu-latest)
13 | - status-success=build (3.8, ubuntu-latest)
14 | actions:
15 | merge:
16 | method: squash
17 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | - Using welcoming and inclusive language
18 | - Being respectful of differing viewpoints and experiences
19 | - Gracefully accepting constructive criticism
20 | - Focusing on what is best for the community
21 | - Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | - The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | - Trolling, insulting/derogatory comments, and personal or political attacks
28 | - Public or private harassment
29 | - Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | - Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at open-source@twilio.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Twilio
2 |
3 | All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project is provided under.
4 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.8
2 |
3 | WORKDIR /usr/src/app
4 |
5 | COPY requirements.txt ./
6 |
7 | COPY Makefile ./
8 |
9 | RUN make install
10 |
11 | COPY . .
12 |
13 | EXPOSE 5000
14 |
15 | CMD ["sh", "-c", ". /usr/src/app/venv/bin/activate && make serve"]
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Twilio Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: venv install serve
2 | UNAME := $(shell uname)
3 |
4 | venv:
5 | ifeq ($(UNAME), Windows)
6 | py -3 -m venv venv;
7 | else
8 | python3 -m venv venv
9 | endif
10 |
11 | install: venv
12 | ifeq ($(UNAME), Windows)
13 | venv\Scripts\activate.bat; \
14 | pip3 install -r requirements.txt;
15 | else
16 | . venv/bin/activate; \
17 | pip3 install -r requirements.txt;
18 | endif
19 |
20 | serve:
21 | ifeq ($(UNAME), Windows)
22 | venv\Scripts\activate.bat; \
23 | python3 app.py
24 | else
25 | . venv/bin/activate; \
26 | python3 app.py
27 | endif
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # Twilio Voice JavaScript SDK Quickstart for Python
6 |
7 | 
8 |
9 | > This template is part of Twilio CodeExchange. If you encounter any issues with this code, please open an issue at [github.com/twilio-labs/code-exchange/issues](https://github.com/twilio-labs/code-exchange/issues).
10 |
11 | ## About
12 |
13 | This application should give you a ready-made starting point for writing your own voice apps with the Twilio Voice JavaScript SDK (formerly known as Twilio Client).
14 |
15 | This application uses the lightweight [Flask Framework](http://flask.pocoo.org/). Once you set up the application, you will be able to make and receive calls from your browser. You will also be able to switch between audio input/output devices, and see dynamic volume levels on the call.
16 |
17 | 
18 |
19 | Implementations in other languages:
20 |
21 | | .NET | Java | Node | PHP | Ruby |
22 | | :--- | :--- | :----- | :-- | :--- |
23 | | [Done](https://github.com/TwilioDevEd/voice-javascript-sdk-quickstart-csharp) | [Done](https://github.com/TwilioDevEd/voice-javascript-sdk-quickstart-java) | [Done](https://github.com/TwilioDevEd/voice-javascript-sdk-quickstart-node) | [Done](https://github.com/TwilioDevEd/voice-javascript-sdk-quickstart-php) | [Done](https://github.com/TwilioDevEd/voice-javascript-sdk-quickstart-ruby) |
24 |
25 | ## Set Up
26 |
27 | ### Requirements
28 |
29 | - [Python](https://www.python.org/) **3.6**, **3.7**, **3.8**, or **3.9** version.
30 | - [ngrok](https://ngrok.com/download)
31 |
32 | ### Twilio Account Settings
33 |
34 | Before we begin, we need to collect all the config values we need to run the application.
35 |
36 | | Config Value | Description |
37 | | :------------- |:------------- |
38 | `TWILIO_ACCOUNT_SID` | Your primary Twilio account identifier - find this [in the console here](https://www.twilio.com/console).
39 | `TWILIO_TWIML_APP_SID` | The TwiML application with a voice URL configured to access your server running this app - create one [in the console here](https://www.twilio.com/console/voice/twiml/apps). Also, you will need to configure the Voice "REQUEST URL" on the TwiML app once you've got your server up and running.
40 | `TWILIO_CALLER_ID` | A Twilio phone number in [E.164 format](https://www.twilio.com/docs/glossary/what-e164) - you can [get one here](https://www.twilio.com/console/phone-numbers/incoming)
41 | `API_KEY` / `API_SECRET` | Your REST API Key information needed to create an [Access Token](https://www.twilio.com/docs/iam/access-tokens) - create [an API key here](https://www.twilio.com/console/project/api-keys). The `API_KEY` value should be the key's `SID`.
42 |
43 | ### Local development
44 |
45 | 1. First, clone this repository and `cd` into it.
46 |
47 | ```bash
48 | git clone https://github.com/TwilioDevEd/voice-javascript-sdk-quickstart-python.git
49 | cd voice-javascript-sdk-quickstart-python
50 | ```
51 |
52 | 2. Run `make install`. This command will create a Python virtual environment, load it, and install the Python dependencies.
53 |
54 | ```bash
55 | make install
56 | ```
57 |
58 | 3. Download the Twilio Voice JavaScript SDK code from GitHub.
59 |
60 | In a production environment, we recommend using `npm` to install the SDK. However, for the purposes of this quickstart,
61 | we are not introducing Node or build tools, and are instead getting the SDK code directly from GitHub.
62 |
63 | See the instructions [here](https://github.com/twilio/twilio-voice.js#github) for downloading the SDK code from GitHub.
64 | You will download a zip or tarball for a specific release version of the Voice JavaScript SDK (ex: `2.0.0`), extract the
65 | files, and retrieve the `twilio.min.js` file from the `dist/` folder. Move that `twilio.min.js` file into this project's `static/` directory.
66 |
67 | 4. Create a configuration file for your application by copying the `.env.example` file to a new file called `.env`. Then, edit the `.env` file to include your account and application details.
68 |
69 | ```bash
70 | cp .env.example .env
71 | ```
72 |
73 | See [Twilio Account Settings](#twilio-account-settings) to locate the necessary environment variables.
74 |
75 | #### Windows (PowerShell)
76 |
77 | Begin by creating a configuration file for your application:
78 | ```powershell
79 | cp .env.example.ps1 .env.ps1
80 | ```
81 |
82 | Edit `.env.ps1` with the four configuration parameters we gathered from above.
83 | "Dot-source" the file in PowerShell like so:
84 | ```powershell
85 | . .\.env.ps1
86 | ```
87 | This assumes you will run the application in the same PowerShell session. If not,
88 | edit the `.env.ps1` and uncomment the `[Environment]::SetEnvironmentVariable` calls.
89 | After re-running the script, the environment variables will be peramently set for
90 | your user account.
91 |
92 | 5. Run the application. It will run locally on port 5000.
93 |
94 | ```bash
95 | make serve
96 | ```
97 |
98 | 6. Navigate to [http://localhost:5000](http://localhost:5000)
99 |
100 | 7. Expose your application to the wider internet using [ngrok](https://ngrok.com/download). You can click [here](https://www.twilio.com/blog/2015/09/6-awesome-reasons-to-use-ngrok-when-testing-webhooks.html) for more details. This step **is important** and your application won't work if you only run the server on localhost.
101 |
102 | ```bash
103 | ngrok http 5000
104 | ```
105 |
106 | 8. When ngrok starts up, it will assign a unique URL to your tunnel.
107 | It might be something like `https://asdf456.ngrok.io`. Take note of this.
108 |
109 | 9. [Configure your TwiML app](https://www.twilio.com/console/voice/twiml/apps)'s
110 | Voice "REQUEST URL" to be your ngrok URL plus `/voice`. For example:
111 |
112 | 
113 |
114 | > **Note:** You must set your webhook urls to the `https` ngrok tunnel created.
115 |
116 | You should now be ready to rock! Make some phone calls or receiving incoming calls in the application.
117 | Note that Twilio Client requires WebRTC enabled browsers, so Edge and Internet Explorer will not work for testing.
118 | We'd recommend Google Chrome or Mozilla Firefox instead.
119 |
120 | ## Your Web Application
121 |
122 | When you navigate to `localhost:5000`, you should see the web application containing a "Start up the Device" button. Click this button to initialize a `Twilio.Device`.
123 |
124 | 
125 |
126 | When the `Twilio.Device` is initialized, you will be assigned a random client name, which will appear in the top left corner of the homepage.
127 | This client name is used as the identity field when generating an access token for the client, and is also used to route incoming calls to the correct client device.
128 |
129 | ### To make an outbound call to a phone number:
130 |
131 | Under "Make a Call", enter a phone number in [E.164 format](https://www.twilio.com/docs/glossary/what-e164) and press the "Call" button.
132 |
133 | ### To make a browser-to-browser call:
134 |
135 | Open two browser windows to `localhost:5000` and click "Start up the Device" button in both windows. You should see a different client name in each window.
136 |
137 | Enter one client's name in the other client's "Make a Call" input field, and press the "Call" button.
138 |
139 | 
140 |
141 | ### Receiving incoming calls from a non-browser device:
142 |
143 | You will first need to configure your Twilio Voice phone number (the phone number you used as the `TWILIO_CALLER_ID` configuration value) to route incoming calls to your TwiML app. This tells Twilio how to handle an incoming call directed to your Twilio Voice number.
144 |
145 | 1. Log in to the [Twilio Console](https://www.twilio.com/console)
146 | 2. Navigate to your [Active Number list](https://www.twilio.com/console/phone-numbers/incoming)
147 | 3. Click on the number you are using as your `TWILIO_CALLER_ID`.
148 | 4. Scroll down to find the "Voice & Fax" section and look for "CONFIGURE WITH".
149 | 5. Select "TwiML App".
150 | 6. Under "TwiML App", choose the TwiML App you created earlier for this quickstart.
151 | 7. Click the "Save" button at the bottom of the browser window.
152 |
153 | 
154 |
155 | You can now call your Twilio Voice phone number from your phone.
156 |
157 | **Note:** Since this is a quickstart with limited functionality, incoming calls will only be routed to your most recently created `Twilio.Device`.
158 |
159 | ### Unknown Devices
160 |
161 | If you see "Unknown Audio Output Device 1" in the "Ringtone" or "Speaker" devices lists, click the button below the boxes (Seeing "Unknown" Devices?) to have your browser identify your input and output devices.
162 | 
163 |
164 | ### Docker
165 |
166 | If you have [Docker](https://www.docker.com/) already installed on your machine, you can use our `docker-compose.yml` to setup your project.
167 |
168 | 1. Make sure you have the project cloned and that Docker is running on your machine.
169 | 2. Retrieve the `twilio.min.js` file and move it to the `static` directory as outlined in Step 3 of the [Local Development](#local-development) steps.
170 | 3. Setup the `.env` file as outlined in Step 4 of the [Local Development](#local-development) steps.
171 | 4. Run `docker-compose up`.
172 | 5. Follow the steps in [Local Development](#local-development) on how to expose your port to Twilio using [ngrok](https://ngrok.com/) and configure the remaining parts of your application.
173 |
174 | ### Tests
175 |
176 | You can run the tests locally with the following command. Before running, make sure the virtual environment is activated.
177 |
178 | ```bash
179 | source venv/bin/activate
180 | python3 -m pytest
181 | ```
182 |
183 | ### Cloud deployment
184 |
185 | Additionally to trying out this application locally, you can deploy it to a variety of host services. Here is a small selection of them.
186 |
187 | Please be aware that some of these might charge you for the usage or might make the source code for this application visible to the public. When in doubt research the respective hosting service first.
188 |
189 | | Service | |
190 | | :-------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
191 | | [Heroku](https://www.heroku.com/) | [](https://heroku.com/deploy) |
192 |
193 | ## Resources
194 |
195 | - The CodeExchange repository can be found [here](https://github.com/twilio-labs/code-exchange/).
196 |
197 | ## Contributing
198 |
199 | This template is open source and welcomes contributions. All contributions are subject to our [Code of Conduct](https://github.com/twilio-labs/.github/blob/master/CODE_OF_CONDUCT.md).
200 |
201 | ## License
202 |
203 | [MIT](http://www.opensource.org/licenses/mit-license.html)
204 |
205 | ## Disclaimer
206 |
207 | No warranty expressed or implied. Software is as is.
208 |
209 | [twilio]: https://www.twilio.com
210 |
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import os
4 | import re
5 |
6 | from dotenv import load_dotenv
7 | from faker import Faker
8 | from flask import Flask, Response, jsonify, redirect, request
9 | from twilio.jwt.access_token import AccessToken
10 | from twilio.jwt.access_token.grants import VoiceGrant
11 | from twilio.twiml.voice_response import Dial, VoiceResponse
12 |
13 | load_dotenv()
14 |
15 | app = Flask(__name__)
16 | fake = Faker()
17 | alphanumeric_only = re.compile("[\W_]+")
18 | phone_pattern = re.compile(r"^[\d\+\-\(\) ]+$")
19 |
20 | twilio_number = os.environ.get("TWILIO_CALLER_ID")
21 |
22 | # Store the most recently created identity in memory for routing calls
23 | IDENTITY = {"identity": ""}
24 |
25 |
26 | @app.route("/")
27 | def index():
28 | return app.send_static_file("index.html")
29 |
30 |
31 | @app.route("/token", methods=["GET"])
32 | def token():
33 | # get credentials for environment variables
34 | account_sid = os.environ["TWILIO_ACCOUNT_SID"]
35 | application_sid = os.environ["TWILIO_TWIML_APP_SID"]
36 | api_key = os.environ["API_KEY"]
37 | api_secret = os.environ["API_SECRET"]
38 |
39 | # Generate a random user name and store it
40 | identity = alphanumeric_only.sub("", fake.user_name())
41 | IDENTITY["identity"] = identity
42 |
43 | # Create access token with credentials
44 | token = AccessToken(account_sid, api_key, api_secret, identity=identity)
45 |
46 | # Create a Voice grant and add to token
47 | voice_grant = VoiceGrant(
48 | outgoing_application_sid=application_sid,
49 | incoming_allow=True,
50 | )
51 | token.add_grant(voice_grant)
52 |
53 | # Return token info as JSON
54 | token = token.to_jwt()
55 |
56 | # Return token info as JSON
57 | return jsonify(identity=identity, token=token)
58 |
59 |
60 | @app.route("/voice", methods=["POST"])
61 | def voice():
62 | resp = VoiceResponse()
63 | if request.form.get("To") == twilio_number:
64 | # Receiving an incoming call to our Twilio number
65 | dial = Dial()
66 | # Route to the most recently created client based on the identity stored in the session
67 | dial.client(IDENTITY["identity"])
68 | resp.append(dial)
69 | elif request.form.get("To"):
70 | # Placing an outbound call from the Twilio client
71 | dial = Dial(caller_id=twilio_number)
72 | # wrap the phone number or client name in the appropriate TwiML verb
73 | # by checking if the number given has only digits and format symbols
74 | if phone_pattern.match(request.form["To"]):
75 | dial.number(request.form["To"])
76 | else:
77 | dial.client(request.form["To"])
78 | resp.append(dial)
79 | else:
80 | resp.say("Thanks for calling!")
81 |
82 | return Response(str(resp), mimetype="text/xml")
83 |
84 |
85 | if __name__ == "__main__":
86 | app.run(debug=True, host="0.0.0.0")
87 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.8"
2 | services:
3 | app:
4 | container_name: app
5 | restart: always
6 | build: .
7 | ports:
8 | - "5000:5000"
9 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | flask~=2.1.3
2 | twilio~=6.38.1
3 | faker~=4.0.3
4 | python-dotenv==0.13.0
5 | pytest==5.4.1
6 |
--------------------------------------------------------------------------------
/screenshots/BrowserToBrowserCall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TwilioDevEd/voice-javascript-sdk-quickstart-python/37d091663c0758d58f09c88040d5ba3ce3878407/screenshots/BrowserToBrowserCall.png
--------------------------------------------------------------------------------
/screenshots/ConfigurePhoneNumber.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TwilioDevEd/voice-javascript-sdk-quickstart-python/37d091663c0758d58f09c88040d5ba3ce3878407/screenshots/ConfigurePhoneNumber.png
--------------------------------------------------------------------------------
/screenshots/ConfigurePhoneNumberWithTwiMLApps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TwilioDevEd/voice-javascript-sdk-quickstart-python/37d091663c0758d58f09c88040d5ba3ce3878407/screenshots/ConfigurePhoneNumberWithTwiMLApps.png
--------------------------------------------------------------------------------
/screenshots/Homepage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TwilioDevEd/voice-javascript-sdk-quickstart-python/37d091663c0758d58f09c88040d5ba3ce3878407/screenshots/Homepage.png
--------------------------------------------------------------------------------
/screenshots/InitializeDevice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TwilioDevEd/voice-javascript-sdk-quickstart-python/37d091663c0758d58f09c88040d5ba3ce3878407/screenshots/InitializeDevice.png
--------------------------------------------------------------------------------
/screenshots/UnknownDevices.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TwilioDevEd/voice-javascript-sdk-quickstart-python/37d091663c0758d58f09c88040d5ba3ce3878407/screenshots/UnknownDevices.png
--------------------------------------------------------------------------------
/screenshots/UpdateRequestURL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TwilioDevEd/voice-javascript-sdk-quickstart-python/37d091663c0758d58f09c88040d5ba3ce3878407/screenshots/UpdateRequestURL.png
--------------------------------------------------------------------------------
/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |