Erklärung zu kJAHR :
Die Seminare bekommen jeden Januar neue Refs, die dann 1,5 Jahre am Seminar sind.
Deswegen werden diese in Kursen geführt.
Der letztjährige ist k24, der aktuelle k25 und der nächsten Januar k26.
Mein Seminar führt diese Refs in Klassen, welche heißen: 24a, 25a und es kommt 26a
Jetzt möchte ich ein hookscript für sophomorix schreiben, das die mailadresse im AD anpasst. Per Default wird VORNAME.NACHNAME@MYDOMAIN reingeschrieben.
Das Hookscript hab ich schon geschrieben. Es liest den Usernamen aus /srv/samba/school/default-schools/students/25a/
aus, holt die Infos mit sophomorix-user und spuckt mir das Ergebniss aus.
Zwei wünsche hätte ich da noch:
da ich den Pfad benutze, muss ich zwei scripte rein machen, die ich jedes Jahr anpasse (eins für den aktuellen Kurs eines für den davor).
unschön.
Kann ich das „zusammenfassen“? Ich kann sowas nicht gut.
Das Kursjahr kann ja aus dem Pfad (25a) ausgeleden werden.
Zweite Frage ist unten.
hier mein script, das jetzt für die 25a das tut, was ich will:
Jetzt hab ich also den korrekten Usernamen in der variable $MYMAIL und würde das dann mittels:
sophomorix-user --u $MYLOGIN --set-single-value-attribute mail --entry "$MYMAIL“
meint ihr, dass ich damit erreiche, dass MYMAIL dann im AD im Feld mail steht?
ich habe mir ein Skript gebaut um die E-Mail-Adresse entsprechend zu setzen.
Ich suche nach dem User-Account und prüfe, ob die E-Mail-Adresse korrekt gesetzt ist, ggf. wird diese neu gesetzt (sprich die Seminar-E-Mail).
Der User-Account mit der E-Mail habe ich in einer csv - Datei.
Im Anhang das Script mit Beschreibung und csv-Datei
Mit 7.3 geht es auch relativ einfach mit lmntools:
from linuxmusterTools.ldapconnector import LMNLdapReader as lr, LMNStudent
MYCLASS = "10a"
MYDOMAIN = "gym-ka.seminar-bw.de"
students = lr.get(f'/schoolclasses/{MYCLASS}/students')
for student in students:
MYSN = student['sn'].lower()
MYGIVENNAME = student['givenName'].lower()
new_mail = f"{MYGIVENNAME}.{MYSN}.{MYCLASS}@{MYDOMAIN}"
print(f"I would change the email of {student['cn']} to {new_mail}.")
# Uncomment to save in LDAP
#writer = LMNStudent(student['cn'])
#writer.setattr(data={'mail': new_mail})
Es gibt noch ein print um zu schauen, was passiert. Um die Änderung zu nehmen muss man die zwei letzte Zeile aktivieren.
Der Skript als UpdateEmail.py speichern und dann mit /opt/linuxmuster/bin/python3 UpdateEmail.py ausführen.
Hallo Holger,
wie dir schon per Mail geschrieben, löst diese Vorgehensweise aber nicht das Problem, dass bei Namensgleichheit innerhalb eines Kurses, 2 gleiche Mailadressen für 2 verschiedene Personen generiert wird.
sophomorix erzeugt beim Anlegen von usern eindeutige Benutzernamen - die bei Namensgleichheit durch anhängen einer Ziffer realisiert wird. D.h. gleiche Vornamen.Nachnamen werden dadurch sicher erkannt. (Denke ich…)
Mein KI-Helfer hat dafü folgende Lösung erzeugt:
def get_trailing_digits(s: str) -> str:
if len(s) >= 2 and s[-1].isdigit() and s[-2].isdigit():
return s[-2:] # letzte und vorletzte Ziffer
if len(s) >= 1 and s[-1].isdigit():
return s[-1] # nur letzte Ziffer
return "" # keine Ziffer am Ende
neu = get_trailing_digits("ABC12") # ergibt "12"
Dann könnte man man den mit Aufruf von get_trailing_digits(student['cn']) einen eindeutigen String erzeugen
Diesen String - der in der Regel leer ist, kann dann an den Nachnamen angehängt werden.
Wenn jetzt noch dieses Skrip so veralgemeinert wird, dass es als sophomorix-hook jedes mal aufgerufen werden kann, dann bräuchte man sich nicht mehr darum kümmern…
Den Kurs könnte man aus sophomorixAdminClass holen.
super Vorschlag. Ich hab jetzt auch mal das script probiert.
Zwei Probleme konnte ich direkt finden:
du nimmst sn und givenname: das geht in email Adressen wegen der möglichen Sonderzeichen nicht. Das habe ich geändert.
es wird VORNAM.NACHNAME.KLASSE@bla generiert, ich brauche aber
VORNAM.NACHNAME.kKLASSE@bla (bachte das kleine K vor dem KLASSE).
Also: peter.lustig.k25@bla
Beides konnte ich „fixen“:
from linuxmusterTools.ldapconnector import LMNLdapReader as lr, LMNStudent
MYCLASS = "25a"
MYDOMAIN = "gym-ka.seminar-bw.de"
students = lr.get(f'/schoolclasses/{MYCLASS}/students')
for student in students:
MYSN = student['sophomorixSurnameASCII'].lower()
MYGIVENNAME = student['sophomorixFirstnameASCII'].lower()
oldmail = student['mail']
new_mail = f"{MYGIVENNAME}.{MYSN}.k{MYCLASS}@{MYDOMAIN}"
print(f"I would change the email of {student['cn']} {student['mail']} to {new_mail}.")
# Uncomment to save in LDAP
#writer = LMNStudent(student['cn'])
#writer.setattr(data={'mail': new_mail})
Nun bleiben zwei Probleme, die ich, als nichtpythonkundiger, nur schwer beheben kann:
Die Klasse ist 25a, in der email soll aber k25 stehen und nicht k25a. Das k hab ich schon drin, jetzt muss das a noch weg…
Hintergrund: ich meine, „damals“ (also vor >15 Jahren) waren Klassennamen ohne Buchstaben (also nur 25) nicht möglich. Vielleicht sind sie es noch immer nicht.
ALso hab ich damals 25a genommen und nicht nur 25. Leider hab ich nicht k25 genommen: dann wäre ich jetzt fein raus.
Kann ich ab nächstem Jahr machen, aber das soll ja für alle Seminare da sein: wir brauchen also Flexibilität, damit wir es an die Gegebenheiten vor Ort anpassen.
das ist schwieriger (denke ich). Bertold will doppelte email ADressenzuverlässig verhindern: hätte ich fast vergessen. Deswegen will er nach Zahlen im cn schauen, da diese auf Namensdopplungen hinweisen. Damit „überkorrigieren“ wir zwar, da ein Peter Lustig in k24 und einer in k25 sein könnte, was die Dopplung verhindert. Sind aber zwei in k25, so hätten wir eine Dopplung. (sorry: ist echt kompliziert)
Man müßte also den strin cn prüfen auf endständige Zahlen und diese Zahl dann in die email Adresse einbauen, so dass der zweite Peter Lustig die email peter.lustig1.k25@bla bekommen würde.
Da bin ich schon weit über mein pythonlatein hinaus: könnte mir da Jemand, der pythonkundig ist, unter die Arme greifen?
Ich fang mal an mcih ein zu lesen: aber ich fürchte, das wird sehr lange dauern …
LG
Holger
PS: für die Jungen Menschen unter uns: Peter Lustig war der Moderator der Kinderwissensserie Löwenzahn vor langer langer Zeit
Hallo Holger,
dein 2. Punkt löst die Funktion get_trailing_digits(student['cn']) - wobei aber wie du schon erwähnt hast die zwei Peter Lustig in den zwei verschiedenen Kursen unnötiger Weise der eine eine ‚1‘ an den Nachnamen angehängt bekommt. Damit könnte man aber leben meine ich.
Der 1. Punkt ließe sich per Skript (wieder aus der KI…) lösen:
def extract_digits(s: str) -> str:
"""
Gibt alle Ziffern im String s als einen zusammenhängenden String zurück.
Beispiel: 'ABC123XY' -> '123'
"""
return ''.join(c for c in s if c.isdigit())
D.h. dein Klassen- bzw. Kursbezeichner wird von allen führenden und folgenden Buchstaben gesäubert. Den String kann man dann nehmen um ihn an die Mailadresse anzuhängen.
Das Problem was aber entsteht ist die fehlende Allgemeingültigkeit - ich habe z.B. Kurse mit Bezeichnern wie ugD25, ugPS25, ugR26 usw.
D.h. in meinem Fall müsste man nur mit s[2:] den führenden Teil abschneiden.
… es wird
Vielen Dank für den Input.
Verstehe ich das richtig, dass du als Code python Code geliefert hast? Kann ich das einfach in Arnauds (und von mir modifiziertes) Script einfügen?
Dann würde ich es mal probieren.
… dein script würde aber auf die Nase Fallen, wenn ein Seminar folgende Kursbezeichnung hätte
k25a-1
(also mehr als nur die Jahreszahlen in der Kursbezeichnung) weil dann 251 draus wird?
Nicht schlimm: muss nur beachtet werden.
Hallo Holger,
wenn die KI nicht gelogen hat, dann sollte das python sein…
Genau - so ist es! Dies allgemeingültigkeit lässt sich aber nur schwer allgemein fassen!
Aus diesem Grund müsste man sich nochmal überlegen ob es nicht doch sinnvoller ist das NICHT als hook in sophomorix zu integrieren, sondern als stand-alone Skript mit Klassen/Kursbezeichnung als Übergabeparameter. Dann müsste man aber immer daran denken das Skript aufzurufen…
also ein Aufruf des scripts mit
get_trailing_digits(student[‚cn‘])
gibt zurück:
Traceback (most recent call last):
File "/root/mailscripte/testing.py", line 13, in <module>
number = get_trailing_digits(student['cn'])
^^^^^^^^^^^^^^^^^^^
NameError: name 'get_trailing_digits' is not defined
diese Funktion ist also anscheinend bei unserem python nicht dabei …
Macht aber nix, wenn ich die Funktion extract_digits() zum laufen bekomme: denn eins ist sicher: im Loginnamen befinden sich nur die Nummern, die sophomorix da rein gemacht hat (wer hat schon eine Zahl im Namen?):
Ich schreibe also in den Kopf der Datei:
def extract_digits(s: str) -> str:
return ''.join(c for c in s if c.isdigit())
Mein ganzes Ding sieht dann so aus:
from linuxmusterTools.ldapconnector import LMNLdapReader as lr, LMNStudent
def extract_digits(s: str) -> str:
return ''.join(c for c in s if c.isdigit())
MYCLASS = "25a"
MYJEAR = "25"
MYDOMAIN = "gym-ka.seminar-bw.de"
students = lr.get(f'/schoolclasses/{MYCLASS}/students')
for student in students:
MYSN = student['sophomorixSurnameASCII'].lower()
MYGIVENNAME = student['sophomorixFirstnameASCII'].lower()
oldmail = student['mail']
new_mail = f"{MYGIVENNAME}.{MYSN}.k{MYJEAR}@{MYDOMAIN}"
print(f"I would change the email of {student['cn']} {student['mail']} to {new_mail}.")
# Uncomment to save in LDAP
#writer = LMNStudent(student['cn'])
#writer.setattr(data={'mail': new_mail})
hier hab ich auch das „Klassenanme“ und „Kursname“ Problem gelößt: man muss ja sowiso den Kursnamen in der lmn oben in das script eintippen: dann soll man einfach noch das Jahr reintippen: dann brauchen wir es nicht extrahieren.
Also: fast da: nur noch herausbekommen, wie ich die Funktion auch nutzen kann (die Definition der selben wird schon mal nicht moniert).
ich habs schon faßt: aber ich kann halt echt nicht programmieren.
Da ich keinen Ref mit Nummer habe, hab ich mir die Variable „studentnumber“ belegt und lasse die einfach bei allen „reinmischen“.
Das käme später dann weg.
Mein script sieht so aus:
from linuxmusterTools.ldapconnector import LMNLdapReader as lr, LMNStudent
studentnumber = "deppchef2"
MYCLASS = "25a"
MYJEAR = "25"
MYDOMAIN = "gym-ka.seminar-bw.de"
students = lr.get(f'/schoolclasses/{MYCLASS}/students')
for student in students:
MYSN = student['sophomorixSurnameASCII'].lower()
MYGIVENNAME = student['sophomorixFirstnameASCII'].lower()
oldmail = student['mail']
# number = [int(s) for s in studentnumber if s.isdigit()]
number = [int(''.join(filter(str.isdigit, studentnumber)))]
new_mail = f"{MYGIVENNAME}.{MYSN}{number}.k{MYJEAR}@{MYDOMAIN}"
print(f"_{number}_ change the email of {student['cn']} {student['mail']} to {new_mail}.")
aber die Ausgabe ist z.B.: [2] change the email of lustigpe [‚peter.lustig@gym-ka.seminar-bw.de‘] to peter.lustig[2].k25@gym-ka.seminar-bw.de.
Es paßt alles, aber er macht mir um das Ausgeben der Variable immer , also [2] statt 2
Das komische ist: er macht das bei der Ausgabe von student[„mail“] ja auch, aber bei der Ausgabe von student[„cn“] nicht. Ich nehme an, dass das unterschiedliche Variablenarten sind und daher das unterschiedliche Verhalten kommt. Am Aufruf kann ich keinen UNterschied erkennen.
Scheint so eine Spezialsache von python zu sein, die ich nicht kenne (ich kenne ja python garnicht ).
hm – eigentlich ist sowas wie x = int("123") bei Python möglich.
Aber ich habe den Verdacht, es liegt daran, dass das filter ein Array zurückgibt. Vielleicht klappt es, wenn Du number[0] nimmst? Du kannst es auch mal mit studentnumber = "de3p65pchef2" testen, dann müsste bei number [3, 65, 2] ausgegeben werden.
… klappt noch nciht.
Wenn ich von studentnumber auf student zurückdrehe, dann wirft es einen Fehler.
Anscheinend hat die Variable student, welches ja die Laufwariable der Schleife ist, nicht das richtige Format für die Funktion int()
/opt/linuxmuster/bin/python mailscript-seminar-k25.sh
Traceback (most recent call last):
File "/root/mailscripte/mailscript-seminar-k25.sh", line 14, in <module>
number = int(''.join(filter(str.isdigit, student)))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: invalid literal for int() with base 10: ''
Das gesammte Script sieht gerade so aus:
from linuxmusterTools.ldapconnector import LMNLdapReader as lr, LMNStudent
MYCLASS = "25a"
MYJEAR = "25"
MYDOMAIN = "gym-ka.seminar-bw.de"
students = lr.get(f'/schoolclasses/{MYCLASS}/students')
for student in students:
MYSN = student['sophomorixSurnameASCII'].lower()
MYGIVENNAME = student['sophomorixFirstnameASCII'].lower()
oldmail = student['mail']
number = int(''.join(filter(str.isdigit, student)))
new_mail = f"{MYGIVENNAME}.{MYSN}{number}.k{MYJEAR}@{MYDOMAIN}"
print(f"_{number}_ change the email of {student['cn']} {student['mail'][0]} to {new_mail}.")