# **************************************************************************** # # # # ::: :::::::: # # login.py :+: :+: :+: # # +:+ +:+ +:+ # # By: tomoron +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2024/11/25 16:22:08 by tomoron #+# #+# # # Updated: 2025/03/26 13:10:42 by tomoron ### ########.fr # # # # **************************************************************************** # import requests import time import subprocess import os import re import json import urllib.parse from getpass import getpass from bs4 import BeautifulSoup class Intra42(): user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0 .6167.160 Safari/537.36" def __init__(self): self.cookieHeader = self.get_cookie_header() print("token ready") def update_cookies(self, cookies, new_cookies, path): cookies_arr = re.compile("^[A-Za-z_.0-9]+=.*?;", re.MULTILINE).findall("\n".join(new_cookies.split(', '))) for x in cookies_arr: cookies[x.split("=")[0]] = x.split("=")[1][:-1] with open(os.path.expanduser(path), 'w') as f: json.dump(cookies, f) return(cookies) def cookie_to_header(self, cookies): cookie_header = "" for x in cookies: cookie_header += x + "="+cookies[x] +"; " cookie_header = cookie_header[:-2] return(cookie_header) def login_user(self, username, password): response = requests.get("https://profile.intra.42.fr/users/auth/keycloak_student", headers={"User-Agent": Intra42.user_agent}, allow_redirects=False) login_url = response.headers["Location"] response = requests.get(login_url, headers={"User-Agent":Intra42.user_agent}, allow_redirects=False); cookies_arr = [x.split('; ')[0] for x in response.headers["Set-Cookie"].split(', ')] cookies = {} for x in cookies_arr: cookies[x.split("=")[0]] = x.split("=")[1] page = BeautifulSoup(response.text, "html.parser") form_html = page.find_all("form",id="kc-form-login")[0] form_start = re.compile("^").findall(str(form_html))[0] url = form_start.split(' ')[1].split("\"")[1] username = urllib.parse.quote(username) password = urllib.parse.quote(password) cookie_header = self.cookie_to_header(cookies) req_body = f'username={username}&password={password}&rememberMe=on&credentialId=' url = url.replace("amp;", "") headers = { "User-Agent":Intra42.user_agent, "Cookie":cookie_header, "Content-Type": "application/x-www-form-urlencoded", } response = requests.post(url, data=req_body ,headers=headers,allow_redirects=False) if(response.status_code == 200): return("error") return(self.update_cookies(cookies, response.headers["Set-Cookie"],"~/.intra_refresh")) def refresh_session(self): cookies = "error" if(os.path.isfile(os.path.expanduser("~/.intra_refresh"))): with open(os.path.expanduser("~/.intra_refresh"), 'r') as f: cookies = json.load(f) else: while(cookies == "error"): username = input("enter intra username :") password = getpass("enter password :") cookies = self.login_user(username, password) response = requests.get("https://profile.intra.42.fr/users/auth/keycloak_student",headers={"User-Agent":Intra42.user_agent},allow_redirects=False) intra_prod_cookie = response.cookies.get("_intra_42_session_production") cookie_header = self.cookie_to_header(cookies) response = requests.get(response.headers["Location"], headers={"User-Agent":Intra42.user_agent,"Cookie":cookie_header},allow_redirects=False) if(response.status_code == 200): os.remove(os.path.expanduser("~/.intra_refresh")) return(self.refresh_session()) self.update_cookies(cookies, response.headers["Set-Cookie"], "~/.intra_refresh") response = requests.get(response.headers["Location"], headers={"User-Agent":Intra42.user_agent,"Cookie":f"_intra_42_session_production={intra_prod_cookie}"},allow_redirects=False) profile_cookies = self.update_cookies({},response.headers["Set-Cookie"],"~/.intra_profile") return(profile_cookies); def get_cookie_header(self): profile_cookies = {} if(os.path.isfile(os.path.expanduser("~/.intra_profile"))): with open(os.path.expanduser("~/.intra_profile")) as f: profile_cookies = json.load(f) else: profile_cookies = self.refresh_session() return(self.cookie_to_header(profile_cookies)) def get_intra_home(self): self.cookieHeader = self.get_cookie_header() cookie_header = self.cookieHeader cookie_header += "; intra=v2" cookie_header += "; locale=en" response = requests.get("https://profile.intra.42.fr/",headers = {"User-Agent":Intra42.user_agent,"Cookie":cookie_header},allow_redirects=False) if(response.status_code == 302): os.remove(os.path.expanduser("~/.intra_profile")) return(get_intra_home(self.get_cookie_header())) return(response.text) def get_goals(self): self.cookieHeader = self.get_cookie_header() response = requests.get("https://profile.intra.42.fr/users/me/goals?cursus=42cursus",headers = {"User-Agent":Intra42.user_agent,"Cookie":self.cookieHeader},allow_redirects=False) if(response.status_code == 302): os.remove(os.path.expanduser("~/.intra_profile")) return(get_goals()) return(response.text) def get_project_page(self, slug): self.cookieHeader = self.get_cookie_header() response = requests.get(f"https://projects.intra.42.fr/projects/{slug}",headers = {"User-Agent":Intra42.user_agent,"Cookie":self.cookieHeader},allow_redirects=False) if(response.status_code == 302): os.remove(os.path.expanduser("~/.intra_profile")) return(get_project_page(slug)) return(response.text) def get_available_slot(self, url): self.cookieHeader = self.get_cookie_header() response = requests.get(url, headers = { "User-Agent": Intra42.user_agent, "Cookie":self.cookieHeader}, allow_redirects=False) if(response.status_code == 302): os.remove(os.path.expanduser("~/.intra_profile")) return(get_available_slot(url)) return(json.loads(response.text))