from rauth import OAuth2Service
import json
class ExampleOAuth2Client:
def __init__(self, client_id, client_secret):
self.access_token = None
self.service = OAuth2Service(
name="secret",
client_id="secret",
client_secret="secret",
access_token_url="https://id.twitch.tv/oauth2/authorize",
authorize_url="https://id.twitch.tv/oauth2/authorize",
base_url="https://id.twitch.tv/",
response_type="token",
scope="channel%3Amanage%3Apolls+channel%3Aread%3Apolls",
state="secret"
)
self.get_access_token()
def get_access_token(self):
data = {'code': 'bar',
'grant_type': 'client_credentials',
'redirect_uri': 'http://localhost'}
session = self.service.get_auth_session(data=data, decoder=json.loads)
self.access_token = session.access_token
k = ExampleOAuth2Client
print(k.get_access_token())
The code is originally not mine so I don't know exactly how it works. When I run this it says I need to add positional argument 'self'
You need to initialize the ExampleOAuth2Client object properly.
Instead of this:
k = ExampleOAuth2Client
It should look something like:
k = ExampleOAuth2Client('your-client-id', 'your-client-secret')
Related
I am attempting to use the Woo exchange trading api. They provided a snippet of code which is an impressive Python class structure. Copied below.
My question is how can I use it?
I have tried to run:
get_orders(self, 'BTCUSDT')
which throws an error "NameError: name 'self' is not defined"
and
get_orders('BTCUSDT')
which throws "TypeError: get_orders() missing 1 required positional argument: 'symbol'"
Here is the code (class structure) the kind woo guys provided:
import requests
import datetime
import time
import hmac
import hashlib
from collections import OrderedDict
#Application ID 9d4d96f6-3d3b-4430-966d-8733aa3dc3bc
#API Key
api_key = 'my_api_key'
#API Secret
api_secret = 'my_api_secret'
class Client():
def __init__(self, api_key=None, api_secret=None):
self.api_key = api_key
self.api_secret = api_secret
self.base_api = "https://api.woo.network/v1/"
def get_signature(self, params, timestamp):
query_string = '&'.join(["{}={}".format(k, v) for k, v in params.items()]) + f"|{timestamp}"
signature = hmac.new(
self.api_secret.encode('utf-8'),
query_string.encode('utf-8'),
hashlib.sha256
).hexdigest()
return signature
def get_orders(self, symbol):
url = self.base_api + "orders/"
params = {
"symbol": 'BTCUSDT'
}
params = OrderedDict(sorted(params.items()))
timestamp = str(int(time.time() * 1000))
signature = self.get_signature(params, timestamp)
headers = {
'Content-Type': "application/x-www-form-urlencoded",
'x-api-key': self.api_key,
'x-api-signature': signature,
'x-api-timestamp': timestamp,
'cache-control': 'no-cache'
}
resp = requests.get(url=url, params=params, headers=headers).json()
So, to repeat and summarize, when I write my own code to use this class, how can I call the function get_orders() and, more generally, reference the elements in the class structure? Thanks, in advance, for help.
Looks like you've truncated the code because get_orders doesn't appear to return anything.
However, you would start by constructing an instance of Client like this:
client = Client(api_key, api_secret)
...then...
client.get_orders(None)
That may look a little strange but get_orders requires one parameter but it's never used. I don't think the implementation of get_orders is quite how it was intended to be because it will always use BTCUSDT
I'm trying to figure out how to mock my request for a bearer token in python.
I have a class:
class grab_apitokens(object):
def __init__(self, consumer_key, first_api_url, second_api_user, second_api_password, second_api_url):
self.consumer_key = consumer_key
self.second_api_user = second_api_user
self.second_api_password = second_api_password
self.first_api_url = first_api_url
self.second_api_url = second_api_url
def logintofirstsite(self):
b64val = base64.b64encode(self.consumer_key.encode()).decode()
headers = {"Authorization": "Basic %s" % b64val}
data = {'grant_type': 'client_credentials', 'validity_period': '3600'}
try:
response = requests.post(self.first_api_url, headers=headers, data=data)
decodedresponse = json.loads(response.content.decode())
access_token = decodedresponse['access_token']
return access_token
except:
return None
def logintosecondsite(self):
header = {"accept": "application/json", "Content-Type": "application/x-www-form-urlencoded"}
logindata = {'grant_type': 'password',
'username': "" + self.second_api_user + "", 'password': "" + self.second_api_password + ""
}
try:
returnedfromsite = requests.post(self.second_api_url + '/api/V1/token',
headers=header, data=logindata)
return returnedfromsite.json()['access_token']
except:
return None
What I can't figure out is how to mock that requests call and what it would look like in Python.
My test currently looks like:
class MyTestCase(unittest.TestCase):
def setUp(self) -> None: # PROBLEM BEGINS HERE
self.grab_apitokens = grab_apitokens(actual_key, actual_site1, actual_user, actual_pass, actual_2nd_site)
#patch('grab_apitokens.requests.get')
def test_login(self, mock_get):
mock_get.return_value.ok = True
response = self.grab_apitokens.logintosite()
assert_is_not_none(response)
# self.assertEqual(True, False)
if __name__ == '__main__':
unittest.main()
How would I mock the requests.post functionality?
With the help of a good mentor I figured out that my approach was all wrong. Here's what I ended up with for the unit test:
class MyTestCase(unittest.TestCase):
def setUp(self) -> None:
self.grab_apitokens = grab_apitokens("complete","gibberish","it really doesnt","matter","what is","in","here")
#patch('grab_apitokens.requests.posts')
def test_login(self, mock_get):
mock_json = {'token': 'foo'}
mock_get.return_value = Mock(ok=True)
mock_get.return_value.json.return_value = mock_json
mock_get.return_value.content = b'{"token": "foo"}'
response = self.grab_apitokens.logintofirstsite()
assert_equal(response, "foo")
if __name__ == '__main_
To understand what this does, I needed to know that what we're really mocking isn't the method logintofirstsite(), we're mocking the response that requests.post is making in the method. With mock_get, we're inject requests.posts to always be: {'token': 'foo'} . So everything after
response = requests.post(self.first_api_url, headers=headers, data=data)
in logintofirstsite() is what I'm really testing. Which is:
decodedresponse = json.loads(response.content.decode())
access_token = decodedresponse['token']
return access_token
The setup before the requests.post call doesn't matter one bit. Since with {'token': 'foo'} is what my requests.post call returns, the returned value after that bit of logic is 'foo', and so the assert_equal back in MyTestCase passes.
I'm trying to send a request to the binance servers which require an api-key and a signature but the console is saying that the timestamp is outside of the revcWindow
I've looked up the problem and found that I need sync my computer's time to the Binance's. I'm not quite sure how to do that though (pretty newbie in Python)
def test(self):
self.url += self.url_list['test']
params = {'symbol': 'BTCETH', "timestamp": 0, "side": "BUY", "type": "LIMIT", "quantity": 0.0005, "recvWindow": 500 }
data = parammanger.encode_params(params)
data += "&signature=" + self.hash(data)
headers = {'X-MBX-APIKEY': self.a_key}
print(data)
r_body = {'signature': self.hash(data)}
r = requests.post(self.url, data, headers=headers)
print(r.request.headers)
print(r.json())
def hash(self, data):
return hashmanager.create_hash(self.s_key.encode("utf-8"), data.encode("utf-8"))
{'code': -1021, 'msg': 'Timestamp for this request is outside of the recvWindow.'}
The syncing has to do more with you SO that with Python.
Those guys here: have some solutions enter link description here
This one seems to be bulletproof (so far)
import time
from binance.client import Client
class Binance:
def __init__(self, public_key = '', secret_key = '', sync = False):
self.time_offset = 0
self.b = Client(public_key, secret_key)
if sync:
self.time_offset = self._get_time_offset()
def _get_time_offset(self):
res = self.b.get_server_time()
return res['serverTime'] - int(time.time() * 1000)
def synced(self, fn_name, **args):
args['timestamp'] = int(time.time() - self.time_offset)
return getattr(self.b, fn_name)(**args)
#I then instantiate it and call my private account functions with synced
binance = Binance(public_key = 'my_pub_key', secret_key = 'my_secret_key', sync=True)
binance.synced('order_market_buy', symbol='BNBBTC', quantity=10)
Edit:
I found an easier solution here, and the other one does not seems to be so bulletproof: enter link description here
from binance.client import Client
client = Client('api_key', 'api_secret')
import time
import win32api
gt = client.get_server_time()
tt=time.gmtime(int((gt["serverTime"])/1000))
win32api.SetSystemTime(tt[0],tt[1],0,tt[2],tt[3],tt[4],tt[5],0)
I'm trying the following code:
import requests
auth_params = {'consumer_key': '77081-4664470ecdeaa9c127925c30', 'redirect_uri': 'https://weibo.com/u/5069317986/home?topnav=1&wvr=6'}
tkn = requests.post('https://getpocket.com/v3/oauth/request', data = auth_params)
tkn.content
usr_params = {'consumer_key': '77081-4664470ecdeaa9c127925c30', 'code': '21ff0ee0-2b65-fe35-f4b3-a18ed3'}
usr = requests.post('https://getpocket.com/v3/oauth/authorize', data = usr_params)
usr.content
And then:
yes_params = {'consumer_key': '77081-4664470ecdeaa9c127925c30', 'access_token': 'f12deb4e-8ead-9f98-430c-baaee7&username=jelly.wxt%40gmail.com', 'tag':'y'}
yes_result = requests.post('https://getpocket.com/v3/get', data = yes_params)
yes_result.text
But it returns a 401.How can I fix that?
HTTP 401 status typically means that the authentication failed.
Looking at the examples in pocket api documentation, it seems that you should not include &username=jelly.wxt%40gmail.com in the access token.
yes_params = {
'consumer_key': '77081-4664470ecdeaa9c127925c30',
'access_token': 'f12deb4e-8ead-9f98-430c-baaee7',
'tag':'y'
}
yes_result = requests.post('https://getpocket.com/v3/get', data = yes_params)
yes_result.text
I am trying to get the list of all calendars for a user. This user has delegate permissions to view the calendar of all the meeting rooms (resources). If I log into the user's account and I am able to see the meeting room calendars in the "Other Calendars" section. I also created my own calendar called "Test" in the "Other Calendars" section.
When I get all the calendar groups first and then iterate through the calendar group list and get the calendars, the list for "Other Calendars" only has "Test" calendar.
Not sure why this is the case. The user is a global administrator as well.
def get_access_info_from_authcode(auth_code, redirect_uri):
post_data = { 'grant_type': 'authorization_code',
'code': auth_code,
'redirect_uri': redirect_uri,
'scope': ' '.join(str(i) for i in scopes),
'client_id': client_registration.client_id(),
'client_secret': client_registration.client_secret()
}
r = requests.post(access_token_url, data = post_data, verify = verifySSL)
try:
return r.json()
except:
return 'Error retrieving token: {0} - {1}'.format(r.status_code, r.text)
def get_access_token_from_refresh_token(refresh_token, resource_id):
post_data = { 'grant_type' : 'refresh_token',
'client_id' : client_registration.client_id(),
'client_secret' : client_registration.client_secret(),
'refresh_token' : refresh_token,
'resource' : resource_id }
r = requests.post(access_token_url, data = post_data, verify = verifySSL)
# Return the token as a JSON object
return r.json()
def get_calendars_from_calendar_groups(calendar_endpoint, token, calendar_groups):
results = []
for group_id in calendar_groups:
get_calendars = '{0}/me/calendargroups/{1}/calendars'.format(calendar_endpoint, group_id)
r = make_api_call('GET', get_calendars, token)
if (r.status_code == requests.codes.unauthorized):
logger.debug('Response Headers: {0}'.format(r.headers))
logger.debug('Response: {0}'.format(r.json()))
results.append(None)
results.append(r.json())
return results
def get_calendars(calendar_endpoint, token, parameters=None):
if (not parameters is None):
logger.debug(' parameters: {0}'.format(parameters))
get_calendars = '{0}/me/calendars'.format(calendar_endpoint)
if (not parameters is None):
get_calendars = '{0}{1}'.format(get_calendars, parameters)
r = make_api_call('GET', get_calendars, token)
if(r.status_code == requests.codes.unauthorized):
logger.debug('Unauthorized request. Leaving get_calendars.')
return None
return r.json()
Logic + Code:
Step 1) Get the authorization URL:
authority = "https://login.microsoftonline.com/common"
authorize_url = '{0}{1}'.format(authority, '/oauth2/authorize?client_id={0}&redirect_uri={1}&response_type=code&state={2}&prompt=consent')
Step 2) Opening the URL takes us to https://login.microsoftonline.com/common where I login as the user:
Step 3) This redirects back to my localhost then the following:
discovery_result = exchoauth.get_access_info_from_authcode(auth_code, Office365.redirect_uri)
refresh_token = discovery_result['refresh_token']
client_id = client_registration.client_id()
client_secret = client_registration.client_secret()
access_token_json = exchoauth.get_access_token_from_refresh_token(refresh_token, Office365.resource_id)
access_token = access_token_json['access_token']
calendar_groups_json = exchoauth.get_calendar_groups(Office365.api_endpoint, access_token)
cal_groups = {}
if calendar_groups_json is not None:
for entry in calendar_groups_json['value']:
cal_group_id = entry['Id']
cal_group_name = entry['Name']
cal_groups[cal_group_id] = cal_group_name
calendars_json_list = exchoauth.get_calendars_from_calendar_groups(Office365.api_endpoint,
access_token, cal_groups)
for calendars_json in calendars_json_list:
if calendars_json is not None:
for ent in calendars_json['value']:
cal_id = ent['Id']
cal_name = ent['Name']
calendar_ids[cal_id] = cal_name
Let me know if you need any other information
The delegate-token which request with the Auth code grant flow only able to get the calendars of sign-in user.
If you want to the get the events from the specific room, you can use the app-only token request with client credential flow.
Here is an helpful link for your reference.