diff --git a/lib/pangea/bot/utils/bot_room_extension.dart b/lib/pangea/bot/utils/bot_room_extension.dart index b658235ed..830ca6a84 100644 --- a/lib/pangea/bot/utils/bot_room_extension.dart +++ b/lib/pangea/bot/utils/bot_room_extension.dart @@ -3,6 +3,7 @@ import 'package:matrix/matrix.dart'; import 'package:fluffychat/pangea/bot/utils/bot_name.dart'; import 'package:fluffychat/pangea/chat_settings/constants/bot_mode.dart'; import 'package:fluffychat/pangea/chat_settings/models/bot_options_model.dart'; +import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart'; extension BotRoomExtension on Room { @@ -23,11 +24,40 @@ extension BotRoomExtension on Room { return BotOptionsModel.fromJson(stateEvent.content); } - Future setBotOptions(BotOptionsModel options) => - client.setRoomStateWithKey( - id, - PangeaEventTypes.botOptions, - '', - options.toJson(), - ); + Future setBotOptions(BotOptionsModel options) async { + const maxRetries = 3; + Duration retryDelay = const Duration(seconds: 5); + + for (int attempt = 1; attempt <= maxRetries; attempt++) { + try { + if (attempt > 1) { + await Future.delayed(retryDelay); + retryDelay *= 2; + } + + await client.setRoomStateWithKey( + id, + PangeaEventTypes.botOptions, + '', + options.toJson(), + ); + + return; + } catch (e, s) { + ErrorHandler.logError( + e: e, + s: s, + data: { + 'roomId': id, + 'options': options.toJson(), + 'attempt': attempt, + }, + ); + + if (attempt == maxRetries) { + rethrow; + } + } + } + } } diff --git a/lib/pangea/chat_settings/utils/bot_client_extension.dart b/lib/pangea/chat_settings/utils/bot_client_extension.dart index 5021d19ed..69c9b84cc 100644 --- a/lib/pangea/chat_settings/utils/bot_client_extension.dart +++ b/lib/pangea/chat_settings/utils/bot_client_extension.dart @@ -1,11 +1,13 @@ import 'package:collection/collection.dart'; import 'package:matrix/matrix.dart'; +import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart'; import 'package:fluffychat/pangea/bot/utils/bot_name.dart'; import 'package:fluffychat/pangea/bot/utils/bot_room_extension.dart'; import 'package:fluffychat/pangea/chat/constants/default_power_level.dart'; import 'package:fluffychat/pangea/chat_settings/constants/bot_mode.dart'; import 'package:fluffychat/pangea/chat_settings/models/bot_options_model.dart'; +import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/user/user_model.dart'; import 'package:fluffychat/widgets/matrix.dart'; @@ -15,10 +17,15 @@ extension BotClientExtension on Client { Room? get botDM => rooms.firstWhereOrNull((r) => r.isBotDM); // All 2-member rooms with the bot - List get targetBotChats => rooms.where((r) { - if (r.isBotDM) return true; - if (r.summary.mJoinedMemberCount != 2) return false; - return r.getParticipants().any((u) => u.id == BotName.byEnvironment); + List get _targetBotChats => rooms.where((r) { + return + // bot settings exist + r.botOptions != null && + // there is no activity plan + r.activityPlan == null && + // it's just the bot and one other user in the room + r.summary.mJoinedMemberCount == 2 && + r.getParticipants().any((u) => u.id == BotName.byEnvironment); }).toList(); Future startChatWithBot() => startDirectChat( @@ -42,30 +49,41 @@ extension BotClientExtension on Client { ); Future updateBotOptions(UserSettings userSettings) async { - final rooms = targetBotChats; - if (rooms.isEmpty) return; + final targetBotRooms = [..._targetBotChats]; + if (targetBotRooms.isEmpty) return; - final futures = []; - for (final room in rooms) { - final botOptions = room.botOptions ?? const BotOptionsModel(); - final targetLanguage = userSettings.targetLanguage; - final languageLevel = userSettings.cefrLevel; - final voice = userSettings.voice; + try { + final futures = []; + for (final targetBotRoom in targetBotRooms) { + final botOptions = targetBotRoom.botOptions ?? const BotOptionsModel(); + final targetLanguage = userSettings.targetLanguage; + final languageLevel = userSettings.cefrLevel; + final voice = userSettings.voice; - if (botOptions.targetLanguage == targetLanguage && - botOptions.languageLevel == languageLevel && - botOptions.targetVoice == voice) { - continue; + if (botOptions.targetLanguage == targetLanguage && + botOptions.languageLevel == languageLevel && + botOptions.targetVoice == voice) { + continue; + } + + final updated = botOptions.copyWith( + targetLanguage: targetLanguage, + languageLevel: languageLevel, + targetVoice: voice, + ); + futures.add(targetBotRoom.setBotOptions(updated)); } - final updated = botOptions.copyWith( - targetLanguage: targetLanguage, - languageLevel: languageLevel, - targetVoice: voice, + await Future.wait(futures); + } catch (e, s) { + ErrorHandler.logError( + e: e, + s: s, + data: { + 'userSettings': userSettings.toJson(), + 'targetBotRooms': targetBotRooms.map((r) => r.id).toList(), + }, ); - futures.add(room.setBotOptions(updated)); } - - await Future.wait(futures); } }