schoolapp-api 2.1.3__tar.gz → 2.1.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {schoolapp_api-2.1.3/schoolapp_api.egg-info → schoolapp_api-2.1.5}/PKG-INFO +1 -1
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/pyproject.toml +1 -1
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/auth.py +20 -9
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/http_client.py +18 -14
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5/schoolapp_api.egg-info}/PKG-INFO +1 -1
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/LICENSE +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/README.md +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/__init__.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/constants.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/managers/__init__.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/managers/attendance_manager.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/managers/base_manager.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/managers/course_manager.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/managers/grades_manager.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/managers/profile_manager.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/parsers/__init__.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/parsers/absences.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/parsers/annees.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/parsers/filieres.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/parsers/modules.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/parsers/note_elem.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/parsers/note_mod.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/parsers/profile.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/parsers/sanctions.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/parsers/semestres.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/parsers/stats.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/school_app_client.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/types/__init__.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/types/annee.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/types/base.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/types/element.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/types/module.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api/types/semestre.py +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api.egg-info/SOURCES.txt +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api.egg-info/dependency_links.txt +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api.egg-info/requires.txt +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/schoolapp_api.egg-info/top_level.txt +0 -0
- {schoolapp_api-2.1.3 → schoolapp_api-2.1.5}/setup.cfg +0 -0
|
@@ -70,19 +70,30 @@ class AuthManager:
|
|
|
70
70
|
return self.logged_in
|
|
71
71
|
|
|
72
72
|
def check_session(self):
|
|
73
|
-
"""
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
"""Confirm whether the session is still valid by visiting the index page"""
|
|
74
|
+
try:
|
|
75
|
+
from schoolapp_api.constants import INDEX_URL
|
|
76
|
+
code, url, content = self.http_client.get(INDEX_URL)
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
# If url is None (exception) or it contains "/login", session is dead
|
|
79
|
+
if not url or "/login" in url.lower():
|
|
80
|
+
logger.warning(f"Session check: Redirected to {url or 'None'} - session invalid")
|
|
81
|
+
self.logged_in = False
|
|
82
|
+
return False
|
|
83
|
+
|
|
84
|
+
# If content is very short or contains login-like keywords, it's also dead
|
|
85
|
+
if content and (len(content) < 1000 or "login" in content.lower()[:500]):
|
|
86
|
+
logger.warning("Session check: Content looks like a login page - session invalid")
|
|
87
|
+
self.logged_in = False
|
|
88
|
+
return False
|
|
89
|
+
|
|
90
|
+
self.logged_in = True
|
|
91
|
+
return True
|
|
92
|
+
except Exception as e:
|
|
93
|
+
logger.error(f"Error during check_session: {e}")
|
|
80
94
|
self.logged_in = False
|
|
81
95
|
return False
|
|
82
96
|
|
|
83
|
-
self.logged_in = True
|
|
84
|
-
return True
|
|
85
|
-
|
|
86
97
|
def refresh_csrf_from_url(self, url):
|
|
87
98
|
"""Fetch a fresh CSRF token from a specific page"""
|
|
88
99
|
try:
|
|
@@ -24,13 +24,9 @@ class HTTPClient:
|
|
|
24
24
|
def __init__(self, base_url):
|
|
25
25
|
self.base_url = base_url
|
|
26
26
|
self.cookie_jar = http.cookiejar.CookieJar()
|
|
27
|
-
opener = urllib.request.build_opener(
|
|
28
|
-
urllib.request.HTTPCookieProcessor(self.cookie_jar)
|
|
29
|
-
NoRedirectHandler()
|
|
27
|
+
self.opener = urllib.request.build_opener(
|
|
28
|
+
urllib.request.HTTPCookieProcessor(self.cookie_jar)
|
|
30
29
|
)
|
|
31
|
-
urllib.request.install_opener(opener)
|
|
32
|
-
# opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.cookie_jar))
|
|
33
|
-
# urllib.request.install_opener(opener)
|
|
34
30
|
self.headers = DEFAULT_HEADERS.copy()
|
|
35
31
|
|
|
36
32
|
def get(self, url, params=None):
|
|
@@ -43,17 +39,21 @@ class HTTPClient:
|
|
|
43
39
|
|
|
44
40
|
req = urllib.request.Request(url, headers=self.headers, method="GET")
|
|
45
41
|
|
|
46
|
-
with
|
|
42
|
+
with self.opener.open(req, timeout=15) as response:
|
|
47
43
|
code = response.getcode()
|
|
48
44
|
response_url = response.geturl()
|
|
49
45
|
content = response.read().decode("utf-8")
|
|
50
46
|
return code, response_url, content
|
|
51
47
|
|
|
52
48
|
except urllib.error.HTTPError as e:
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
try:
|
|
50
|
+
content = e.read().decode("utf-8")
|
|
51
|
+
except:
|
|
52
|
+
content = None
|
|
53
|
+
logger.error(f"HTTP Error {e.code} on {url}: {e.reason}")
|
|
54
|
+
return e.code, e.url, content
|
|
55
55
|
except Exception as e:
|
|
56
|
-
logger.error(f"GET Error: {e}")
|
|
56
|
+
logger.error(f"GET Error on {url}: {e}")
|
|
57
57
|
return None, None, None
|
|
58
58
|
|
|
59
59
|
def post(self, url, data, referer=None):
|
|
@@ -66,14 +66,18 @@ class HTTPClient:
|
|
|
66
66
|
if referer:
|
|
67
67
|
req.add_header('Referer', referer)
|
|
68
68
|
|
|
69
|
-
with
|
|
69
|
+
with self.opener.open(req, timeout=15) as response:
|
|
70
70
|
code = response.getcode()
|
|
71
71
|
response_url = response.geturl()
|
|
72
72
|
content = response.read().decode('utf-8')
|
|
73
73
|
return code, response_url, content
|
|
74
74
|
except urllib.error.HTTPError as e:
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
try:
|
|
76
|
+
content = e.read().decode("utf-8")
|
|
77
|
+
except:
|
|
78
|
+
content = None
|
|
79
|
+
logger.error(f"HTTP Error {e.code} on {url}: {e.reason}")
|
|
80
|
+
return e.code, e.url, content
|
|
77
81
|
except Exception as e:
|
|
78
|
-
logger.error(f"POST Error: {e}")
|
|
82
|
+
logger.error(f"POST Error on {url}: {e}")
|
|
79
83
|
return None, None, None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|