4.5 KiB
4.5 KiB
TeamPulse — Design-Dokument
Datum: 2026-05-16
Status: Zur Implementierung freigegeben
Ziel
Ein Python-Script, das den Chat eines laufenden Microsoft Teams-Meetings überwacht, alle Personen erfasst, die in einem definierten Zeitfenster eine Nachricht gepostet haben, und ein Memo mit Name und E-Mail-Adresse der Teilnehmer erzeugt.
Ausgangslage: Nutzer ohne Admin-Rechte, kein Zugriff auf Microsoft Graph API / Azure AD App-Registrierung.
Architektur
main.py
├── auth.py — Playwright-Session verwalten (Login, Persistenz)
├── monitor.py — Teams-Chat pollen, Trigger erkennen, Nachrichten sammeln
├── resolver.py — Sender-Name → E-Mail via Profilkarte (mit lokalem Cache)
└── memo.py — Markdown-Memo erzeugen und speichern
Komponenten
auth.py
- Startet Playwright mit persistentem User-Data-Verzeichnis (
~/.teampulse/session) - Beim ersten Start: sichtbares Browser-Fenster für manuellen SSO/MFA-Login
- Bei bekannter Session: headless, unsichtbar im Hintergrund
- Erkennt Session-Ablauf (Login-Redirect) und öffnet Browser-Fenster zur Re-Authentifizierung
- Liest beim Start den Display-Namen des eingeloggten Nutzers aus → wird als „Moderator" gespeichert
monitor.py
- Öffnet Teams Web im Hintergrund-Browser
- Nutzer navigiert einmalig manuell zur Meeting-Chat-URL
- Pollt den Chat-DOM alle ~2 Sekunden auf neue Nachrichten
- Erkennt Trigger-Befehle (nur wenn gepostet vom eingeloggten Nutzer):
!start "Name des Vortragenden"→ startet Zeitfenster, speichert Vortragendenname!stop→ beendet Zeitfenster
- Fallback: Enter-Taste in der Konsole als alternativer Trigger
- Sammelt während des Zeitfensters:
{ sender: str, timestamp: str } - Reconnect-Logik bei Seitenreload oder Verbindungsverlust (gesammelte Daten bleiben erhalten)
resolver.py
- Iteriert nach
!stopüber alle eindeutigen Sender - Prüft
~/.teampulse/cache.json— bekannte Namen werden nicht erneut aufgelöst - Für unbekannte Sender: klickt Profilkarte im Teams-Web → extrahiert E-Mail
- Fehlerbehandlung:
- Profilkarte nicht ladbar →
<nicht auflösbar> - Externer Gast → als Gast markieren:
<gast@extern.com>oder<externer Gast>
- Profilkarte nicht ladbar →
- Cache wird bei jedem neuen Eintrag sofort geschrieben
memo.py
- Filtert Vortragenden und Moderator aus der Teilnehmerliste
- Sortiert verbleibende Einträge nach E-Mail-Adresse
- Erzeugt Markdown-Ausgabe (siehe Format unten)
- Speichert Datei als
audit_YYYYMMDD_HHMM.mdim aktuellen Verzeichnis - Gibt Inhalt zusätzlich in der Konsole aus
Trigger-Verhalten
| Aktion | Chat-Befehl | Konsole |
|---|---|---|
| Zeitfenster starten | !start "Anna Bauer" |
Enter drücken |
| Zeitfenster beenden | !stop |
Enter drücken |
- Nur Befehle vom eingeloggten Nutzer werden als Trigger akzeptiert
!startohne Anführungszeichen oder ohne Namen → Warnung, Zeitfenster startet mit Platzhalter „Unbekannter Vortragender"- Mehrfaches
!startohne!stop→ zweites!startüberschreibt das erste (kein Fehler)
Ausgabeformat
# Meeting Chat Audit
Zeitfenster: 10:03:42 – 10:47:15
## Teilnehmer am Vortrag von Anna Bauer (4)
_Moderator: Oliver Hofmann — Vortragender und Moderator ausgeschlossen_
- Klaus Huber <k.huber@company.com>
- Max Mustermann <m.mustermann@company.com>
- Sandra Vogel <s.vogel@company.com>
- Thomas Wolf <t.wolf@company.com>
_Sortiert nach E-Mail-Adresse. Erstellt: 2026-05-16 10:51_
- Keine Nachrichten im Zeitfenster → Hinweis „Keine Chat-Aktivität in diesem Zeitfenster"
- Nicht auflösbare E-Mails → Eintrag trotzdem aufgeführt, E-Mail als
<nicht auflösbar>
Technologie-Stack
| Komponente | Wahl |
|---|---|
| Sprache | Python 3.12 (.venv) |
| Browser-Automation | Playwright (sync API) |
| Cache | JSON-Datei (~/.teampulse/cache.json) |
| Ausgabe | Markdown |
| Plattform | Mac, Windows, Linux |
Randfälle
| Situation | Verhalten |
|---|---|
| Session abgelaufen | Sichtbarer Browser für Re-Auth, danach wieder headless |
| Profilkarte nicht ladbar | <nicht auflösbar>, kein Absturz |
| Externer Gast | Als Gast markiert |
!start ohne Namen |
Warnung + Platzhalter |
!start von anderem Nutzer |
Ignoriert |
| Seitenreload während Monitoring | Automatischer Reconnect, keine Datenverlust |
| Keine Nachrichten im Fenster | Memo mit entsprechendem Hinweis |
Nicht im Scope
- Graph API / Azure AD Integration
- GUI / Web-Dashboard
- Mehrere gleichzeitige Zeitfenster
- Historische Chat-Auswertung (vergangene Meetings)