Streaming Last Christmas into a Phone Call

Send Your Friends to Whamhalla by Streaming Last Christmas Into a Phone Call

Published December 11, 2018 by Aaron Bassett
Categories:

Christmas is an expensive time, but I can help save you a fortune on gifts by ensuring no-one is speaking to you on Christmas day by sending them all to Whamhalla!

Every year my friends and I compete in Whamageddon, the rules are simple:

  1. The objective is to go as long as possible without hearing WHAM’s Christmas classic; “Last Christmas”
  2. The game starts on December 1st, and ends at midnight on December 24th
  3. Only the original version applies
  4. You’re out as soon as you recognise the song

Anyone who has ever set foot outside, or turned on the radio during Christmas can attest as to how difficult it is to avoid “Last Christmas”. From one second past midnight on the 1st of December it’s as if every store has it on repeat. Most people play the game defensively, avoiding those places which are most likely to be playing the song. We’re not most people though; we’re going to go on the attack.

The Principles of War

Santa driving a tank

Seize, retain, and exploit the initiative. Offensive action is the most effective and decisive way to attain a clearly defined common objective. Offensive operations are the means by which a military force seizes and holds the initiative while maintaining freedom of action and achieving decisive results. This is fundamentally true across all levels of war.

We can win Whamageddon either by avoiding the song until 25th of December or by ensuring all our friends hear it before us, so we’re last person standing. We need to find a way to trick them into hearing the song, and without exposing ourselves to it at the same time. No friendly fire incidents, please!

The obvious attack vector is to send them a Youtube link of the song, but Rickrolling has left everyone too wary of clicking on unknown Youtube links. We need a channel they wouldn’t suspect.

Strike the enemy at a time or place or in a manner for which he is unprepared. Surprise can decisively shift the balance of combat power. By seeking surprise, forces can achieve success well out of proportion to the effort expended. Surprise can be in tempo, size of force, direction or location of main effort, and timing. Deception can aid the probability of achieving surprise.

Streaming Audio into a Phone Call

As much as Last Christmas permeates everything this time of year I don’t think I’ve ever answered the phone and heard it. Nobody would ever suspect Wham! is calling.

We’re going to use two APIs to accomplish this, the Nexmo Voice API to make the outbound call and to play the mp3 to our friends, and the Spotify API to provide a short sample of Last Christmas. Both APIs have Python wrappers to make them easier to work with, and we’re going to wrap it all up in a nice CLI so we can eliminate our friends with a single command. When we’re finished it is going to look just like this:

Screencast of our Voice Application CLI

Getting Started

You’ll need a bit of experience with Python to get this running, and at least version 3.6 as we’re using f-strings (because they’re amazing) as well as a couple of other things:

  1. The source code from GitHub
  2. A Spotify account and your own Spotify application. Make a note of your client id and secret as you’ll need to add those to your .env later
  3. A Nexmo account which you’ve topped up with some credit
  4. Ngrok; if you’re not sure what this is for you should read our ngrok tutorial first

Configuration

There is an example .env.example file in the repository, rename this to .env and start filling in the values. For the NEXMO_APPLICATION_ID and NEXMO_PRIVATE_KEY you have to create a new Nexmo Application, you can do this via the Dashboard, remember to save the generated private.key somewhere safe and set the value of NEXMO_PRIVATE_KEY to the location of your key.

The script also has several dependencies; I’d recommend installing them via pipenv, but you can use some other Python dependency management if you prefer.

pipenv install

Once you have installed your dependencies ensure you have activated your virtual environment (this would be pipenv shell if you’re using pipenv) and that your shell contains the environmental variables from the .env file. Lastly, we need to be able to expose our script to the public internet so that the Nexmo webhooks can reach it. For this we’ll use ngrok, don’t worry about configuring your tunnel, just make sure ngrok is running.

ngrok http 80

You’re now ready to run the script.

python pvpwham.py NUMBER

There are a few extra options you can specify, run python pvpwham.py --help for more information.

Let’s step through some of the more interesting parts of the code in more detail.

Validating the Number

Ensuring we have a valid phone number to target is crucial, nothing else works without it. So we spend a bit of time validating the number and converting it into the correct format. However, people write phone numbers in a whole range of weird and wonderful ways so if we can’t validate it we prompt them to stick to E.164, and even provide a link to more information before they’re asked to try again.

Finding an MP3 of the Song

We don’t need the whole song; a few seconds should be enough to send someone to Whamhalla. The 30-second preview from Spotify is ideal. The script defaults to “Last Christmas”, but you can configure this using the --track option.

Our Server

We have several different Nexmo webhooks we have to handle.

Answer URL – this is called whenever someone answers the call and contains a list of actions for Nexmo to perform. In our case, we’re going to tell Nexmo to record the call, to use text-to-speech to read out a short warning to the user (this is disabled by default but can be enabled using the --delay option), and finally to stream our Spotify preview into the call

Recording URL – Once the user has hung up the phone and the call is complete Nexmo hits this webhook with the recording details so we can download the mp3 and listen to our friend’s dismay as they realise what has happened.

NB: We record everything, including the audio that we have streamed into the call. You don’t want to send yourself to Whamhalla accidentally as well. You could modify the script to use split recordings to prevent this.

Events URL – This is purely for informational purposes. The script updates the terminal with the latest status it receives via the events webhook.

Housekeeping

Whenever the call has completed, we have an on_end_request hook which does some tidying up. We shut down our Cherrypy server and kill our Ngrok tunnel.

Some Other Fun Commands

You can find some pretty strange things on Spotify if you’re creative enough.

python pvpwham.py NUMBER --track='Rick Astley Never gonna give you up'

python pvpwham.py NUMBER --track='Sound Effects Animals Chimps, Apes'

python pvpwham.py NUMBER --track='Halloween Sound effects machine ghostly whispers'

What Next?

Direct every military operation toward a clearly defined, decisive and attainable objective. The ultimate military purpose of war is the destruction of the enemy’s ability to fight and will to fight.

Even if you don’t manage to eliminate all your friends, hopefully the survivors are going to be so anxious every time the phone rings that they’ll surrender. Walking into their local shopping centre to sit and wait for the inevitable.

Then after you have crushed the opposition have a look at some of the less militant uses for the Voice API:

Leave a Reply

Your email address will not be published.