Skip to content

Commit

Permalink
Update express-call-control to Typescript (#25)
Browse files Browse the repository at this point in the history
* update express-call-control to Typescript

* update instructions

* update package deps
  • Loading branch information
lucasassisrosa authored Oct 21, 2024
1 parent b07714a commit e28d961
Show file tree
Hide file tree
Showing 10 changed files with 3,432 additions and 3,177 deletions.
30 changes: 30 additions & 0 deletions .github/workflows/express-call-control.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: CI express-call-control

on:
push:
branches: [master]
paths:
- "express-call-control/**"
pull_request:
branches: [master]
paths:
- "express-call-control/**"

jobs:
type-check:
runs-on: ubuntu-latest
defaults:
run:
working-directory: express-call-control
strategy:
matrix:
node-version: [18.x, 20.x, 22.x]

steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run type-check
9 changes: 9 additions & 0 deletions express-call-control/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
parserOptions: {
ecmaVersion: 6,
},
rules: {
'new-cap': 'off',
'no-console': 'off',
},
};
1 change: 1 addition & 0 deletions express-call-control/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20.17.0
2 changes: 2 additions & 0 deletions express-call-control/.tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
nodejs 20.17.0
npm 10.8.1
48 changes: 26 additions & 22 deletions express-call-control/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,40 @@ Sample application demonstrating Telnyx-Node Call Control functionality.

You will need to set up:

* [Telnyx Account](https://telnyx.com/sign-up?utm_source=referral&utm_medium=github_referral&utm_campaign=cross-site-link)
* [Telnyx Phone Number](https://portal.telnyx.com/#/app/numbers/my-numbers) enabled with:
* [Telnyx Call Control Application](https://portal.telnyx.com/#/app/call-control/applications)
* [Telnyx Outbound Voice Profile](https://portal.telnyx.com/#/app/outbound-profiles)
* [Node & NPM](https://developers.telnyx.com/docs/v2/development/dev-env-setup?lang=node&utm_source=referral&utm_medium=github_referral&utm_campaign=cross-site-link) installed
- [Telnyx Account](https://telnyx.com/sign-up?utm_source=referral&utm_medium=github_referral&utm_campaign=cross-site-link)
- [Telnyx Phone Number](https://portal.telnyx.com/#/app/numbers/my-numbers) enabled with:
- [Telnyx Call Control Application](https://portal.telnyx.com/#/app/call-control/applications)
- [Telnyx Outbound Voice Profile](https://portal.telnyx.com/#/app/outbound-profiles)
- [Node & NPM](https://developers.telnyx.com/docs/v2/development/dev-env-setup?lang=node&utm_source=referral&utm_medium=github_referral&utm_campaign=cross-site-link) installed

## What you can do

This app, when running has the following behavior for inbound and outbound calls:

Inbound:
* Receives inbound callback
* Answers the call
* Speaks a sentence and waits for speak.ended callback
* Ends the call

- Receives inbound callback
- Answers the call
- Speaks a sentence and waits for speak.ended callback
- Ends the call

Outbound:
* Makes the call to the specified number
* On answer, speaks audio
* Waits for speak.ended callback
* Ends the call

- Makes the call to the specified number
- On answer, speaks audio
- Waits for speak.ended callback
- Ends the call

## Usage

The following environmental variables need to be set

| Variable | Description |
|:-----------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------|
| `TELNYX_API_KEY` | Your [Telnyx API Key](https://portal.telnyx.com/#/app/api-keys?utm_source=referral&utm_medium=github_referral&utm_campaign=cross-site-link) |
| `TELNYX_NUMBER` | Your [Telnyx Phone Number](https://portal.telnyx.com/#/app/numbers/my-numbers) |
| `TELNYX_CONNECTION_ID` | Your [Telnyx Call Control Application ID](https://portal.telnyx.com/#/app/call-control/applications) |
| `TELNYX_APP_PORT` | **Defaults to `8000`** The port the app will be served. |
| Variable | Description |
| :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ |
| `TELNYX_API_KEY` | Your [Telnyx API Key](https://portal.telnyx.com/#/app/api-keys?utm_source=referral&utm_medium=github_referral&utm_campaign=cross-site-link) |
| `TELNYX_NUMBER` | Your [Telnyx Phone Number](https://portal.telnyx.com/#/app/numbers/my-numbers) |
| `TELNYX_CONNECTION_ID` | Your [Telnyx Call Control Application ID](https://portal.telnyx.com/#/app/call-control/applications) |
| `TELNYX_APP_PORT` | **Defaults to `8000`** The port the app will be served. |

### .env file

Expand Down Expand Up @@ -91,16 +93,18 @@ Run the following commands to get started

```
$ git clone https://github.com/d-telnyx/demo-node-telnyx.git
$ cd express-call-control
```

### Run

Start the server `node index.js`
Start the server `npm run start`

When the application is started, express serves it to the port specified in the .env file (Default 8000), so you can sipmly take a look at the application at localhost:8000.

**Note: You must enter phone number in E.164 format (i.e. +12345678910) for the call to be sent correctly.**

Once everything is setup, you should now be able to:
* Make calls to a specified outbound number
* Receive an inbound call

- Make calls to a specified outbound number
- Receive an inbound call
79 changes: 0 additions & 79 deletions express-call-control/index.js

This file was deleted.

113 changes: 113 additions & 0 deletions express-call-control/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Telnyx Call Control Demo

// Set up environmental variables from .env file
import "dotenv/config";

// Library Requirements
import express from "express";
import bodyParser from "body-parser";
import nunjucks from "nunjucks";

// Set up telnyx library with user API Key
import Telnyx from "telnyx";
const telnyx = new Telnyx(process.env.TELNYX_API_KEY || "");

// Fire up express app and settings
const app = express();
app.use(express.json());
app.use(
bodyParser.urlencoded({
extended: true,
})
);

// Set default express engine and extension
app.engine("html", nunjucks.render);
app.set("view engine", "html");

// configure nunjucks engine
nunjucks.configure("templates/views", {
autoescape: true,
express: app,
});

// Simple page that can send a phone call
app.get("/", function (request, response) {
response.render("messageform");
});

app.post("/outbound", async (request, response) => {
const to_number = request.body.to_number;

try {
const { data: call } = await telnyx.calls.create({
connection_id: process.env.TELNYX_CONNECTION_ID || "",
to: to_number,
from: process.env.TELNYX_NUMBER || "",
timeout_secs: 0,
time_limit_secs: 0,
answering_machine_detection: "premium",
media_encryption: "disabled",
sip_transport_protocol: "UDP",
stream_track: "inbound_track",
send_silence_when_idle: false,
webhook_url_method: "POST",
record_channels: "single",
record_format: "wav",
record_max_length: 0,
record_timeout_secs: 0,
enable_dialogflow: false,
transcription: false,
});

response.render("messagesuccess");
console.log(call?.call_control_id);
} catch (e) {
response.send(e);
}
});

type CallControlEvent =
| Telnyx.events.CallHangupEvent
| Telnyx.events.CallInitiatedEvent
| Telnyx.events.CallAnsweredEvent
| Telnyx.events.CallSpeakEndedEvent;

app.post("/call_control", async (request, response) => {
response.sendStatus(200);

const data = (request.body as CallControlEvent).data!;
try {
const callControlId = data.payload!.call_control_id!;

if (data.event_type == "call.hangup") {
console.log("Call has ended.");
} else if (data.event_type == "call.initiated") {
telnyx.calls.answer(callControlId, {
stream_track: "inbound_track",
send_silence_when_idle: false,
webhook_url_method: "POST",
transcription: false,
});
} else if (data.event_type == "call.answered") {
telnyx.calls.speak(callControlId, {
payload:
"Hello, Telnyx user! Welcome to this call control demonstration.",
voice: "male",
language: "en-US",
payload_type: "text",
service_level: "premium",
});
} else if (data.event_type == "call.speak.ended") {
console.log("Speak has ended.");
telnyx.calls.hangup(callControlId, {});
}
} catch (error) {
console.log("Error issuing call command");
console.log(error);
}
});

// Fire up the app on port specified in env
app.listen(process.env.TELNYX_APP_PORT);
console.log(`Server listening on port ${process.env.TELNYX_APP_PORT}`);
Loading

0 comments on commit e28d961

Please sign in to comment.