I would like to constantly send data using Django WebSockets. At this moment I try in the way shown below.
routing.py:
channel_routing = [
route("websocket.connect", ws_connect),
consumers.py:
def ws_connect(message):
message.reply_channel.send({"accept": True})
while True:
message.reply_channel.send({
"text": json.dumps({
'message': 'My response2'
})
})
Unfortunately it doesn't work properly. Obviously without while True it send data but only once. Any ideas how can I solve it?
Related
I am currently trying to read my dynamodb table "saved_measurements" with the partition key "Name". I'm doing this through API Gateway Lambda proxy integration, and have tested my
event['pathParameters']['name'] to be working just fine so that shouldn't be the issue.
However, when I query my dynamodb table with my 'Name', the error appears.
{"message": "Internal server error"}
I have referenced many resources for querying dynamodb but nothing seems to work. I have also tried printing a example string within the response body like "yes" and it works with no issues. Only when I attempt to send my data in my response body do I meet that issue again.
What can I try to resolve this?
import json
import boto3
from boto3.dynamodb.conditions import Key, Attr
def lambda_handler(event, context):
client = boto3.resource('dynamodb')
table = client.Table('saved_measurements')
data = table.query(KeyConditionExpression=Key('Name').eq(event['pathParameters']['name']))
stuff = data.Items
response = {
"statusCode": 200,
"headers": {
"Content-Type": 'application/json',
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
},
"body": json.dumps(stuff),
"isBase64Encoded": False
}
return response
You code needs some optimising, however i'm not certain it will resolve the issue. Let me share how I would write it:
import json
import boto3
from boto3.dynamodb.conditions import Key, Attr
client = boto3.resource('dynamodb')
table = client.Table('saved_measurements')
def lambda_handler(event, context):
status_code=0
stuff = ""
try:
data = table.query(KeyConditionExpression=Key('Name').eq(event['pathParameters']['name']))
stuff = json.dumps(data['Items'])
status_code = 200
except Exception as e:
print(e)
stuff = e
status_code = 400
response = {
"statusCode": status_code,
"headers": {
"Content-Type": 'application/json',
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
},
"body": stuff,
"isBase64Encoded": False
}
return response
Some points on the code:
Use try/except block anytime you are making API requests to ensure you are not returning exceptions to your downstream tasks unexpectedly
I tend not to use dot notation in Python, hence I changed date.Items to data['Items']. It tends to work more often than dot notation.
Create you clients outside of your request handler in Lambda, this allows Lambda to reuse clients across multiple invocations which will improve your latency.
Don't return 200 for every request regardless on how it resulted, return the correct status code so your downstream processes don't get confused.
Give those changes a go, if you don't succeed, please share your APIGW config.
I want to create simple function for sending push notification to IOS devices. Inside my model i am storing Device_type and Device_token
for Android i had written simple code using requests like below
import requests, json
def send_push_notif_android(device_token,title,msg):
payload = {
"to" : device_token,
"notification" : {
"title": title,
"text": msg
}
}
url = "https://fcm.googleapis.com/fcm/send"
header = {
"Content-Type":"application/json",
"Authorization":"key = <app key>"
}
requests.post(url, data=json.dumps(payload), headers=header)
I dont know how to do it for IOS
i had generated Certificates.pem file and kept it in my root folder.
Can someone tell me how to write simplest example like this.
Maybe you are looking for django-push-notifications
Since this questions still turns up in search, here is 2020 update version of Python3 HTTP2-compatible script to send push notifications.
I am making a chatbot using a messenger called KakaoTalk.
I wrote a function that sends a message when the current request is received.
However, I can not implement the function of sending notification characters in the morning.
I need your help.
Here is my code sample.
def message(request):
json_str = ((request.body).decode('utf-8'))
received_json_data = json.loads(json_str)
content = received_json_data['content']
data_will_be_send = {
'message': {
'text': connect_apiai.get_apiai(papago.get_papago(content))
}
}
return JsonResponse(data_will_be_send)
How can I send JsonResponse without a request?
I'm building a chat application based on this example (https://github.com/andrewgodwin/channels-examples/blob/master/multichat/chat/routing.py).
When the javascript runs (socket already open, ws_connect has already been executed) it sends the JSON to over the websocket. This 'message' is routed to ws_receive which then loads the JSON into a 'payload' variable. The 'message' reply_channel is added to the payload variable (dict). Using the Channels command, the payload is then sent and routed to chat_join, where it should simply execute the hardcoded message.reply_channel.send.
All steps up until
payload['reply_channel'] = message.content['reply_channel']
work fine. But then the payload is not being routed to the chat_join consumer. If it is being routed correctly, then the reply_channel value is not being read properly, due to which the message is not being sent back to the client.
Can't seem to find the breaking point here. Need help fixing this code.
.js
//Join Room
socket.send(JSON.stringify({
"command": "join",
"room": "102"
}));
routing.py
from channels.routing import route
from MyProject.consumers import ws_connect, ws_receive, chat_join
websocket_routing = [
route("websocket.connect", ws_connect),
route("websocket.receive", ws_receive),
]
custom_routing = [
route("chat.receive", chat_join, command=r'^join$'),
]
consumers.py
from channels import Channel
def ws_receive(message):
payload = json.loads(message['text'])
payload['reply_channel'] = message.content['reply_channel']
Channel("chat.receive").send(payload)
def chat_join(message):
message.reply_channel.send({
"text": json.dumps({
"alpha": "1",
"beta": "2",
}),
})
The Javascript file should be sending the data with a "text" key.
Source: https://channels.readthedocs.io/en/latest/asgi.html#send-close
I tried to change my routing.py to as given below. I included the custom routing as normal routes in the websocket_routing and it started working for me. Hope this helps.
websocket_routing = [
# Called when WebSockets connect
route("websocket.connect", ws_connect),
# Called when WebSockets get sent a data frame
route("websocket.receive", ws_receive),
# Called when WebSockets disconnect
route("websocket.disconnect", ws_disconnect),
#Custom Routing
#Join Chat
route("chat.receive", chat_join, command=r'^join$'),
route("chat.receive", chat_send, command=r'^send$'),
]
I'm trying to get the FB messenger API working using Python's Flask, adapting the following instructions: https://developers.facebook.com/docs/messenger-platform/quickstart
So far, things have been going pretty well. I have verified my callback and am able to receive the messages I send using Messenger on my page, as in the logs in my heroku server indicate the appropriate packets of data are being received by my server. Right now I'm struggling a bit to send responses to the client messenging my app. In particular, I am not sure how to perform the following segment from the tutorial in Flask:
var token = "<page_access_token>";
function sendTextMessage(sender, text) {
messageData = {
text:text
}
request({
url: 'https://graph.facebook.com/v2.6/me/messages',
qs: {access_token:token},
method: 'POST',
json: {
recipient: {id:sender},
message: messageData,
}
}, function(error, response, body) {
if (error) {
console.log('Error sending message: ', error);
} else if (response.body.error) {
console.log('Error: ', response.body.error);
}
});
}
So far, I have this bit in my server-side Flask module:
#app.route('/', methods=["GET", "POST"])
def chatbot_response():
data = json.loads(req_data)
sender_id = data["entry"][0]["messaging"][0]["sender"]["id"]
url = "https://graph.facebook.com/v2.6/me/messages"
qs_value = {"access_token": TOKEN_OMITTED}
json_response = {"recipient": {"id": sender_id}, "message": "this is a test response message"}
response = ("my response text", 200, {"url": url, "qs": qs_value, "method": "POST", "json": json_response})
return response
However, running this, I find that while I can process what someone send my Page, it does not send a response back (i.e. nothing shows up in the messenger chat box). I'm new to Flask so any help would be greatly appreciated in doing the equivalent of the Javascript bit above in Flask.
Thanks!
This is the code that works for me:
data = json.loads(request.data)['entry'][0]['messaging']
for m in data:
resp_id = m['sender']['id']
resp_mess = {
'recipient': {
'id': resp_id,
},
'message': {
'text': m['message']['text'],
}
}
fb_response = requests.post(FB_MESSAGES_ENDPOINT,
params={"access_token": FB_TOKEN},
data=json.dumps(resp_mess),
headers = {'content-type': 'application/json'})
key differences:
message needs a text key for the actual response message, and you need to add the application/json content-type header.
Without the content-type header you get the The parameter recipient is required error response, and without the text key under message you get the param message must be non-empty error response.
This is the Flask example using fbmq library that works for me:
echo example :
from flask import Flask, request
from fbmq import Page
page = fbmq.Page(PAGE_ACCESS_TOKEN)
#app.route('/webhook', methods=['POST'])
def webhook():
page.handle_webhook(request.get_data(as_text=True))
return "ok"
#page.handle_message
def message_handler(event):
page.send(event.sender_id, event.message_text)
In that scenario in your tutorial, the node.js application is sending an HTTP POST request back to Facebook's servers, which then forwards the content on to the client.
So far, sounds like your Flask app is only receiving (AKA serving) HTTP requests. The reason is that that's what the Flask library is all about, and it's the only thing that Flask does.
To send an HTTP request back to Facebook, you can use any Python HTTP client library you like. There is one called urllib in the standard library, but it's a bit clunky to use... try the Requests library.
Since your request handler is delegating to an outgoing HTTP call, you need to look at the response to this sub-request also, to make sure everything went as planned.
Your handler may end up looking something like
import json
import os
from flask import app, request
# confusingly similar name, keep these straight in your head
import requests
FB_MESSAGES_ENDPOINT = "https://graph.facebook.com/v2.6/me/messages"
# good practice: don't keep secrets in files, one day you'll accidentally
# commit it and push it to github and then you'll be sad. in bash:
# $ export FB_ACCESS_TOKEN=my-secret-fb-token
FB_TOKEN = os.environ['FB_ACCESS_TOKEN']
#app.route('/', method="POST")
def chatbot_response():
data = request.json() # flasks's request object
sender_id = data["entry"][0]["messaging"][0]["sender"]["id"]
send_back_to_fb = {
"recipient": {
"id": sender_id,
},
"message": "this is a test response message"
}
# the big change: use another library to send an HTTP request back to FB
fb_response = requests.post(FB_MESSAGES_ENDPOINT,
params={"access_token": FB_TOKEN},
data=json.dumps(send_back_to_fb))
# handle the response to the subrequest you made
if not fb_response.ok:
# log some useful info for yourself, for debugging
print 'jeepers. %s: %s' % (fb_response.status_code, fb_response.text)
# always return 200 to Facebook's original POST request so they know you
# handled their request
return "OK", 200
When doing responses in Flask, you have to be careful. Simply doing a return statement won't return anything to the requester.
In your case, you might want to look at jsonify(). It will take a Python dictionary and return it to your browser as a JSON object.
from flask import jsonify
return jsonify({"url": url, "qs": qs_value, "method": "POST", "json": json_response})
If you want more control over the responses, like setting codes, take a look at make_response()