Skip to content

feat(templates): add block-spam-calls template #555

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions block-spam-calls/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# description: The path to the webhook
# configurable: false
TWILIO_VOICE_WEBHOOK_URL=/block-spam-calls
9 changes: 9 additions & 0 deletions block-spam-calls/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Changelog

## [Unreleased]

## [1.0.0]

### Added

- Initial release.
54 changes: 54 additions & 0 deletions block-spam-calls/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# block-spam-calls

Uses Twilio Add-ons to block unwanted calls by checking the spam ratings of incoming phone numbers.

## Pre-requisites

- A Twilio account - [sign up here](https://www.twilio.com/try-twilio)
- A Twilio phone number
- Spam filtering Add-ons (see below)

### Install Add-Ons

The following guide will help you to [install Add-ons](https://www.twilio.com/docs/add-ons/install). You can access the Add-ons in the Twilio console [here](https://www.twilio.com/console/add-ons). The Spam Filtering Add-ons that are used on this application are:

- [Marchex Clean Call](https://www.twilio.com/console/add-ons/XBac2c99d9c684a765ced0b18cf0e5e1c7)
- [Nomorobo Spam Score](https://www.twilio.com/console/add-ons/XB06d5274893cc9af4198667d2f7d74d09)

Once you've selected the Add-on, just click on `Install` button. Then, you will see a pop-up window where you should read and agree the terms, then, click the button `Agree & Install`. For this application, you just need to handle the incoming voice calls, so make sure the `Incoming Voice Call` box for `Use In` is checked and click `Save`.

### Function Parameters

This template by default accepts no additional parameters.

## Create a new project with the template

1. Install the [serverless toolkit](https://www.twilio.com/docs/labs/serverless-toolkit/getting-started)
2. Install the [Twilio CLI](https://www.twilio.com/docs/twilio-cli/quickstart#install-twilio-cli)
3. Initiate a new project

```
twilio serverless:init sample --template=block-spam-calls && cd sample
```

4. Start the server with the [Twilio CLI](https://www.twilio.com/docs/twilio-cli/quickstart):

```
twilio serverless:start --ngrok
```

5. Set your incoming call webhook URL for the phone number you want to configure to `https://<your-ngrok-code>.ngrok.io/block-spam-calls`

ℹ️ Check the developer console and terminal for any errors

## Deploying

Deploy your functions and assets with either of the following commands. Note: you must run these commands from inside your project folder. [More details in the docs.](https://www.twilio.com/docs/labs/serverless-toolkit)

With the [Twilio CLI](https://www.twilio.com/docs/twilio-cli/quickstart):

```
twilio serverless:deploy
```

Make sure to update your incoming voice URL to your newly deployed Function URL.
141 changes: 141 additions & 0 deletions block-spam-calls/assets/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title>Get started with your Twilio Functions!</title>

<link
rel="icon"
href="https://twilio-labs.github.io/function-templates/static/v1/favicon.ico"
/>
<link
rel="stylesheet"
href="https://twilio-labs.github.io/function-templates/static/v1/ce-paste-theme.css"
/>
<script
src="https://twilio-labs.github.io/function-templates/static/v1/ce-helpers.js"
defer
></script>
<script>
window.addEventListener('DOMContentLoaded', (_event) => {
inputPrependBaseURL();
});
</script>
</head>
<body>
<div class="page-top">
<header>
<div id="twilio-logo">
<a href="https://www.twilio.com/" target="_blank" rel="noopener">
<svg
class="logo"
data-name="Layer 1"
xmlns="http://www.w3.org/2000/svg"
viewbox="0 0 60 60"
>
<title>Twilio Logo</title>
<path
class="cls-1"
d="M30,15A15,15,0,1,0,45,30,15,15,0,0,0,30,15Zm0,26A11,11,0,1,1,41,30,11,11,0,0,1,30,41Zm6.8-14.7a3.1,3.1,0,1,1-3.1-3.1A3.12,3.12,0,0,1,36.8,26.3Zm0,7.4a3.1,3.1,0,1,1-3.1-3.1A3.12,3.12,0,0,1,36.8,33.7Zm-7.4,0a3.1,3.1,0,1,1-3.1-3.1A3.12,3.12,0,0,1,29.4,33.7Zm0-7.4a3.1,3.1,0,1,1-3.1-3.1A3.12,3.12,0,0,1,29.4,26.3Z"
/>
</svg>
</a>
</div>
<nav>
<span>Your Twilio application</span>
<aside>
<svg
class="icon"
role="img"
aria-hidden="true"
width="100%"
height="100%"
viewBox="0 0 20 20"
aria-labelledby="NewIcon-1577"
>
<path
fill="currentColor"
fill-rule="evenodd"
d="M6.991 7.507c.003-.679 1.021-.675 1.019.004-.012 2.956 1.388 4.41 4.492 4.48.673.016.66 1.021-.013 1.019-2.898-.011-4.327 1.446-4.48 4.506-.033.658-1.01.639-1.018-.02-.03-3.027-1.382-4.49-4.481-4.486-.675 0-.682-1.009-.008-1.019 3.02-.042 4.478-1.452 4.49-4.484zm.505 2.757l-.115.242c-.459.9-1.166 1.558-2.115 1.976l.176.08c.973.465 1.664 1.211 2.083 2.22l.02.05.088-.192c.464-.973 1.173-1.685 2.123-2.124l.039-.018-.118-.05c-.963-.435-1.667-1.117-2.113-2.034l-.068-.15zm10.357-8.12c.174.17.194.434.058.625l-.058.068-1.954 1.905 1.954 1.908a.482.482 0 010 .694.512.512 0 01-.641.056l-.07-.056-1.954-1.908-1.954 1.908a.511.511 0 01-.71 0 .482.482 0 01-.058-.626l.058-.068 1.954-1.908-1.954-1.905a.482.482 0 010-.693.512.512 0 01.64-.057l.07.057 1.954 1.905 1.954-1.905a.511.511 0 01.71 0z"
></path>
</svg>
Live
</aside>
</nav>
</header>
</div>
<main>
<div class="content">
<h1>
<img
src="https://twilio-labs.github.io/function-templates/static/v1/success.svg"
/>
<div>
<p>Welcome!</p>
<p>Your live application with Twilio is ready to use!</p>
</div>
</h1>
<section>
<h2>Get started with your application</h2>
<p>
Follow the set up steps located in the
<a
href="https://github.com/twilio-labs/function-templates/tree/main/block-spam-calls"
target="_blank"
rel="noopener"
>Block Spam Calls functions template repo</a
>
to get started.
</p>

<p>
This app will return the
<a
href="https://www.twilio.com/docs/sms/twiml"
target="_blank"
rel="noopener"
>TwiML</a
>
required to reject or accept incoming Voice calls based on the phone
numbers spam rating.
</p>
</section>
<section>
<!-- APP_INFO_V2 -->
</section>
<section>
<h2>Troubleshooting</h2>
<ul>
<li>
Check the
<a
href="https://www.twilio.com/console/phone-numbers/incoming"
target="_blank"
rel="noopener"
>
phone number configuration
</a>
and make sure the Twilio phone number you want for your app has a
Voice webhook configured to point at the following URL
<form>
<label for="twilio-webhook">Webhook URL</label>
<input
type="text"
id="twilio-webhook"
class="function-root"
readonly="true"
value="/block-spam-calls"
/>
</form>
</li>
</ul>
</section>
</div>
</main>
<footer>
<span class="statement">We can't wait to see what you build.</span>
</footer>
</body>
</html>
83 changes: 83 additions & 0 deletions block-spam-calls/functions/block-spam-calls.protected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Block Spam Calls
*
* Description:
* This application uses Twilio Add-ons from the Twilio Marketplace to block
* unwanted voice calls. The 2 Add-ons used in this application are Marchex
* Clean Call and Nomorobo Spam Score. The application provides the spam rating
* of every inbound call to a Twilio number via the three Add-ons.
* If the phone number is classified as spam by any of the two integrations, the
* call is rejected. If the number isn't categorized as spam, the call will go through.
*
* Contents:
* 1. Input Helpers
* 2. Main Handler
*/

/*
* 1. Input Helpers
* These helper functions help read the results from the spam Add-ons
* in the incoming voice TwiML callback.
*
* Function will return true if the call is classified as spam.
* Otherwise, it will return false.
*/

function blockedByMarchex(response) {
if (!response || response.status !== 'successful') {
return false;
}

return response.result.result.recommendation === 'BLOCK';
}

function blockedByNomorobo(response) {
if (!response || response.status !== 'successful') {
return false;
}

return response.result.score === 1;
}
/**
* 2. Main Handler
*
* This is the entry point to your Twilio Function,
* which will create a new Voice Response using Twiml based on
* the spam filters. If the call is flagged as spam by any of the
* spam filtering add-ons, the call will blocked by the <Reject> Twiml
* verb. Else, the call will proceed and the Voice Response
* will respond to the caller with a greeting.
*
* The callback will be used to return from your function
* with the Twiml Voice Response you defined earlier.
* In the callback in non-error situations, the first
* parameter is null and the second parameter
* is the value you want to return.
*/
exports.handler = function (context, event, callback) {
const twiml = new Twilio.twiml.VoiceResponse();

let blockCalls = false;

/*
* If the request body contains add-ons, check to see if any of
* the spam filtering add-ons have flagged the number.
*/
const addOns = 'AddOns' in event && JSON.parse(event.AddOns);
if (addOns && addOns.status === 'successful') {
const { results } = addOns;
blockCalls =
blockedByMarchex(results.marchex_cleancall) ||
blockedByNomorobo(results.nomorobo_spamscore);
}

if (blockCalls) {
twiml.reject();
} else {
// Add instructions here on what to do if call goes through
twiml.say('Welcome to the jungle.');
twiml.hangup();
}

callback(null, twiml);
};
6 changes: 6 additions & 0 deletions block-spam-calls/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "block-spam-calls",
"version": "1.0.0",
"private": true,
"dependencies": {}
}
Loading
Loading