Skip to content
This repository has been archived by the owner on Jul 23, 2024. It is now read-only.

Avoid captcha problem and more ! #3

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
OUISNCF_COOKIE=
# Example : "cookie-name=cookie-value; cookie-name2=cookie-value2"
TGVMAX_CARD_NUMBER=
# Card number with "HC" prefix included. Example : HCXXXXXXXXX
BIRTH_DATE=
# FR/UK/ES format : YYYY-MM-DD Example : 2000-01-31
OUISNCF_STATS_COOKIE='not mandatory in classic use'
# Example : "cookie-name=cookie-value; cookie-name2=cookie-value2"
REAUTHENTICATE=
# Exemple : REAUTHENTICATE='__Secure-refresh-account-token= SOMETHING; datadome=SOMETHING'
You need to find the value field in your cookies !!
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
## Setup

Create and fill a `.env` file with your cookies contents, your birthdate and your TGVMax card number.

The two important cookies are :
- __Secure-refresh-account-token --> It allows you to authentificate
- datadome=SOMETHING' --> I don't know but seems to be important to avoid captcha

<details>
<summary>Tutorial to get your oui.sncf cookies. Reproduce it once connected. </summary>

Expand Down
41 changes: 38 additions & 3 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,25 @@

from dotenv import load_dotenv


load_dotenv()

def dict_cookie_from_str(str_cookies):
d_cookies = {}
l_cookies = str_cookies.split("; ")
for key_item in l_cookies:
i = key_item.find("=")
key = key_item[:i]
item = key_item[i+1:]
d_cookies[key] = item
return d_cookies

def str_cookies_from_dict(d_cookies):
str_cookie = ""
for key, item in d_cookies.items():
str_cookie += key + "="+ item + "; "
str_cookie = str_cookie[:-2]
return str_cookie

class AppConfigError(Exception):
"""
Expand All @@ -21,11 +38,9 @@ class AppConfig:
Application configuration.
"""

OUISNCF_COOKIE: str
TGVMAX_CARD_NUMBER: str
BIRTH_DATE: str
OUISNCF_STATS_COOKIE: str

REAUTHENTICATE: str
"""
Map environment variables to class fields according to these rules:
- Field won't be parsed unless it has a type annotation
Expand Down Expand Up @@ -56,9 +71,29 @@ def __init__(self, env):
except ValueError:
raise AppConfigError(f'Unable to cast value of "{env[field]}" '
f'to type "{var_type}" for "{field}" field') from None
self.write_temp_env()

def __repr__(self):
return str(self.__dict__)

def update_cookies_from_dict(self, field, dict_cookies):
str_old = self.__dict__[field]
d_new_cookies = dict_cookie_from_str(str_old)
for key, value in dict_cookies.items():
d_new_cookies[key] = value
self.__dict__[field] = str_cookies_from_dict(d_new_cookies)
self.write_temp_env()

def write_temp_env(self):
f = open("./.env", "w")
f.close()
f = open("./.env", "a")
for field in AppConfig.__annotations__:
str_write = field
value = self.__getattribute__(field)
str_write += "='" + value + "'"
f.write(str_write + "\n")
f.close()


# Expose Config object for app to import
Expand Down
43 changes: 33 additions & 10 deletions proposal.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def parse_intercites_de_nuit(second_class_offers: any) -> dict:
"""
remaining = {}
for offer in second_class_offers:
if float(offer['priceLabel'].split(' ')[0]) == 0:
if float(offer['priceLabel'].split(' ')[0].replace(",", ".") ) == 0:
for message in offer['messages']:
physical_space = offer['comfortClass']['physicalSpaceLabel']
if 'Plus que' in message['message']:
Expand All @@ -70,13 +70,35 @@ def get_next(dpt_station, arr_station, dpt_date, verbosity) -> requests.Response
"""

headers = {
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.61 Safari/537.36',
'x-bff-key': 'ah1MPO-izehIHD-QZZ9y88n-kku876',
'x-market-locale': 'fr_FR',
'x-nav-current-path': '/app/en-en/home/shop/results/outward',
'cookie': Config.OUISNCF_COOKIE,
'Host': 'www.sncf-connect.com',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0',
'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'fr,en-US;q=0.7,en;q=0.3', 'Accept-Encoding': 'gzip, deflate, br',
'x-bff-key': 'ah1MPO-izehIHD-QZZ9y88n-kku876', 'x-client-channel': 'web', 'x-client-app-id': 'front-web',
'x-api-env': 'production', 'x-market-locale': 'fr_FR',
'x-email-hidden': '358C5C06A9357683EAF0119515C81AAE0A942BB5',
'x-email-strong': '9b0b6129b4c95891f8965bc7ad8d537ae9a1c71f3fa26da516c246afd17b765e',
'x-email-stronger': '860f0711e955b6bdb08000f7b4cba8c6b4eda78b5eb14e2bafae05510838f055',
'x-con-s': 'CPfztUAPfztUAAHABBENChCgAAAAAAAAAAAAAAAAAAEDoAMAAQSAIQAYAAgkAUgAwABBIANABgACCQAqADAAEEgBEAGAAIJABIAMAAQSAGQAYAAgkAAA.YAAAAAAAAAAA',
'x-con-id': 'fbac099fd2cccb74601b3c50ca1f697e78f', 'x-con-ex': 'fbab7d18833206847f893fb8a0d355225a5', 'x-app-version': '20220903.0.0-2022090300-641abe9ff5',
'x-device-os-version': 'Linux (x86_64)', 'x-device-class': 'desktop',
'x-attribution-referrer': 'https://www.sncf-connect.com/',
'x-nav-previous-page': 'Homepage', 'x-nav-current-path': '/app/home/search',
'x-visitor-type': '1', 'Origin': 'https://www.sncf-connect.com', 'DNT': '1',
'Connection': 'keep-alive', 'Referer': 'https://www.sncf-connect.com/app/home/search?destinationLabel=Paris&destinationId=CITY_FR_6455259',
'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'Pragma': 'no-cache', 'Cache-Control': 'no-cache', 'Content-Length': '0'
}

#### reauthentification ######
session = requests.Session()
headers["Cookie"] = Config.REAUTHENTICATE
response = session.post("https://www.sncf-connect.com/bff/api/v1/web-refresh/reauthenticate",
headers=headers)
if response.status_code != 200:
print("__Secure-refresh-account-tokem in REAUTHENTICATE in the .env file is misconfigured ! ")
Config.update_cookies_from_dict("REAUTHENTICATE", session.cookies.get_dict())

headers["Cookie"] = Config.REAUTHENTICATE

data = {
'schedule': {
'outward': {
Expand Down Expand Up @@ -104,7 +126,7 @@ def get_next(dpt_station, arr_station, dpt_date, verbosity) -> requests.Response
'discountCards': [
{
'code': 'HAPPY_CARD',
'number': 'HC700678060',
'number': Config.TGVMAX_CARD_NUMBER,
'label': 'MAX JEUNE',
},
{
Expand All @@ -130,17 +152,18 @@ def get_next(dpt_station, arr_station, dpt_date, verbosity) -> requests.Response
'strictMode': False,
}

response = requests.post('https://www.sncf-connect.com/bff/api/v1/itineraries',
response = session.post('https://www.sncf-connect.com/bff/api/v1/itineraries',
headers=headers, json=data)
Config.update_cookies_from_dict("REAUTHENTICATE", session.cookies.get_dict())

if response.status_code == 404:
return False
elif response.status_code != 200:
print(BColors.FAIL + 'Error: HTTP', str(response.status_code) + BColors.ENDC)
if verbosity:
print(response.text)
if response.status_code == 403:
print('Too many requests. Resolve captcha at '
'https://oui.sncf/billet-train and recover your new cookies')
print(response.text)
sys_exit('Error in the request to get proposal')
return response

Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
description='Python Distribution Utilities',
author='Divulgacheur',
author_email='[email protected]',
packages=['distutils', 'requests', 'dotenv'],
)