Facebook Messenger Bot - Invalid URL button fields for List Template - django

I have been working to send a list to user containing some data. I am following facebook's doc to setup my request payload. However, I am getting the following error:
{'error': {
'message': '(#100) Invalid URL button fields provided. Please check documentation for details.',
'type': 'OAuthException',
'code': 100,
'error_subcode': 2018125, 'fbtrace_id': 'GZFFcM+j5e/'}}
Here is my JSON Payload:
{'recipient': {'id': 'MY_MESSENGER_ID'},
'message':
{'attachment':
{'type': 'template',
'payload':
{'template_type': 'list',
'top_element_style': 'compact',
'elements':
[{'title': 'Hello 1', 'subtitle': 'Subtitle 1',
'buttons':
[{'title': 'View', 'type': 'web_url',
'url': 'https://www.medium.com/',
'messenger_extensions': 'false',
'webview_height_ratio': 'full',
'fallback_url': 'https://www.medium.com/'}],
'default_action':
{'title': 'View', 'type': 'web_url',
'url': 'https://www.medium.com/',
'messenger_extensions': 'false',
'webview_height_ratio': 'full',
'fallback_url': 'https://www.medium.com/'}},
{'title': 'Hello 2', 'subtitle': 'Subtitle 2',
'image_url': 'https://cdn-images-1.medium.com/1*Vkf6A8Mb0wBoL3Fw1u0paA.jpeg',
'buttons':
[{'title': 'View', 'type': 'web_url',
'url': 'https://www.medium.com/',
'messenger_extensions': 'false',
'webview_height_ratio': 'full',
'fallback_url': 'https://www.medium.com/'}],
'default_action':
{'title': 'View', 'type': 'web_url',
'url': 'https://www.medium.com/',
'messenger_extensions': 'false',
'webview_height_ratio': 'full',
'fallback_url': 'https://www.medium.com/'}}]}}}}
I have checked, re-checked it multiple times. PLUS, I have sent the facebook's example json from the doc but I have got the same reply. Please take a look and let me know where I am stuck!
This is my end url:
"https://graph.facebook.com/v2.6/me/messages?access_token="
Thanks in advance!

Your request has two issues:
For default_action, you can set fallback_url only if messenger_extensions:true
default_action cannot have a title prop.
Try this:
{
"recipient": {
"id": "{{PSID}}"
},
"message": {
"attachment": {
"type": "template",
"payload": {
"template_type": "list",
"top_element_style": "compact",
"elements": [{
"title": "Hello 1",
"subtitle": "Subtitle 1",
"buttons": [{
"title": "View",
"type": "web_url",
"url": "https://www.medium.com/",
"messenger_extensions": "false",
"webview_height_ratio": "full"
}],
"default_action": {
"type": "web_url",
"url": "https://www.medium.com/",
"messenger_extensions": "false",
"webview_height_ratio": "full"
}
},
{
"title": "Hello 2",
"subtitle": "Subtitle 2",
"image_url": "https://cdn-images-1.medium.com/1*Vkf6A8Mb0wBoL3Fw1u0paA.jpeg",
"buttons": [{
"title": "View",
"type": "web_url",
"url": "https://www.medium.com/",
"messenger_extensions": "false",
"webview_height_ratio": "full"
}],
"default_action": {
"type": "web_url",
"url": "https://www.medium.com/",
"messenger_extensions": "false",
"webview_height_ratio": "full"
}
}
]
}
}
}
}

Related

I need to append a value in an array to another value in python

This is the current json response
[
[
{
"TO":"nathanoluwaseyi#gmail.com",
"FROM":"johndoe#gmail.com",
"SUBJECT":"This is the subject 1",
"MESSAGE":[
"First Message"
],
"NAME":"John Doe",
"DATE":"2019-08-18 19:48:10"
},
{
"TO":"nathanoluwaseyi#gmail.com",
"FROM":"johndoe#gmail.com",
"SUBJECT":"This is the subject 2",
"MESSAGE":[
"Second message"
],
"NAME":"John Doe",
"DATE":"2019-08-18 19:48:10"
}
]
]
But i want a situation whereby more than one of the response have the same FROM then, the MESSAGE should be together in this format or something like this. How do i go about this? Everything i have tried didn't work
the date issue can be left for now. the most important is getting the messages into one.
[
[
{
"TO":"nathanoluwaseyi#gmail.com",
"FROM":"johndoe#gmail.com",
"SUBJECT":"This is the subject 1",
"MESSAGE":[
"First Message", "Second Message"
],
"NAME":"John Doe",
"DATE":"2019-08-18 19:48:10"
}
]
]
import json
s = '[...]' # Json string
loaded = json.loads(s) # [[{one json thing}], [{second json thing}]]
loaded = [t[0] for t in loaded] # [{json}, {json}] :)
dictionary = {}
for item in loaded:
FROM = item["FROM"] # From
MESSAGE = item["MESSAGE"][0] # Message
DATE = item["DATE"] # Date
if FROM not in dictionary: # If it hasn't been seen before
dictionary[FROM] = item.copy() # To preserve TO, SUBJECT, ...
del dictionary[FROM]["MESSAGE"] # No more >:)
del dictionary[FROM]["DATE"] # No more >:)
dictionary[FROM]["MESSAGE-DATE"] = [] # This will store the message-date pairs as a tuple
dictionary[FROM]["MESSAGE-DATE"].append((MESSAGE, DATE)) # Here, the message and date are combined into a single item as a tuple
for key in dictionary:
print (dictionary[key])
I've included comments that should explain. Try and see if it fits your purpose :)
(Btw I haven't dealt with json before, just know that it's basically a dictionary haha)
You can create a dict with the unfied messages, checking if 'FROM' is already present. If yes, append the message, otherwise, just add it:
def unify_messages(messages):
unified_msgs = {}
for message in messages:
if message['FROM'] in unified_msgs:
unified_msgs[message['FROM']]['MESSAGE'].extend(message['MESSAGE'])
else:
unified_msgs[message['FROM']] = message
return [v for v in unified_msgs.values()]
for message in messages:
unified_messages = unify_messages(messages)
If you try with:
messages = [
[
{
"TO":"nathanoluwaseyi#gmail.com",
"FROM":"johndoe#gmail.com",
"SUBJECT":"This is the subject 1",
"MESSAGE":[
"First Message"
],
"NAME":"John Doe",
"DATE":"2019-08-18 19:48:10"
},
{
"TO":"nathanoluwaseyi#gmail.com",
"FROM":"johndoe#gmail.com",
"SUBJECT":"This is the subject 2",
"MESSAGE":[
"Second message"
],
"NAME":"John Doe",
"DATE":"2019-08-18 19:48:10"
},
{
"TO":"nathanoluwaseyi#gmail.com",
"FROM":"alice#gmail.com",
"SUBJECT":"This is the subject 1",
"MESSAGE":[
"First Message from alice"
],
"NAME":"John Doe",
"DATE":"2019-08-18 19:48:10"
},
{
"TO":"nathanoluwaseyi#gmail.com",
"FROM":"sam#gmail.com",
"SUBJECT":"This is the subject 1",
"MESSAGE":[
"First Message from sam"
],
"NAME":"John Doe",
"DATE":"2019-08-18 19:48:10"
},
]
]
You`ll get:
[{'DATE': '2019-08-18 19:48:10',
'FROM': 'johndoe#gmail.com',
'MESSAGE': ['First Message', 'Second message'],
'NAME': 'John Doe',
'SUBJECT': 'This is the subject 1',
'TO': 'nathanoluwaseyi#gmail.com'},
{'DATE': '2019-08-18 19:48:10',
'FROM': 'alice#gmail.com',
'MESSAGE': ['First Message from alice'],
'NAME': 'John Doe',
'SUBJECT': 'This is the subject 1',
'TO': 'nathanoluwaseyi#gmail.com'},
{'DATE': '2019-08-18 19:48:10',
'FROM': 'sam#gmail.com',
'MESSAGE': ['First Message from sam'],
'NAME': 'John Doe',
'SUBJECT': 'This is the subject 1',
'TO': 'nathanoluwaseyi#gmail.com'}]

How to send a request?

I need to send a request with the following data
"order": {
"server_callback_url": "http://site.id/callback",
"currency": "UAH",
"amount": "1400",
"order_type": "settlement",
"response_url": "http://site.id/test/responsepage/",
"order_id": "test1234561467462099.19",
"operation_id": "test1234561467462099.19",
"order_desc": "test order",
"merchant_id": 700001,
"receiver": [
{
"requisites": {
"amount": 100,
"merchant_id": 500001
},
"type": "merchant"
},{
"requisites": {
"amount": 200,
"merchant_id": 600001
},
"type": "merchant"
},
]
}
I need to send them to https://api.fondy.eu/api/settlement
But I never did that. I am not familiar with DRF at all. Tell me how to implement it, please.
If we visit the endpoint, it says that only POST methods are allowed. We can make a POST request for example with the requests package.
import requests
data = {
"order": {
"server_callback_url": "http://site.id/callback",
"currency": "UAH",
"amount": "1400",
"order_type": "settlement",
"response_url": "http://site.id/test/responsepage/",
"order_id": "test1234561467462099.19",
"operation_id": "test1234561467462099.19",
"order_desc": "test order",
"merchant_id": 700001,
"receiver": [
{
"requisites": {
"amount": 100,
"merchant_id": 500001
},
"type": "merchant"
},{
"requisites": {
"amount": 200,
"merchant_id": 600001
},
"type": "merchant"
},
]
}
}
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
response = requests.post('https://api.fondy.eu/api/settlement', data=data, headers=headers)
The header can be important, since it tells you in what format you make your reqest, and some APIs do not work if you do not set the Content-type properly.
The response is here a Response object, and you can parse the response to a Python dictionary with:
response.json()
locally this gives me:
{'response': {'error_code': 1002,
'error_message': 'Application error',
'request_id': 'iUxQzJfyBuxdI'}}
The status code is 200, so that probably means that the callback you specified was not valid (or some other items in your request).
You could use DRF as the documentation :
https://www.django-rest-framework.org/tutorial/2-requests-and-responses/
Or without DRF :
# importing the requests library
import requests
# api-endpoint
URL = "https://api.fondy.eu/api/settlement"
# defining a params dict for the parameters to be sent to the API
data =
"order": {
"server_callback_url": "http://site.id/callback",
"currency": "UAH",
"amount": "1400",
"order_type": "settlement",
"response_url": "http://site.id/test/responsepage/",
"order_id": "test1234561467462099.19",
"operation_id": "test1234561467462099.19",
"order_desc": "test order",
"merchant_id": 700001,
"receiver": [
{
"requisites": {
"amount": 100,
"merchant_id": 500001
},
"type": "merchant"
},{
"requisites": {
"amount": 200,
"merchant_id": 600001
},
"type": "merchant"
},
]
}
# sending get request and saving the response as response object
r = requests.POST(url = URL, data= data)
# extracting data in json format
data = r.json()
Maybe you would like to try the API before writing code, there is tool like postman to do this quickly :)

Django and Mailgun : 552 sorry, your envelope sender domain must exist (#5.7.1)

I'm trying to send mail using Django and Mailgun through the Anymail package and with an OVH server.
I'm currently receiving the 552 sorry, your envelope sender domain must exist (#5.7.1) error.
In this question/answer, it is suggested that I would need a "from" header, but the response I'm getting seems to show that the header is already included :
"headers": {
"to": "evenements#mydomain-longversion.org",
"message-id": "20160915065953.15168.46300.4ABD80EB#mailgun.mydomain.fr",
"from": "covoiturage#mydomain.fr",
"subject": "Mail test !"
},
Here is the full response, for reference :
{
"severity": "permanent",
"tags": [],
"storage": {
"url": "https://si.api.mailgun.net/v3/domains/mailgun.mydomain.fr/messages/eyJwIjpmYWxzZSwiayI6ImI5OGIyN2QzLTM2MmEtNGJjNi05ZWViLTRlMTA0NTVmYTIxMiIsInMiOiJlNmY5NzZhZTYwIiwiYyI6InNiaWFkIn0=",
"key": "eyJwIjpmYWxzZSwiayI6ImI5OGIyN2QzLTM2MmEtNGJjNi05ZWViLTRlMTA0NTVmYTIxMiIsInMiOiJlNmY5NzZhZTYwIiwiYyI6InNiaWFkIn0="
},
"delivery-status": {
"tls": false,
"mx-host": "redirect.ovh.net",
"attempt-no": 1,
"description": null,
"session-seconds": 0.9216420650482178,
"code": 552,
"message": "552 sorry, your envelope sender domain must exist (#5.7.1)",
"certificate-verified": false
},
"recipient-domain": "mydomain-longversion.org",
"event": "failed",
"campaigns": [],
"reason": "generic",
"user-variables": {},
"flags": {
"is-routed": null,
"is-authenticated": true,
"is-system-test": false,
"is-test-mode": false
},
"log-level": "error",
"timestamp": 1473922798.282194,
"envelope": {
"transport": "smtp",
"sender": "postmaster#mailgun.mydomain.fr",
"sending-ip": "209.61.151.224",
"targets": "evenements#mydomain-longversion.org"
},
"message": {
"headers": {
"to": "evenements#mydomain-longversion.org",
"message-id": "20160915065953.15168.46300.4ABD80EB#mailgun.mydomain.fr",
"from": "covoiturage#mydomain.fr",
"subject": "Mail test !"
},
"attachments": [],
"recipients": [
"evenements#mydomain-longversion.org"
],
"size": 643
},
"recipient": "evenements#mydomain-longversion.org",
"id": "TfJKwpoZQq6bM-MW5sm6nA"
}
And here is my Django code :
def SendTestEmail(request):
if request.user.is_staff and settings.DEBUG == True :
send_mail(
subject='Mail test !',
message='''Bonjour {}, votre email a bien été envoyé.'''.format(request.user.get_full_name()),
recipient_list=['evenements#mydomain-longversion.org',],
from_email=settings.DEFAULT_FROM_EMAIL,
fail_silently=False,
)
messages.success(request, 'Email correctement envoyé !')
return redirect('rideshare_event_list')
Try using covoiturage#mailgun.mydomain.fr as your from address instead of covoiturage#mydomain.fr.
I'm afraid I'm not sure whether it's possible to use covoiturage#mydomain.fr as the from address.

How to nest a serializer?

So I'm trying to create an /api/info url that return various data on my application. It pulls data from various models and puts it together in one response. I got the following:
class SessionInfo(generics.GenericAPIView):
def get(self, request, format=None):
token = Token.objects.get(user=self.request.user)
userprofile = UserProfile.objects.get(user=self.request.user)
is_admin = self.request.user.is_staff
is_primary_owner = userprofile.primary_owner
managers = userprofile.reports_to.all()
man = ["test manager 1", "test manager 2"]
pages = Page.objects.filter(published=True, show_in_menu=True)
pages_output = JSONRenderer().render(PageSerializer(pages).data)
content = {
'user': {
"username": str(self.request.user.username),
"first_name": str(self.request.user.first_name),
"last_name": str(self.request.user.last_name),
"is_admin": is_admin,
"is_primary_owner": is_primary_owner,
"api_token": token.key,
"timezone": 'blalala',
"managers": man,
},
'license': {
"plan" : "gold",
"expiry_date" : "lol",
},
'feature_flags': {
'billing_test': False,
},
'pages': { pages_output },
}
return Response(content)
However it doesn't properly serialize and render pages, making it an escaped string instead:
{
"feature_flags": {
"billing_test": false
},
"user": {
"username": "test#user.com",
"first_name": "Test",
"last_name": "User",
"is_admin": true,
"managers": [
"test manager 1",
"test manager 2"
],
"api_token": "08d1a5827da9a90e7746949ffd2e69e87c51b272",
"timezone": "blalala",
"is_primary_owner": false
},
"license": {
"expiry_date": "lol",
"plan": "gold"
},
"pages": [
"[{\"id\": 1, \"title\": \"Trololol\"}, {\"id\": 2, \"title\": \"NEW pages\"}]"
]
}
if I use directuly use pages_output = PageSerializer(pages) I get:
<webapp_api_v1.serializers.PageSerializer object at 0x10a0d8f90> is not JSON serializable
How can I make a serializer properly nest within my constructed response? Thanks!
Solved it with pages_output = PageSerializer(pages).data and changing 'pages': pages_output,

Access meta reply message

My backed is giving me some information about the reply in a meta field. For example, when going to #/phoneNumbers/phonelocations/index a request to /api/phonelocations is sent, and this is the data received:
{
"meta": {
"api_action": "find_all",
"api_id": "phonelocations",
"content_type": "application/json",
"error_code": 200,
"errors": [
{
"admin_message": "",
"code": 200,
"message": ""
}
],
"message": "Successfully read phonelocations",
"success": true
},
"phonelocations": [
{
"_id": "0",
"city": "Berlin",
"count": 10,
"country": "DE",
"country_name": "Germany",
"loctype": "GEO",
"loctype_human": "Geographical number",
"subtype": "49GEO",
"subtype_human": "German geographical number",
"type": "phonelocation-faketype"
},
...
]
}
This is present in all replies coming from the backend. I would like to use the message in _reply_meta.message to display it to the user. Is there a standard way in Ember to access the meta information of the replies?
Just use store.metadataFor(type), in your case:
var meta = this.store.metadataFor('phonelocation');
// all metadata is in meta object
meta.message // => "Successfully read phonelocations"
See this in action http://jsfiddle.net/marciojunior/3vfQD/