133 lines
4.5 KiB
Markdown
133 lines
4.5 KiB
Markdown
# 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>`
|
||
- 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.md` im 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
|
||
- `!start` ohne Anführungszeichen oder ohne Namen → Warnung, Zeitfenster startet mit Platzhalter „Unbekannter Vortragender"
|
||
- Mehrfaches `!start` ohne `!stop` → zweites `!start` überschreibt das erste (kein Fehler)
|
||
|
||
---
|
||
|
||
## Ausgabeformat
|
||
|
||
```markdown
|
||
# 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.11+ |
|
||
| 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)
|