You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
296 lines
9.8 KiB
Dart
296 lines
9.8 KiB
Dart
import 'dart:developer';
|
|
import 'dart:math';
|
|
|
|
import 'package:fluffychat/pangea/constants/class_default_values.dart';
|
|
import 'package:fluffychat/pangea/constants/pangea_event_types.dart';
|
|
import 'package:fluffychat/pangea/controllers/class_controller.dart';
|
|
import 'package:fluffychat/pangea/controllers/contextual_definition_controller.dart';
|
|
import 'package:fluffychat/pangea/controllers/language_controller.dart';
|
|
import 'package:fluffychat/pangea/controllers/language_list_controller.dart';
|
|
import 'package:fluffychat/pangea/controllers/local_settings.dart';
|
|
import 'package:fluffychat/pangea/controllers/message_data_controller.dart';
|
|
import 'package:fluffychat/pangea/controllers/my_analytics_controller.dart';
|
|
import 'package:fluffychat/pangea/controllers/permissions_controller.dart';
|
|
import 'package:fluffychat/pangea/controllers/subscription_controller.dart';
|
|
import 'package:fluffychat/pangea/controllers/text_to_speech_controller.dart';
|
|
import 'package:fluffychat/pangea/controllers/user_controller.dart';
|
|
import 'package:fluffychat/pangea/controllers/word_net_controller.dart';
|
|
import 'package:fluffychat/pangea/extensions/client_extension.dart';
|
|
import 'package:fluffychat/pangea/guard/p_vguard.dart';
|
|
import 'package:fluffychat/pangea/utils/bot_name.dart';
|
|
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
|
import 'package:fluffychat/pangea/utils/instructions.dart';
|
|
import 'package:fluffychat/widgets/matrix.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:matrix/matrix.dart';
|
|
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
|
|
import '../../config/app_config.dart';
|
|
import '../utils/firebase_analytics.dart';
|
|
import '../utils/p_store.dart';
|
|
import 'it_feedback_controller.dart';
|
|
import 'message_analytics_controller.dart';
|
|
|
|
class PangeaController {
|
|
///pangeaControllers
|
|
late UserController userController;
|
|
late LanguageController languageController;
|
|
late ClassController classController;
|
|
late PermissionsController permissionsController;
|
|
late AnalyticsController analytics;
|
|
late MyAnalyticsController myAnalytics;
|
|
late WordController wordNet;
|
|
late LocalSettings localSettings;
|
|
late MessageDataController messageData;
|
|
late ContextualDefinitionController definitions;
|
|
late ITFeedbackController itFeedback;
|
|
late InstructionsController instructions;
|
|
late SubscriptionController subscriptionController;
|
|
late TextToSpeechController textToSpeech;
|
|
|
|
///store Services
|
|
late PLocalStore pStoreService;
|
|
final pLanguageStore = PangeaLanguage();
|
|
|
|
///Matrix Variables
|
|
MatrixState matrixState;
|
|
Matrix matrix;
|
|
|
|
int? randomint;
|
|
PangeaController({required this.matrix, required this.matrixState}) {
|
|
_setup();
|
|
_subscribeToMatrixStreams();
|
|
randomint = Random().nextInt(2000);
|
|
}
|
|
|
|
/// Pangea Initialization
|
|
void _setup() {
|
|
_addRefInObjects();
|
|
}
|
|
|
|
Future<void> afterSyncAndFirstLoginInitialization(
|
|
BuildContext context,
|
|
) async {
|
|
await classController.checkForClassCodeAndSubscription(context);
|
|
// startChatWithBotIfNotPresent();
|
|
await classController.fixClassPowerLevels();
|
|
}
|
|
|
|
/// Initialize controllers
|
|
_addRefInObjects() {
|
|
pStoreService = PLocalStore(pangeaController: this);
|
|
userController = UserController(this);
|
|
languageController = LanguageController(this);
|
|
localSettings = LocalSettings(this);
|
|
classController = ClassController(this);
|
|
permissionsController = PermissionsController(this);
|
|
analytics = AnalyticsController(this);
|
|
myAnalytics = MyAnalyticsController(this);
|
|
messageData = MessageDataController(this);
|
|
wordNet = WordController(this);
|
|
definitions = ContextualDefinitionController(this);
|
|
instructions = InstructionsController(this);
|
|
subscriptionController = SubscriptionController(this);
|
|
itFeedback = ITFeedbackController(this);
|
|
textToSpeech = TextToSpeechController(this);
|
|
PAuthGaurd.pController = this;
|
|
}
|
|
|
|
_logOutfromPangea() {
|
|
debugPrint("Pangea logout");
|
|
GoogleAnalytics.logout();
|
|
pStoreService.clearStorage();
|
|
}
|
|
|
|
Future<void> checkHomeServerAction() async {
|
|
if (matrixState.getLoginClient().homeserver != null) {
|
|
await Future.delayed(Duration.zero);
|
|
return;
|
|
}
|
|
|
|
final String homeServer =
|
|
AppConfig.defaultHomeserver.trim().toLowerCase().replaceAll(' ', '-');
|
|
var homeserver = Uri.parse(homeServer);
|
|
if (homeserver.scheme.isEmpty) {
|
|
homeserver = Uri.https(homeServer, '');
|
|
}
|
|
|
|
matrixState.loginHomeserverSummary =
|
|
await matrixState.getLoginClient().checkHomeserver(homeserver);
|
|
|
|
try {
|
|
await matrixState.getLoginClient().register();
|
|
matrixState.loginRegistrationSupported = true;
|
|
} on MatrixException catch (e) {
|
|
matrixState.loginRegistrationSupported =
|
|
e.requireAdditionalAuthentication;
|
|
}
|
|
|
|
// setState(() => error = (e).toLocalizedString(context));
|
|
}
|
|
|
|
/// check user information if not found then redirect to Date of birth page
|
|
_handleLoginStateChange(LoginState state) {
|
|
if (state != LoginState.loggedIn) {
|
|
_logOutfromPangea();
|
|
}
|
|
Sentry.configureScope(
|
|
(scope) => scope.setUser(SentryUser(id: matrixState.client.userID)),
|
|
);
|
|
GoogleAnalytics.analyticsUserUpdate(matrixState.client.userID);
|
|
}
|
|
|
|
// void startChatWithBotIfNotPresent() {
|
|
// Future.delayed(const Duration(milliseconds: 5000), () async {
|
|
// try {
|
|
// if (pStoreService.read("started_bot_chat", addClientIdToKey: false) ??
|
|
// false) {
|
|
// return;
|
|
// }
|
|
// await pStoreService.save("started_bot_chat", true,
|
|
// addClientIdToKey: false);
|
|
// final rooms = matrixState.client.rooms;
|
|
|
|
// await matrixState.client.startDirectChat(
|
|
// BotName.byEnvironment,
|
|
// enableEncryption: false,
|
|
// );
|
|
// } catch (err, stack) {
|
|
// debugger(when: kDebugMode);
|
|
// ErrorHandler.logError(e: err, s: stack);
|
|
// }
|
|
// });
|
|
// }
|
|
|
|
void startChatWithBotIfNotPresent() {
|
|
Future.delayed(const Duration(milliseconds: 10000), () async {
|
|
// check if user is logged in
|
|
if (!matrixState.client.isLogged() ||
|
|
(await matrixState.client.hasBotDM)) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await matrixState.client.startDirectChat(
|
|
BotName.byEnvironment,
|
|
enableEncryption: false,
|
|
);
|
|
} catch (err, stack) {
|
|
debugger(when: kDebugMode);
|
|
ErrorHandler.logError(e: err, s: stack);
|
|
}
|
|
});
|
|
}
|
|
|
|
_handleJoinEvent(SyncUpdate syncUpdate) {
|
|
// for (final joinedRoomUpdate in syncUpdate.rooms!.join!.entries) {
|
|
// debugPrint(
|
|
// "room update for ${joinedRoomUpdate.key} - ${joinedRoomUpdate.value}");
|
|
// }
|
|
}
|
|
|
|
_handleOnSyncUpdate(SyncUpdate syncUpdate) {
|
|
// debugPrint(syncUpdate.toString());
|
|
}
|
|
|
|
_handleSyncStatusFinished(SyncStatusUpdate event) {
|
|
//might be useful to do something periodically, probably be overkill
|
|
}
|
|
|
|
void _subscribeToMatrixStreams() {
|
|
matrixState.client.onLoginStateChanged.stream
|
|
.listen(_handleLoginStateChange);
|
|
|
|
// matrixState.client.onSyncStatus.stream
|
|
// .where((SyncStatusUpdate event) => event.status == SyncStatus.finished)
|
|
// .listen(_handleSyncStatusFinished);
|
|
|
|
//PTODO - listen to incoming invites and autojoin if in class
|
|
// matrixState.client.onSync.stream
|
|
// .where((event) => event.rooms?.invite?.isNotEmpty ?? false)
|
|
// .listen((SyncUpdate event) {
|
|
// });
|
|
|
|
// matrixState.client.onSync.stream.listen(_handleOnSyncUpdate);
|
|
}
|
|
|
|
Future<void> inviteBotToExistingSpaces() async {
|
|
final List<Room> spaces =
|
|
matrixState.client.rooms.where((room) => room.isSpace).toList();
|
|
for (final Room space in spaces) {
|
|
if (space.ownPowerLevel < ClassDefaultValues.powerLevelOfAdmin ||
|
|
!space.canInvite) {
|
|
continue;
|
|
}
|
|
List<User> participants;
|
|
try {
|
|
participants = await space.requestParticipants();
|
|
} catch (err) {
|
|
ErrorHandler.logError(
|
|
e: "Failed to fetch participants for space ${space.id}",
|
|
);
|
|
continue;
|
|
}
|
|
final List<String> userIds = participants.map((user) => user.id).toList();
|
|
if (!userIds.contains(BotName.byEnvironment)) {
|
|
try {
|
|
await space.invite(BotName.byEnvironment);
|
|
await space.postLoad();
|
|
await space.setPower(
|
|
BotName.byEnvironment,
|
|
ClassDefaultValues.powerLevelOfAdmin,
|
|
);
|
|
} catch (err) {
|
|
ErrorHandler.logError(
|
|
e: "Failed to invite pangea bot to space ${space.id}",
|
|
);
|
|
}
|
|
} else if (space.getPowerLevelByUserId(BotName.byEnvironment) <
|
|
ClassDefaultValues.powerLevelOfAdmin) {
|
|
try {
|
|
await space.setPower(
|
|
BotName.byEnvironment,
|
|
ClassDefaultValues.powerLevelOfAdmin,
|
|
);
|
|
} catch (err) {
|
|
ErrorHandler.logError(
|
|
e: "Failed to reset power level for pangea bot in space ${space.id}",
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<void> setPangeaPushRules() async {
|
|
if (!(matrixState.client.globalPushRules?.override?.any(
|
|
(element) => element.ruleId == PangeaEventTypes.textToSpeechRule,
|
|
) ??
|
|
false)) {
|
|
await matrixState.client.setPushRule(
|
|
'global',
|
|
PushRuleKind.override,
|
|
PangeaEventTypes.textToSpeechRule,
|
|
[PushRuleAction.dontNotify],
|
|
conditions: [
|
|
PushCondition(
|
|
kind: 'event_match',
|
|
key: 'content.msgtype',
|
|
pattern: MessageTypes.Audio,
|
|
),
|
|
PushCondition(
|
|
kind: 'event_match',
|
|
key: 'content.transcription.lang_code',
|
|
pattern: '*',
|
|
),
|
|
PushCondition(
|
|
kind: 'event_match',
|
|
key: 'content.transcription.text',
|
|
pattern: '*',
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
}
|