I understand that it used to be possible to join the discord server using a token via python requests, but judging by the video I found, this method no longer works...Is there anything else on this topic?
The code I made using a YouTube video
import requests
token_list = ["12345", "1233456", etc.]
def join(server_invite):
while True:
for item in range(len(token_list)):
header = {
"authorization": token_list[item]
}
r = requests.post("https://discord.com/api/v9/invites/{}".format(server_invite), headers=header)
if __name__ == '__main__':
join("Server invite code")
I'm trying to get data about a stream via the twitch api, the first request for the oauth2 token works perfectly, but then as soon as I make the first request I get this error 401 Client Error: Unauthorized for url: https://api.twitch.tv/helix/users?login=im_marcotv&. What I understand is that there is an error in my token submission, but I don't understand what I did wrong, this is the complete code:
import requests
import os
import json
from dotenv import load_dotenv
load_dotenv()
CLIENTID = os.getenv("CLIENTID")
CLIENTSID = os.getenv("CLIENTSID")
sCLIENTID = str(CLIENTID)
sCLIENTSID = str(CLIENTSID)
if __name__ == "__main__":
print("print1")
request_token_url = f'https://id.twitch.tv/oauth2/token?
client_id=&client_secret=&grant_type=client_credentials'
response = requests.post(request_token_url)
response.raise_for_status()
print(response.json())
token = json.loads(response.text)["access_token"]
print(f"Token: {token}")
header = {"Client-ID": "", f"Authorization": "Bearer {token}"}
response = requests.get("https://api.twitch.tv/helix/users?login=im_marcotv&", headers=header)
response.raise_for_status() #line that raise the error
print(response.json())
data = json.loads(response.text)["data"]
if data:
streamer = data[0]
user_name = streamer["user_name"]
game_name = streamer["game_name"]
viewer_count = streamer["viewer_count"]
output = f"{user_name} is online on {game_name} con {viewer_count} visualizzazioni"
print(output)
else:
#print(f"{name} is offline")
pass
The line getting the token was also giving the same error, but I fixed it by stopping using variables to hold the client id and secret id. In all the places where there should be the ids I removed them, but in the actual code they are present and correct
I'm currently trying to write a Python script that will use Deviantart's API to automatically shuffle my favourites. To do that I need to first log in in my script. Deviantart uses OAuth2 authentication, which requires a redirect_uri, which as I understand it is supposed to be the server where my application is running.
However I'm running the script locally on my computer (not on a server) and just sending http requests via Python's Requests library. How do I then authenticate, when the OAuth procedure sends the code required for the authentication token as a parameter of a GET call to the redirect_uri, which points to nowhere in particular for me? Is there no way to authenticate without running a server?
EDIT
My problem is still that I'm running a simple offline script, and I'm not sure how to authenticate from it.
This is my authentication code so far:
import binascii, os, requests
def auth():
request = 'https://www.deviantart.com/oauth2/authorize'
state = binascii.hexlify(os.urandom(160))
params = {
'response_type': 'token',
'client_id': 1,
'redirect_uri': 'https://localhost:8080',
'state': state,
'scope': 'user'
}
r = requests.get(request, params)
print(r)
The printed response is simply a 200 HTTP code, rather than an access token (obviously, since the username and password haven't been entered anywhere). The request is sent to DA's authorisation page, but since the page itself doesn't actually open in my script, I can't enter my username and password to log in anywhere. And I can't directly send the username and password in the GET request to authenticate that way either (again obviously, since it would be a terrible idea to send the password like that).
Preferably I'd like a way to simply have the user (me) prompted for the username and password in the console that the script is running in and then have the script continue executing after the user has successfully logged in.
Alternatively, if the above is not possible, the script should open the authorisation webpage in a browser, and then continue execution once the user logs in.
How would I go about realising either of these two solutions in Python?
If your application is offline, you cannot use the Authorization Code nor the Implicit grant type: both flows require a redirection URI.
As your python script cannot be reached from the Internet and because Deviantart does not allow the use of another grant type (except Client Credentials, but not relevant in you case), then you won't be able to issue any access token.
Your application must be accessible from the Internet.
You are supposed to get authorization token using received code. This token will be used to access DeviantArt afterwards.
Refer to https://www.deviantart.com/developers/authentication (section "Using The Authorization Code Grant").
Per request, I'm updating this question with the code I ended up using for my script's authentication in the hope that it helps somebody.
import webbrowser
import requests
import urllib.parse
import binascii
import os
import time
from http.server import HTTPServer, BaseHTTPRequestHandler
AUTH = 'https://www.deviantart.com/oauth2/authorize'
TOKEN = 'https://www.deviantart.com/oauth2/token'
code = ''
state = binascii.hexlify(os.urandom(20)).decode('utf-8')
class Communicator:
def __init__(self):
self.client_id = '<insert-actual-id>' # You get these two from the DA developer API page
self.client_secret = '<insert-actual-secret>' # but it's safer if you store them in a separate file
self.server, self.port = 'localhost', 8080
self._redirect_uri = f'http://{self.server}:{self.port}'
self._last_request_time = 0
def auth(self, *args):
scope = ' '.join(args)
params = {
'response_type': 'code',
'client_id': self.client_id,
'redirect_uri': self._redirect_uri,
'scope': scope,
'state': state
}
request = requests.Request('GET', AUTH, params).prepare()
request.prepare_url(AUTH, params)
webbrowser.open(request.url)
server = HTTPServer((self.server, self.port), RequestHandler)
server.handle_request()
params = {
'client_id': self.client_id,
'client_secret': self.client_secret,
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': self._redirect_uri
}
self._get_token(params)
def _get_token(self, params):
r = requests.get(TOKEN, params).json()
self.token = r['access_token']
self.refresh_token = r['refresh_token']
def _refresh_token(self):
params = {
'client_id': self.client_id,
'client_secret': self.client_secret,
'grant_type': 'refresh_token',
'refresh_token': self.refresh_token
}
self._get_token(params)
def _request(self, func, url, params, sleep=5, cooldown=600):
t = time.time()
if t - self._last_request_time < sleep:
time.sleep(sleep - t + self._last_request_time)
self._last_request_time = t
max_sleep = 16 * sleep
params['access_token'] = self.token
while True:
try:
r = func(url, params).json()
if 'error_code' in r and r['error_code'] == 429:
sleep *= 2
time.sleep(sleep)
if sleep > max_sleep:
raise ConnectionError("Request timed out - server is busy.")
elif 'error' in r and r['error'] == 'user_api_threshold':
raise ConnectionError("Too many requests")
elif 'error' in r and r['error'] == 'invalid_token':
print("Refreshing token.")
self._refresh_token()
params['access_token'] = self.token
else:
return r
except ConnectionError:
print(f"Request limit reached - waiting {cooldown // 60} minutes before retrying...")
time.sleep(cooldown)
def get(self, url, params):
return self._request(requests.get, url, params)
def post(self, url, params):
return self._request(requests.post, url, params)
class RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
global code
self.close_connection = True
query = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query)
if not query['state'] or query['state'][0] != state:
raise RuntimeError("state argument missing or invalid")
code = query['code']
BROWSE = 'browse'
BROWSE_MORE_LIKE_THIS = 'browse.mlt'
COLLECTION = 'collection'
COMMENT = 'comment.post'
FEED = 'feed'
GALLERY = 'gallery'
MESSAGE = 'message'
NOTE = 'note'
PUBLISH = 'publish'
STASH = 'stash'
USER = 'user'
USER_MANAGE = 'user.manage'
if __name__ == '__main__':
com = Communicator()
com.auth(BROWSE, COLLECTION) # request specific permissions
... # do stuff with com.get() and com.post() requests
I'm trying to make a post request to Quizlet following their OAuth flow from these instructions https://quizlet.com/api/2.0/docs/authorization-code-flow. I'm running into a problem where on Step 2, I have to make a post request with a token I generated from their server, but I'm not having success passing in the token to the url. I know it was generated correctly, but I'm having trouble passing it in and not getting a 400 response.
More directly, my question is, is there another way of including the grant_type and code parameters that I'm trying to pass in through the url in the post request such as passing them in through the header of the post request? I've looked at the documentation for requests but I've had no luck.
#app.route('/')
#app.route('/index')
def index():
code = request.args.get('code')
state = request.args.get('state')
print("code is " + code)
r = requests.post("https://api.quizlet.com/oauth/token?grant_type=authorization_code&code=" + code)
return render_template('index.html')
You must specify the required headers Authorization, Content-Type.
import requests
from requests.auth import _basic_auth_str
client_id = 'YOUR CLIENT ID'
secret = 'YOUR CLIENT SECRET'
code = 'CODE FROM STEP 1'
headers = {
'Authorization': _basic_auth_str(client_id, secret),
'Content-Type': 'application/x-www-form-urlencoded'
}
r = requests.post('https://api.quizlet.com/oauth/token?grant_type=authorization_code&code={0}'.format(
code), headers=headers)
print r.status_code
print r.content
I am trying to create generic class in python which will do all the oAuth process and then will allow to retrieve data from any oAuth supporting service (for example Twitter,LinkedIn).
Edited:
I have customer key and secret and access token key and secret,when I try to request any resource request I get the following error:
{"error":"Could not authenticate with OAuth.","request":"\/1\/statuses\/retweeted_by_me.json}'
any idea why?
My Code is:
import httplib
import time
import oauth as oauth
# settings for the local test consumer
SERVER = 'api.twitter.com'
RESOURCE_URL = 'https://api.twitter.com/1/statuses/retweeted_by_me.json'
CONSUMER_KEY = 'MY_CUSTOMER_KEY'
CONSUMER_SECRET = 'MY_CUSTOMER_SECRET'
ACCESS_TOKEN_KEY = 'MY_ACCESS_TOKEN_KEY'
ACCESS_TOKEN_SECRET = 'MY_ACCESS_TOKEN_SECRET'
# example client using httplib with headers
class SimpleOAuthClient(oauth.OAuthClient):
def __init__(self, server):
self.server = server
self.connection = httplib.HTTPSConnection(self.server)
def access_resource(self, oauth_request):
# via post body
# -> some protected resources
self.connection.request(oauth_request.http_method, RESOURCE_URL)
response = self.connection.getresponse()
return response.read()
def run_example2():
print '** OAuth Python Library Example **'
client = SimpleOAuthClient(SERVER, )
consumer = oauth.OAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET)
signature_method_hmac_sha1 = oauth.OAuthSignatureMethod_HMAC_SHA1()
pause()
# access some protected resources
print '* Access protected resources ...'
pause()
token = oauth.OAuthToken('ACCESS_TOKEN_KEY', 'ACCESS_TOKEN_SECRET')
oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, token=token, http_method='GET', http_url=RESOURCE_URL)
oauth_request.sign_request(signature_method_hmac_sha1, consumer, token)
print 'REQUEST (via post body)'
print 'parameters: %s' % str(oauth_request.parameters)
pause()
params = client.access_resource(oauth_request)
print 'GOT'
print 'non-oauth parameters: %s' % params
pause()
def pause():
print ''
time.sleep(1)
if __name__ == '__main__':
run_example2()
print 'Done.'
AUTHORIZATION_URL = 'https://api.twitter.com/oauth/authenticate'
This is the incorrect URL to use for OAuth. If you look at Twitter's 3-legged OAuth documentation, they state "The GET oauth/authorize endpoint is used instead of /oauth/authenticate". Change the URL to "https://api.twitter.com/oauth/authorize" and try again.
I managed to fix it by changing self.connection.request(oauth_request.http_method, RESOURCE_URL)
to self.connection.request(oauth_request.http_method, oauth_request.to_url())
Notice that will will work only if oauth_request.http_method is GET