Files
Client/lib/api/webuntis/webuntis_api.dart
T
2026-05-08 20:12:40 +02:00

100 lines
2.8 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
import '../../model/endpoint_data.dart';
import '../api_params.dart';
import '../api_request.dart';
import '../api_response.dart';
import '../errors/network_exception.dart';
import '../errors/parse_exception.dart';
import 'queries/authenticate/authenticate.dart';
import 'webuntis_error.dart';
abstract class WebuntisApi extends ApiRequest {
Uri endpoint = Uri.parse(
'https://${EndpointData().webuntis().full()}/WebUntis/jsonrpc.do?school=marianum-fulda',
);
String method;
ApiParams? genericParam;
http.Response? response;
bool authenticatedResponse;
WebuntisApi(
this.method,
this.genericParam, {
this.authenticatedResponse = true,
});
Future<String> query(WebuntisApi untis, {bool retry = false}) async {
final body =
'{"id":"ID","method":"$method","params":${untis._body()},"jsonrpc":"2.0"}';
var sessionId = '0';
if (authenticatedResponse) {
sessionId = (await Authenticate.getSession()).sessionId;
}
final data = await post(body, {'Cookie': 'JSESSIONID=$sessionId'});
response = data;
final Map<String, dynamic> jsonData;
try {
jsonData = jsonDecode(data.body) as Map<String, dynamic>;
} on FormatException catch (e) {
throw ParseException(
technicalDetails: 'WebUntis JSON decode: ${e.message}',
);
}
final error = jsonData['error'] as Map<String, dynamic>?;
if (error != null) {
final code = error['code'] as int;
if (code == -8520) {
if (retry) {
throw WebuntisError(
'Authentication was tried (probably session timeout), but was not successful!',
-8520,
);
}
await Authenticate.createSession();
return query(untis, retry: true);
} else {
throw WebuntisError(error['message'] as String, code);
}
}
return data.body;
}
T finalize<T extends ApiResponse>(T response) {
response.rawResponse = this.response!;
return response;
}
Future<ApiResponse> run();
String _body() => genericParam == null ? '{}' : jsonEncode(genericParam);
Future<http.Response> post(String data, Map<String, String>? headers) async {
try {
return await http
.post(endpoint, body: data, headers: headers)
.timeout(
const Duration(seconds: 10),
onTimeout: () => throw NetworkException.timeout(
technicalDetails: 'WebUntis $method timed out after 10s',
),
);
} on SocketException catch (e) {
throw NetworkException(
technicalDetails: 'WebUntis $method: ${e.message}',
);
} on http.ClientException catch (e) {
throw NetworkException(
technicalDetails: 'WebUntis $method: ${e.message}',
);
}
}
}