88import re
99from datetime import datetime , date
1010import calendar
11+ import json
12+ import os .path
1113
1214from .authentication_functions import get_authentication_data , get_authentication_url , get_session
1315
@@ -19,12 +21,15 @@ class LanisClient:
1921
2022 Parameters
2123 ----------
22- schoolid : str
23- The id of the school which you can see it in the url at ``i=``.
24+ school : str | School
25+ 1. The id of the school which you can see it in the url at ``i=``.
26+ 2. The school name and city in ``School``.
2427 username : str
2528 The username in firstname.lastname.
2629 password : str
2730 The password.
31+ save : bool, default True
32+ If False the school list and future things won't be saved to a file.
2833 ad_header : httpx.Headers, default {"user-agent": ....}
2934 Send custom headers to Lanis. Primarily used to send a
3035 custom ``user-agent``.
@@ -134,6 +139,21 @@ class CalendarData:
134139 end : datetime
135140 data : list [CalendarData ] = None
136141 json : list [dict [str , any ]] = None
142+
143+ @dataclass
144+ class School :
145+ """
146+ Alternative to school id for authentication.
147+
148+ Parameters
149+ ----------
150+ name : str
151+ Full school name
152+ city : str
153+ City name sometimes with abbreviations or fully written.
154+ """
155+ name : str
156+ city : str
137157
138158 @dataclass
139159 class TaskData :
@@ -170,28 +190,22 @@ class TaskData:
170190 attachment : Optional [list [str ]] = None
171191 attachment_url : Optional [ParseResult ] = None
172192
173- def requires_auth (f ):
174- @wraps (f )
175- def decorated (* args , ** kwargs ):
176- if not args [0 ].authenticated :
177- args [0 ].logger .error ("A2: Not authenticated." )
178- return
179- return f (* args , ** kwargs )
180- return decorated
181-
182193 def __init__ (self ,
183- schoolid : str ,
194+ school : str | School ,
184195 username : str ,
185196 password : str ,
197+ save : bool = True ,
186198 ad_header : httpx .Headers =
187199 httpx .Headers ({ "user-agent" :
188200 "LanisClient by kurwjan and contributors (https://github.com/kurwjan/LanisAPI/)" })
189201 ) -> None :
190202
191- self .schoolid = schoolid
203+ self .school = school
192204 self .username = username
193205 self .password = password
194206
207+ self .save = save
208+
195209 self .ad_header = ad_header
196210
197211 self .parser = httpx .Client (headers = ad_header )
@@ -207,12 +221,50 @@ def __init__(self,
207221 def __del__ (self ) -> None :
208222 self .parser .close ()
209223
224+ def requires_auth (f ):
225+ @wraps (f )
226+ def decorated (* args , ** kwargs ):
227+ if not args [0 ].authenticated :
228+ args [0 ].logger .error ("A2: Not authenticated." )
229+ return
230+ return f (* args , ** kwargs )
231+ return decorated
232+
210233 def close (self ) -> None :
211234 """Closes the client; you need to do this.
212235 """
213236 self .parser .close ()
214237 self .authenticated = False
215238
239+ def get_schools (self ):
240+ """
241+ Returns all schools with their id, name and city.
242+
243+ Returns
244+ -------
245+ list[dict[str, str]]
246+ JSON
247+ """
248+
249+ if os .path .exists ("schools.json" ):
250+ with open ("schools.json" , "r" ) as file :
251+ return json .load (file )
252+
253+ url = "https://startcache.schulportal.hessen.de/exporteur.php"
254+
255+ response = self .parser .get (url , params = httpx .QueryParams ({"a" : "schoollist" })).json ()
256+
257+ schools = []
258+
259+ for group in response :
260+ for school in group ["Schulen" ]:
261+ schools .append (school )
262+
263+ if self .save is True :
264+ with open ("schools.json" , "w" ) as file :
265+ json .dump (schools , file )
266+
267+ return schools
216268
217269 def authenticate (self ) -> None :
218270 """Logs into the school portal and sets the session id in the auth_cookies.
@@ -221,8 +273,21 @@ def authenticate(self) -> None:
221273 if self .authenticated :
222274 self .logger .warning ("A1: Already authenticated." )
223275 return
276+
277+ school_id : int
278+
279+ if isinstance (self .school , str ):
280+ school_id = self .school
281+ else :
282+ schools = self .get_schools ()
283+
284+ try :
285+ school_id = next (school for school in schools if school ["Name" ] == self .school .name and school ["Ort" ] == self .school .city )["Id" ]
286+ except StopIteration :
287+ self .logger .warning ("E0: School doesn't exist check for right spelling." )
288+ return
224289
225- response_session = get_session (self . schoolid , self .username ,
290+ response_session = get_session (school_id , self .username ,
226291 self .password ,self .parser , self .ad_header )
227292 response_cookies = response_session ["cookies" ]
228293
@@ -234,7 +299,7 @@ def authenticate(self) -> None:
234299
235300 self .parser .cookies = get_authentication_data (auth_url , response_cookies ,
236301 self .parser , self .ad_header ,
237- schoolid = self . schoolid )
302+ schoolid = school_id )
238303
239304 self .authenticated = True
240305
@@ -473,4 +538,4 @@ def get_tasks(self) -> list[TaskData]:
473538
474539 self .logger .info ("D0: Successfully got tasks" )
475540
476- return task_list
541+ return task_list
0 commit comments