Change JSON-RPC RESPONSE - python

I am using ODOO 11.0
how to return simple JSON object without JSON-RPC additional parameters
Here is my odoo controller code:
#http.route('/userappoint/webhook_test/',type='json', auth='public',method=['POST'], csrf=False,website=True)
def webhook_test(self,**kw):
response = {
'speech' : 'hello my name is shubham',
'displayText' : 'hello testing',
'source' : 'webhook'
}
return response
And I am getting this result :
{
"result": {
"displayText": "hello testing",
"source": "webhook",
"speech": "hello my name is shubham"
},
"id": "6eaced3e-6b0d-4518-9710-de91eaf16dd9",
"jsonrpc": "2.0"
}
But I need this :
{
"speech": "hello my name is shubham",
"displayText": "hello testing",
"source": "webhook"
}
Any help to point me in the right direction?
Thanks

Works on Odoo11. Just edit below portion of the function _json_response defined at odoo/odoo11/odoo/http.py near about line no : 621-630 as below & Restart the odoo service.
def _json_response(self, result=None, error=None):
response = {
'jsonrpc': '2.0',
'id': self.jsonrequest.get('id')
}
if error is not None:
response['error'] = error
if result is not None:
response['result'] = result
to new:
def _json_response(self, result=None, error=None):
response = {}
if error is not None:
response = error
if result is not None:
response = result
Then, restart the odoo service

Place the following code in any of your controller before you initialize the controller class
from odoo import http
from odoo.http import request, Response, JsonRequest
from odoo.tools import date_utils
class JsonRequestNew(JsonRequest):
def _json_response(self, result=None, error=None):
# response = {
# 'jsonrpc': '2.0',
# 'id': self.jsonrequest.get('id')
# }
# if error is not None:
# response['error'] = error
# if result is not None:
# response['result'] = result
responseData = super(JsonRequestNew, self)._json_response(result=result,error=error)
response = {}
if error is not None:
response = error
if result is not None:
response = result
mime = 'application/json'
body = json.dumps(response, default=date_utils.json_default)
return Response(
body, status=error and error.pop('http_status', 200) or 200,
headers=[('Content-Type', mime), ('Content-Length', len(body))]
)
class RootNew(http.Root):
def get_request(self, httprequest):
# deduce type of request
jsonResponse = super(RootNew, self).get_request(httprequest=httprequest)
if httprequest.mimetype in ("application/json", "application/json-rpc"):
return JsonRequestNew(httprequest)
else:
return jsonResponse
http.root = RootNew()
class MyController(http.Controller):

Related

Bad Request Did not attempt to load JSON data because the request Content-Type was not 'application/json'

Hello I am getting the mentioned error above in my python flask website
here is the code for adding expenses in my auth.py file
#auth.route('/add_expenses', methods=['GET', 'POST'] )
def adding_new_expenses():
name_user = request.args.get("user")
user = None
if name_user is None:
return redirect (url_for("auth.home"))
else:
form = AddExpense(request.form)
if request.method == 'GET':
return render_template("add_expenses.html", form=form)
else:
user = User.query.filter_by(id=name_user).first()
if user is not None:
if form.validate_on_submit():
new_expense = Expenses(expense_category_name=form.expense_category_name.data,
description_expense=form.description_expense.data,
date_purchase=form.date_purchase.data,
amount=form.amount.data,
user_id=user.id)
db.session.add(new_expense)
db.session.commit()
flash("Expense added successfully.")
return redirect(url_for("auth.home", user = name_user))
and my views.py:
#views.route('/add_expenses', methods=['POST'])
def adding_new_expenses():
data = request.json
name_user = data.get("user")
expense_category_name = data.get('expense_category_name')
description = data.get('description_expense')
date = data.get('date_purchase')
amount = data.get('amount')
if name_user is None or expense_category_name is None or description is None or date is None or amount is None:
return jsonify({"error": "Missing required fields"}), 400
user = session.query(User).filter_by(id=name_user).first()
if user is None:
return jsonify({"error": "User not found"}), 400
new_expense = Expenses(expense_category_name=expense_category_name, description_expense=description,
date_purchase=date,
amount=amount, user_id=user.id)
db.session.add(new_expense)
db.session.commit()
return jsonify({"message": "Expense added successfully."}), 200
and my javascript code:
function adding_new_expenses(name_user, type, description, date, amount) {
fetch("/add_expenses", {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name_user: name_user,
expense_category_name: type,
description_expense: description,
date_purchase: date,
amount: amount
})
})
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error("An error occurred while adding the expense.");
}
})
.then(data => {
if (data.message === "Expense added successfully.") {
console.log("Expense added successfully.");
window.location.href = '/home?user=' + name_user;
} else {
console.log(data.error)
}
})
.catch(error => {
console.error(error);
})
}
i can't seem to figure out this error, maybe someone can help me out here.
i am using python flask as my framework, slqalchemy as my database, jinja2 template, bootstrap, and a javascript code

WriteError in pymongo through using test in Postman

I am getting this error in my application after trying to do a test case like this: test case in Postman
Here is my application code, I am quite unsure as to why python is throwing this error at me. It seems to not like me trying to add a new review through Postman which is in this format here: enter image description here
from flask import Flask, request, jsonify, make_response
from pymongo import MongoClient
from bson import ObjectId
import json
import jwt
import datetime
from functools import wraps
import bcrypt
def jwt_required(func):
#wraps(func)
def jwt_required_wrapper(*args, **kwargs):
token = None
if 'x-access-token' in request.headers:
token = request.headers['x-access-token']
if not token:
return jsonify( { 'message' : 'Token is missing' }), 401
try:
data = jwt.decode(token, app.config['SECRET_KEY'])
except:
return jsonify({ 'message' : 'Token is invalid' }), 401
bl_token = blacklist.find_one( { "token" : token })
if bl_token is not None:
return make_response( jsonify ( { "message" : "Token has been cancelled "}), 401)
return func(*args, **kwargs)
return jwt_required_wrapper
def admin_required(func):
#wraps(func)
def admin_required_wrapper(*args, **kwargs):
token = request.headers['x-access-token']
data = jwt.decode(token, app.config['SECRET_KEY'])
if data["admin"]:
return func(*args, **kwargs)
else:
return make_response( jsonify ( { "message" : "Admin access required"}), 401)
return admin_required_wrapper
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, ObjectId):
return str(obj)
return super(MyEncoder, self).default(obj)
app = Flask(__name__)
app.config['SECRET_KEY'] = 'password123'
client = MongoClient("mongodb://127.0.0.1:27017")
db = client.bizDB
businesses = db.biz
users = db.users
blacklist = db.blacklist
app.json_encoder = MyEncoder
with app.test_request_context():
db.mycollection.insert_one({'a': 1})
doc = db.mycollection.find_one({'a': 1})
print(jsonify(doc).response)
#app.route("/api/v1.0/businesses", methods=["GET"])
def show_all_businesses():
page_num, page_size = 1, 10
if request.args.get("pn"):
page_num = int(request.args.get("pn"))
if request.args.get("ps"):
page_size = int(request.args.get("ps"))
page_start = page_size * (page_num - 1)
data_to_return = []
for business in businesses.find().skip(page_start).limit(page_size):
business["_id"] = str(business["_id"])
for review in business["reviews"]:
review["_id"] = str(review["_id"])
data_to_return.append(business)
return make_response( jsonify( data_to_return ), 200 )
#app.route("/api/v1.0/businesses/<string:id>", methods=["GET"])
#jwt_required
def show_one_business(id):
business = businesses.find_one({"_id":ObjectId(id)})
if business is not None:
business["_id"] = str(business["_id"])
for review in business["reviews"]:
review["_id"] = str(review["_id"])
return make_response ( jsonify ( business ), 200)
else:
return make_response (jsonify({ "error" : "Invalid Business ID" } ), 404)
#app.route("/api/v1.0/businesses", methods=["POST"])
#jwt_required
def add_business():
if "name" in request.form and "town" in request.form and "rating" in request.form:
new_business = { "name" : request.form["name"],
"town" : request.form["town"],
"rating" : request.form["rating"],
"reviews" : {}
}
new_business_id = businesses.insert_one(new_business)
new_business_link = "http://localhost:5000/api/v1.0/businesses/" + str(new_business_id.inserted_id)
return make_response( jsonify( { "url" : new_business_link } ), 201 )
else:
return make_response ( jsonify( { "error" : "Missing form data" } ), 404 )
#app.route("/api/v1.0/businesses/<string:id>", methods=["PUT"])
def edit_business(id):
if "name" in request.form and "town" in request.form and "rating" in request.form:
result = businesses.update_one(
{"_id" : ObjectId(id)},
{
"$set": {
"name" : request.form["name"],
"town" : request.form["town"],
"rating" : request.form["rating"]
}
}
)
if result.matched_count == 1:
edited_business_link = "http://localhost:5000/api/v1.0/businesses/" + id
return make_response( jsonify( { "url": edited_business_link } ), 200 )
else:
return make_response ( jsonify( { "error" : "Invalid business ID" } ), 404 )
else:
return make_response ( jsonify( { "error" : "Missing form data" } ), 404 )
#app.route("/api/v1.0/businesses/<string:id>", methods=["DELETE"])
#jwt_required
#admin_required
def delete_business(id):
result = businesses.delete_one( { "_id" : ObjectId(id) })
if result.deleted_count == 1:
return make_response( jsonify( {} ), 204)
else:
return make_response ( jsonify( { "error" : "Invalid business ID" } ), 404 )
#app.route("/api/v1.0/businesses/<string:id>/reviews", methods=["POST"])
#jwt_required
def add_new_review(id):
new_review = {
"_id" : ObjectId(),
"username" : request.form["username"],
"comment" : request.form["comment"],
"stars" : request.form["stars"]
}
businesses.update_one( { "_id" : ObjectId(id)} , {"$push" : { "reviews" : new_review}})
new_review_link = "http://localhost:5000/api/v1.0/businesses/" + id + "/reviews/" + str(new_review["_id"])
return make_response( jsonify( { "url" : new_review_link } ), 201 )
#app.route("/api/v1.0/businesses/<string:id>/reviews", methods=["GET"])
def fetch_all_reviews(id):
data_to_return = []
business = businesses.find_one( {"_id" : ObjectId(id) }, { "reviews" : 1, "_id" : 0})
for review in business["reviews"]:
review["_id"] = str(review["_id"])
data_to_return.append(review)
return make_response( jsonify( data_to_return), 200 )
#app.route("/api/v1.0/businesses/<string:business_id>/reviews/<string:review_id>", methods=["GET"])
def fetch_one_review(business_id, review_id):
business = businesses.find_one( { "reviews._id" : ObjectId(review_id)}, {"_id" : 0, "reviews.$" : 1} )
if business is None:
return make_response ( jsonify( { "error" : "Invalid business ID or Review ID" } ), 404 )
business["reviews"][0]["_id"] = str(business["reviews"][0]["_id"])
return make_response( jsonify( business["reviews"][0] ), 200)
#app.route("/api/v1.0/businesses/<string:id>/reviews/<string:review_id>", methods=["PUT"])
def edit_review(id, review_id):
edited_review = {
"reviews.$.username" : request.form["username"],
"reviews.$.comment" : request.form["comment"],
"reviews.$.stars" : request.form["stars"]
}
businesses.update_one( { "reviews._id" : ObjectId(review_id) }, {"$set" : edited_review })
edit_review_url = "http://localhost:5000/api/v1.0/businesses/" + id + "/reviews/" + review_id
return make_response( jsonify({ "url" : edit_review_url } ), 200 )
#app.route("/api/v1.0/businesses/<string:id>/reviews/<string:review_id>", methods=["DELETE"])
#jwt_required
#admin_required
def delete_review(id, review_id):
businesses.update_one( { "_id" : ObjectId(id) }, { "$pull" : {"reviews" : { "_id" : ObjectId(review_id) } } } )
return make_response( jsonify( {} ), 204)
#app.route("/api/v1.0/login", methods = ["GET"])
def login():
auth = request.authorization
if auth:
user = users.find_one( { "username" : auth.username } )
if user is not None:
if bcrypt.checkpw(bytes(auth.password, 'UTF-8'), user["password"]):
token = jwt.encode( {
'user' : auth.username,
'admin' : user["admin"],
'exp' : datetime.datetime.utcnow() + datetime.timedelta(minutes=30)
}, app.config['SECRET_KEY'])
return make_response (jsonify({ 'token' : token.decode('UTF-8') }), 200)
else:
return make_response(jsonify({ "message" : "Bad password" } ), 401 )
else:
return make_response(jsonify({ "message" : "Bad username" } ), 401 )
return make_response(jsonify({ "message" : "Authentication required" } ), 401 )
#app.route("/api/v1.0/logout", methods=["GET"])
#jwt_required
def logout():
token = None
if 'x-access-token' in request.headers:
token = request.headers['x-access-token']
if not token:
return make_response(jsonify({ "message" : "Token is missing" } ), 401 )
else:
blacklist.insert_one( { "token" : token } )
return make_response(jsonify({ "message" : "Logout Successful" } ), 200 )
if __name__ == "__main__":
app.run(debug=True)
The error I get back is simply:
pymongo.errors.WriteError: The field 'reviews' must be an array but is of type object in document {_id:
ObjectId('5ff3b9a145f6d9013ddb7586')}, full error: {'index': 0, 'code': 2, 'errmsg': "The field 'reviews'
must be an array but is of type object in document {_id: ObjectId('5ff3b9a145f6d9013ddb7586')}"}
You're using a $push on a field that isn't an array. Likely because you are setting it to a dict somewhere. Possibly change the line
"reviews" : {}
to
"reviews" : []

Amazon lex error-An error has occurred: Invalid Lambda Response: Received error response from Lambda: Unhandled

I am developing a chatbot using lex.I created one intent called "latestdetails" and one slot "uniquename".I want to validate the slot "uniquename" such that it does not accept alphabets and ask the message "please enter again" when the input is wrong . Below is my code in python.
When testing the lambda function,I get the correct response but when lambda function is connected with lex via initialization and validation code hook,I get the following error at bot :"Amazon lex error-An error has occurred: Invalid Lambda Response: Received error response from Lambda: Unhandled".
I saw related questions in stackoverflow but I am not able to get the required solution.
import os
import time
import json
import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
def get_slots(event):
return event['currentIntent']['slots']
def elicit_slot(intent_name, slots, slot_to_elicit ,message):
response = {
"dialogAction":
{
"type":"ElicitSlot",
"intentName": intent_name,
"slots": slots,
"slotToElicit": slot_to_elicit,
"message": {
"content": message,
"contentType": "PlainText"
}
}
}
return response
def delegate(slots):
response = {
"dialogAction":
{
"type":"Delegate",
"slots": slots
}
}
return response
def close():
response = {
"dialogAction":
{
"fulfillmentState":"Fulfilled",
"type":"Close",
"message":
{
"contentType":"PlainText",
"content": "Hey your ticket has been raised"
}
}
}
return response
def dispatch(event):
intent_name=event['currentIntent']['name']
if intent_name == 'latestdetails':
source = event['invocationSource']
if source == 'DialogCodeHook':
slots= get_slots(event)
uniquename = event["currentIntent"]["slots"]["uniquename"]
if uniquename.isalpha():
return elicit_slot(intent_name,'uniquename','uniquename','please enteragain')
return delegate(slots)
return close('Fulfilled')
elif source == 'FulfillmentCodeHook':
return close()
def lambda_handler(event, context):
return dispatch(event)

Working with session cookies in Python

I am trying to get access to the Kerio Connect (mailserver) api which uses jsonrpc as a standard for their api.
There is Session.login method that works just fine, I get back a SESSION_CONNECT_WEBADMIN cookie that gets saved in the session:
SESSION_CONNECT_WEBADMIN=2332a56d0203f27972ebbe74c09a7f41262e5b224bc6a05e53e62e5872e9b698; \
path=/admin/; domain=<server>; Secure; HttpOnly; Expires=Tue, 19 Jan 2038 03:14:07 GMT;
But when I then do my next request with the same session, I get back a message that tells me, that my session has expired:
{
"jsonrpc": "2.0",
"id": 2,
"error": {
"code": -32001,
"message": "Session expired.",
"data": {
"messageParameters": {
"positionalParameters": [],
"plurality": 1
}
}
}
}
So here's the Python script leading to that message
import json
import requests
userName = "username"
password = "password"
n=1
application = {}
application["name"] = "Log in"
application["vendor"] = "My Company"
application["version"] = "1.0"
params = {}
params["userName"] = userName
params["password"] = password
params["application"] = application
payload = {}
payload["jsonrpc"] = "2.0"
payload["id"] = n
n += 1
payload["method"] = "Session.login"
payload["params"] = params
headers = {}
headers["Content-Type"] = "application/json-rpc"
json_payload =json.dumps(payload, sort_keys=True, indent=2)
url = "https://<server>:4040/admin/api/jsonrpc/"
session = requests.Session()
response = session.post(url, headers=headers, data=json_payload, verify=False)
# Results in a token / a cookie with that token
payload2 = {}
payload2["jsonrpc"] = "2.0"
payload2["id"] = n
n += 1
payload2["method"] = "Users.get"
json_payload2 = json.dumps(payload2, sort_keys=True, indent=2)
response2 = session.post(url, data=json_payload2, verify=False)
print(response2.text)
What am I missing here because of my lack of experience?
[EDIT]:
I just now realise that when I log in with a browser, two cookies are actually created, each with another token, whereas I get only one cookie back when I try to access the api with Python. Why is that?
Cookies received with Chrome:
TOKEN_CONNECT_WEBADMIN
SESSION_CONNECT_WEBADMIN
Cookie received with Python:
SESSION_CONNECT_WEBADMIN
Working example:
import json
import urllib.request
import http.cookiejar
import ssl
jar = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(jar))
urllib.request.install_opener(opener)
server = "https://mail.smkh.ru:4040"
username = "admin"
password = "pass"
ssl._create_default_https_context = ssl._create_unverified_context # disable ssl cert error
def callMethod(method, params, token=None):
"""
Remotely calls given method with given params.
:param: method string with fully qualified method name
:param: params dict with parameters of remotely called method
:param: token CSRF token is always required except login method. Use method "Session.login" to obtain this token.
"""
data = {"jsonrpc": "2.0", "id": 1, "method": method, "params": params}
req = urllib.request.Request(url=server + '/admin/api/jsonrpc/')
req.add_header('Content-Type', 'application/json')
if token is not None:
req.add_header('X-Token', token)
httpResponse = opener.open(req, json.dumps(data).encode())
if httpResponse.status == 200:
body = httpResponse.read().decode()
return json.loads(body)
session = callMethod("Session.login", {"userName": username, "password": password, "application": {"vendor":"Kerio", "name":"Control Api Demo", "version":"8.4.0"}})
token = session["result"]["token"]
sessions = callMethod("Users.get",
{"query": {
"fields": [
"id",
"loginName",
"fullName",
"description",
"authType",
"itemSource",
"isEnabled",
"isPasswordReversible",
"emailAddresses",
"emailForwarding",
"userGroups",
"role",
"itemLimit",
"diskSizeLimit",
"consumedItems",
"consumedSize",
"hasDomainRestriction",
"outMessageLimit",
"effectiveRole",
"homeServer",
"migration",
"lastLoginInfo",
"accessPolicy"
],
"start": 0,
"limit": 200,
"orderBy": [
{
"columnName": "loginName",
"direction": "Asc"
}
]
},
"domainId": Example:"keriodb://domain/908c1118-94ef-49c0-a229-ca672b81d965"
},
token)
try:
user_names = []
for user in users["result"]["list"]:
print(user["fullName"], " (", user["loginName"], ")", sep="")
user_names.append(user["fullName"])
call_method("Session.logout", {}, token)
return users
except KeyError:
print('Error: {}'.format(users['error']['message']))
call_method("Session.logout", {}, token)
return None

Access the user utterance(first) which triggers the bot(lambda function) in Python aws lex?

I am using python 2.7 trying to achieve the user utterance so after I can prompt it back to user.
I tried
mess = intent_request['currentIntent']['slots']['drink']['inputTranscript']
I want to access the user utterance(current utterance), example "can i order pizza".
I am using python 2.7 aws lambda.
How can i get this utterance?
My code:
import os
import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
def lambda_handler(event,context):
logger.debug('event.bot.name={}'.format(event['bot']['name']))
return dispatch(event)
def dispatch(intent_request):
intent_name = intent_request['currentIntent']['name']
#prompt = intent_request['currentIntent']['inputTranscript']
if intent_name == 'BurgerType':
return get_burger(intent_request)
if intent_name == 'drinks':
return get_drink(intent_request)
def get_drink(intent_request):
slot = intent_request['currentIntent']['slots']
value2 = intent_request['currentIntent']['slots']['drink']
mess = intent_request['currentIntent']['slots']['drink']['inputTranscript']
session_attributes = {}
return close(
session_attributes,
'Fulfilled',{
'contentType':'PlainText',
'content':'Your order of 000'+mess
})
def get_burger(intent_request):
slots = intent_request['currentIntent']['slots']
value = intent_request['currentIntent']['slots']['Burgers']
#value2 = intent_request['currentIntent']['slots']['cheese']
session_attributes = {}
return close(
session_attributes,
'Fulfilled',{
'contentType': 'PlainText',
'content':'Your order of '+value+' burger '#+value2+'has been placed'
})
def close(session_attributes, fulfillment_state, message):
response = {
'sessionAttributes': session_attributes,
'dialogAction':{
'type':'Close',
'fulfillmentState': fulfillment_state,
'message': message
}
}
return response
As you can see the below example request, the utterance by the user i.e the user input is stored in 'inputTranscript' in the 'intent_request' object.
{
'messageVersion': '1.0',
'invocationSource': 'DialogCodeHook',
'userId': 'some_user_id',
'sessionAttributes': {},
'requestAttributes': None,
'bot':
{'name': 'bot_name',
'alias': '$LATEST', 'version': '$LATEST'
},
'outputDialogMode': 'Text',
'currentIntent':
{
'name': 'intent_name',
'slots':
{
'slot1': 'value1'
},
'slotDetails':
{
'slot1':
{
'resolutions': [],
'originalValue': 'value1'
}
},
'confirmationStatus': 'None'
},
'inputTranscript': 'what am i saying to this chatbot'
}
So you can access it using below code:
mess = intent_request['inputTranscript']
Hope it helps.

Categories

Resources