74 lines
3.6 KiB
C#
74 lines
3.6 KiB
C#
using System.Net;
|
|
using System.Net.Http.Json;
|
|
using System.Text.Json;
|
|
using LehrerApp.Core.Models;
|
|
|
|
namespace LehrerApp.Desktop.Services;
|
|
|
|
public sealed class SchoolWeatherException(string message) : Exception(message);
|
|
|
|
/// <summary>Client für das serverseitige Schulstandort-/Wetterprofil. Liest URL und Token je
|
|
/// Aufruf, damit ein Login oder Serverwechsel in den Einstellungen sofort berücksichtigt wird.</summary>
|
|
public sealed class SchoolWeatherService(HttpClient http, SyncSettingsService syncSettings)
|
|
{
|
|
public bool IsAvailable => !string.IsNullOrWhiteSpace(syncSettings.ServerUrl) && syncSettings.IsLoggedIn;
|
|
|
|
public async Task<SchoolLocationProfile?> GetLocationAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
using var response = await SendAsync(HttpMethod.Get, "/api/school/location", null, cancellationToken);
|
|
if (response.StatusCode == HttpStatusCode.NotFound) return null;
|
|
await EnsureSuccessAsync(response);
|
|
return await response.Content.ReadFromJsonAsync<SchoolLocationProfile>(cancellationToken);
|
|
}
|
|
|
|
public async Task<SchoolLocationProfile> SaveLocationAsync(SchoolLocationRequest location,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
using var response = await SendAsync(HttpMethod.Put, "/api/school/location", location, cancellationToken);
|
|
await EnsureSuccessAsync(response);
|
|
return await response.Content.ReadFromJsonAsync<SchoolLocationProfile>(cancellationToken)
|
|
?? throw new SchoolWeatherException("Der Server hat keine Standortdaten zurückgegeben.");
|
|
}
|
|
|
|
public async Task<WeatherSnapshot?> GetWeatherAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
using var response = await SendAsync(HttpMethod.Get, "/api/school/weather", null, cancellationToken);
|
|
if (response.StatusCode == HttpStatusCode.NotFound) return null;
|
|
await EnsureSuccessAsync(response);
|
|
return await response.Content.ReadFromJsonAsync<WeatherSnapshot>(cancellationToken);
|
|
}
|
|
|
|
private async Task<HttpResponseMessage> SendAsync(HttpMethod method, string path, object? body,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(syncSettings.ServerUrl) || !syncSettings.IsLoggedIn)
|
|
throw new SchoolWeatherException("Bitte zuerst im Reiter „Synchronisation“ am Server anmelden.");
|
|
using var request = new HttpRequestMessage(method, new Uri(new Uri(syncSettings.ServerUrl), path));
|
|
var token = syncSettings.GetToken();
|
|
if (token is not null)
|
|
request.Headers.Authorization = new("Bearer", token);
|
|
if (body is not null) request.Content = JsonContent.Create(body);
|
|
try { return await http.SendAsync(request, cancellationToken); }
|
|
catch (HttpRequestException)
|
|
{
|
|
throw new SchoolWeatherException("Der LehrerApp-Server ist nicht erreichbar.");
|
|
}
|
|
}
|
|
|
|
private static async Task EnsureSuccessAsync(HttpResponseMessage response)
|
|
{
|
|
if (response.IsSuccessStatusCode) return;
|
|
if (response.StatusCode == HttpStatusCode.Unauthorized)
|
|
throw new SchoolWeatherException("Die Server-Anmeldung ist abgelaufen. Bitte erneut anmelden.");
|
|
try
|
|
{
|
|
using var document = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
|
|
if (document.RootElement.TryGetProperty("detail", out var detail) &&
|
|
!string.IsNullOrWhiteSpace(detail.GetString()))
|
|
throw new SchoolWeatherException(detail.GetString()!);
|
|
}
|
|
catch (JsonException) { }
|
|
throw new SchoolWeatherException("Der Schulstandort konnte nicht gespeichert werden.");
|
|
}
|
|
}
|