Progress: interface, authentication and receiving messages
Tags: twiliohackathon
Published: 2020-04-10 19:54:35

## Interface
At first I wanted to build a simple no-interface client - just a prompt to send messages. Then I figured that wouldn't be very user friendly for a chat app (obviously). I still want to keep things simple so the interface just has the bare minimum:
- channels list on the left
- messages on the right
- messages/commands input area at the bottom

![interface](https://dev-to-uploads.s3.amazonaws.com/i/c9ni620wf12xsoi94ywx.png)

## Authentication
All required credentials are stored in a `.env` file at the root of the project. This makes it easy to pick them up safely in the code and use them to make requests to the chat api. e.g ,

```py
import os

account_sid = os.getenv('ACCOUNT_SID')

# use account_sid wherever needed
```

## Logging in users
The input section has two modes (insert mode and command mode) that can be toggled by clicking the `escape` key. 

![toggle](https://dev-to-uploads.s3.amazonaws.com/i/fd5kqxsfarsabqe37k0s.gif)

Command mode has to be activated to enter the command to login a user. The command is simple: `-u username`.

![cchat-auth](https://dev-to-uploads.s3.amazonaws.com/i/lrlzmepwzkm553j3lirk.gif)

New users are automatically added to the "general" channel.

## Receiving messages
When the app is launched, a daemon server is started on port 8000. This took me a while to figure out but python's threading module provides some pretty nice features. With it, I can have a non-blocking listener run in the background while the client remains functional in the foreground. 

Once I have a local server running, I can connect it to ngrok, then create a webhook with the ngrok link on Twilio.

```py
class ChatServer(BaseHTTPRequestHandler, ):
   """Creates simple http server"""
   def do_GET(self):
       # hanlde requests from webhook here

   def log_message(self, format, *args):
       # suppress server logs

def chat_server(server_class=HTTPServer,
                handler_class=ChatServer,
                addr="localhost",
                port=8000):
    server_address = (addr, port)
    httpd = server_class(server_address, handler_class)
    httpd.serve_forever()

daemon = threading.Thread(name='daemon_server',
                          target=chat_server)
# set as a daemon so it will be killed once the main thread is dead
daemon.setDaemon(True)
daemon.start()
```

![test](https://dev-to-uploads.s3.amazonaws.com/i/9ythhpsfogx8gtbubnxg.gif)

The browser chat client is running on port 5000. When I post a message, the webhook on Twilio fires and my daemon server on port 8000 receives and processes the request, displaying the message in the cli app.

Apparently, messages sent from the python twilio client don't activate the webhook so I have to do a direct `POST` request to the API. Doing that returns an empty response for some reason so I'm not yet able to send messages from the terminal. But I'll figure it out.

I've not had a lot of time to work on this because of work and starting out was the hardest part. I think it's coming together nicely though. Lets see how much I'll be able to accomplish with the long weekend ahead 🙂.