Untis API Integration
This commit is contained in:
@@ -287,7 +287,10 @@ public sealed class WebUntisClient : IAsyncDisposable
|
||||
client = configuration.Client,
|
||||
}, null, cancellationToken);
|
||||
_sessionId = OptionalString(result, "sessionId")
|
||||
?? throw new WebUntisException("WebUntis-Login fehlgeschlagen: Keine sessionId erhalten.");
|
||||
?? throw new WebUntisException(
|
||||
$"WebUntis-Login fehlgeschlagen: {configuration.Host} hat für die Schulkennung " +
|
||||
$"„{configuration.School}“ keine Sitzung geliefert. Bitte insbesondere Server und " +
|
||||
"Schulkennung mit der WebUntis-Anmeldeseite vergleichen.");
|
||||
}
|
||||
|
||||
_activeRequests++;
|
||||
@@ -499,24 +502,71 @@ public sealed class WebUntisClient : IAsyncDisposable
|
||||
{
|
||||
var schoolValue = _options.School.Trim();
|
||||
var username = _options.Username.Trim();
|
||||
var password = _options.Password.Trim();
|
||||
// Passwörter dürfen führende/abschließende Leerzeichen enthalten und werden deshalb
|
||||
// anders als Schule/Benutzername nicht normalisiert.
|
||||
var password = _options.Password;
|
||||
if (schoolValue.Length == 0) throw new WebUntisConfigurationException("WEBUNTIS_SCHOOL fehlt.");
|
||||
if (username.Length == 0) throw new WebUntisConfigurationException("WEBUNTIS_USER fehlt.");
|
||||
if (password.Length == 0) throw new WebUntisConfigurationException("WEBUNTIS_PASSWORD fehlt.");
|
||||
|
||||
var cleaned = schoolValue.Replace("https://", "", StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("http://", "", StringComparison.OrdinalIgnoreCase).Split('/')[0];
|
||||
var school = cleaned.Contains('.') ? cleaned.Split('.')[0] : cleaned;
|
||||
var host = string.IsNullOrWhiteSpace(_options.Host)
|
||||
? (cleaned.Contains('.') ? cleaned : $"{school}.webuntis.com")
|
||||
: _options.Host.Trim().Replace("https://", "", StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("http://", "", StringComparison.OrdinalIgnoreCase).TrimEnd('/');
|
||||
if (host.Contains('/') || !Uri.CheckHostName(host).Equals(UriHostNameType.Dns))
|
||||
var (school, host) = ResolveLocation(schoolValue, _options.Host);
|
||||
if (host.Contains('/') || !Uri.CheckHostName(host).Equals(UriHostNameType.Dns) ||
|
||||
!(host.Equals("webuntis.com", StringComparison.OrdinalIgnoreCase) ||
|
||||
host.EndsWith(".webuntis.com", StringComparison.OrdinalIgnoreCase)))
|
||||
throw new WebUntisConfigurationException("WEBUNTIS_HOST ist ungültig.");
|
||||
return new Config(school, host, username, password,
|
||||
string.IsNullOrWhiteSpace(_options.Client) ? "LehrerApp" : _options.Client.Trim());
|
||||
}
|
||||
|
||||
private static (string School, string Host) ResolveLocation(string schoolValue, string? hostValue)
|
||||
{
|
||||
var school = schoolValue.Trim();
|
||||
string? hostFromSchool = null;
|
||||
if (LooksLikeLocation(school) && TryParseLocation(school, out var schoolLocation))
|
||||
{
|
||||
hostFromSchool = schoolLocation.Host;
|
||||
school = QueryHelpers.ParseQuery(schoolLocation.Query).TryGetValue("school", out var querySchool) &&
|
||||
!string.IsNullOrWhiteSpace(querySchool)
|
||||
? querySchool.ToString().Trim()
|
||||
: schoolLocation.Host.Split('.')[0];
|
||||
}
|
||||
|
||||
string host;
|
||||
if (!string.IsNullOrWhiteSpace(hostValue))
|
||||
{
|
||||
if (!TryParseLocation(hostValue, out var hostLocation))
|
||||
throw new WebUntisConfigurationException("WEBUNTIS_HOST ist ungültig.");
|
||||
host = hostLocation.Host;
|
||||
// Komfortfall: In das Serverfeld wurde die vollständige Login-URL kopiert. Eine
|
||||
// explizit im Schulfeld angegebene Kennung behält trotzdem Vorrang.
|
||||
if (LooksLikeLocation(schoolValue) &&
|
||||
QueryHelpers.ParseQuery(hostLocation.Query).TryGetValue("school", out var querySchool) &&
|
||||
!string.IsNullOrWhiteSpace(querySchool))
|
||||
school = querySchool.ToString().Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
host = hostFromSchool ?? $"{school}.webuntis.com";
|
||||
}
|
||||
|
||||
if (school.Length == 0)
|
||||
throw new WebUntisConfigurationException("WEBUNTIS_SCHOOL fehlt oder ist ungültig.");
|
||||
return (school, host);
|
||||
}
|
||||
|
||||
private static bool LooksLikeLocation(string value) => value.Contains('.') || value.Contains('/') ||
|
||||
value.StartsWith("http:", StringComparison.OrdinalIgnoreCase) ||
|
||||
value.StartsWith("https:", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
private static bool TryParseLocation(string value, out Uri location)
|
||||
{
|
||||
var candidate = value.Trim();
|
||||
if (!candidate.StartsWith("http://", StringComparison.OrdinalIgnoreCase) &&
|
||||
!candidate.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
|
||||
candidate = $"https://{candidate}";
|
||||
return Uri.TryCreate(candidate, UriKind.Absolute, out location!) && !string.IsNullOrWhiteSpace(location.Host);
|
||||
}
|
||||
|
||||
private string SchoolCookie() => Convert.ToBase64String(Encoding.UTF8.GetBytes(GetConfiguration().School));
|
||||
|
||||
private static async Task<JsonElement> ReadJsonAsync(HttpResponseMessage response, CancellationToken token) =>
|
||||
|
||||
Reference in New Issue
Block a user