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"
}
}
},
Related
I am using the python slack bolt. https://api.slack.com/start/building/bolt-python#create
I created the example in the link and was able to make a home tab page but I want to create a modal from a message in a channel, not a home page view. I have looked everywhere for a basic example but I can't get any MODALS to work with what I have learned from slack's own documentation. This is the only examples I can find (which came from slack's own documentation after you read the starting out page).
Here is the test example that works but shows up with a home page instead of a modal:
SLACK_BOT_TOKEN="slackbottokenstring"
SLACK_SIGNING_SECRET="slacksigningsecretstring"
import os
# Use the package we installed
from slack_bolt import App
# Initializes your app with your bot token and signing secret
app = App(
token = SLACK_BOT_TOKEN,
signing_secret = SLACK_SIGNING_SECRET
# token=os.environ.get("SLACK_BOT_TOKEN"),
# signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
)
# Add functionality here
#app.event("app_home_opened")
def update_home_tab(client, event, logger):
try:
# views.publish is the method that your app uses to push a view to the Home tab
client.views_publish(
# the user that opened your app's app home
user_id=event["user"],
# the view object that appears in the app home
view={
"type": "home",
"callback_id": "home_view",
# body of the view
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Welcome to your _App's Home_* :tada:"
}
},
{
"type": "divider"
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "This button won't do much for now but you can set up a listener for it using the `actions()` method and passing its unique `action_id`. See an example in the `examples` folder within your Bolt app."
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Click me!"
}
}
]
}
]
}
)
except Exception as e:
logger.error(f"Error publishing home tab: {e}")
# Start your app
if __name__ == "__main__":
app.start(port=int(os.environ.get("PORT", 3000)))
And that works:
But if I try to change it to a modal, it fails:
CODE:
#app.event("app_home_opened")
def update_home_tab(client, event, logger):
try:
# views.publish is the method that your app uses to push a view to the Home tab
client.views_publish(
# the user that opened your app's app home
user_id=event["user"],
# the view object that appears in the app home
view={
"type": "modal",
"callback_id": "modal-identifier",
"title": {
"type": "plain_text",
"text": "Just a modal"
},
"blocks": [
{
"type": "section",
"block_id": "section-identifier",
"text": {
"type": "mrkdwn",
"text": "*Welcome* to ~my~ Block Kit _modal_!"
},
"accessory": {
"type": "button",
"text": {
"type": "plain_text",
"text": "Just a button",
},
"action_id": "button-identifier",
}
}
],
}
)
Error:
127.0.0.1 - - [14/Aug/2022 15:21:15] "POST /slack/events HTTP/1.1" 200 -
Error publishing home tab: The request to the Slack API failed. (url: https://www.slack.com/api/views.publish)
The server responded with: {'ok': False, 'error': 'invalid_arguments', 'response_metadata': {'messages': ['[ERROR] failed to match all allowed schemas [json-pointer:/view]', '[ERROR] unsupported type: modal [json-pointer:/view/type]']}}
I am following the view structure design in a json object like it says here: https://api.slack.com/surfaces/modals/using#composing_views
I figured out what I had to do but it was kinda annoying, I want to just say that first. There are a couple reasons as to why it was annoying to figure out.
There is no direct python example from the website, BUT slack does have a github where they show a modal example.
Using specifically Modals require than just making text blocks in a chat. It requires some weird thing called a trigger_id which you get from initiating a specific response that would cause slack to send an object over to your endpoint. The problem is that there is no example of this. If you are going through slack's tutorial, they ONLY show you how to create a url for making a bot that event listens and responds to messages. You can make your own url using flask but since I am using the bolt slack module, they wrap there own stuff around flask which makes it hard to make basic decorators for flask. - In other words, the slack documentation is super confusing for modals and they don't have any real examples for modals with bolt python.
after doing days of research in my spare time, I was finally able to get an example working where you can COPY AND PASTE this code. You just need your bot token secret and signing key which you can set in your environment or as a string if you are just testing around in your local computer.
SLACK_BOT_TOKEN="slackbottokenstring"
SLACK_SIGNING_SECRET="slacksigningsecretstring"
import os
# Use the package we installed
from slack_bolt import App
from slack_bolt.adapter.flask import SlackRequestHandler
from flask import Flask, request
flask_app = Flask(__name__)
# Initializes your app with your bot token and signing secret
app = App(
token = SLACK_BOT_TOKEN,
signing_secret = SLACK_SIGNING_SECRET
# token=os.environ.get("SLACK_BOT_TOKEN"),
# signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
)
handler = SlackRequestHandler(app)
#flask_app.route("/slack/events", methods=["POST"])
def slack_events():
return handler.handle(request)
#app.shortcut("SearchMessagesID")
def handle_shortcuts(ack, body, logger,client):
ack()
logger.info(body)
print(body)
res = client.views_open(
trigger_id=body["trigger_id"],
view={
"type": "modal",
"callback_id": "modal-identifier",
"title": {
"type": "plain_text",
"text": "Just a modal"
},
"blocks": [
{
"type": "section",
"block_id": "section-identifier",
"text": {
"type": "mrkdwn",
"text": "*Welcome* to ~my~ Block Kit _modal_!"
},
"accessory": {
"type": "button",
"text": {
"type": "plain_text",
"text": "Just a button",
},
"action_id": "button-identifier",
}
}
],
}
)
# Start your app
if __name__ == "__main__":
app.start(port=int(os.environ.get("PORT", 3000)))
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 have to integrate my django project with Ebay. I have followed the SDK repository and set up an account on the developers forum as specified here
Ebay SDK Repository for Python
I tried to run the following function to add an item
#!/usr/bin/env python3
from ebaysdk.trading import Connection
if __name__ == '__main__':
api = Connection(config_file="ebay.yaml", domain="api.sandbox.ebay.com", debug=True)
request = {
"Item": {
"Title": "Professional Mechanical Keyboard",
"Country": "US",
"Location": "IT",
"Site": "US",
"ConditionID": "1000",
"PaymentMethods": "PayPal",
"PayPalEmailAddress": "nobody#gmail.com",
"PrimaryCategory": {"CategoryID": "33963"},
"Description": "A really nice mechanical keyboard!",
"ListingDuration": "Days_10",
"StartPrice": "150",
"Currency": "USD",
"ReturnPolicy": {
"ReturnsAcceptedOption": "ReturnsAccepted",
"RefundOption": "MoneyBack",
"ReturnsWithinOption": "Days_30",
"Description": "If you are not satisfied, return the keyboard.",
"ShippingCostPaidByOption": "Buyer"
},
"ShippingDetails": {
"ShippingServiceOptions": {
"FreeShipping": "True",
"ShippingService": "USPSMedia"
}
},
"DispatchTimeMax": "3"
}
}
api.execute("AddItem", request)
but then I'm running into the following errors
ebaysdk.exception.ConnectionError: "AddItem: Class: RequestError, Severity: Error, Code: 120, You need to create a seller's account. Before you can list this item we need some additional information to create a seller's account."
020-01-16 17:13:02,385 ebaysdk [WARNING]:AddItem: Class: RequestError, Severity: Warning, Code: 21920200, Return Policy Attribute Not Valid Return Policy Attribute returnDescription Not Valid On This Site
I am not getting how to set a seller account or return policy on Ebay. I did a lot of R&D from my side but couldn't find a solution. Any help with this will be highly appreciated.
You have something wrong in your credentials please copy sand box credentials and if you want to generate auth token go to this url : https://developer.ebay.com/DevZone/build-test/test-tool/?index=0 and generate token and if you want to find your sand box credentials visit : https://developer.ebay.com/my/keys and if you are new user please sign up to ebay and it may take one week or 2 days to accept your account and for registration please visit : https://developer.ebay.com/signin
ebay-yaml file:
name: ebay_api_config
# Trading API Sandbox - https://www.x.com/developers/ebay/products/trading-api
api.sandbox.ebay.com:
compatability: 719
appid: ENTER_YOUR_APPID_HERE
certid: ENTER_YOUR_CERTID_HERE
devid: ENTER_YOUR_DEVID_HERE
token: ENTER_YOUR_TOKEN_HERE
# Trading API - https://www.x.com/developers/ebay/products/trading-api
api.ebay.com:
compatability: 719
appid: ENTER_YOUR_APPID_HERE
certid: ENTER_YOUR_CERTID_HERE
devid: ENTER_YOUR_DEVID_HERE
token: ENTER_YOUR_TOKEN_HERE
# Finding API - https://www.x.com/developers/ebay/products/finding-api
svcs.ebay.com:
appid: ENTER_YOUR_APPID_HERE
version: 1.0.0
# Shopping API - https://www.x.com/developers/ebay/products/shopping-api
open.api.ebay.com:
appid: ENTER_YOUR_APPID_HERE
version: 671
additem code:
#!/usr/bin/env python3
from ebaysdk.trading import Connection
if __name__ == '__main__':
api = Connection(config_file="<your-yaml-file-path>", domain="api.sandbox.ebay.com", debug=True)
request = {
"Item": {
"Title": "Professional Mechanical Keyboard",
"Country": "US",
"Location": "IT",
"Site": "US",
"ConditionID": "1000",
"PaymentMethods": "PayPal",
"PayPalEmailAddress": "nobody#gmail.com",
"PrimaryCategory": {"CategoryID": "33963"},
"Description": "A really nice mechanical keyboard!",
"ListingDuration": "Days_10",
"StartPrice": "150",
"Currency": "USD",
"ReturnPolicy": {
"ReturnsAcceptedOption": "ReturnsAccepted",
"RefundOption": "MoneyBack",
"ReturnsWithinOption": "Days_30",
"Description": "If you are not satisfied, return the keyboard.",
"ShippingCostPaidByOption": "Buyer"
},
"ShippingDetails": {
"ShippingServiceOptions": {
"FreeShipping": "True",
"ShippingService": "USPSMedia"
}
},
"DispatchTimeMax": "3"
}
}
d=api.execute("AddItem", request)
print(d)
What are the steps to create a push notification/proactive messaging bot using Python with microsoft bot framework? Since there's no official documentation yet, I don't really know where to start.
I have imported the following:
from botbuilder.schema import Activity, ActivityTypes, ConversationReference
How can it be used and what's a very simple example?
I worked a sample demo which based on state management sample for you .
Pls follow the setps to make it work :
1.Adding code below into app.py :
#APP.route("/api/notify", methods=["POST"])
def notify():
if request.headers["Content-Type"] == "application/json":
body = request.json
else:
return Response(status=415)
activity = Activity().deserialize(body)
auth_header = (
request.headers["Authorization"] if "Authorization" in request.headers else ""
)
async def aux_func(turn_context):
await BOT.on_turn(turn_context)
try:
task = LOOP.create_task(
ADAPTER.process_activity(activity, auth_header, aux_func)
)
LOOP.run_until_complete(task)
return Response(status=201)
except Exception as exception:
raise exception
2.Modify function on_message_activity in state_management_bot.py as code below
async def on_message_activity(self, turn_context: TurnContext):
# Get the state properties from the turn context.
if(turn_context.activity.channel_id != 'notify'):
await turn_context.send_activity("You asid:" + turn_context.activity.text);
else:
await turn_context.send_activity("You get a notify : "+ turn_context.activity.text);
Run this sample locally on Azure bot emulator, click the message from bot and note the conversation id and serviceUrl :
Use postman or restclient to do a post call to trigger the notify endpoint with json content :
{
"text": "this is a notify sent from outside ",
"textFormat": "plain",
"type": "message",
"channelId": "notify",
"from": {
"id": "backend",
"name": "xxxxx",
"role": "xxxxxx"
},
"conversation": {
"id": "<conversation id>"
},
"recipient": {
"id": "",
"name": "bot",
"role": "bot"
},
"serviceUrl": "<service URL>"
}
Result :
Following on from my file upload question, I am getting stuck at Step 5 in the documentation. I get a 400 error suggesting some of the data I am sending is incorrect, but I think I have matched the code exactly.
def create_version_for_file(self, file_name, project_id, folder_id, object_id):
url = '{}data/v1/projects/{}/items'.format(self.DOMAIN, project_id)
logger.info('Starting version create at %s for file_name %s, folder %s, object %s',
url, file_name, folder_id, object_id)
data = {
"jsonapi": {"version": "1.0"},
"data": {
"type": "items",
"attributes": {
"displayName": file_name,
"extension": {
"type": "items:autodesk.core:File",
"version": "1.0"
}
},
"relationships": {
"tip": {
"data": {
"type": "versions",
"id": "1"
}
},
"parent": {
"data": {
"type": "folders",
"id": folder_id
}
}
}
},
"included": [
{
"type": "versions",
"id": "1",
"attributes": {
"name": file_name,
"extension": {
"type": "versions:autodesk.core:File",
"version": "1.0"
}
},
"relationships": {
"storage": {
"data": {
"type": "objects",
"id": object_id
}
}
}
}
]
}
response = self.session.post(url, json=data, headers={
'content-type': 'application/vnd.api+json',
'accept': 'application/vnd.api+json'
})
if response.status_code != status.HTTP_201_CREATED:
logger.warn('Version create for %s failed with status %s: %s', file_name, response.status_code,
response.content)
return None
return json.loads(response.content)
However, the request always fails like so:
Upload succeeded for README.md 2017-10-12 16:53:15,943
Starting version create at https://developer.api.autodesk.com/data/v1/projects/b.f19577f2-c4da-428f-9625-bb53bf434cca/items for file_name README.md, folder urn:adsk.wipprod:fs.folder:co.Hx1ePxPtS1e0P-Ib9qudyQ, object urn:adsk.objects:os.object:3a06e38e-4cac-4ffc-981f-0e5c4e4078aab.f19577f2-c4da-428f-9625-bb53bf434cca/d14c3591-d339-4e62-907c-6f0c8b58b743.md
Version create for README.md failed with status 400: {"jsonapi":{"version":"1.0"},"errors":[{"id":"bfbf0a93-c92a-47af-9ce7-a6af48594e44","status":"400","code":"BAD_INPUT","title":"One or more input values in the request were bad","detail":"Request input is invalid for this operation."}]}
Sample values for all of the variables are off to the right in the logs above.
This might be setup correctly but maybe you have your storage location created in the incorrect folder. From the tutorial I suggested in the forum post, you need to navigate down one level to avoid the creation of the storage location on the Root folder of BIM 360 Docs. Try going back on your steps and do the followed suggested on the tutorial. Focus on step number 4
Authorization Web Flow (This will return us the code we need to obtain our oauth token)
Rest call to the Authentication API to obtain a 3 legged Token GET call to obtain detail of which Hubs do we have access in BIM 360 Docs (Registration of APP required for BIM 360 API access)
GET call to find the project that has your resource
GET call to find the folder where the upload will happen (Plans, Project File, Drawings).
4.1 Extra step can include the access to a sub-folder.
POST call to create a storage location in the previously defined folder
PUT call to upload file to the storage location
POST call to create the first version of the uploaded file.
Check BIM 360 Docs to see your recently uploaded file.
From this forum response, the tutorial is out-of-date and you should use autodesk.bim360:File (but not autodedsk.bim360:File as the typo suggests) in place of autodesk.core:File. There is a more recent example here..
It's still not working but at least my error moved on to The urn must be an unassigned urn prepared by the create storage endpoint, by the same user.