Tinder API Authentication Token Retrieval - python-3.x

I'm working on implementing an AI bot that uses DiauogeFlow to have intelligent conversations with my matches. The link to the github package that contains all the scripts is here: https://github.com/nathan-149/tinderbot
I am at this point just trying to get the authentication token in order to hook up the bot, here is the code for the first script which is supposed to return the API token:
import json
import requests
CODE_REQUEST_URL = "https://api.gotinder.com/v2/auth/sms/send?auth_type=sms"
CODE_VALIDATE_URL = "https://api.gotinder.com/v2/auth/sms/validate?auth_type=sms"
TOKEN_URL = "https://api.gotinder.com/v2/auth/login/sms"
HEADERS = {'user-agent': 'Tinder/11.4.0 (iPhone; iOS 12.4.1; Scale/2.00)', 'content-type': 'application/json'}
def send_otp_code(phone_number):
data = {'phone_number': phone_number}
r = requests.post(CODE_REQUEST_URL, headers=HEADERS, data=json.dumps(data), verify=False)
print(r.url)
response = r.json()
if(response.get("data")['sms_sent'] == False):
return False
else:
return True
def get_refresh_token(otp_code, phone_number):
data = {'otp_code': otp_code, 'phone_number': phone_number}
r = requests.post(CODE_VALIDATE_URL, headers=HEADERS, data=json.dumps(data), verify=False)
print(r.url)
response = r.json()
if(response.get("data")["validated"] == False):
return False
else:
return response.get("data")["refresh_token"]
def get_api_token(refresh_token):
data = {'refresh_token': refresh_token }
r = requests.post(TOKEN_URL, headers=HEADERS, data=json.dumps(data), verify=False)
print(r.url)
response = r.json()
return response.get("data")["api_token"]
phone_number = input("Please enter your phone number under the international format (country code + number): ")
log_code = send_otp_code(phone_number)
otp_code = input("Please enter the code you've received by sms: ")
refresh_token = get_refresh_token(otp_code, phone_number)
print("Here is your Tinder token: " + str(get_api_token(refresh_token)))
Unfortunatley when I run the code and put in the access code from my phone I get the following error:
File "c:\Users\MIS-l\OneDrive\Desktop\tinderbot-master\phone_auth_token.py", line 44, in <module>
print("Here is your Tinder token: " + get_api_token(refresh_token))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "c:\Users\MIS-l\OneDrive\Desktop\tinderbot-master\phone_auth_token.py", line 37, in get_api_token
return response.get("data")["api_token"]
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
TypeError: 'NoneType' object is not subscriptable
I have tried accessing the API links at the top of the beginning of the script but I just get Error 404 for all of them.
What can I do to get the access token?
Thank you,
Vercetti

Related

bithumb Api error -{'status': '5100', 'message': 'Bad Request.(Auth Data)'}

I wanted to make a program where I can check the order details of my order at Bithumb Exchange.
So I looked at the docs(https://api.bithumb.com/info/orders) and made it, but the same error code kept coming out, so I don't know what to do.
import time
import math
import base64
import hmac, hashlib
import urllib.parse
import requests
class XCoinAPI:
api_url = "https://api.bithumb.com";
api_key = "";
api_secret = "";
def __init__(self, api_key, api_secret):
self.api_key = api_key;
self.api_secret = api_secret;
def body_callback(self, buf):
self.contents = buf;
def microtime(self, get_as_float = False):
if get_as_float:
return time.time()
else:
return '%f %d' % math.modf(time.time())
def usecTime(self) :
mt = self.microtime(False)
mt_array = mt.split(" ")[:2];
return mt_array[1] + mt_array[0][2:5];
def xcoinApiCall(self, endpoint, rgParams):
# 1. Api-Sign and Api-Nonce information generation.
# 2. Request related information from the Bithumb API server.
#
# - nonce: it is an arbitrary number that may only be used once.
# - api_sign: API signature information created in various combinations values.
endpoint_item_array = {
"endpoint" : endpoint
}
uri_array = dict(endpoint_item_array, **rgParams) # Concatenate the two arrays.
str_data = urllib.parse.urlencode(uri_array)
nonce = self.usecTime()
data = endpoint + chr(1) + str_data + chr(1) + nonce
utf8_data = data.encode('utf-8')
key = self.api_secret
utf8_key = key.encode('utf-8')
h = hmac.new(bytes(utf8_key), utf8_data, hashlib.sha512)
hex_output = h.hexdigest()
utf8_hex_output = hex_output.encode('utf-8')
api_sign = base64.b64encode(utf8_hex_output)
utf8_api_sign = api_sign.decode('utf-8')
headers = {
"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded",
"Api-Key": self.api_key,
"Api-Nonce": nonce,
"Api-Sign": utf8_api_sign
}
url = self.api_url + endpoint
r = requests.post(url, headers=headers, data=uri_array)
return r.json()
a = XCoinAPI(api_key="MYKEY1c", api_secret="MYKEY2")
aa= a.xcoinApiCall("/info/orders",{"order_currency":"LN","payment_currency":"BTC"})
print(aa)
{'status': '5100', 'message': 'Bad Request.(Auth Data)'}
Process finished with exit code 0
The error code 5100, bad request keeps coming up(https://apidocs.bithumb.com/docs/api-%EC%A3%BC%EC%9A%94-%EC%97%90%EB%9F%AC-%EC%BD%94%EB%93%9C)
I really don't know which code to modify.
I think it's a parameter problem with XcoinApiCall, but I don't know.

Can I use urlencode in python to insert a string of characters into this Spotify API request?

I am working with Spotify API to request song data through a URL. I imported urlencode to run the song's ID as a function parameter into the url. Essentially, I need the ID portion of the url request to be the ID by itself, not "id=<id string>"
I tried assigning the id string to a parameter of my 'search' function. The search function takes a user input song ID from spotify, inserts it into the proper position in the URL request, and sends it to the spotify database to retrieve that songs data analysis. The program successfully sends out the request, but the id portion I am filling in puts "id=<song ID>" instead of the song ID by itself.
import requests
import datetime
from urllib.parse import urlencode
# In[3]:
import base64
# In[4]:
client_id = 'fb5af83351d4402fa82904fc04f7fc9e'
client_secret = 'b5057eb39b024180b61b02eb45fb97a6'
# In[5]:
class SpotifyAPI(object):
access_token = None
access_token_expires = datetime.datetime.now()
access_token_did_expire = True
client_id = None
client_secret = None
token_url = "https://accounts.spotify.com/api/token"
def __init__(self, client_id, client_secret, *args, **kwargs):
super().__init__(*args, **kwargs)
self.client_id = client_id
self.client_secret = client_secret
def get_client_credentials(self):
client_id = self.client_id
client_secret = self.client_secret
if client_secret == None or client_id == None:
raise Exception("You must set client_id and client_secret")
client_creds = f"{client_id}:{client_secret}"
client_creds_b64 = base64.b64encode(client_creds.encode())
return client_creds_b64.decode()
def get_token_headers(self):
client_creds_b64 = self.get_client_credentials()
return {
"Authorization": f"Basic {client_creds_b64}"
}
def get_token_data(self):
return {
"grant_type": "client_credentials"
}
def perform_authorization(self):
token_url = self.token_url
token_data = self.get_token_data()
token_headers = self.get_token_headers()
r = requests.post(token_url, data=token_data, headers=token_headers)
print(r.json())
if r.status_code not in range(200,299):
raise Exception("Could not authenticate client")
#return False
data = r.json()
now = datetime.datetime.now()
access_token = data['access_token']
expires_in = data['expires_in'] #seconds
expires = now + datetime.timedelta(seconds=expires_in)
self.access_token = access_token
self.access_token_expires = expires
self.access_token_did_expire = expires < now
return True
def get_access_token(self):
token = self.access_token
expires = self.access_token_expires
now = datetime.datetime.now()
if expires < now:
self.perform_authorization()
return self.get_access_token()
elif token == None:
self.perform_authorization()
return self.get_access_token()
return token
def search(self, id):
access_token = self.get_access_token()
headers = {
"Authorization": f"Bearer {access_token}"
}
end_point = "https://api.spotify.com/v1/audio-analysis/"
data = urlencode({"id":id})
print(data)
lookup_url = f"{end_point}{data}"
print(lookup_url)
r = requests.get(lookup_url, headers = headers)
if r.status_code not in range(200, 299):
return r
return r.json()
it returns
{'access_token': 'BQCLoKT_b2PF7KPSbscosa1dCpE5rzd_RBkswOvwklVdlAL4AeEGCDn0iYuqac5o86BTqCIz0m95u3olLp4', 'token_type': 'Bearer', 'expires_in': 3600}
id=1UGD3lW3tDmgZfAVDh6w7r
https://api.spotify.com/v1/audio-analysis/id=1UGD3lW3tDmgZfAVDh6w7r

Authenticating to an API using Python3 with a consumer key and consumer secret

I'm trying to login to an API to retrieve an access token using a consumer secret and key. Following several threads on stackoverflow, I've gotten this far:
consumer = "<myconsumerkey>:<myconsumersecret>"
b64val = base64.b64encode(consumer.encode()).decode()
headers = {"Authorization": "Basic %s" % b64val, "Content-Type": 'application/x-www-form-urlencode'}
response = requests.post('https://mysite/token', headers=headers, verify=False)
This always throws a 415 error. I've read the requests api documentation so many times I'm going crazy where is my malfunction here?
I do not know why, but adding
data = {'grant_type': 'client_credentials'}
to the post worked. The code is:
def login():
consumer = consumer_key + ":" + consumer_secret
b64val = base64.b64encode(consumer.encode()).decode()
headers = {"Authorization": "Basic %s" % b64val}
data = {'grant_type': 'client_credentials'}
response = requests.post('https://mywebsite:8243/token', headers=headers, data=data)

how to add content_type explicitly for json and file in post request

I would like to add content type explicity for multipart form data before sending post request
Below is my sample code i managed to add conten type for file data but couldn't figure out how to add content type correctly for json data, i would like to add "application/json; charset=utf-8" for json data
import requests
import json
import traceback
def uploadLogs(fileName):
f = open(fileName, 'rb')
payload = { "var1":"this", "var2" : "that"
}
files = {'file': ('current', f, "text/plain; charset=us-ascii")}
data = {'info': json.dumps(payload)}
headers = {'type': 'myReport', "Keep-Alive": "timeout=100"}
try:
url = "http://localhost:8009/upload"
response = requests.post(url, data=data, files=files, headers=headers)
print(response.request.body)
print(response.request.headers)
print(response.status_code)
if (response != None and (response.status_code == 200 or
response.status_code == 201)):
return True
except:
traceback.print_exc()
return False
filename = "C:\\sample.txt"
print(uploadLogs(filename))
If someone knows how to do please suggest

python django Mock SAML Response from onelogin.saml.auth library using python3-saml

I have implemented for our django back-end application (SP) possibility to login via SAML, as IDP im using Keycloak. It works fine, but I want to write tests to be sure that all logic is being executed correctly. For this I want to generate a post request with SAML as body and mock (unittest.mock.patch) the real request. But i stuck.
Here is my django view, which accepts get and post requests when I try to login via SAML:
class SamlLoginView(View):
#staticmethod
def prepare_django_request(request):
if 'HTTP_X_FORWARDED_FOR' in request.META:
server_port = 443
else:
server_port = request.META.get('SERVER_PORT')
result = {
'https': 'on' if request.is_secure() else 'off',
'http_host': request.META['HTTP_HOST'],
'script_name': request.META['PATH_INFO'],
'server_port': server_port,
'get_data': request.GET.copy(),
'post_data': request.POST.copy(),
}
return result
#never_cache
def get(self, *args, **kwargs):
req = SamlLoginView.prepare_django_request(self.request)
auth = OneLogin_Saml2_Auth(req, settings.SAML_IDP_SETTINGS)
return_url = self.request.GET.get('next') or settings.LOGIN_REDIRECT_URL
return HttpResponseRedirect(auth.login(return_to=return_url))
#never_cache
def post(self, *args, **kwargs):
req = SamlLoginView.prepare_django_request(self.request)
print(req['post_data']['SAMLResponse'])
auth = OneLogin_Saml2_Auth(req, settings.SAML_IDP_SETTINGS)
auth.process_response()
errors = auth.get_errors()
if not errors:
if auth.is_authenticated():
logger.info("Login", extra={'action': 'login',
'userid': auth.get_nameid()})
user = authenticate(request=self.request,
saml_authentication=auth)
login(self.request, user)
return HttpResponseRedirect("/")
else:
raise PermissionDenied()
else:
return HttpResponseBadRequest("Error when processing SAML Response: %s" % (', '.join(errors)))
In my tests, I wanted to directly call the post method, in which there will be a saml inside:
class TestSamlLogin(TestCase):
def test_saml_auth(self, prepare):
client = APIClient()
url = reverse_lazy("miri_auth:samllogin")
saml_resp='<xml with saml response>'
resp = client.post(url, data=saml_resp)
but obviously it shows that request.POST is empty.
I then decided to make a mock for the prepare_django_request function, and manually insert the saml:
def mocked_prepare_request(request):
post_query_dict = QueryDict(mutable=True)
post_data = {
'SAMLResponse': saml_xml,
'RelayState': '/accounts/profile/'
}
post_query_dict.update(post_data)
result = {
'https': 'on',
'http_host': '<http-host>',
'script_name': '/api/auth/samllogin/',
'server_port': '443',
'get_data': {},
'post_data': post_query_dict,
}
return result
class TestSamlLogin(TestCase):
#patch('miri_auth.views.SamlLoginView.prepare_django_request', side_effect=mocked_prepare_request)
def test_saml_auth(self, prepare):
client = APIClient()
url = reverse_lazy("miri_auth:samllogin")
saml_resp='<xml with saml response>'
resp = client.post(url, data=saml_resp)
and depending on how I pass the saml_xml it throws different errors, if i define it as string:
with open(os.path.join(TEST_FILES_PATH, 'saml.xml')) as f:
saml_xml = " ".join([x.strip() for x in f])
it returns: lxml.etree.XMLSyntaxError: Start tag expected, '<' not found, line 1, column 1, although I checked the output from saml_xml in the xml validator and it says that the xml is valid.
When i try to parse the file into xml in advance, i get another error later,
libraries with which I tried to parse:
import xml.etree.ElementTree as ET
from xml.dom import minidom
from lxml import etree
tree = etree.parse(os.path.join(TEST_FILES_PATH, 'saml.xml'))
it returns:
TypeError: argument should be a bytes-like object or ASCII string, not '_ElementTree'
Debugging these errors didn't lead me to any solution.
If anyone has any thoughts on how this can be implemented (Mocking response with SAML), or where I made a mistake, I would be glad to hear.
Thank in advance
I realized that the SAML Response must be encoded:
with open(os.path.join(TEST_FILES_PATH, 'saml.xml')) as f:
saml_xml = " ".join([x.strip() for x in f])
base64_saml = base64.b64encode(saml_xml.encode('ascii')).decode('ascii')
post_data = {'SAMLResponse': base64_saml, 'RelayState': '/accounts/profile/'}
url = reverse_lazy("miri_auth:samllogin")
request = self.client.post(url, post_data)
but now i am getting the following errors:
func=xmlSecOpenSSLEvpDigestVerify:file=digests.c:line=280:obj=sha256:subj=unknown:error=12:invalid data:data and digest do not match

Resources