I tried Group(groupname).send in the python console and it does not seem to work. Why is this?
This is my consumers.py arrangement:
def ws_connect(message):
message.reply_channel.send({"accept": True})
Group(secure_group).add(message.reply_channel)
def ws_receive(message):
# Nothing to do here
Group(secure_group).send({
"text": "Received {}".format(message.content['text'])
})
def ws_disconnect(message):
Group(secure_group).discard(message.reply_channel)
Routing:
from channels.routing import route
from App.consumers import (
ws_connect,
ws_receive,
ws_disconnect
)
channel_routing = [
route("websocket.connect", ws_connect),
route("websocket.receive", ws_receive),
route("websocket.disconnect", ws_disconnect),
]
Terminal commands:
from channels import Group
#import secure_group here
Group(secure_group).send({ "text": "Tester" })
All my clients have never recieved the text.
CHANNEL_LAYERS config:
CHANNEL_LAYERS = {
"default": {
"BACKEND": "asgiref.inmemory.ChannelLayer",
"ROUTING": "App.routing.channel_routing",
},
}
Inmemory channel layer doesn't support cross-process communication. You can't perform Group send in other say terminal. Try with Redis backend you can send message.
From the doc In-Memory
Related
Here is the code
message = {
"default":"Sample fallback message",
"http":{
"data":[
{
"type":"articles",
"id":"1",
"attributes":{
"title":"JSON:API paints my bikeshed!",
"body":"The shortest article. Ever.",
"created":"2015-05-22T14:56:29.000Z",
"updated":"2015-05-22T14:56:28.000Z"
}
}
]
}
}
message_as_json = json.dumps(message)
response = sns_client.publish(TopicArn = "arn:aws:sns:us-east-1:MY-ARN",
Message = message_as_json, MessageStructure = "json")
print(response)
To test, I used ngrok to connect the localhost (which runs my flask app) to the web and created a http subscription.
When I publish the message I can only see default message in that.
Any idea why this happens?
You need to specify the value of the http key as a simple JSON string value according to the AWS boto3 docs:
Keys in the JSON object that correspond to supported transport
protocols must have simple JSON string values.
Non-string values will cause the key to be ignored.
import json
import boto3
sns_client = boto3.client("sns")
message = {
"default": "Sample fallback message",
"http": json.dumps(
{
"data": [
{
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON:API paints my bikeshed!",
"body": "The shortest article. Ever.",
"created": "2015-05-22T14:56:29.000Z",
"updated": "2015-05-22T14:56:28.000Z",
},
}
]
}
),
}
response = sns_client.publish(
TopicArn="arn:aws:sns:us-east-1:MY-ARN", Message=json.dumps(message), MessageStructure="json"
)
I am new to this, but the code seems to be not working.
Intension is to read json message from Service bus endpoint and then copy and store them in a blob container, but to keep the integrity constant throughout need to keep the name as is.
Do not have much knowledge on this , collected these codes from some blog.
Also if i can listen without func that will also help
Here is the code piece:
with receiver:
for msg in receiver:
print(str(msg))
logging.info('Python ServiceBus trigger processed an Topics: %s', msg.get_body().decode('utf-8'))
#receiver.complete_message(msg)
temp_path = tempfile.gettempdir()
# Create a file in the local data directory to upload and download
local_file_name = str(uuid.uuid4()) + ".txt"
upload_file_path = os.path.join(temp_path, local_file_name)
# Write text to the file
file = open(upload_file_path, 'w')
file.write(msg.get_body().decode('utf-8'))
file.close()
# Create a blob client using the local file name as the name for the blob
blob_client = blob_service_client.get_blob_client(container=container_name, blob=local_file_name)
print("\nUploading to Azure Storage as blob:\n\t" + local_file_name)
# Upload the created file
with open(upload_file_path, "rb") as data:
blob_client.upload_blob(data)
Here we need to create a function where we can configure messages to read which are received from Service Bus queues.
For this we need to mention the bindings in function.json file as below:
serviceBusTrigger:
{
"bindings": [
{
"type": "serviceBusTrigger",
"name": "inputMessage",
"connection": "AzureServiceBusConnectionString",
"queueName": "inputqueue",
"accessRights": "listen",
"direction": "in"
},
{
"type": "blob",
"name": "inputBlob",
"path": "container/{inputMessage}",
"connection": "EnterConnection",
"direction": "in"
}
],
"disabled": false
}
queueTrigger:
{
"bindings": [
{
"type": "blob",
"name": "inputBlob",
"path": "incontainer/{queueTrigger}",
"connection": "testweblog_STORAGE",
"direction": "in"
},
{
"type": "queueTrigger",
"name": "myQueue",
"queueName": "myqueue",
"connection": " EnterConnection _STORAGE",
"direction": "in"
}
],
"disabled": false
}
For more information about the triggers please refer to input and output triggers:
A queue is basically for first-in-first-out messages. When a message comes from the service bus, the service bus queue trigger gets fired and the Azure Function is called. In the Azure Function, we can process the message and then deliver it to destination.
Below is the sample code to receive service bus queue.
Import os
from azure.servicebus import ServiceBusClient
CONNECTION_STR = os.environ['SERVICE_BUS_CONNECTION_STR']
QUEUE_NAME = os.environ["SERVICE_BUS_QUEUE_NAME"]
servicebus_client = ServiceBusClient.from_connection_string(conn_str=CONNECTION_STR)
with servicebus_client:
receiver = servicebus_client.get_queue_receiver(queue_name=QUEUE_NAME)
with receiver:
received_msgs = receiver.receive_messages(max_message_count=10, max_wait_time=5)
for msg in received_msgs:
print(str(msg))
receiver.complete_message(msg)
print("Receive is done.")
For more information refer to Azure Service Bus client library for Python
servicebus_client = ServiceBusClient.from_connection_string(conn_str=CONNECTION_STR, logging_enable=True)
msg_topic="XYZ"
with servicebus_client:
receiver = servicebus_client.get_subscription_receiver(topic_name=TOPIC_NAME, subscription_name=SUBSCRIPTION_NAME, max_wait_time=5)
with receiver:
for msg in receiver:
print(str(msg))
msg_topic=msg
print(str(msg_topic))
receiver.complete_message(msg)
block_blob_service=BlockBlobService(account_name='stgidpdev',account_key='ZZZZ')
block_blob_service.create_container('servicebuscontainer',public_access=PublicAccess.Container)
print('Container Created')
#from azure.storage.blob import ContentSetting
block_blob_service.create_blob_from_text('servicebuscontainer','myblockblob',str(msg_topic),content_settings=None)
I'm making an action-on-google assistant. I'm able to receive the request in JSON format by using Flask to establish webhook in Python. But I've no idea how to send the response back to the assistant.
enter image description here
enter image description here
import os, sys
from flask import Flask, request, send_from_directory, make_response
from googleactions import AppRequest, AppResponse, SimpleResponse
class operation():
def justPrint(self):
print("Hi dear user")
print(AppResponse('告訴我故事發生什麼事吧').json())
app = Flask(__name__)
#app.route('/', methods=['GET'])
def verify():
return "hello world"
#app.route('/', methods=['POST'])
def webhook():
req = request.get_json()
print(req)
op = operation()
getattr(op, req['handler']['name'])()
return 'ok', 200
if __name__ == "__main__":
app.run(debug=True, port=8080)
Your Flask server should return a JSON response in the correct format. It looks like you may be using the googleactions package, but unfortunately that package seems to be out-of-date with the response format expected by Actions Builder.
You should consult the JSON schema for the HandlerResponse type. As it is JSON schema, you can use a tool like Quicktype to generate the appropriate classes for additional syntax support.
The schema file also includes definitions for the internal types.
"HandlerResponse": {
"description": "Represents a response sent from a developer's fulfillment to Actions on\nGoogle.",
"type": "object",
"properties": {
"prompt": {
"description": "Optional. Represents the prompts to be sent to the user, these prompts\nwill be appended to previously added messages unless explicitly\noverwritten.",
"$ref": "#/definitions/Prompt"
},
"scene": {
"description": "Optional. Represents the current and next scene. If `Scene.next` is set\nthe runtime will immediately transition to the specified scene.",
"$ref": "#/definitions/Scene"
},
"session": {
"description": "Optional. Describes data for the current session, session\nparameters can be created, updated, or removed by the fulfillment.",
"$ref": "#/definitions/Session"
},
"user": {
"description": "Optional. Use to specify user parameters to send back.",
"$ref": "#/definitions/User"
},
"home": {
"description": "Optional. Used to specify parameters related to the HomeGraph structure\nthat the target device belongs to. See\nhttps://developers.google.com/actions/smarthome/concepts/homegraph.",
"$ref": "#/definitions/Home"
},
"device": {
"description": "Optional. Use to move between Assistant devices the user has access to.",
"$ref": "#/definitions/Device"
},
"expected": {
"description": "Optional. Describes the expectations for the next dialog turn.",
"$ref": "#/definitions/Expected"
}
}
},
I'm trying to host the Swagger UI of Flask Restplus on Heroku server. It builds successfully and when checked in the logs of the heroku, even there it says "Build succeeded".
But the problem is when I check the actual hosting there's just a msg on the page saying
No API definition provided.
Btw the swagger-UI loads successfully on the browser when run locally.
Following is a sample code snipet for swagger-ui
from flask import Flask
from flask_restplus import Resource, Api
import os
app = Flask(__name__)
api = Api(app)
#api.route('/hello')
class HelloWorld(Resource):
def get(self):
return {'hello': 'world'}
if __name__ == '__main__':
port = int(os.environ.get("PORT", 5000))
app.run(host="0.0.0.0", port=port, debug=True)
So what am I doing wrong here? Is there any way that you can host a simple minimal flask_restplus swagger-UI on heroku ? Any help is appreciated, thanks.
EDIT
Following is the content of the swagger.json
{
"swagger": "2.0",
"basePath": "/",
"paths": {
"/hello": {
"get": {
"responses": {
"200": {
"description": "Success"
}
},
"operationId": "get_hello_world",
"tags": [
"default"
]
}
}
},
"info": {
"title": "API",
"version": "1.0"
},
"produces": [
"application/json"
],
"consumes": [
"application/json"
],
"tags": [
{
"name": "default",
"description": "Default namespace"
}
],
"responses": {
"ParseError": {
"description": "When a mask can't be parsed"
},
"MaskError": {
"description": "When any error occurs on mask"
}
}
}
Also if it helps, this is what's inside the Procfile
web: python app.py
Posting what worked for me, just in case if someone has the same concern in future.
I changed the Procfile from
web: python app.py
to
web: gunicorn app:app
and then the swagger-UI first page also started showing up on heroku. Earlier the endpoints were still accessible but the first page ie. the swagger-UI page wasn't showing up. But making this change got it working.
I am trying to develop a consumer (AsyncWebsocketConsumer type) which will be connected with a websocket and make changes to the frontend using JavaScript.
The first thing that I am failing to implement is the consumer's functions (connect, send, disconnect). Also , using Redis.
my settings.py is
ASGI_APPLICATION = "myapp.routing.application"
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
'hosts': [('localhost', 6379)],
},
}
}
and my routing.py is
application = ProtocolTypeRouter({
"channel": ChannelNameRouter({
"example": ExampleConsumer,
}),
})
Last, my consumers.py is
class ExampleConsumer(AsyncWebsocketConsumer):
async def connect(self,msg):
# Called on connection.
# To accept the connection call:
await self.accept()
print('Channel connected')
When I tried the :
channel_layer = get_channel_layer()
async_to_sync(channel_layer.send)('example', {'type': 'connect'})
so that I could call the connect and see the connected-message that will let me know that the socket is connected , and then continue by sending a message , I get the :
raise NotImplementedError("You must implement application_send()")
You must implement application_send()
I am pretty sure that I have misunderstood so many things but I am looking how to solve this problem for a long time and I couldn't find anything useful for my case , like an example or good documentation , so whatever helps will be appreciated!
You are using ChannelLayers wrong. They are for communicating between different instances of an application. Not for actual establishing WebSocket connections.
Try this:
settings.py
ASGI_APPLICATION = "myapp.routing.application" # make sure your project is called 'myapp' ;-)
routing.py
application = ProtocolTypeRouter({
'websocket': AuthMiddlewareStack(
URLRouter([
path('ws/example/', consumers.ExampleConsumer),
])
),
})
consumers.py
class ExampleConsumer(AsyncWebsocketConsumer):
async def connect(self,msg):
# Called on connection.
# To accept the connection call:
await self.accept()
print('Channel connected')
async def receive(self, data):
# do something with data
print(data)
# send response back to connected client
await self.send('We received your message')
You can use a Simple Websocket Client to test your ws-endpoint.
Connect to http://localhost:8000/ws/example/: You should see "Channel connected" on the console, as well as a message that a client connected.
Send a request with some data. This data should get logged in the console and you will get a response back to your client.
Hope that helps to get you started.