79 lines
2.6 KiB
Dart
79 lines
2.6 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}');
|
|
}
|
|
}
|
|
}
|