Similar to a previous SO query, I have a webhook receiver that listens for a POST. I send a WhatsApp message to my Twilio number, Twilio POSTs to the webhook receiver, the server code processes the request and then returns a response object to Twilio. The code pulls some items from an events calendar on Airtable and should send them to WhatsApp via Twilio.
The webhook tests OK with Postman. However, WhatsApp doesn't return results of the POST request and I receive the following warning from the Twilio Debugger:
sourceComponent "14100"
line "1"
ErrorCode "12200"
LogLevel "WARN"
Msg "Content is not allowed in prolog."
EmailNotification "false"
parserMessage "Content is not allowed in prolog."
cols "1"
My full code is here:
from flask import Flask, request
import requests
import json
from airtable import Airtable
from datetime import datetime
from twilio.twiml.messaging_response import MessagingResponse
base_key = 'BASE_KEY'
table_name = 'Events Calendar'
api_key = 'API_KEY'
airtable = Airtable(base_key, table_name, api_key)
API_URL = "https://api.airtable.com/v0/BASE_KEY/Events%20Calendar?maxRecords=3&filterByFormula=IS_AFTER(%7BDate%7D,NOW())"
headers = {
"Authorization": "Bearer API_KEY"
}
app = Flask(__name__)
@app.route('/bot', methods=['POST'])
def accessdb():
incoming_msg = request.values.get('Body', '').lower()
resp = MessagingResponse()
msg = resp.message()
responded = False
if 'next' in incoming_msg:
def pretty(d):
date = datetime.strptime(d["Date"], "%Y-%m-%dT%H:%M:%S.%fZ")
return f'''Date: {date.strftime("%A, %d. %B %Y %I:%M%p")}
Title: {d['Title']}
Description: {d['Description']}
'''
pages = airtable.get_iter(maxRecords=3, formula="Date >= NOW()", sort=["Date"], fields=('Date', 'Title', 'Description'))
mylist = []
for page in pages:
for record in page:
if 'fields' not in record:
continue
fields = record['fields']
mylist.append(pretty(fields))
return "\n".join(mylist)
elif 'what' in incoming_msg:
msg.body("Please enter 'next' to get the next events.")
responded = True
elif not responded:
msg.body("I don't know about that, sorry!")
return str(resp)
if __name__ == '__main__':
app.run()
The above code is deployed to Heroku and I can use curl or Postman to call the webhook and successfully yield the following results:
Date: Wednesday, 07. October 2020 06:00PM
Title: Social Distancing Dance Party: Slow Motion
Description: Slow Motion is the yang to the Saturday Dance Party's yin
Date: Thursday, 08. October 2020 08:00AM
Title: Free Online Meditation Mornings
Description: 20-30 minute meditation. Donations can be made at https://example.com
Date: Saturday, 10. October 2020 07:00PM
Title: Social Distancing Dance Party
Description: A party in your very own kitchen
But calling the webhook from Twilio produces the error given previously.
The earlier SO answer advises to return the query results as follows: return twilioResponse.ToString()
I'm not confident about the syntax and have tried the following:
for page in pages:
for record in page:
if 'fields' not in record:
continue
fields = record['fields']
mylist.append(pretty(fields))
return "\n".join.twilioResponse.ToString(mylist)
However when I try the above it fails as follows:
return "\n".join.twilioResponse.ToString(mylist)
AttributeError: 'builtin_function_or_method' object has no attribute 'twilioResponse'
A nudge in the right direction would be much appreciated. Many thanks in advance.