2025-07-15 16:36:34 +02:00
|
|
|
import requests
|
|
|
|
|
import urllib.parse
|
|
|
|
|
import re
|
|
|
|
|
import html
|
|
|
|
|
import time
|
|
|
|
|
import datetime
|
|
|
|
|
import pytz
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
|
|
|
|
|
|
def get_day():
|
|
|
|
|
dt = datetime.datetime.now(pytz.timezone('Europe/Berlin')) + datetime.timedelta(days=3)
|
|
|
|
|
date = dt.strftime('%Y-%m-%d')
|
|
|
|
|
return date
|
|
|
|
|
|
|
|
|
|
def login(username, password):
|
|
|
|
|
|
2025-07-15 16:47:53 +02:00
|
|
|
session = requests.Session()
|
|
|
|
|
session.headers = {
|
2025-07-15 16:36:34 +02:00
|
|
|
'accept': 'text/html, application/xhtml+xml',
|
|
|
|
|
'accept-encoding': 'plain',
|
|
|
|
|
'referer': 'https://auth.anny.eu/',
|
|
|
|
|
'origin': 'https://auth.anny.eu',
|
|
|
|
|
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0',
|
|
|
|
|
'x-requested-with': 'XMLHttpRequest',
|
|
|
|
|
'x-inertia': 'true',
|
|
|
|
|
'x-inertia-version': '66b32acea13402d3aef4488ccd239c93',
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-15 16:47:53 +02:00
|
|
|
r = session.get(
|
2025-07-15 16:36:34 +02:00
|
|
|
'https://auth.anny.eu/login/sso'
|
|
|
|
|
)
|
|
|
|
|
|
2025-07-15 16:47:53 +02:00
|
|
|
session.headers['X-XSRF-TOKEN'] = urllib.parse.unquote(r.cookies['XSRF-TOKEN'])
|
2025-07-15 16:36:34 +02:00
|
|
|
|
2025-07-15 16:47:53 +02:00
|
|
|
r2 = session.post(
|
2025-07-15 16:36:34 +02:00
|
|
|
'https://auth.anny.eu/login/sso',
|
|
|
|
|
json={
|
|
|
|
|
'domain': 'kit.edu'
|
|
|
|
|
}, headers={
|
|
|
|
|
'referer': 'https://auth.anny.eu/login/sso',
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
redirect_url = r2.headers['x-inertia-location']
|
|
|
|
|
|
2025-07-15 16:47:53 +02:00
|
|
|
r3 = session.get(
|
2025-07-15 16:36:34 +02:00
|
|
|
redirect_url,
|
|
|
|
|
allow_redirects=True
|
|
|
|
|
)
|
|
|
|
|
|
2025-07-15 16:47:53 +02:00
|
|
|
session.headers.pop('x-requested-with')
|
|
|
|
|
session.headers.pop('x-inertia')
|
|
|
|
|
session.headers.pop('x-inertia-version')
|
2025-07-15 16:36:34 +02:00
|
|
|
|
|
|
|
|
pattern = r'name="csrf_token" value="([^"]+)"'
|
|
|
|
|
csrf_token = re.search(pattern, r3.text).group(1)
|
|
|
|
|
|
2025-07-15 16:47:53 +02:00
|
|
|
r4 = session.post(
|
2025-07-15 16:36:34 +02:00
|
|
|
'https://idp.scc.kit.edu/idp/profile/SAML2/Redirect/SSO?execution=e1s1',
|
|
|
|
|
data={
|
|
|
|
|
'csrf_token': csrf_token,
|
|
|
|
|
'j_username': username,
|
|
|
|
|
'j_password': password,
|
|
|
|
|
'_eventId_proceed': '',
|
|
|
|
|
'fudis_web_authn_assertion_input': '',
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
response = html.unescape(r4.text)
|
|
|
|
|
|
|
|
|
|
if '/consume' in response:
|
|
|
|
|
print("KIT-Login successful!")
|
|
|
|
|
else:
|
|
|
|
|
print("Failed to login, probably wrong credentials!")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
pattern = r'form action="([^"]+)"'
|
|
|
|
|
consume_url = re.search(pattern, response).group(1)
|
|
|
|
|
pattern = r'name="RelayState" value="([^"]+)"'
|
|
|
|
|
relayState = re.search(pattern, response).group(1)
|
|
|
|
|
pattern = r'name="SAMLResponse" value="([^"]+)"'
|
|
|
|
|
samlResponse = re.search(pattern, response).group(1)
|
|
|
|
|
|
2025-07-15 16:47:53 +02:00
|
|
|
r5 = session.post(
|
2025-07-15 16:36:34 +02:00
|
|
|
consume_url,
|
|
|
|
|
data={
|
|
|
|
|
'RelayState': relayState,
|
|
|
|
|
'SAMLResponse': samlResponse
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
2025-07-15 16:47:53 +02:00
|
|
|
r6 = session.get(
|
2025-07-15 16:36:34 +02:00
|
|
|
'https://anny.eu/en-us/login?target=/en-us/home?withoutIntent=true',
|
|
|
|
|
allow_redirects=True
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2025-07-15 16:47:53 +02:00
|
|
|
return session.cookies
|
2025-07-15 16:36:34 +02:00
|
|
|
|
|
|
|
|
def test_reservation():
|
|
|
|
|
load_dotenv('credentials.env', override=True)
|
|
|
|
|
|
|
|
|
|
username = os.getenv('USERNAME')
|
|
|
|
|
password = os.getenv('PASSWORD')
|
|
|
|
|
|
|
|
|
|
cookies = login(username, password)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TOKEN = cookies['anny_shop_jwt']
|
|
|
|
|
|
|
|
|
|
ses = requests.Session()
|
|
|
|
|
ses.cookies = cookies
|
|
|
|
|
ses.headers = {
|
|
|
|
|
'accept': 'application/vnd.api+json',
|
|
|
|
|
'accept-encoding': 'plain',
|
|
|
|
|
'authorization': 'Bearer ' + TOKEN,
|
|
|
|
|
'content-type': 'application/vnd.api+json',
|
|
|
|
|
'origin': 'https://anny.eu',
|
|
|
|
|
'referer': 'https://anny.eu/',
|
|
|
|
|
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r = ses.post(
|
|
|
|
|
'https://b.anny.eu/api/v1/order/bookings?include=customer,voucher,bookings.booking_add_ons.add_on.cover_image,bookings.sub_bookings.resource,bookings.sub_bookings.service,bookings.series_bookings,bookings.customer,bookings.service.custom_forms.custom_fields,bookings.cancellation_policy,bookings.resource.cover_image,bookings.resource.parent,bookings.resource.category,bookings.reminders,bookings.booking_series,sub_orders.bookings,sub_orders.organization.legal_documents&stateless=1',
|
|
|
|
|
json={
|
|
|
|
|
"resource_id": [
|
|
|
|
|
"3305"
|
|
|
|
|
], "service_id": {
|
|
|
|
|
"449": 1
|
|
|
|
|
}, "start_date": get_day() + "T13:00:00+02:00",
|
|
|
|
|
"end_date": get_day() + "T18:00:00+02:00",
|
|
|
|
|
"description":"", "customer_note": "",
|
|
|
|
|
"add_ons_by_service": {
|
|
|
|
|
"449": [
|
|
|
|
|
[]
|
|
|
|
|
]
|
|
|
|
|
}, "sub_bookings_by_service": {},
|
|
|
|
|
"strategy": "multi-resource"
|
|
|
|
|
}, cookies=cookies
|
|
|
|
|
)
|
|
|
|
|
|
2025-07-15 16:46:12 +02:00
|
|
|
if not r.ok:
|
|
|
|
|
print("Slot is not available anymore!")
|
|
|
|
|
return False
|
2025-07-15 16:36:34 +02:00
|
|
|
|
|
|
|
|
oid = r.json()['data']['id']
|
|
|
|
|
oat = r.json()['data']['attributes']['access_token']
|
|
|
|
|
|
|
|
|
|
r2 = ses.get(
|
|
|
|
|
'https://b.anny.eu/api/ui/checkout-form?oid=' + oid + '&oat=' + oat + '&stateless=1'
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
customer = r2.json()['default']['customer']
|
|
|
|
|
|
|
|
|
|
r3 = ses.post(
|
|
|
|
|
'https://b.anny.eu/api/v1/order?include=customer,voucher,bookings.booking_add_ons.add_on,bookings.sub_bookings.resource,bookings.sub_bookings.service,bookings.service.custom_forms.custom_fields,bookings.cancellation_policy,bookings.resource.cover_image,bookings.resource.parent,bookings.reminders,bookings.customer,bookings.attendees,sub_orders.bookings,sub_orders.organization.legal_documents,last_payment.method&oid=' + oid + '&oat=' + oat + '&stateless=1',
|
|
|
|
|
json={
|
|
|
|
|
"customer": {
|
|
|
|
|
"given_name": customer['given_name'],
|
|
|
|
|
"family_name": customer['family_name'],
|
|
|
|
|
"email": customer['email']
|
|
|
|
|
}, "accept_terms": True,
|
|
|
|
|
"payment_method": "",
|
|
|
|
|
"success_url": "https://anny.eu/checkout/success?oids=" + oid + "&oats=" + oat,
|
|
|
|
|
"cancel_url": "https://anny.eu/checkout?step=checkout&childResource=3302",
|
|
|
|
|
"meta": {
|
|
|
|
|
"timezone":"Europe/Berlin"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if r3.ok:
|
|
|
|
|
print("Reservation successful!")
|
2025-07-15 16:47:53 +02:00
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
print("Reservation failed!")
|
|
|
|
|
return False
|
2025-07-15 16:36:34 +02:00
|
|
|
|
|
|
|
|
test_reservation()
|