-
Notifications
You must be signed in to change notification settings - Fork 1
/
views.py
91 lines (71 loc) · 2.97 KB
/
views.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
"""Flask webhook endpoints which get triggered when message from client is received"""
from flask import Blueprint, request, jsonify
import logging
import json
from config import Config
from security import signature_required
from whatsapp_api import (
is_valid_whatsapp_message,
process_whatsapp_message
)
from ai_bot import AIBot
webhook_blueprint = Blueprint("webhook", __name__)
#handle POST requests to /webhook
def handle_message():
"""Handle incoming webhook events from the whatsapp API
The webhook event can be a whatsapp message or a status update
Returns:
response: Tuple containing server response and status code
"""
body = request.get_json()
#check if event received is a whatsapp status update
if (
body.get('entry', [{}])[0]
.get('changes', [{}])[0]
.get('value', {})
.get('statuses')
):
logging.info('Received Whatsapp status update')
return jsonify({'status': 'ok'}), 200
try:
#check if the event received is a whatsapp message
if is_valid_whatsapp_message(body):
#if it is process the whatsapp message
process_whatsapp_message(body)
return jsonify({'status': 'ok'}), 200
else:
#event received is not a Whatsapp event, hence return an error=
return jsonify({'status': 'error', 'message': 'Not a WhatsApp API event'})
except Exception as e:
logging.error(f'Failed to process event: {e}')
return jsonify({'status': 'error', 'message': f'Failed to process event: {e}'}), 400
#handle GET requests to /webhook (verification)
def verify():
#parse request query parameters
mode = request.args.get('hub.mode')
token = request.args.get('hub.verify_token')
challenge = request.args.get('hub.challenge')
#check if both a token and mode were send
if mode and token:
#check if mode and token sent are correct, to verify the authenticity of the sender
if mode == 'subscribe' and token == Config.VERIFY_TOKEN:
logging.info('Webhook verified successfully.')
return challenge, 200
else:
#incorrect token / mode
logging.info('Webhook verification failed')
return jsonify({'status': 'error', 'message': 'Verification failed'}), 403
else:
#missing paramters
logging.info('Verification failed')
return jsonify({'status': 'error', 'message': 'Verification failed'}), 400
#attach functions to webhook blueprint
#explanation of flask blueprints: https://realpython.com/flask-blueprint/#:~:text=Each%20Flask%20Blueprint%20is%20an,before%20you%20can%20run%20it.
#(blueprints are a simple feature to embelish code)
@webhook_blueprint.route('/webhook', methods=['GET'])
def webhook_get():
return verify()
@webhook_blueprint.route('/webhook', methods=['POST'])
@signature_required
def webhook_post():
return handle_message()