I'm trying to convert an module that interact with Cleverbot. It's on python 2, but I would like it to be working with python 3. But I encounter an error :
parsed = [ item.split('\r') for item in self.resp.split('\r\r\r\r\r\r')[:-1]]
TypeError: 'str' does not support the buffer interface
I don't know how to resolve it ! Please help !
Here is the entire code :
"""Python library allowing interaction with the Cleverbot API."""
import hashlib
import urllib.request, urllib.parse, urllib.error
from urllib.request import *
class Cleverbot:
"""
Wrapper over the Cleverbot API.
"""
HOST = "www.cleverbot.com"
PROTOCOL = "http://"
RESOURCE = "/webservicemin"
API_URL = PROTOCOL + HOST + RESOURCE
headers = {
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)',
'Accept': 'text/html,application/xhtml+xml,'
'application/xml;q=0.9,*/*;q=0.8',
'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'Accept-Language': 'en-us,en;q=0.8,en-us;q=0.5,en;q=0.3',
'Cache-Control': 'no-cache',
'Host': HOST,
'Referer': PROTOCOL + HOST + '/',
'Pragma': 'no-cache'
}
def __init__(self):
""" The data that will get passed to Cleverbot's web API """
self.data = {
'stimulus': '',
'start': 'y', # Never modified
'sessionid': '',
'vText8': '',
'vText7': '',
'vText6': '',
'vText5': '',
'vText4': '',
'vText3': '',
'vText2': '',
'icognoid': 'wsf', # Never modified
'icognocheck': '',
'fno': 0, # Never modified
'prevref': '',
'emotionaloutput': '', # Never modified
'emotionalhistory': '', # Never modified
'asbotname': '', # Never modified
'ttsvoice': '', # Never modified
'typing': '', # Never modified
'lineref': '',
'sub': 'Say', # Never modified
'islearning': 1, # Never modified
'cleanslate': False, # Never modified
}
# the log of our conversation with Cleverbot
self.conversation = []
self.resp = str()
def ask(self, question):
"""Asks Cleverbot a question.
Maintains message history.
Args:
q (str): The question to ask
Returns:
Cleverbot's answer
"""
# Set the current question
self.data['stimulus'] = question
# Connect to Cleverbot's API and remember the response
try:
self.resp = self._send()
except urllib.error.HTTPError:
# request failed. returning empty string
return str()
# Add the current question to the conversation log
self.conversation.append(question)
parsed = self._parse()
# Set data as appropriate
if self.data['sessionid'] != '':
self.data['sessionid'] = parsed['conversation_id']
# Add Cleverbot's reply to the conversation log
self.conversation.append(parsed['answer'])
return parsed['answer']
def _send(self):
"""POST the user's question and all required information to the
Cleverbot API
Cleverbot tries to prevent unauthorized access to its API by
obfuscating how it generates the 'icognocheck' token, so we have
to URLencode the data twice: once to generate the token, and
twice to add the token to the data we're sending to Cleverbot.
"""
# Set data as appropriate
if self.conversation:
linecount = 1
for line in reversed(self.conversation):
linecount += 1
self.data['vText' + str(linecount)] = line
if linecount == 8:
break
# Generate the token
enc_data = urllib.parse.urlencode(self.data)
digest_txt = enc_data[9:35]
token = hashlib.md5(digest_txt.encode('utf-8')).hexdigest()
self.data['icognocheck'] = token
# Add the token to the data
enc_data = urllib.parse.urlencode(self.data)
binary_data = enc_data.encode('utf-8')
req = urllib.request.Request(self.API_URL, binary_data, self.headers)
# POST the data to Cleverbot's API
conn = urllib.request.urlopen(req)
resp = conn.read()
# Return Cleverbot's response
return resp
def _parse(self):
"""Parses Cleverbot's response"""
parsed = [ item.split('\r') for item in self.resp.split('\r\r\r\r\r\r')[:-1]]
return {
'answer': parsed[0][0],
'conversation_id': parsed[0][1],
'conversation_log_id': parsed[0][2],
'unknown': parsed[1][-1]
}
quest=input("Question: ")
cb = Cleverbot()
quest=cb.ask(quest)
print(quest)
Your self.resp is a bytestring, and you probably want to decode it before you work on it.
Related
I need help please.
I have 2 scripts. The first script consumes from RabbitMQ and I need to send the body received to a variable in script 2.
However, the variable remains empty. I think that script 1 maybe is calling script 2 before the value is received from RabbitMQ?
How can I achieve this? Thanks
script 1
import pika
import time
from script2 import strQueue
class ReceiveFromMQ(object):
def __init__(self):
credentials = pika.PlainCredentials('xxxx', 'xxxx')
parameters = pika.ConnectionParameters('xxxx', xxx, 'xxx',
credentials)
self.connection = pika.BlockingConnection(parameters)
self.channel = self.connection.channel()
self.channel.basic_qos(prefetch_count=1)
self.channel.basic_consume(
queue='queue',
on_message_callback=self.on_response,
auto_ack=True)
self.response = None
self.channel.start_consuming()
def on_response(self, ch, method, props, body):
self.response = body.decode()
strQueue = body.decode()
print(" [x] Received %r" % body.decode())
# getMsg(body.decode())
time.sleep(body.count(b'.'))
print(" [x] Done")
print(' [*] Waiting for messages. To exit press CTRL+C')
return self.response
def call(self):
self.response = None
self.connection.process_data_events(time_limit=None)
print(str(self.response))
return str(self.response)
receive_mq = ReceiveFromMQ()
response = receive_mq.call()
print(response)
script 2
import requests
import json
strQueue = None
# Function Authenticate
def httpAuthenticate (in_apiusers, in_apipass, in_Tenant, in_URL):
try:
print('retrieve token...')
url = in_URL
payload = json.dumps({
"password": str(in_apipass),
"usernameOrEmailAddress": str(in_apiusers),
"tenancyName": str(in_Tenant)
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
json_object = json.loads(response.text)
print('token code: ' + str(response.status_code))
return str(json_object["result"])
except Exception as e:
return 'Fail:'
# Function:Add Queue Item on Uipath Orchestrator
def httpAddQueueItems(in_URL, in_Token, in_QueueName, in_strjson):
try:
print('add queue item...')
url = in_URL
payload = json.dumps({
"itemData": {
"Priority": "Normal",
"Name": str(in_QueueName),
"SpecificContent": {
"in_pjsorequest": in_strpjson
},
"Reference": "ggg"
}
})
headers = {
'X-UIPATH-OrganizationUnitId': '',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + in_Token
}
response = requests.request("POST", url, headers=headers, data=payload)
except Exception as e:
print(e)
return 'Fail'
# CONSTANTS
OnPremuser = "xxxx"
OnPrempass = "xxx!"
OnPremtenant = "Default"
OnPremUrlAuth = "xxxx"
OnPremUrlAddQueue = "https://xxxx"
OnPremQueue = "JSON"
OnPremPJSON = strQueue
OnPremtoken = httpAuthenticate(OnPremuser, OnPrempass, OnPremtenant, OnPremUrlAuth)
httpAddQueueItems(OnPremUrlAddQueue, OnPremtoken, OnPremQueue, OnPremJSON)
What you are trying to achieve is not possible in this way since you are
trying to access a shared variable (Race Condition).
Moreover, only one bytecode instruction can be executed at a time, mean to
say, only one CPU bound task can be run at a time.
P.S:- It can be achieved by running a consumer for the RabbitMQ producer and then assign the json received to a variable.
Recently I've been having some trouble with the X-Flashbots-Signature header when sending a request to the flashbots goerli endpoint.
My python code looks like this:
import requests
import json
import secrets
from eth_account import Account, messages
from web3 import Web3
from math import ceil
rpcUrl = GOERLI_RPC_NODE_PROVIDER
web3 = Web3(Web3.HTTPProvider(rpcUrl))
publicKey = ETH_PUBLIC_KEY
privateKey = ETH_PRIVATE_KEY
contractAddress = GOERLI_TEST_CONTRACT # Goerli test contract
data = CONTRACT_DATA # Contract data to execute
signed = []
for _ in range(2):
nonce = web3.eth.getTransactionCount(publicKey, 'pending')
checksumAddress = Web3.toChecksumAddress(contractAddress)
checksumPublic = Web3.toChecksumAddress(publicKey)
tx = {
'nonce': nonce,
'to': checksumAddress,
'from': checksumPublic,
'value': 0,
'gasPrice': web3.toWei(200, 'gwei'),
'data': data
}
gas = web3.eth.estimateGas(tx)
tx['gas'] = ceil(gas + gas * .1)
signed_tx = web3.eth.account.signTransaction(tx, privateKey)
signed.append(Web3.toHex(signed_tx.rawTransaction))
dt = {
'jsonrpc': '2.0',
'method': 'eth_sendBundle',
'params': [
{
'txs': [
signed[0], signed[1] # Signed txs with web3.eth.account.signTransaction
],
'blockNumber': web3.eth.block_number + 1,
'minTimestamp': '0x0',
'maxTimestamp': '0x0',
'revertingTxHashes': []
}
],
'id': 1337
}
pvk = secrets.token_hex(32)
pbk = Account.from_key(pvk).address
body = json.dumps(dt)
message = messages.encode_defunct(text=Web3.keccak(text=body).hex())
signature = pbk + ':' + Account.sign_message(message, pvk).signature.hex()
hd = {
'Content-Type': 'application/json',
'X-Flashbots-Signature': signature,
}
res = requests.post('https://relay-goerli.flashbots.net/', headers=hd, data=body)
print(res.text)
This code is a modified version of code taken straight from the flashbots docs: https://docs.flashbots.net/flashbots-auction/searchers/advanced/rpc-endpoint/#authentication
Upon running this code I get an internal server error error response. At first, I thought the problem might be fixed by replacing text=Web3.keccak(text=body).hex() to hexstr=Web3.keccak(text=body).hex() or primative=Web3.keccak(text=body), as per the definition of messages.encode_defunct: https://eth-account.readthedocs.io/en/stable/eth_account.html#eth_account.messages.encode_defunct. But after making this replacement, I got the error signer address does not equal expected. This is very confusing, especially because I have resolved the message
with the signature myself and the public key does match. But whenever I send it to the flashbots endpoint, I am left with this error.
Any ideas would be greatly appreciated.
Working example to generate a valid url (including signature) for the Huobi API.
In the Huobi API documenation there is no explicit example that allows you to verify your signature creation method step by step.
My intention is to create that here, but I need help, because I haven't managed yet.
Try to order using huobi api
First, I succeed to get account information
from datetime import datetime
import requests
import json
import hmac
import hashlib
import base64
from urllib.parse import urlencode
#Get all Accounts of the Current User
#apiAccessKey = hb_access, apiSecretKey = hb_secret
timestamp = str(datetime.utcnow().isoformat())[0:19]
params = urlencode({'AccessKeyId': hb_access,
'SignatureMethod': 'HmacSHA256',
'SignatureVersion': '2',
'Timestamp': timestamp
})
method = 'GET'
endpoint = '/v1/account/accounts'
base_uri = 'api.huobi.pro'
pre_signed_text = method + '\n' + base_uri + '\n' + endpoint + '\n' + params
hash_code = hmac.new(hb_secret.encode(), pre_signed_text.encode(), hashlib.sha256).digest()
signature = urlencode({'Signature': base64.b64encode(hash_code).decode()})
url = 'https://' + base_uri + endpoint + '?' + params + '&' + signature
# url = 'https://' + base_uri + endpoint2 + '?' + params + '&' + signature
response = requests.request(method, url)
accts = json.loads(response.text)
print(accts)
it gives :
{'status': 'ok', 'data': [{'id': 1153465, 'type': 'spot', 'subtype': '', 'state': 'working'}, {'id': 1170797, 'type': 'otc', 'subtype': '', 'state': 'working'}]}
but, I have problem with market order.
want to look matchresults :
here is the discription from the website
https://alphaex-api.github.io/openapi/spot/v1/en/#search-match-results
GET /v1/order/matchresults
Parameter DataType Required Default Description Value Range
symbol string true btcusdt, bccbtc.Refer to
I know I should add symbol parameter, but I don't know how I do that,,,
and my code :
timestamp = str(datetime.utcnow().isoformat())[0:19]
params = urlencode({'AccessKeyId': hb_access,
'SignatureMethod': 'HmacSHA256',
'SignatureVersion': '2',
'Timestamp': timestamp,
})
method = 'GET'
base_uri = 'api.huobi.pro'
enpoint ='/v1/order/matchresults'
pre_signed_text = base_uri + '\n' + endpoint + '\n' + params
hash_code = hmac.new(hb_secret.encode(), pre_signed_text.encode(), hashlib.sha256).digest()
signature = urlencode({'Signature': base64.b64encode(hash_code).decode()})
url = 'https://'+base_uri + endpoint +'?'+params+'&'+signature
resp = requests.request(method, url)
resp.json()
it gives :
{'status': 'error',
'err-code': 'api-signature-not-valid',
'err-msg': 'Signature not valid: Verification failure [校验失败]',
'data': None}
I need help...
and another question is :
is way to make Sinature different with using Get method from using POST method?
like placing market order(POST /v1/order/orders/place), when I request using POST do I need to give different Signature?
To get exact symbol you have to provide required parameters in param variable
params = urlencode({'AccessKeyId': hb_access,
'SignatureMethod': 'HmacSHA256',
'SignatureVersion': '2',
'Timestamp': timestamp,
"symbol": "btcusdt" # allowed symbols: GET /v1/common/symbols
})
url variable:
https://api.huobi.pro/v1/order/matchresults?AccessKeyId=39****-b******-4*****-3****&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2022-09-26T19%3A09%3A16&symbol=btcusdt&Signature=1K**************************
Output:
{'status': 'ok', 'data': []}
Here is my way adding parameters and making request:
def huobi(endpoint: str, extra_params: dict={}, AccessKeyId: str=None, SecretKey: str=None) -> dict:
AccessKeyId = 'xxxxxx-xxxxxx-xxxxxx-xxxx' # tmp
SecretKey = 'xxxxxx-xxxxxx-xxxxxx-xxxx' # tmp
timestamp = str(datetime.utcnow().isoformat())[0:19]
standart_params = {
'AccessKeyId': AccessKeyId,
'SignatureMethod': 'HmacSHA256',
'SignatureVersion': '2',
'Timestamp': timestamp
}
params = dict(standart_params, **extra_params)
params_url_enc = urlencode(
sorted(params.items(), key=lambda tup: tup[0])
)
pre_signed = 'GET\n'
pre_signed += 'api.huobi.pro\n'
pre_signed += f'{endpoint}\n'
pre_signed += params_url_enc
sig_bin = hmac.new(
SecretKey.encode(),
pre_signed.encode(),
hashlib.sha256
).digest()
sig_b64_bytes = base64.b64encode(sig_bin)
sig_b64_str = sig_b64_bytes.decode()
signature = urlencode({'Signature': sig_b64_str})
url = f'https://api.huobi.pro{endpoint}?'
url += params_url_enc + '&'
url += signature
return requests.get(url).json()
endpoint = "/v2/account/valuation"
extra_params = {
"accountType": "1",
"valuationCurrency": "BTC"
}
print(huobi(endpoint=endpoint, extra_params=extra_params))
This is my code to extract player data from an endpoint containing basketball data for a Data Science project.NOTE: I changed the name of the actual API key I was given since it's subscription. And I change the username/password because for privacy purposes. Using the correct credentials, I wouldn't receive a syntax error but the status code always returns 401. Since it wasn't accepting the API key, I added my account username, password, and the HTTP authentication header as well, but the status code still returns 401.
In case this is relevant, this is the website's recommendation in the developer portal: **The API key can be passed either as a query parameter or using the following HTTP request header.
Please let me know what changes I can make to my code. Any help is appreciated.
Ocp-Apim-Subscription-Key: {key}**
PS: My code got fragmented while posting this, but it is all in one function.
def getData():
user_name = "name#gmail.com"
api_endpoint = "https://api.sportsdata.io/v3/nba/stats/json/PlayerGameStatsByDate/2020-FEB7"
api_key = "a45;lkf"
password = "ksaljd"
header = "Ocp-Apim-Subscription-Key"
PARAMS = {'user': user_name, 'pass': password, 'header': header, 'key': api_key}
response = requests.get(url = api_endpoint, data = PARAMS)
print(response.status_code)
file = open("Data.csv", "w")
file.write(response.text)
file.close()
def _get_auth_headers() -> dict:
return {
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': "`Insert key here`"
}
api_endpoint = "https://api.sportsdata.io/v3/nba/stats/json/PlayerGameStatsByDate/2020-FEB7"
PARAMS = {
# Your params here
}
response = requests.get(
api_endpoint,
headers=_get_auth_headers(),
params=PARAMS
)
Instead of just a string, you need to pass dict in the headers parameter and auth param exist so you can use it as follow:
def getData():
[...]
header = {
"Ocp-Apim-Subscription-Key": api_key
}
[...]
response = requests.get(url = api_endpoint, data = PARAMS, headers=header, auth = (user_name, password))
According to the API documentation you don't need to provide email and password. You're only need to add your API Key to header:
import requests
r = requests.get(url='https://api.sportsdata.io/v3/nba/stats/json/PlayerGameStatsByDate/2020-FEB7', headers={'Ocp-Apim-Subscription-Key': 'API_KEY'})
print(r.json())
Output:
[{
'StatID': 768904,
'TeamID': 25,
'PlayerID': 20000788,
'SeasonType': 1,
'Season': 2020,
'Name': 'Tim Hardaway Jr.',
'Team': 'DAL',
'Position': 'SF',
'Started': 1,
'FanDuelSalary': 7183,
'DraftKingsSalary': 7623,
'FantasyDataSalary': 7623,
...
I am trying to update a value in REST API of openhab using requests.put in Python. But I am getting error 404.
My code is copied below
import requests
import json
from pprint import pprint
TemperatureA_FF_Office = 20
headers = {'Content-type': 'application/json'}
payload = {'state' : TemperatureA_FF_Office}
payld = json.dumps(payload)
re = requests.put("http://localhost:8080/rest/items/TemperatureA_FF_Office
/state/put", params= payld, headers = headers)
pprint(vars(re))
The error code I am getting is
{'_content': '',
'_content_consumed': True,
'connection': <requests.adapters.HTTPAdapter object at 7fd3b55ec9d0>,
'cookies': <<class 'requests.cookies.RequestsCookieJar'>[]>,
'elapsed': datetime.timedelta(0, 0, 4019),
'encoding': None,
'history': [],
'raw': <urllib3.response.HTTPResponse object at 0x7fd3b55ecd90>,
'reason': 'Not Found',
'request': <PreparedRequest [PUT]>,
'status_code': 404,
'url': u'http://localhost:8080/rest/items/TemperatureA_FF_Office/state/put?state=21.0'}
Is this the way to use requests.put? Please help.
Try something along these lines:
import requests
req = "http://localhost:8080/rest/items/YOUR_SENSOR_HERE/state"
val = VARIABLE_WITH_YOUR_SENSOR_DATA
try:
r = requests.put(req,data=val)
except requests.ConnectionError as e:
r = "Response Error"
print e
print r
This is a massively simplified version of what I'm using for some of my presence detection and temperature scripts.
The printing of 'r' and 'e' is useful for debug purposes and can be removed once you've got your script working properly.