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 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; return GetChatResponse.fromJson(decoded['ocs'] as Map) ..headers = response.headers; } throw ServerException( statusCode: status, technicalDetails: 'LongPollChat $uri: HTTP $status', ); } }