Send Linux commands to a remote PC(or server) from WhatsApp
Tags: python, twiliohackathon, twilio, linux
Published: 2022-02-05 15:37:14

### Inspiration
Some years back, I wanted to link two systems talking to each other through Linux commands. It was just a project out of curiosity, and wasn't even a serious one. I didn't know [Twilio](https://www.twilio.com/) or [Plivo](https://www.plivo.com/) or any other platform related. I tried to die hard, but guess what! it was hard indeed :) I learnt about Twilio and built many other related projects. You can do the same, or even start building your very own next Twilio. Yes! It's possible. Hell, yess !


You can learn from this project, going further and building something tremendous! From the concept of this project (of-course you need to improve and add few other things) you can:

- Deploy your docker replicas just by sending WhatsApp text
- You can monitor your IoT devices remotely
- Send commands to your K8's engine for some orchestration processes

In fact you can do a lot, the sky is not a limit :) Let's set up our project.

 
### Setup a project in Twilio
In this article, we will focus more on how to interact these technologies and accomplish what we want. Our focus won't be more on Twilio.
- To setup a sandbox and obtain a WhatsApp number (sender id) follow this [link](https://www.twilio.com/docs/whatsapp/sandbox)

- Obtain `ACCOUNT_SID` and `AUTH_TOKEN` from the platform. Click [here](https://www.twilio.com/blog/better-twilio-authentication-csharp-twilio-api-keys)

- Now let's proceed with the project.

#### Flow of our project

![architecture flow(3).jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1641558621593/iUrIZm_di.jpeg)

### Building a server in Python
Now that we have already setup our project in Twilio platform and obtained `ACCOUNT_SID` and `AUTH_TOKEN` its time to build our server. We will use Flask for this project.

Create a file, name it `command.py`. This is the file where we will write our server-side application to and establish a connection between the machine (which will receive the commands) and WhatsApp through Twilio.

Install the required packages and make them available in the `requirements.txt` file.
```
$ pip install flask, twilio
$ pip freeze > requirements.txt
```

In the file `command.py` import the libraries:
```
import os
from flask import Flask, request
from twilio.twiml.messaging_response import MessagingResponse

```
From the import, `Flask` will help us to setup the server, `request` will enable us to send requests from WhatsApp via the Twilio sandbox to this server we're building. 

`MessagingResponse`
 is the Twilio Python class whose object helps to manage responses, that is incoming and outgoing messages or even calls. In short, `MessagingResponse` helps to starts the [TwiML](https://www.twilio.com/docs/glossary/what-is-twilio-markup-language-twiml)

We will use `os` to make our WhatsApp text be excuted on the remote terminal (can be your remote Linux machine or the Server) as Linux commands (not just text).

Now lets write our first function to handle incomming commands sent from a phone (via WhatsApp) to the Twilio number we obtained early.

```
@app.route("/command", methods=['GET', 'POST'])
def command():
    # get the message body which sent to the Twilio number
    body = request.values.get('Body', None)
    # Start our TwiML response
    resp = MessagingResponse()
```
Now `MessagingResponse` is well set, we can listen to the response coming to our Twilio number obtained. We can receive and process the message sent from any WhatsApp number (ofcourse, sent to our Twilio number). We can now start the chat, receive the commands and run them on the terminal.
```
# Determine the right reply for this message
    if body == 'command':
        resp.message('What command do you want to run on your machine?')
    
    # You can send any command
    elif body == 'init 0':
        resp.message('Shutting down your machine...')
        os.system('init 0')
    
    elif body != 'command':
        os.system(body)
```

Here's the `command.py` file
```
from flask import Flask, request, redirect
from twilio.twiml.messaging_response import MessagingResponse
import os
from decouple import config

app = Flask(__name__)

@app.route("/")
def home():
    # Just to make sure if flask server runs successfully
    return 'Hello, the server is running...'

@app.route("/command", methods=['GET', 'POST'])
def command():
     """
        Send a dynamic reply to an incoming text message
        Get the message the user sent our Twilio number
     """
    body = request.values.get('Body', None)
    # Start our TwiML response
    resp = MessagingResponse()
    
    if body == 'command':
        resp.message('What command do you want to run on your machine?')
    # You can send any command
    elif body == 'init 0':
        resp.message('Shutting down your machine...')
        os.system('init 0')
    elif body != 'command':
        os.system(body)
    return str(resp)

if __name__ == "__main__":
    # Run the script on port 5000
    app.run(debug=True, host='0.0.0.0', port='5000')
 
```
### Send linux commands from your WhatsApp
Finally, we need to send commands and let them be processed by our server. But the server is currently running on localhost. We need to expose the server publicly and use its url as callback url in the Twilio platform. You can choose to deploy the app and continue, but for now i will use [Ngrok](https://ngrok.com/) for this task. Make sure you install **ngrok** before continue.

On the terminal, run this command:
```
$ ngrok http 5000
```
Running this command will expose port 5000 which is the same port where our server is running. Ngrok will return a url (a link) of our running server. Copy this url and fill in the Twilio platform in your project console as a `callback url`.  Check this example below:


![sandbox.jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1641566429289/KZaqRTmIjA.jpeg)

If you followed all instructions up to now, then you're on the right track and ready to start sending commands from your WhatsApp. 

Happy coding! 

### References
- [Source code](https://github.com/maen08/remote-terminal-control)
- [Twilio Sandbox docs](https://www.twilio.com/docs/libraries/python)


Posted [here](https://maenblog.tech/send-linux-commands-to-a-remote-pcor-server-from-whatsapp)