Using the Conversation class in our server

To integrate the Conversation class with our flask server, we need to create some endpoints that will call its methods. Since the Conversation class needs a database passed in, we will also have to deduce which database we are writing to in our endpoints.

The following naming conventions will be used for our databases:

  • Take the username of the author
  • Take the username of the person receiving the message
  • Arrange them alphabetically
  • Join them with an underscore
  • Add .db as the file extension

When we name our database as such, we will only have one database per two people conversing. Arranging the names alphabetically when determining the database to use ensures that it doesn't matter which user opens the conversation; they will always refer to the same database.

Since we are requiring usernames to be unique, we shouldn't ever have a clash of database names, either.

Let's create the method which determines the database file from two provided usernames. Since this is just a helper function, it does not need its own route:

...
from conversation import Conversation
...
conversations_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'conversations/'))
...

def get_conversation_db_path_for_users(data):
user_one = data["user_one"]
user_two = data["user_two"]

users_in_order = sorted([user_one, user_two])
users_in_order = "_".join(users_in_order)

conversation_db = users_in_order + ".db"
conversation_db_path = os.path.join(conversations_dir, conversation_db)

return conversation_db_path

Since our conversation databases will all be kept in the conversations folder, we create an absolute path to this directory and save it in a variable named conversations_dir. We can then use this to keep the location of all the databases consistent.

Our get_conversation_db_path_for_users will take a dictionary, which should have user_one and user_two as keys. These will contain the two usernames of the people who are talking.

As mentioned, these will be ordered alphabetically and joined with an underscore, before .db is added on to create the full filename. The database filename is then joined to the conversations_dir to create the full path to the file.

Now that we are able to determine the database file from two usernames, we can write the endpoints which use this function.

The first endpoint will initialize the database with its table if it does not already exist:

@app.route("/create_conversation_db", methods=["POST"])
def create_conversation_db():
conversation_db_path = get_conversation_db_path_for_users(request.form)

if not os.path.exists(conversation_db_path):
conversation = Conversation(conversation_db_path)
conversation.initialise_table()

return jsonify({
"success": True,
})

This method begins by figuring out the conversation database file path from the supplied POST parameters. If this does not correspond to an existing file, we initialize an instance of our Conversation class and tell it to initialize the table.

We don't need any feedback from this endpoint, so, we can just return a simple JSON object.

Now, we can write an endpoint which obtains the conversation history between two users:

@app.route("/get_message_history", methods=["POST"])
def get_message_history():
conversation_db_path = get_conversation_db_path_for_users(request.form)
conversation = Conversation(conversation_db_path)

history = conversation.get_history()

return jsonify({
"history": history
})

We again use the POST parameters to get the conversation database, and then use this to create an instance of our Conversation class.

The history is obtained with the get_history method of the Conversation instance and this is returned as JSON to the requester.

Finally, we need an endpoint to add messages to the conversation database, which can be called by our ChatWindow:

import arrow
...

@app.route("/send_message/<username>", methods=["POST"])
def send_message(username):
data = request.form
author = data["author"]
message = data["message"]
date_sent = arrow.now().timestamp

conversation_db_path = get_conversation_db_path_for_users({"user_one": author, "user_two": username})
conversation = Conversation(conversation_db_path)
conversation.add_message(author, message, date_sent)

return jsonify({
"success": True
})

This endpoint shows some syntax, which we have not yet come across. In order to extract a part of a URL as a variable, we can wrap it in pointy brackets inside the route string, then include it as an argument with the decorated function. In the preceding example, we have done this with the username variable.

This now means that, if we visit http://127.0.0.1:5000/send_message/James, our username variable will be James.

Along with the receiver's username, we also extract the author and message from the POST data. Our date_sent will be set to the current timestamp.


I have used the arrow library to handle the timestamp, which can be installed with pip install arrow. You could also use the datetime module to get the timestamp if you would prefer.

We can construct the necessary parameters for our get_db_path_for_users function by putting the author and username variables into a dictionary. This then gives us the path to the conversation database, which we can use to create a Conversation instance and use its add_message method to insert our message.

Again, we shouldn't need any feedback from this endpoint, so we can just return JSON, which lets the requester know that it has completed.

Our server is now equipped to update the relevant conversation database in response to some web requests. The next thing to do is to update our Requester to send them.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset