# Anrufmonitor SIP-Client (Windows, .NET/C# Tray-App), der eingehende Anrufe passiv mitliest und automatisch den passenden Kontakt aus Office 365, Google Contacts oder einem öffentlichen Verzeichnis anzeigt. ## Funktionsweise - **SIP:** registriert sich bei der Telefonanlage/dem Provider und liest eingehende `INVITE`-Requests passiv mit (Anrufer-Rufnummer). Es wird **nie** `Answer()` aufgerufen – der Client nimmt den Anruf nicht an, sondern zeigt nur an, wer anruft. Voraussetzung: die Telefonanlage forkt eingehende Anrufe an mehrere registrierte Geräte/Kontakte derselben Nebenstelle. - **Kontakte:** werden periodisch im Hintergrund aus Office 365 (Microsoft Graph) und Google Contacts (People API) in einen lokalen SQLite-Cache synchronisiert. Beim eingehenden Anruf wird **nur der Cache** abgefragt (schnell, keine Live-API-Calls während des Anrufs). Ist die Nummer unbekannt, kann optional ein öffentliches Verzeichnis per On-Demand-Reverse-Lookup gefragt werden (Ergebnis wird ebenfalls gecacht). - **UI:** Tray-Icon, Popup unten rechts mit Name/Firma/Nummer bei eingehendem Anruf. ## Projektstruktur ``` src/ Anrufmonitor.App/ WPF-Tray-App (Einstiegspunkt, appsettings.json) Anrufmonitor.Sip/ Passiver SIP-Monitor (SIPSorcery) Anrufmonitor.Contacts/ Kontakt-Provider, SQLite-Cache, Lookup-Service tests/ Anrufmonitor.Tests/ xUnit-Tests ``` ## Bauen & Starten ```powershell dotnet build Anrufmonitor.slnx dotnet test tests\Anrufmonitor.Tests\Anrufmonitor.Tests.csproj dotnet run --project src\Anrufmonitor.App\Anrufmonitor.App.csproj ``` ## Autostart (Windows) ```powershell .\scripts\setup-autostart.ps1 ``` Baut eine Release-Version und legt eine Verknuepfung im Windows-Autostart-Ordner an (`shell:startup`). Idempotent, kann nach jedem Update erneut ausgefuehrt werden. ## Konfiguration `src\Anrufmonitor.App\appsettings.json` enthält nur die Struktur (keine Secrets, wird committet). Für echte Werte `appsettings.Local.json.example` nach `appsettings.Local.json` kopieren (liegt in `.gitignore`, wird beim Build automatisch mitkopiert falls vorhanden) und ausfüllen: - **Sip:** Server, Username, Password der Telefonanlage. - **Contacts:Office365Accounts:** Liste von Office365/Outlook-Accounts (Firmen-Tenant und/oder outlook.com/persoenliche Konten koennen parallel laufen). Pro Account: App-Registration in Azure/Entra (Typ *Public client*, Delegated Permission `Contacts.Read`), `Name`/`TenantId`/`ClientId` eintragen. Fuer outlook.com: `TenantId: "common"` oder `"consumers"`, und die App-Registration muss unter Authentifizierung -> Unterstuetzte Kontotypen auch persoenliche Microsoft-Konten erlauben. Anmeldung per Device-Code-Flow (Code wird per Tray-Benachrichtigung und im Log angezeigt, unter microsoft.com/devicelogin eingeben). Login und Kontakt-Cache sind pro Account getrennt. - **Contacts:Google:** OAuth-Client (Typ *Desktop app*) in der Google Cloud Console, People API aktivieren, `ClientId`/`ClientSecret` eintragen. Anmeldung per Browser-Login beim ersten Sync, Token wird danach lokal zwischengespeichert. - **Contacts:PublicDirectory:** optional, generisches URL-Template (`{number}` wird ersetzt) für ein öffentliches Verzeichnis – muss je nach Anbieter angepasst werden (`PublicDirectoryLookupProvider.ExtractDisplayName`). ## Sicherheit **Public Repo** – niemals Zugangsdaten, Tokens, Client-Secrets oder SIP-Passwörter committen. Konfiguration ausschließlich über `appsettings.Local.json` (gitignored) oder Umgebungsvariablen. ## Lizenz TBD