From f702b85a86ff9f3a0b35641dee712f400465f576 Mon Sep 17 00:00:00 2001 From: Nathan Date: Fri, 11 Mar 2022 14:42:02 -0500 Subject: [PATCH 1/9] moving helper functions to pyracing class --- pyracing/client.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/pyracing/client.py b/pyracing/client.py index e9e0a26..caf3b2e 100644 --- a/pyracing/client.py +++ b/pyracing/client.py @@ -946,6 +946,68 @@ async def league_seasons(self, league_id): url = ct.URL_LEAGUE_SEASONS response = await self._build_request(url, payload) + + + async def getCompletedSessionInfo(self, sessID): + payload = { + 'subsessionID': sessID, + } + mSite = 'https://members.iracing.com/membersite/member' + url = (mSite + '/GetSubsessionResults') + web_fb = await self.ir._build_request(url, payload) + print(web_fb) + return session_data.SubSessionData(web_fb.json()) + + + async def getCalendarBySeason(self, seasonID, leagueID): + payload = { + 'leagueID': leagueID, + 'leagueSeasonID': seasonID, + } + mSite = 'https://members.iracing.com/membersite/member' + url = (mSite + '/GetLeagueCalendarBySeason') + web_fb = await self.ir._build_request(url, payload) + return web_fb.json()["rows"] + + + + + async def getActiveSessions(self, leagueID): + payload = { + 'ts': 0, + 'leagueID': leagueID, + 'startRow':1, + 'stopRow': 20 + } + mSite = 'https://members.iracing.com/membersite/member' + url = (mSite + '/GetLeagueSessions') + web_fb = await self.ir._build_request(url, payload) + return web_fb.json()["rows"] + + async def get_league_seasons(self, leagueID): + payload = { + 'leagueID': leagueID, + 'getInactiveSeasons':1 + } + mSite = 'https://members.iracing.com/membersite/member' + url = (mSite + '/GetLeagueSeasons') + web_fb = await self.ir._build_request(url, payload) + return [league_data.LeagueSeason(x) for x in web_fb.json()['d']['r']] + + async def get_league_members(self, leagueID): + payload = { + 'leagueid': leagueID, + 'lowerBound': 100, + 'upperBound': 100 + } + mSite = 'https://members.iracing.com/membersite/member' + URL_LEAGUE_MEMBERS = (mSite + '/GetLeagueMembers') + url = URL_LEAGUE_MEMBERS + membersWeb = await self.ir._build_request(url, payload) + return membersWeb.json() + + + if response.json(): mapping = response.json().get('m') From fb1d37e4e7d7e04f5b810b1c18d029ccd97cb88e Mon Sep 17 00:00:00 2001 From: Nathan Date: Fri, 11 Mar 2022 16:30:40 -0500 Subject: [PATCH 2/9] fixed errors form moving functions to the pyracing class --- pyracing/client.py | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/pyracing/client.py b/pyracing/client.py index caf3b2e..049fb14 100644 --- a/pyracing/client.py +++ b/pyracing/client.py @@ -940,13 +940,6 @@ async def league_standings(self, league_id, league_season_id): return league_data.SeasonStandings(response.json()) - async def league_seasons(self, league_id): - """Get the season for a league""" - payload = {'leagueID': league_id} - - url = ct.URL_LEAGUE_SEASONS - response = await self._build_request(url, payload) - async def getCompletedSessionInfo(self, sessID): payload = { @@ -958,15 +951,14 @@ async def getCompletedSessionInfo(self, sessID): print(web_fb) return session_data.SubSessionData(web_fb.json()) - - async def getCalendarBySeason(self, seasonID, leagueID): + async def getCalendarBySeason(self, seasonID, leagueID): payload = { 'leagueID': leagueID, 'leagueSeasonID': seasonID, } mSite = 'https://members.iracing.com/membersite/member' url = (mSite + '/GetLeagueCalendarBySeason') - web_fb = await self.ir._build_request(url, payload) + web_fb = await self._build_request(url, payload) return web_fb.json()["rows"] @@ -981,20 +973,11 @@ async def getActiveSessions(self, leagueID): } mSite = 'https://members.iracing.com/membersite/member' url = (mSite + '/GetLeagueSessions') - web_fb = await self.ir._build_request(url, payload) + web_fb = await self._build_request(url, payload) return web_fb.json()["rows"] - async def get_league_seasons(self, leagueID): - payload = { - 'leagueID': leagueID, - 'getInactiveSeasons':1 - } - mSite = 'https://members.iracing.com/membersite/member' - url = (mSite + '/GetLeagueSeasons') - web_fb = await self.ir._build_request(url, payload) - return [league_data.LeagueSeason(x) for x in web_fb.json()['d']['r']] - async def get_league_members(self, leagueID): + async def get_league_members(self, leagueID): payload = { 'leagueid': leagueID, 'lowerBound': 100, @@ -1003,12 +986,19 @@ async def get_league_members(self, leagueID): mSite = 'https://members.iracing.com/membersite/member' URL_LEAGUE_MEMBERS = (mSite + '/GetLeagueMembers') url = URL_LEAGUE_MEMBERS - membersWeb = await self.ir._build_request(url, payload) + membersWeb = await self._build_request(url, payload) return membersWeb.json() + async def league_seasons(self, league_id): + """Get the season for a league""" + payload = {'leagueID': league_id, + 'getInactiveSeasons':1 + } + + url = ct.URL_LEAGUE_SEASONS + response = await self._build_request(url, payload) - if response.json(): mapping = response.json().get('m') response_data = response.json().get('d') From e97db34ef14794dfcbca519e8476c47174e46293 Mon Sep 17 00:00:00 2001 From: Nathan Date: Tue, 29 Mar 2022 21:51:09 -0400 Subject: [PATCH 3/9] fixed the client indicies cannot be integers error... --- pyracing/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyracing/client.py b/pyracing/client.py index 049fb14..6fa3983 100644 --- a/pyracing/client.py +++ b/pyracing/client.py @@ -959,8 +959,8 @@ async def getCalendarBySeason(self, seasonID, leagueID): mSite = 'https://members.iracing.com/membersite/member' url = (mSite + '/GetLeagueCalendarBySeason') web_fb = await self._build_request(url, payload) - return web_fb.json()["rows"] - + #return web_fb.json()["rows"] + return web_fb.json() From 9440773acf3d4e90f744cc7ac5a84ab7d4b0b3db Mon Sep 17 00:00:00 2001 From: Nathan Date: Tue, 5 Apr 2022 10:07:00 -0400 Subject: [PATCH 4/9] added some error checking for empty rows in get season helper func --- pyracing/client.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyracing/client.py b/pyracing/client.py index 6fa3983..326a323 100644 --- a/pyracing/client.py +++ b/pyracing/client.py @@ -959,8 +959,10 @@ async def getCalendarBySeason(self, seasonID, leagueID): mSite = 'https://members.iracing.com/membersite/member' url = (mSite + '/GetLeagueCalendarBySeason') web_fb = await self._build_request(url, payload) - #return web_fb.json()["rows"] - return web_fb.json() + try: + return web_fb.json()["rows"] + except: + return web_fb.json() From 0e7f80bd323f1f30d6e378e5f74c3b68ac612b48 Mon Sep 17 00:00:00 2001 From: Nathan Date: Tue, 12 Apr 2022 21:29:31 -0400 Subject: [PATCH 5/9] fixed the client reference to the ir object which was not working --- pyracing/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyracing/client.py b/pyracing/client.py index 326a323..78d7238 100644 --- a/pyracing/client.py +++ b/pyracing/client.py @@ -947,7 +947,7 @@ async def getCompletedSessionInfo(self, sessID): } mSite = 'https://members.iracing.com/membersite/member' url = (mSite + '/GetSubsessionResults') - web_fb = await self.ir._build_request(url, payload) + web_fb = await self._build_request(url, payload) print(web_fb) return session_data.SubSessionData(web_fb.json()) From 11e52b26a5593c063b473ee74445f4858f211eee Mon Sep 17 00:00:00 2001 From: Nathan Crosty Date: Tue, 3 May 2022 13:48:15 -0400 Subject: [PATCH 6/9] The web request was throwing an error on allow redirects so commented that out --- pyracing/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyracing/client.py b/pyracing/client.py index 78d7238..a80f973 100644 --- a/pyracing/client.py +++ b/pyracing/client.py @@ -99,7 +99,7 @@ async def _build_request(self, url, params): response = await self.session.get( url, params=params, - allow_redirects=False, + #allow_redirects=False, timeout=10.0 ) logger.info(f'Request sent for URL: {response.url}') From 302261e5ac7d043e60891c353cf0514f096730fc Mon Sep 17 00:00:00 2001 From: Nathan Crosty Date: Fri, 10 Jun 2022 15:33:59 -0400 Subject: [PATCH 7/9] added the updated password encrpytion code and functions --- pyracing/client.py | 9 +++++++-- pyracing/helpers.py | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/pyracing/client.py b/pyracing/client.py index a80f973..e471d88 100644 --- a/pyracing/client.py +++ b/pyracing/client.py @@ -1,7 +1,12 @@ from pyracing import constants as ct from pyracing import logger -from pyracing.helpers import now_five_min_floor +from pyracing.helpers import ( + encode_password, + now_five_min_floor +) + + from pyracing.response_objects import ( career_stats, chart_data, @@ -39,7 +44,7 @@ def __init__(self, username: str, password: str): is to store then in your OS environment and call with os.getenv(). """ self.username = username - self.password = password + self.password = encode_password(username,password) self.session = httpx.AsyncClient() def _rename_numerical_keys(self, response_item, mapping): diff --git a/pyracing/helpers.py b/pyracing/helpers.py index be3a6c6..b1c6a6f 100644 --- a/pyracing/helpers.py +++ b/pyracing/helpers.py @@ -1,3 +1,5 @@ +import base64 +import hashlib import math import urllib.parse from time import time @@ -11,6 +13,19 @@ def datetime_from_iracing_timestamp(timestamp): except Exception: return None +def encode_password(username, password): + """ Encodes the username/password combination as a Base64 string for + submission in the password field on iRacing login forms. This is not what + iRacing stores as the hashed password. It is merely to prevent the plain + text version of a user's password from being transmitted to iRacing. + """ + s256Hash = hashlib.sha256((password + username.lower()).encode('utf-8')).digest() + base64Hash = base64.b64encode(s256Hash).decode('utf-8') + + return base64Hash + + + def now_five_min_floor(): """ Takes the current time and rounds down to the nearest five minute mark From 723d23a777e72b661f355e0685bb23e23d398ed5 Mon Sep 17 00:00:00 2001 From: Nathan Crosty Date: Fri, 6 Jan 2023 11:29:53 -0500 Subject: [PATCH 8/9] updated the json start number because it wasnt working for the other leagues --- pyracing/client.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyracing/client.py b/pyracing/client.py index e471d88..505257a 100644 --- a/pyracing/client.py +++ b/pyracing/client.py @@ -107,6 +107,8 @@ async def _build_request(self, url, params): #allow_redirects=False, timeout=10.0 ) + + print(response.request) logger.info(f'Request sent for URL: {response.url}') logger.info(f'Status code of response: {response.status_code}') logger.debug(f'Contents of the response object: {response.__dict__}') @@ -953,7 +955,6 @@ async def getCompletedSessionInfo(self, sessID): mSite = 'https://members.iracing.com/membersite/member' url = (mSite + '/GetSubsessionResults') web_fb = await self._build_request(url, payload) - print(web_fb) return session_data.SubSessionData(web_fb.json()) async def getCalendarBySeason(self, seasonID, leagueID): @@ -987,12 +988,13 @@ async def getActiveSessions(self, leagueID): async def get_league_members(self, leagueID): payload = { 'leagueid': leagueID, - 'lowerBound': 100, + 'lowerBound': 0, 'upperBound': 100 } mSite = 'https://members.iracing.com/membersite/member' URL_LEAGUE_MEMBERS = (mSite + '/GetLeagueMembers') url = URL_LEAGUE_MEMBERS + membersWeb = await self._build_request(url, payload) return membersWeb.json() From a29ff8a5155828a84d357c3dea5b02c767282064 Mon Sep 17 00:00:00 2001 From: Nathan Crosty Date: Fri, 6 Jan 2023 11:32:42 -0500 Subject: [PATCH 9/9] removed print statement --- pyracing/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyracing/client.py b/pyracing/client.py index 505257a..22591df 100644 --- a/pyracing/client.py +++ b/pyracing/client.py @@ -108,7 +108,7 @@ async def _build_request(self, url, params): timeout=10.0 ) - print(response.request) + #print(response.request) logger.info(f'Request sent for URL: {response.url}') logger.info(f'Status code of response: {response.status_code}') logger.debug(f'Contents of the response object: {response.__dict__}')