initial commit
This commit is contained in:
BIN
__pycache__/login.cpython-312.pyc
Normal file
BIN
__pycache__/login.cpython-312.pyc
Normal file
Binary file not shown.
139
login.py
Executable file
139
login.py
Executable file
@ -0,0 +1,139 @@
|
|||||||
|
# **************************************************************************** #
|
||||||
|
# #
|
||||||
|
# ::: :::::::: #
|
||||||
|
# login.py :+: :+: :+: #
|
||||||
|
# +:+ +:+ +:+ #
|
||||||
|
# By: tomoron <tomoron@student.42angouleme.fr> +#+ +:+ +#+ #
|
||||||
|
# +#+#+#+#+#+ +#+ #
|
||||||
|
# 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("^<form.*>").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))
|
||||||
40
scrap.py
Normal file
40
scrap.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# **************************************************************************** #
|
||||||
|
# #
|
||||||
|
# ::: :::::::: #
|
||||||
|
# scrap.py :+: :+: :+: #
|
||||||
|
# +:+ +:+ +:+ #
|
||||||
|
# By: tomoron <tomoron@student.42angouleme.fr> +#+ +:+ +#+ #
|
||||||
|
# +#+#+#+#+#+ +#+ #
|
||||||
|
# Created: 2024/11/25 16:39:19 by tomoron #+# #+# #
|
||||||
|
# Updated: 2025/03/28 13:13:48 by tomoron ### ########.fr #
|
||||||
|
# #
|
||||||
|
# **************************************************************************** #
|
||||||
|
|
||||||
|
from login import Intra42
|
||||||
|
from getpass import getpass
|
||||||
|
import re
|
||||||
|
import json
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
import dateutil
|
||||||
|
from datetime import date, timedelta
|
||||||
|
|
||||||
|
if(len(sys.argv) != 2):
|
||||||
|
print("missing team id, usage :", sys.argv[0], "<project_id>")
|
||||||
|
exit(1);
|
||||||
|
project_id = sys.argv[1]
|
||||||
|
start_search_date = date.today().strftime("%Y-%m-%d")
|
||||||
|
end_search_date = (date.today() + timedelta(days=1)).strftime("%Y-%m-%d")
|
||||||
|
getUrl = f"https://projects.intra.42.fr/projects/{project_id}/slots.json?start={start_search_date}&end={end_search_date}"
|
||||||
|
connIntra = Intra42()
|
||||||
|
found = set();
|
||||||
|
while(True):
|
||||||
|
res = connIntra.get_available_slot(getUrl)
|
||||||
|
for x in res:
|
||||||
|
if x["ids"] not in found:
|
||||||
|
start = dateutil.parser.isoparse(x["start"]).strftime("%d/%m %H:%M")
|
||||||
|
end = dateutil.parser.isoparse(x["end"]).strftime("%d/%m %H:%M")
|
||||||
|
print("\aslot found starting at", start, ",ending at", end);
|
||||||
|
found.add(x["ids"])
|
||||||
|
time.sleep(1);
|
||||||
Reference in New Issue
Block a user