Lektoren app-weit: Plan/Details/iCal mit type=lektor, Namenssuche (Autocomplete) für Studierende und Lektoren, Lektor-Karte mit Profil-Link

This commit is contained in:
Nicolas Gruber
2026-10-19 16:01:41 +02:00
parent 6763faf9c1
commit 139b3677b5
5 changed files with 127 additions and 23 deletions
+30 -12
View File
@@ -58,10 +58,11 @@ class Event:
class Person:
uid: str
name: str
stg: str
semester: str
verband: str
gruppe: str
stg: str = ""
semester: str = ""
verband: str = ""
gruppe: str = ""
kind: str = "student" # student | lektor
@dataclass
@@ -177,7 +178,8 @@ class CISClient:
return f"{self.base}/private/lvplan/stpl_kalender.php?{q}"
def _ical_student_params(self, uid: str, begin: int, ende: int) -> dict:
return {"type": "student", "pers_uid": uid, "ort_kurzbz": "",
ptype = "student" if uid.isdigit() else "lektor"
return {"type": ptype, "pers_uid": uid, "ort_kurzbz": "",
"stg_kz": "", "sem": "", "ver": "", "grp": "",
"gruppe_kurzbz": "", "lva": "", "begin": begin, "ende": ende,
"format": "ical", "version": "2", "target": "ical"}
@@ -197,25 +199,38 @@ class CISClient:
return parse_ical(self._get(self._ical_url(self._ical_stg_params(kz, sem, ver, grp, begin, ende))))
def ical_raw(self, kind: str, **kw) -> str:
if kind == "student":
if kind in ("student", "lektor"):
return self._get(self._ical_url(self._ical_student_params(kw["uid"], kw["begin"], kw["ende"])))
return self._get(self._ical_url(self._ical_stg_params(kw["kz"], kw["sem"], kw["ver"], kw.get("grp", ""), kw["begin"], kw["ende"])))
# ---------- person ----------
@lru_cache(maxsize=256)
def person(self, uid: str) -> Optional[Person]:
uid = (uid or "").strip()
if not uid:
return None
is_student = uid.isdigit()
try:
html = self._get(f"{self.base}/private/lvplan/stpl_week.php?pers_uid={uid}")
url = f"{self.base}/private/lvplan/stpl_week.php?pers_uid={uid}"
if not is_student:
url += "&type=lektor"
html = self._get(url)
except requests.HTTPError:
return None
t = re.sub(r"<[^>]+>", " ", html)
t = re.sub(r"\s+", " ", t)
m = re.search(r"Person:\s*(.+?)\s*-\s*(\d{9,10}).*?Studiengang:\s*(.+?)\s+Semester:\s*(\S+?)\s+Verband:\s*(\S+?)\s+Gruppe:", t)
if is_student:
m = re.search(r"Person:\s*(.+?)\s*-\s*(\d{9,10}).*?Studiengang:\s*(.+?)\s+Semester:\s*(\S+?)\s+Verband:\s*(\S+?)\s+Gruppe:", t)
if not m:
return None
name, u, stg, sem, ver = m.groups()
return Person(uid=u, name=name.strip(), stg=stg.strip(),
semester=sem.strip(), verband=ver.strip(), gruppe="", kind="student")
m = re.search(r"Person:\s*(.+?)\s*-\s*([A-Za-z][\w.]*)", t)
if not m:
return None
name, u, stg, sem, ver = m.groups()
return Person(uid=u, name=name.strip(), stg=stg.strip(),
semester=sem.strip(), verband=ver.strip(), gruppe="")
name, u = m.groups()
return Person(uid=u, name=name.strip(), kind="lektor")
# ---------- person_id + photos ----------
def person_id_for(self, uid: str) -> str:
@@ -416,7 +431,10 @@ class CISClient:
def detail(self, kind: str, datum: str, stunde: int, uid: str = "",
kz: str = "", sem: str = "", ver: str = "", grp: str = "",
ort: str = "") -> dict:
if kind == "student":
if kind == "lektor":
url = (f"{self.base}/private/lvplan/stpl_detail.php?type=lektor&datum={datum}"
f"&stunde={stunde}&pers_uid={uid}&stg_kz=&sem=&ver=&grp=&ort_kurzbz={ort}")
elif kind == "student":
url = (f"{self.base}/private/lvplan/stpl_detail.php?type=student&datum={datum}"
f"&stunde={stunde}&pers_uid={uid}&stg_kz={kz}&sem={sem}&ver={ver}"
f"&grp= {grp}&ort_kurzbz={ort}")