How to build a Flask chat app with TalkJS

In this tutorial, we'll show you how to integrate the TalkJS chat API with Flask to build a chat app. We'll build a Spring Boot backend that stores user data in a database and serves it from a REST endpoint, and then use this data in our frontend to create TalkJS users and start a chat between them. To keep things simple, we will use the sqlite3 module to create a lightweight database, but you can extend the idea to other popular database options.

The entire source code is available on GitHub.

Setting up a Flask application

Before you start, you will need to have Python installed. You'll also need two additional dependencies, flask and flask_cors. You can install these using pip:

pip install -U flask-cors
pip install Flask

Note that flask_cors is only needed for allowing requests from the same host. We are also using sqlite3, but it comes out-of-the-box with Python.

Setting up the USERS table in SQLite

Next, we'll create a USERS table in sqlite3. We'll open a connection to the database and execute SQL statements using the execute() method on the connection. Note that we must use the execute() method for every statement execution.

conn = sqlite3.connect('test.db')
conn.execute('''CREATE TABLE IF NOT EXISTS USERS
         (ID INT PRIMARY KEY NOT NULL,
         DP CHAR(100) NOT NULL,
         EMAIL CHAR(100) NOT NULL,
         NAME CHAR(50) NOT NULL,
         ROLE CHAR(20) NOT NULL);''')
print("Table created successfully");
conn.close()

Once complete, close the database connection. Now that we have our table, we must set up the endpoints to insert users and retrieve them to the frontend.

Setting up the endpoints

We'll create two endpoints, createUser and getUser . The createUser endpoint add a new user to the database:

@app.route('/createUser/', methods=['POST'])
def createUser():
    conn = sqlite3.connect('test.db')
    requestData = request.json
    id = requestData['id']
    name = requestData['name']
    dp = requestData['dp']
    email = requestData['email']
    role = requestData['role']
    conn.execute("INSERT INTO USERS (ID,DP,EMAIL,NAME,ROLE) VALUES (?,?,?,?,?)",(id, dp, email, name, role));
    conn.commit()
    conn.close()
    return "User Created", 200

The first line denotes the endpoint and the methods you can use. Here, it is just POST. We open a connection to our test.db and retrieve the data from the request using Flask’s inbuilt methods. Once we have all the fields from the request, we execute an INSERT statement. Once the execution is complete, we commit and close the connection and return a 200 response with the user object.

The getUser endpoint retrieves user details. This endpoint fetches the user based on the user id that is sent from the frontend. We use Flask’s inbuilt args method to get the query params and then retrieve the id from it.

@app.route('/getUser/', methods=['GET'])
def getUser():
    requestData = request.args
    id = requestData['id']
    conn = sqlite3.connect('test.db')
    cursor = conn.execute("SELECT * from USERS WHERE ID = ?", id)
    user = {
      'id': "",
      'name': "",
      'dp': "",
      'email': "",
      'role': ""
    }
    for row in cursor:
      user['id'] = row[0]
      user['dp'] = row[1]
      user['email'] = row[2]
      user['name'] = row[3]
      user['role'] = row[4]
    conn.close()
    response = jsonify(user)
    return response, 200

Once we get the id, we open up a connection to the database, and execute a SELECT statement passing the id. The difference here is that we get a cursor returned from the SELECT statement and we must query each row in it to get the actual data. There’s an empty user object to which we will append the retrieved data and once that’s done, we return it to the frontend with a 200 response.

Creating test users

We can now add some test users by making POST requests to the /createUser endpoint. You can use curl or an API platform like Postman to perform the API calls:

curl -X POST -H "Content-Type: application/json" -d '{
    "id": 1,
    "name": "Tom Hardy",
    "dp": "https://randomuser.me/api/portraits/men/1.jpg",
    "email": "tom.hardy@operator.com",
    "role": "AGENT"
  }' http://localhost:8080/createUser/
curl -X POST -H "Content-Type: application/json" -d '{
    "id": 2,
    "name": "John Morrison",
    "dp": "https://randomuser.me/api/portraits/men/62.jpg",
    "email": "john.morrison@operator.com",
    "role": "USER"
  }' http://localhost:8080/createUser/

You should get a 200 OK response and the created user for both the API calls.

Setting up the frontend application

Now we'll create the frontend, following the TalkJS getting started guide to set up a inbox. Make changes to the code as follows:

(
    async function() {
    await Talk.ready;
    let agent = await getAgent();
    let user = await getUser();

    const session = new Talk.Session({
        appId: '<APP_ID>',
        me: user,
    });
    var conversation = session.getOrCreateConversation(Talk.oneOnOneId(user, agent));

    conversation.setAttributes({
        welcomeMessages: ["You can start typing your message here and one of our agents will be with you shortly.", "Please do not divulge any of your personal information."]
    })
    conversation.setParticipant(user);
    conversation.setParticipant(agent);

    var inbox = session.createInbox(conversation);
    inbox.select(conversation);
    inbox.mount(document.getElementById("talkjs-container"));
}());

You will need to replace your app ID with with the value found in the Settings tab of your TalkJS dashboard.

Note that we use two asynchronous functions here, getAgent() and getUser() to retrieve the agent and user data. Add the following functions above the existing code inside the script file.

const getAgent = async () => {
    const response = await fetch('http://localhost:8080/getUser?userId=1');
    const data = await response.json();
    let agent = new Talk.User({
        id: data.id,
        name: data.name,
        photoUrl: data.dp,
        email: data.email,
        role: data.role
    });
    return agent;
}
const getUser = async () => {
    const response = await fetch('http://localhost:8080/getUser?userId=2');
    const data = await response.json();
    let user = new Talk.User({
        id: data.id,
        name: data.name,
        photoUrl: data.dp,
        email: data.email,
        role: data.role
    });
    return user;
}

Once we receive the user and agent data from our database through the API calls, we create Talk.User objects and map them to it. This will allow us to start a conversation with the users retrieved from the database.

Conclusion

We have successfully integrated a Flask application with TalkJS and retrieved user data from a SQLite database through API calls. Even though this is a very simple example that showcases the capabilities of TalkJS, you can expand it to any production scenario by implementing authentication, authorization, role-based dashboards, and more. The source code is available on GitHub.