Related
I am creating posts on my site with the Wordpress API, using Python.
Everything works well.
When I am trying to update a post, it doesn't update.
I have no idea if the problem is in my code, or maybe a setting I should change?
In this example I am trying to change a simple setting on a post with just a title. Nothing fancy.
import requests
import json
import base64
credentials = "username:password"
token = base64.b64encode(credentials.encode())
post_url = "https://www.example.com/wp-json/wp/v2/posts"
header = {"Authorization": "Basic " + token.decode('utf-8'), "Content-Type":"application/json"}
postID = "1122"
data_to_send = {"comment_status": "closed"}
json_to_send = json.dumps(data_to_send)
response = requests.post(post_url + "/" + postID , headers=header, json=json_to_send)
Here is the response. The "modified" time is correct (and is also reflected in the site admin) but the value of comment_status has not changed.
Any help with this will be greatly appreciated.
{
"id": 1122,
"date": "2022-02-03T21:24:32",
"date_gmt": "2022-02-03T19:24:32",
"guid": {
"rendered": "https:\\/\\/www.example.com\\/?p=1122"
},
"modified": "2022-02-03T21:24:32",
"modified_gmt": "2022-02-03T19:24:32",
"slug": "",
"status": "draft",
"type": "post",
"link": "https:\\/\\/www.example.com\\/?p=1122",
"title": {
"rendered": "title"
},
"content": {
"rendered": "",
"protected": false
},
"excerpt": {
"rendered": "",
"protected": false
},
"author": 1,
"featured_media": 0,
"comment_status": "open",
"ping_status": "open",
"sticky": false,
"template": "",
"format": "standard",
"meta": [],
"categories": [1],
"tags": [],
"acf": {
"Description": "",
"first_page_image_id": "",
"Date": "",
"Authors": "",
"Publisher": "",
"Filename": "",
"Format": "",
"Donated_by": "",
"ocr": "",
"Series": ""
},
"_links": {
"self": [{
"href": "https:\\/\\/www.example.com\\/wp-json\\/wp\\/v2\\/posts\\/1122"
}
],
"collection": [{
"href": "https:\\/\\/www.example.com\\/wp-json\\/wp\\/v2\\/posts"
}
],
"about": [{
"href": "https:\\/\\/www.example.com\\/wp-json\\/wp\\/v2\\/types\\/post"
}
],
"author": [{
"embeddable": true,
"href": "https:\\/\\/www.example.com\\/wp-json\\/wp\\/v2\\/users\\/1"
}
],
"replies": [{
"embeddable": true,
"href": "https:\\/\\/www.example.com\\/wp-json\\/wp\\/v2\\/comments?post=1122"
}
],
"version-history": [{
"count": 1,
"href": "https:\\/\\/www.example.com\\/wp-json\\/wp\\/v2\\/posts\\/1122\\/revisions"
}
],
"predecessor-version": [{
"id": 1123,
"href": "https:\\/\\/www.example.com\\/wp-json\\/wp\\/v2\\/posts\\/1122\\/revisions\\/1123"
}
],
"wp:attachment": [{
"href": "https:\\/\\/www.example.com\\/wp-json\\/wp\\/v2\\/media?parent=1122"
}
],
"wp:term": [{
"taxonomy": "category",
"embeddable": true,
"href": "https:\\/\\/www.example.com\\/wp-json\\/wp\\/v2\\/categories?post=1122"
}, {
"taxonomy": "post_tag",
"embeddable": true,
"href": "https:\\/\\/www.example.com\\/wp-json\\/wp\\/v2\\/tags?post=1122"
}
],
"curies": [{
"name": "wp",
"href": "https:\\/\\/api.w.org\\/{rel}",
"templated": true
}
]
}
}
I am running a flask app and using flasgger to generate Swagger Specs as well as a Swagger UI. My API requires the requests to be authenticated using a bearer token. I am able to get the button on the page and set the token. But it is not sent through the requests. I am using OpenAPI 3.0.3. Below is my code:
from flasgger import Swagger
swagger_template = {
'components': {
'securitySchemes': {
'bearerAuth': {
'type': 'http',
'scheme': 'bearer',
'bearerFormat': 'JWT'
}
},
'security': {
'bearerAuth': []
}
}
}
# Register controllers
api = Api(app)
swagger = Swagger(app=app, config={
'headers': [
],
'title': 'Model Design Application API',
'specs': [
{
'endpoint': 'apispec',
'route': '/apispec.json'
}
],
'openapi': '3.0.3'
}, template=swagger_template)
This is the token to be set in the Swagger UI:
This is the UI I get in Swagger:
This is the apispec.json that is generated:
{
"definitions": {
"User": {
"properties": {
"username": {
"default": "Steven Wilson",
"description": "The name of the user",
"type": "string"
}
}
}
},
"info": {
"description": "powered by Flasgger",
"termsOfService": "/tos",
"title": "Model Design Application API",
"version": "0.0.1"
},
"openapi": "3.0.3",
"paths": {
"/profile": {
"get": {
"description": "It works also with swag_from, schemas and spec_dict<br/>",
"responses": {
"200": {
"description": "A single user item",
"schema": {
"$ref": "#/definitions/User"
}
}
},
"summary": "This examples uses FlaskRESTful Resource"
}
}
},
"security": {
"bearerAuth": []
},
"securitySchemes": {
"bearerAuth": {
"bearerFormat": "JWT",
"scheme": "bearer",
"type": "http"
}
}
}
Please advice. Any help is appreciated.
For adding header in Flasgger API, do the following changes:
SWAGGER_TEMPLATE = {"securityDefinitions": {"APIKeyHeader": {"type": "apiKey", "name": "x-access-token", "in": "header"}}}
swagger = Swagger(app, template=SWAGGER_TEMPLATE)
Here, x-access-token is our key name in header. you can change this name according to your requirement.
After this, we need to add this header in our .yml file. Our .yml file will look like this:
summary: "Put your summery here."
description: "Put your description here."
consumes:
- "application/json"
produces:
- "application/json"
security:
- APIKeyHeader: ['x-access-token']
responses:
200:
description: "Success"
Check the working code here
template = {
"swagger": "2.0",
"info": {
"title": XYZ API Docs",
"description": "API Documentation for XYZ Application",
"contact": {
"responsibleOrganization": "",
"responsibleDeveloper": "",
"email": "XYZ#XYZ.com",
"url": "XYZ.com",
},
"termsOfService": "XYZ .com",
"version": "1.0"
},
"basePath": "/api/v1", # base bash for blueprint registration
"schemes": [
"http",
"https"
],
"securityDefinitions": {
"Bearer": {
"type": "apiKey",
"name": "Authorization",
"in": "header",
"description": "\
JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\""
}
},
"security": [
{
"Bearer": []
}
]
}
swagger_config = {
"headers": [
],
"specs": [
{
"endpoint": 'apispec',
"route": '/apispec.json',
"rule_filter": lambda rule: True, # all in
"model_filter": lambda tag: True, # all in
}
],
"static_url_path": "/flasgger_static",
"swagger_ui": True,
"specs_route": "/api/v1/apispec"
}
I'm working with the requests library, Python 3.6, and an SMS platform's Swagger API.
I'm a little bit confused as to how I would extract a specific key:value from this JSON hierarchy.
Here is the URL to the API documentation:
api docs
I am trying to query the endpoint for a specific phone number based on an ID.
This is the URL to query: https://api.kenect.com/v1/conversations/****ID***
Here is the JSON hierarchy, so I would like to use the 'phoneNumbers' key and the 'number' value:
{
"archiveDate": 1514801105185,
"assignedTeamId": 0,
"assignedTeamName": "string",
"assignedUser": {
"departmentId": 1234,
"firstName": "John",
"id": 1234,
"inactiveDate": 1514801105185,
"includeSignature": true,
"lastName": "Doe",
"messageSignature": "Best, John Doe",
"username": "jdoe#mymail.com"
},
"contact": {
"createdDate": 1514801105185,
"emailAddress": "contact#email.com",
"externalId": "8adf-7865",
"firstActiveDate": 1514801105185,
"firstName": "Jane",
"groups": [
{
"createdDate": 1514801105185,
"id": 1234,
"locationId": 1234,
"name": "the inner circle",
"updatedDate": 1514801105185
}
],
"id": 1234,
"inactiveDate": 1514801105185,
"lastContacted": 1514801105185,
"lastName": "Doe",
"locationId": 12345,
"note": "string",
"phoneNumbers": [
{
"city": "Pleasant Grove",
"country": "US",
"createdDate": 1514801105185,
"id": 1234,
"messageOptInDate": 1514801105185,
"messageStopDate": 1514801105185,
"number": "+18015552671",
"primary": true,
"sentOptInMessageDate": 1514801105185,
"smsCapable": true,
"state": "UT",
"status": true,
"type": "CELL",
"updatedDate": 1514801105185,
"zipCode": 84062
}
],
"reviewRequestSent": 1514801105185,
"source": "LIGHTSPEED",
"updatedDate": 1514801105185
},
"createdDate": 1514801105185,
"dataAssigned": 0,
"id": 1234,
"lastMessageType": "FACEBOOK",
"lastSent": 1514801105185,
"locationId": 0,
"messages": [
{
"assignedUserId": 0,
"attachments": [
{
"contentType": "string",
"createdDate": 1514801105185,
"friendlyName": "string",
"id": 1234,
"md5": "string",
"size": 16384,
"thumbnailBase64": "string",
"updatedDate": 1514801105185
}
],
"body": "string",
"contactId": 0,
"conversationId": 0,
"error": "string",
"id": 1234,
"kind": "string",
"locationId": 0,
"outgoing": true,
"readDate": 0,
"respondedDate": 0,
"reviewRequest": true,
"sentDate": 0,
"status": "string",
"type": "FACEBOOK"
}
],
"newConversation": true,
"read": true,
"responded": true,
"snippet": "string",
"subject": "string",
"updatedDate": 1514801105185
}
And finally, here is the code I am trying. I had used a similar function to obtain the message body from this same endpoint, but it's not working for the phone number.
url='https://api.kenect.com/v1/conversations/'
h = {'accept': recContentType,
'content-type': recContentType,
'x-api-token': apiToken,
'x-api-Key': apiKey}
p={'id': id}
response=requests.get(url + id, headers=h, params=p).json()
for item in response['phoneNumber']:
pnum = item['number']
print(pnum)
What am I doing incorrectly here?
Here's the path you'll need to access to get to number:
.contact.phoneNumbers[0].number
So, you'll need this:
number = response['contact']['phoneNumbers'][0]['number']
print(number)
Or editing your code:
url='https://api.kenect.com/v1/conversations/'
h = {'accept': recContentType,
'content-type': recContentType,
'x-api-token': apiToken,
'x-api-Key': apiKey}
p={'id': id}
response=requests.get(url + id, headers=h, params=p).json()
for item in response['contact']['phoneNumbers']:
pnum = item['number']
print(pnum)
As per the comments below, the code above can result in errors if a field in the json is missing. For instance, if a reponse doesn't have a contact there will be an issue.
Consider adding some more bullet proofing to the code above as follows:
url='https://api.kenect.com/v1/conversations/'
h = {'accept': recContentType,
'content-type': recContentType,
'x-api-token': apiToken,
'x-api-Key': apiKey}
p={'id': id}
response=requests.get(url + id, headers=h, params=p).json()
if response:
if 'contact' in response:
if 'phoneNumbers' in response['contact']:
for item in response['contact']['phoneNumbers']:
pnum = item['number']
print(pnum)
I think there is enough checking in the new version of code to avoid the error you described in the comments below. Now, we only process the response when it is non empty and when it contains a contact key which in turn has to contain the phoneNumbers key. There is still an opportunity to print None, when a phoneNumber doesn't contain a number, but that won't generate an error. Just be aware that pnum could be None.
I recently enabled persistent_menu for my bot but now I want to disable it.
Below is how i enabled it
data={
"psid" : uid,
"persistent_menu" : [{
"locale" : "default",
"composer_input_disabled" : False,
"call_to_actions" : [
{
"type": "postback",
"title": "Request Ride",
"payload": "Request Ride"
},
{
"type": "postback",
"title": "Call Customer Service",
"payload": "Call"
},
]
}]
}
r = requests.post("https://graph.facebook.com/v6.0/me/custom_user_settings?access_token=<PAGE TOKEN>", data=json.dumps(data), headers={"Content-Type" : "application/json"})
To disable it, simply omit the call_to_actions field:
{
"psid": <PSID>,
"persistent_menu": [
{
"locale": "default",
"composer_input_disabled": false
}
]
}
I am using python to create webhook for Assistat app. I am able to ask user for location permission, but as soon as user gives consent, I receive following error
UnparseableJsonResponse
API Version 2: Failed to parse JSON response string with 'INVALID_ARGUMENT' error: ": Cannot find field.".
I have checked my webhook server and no request comes to it. This looks like some issue at API.ai side. Below is the Debug response from Actions console when using Python client
{
"assistantToAgentDebug": {
"curlCommand": "curl -v '<URL>'{\"user\":{\"userId\":\"<USED_ID>\",\"locale\":\"en-US\"},\"conversation\":{\"conversationId\":\"1504592665563\",\"type\":\"ACTIVE\",\"conversationToken\":\"[\\\"defaultwelcomeintent-followup\\\"]\"},\"inputs\":[{\"intent\":\"actions.intent.PERMISSION\",\"rawInputs\":[{\"inputType\":\"VOICE\",\"query\":\"yes\"}],\"arguments\":[{\"name\":\"PERMISSION\",\"textValue\":\"true\"}]}],\"surface\":{\"capabilities\":[{\"name\":\"actions.capability.AUDIO_OUTPUT\"},{\"name\":\"actions.capability.SCREEN_OUTPUT\"}]},\"device\":{\"location\":{\"coordinates\":{\"latitude\":37.4219806,\"longitude\":-122.0841979}}},\"isInSandbox\":true}'",
"assistantToAgentJson": {
"user": {
"userId": "<USED_ID>",
"locale": "en-US"
},
"conversation": {
"conversationId": "1504592665563",
"type": "ACTIVE",
"conversationToken": "[\"defaultwelcomeintent-followup\"]"
},
"inputs": [
{
"intent": "actions.intent.PERMISSION",
"rawInputs": [
{
"inputType": "VOICE",
"query": "yes"
}
],
"arguments": [
{
"name": "PERMISSION",
"textValue": "true"
}
]
}
],
"surface": {
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
}
]
},
"device": {
"location": {
"coordinates": {
"latitude": 37.4219806,
"longitude": -122.0841979
}
}
},
"isInSandbox": true
}
},
"agentToAssistantDebug": {
"agentToAssistantJson": {
"message": "Unexpected apiai response format: Empty speech response",
"apiResponse": {
"id": "<ID>",
"timestamp": "2017-09-05T06:24:41.711Z",
"lang": "en",
"result": {},
"status": {
"code": 200,
"errorType": "success"
},
"sessionId": "1504592665563"
}
}
},
"sharedDebugInfo": [
{
"name": "GOOGLE_SYSTEM_ACTION",
"debugInfo": "Your query was handled by Actions on Google."
},
{
"name": "GOOGLE_SYSTEM_ACTION",
"debugInfo": "Your query was handled by Actions on Google."
},
{
"name": "ResponseValidation",
"subDebugEntry": [
{
"name": "UnparseableJsonResponse",
"debugInfo": "API Version 2: Failed to parse JSON response string with 'INVALID_ARGUMENT' error: \": Cannot find field.\"."
}
]
}
]
}
Using Python library Flask-Assistant
How can I resolve this issue?
UPDATE
Node JS client works... what is the issue with Python client?
Action Console Debug response
{
"assistantToAgentDebug": {
"curlCommand": "curl -v '<URL>'{\"user\":{\"userId\":\"<USER_ID>\",\"locale\":\"en-US\"},\"conversation\":{\"conversationId\":\"<ID>\",\"type\":\"ACTIVE\",\"conversationToken\":\"[\\\"_actions_on_google_\\\",\\\"defaultwelcomeintent-followup\\\"]\"},\"inputs\":[{\"intent\":\"actions.intent.PERMISSION\",\"rawInputs\":[{\"inputType\":\"VOICE\",\"query\":\"yes\"}],\"arguments\":[{\"name\":\"PERMISSION\",\"textValue\":\"true\"}]}],\"surface\":{\"capabilities\":[{\"name\":\"actions.capability.AUDIO_OUTPUT\"}]},\"device\":{\"location\":{\"coordinates\":{\"latitude\":37.4219806,\"longitude\":-122.0841979},\"formattedAddress\":\"Googleplex, Mountain View, CA 94043, United States\",\"zipCode\":\"94043\",\"city\":\"Mountain View\"}},\"isInSandbox\":true}'",
"assistantToAgentJson": {
"user": {
"userId": "<USER_ID>",
"locale": "en-US"
},
"conversation": {
"conversationId": "<ID>",
"type": "ACTIVE",
"conversationToken": "[\"_actions_on_google_\",\"defaultwelcomeintent-followup\"]"
},
"inputs": [
{
"intent": "actions.intent.PERMISSION",
"rawInputs": [
{
"inputType": "VOICE",
"query": "yes"
}
],
"arguments": [
{
"name": "PERMISSION",
"textValue": "true"
}
]
}
],
"surface": {
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
}
]
},
"device": {
"location": {
"coordinates": {
"latitude": 37.4219806,
"longitude": -122.0841979
},
"formattedAddress": "Googleplex, Mountain View, CA 94043, United States",
"zipCode": "94043",
"city": "Mountain View"
}
},
"isInSandbox": true
}
},
"agentToAssistantDebug": {
"agentToAssistantJson": {
"conversationToken": "[\"_actions_on_google_\",\"defaultwelcomeintent-followup\"]",
"expectUserResponse": true,
"expectedInputs": [
{
"inputPrompt": {
"richInitialPrompt": {
"items": [
{
"simpleResponse": {
"textToSpeech": "Given permission"
}
}
]
}
},
"possibleIntents": [
{
"intent": "assistant.intent.action.TEXT"
}
]
}
],
"responseMetadata": {
"status": {
"code": 14
},
"queryMatchInfo": {
"queryMatched": true,
"intent": "Default Welcome Intent - fallback"
}
}
}
}
}
Request from Actions server to my Node JS webhook server
{ originalRequest:
{ source: 'google',
version: '2',
data:
{ isInSandbox: true,
surface: [Object],
inputs: [Array],
user: [Object],
device: [Object],
conversation: [Object] } },
id: '<ID>',
timestamp: '2017-09-06T05:43:21.342Z',
lang: 'en',
result:
{ source: 'agent',
resolvedQuery: 'actions_intent_PERMISSION',
speech: '',
action: 'DefaultWelcomeIntent.DefaultWelcomeIntent-fallback',
actionIncomplete: false,
parameters: {},
contexts: [ [Object], [Object], [Object], [Object], [Object] ],
metadata:
{ intentId: '<ID>',
webhookUsed: 'true',
webhookForSlotFillingUsed: 'false',
nluResponseTime: 2,
intentName: 'Default Welcome Intent - fallback' },
fulfillment: { speech: 'Given permission', messages: [Array] },
score: 1 },
status: { code: 200, errorType: 'success' },
sessionId: '<SID>'
}
API.ai Intent settings
The most likely reason you're not getting any hits on your webhook is that you don't have an intent registered to get the reply.
You can do this by creating an Intent with the Event set to actions_intent_PERMISSION.
See also the following answers on SO:
Unable to accept the permission prompt on Actions on Google
Permission response not handled correctly