python-whatsapp-bot icon indicating copy to clipboard operation
python-whatsapp-bot copied to clipboard

open AI whatsapp re-send message automatically

Open jdevsan opened this issue 1 year ago • 10 comments

Hi im facing some issues with randomness I dont know what it is, but sometimes messages are resending, open ai assitante send a message with no user interaction in th e chat..

jdevsan avatar Jan 20 '24 16:01 jdevsan

Same here

kaiofreitas avatar Feb 02 '24 19:02 kaiofreitas

@kaiofreitas did u solve it?

jdevsan avatar Mar 22 '24 01:03 jdevsan

Hi, did anyone find a solution for this? I´m over my head trying to solve this and currently didn´t have much progress

GuidoLorenzetti avatar Jun 24 '24 20:06 GuidoLorenzetti

WhatsApp messages are not synchronous. If a WhatsApp message is not received properly, it is resent by meta automatically. Make sure you send meta a 200 every time you push a message into a thread successfully. Otherwise, the message is resent meta. This also happens for status updates of the messages. You would use a more mature what’s app api implementation for python that handles that. In guess this project is not meant to be a productive WhatsApp api implementation but an nice example for beginners.

CeadeS avatar Jun 24 '24 21:06 CeadeS

@CeadeS Thanks for your explanation, I'm having the same problem. Do you think taking this repo as a base for building something to be on production environment is recommended or not even close. I would really appreciate any suggestion related with launching this project to a production environment. Thanks in advanced.

Edwin2711 avatar Jul 10 '24 03:07 Edwin2711

I found a solution, basically it implies checking if the message has already been processed before sending it to OpenAI.

Add this to your views.py file

def is_message_processed(message_id):
    with shelve.open(PROCESSED_MESSAGES_DB) as db:
        return message_id in db

def mark_message_as_processed(message_id):
    with shelve.open(PROCESSED_MESSAGES_DB, writeback=True) as db:
        db[message_id] = datetime.datetime.now().timestamp()

Then, in the handle_message function:

    try:
        if is_valid_whatsapp_message(body):
            message = body["entry"][0]["changes"][0]["value"]["messages"][0]
            message_id = message["id"]

            if is_message_processed(message_id):
                logging.info(f"Message {message_id} has already been processed.")
                return jsonify({"status": "ok"}), 200
            
            mark_message_as_processed(message_id)
            process_whatsapp_message(body)
            return jsonify({"status": "ok"}), 200
        else:
            # if the request is not a WhatsApp API event, return an error
            return (
                jsonify({"status": "error", "message": "Not a WhatsApp API event"}),
                404,
            )
    except json.JSONDecodeError:
        logging.error("Failed to decode JSON")
        return jsonify({"status": "error", "message": "Invalid JSON provided"}), 400

GuidoLorenzetti avatar Jul 12 '24 19:07 GuidoLorenzetti

I found a solution, basically it implies checking if the message has been already processed before sending it to OpenAI.

Add this to your views.py file

def is_message_processed(message_id):
    with shelve.open(PROCESSED_MESSAGES_DB) as db:
        return message_id in db

def mark_message_as_processed(message_id):
    with shelve.open(PROCESSED_MESSAGES_DB, writeback=True) as db:
        db[message_id] = datetime.datetime.now().timestamp()

Then, in the handle_message function:

    try:
        if is_valid_whatsapp_message(body):
            message = body["entry"][0]["changes"][0]["value"]["messages"][0]
            message_id = message["id"]

            if is_message_processed(message_id):
                logging.info(f"Message {message_id} has already been processed.")
                return jsonify({"status": "ok"}), 200
            
            mark_message_as_processed(message_id)
            process_whatsapp_message(body)
            return jsonify({"status": "ok"}), 200
        else:
            # if the request is not a WhatsApp API event, return an error
            return (
                jsonify({"status": "error", "message": "Not a WhatsApp API event"}),
                404,
            )
    except json.JSONDecodeError:
        logging.error("Failed to decode JSON")
        return jsonify({"status": "error", "message": "Invalid JSON provided"}), 400

PROCESSED_MESSAGES_DB is just a name, you can put anything you like in there or define it before. Mine is: PROCESSED_MESSAGES_DB="pm_db"

GuidoLorenzetti avatar Jul 12 '24 19:07 GuidoLorenzetti

@CeadeS Thanks for your explanation, I'm having the same problem. Do you think taking this repo as a base for building something to be on production environment is recommended or not even close. I would really appreciate any suggestion related with launching this project to a production environment. Thanks in advanced.

I´m been building a bot to be on a production environment and even if the current repo is nothing like the original, I think it´s a pretty good starting point. For someone like me who did not know anything about webhooks or things like that, if i would had to start from scratch it would had been a nightmare.

GuidoLorenzetti avatar Jul 12 '24 19:07 GuidoLorenzetti

@CeadeS Thanks for your explanation, I'm having the same problem. Do you think taking this repo as a base for building something to be on production environment is recommended or not even close. I would really appreciate any suggestion related with launching this project to a production environment. Thanks in advanced.

I´m been building a bot to be on a production environment and even if the current repo is nothing like the original, I think it´s a pretty good starting point. For someone like me who did not know anything about webhooks or things like that, if i would had to start from scratch it would had been a nightmare.

I would not recommend launching a production environment at this point at all. But you can start with this repo to learn and test and then build you own with libraries that are well maintained and tested. There are libraries that talk to WhatsApp so you do not have to care about all this stuff with webhooks anymore. But it is important that you understand what is happening so this is more bare metal. But one would not use shelve nor would you run a server directly without proxy or single threaded. In the end you would use nginx and uwsgi with flask or django redis db and a WhatsApp python library to implement your stuff and run it productively.

CeadeS avatar Jul 12 '24 20:07 CeadeS

I found a solution, basically it implies checking if the message has already been processed before sending it to OpenAI.

Add this to your views.py file

def is_message_processed(message_id):
    with shelve.open(PROCESSED_MESSAGES_DB) as db:
        return message_id in db

def mark_message_as_processed(message_id):
    with shelve.open(PROCESSED_MESSAGES_DB, writeback=True) as db:
        db[message_id] = datetime.datetime.now().timestamp()

Then, in the handle_message function:

    try:
        if is_valid_whatsapp_message(body):
            message = body["entry"][0]["changes"][0]["value"]["messages"][0]
            message_id = message["id"]

            if is_message_processed(message_id):
                logging.info(f"Message {message_id} has already been processed.")
                return jsonify({"status": "ok"}), 200
            
            mark_message_as_processed(message_id)
            process_whatsapp_message(body)
            return jsonify({"status": "ok"}), 200
        else:
            # if the request is not a WhatsApp API event, return an error
            return (
                jsonify({"status": "error", "message": "Not a WhatsApp API event"}),
                404,
            )
    except json.JSONDecodeError:
        logging.error("Failed to decode JSON")
        return jsonify({"status": "error", "message": "Invalid JSON provided"}), 400

In my view, this is a form of error handling. Meta might not have received a confirmation that you got the message, or a status update might be incorrectly interpreted as a new message. While this was my initial solution, it doesn't address the root cause of the issue. Meta could repeatedly send you thousands of messages if you don't properly acknowledge their receipt. They deliver messages multiple times if they don't receive a proper confirmation from you.

CeadeS avatar Jul 12 '24 20:07 CeadeS