I am unable to fetch the JSON response as shown in the tutorial.
I have implemented a Programmable Voice program. I want to show the user the details of the call and if I get the JSON response I would be able to get all of them (cost, duration, status, etc).
# views.py
def start_campaign(request, campaign_id):
try:
campaign = Campaign.objects.get(pk=campaign_id)
account_sid = 'XXX'
auth_token = 'XXX'
client = Client(account_sid, auth_token)
phone_numbers = Contact.objects.filter(phone_book=campaign.phone_book)
custom_url = 'http://XXX.ngrok.io/assets/' + str(campaign_id)
for phone_number in phone_numbers:
call = client.calls.create(
method='GET',
status_callback='http://XXX.ngrok.io/events',
status_callback_event='completed',
status_callback_method='GET',
url=str(custom_url),
to=str(phone_number),
from_='+1XXX'
)
detail = client.calls(str(call.sid)).fetch()
print(detail.price)
except Campaign.DoesNotExist:
raise Http404("Campaign Does Not Exist")
context = {
'all_campaigns': campaign
}
return render(request, "CallCenter/start_campaign.html", context)
def events(request):
status = request.GET.getlist('CallStatus', default=None)
duration = request.GET.getlist('CallDuration', default=None)
print("Duration:{}\nStatus:{}".format(duration, status))
return render(request, "CallCenter/events.html")
In the terminal, I get a output which prints out the status and duration of the call from
"GET /events?Called=%2BXX&ToState=&CallerCountry=US&Direction=outbound-api&Timestamp=Sat,+12+Oct+2019+19:11:50+%2B0000&CallbackSource=call-progress-events&SipResponseCode=200&Ca
llerState=AL&ToZip=&SequenceNumber=0&CallSid=XXX&To=%2BXXX&CallerZip=35766&ToCountry=IN&CalledZip=&ApiVersion=2010-04-01&CalledCity=&CallStatus=completed&Duration=1&From=
%2BXXX&CallDuration=5&AccountSid=XXX&CalledCountry=IN&CallerCity=ESTILLFORK&ToCity=&FromCountry=US&Caller=%2B12563804721&FromCity=ESTILLFORK&CalledState=&FromZip=35766&Fro
mState=AL HTTP/1.1" 200 123
printing out
Duration:['5', '5']
Status:['completed', 'completed']
Unfortunately, I don't know how to ask for the JSON response from Twilio.
Once the callback is received, you have the CallSid ID in the GET data. So you can use that to fetch the complete Call resource:
def events(request):
sid = request.GET['CallSid']
call = client.calls(sid).fetch()
print(call.price)
Related
I am sending a get request in my view and then using the response to fill my database and I need some confirmation on the following:
should i make an api call inside of a view?
what should that view response be?
if i have done it wrong then what would be the right way to send get requests in Django?
my_app/views.py
class api(APIView):
template_name = 'payment/api.html'
def get(self, request):
#I SEND THE GET REQUEST HERE
config = configparser.ConfigParser()
config.read('config.ini')
r = requests.get(config['DEFAULT']['api'])
response = r.json()
#HERE I FILTER THE RESPONSE AND PUT IN A DB
for item in response:
if 'Covered Recipient Physician' in item.values():
person, _ = models.Person.objects.get_or_create(
profile_id = int(item['physician_profile_id']),
first_name = item['physician_first_name'].lower(),
last_name = item['physician_last_name'].lower()
)
address, _ = models.Address.objects.get_or_create(
business_street =
item['recipient_primary_business_street_address_line1'].lower(),
city = item['recipient_city'].lower(),
state = item['recipient_state'].lower(),
country = item['recipient_country'].lower()
)
business, _ = models.Business.objects.get_or_create(
business = item['submitting_applicable_manufacturer_or_applicable_gpo_name'].lower(),
)
business_address_link = models.Business_address_link.objects.create(
business = business,
address = address
)
business_address_link.save()
payment = models.Payment.objects.create(
record_id = int(item['record_id']),
amount = float(item['total_amount_of_payment_usdollars']),
date = item['date_of_payment'],
number_of_payments = int(item['number_of_payments_included_in_total_amount']),
payment_form = item['form_of_payment_or_transfer_of_value'],
nature_of_payment = item['nature_of_payment_or_transfer_of_value']
)
payment.save()
person_payment_information = models.Person_payment_information.objects.create(
person = person,
business_address_link = business_address_link,
payment = payment
)
person_payment_information.save()
Try to use this function for GET request -
#require_http_methods(['GET'])
def get_persons(request):
try:
data = list(Message.objects.all.values())
return render(request=request, template_name='template.html', context={"data": data})
except Exception as e:
return render(request=request, template_name='template.html', context={"error": e})
Once you get the response and send it to template.html, you can display it in any way you want.
If you want to add information to the DB you better use POST request, for example -
#require_http_methods(['POST'])
def add_person(request):
try:
data = json.loads(request.body)
new_person = Person(**data)
new_person.save()
return render(request=request, template_name='template.html', context={"data": data})
except Exception as e:
return render(request=request, template_name='template.html', context={"error": e})
When I am using push notification in python then I am not able to sent push notification time as per required
Example : 1m or 60m etc
I am using https://github.com/olucurious/PyFCM this in application.
Please give me example how to send push notification time as per required
registration_id = request.POST['registration_id']
message_title = request.POST['message_title']
message_body = request.POST['message_body']
result = push_service.notify_single_device(registration_id=registration_id, message_title=message_title, message_body=message_body)
Where we need to sent push notification type for this application When I am setting time then getting so many problems and example not exit in whole example.
Full Example:
def index(request):
if (request.POST['type'] == 'android'):
push_service = FCMNotification(api_key="abc.pem")
registration_id = request.POST['registration_id']
message_title = request.POST['message_title']
message_body = request.POST['message_body']
result = push_service.notify_single_device(registration_id=registration_id, message_title=message_title, message_body=message_body)
print result
return HttpResponse("Hello Testing, world. You're at the tesing index.")
else:
apns = APNs(use_sandbox=True, cert_file='abc.pem', enhanced=True)
token_hex = request.POST['registration_id']
messageTitle = request.POST['message_title']
dict = {'title': request.POST['message_title'], 'body': request.POST['message_body']}
payload = Payload(alert=dict, sound="default", badge=1)
apns.gateway_server.send_notification(token_hex, payload)
frame = Frame()
identifier = 1
expiry = time.time()+3600
priority = 10
frame.add_item(request.POST['registration_id'], payload, identifier, expiry, priority)
return HttpResponse("Hello Testing, world. You're at the tesing index second")
I've tried to build a simple bot on Messenger that echoing back whenever we send a message to it.
The message is sent successfully so far but in the log, it keeps displaying error:
message_id = data['entry'][0]['messaging'][0]['message']['mid']
KeyError: 'message'
I have no idea why it happen, this is the logic operations:
import requests
import traceback
from flask import request
from ...config.default import VERIFY_TOKEN, ACCESS_TOKEN
ROOT_URL = "https://graph.facebook.com/v2.6/me/messages?access_token="
def reply(user_id, page_id, msg):
data = {
"sender": {"id": page_id},
"recipient": {"id": user_id},
"message": {"text": msg}
}
requests.post(ROOT_URL + ACCESS_TOKEN, json=data)
def verification_handler():
if request.args['hub.verify_token'] == VERIFY_TOKEN:
return request.args['hub.challenge'], 200
return "Invalid verification token"
def handle_incoming_messages(data):
try:
# Get all data from Messenger callback - Text
recipient_id = data['entry'][0]['messaging'][0]['recipient']['id']
sender_id = data['entry'][0]['messaging'][0]['sender']['id']
timestamp = data['entry'][0]['messaging'][0]['timestamp']
message_id = data['entry'][0]['messaging'][0]['message']['mid']
text = data['entry'][0]['messaging'][0]['message']['text']
reply(sender_id, recipient_id, text)
except KeyError:
print(traceback.format_exc())
return ''
this is the routes:
from flask import Blueprint, request
from .ops import verification_handler, handle_incoming_messages
mod = Blueprint('messenger', __name__)
# Route: /messenger/
#mod.route('/', methods=['GET'])
def verify():
"""Facebook will GET request to this endpoint for verification."""
return verification_handler()
# Route: /messenger/
#mod.route('/', methods=['POST'])
def handle():
data = request.json
handle_incoming_messages(data)
return ''
# Route: /messenger/hello
#mod.route('/hello')
def hello():
return 'hello there'
I don't have enough reputation to leave a comment so I have to post this here.
From the Python Wiki
Python raises a KeyError whenever a dict() object is requested (using the format a = adict[key]) and the key is not in the dictionary.
Are you sure the key 'message' exists?
I do this to extract the info
if keys_exist(event, ['body']):
event_entry=json.loads(event['body'])
if ((len(event_entry['entry'])>0) & (keys_exist(event_entry['entry'][0],['messaging'])) ):
messaging_event = event_entry['entry'][0]['messaging'][0]
if (keys_exist(messaging_event,['message'])):
msg_txt = messaging_event['message']['text']
sender_id = messaging_event['sender']['id']
I have created a fb bot which simply echoes the user input.
I want it to echo the user inputs continuously and stop when the user types in "bye".
How do I do that? Please help out.
Code :
```import os
import sys
import json
import requests
import time
from flask import Flask, request
app = Flask(__name__)
#app.route('/', methods=['GET'])
def verify():
if request.args.get("hub.mode") == "subscribe" and request.args.get("hub.challenge"):
if not request.args.get("hub.verify_token") == os.environ["VERIFY_TOKEN"]:
return "Verification token mismatch", 403
return request.args["hub.challenge"], 200
return "Hello world", 200
#app.route('/', methods=['POST'])
def webhook():
data = request.get_json()
if data["object"] == "page":
for entry in data["entry"]:
for messaging_event in entry["messaging"]:
if messaging_event.get("message"): # someone sent us a message
sender_id = messaging_event["sender"]["id"]
recipient_id = messaging_event["recipient"]["id"]
message_text = messaging_event["message"]["text"]
reply = "Received : " + message_text
if "bye" in message_text.lower():
reply = "Good-bye"
send_message(sender_id, reply)
return "ok", 200
def send_message(recipient_id, message_text):
log("sending message to {recipient}: {text}".format(recipient=recipient_id, text=message_text))
params = {
"access_token": os.environ["PAGE_ACCESS_TOKEN"]
}
headers = {
"Content-Type": "application/json"
}
data = json.dumps({
"recipient": {
"id": recipient_id
},
"message": {
"text": message_text
}
})
r = requests.post("https://graph.facebook.com/v2.6/me/messages", params=params, headers=headers, data=data)
if r.status_code != 200:
log(r.status_code)
log(r.text)
if __name__ == '__main__':
app.run(debug=True) ```
How about return without send_message(sender_id, reply) function? Like this
if "bye" in message_text.lower():
return "bye", 200
This code is very similar to yours, except the fact that I used class based view
To break the loop add fbid of the user in a file or a DB after he/she says bye.
Everytime a message is posted check fbid to see whether user had already said "bye". If yes return empty response
def post_facebook_message(fbid, recevied_message):
"""
takes a user fb id and posts the bot message as response
"""
post_message_url = 'https://graph.facebook.com/v2.6/me/messages?access_token='+PAGE_ACCESS_TOKEN
response_msg = json.dumps({"recipient":{"id":fbid}, "message":{"text":recevied_message}})
status = requests.post(post_message_url, headers={"Content-Type": "application/json"},data=response_msg)
print status.json()
class FBBotView(generic.View):
#this is to verify your FB account with your program
#use ythe same verify token used while registering the bot
#method_decorator(csrf_exempt)
def get(self, request, *args, **kwargs):
if self.request.GET['hub.verify_token'] == VERIFY_TOKEN:
return HttpResponse(self.request.GET['hub.challenge'])
else:
return HttpResponse('Error, invalid token')
#method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return generic.View.dispatch(self, request, *args, **kwargs)
# Post function to handle Facebook messages
def post(self, request, *args, **kwargs):
# Converts the text payload into a python dictionary
incoming_message = json.loads(self.request.body.decode('utf-8'))
# Facebook recommends going through every entry since they might send
# multiple messages in a single call during high load
for entry in incoming_message['entry']:
for message in entry['messaging']:
# Check to make sure the received call is a message call
# This might be delivery, optin, postback for other events
if 'message' in message:
if recieved_message.lower() == "bye":
#sends an empty response
message = "Good bye"
post_facebook_message(message['sender']['id'],message)
#this line is important because many times FB checks validity of webhook.
return HttpResponse()
I want to text a twilio number and start a series of questions for a user. If it is their first time texting, a new "Caller" should be created. If they have played before, I'd like to look up the "last_question", we asked them and ask them the appropriate question. My code below yields no SMS response and a Twilio error "HTTP retrieval failure."
In models.py I have
class Caller(models.Model):
body = models.CharField(max_length=200)
from_number = models.CharField(max_length=20)
last_question = models.CharField(max_length=2, default="0")
def __unicode__(self):
return self.body
In views.py
def hello_there(request):
body = request.REQUEST.get('Body', None)
from_number = request.REQUEST.get('From', None)
try:
caller = Caller.objects.get(from_number = from_number)
except Caller.DoesNotExist:
caller = None
if caller:
if caller.last_question == "0":
if body == "Password":
message = "Welcome to the game. What is 3 + 4?"
caller.last_question = "1"
else:
message = "What is the password?"
else:
message = "you broke me"
else:
new_caller = Caller(body=body, from_number=from_number, last_question="0")
new_caller.save()
message = "New user created"
resp = twilio.twiml.Reponse()
resp.sms(message)
return HttpResponse(str(resp))
Twilio employee here - the issue could be because you're not providing a csrf_exempt decorator around this view. Django will trigger a security error because it is receiving a HTTP POST request from twilio.com. Django will not accept any HTTP POST request without a csrf token unless you make it exempt.
Have you thought about using the django-twilio package for Django? It will make your life much easier when developing with twilio. This is what your view will look like with django-twilio:
from django_twilio.decorators import twilio_view
#twilio_view
def hello_there(request):
body = request.REQUEST.get('Body', None)
from_number = request.REQUEST.get('From', None)
try:
caller = Caller.objects.get(from_number=from_number)
except Caller.DoesNotExist:
caller = None
if caller:
if caller.last_question == "0":
if body == "Password":
message = "Welcome to the game. What is 3 + 4?"
caller.last_question = "1"
else:
message = "What is the password?"
else:
message = "you broke me"
else:
new_caller = Caller(body=body, from_number=from_number, last_question="0")
new_caller.save()
message = "New user created"
resp = twilio.twiml.Reponse()
resp.sms(message)
return resp
The twilio_view decorator will provide csrf exemption as well as ensuring all your requests are genuine and from twilio.com.
Check out the installation instructions to get started.