Rick Roll Your Friends Using Appwrite, Twilio, and .NET
Tags: appwrite, twilio, dotnet, opensource
Published: 2022-06-10 08:24:36

Being the fun-loving guy and absolute geek that I am, I've always looked for ways to use tech to prank my friends 😏. I remember that first prank I did 11 years back, a little shortcut hidden behind an Internet Explorer icon that shut down my friend's Windows XP based PC and gave him a mini heart-attack 😆. My pranks have gotten "a little more sophisticated" since then, having graduated to [rick rolling](https://www.youtube.com/watch?v=dQw4w9WgXcQ&ab_channel=RickAstley) them via phone calls now! 🤣

![Rick Roll GIF](https://media.giphy.com/media/5kq0GCjHA8Rwc/giphy.gif)

The best part is that little prank is really easy to create, and I will show you how to create this prank using 3 of my favourite technologies, **Appwrite**, **Twilio**, and **.NET** today! 😄 

### 📃 Table of Contents

- [📝 Prerequisites](#prerequisites)
- [🏗️ Setting up Appwrite and Initializing Our Function](#setting-up-appwrite-and-initializing-our-function)
- [🧑‍💻 Creating the Rick Roll Function](#creating-the-rick-roll-function)
- [😜 Testing the Rick Roll Cloud Function](#testing-the-rick-roll-cloud-function)
- [🏆 Conclusion](#conclusion)

## 📝 Prerequisites

Before we get started, there are a couple of prerequisites. If you have the prerequisites set up already, you can skip to the following section. 

In order to follow along, you’ll need a few things beforehand.

* 🖥 **An Appwrite instance**

If you haven’t set up an Appwrite instance yet, you can follow the getting started guides to get it up and running quickly. Feel free to choose between the [One-Click installations on DigitalOcean](https://appwrite.io/docs/installation#one-click-setups) or [manual installations with Docker](https://appwrite.io/docs/installation#installWithDocker).

**TL;DR**: It just takes a single command to install Appwrite.

```bash
docker run -it --rm \
    --volume /var/run/docker.sock:/var/run/docker.sock \
    --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
    --entrypoint="install" \
    appwrite/appwrite:1.3.2
```

Once your server is up and running, head over to the Appwrite Dashboard on your server’s public IP address ( or `localhost` if you installed locally ) and create a new admin user account.

![Sign Up](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ux0zhut29fbjtjp899c.png)

> In order to enable the **.NET 6.0 runtime for Appwrite Cloud Functions**, you need to update the `.env` file in the Appwrite installation folder. Enter the file and add `dotnet-6.0` to the comma-separated list in the environment variable `_APP_FUNCTIONS_RUNTIMES`. This will make the .NET runtime available in Appwrite Functions. You can then load the updated configuration using the `docker-compose up -d` command.

* 🧑‍💻 **The Appwrite CLI**

We’ll use the Appwrite CLI during this exercise as it makes the process super simple. If you have Node.js installed, the installation command is a simple

```bash
npm install -g appwrite-cli
```

If `npm` is not your thing, we have numerous installation options you can find in the [getting started guide for the CLI](https://appwrite.io/docs/command-line). 

* 📱 **A Twilio Account and Phone Number**

Sign up for a [Twilio account](https://www.twilio.com/referral/zigWwk) if you don't have one already. Add a phone number to your account that has calling capabilities at the very minimum. 

![Twilio Console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/unallbgbry927eqqtbej.jpg)

> ℹ️ The Twilio Account SID and Auth Token can be obtained from your Twilio console. You can purchase a Twilio phone number using [this guide](https://support.twilio.com/hc/en-us/articles/223135247-How-to-Search-for-and-Buy-a-Twilio-Phone-Number-from-Console).

## 🏗️ Setting up Appwrite and Initializing Our Function

> _If you already know how to create a Cloud Function from the Appwrite CLI, please [skip over to the next section](#creating-the-rick-roll-function)._

In order to create an Appwrite Cloud Function, first we must login to the Appwrite CLI using the `appwrite login` command using the credentials we created when setting up the Appwrite instance.

```bash
appwrite login
? Enter your email test@test.com
? Enter your password ********
? Enter the endpoint of your Appwrite server http://localhost/v1
✓ Success
```

Next up, we need to create a new Appwrite project (or link an existing one) to work with. This can be achieved via the `appwrite init project` command.

```bash
appwrite init project
? How would you like to start? Create a new Appwrite project
? What would you like to name your project? Project X
✓ Success
```

You can give your project any name you'd like. As soon as you create or link a project, you should notice a new `appwrite.json` file in the current directory which stores all the information about your project.

Now that our CLI is all set up with our Appwrite project, let's initialize our function using the `appwrite init function` command.

```bash
appwrite init function
? What would you like to name your function? RickRoll
? What runtime would you like to use? .NET (dotnet-6.0)
✓ Success 
```

Give your function a name (I've chosen **RickRoll** here for convenience) and choose the **.NET 6.0** runtime. This will create a new Appwrite Function in your project and set up all the boilerplate code necessary. The function's files are available in the `functions/RickRoll` directory, which is where we'll be working.

> If you don't feel comfortable creating Appwrite Cloud Functions with .NET, please make sure to check out our [blog](https://dev.to/appwrite/cloud-functions-using-the-new-net-runtime-4fkm) before moving onto the next step.

## 🧑‍💻 Creating the Rick Roll Function

After initializing the RickRoll Function, please visit the `functions/RickRoll` directory. Our file structure here looks as follows.

```
RickRoll
├── Function.csproj 
|
└── src
    └── Index.cs
```

Enter `src/Index.cs` and replace the boilerplate with the following code.

```csharp
using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Twilio;
using Twilio.Types;
using Twilio.Rest.Api.V2010.Account;

public async Task<RuntimeResponse> Main(RuntimeRequest req, RuntimeResponse res)
{
  // Convert payload from JSON string to Dictionary and get the phone number to call 
  var payload = JsonConvert.DeserializeObject<Dictionary<string, string>>(req.Payload);
  var toPhoneNumber = payload["phoneNumber"];

  // Get Twilio Account SID, Auth Token, and Phone Number from the Environment Variables
  var accountSID = req.Env["TWILIO_ACCOUNTSID"];
  var authToken = req.Env["TWILIO_AUTHTOKEN"];
  var twilioPhoneNumber = req.Env["TWILIO_PHONENUMBER"];

  //Initialize the Twilio SDK
  TwilioClient.Init(accountSID, authToken);

  // Create the phone call with the Twilio Voice API
  var call = CallResource.Create(
                to: new PhoneNumber(toPhoneNumber),
                from: new PhoneNumber(twilioPhoneNumber),
                twiml: new Twiml("<Response><Play>https://demo.twilio.com/docs/classic.mp3</Play></Response>") 
             );
  
  // Return the response from the Twilio SDK
  return res.Json(new()
  {
    { "twilioResponse", call }
  });
}
```

Let’s go over the code we have here. From the [Cloud Functions documentation](https://appwrite.io/docs/functions#writingYourOwnFunction), we see that the `payload` and `environment variables` are available through the `request` object. Here, we take the payload, which we receive as a JSON string, and convert it into a Dictionary. This is achieved using the `Newtonsoft.Json` library. We grab the phone number we want to call from the deserialized payload as well.

We then retrieve the `Twilio Account SID`, `Twilio Auth Token`, and our `Twilio Phone Number` from our environment variables and use the `Twilio C# / .NET SDK` to make a phone call with a [very special audio](https://demo.twilio.com/docs/classic.mp3) 😉.

![Dancing to the music](https://media.giphy.com/media/olAik8MhYOB9K/giphy.gif)

In order to make sure that Appwrite installs the `Newtonsoft.Json` library and the `Twilio` SDK to our function, we must include them in the `Function.csproj` file.

```xml
<ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
    <PackageReference Include="Twilio" Version="5.75.2" />
</ItemGroup>
```

Now that our function is ready, we can deploy it to our Appwrite instance using the `appwrite deploy function` command.

```bash
appwrite deploy function
? Which functions would you like to deploy? RickRoll (62a1a474b154de566308)
ℹ Info Deploying function RickRoll ( 62a1a474b154de566308 )
ℹ Info Ignoring files using configuration from appwrite.json
✓ Success Deployed RickRoll ( 62a1a474b154de566308 )
```
The function should be visible within your Appwrite Instance here.

![RickRoll Function](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9xb7yq654mkz8xwghwq.png)

One last thing we must do before we can test the function is add the necessary environment variables to the Function's Settings page.

- `TWILIO_ACCOUNTSID`: Twilio Account SID
- `TWILIO_AUTHTOKEN`: Twilio Auth Token
- `TWILIO_PHONENUMBER`: Twilio Phone Number to make the call from

![RickRoll Environment Variables](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fy6nvn2js419fapdptnt.png)

Now our function is fully ready to test! 🥳

## 😜 Testing the Rick Roll Cloud Function

Once the function is deployed, we can head over to the Appwrite console and execute the function with the payload in the following format.

```json
{
    "phoneNumber": "+919876543210"
}
```

Executing the function should lead to the phone number you entered receiving a call as shown.

{% embed https://www.youtube.com/watch?v=82-mF8WbiBA %}

We can also find the response from the Twilio SDK in the Function's Logs page.

```json
{
	"twilioResponse": {
		"Sid": "CA83758d533c786be5bcf82e34b94cc8b5",
		"DateCreated": null,
		"DateUpdated": null,
		"ParentCallSid": null,
		"AccountSid": "ACe29c144db149972dbf5427bbdd0c16dd",
		"To": "\u002B919876543210",
		"ToFormatted": "\u002B919876543210",
		"From": "\u002B12184232045",
		"FromFormatted": "(218) 423-2045",
		"PhoneNumberSid": "PN671d012061f32085fcd63b046f23826f",
		"Status": {},
		"StartTime": null,
		"EndTime": null,
		"Duration": null,
		"Price": null,
		"PriceUnit": "USD",
		"Direction": "outbound-api",
		"AnsweredBy": null,
		"ApiVersion": "2010-04-01",
		"ForwardedFrom": null,
		"GroupSid": null,
		"CallerName": null,
		"QueueTime": "0",
		"TrunkSid": null,
		"Uri": "/2010-04-01/Accounts/ACe29c144db149972dbf5427bbdd0c16dd/Calls/CA83758d533c786be5bcf82e34b94cc8b5.json",
		"SubresourceUris": {
			"feedback": "/2010-04-01/Accounts/ACe29c144db149972dbf5427bbdd0c16dd/Calls/CA83758d533c786be5bcf82e34b94cc8b5/Feedback.json",
			"notifications": "/2010-04-01/Accounts/ACe29c144db149972dbf5427bbdd0c16dd/Calls/CA83758d533c786be5bcf82e34b94cc8b5/Notifications.json",
			"recordings": "/2010-04-01/Accounts/ACe29c144db149972dbf5427bbdd0c16dd/Calls/CA83758d533c786be5bcf82e34b94cc8b5/Recordings.json",
			"streams": "/2010-04-01/Accounts/ACe29c144db149972dbf5427bbdd0c16dd/Calls/CA83758d533c786be5bcf82e34b94cc8b5/Streams.json",
			"payments": "/2010-04-01/Accounts/ACe29c144db149972dbf5427bbdd0c16dd/Calls/CA83758d533c786be5bcf82e34b94cc8b5/Payments.json",
			"siprec": "/2010-04-01/Accounts/ACe29c144db149972dbf5427bbdd0c16dd/Calls/CA83758d533c786be5bcf82e34b94cc8b5/Siprec.json",
			"events": "/2010-04-01/Accounts/ACe29c144db149972dbf5427bbdd0c16dd/Calls/CA83758d533c786be5bcf82e34b94cc8b5/Events.json",
			"feedback_summaries": "/2010-04-01/Accounts/ACe29c144db149972dbf5427bbdd0c16dd/Calls/FeedbackSummary.json"
		}
	}
}
```

## 🏆 Conclusion

And that brings us to the end folks! I sincerely hope you enjoyed yourself learning how you can leverage Appwrite Cloud Functions to build a fun little prank project. Feel free to visit the **GitHub repo** for this project (and give it a star 🌟 if you like it).

{% github adityaoberai/RickRoll-AppwriteFunction %}

In case you want to learn more about Appwrite Cloud Functions, feel free to visit the [Functions Guide](https://appwrite.io/docs/functions) and feel free to visit the [Appwrite Discord Server](https://appwrite.io/discord) if you need any help.

Thanks a lot and hope you have a great day! ❤️