70 lines
2.3 KiB
Dart
70 lines
2.3 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:http/http.dart' as http;
|
|
|
|
import '../../../errors/network_exception.dart';
|
|
import '../../../errors/server_exception.dart';
|
|
import '../../nextcloud_ocs.dart';
|
|
import 'get_chat_params.dart';
|
|
import 'get_chat_response.dart';
|
|
|
|
/// Long-poll variant of GetChat (`lookIntoFuture=1`). Bypasses [TalkApi]
|
|
/// because that layer treats non-2xx as errors, and we need 304 to be a
|
|
/// normal "no new messages" outcome. `setReadMarker=on` lets the server
|
|
/// move the read cursor whenever the call returns messages.
|
|
class LongPollChat {
|
|
final String chatToken;
|
|
final int lastKnownMessageId;
|
|
final int timeoutSeconds;
|
|
|
|
LongPollChat({
|
|
required this.chatToken,
|
|
required this.lastKnownMessageId,
|
|
this.timeoutSeconds = 30,
|
|
});
|
|
|
|
/// Returns the response, or `null` on HTTP 304 (server timeout, nothing new).
|
|
Future<GetChatResponse?> run() async {
|
|
final params = GetChatParams(
|
|
lookIntoFuture: GetChatParamsSwitch.on,
|
|
timeout: timeoutSeconds,
|
|
lastKnownMessageId: lastKnownMessageId,
|
|
includeLastKnown: GetChatParamsSwitch.off,
|
|
setReadMarker: GetChatParamsSwitch.on,
|
|
limit: 100,
|
|
);
|
|
final uri = NextcloudOcs.uri(
|
|
'apps/spreed/api/v1/chat/$chatToken',
|
|
queryParameters: params.toJson(),
|
|
);
|
|
final headers = NextcloudOcs.headers();
|
|
|
|
final http.Response response;
|
|
try {
|
|
response = await http
|
|
.get(uri, headers: headers)
|
|
.timeout(Duration(seconds: timeoutSeconds + 15));
|
|
} on TimeoutException catch (e) {
|
|
throw NetworkException.timeout(technicalDetails: 'LongPollChat $uri: $e');
|
|
} on SocketException catch (e) {
|
|
throw NetworkException(technicalDetails: 'LongPollChat $uri: ${e.message}');
|
|
} on http.ClientException catch (e) {
|
|
throw NetworkException(technicalDetails: 'LongPollChat $uri: ${e.message}');
|
|
}
|
|
|
|
final status = response.statusCode;
|
|
if (status == 304) return null;
|
|
if (status >= 200 && status < 300) {
|
|
final decoded = jsonDecode(response.body) as Map<String, dynamic>;
|
|
return GetChatResponse.fromJson(decoded['ocs'] as Map<String, dynamic>)
|
|
..headers = response.headers;
|
|
}
|
|
throw ServerException(
|
|
statusCode: status,
|
|
technicalDetails: 'LongPollChat $uri: HTTP $status',
|
|
);
|
|
}
|
|
}
|