Wetterdienst
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
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.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user