From 57d38535d3f2c97469ff024cc9a5bd2c8bb0b9e8 Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Sun, 3 Aug 2025 11:51:15 -0400 Subject: [PATCH] error handling --- .vscode/launch.json | 2 ++ bin/nexusbot.dart | 61 ++++++++++++++++++++------------ lib/models/settings.dart | 1 + lib/models/settings.freezed.dart | 27 +++++++------- lib/models/settings.g.dart | 2 ++ 5 files changed, 58 insertions(+), 35 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index fc9dead..9fab56e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -21,6 +21,8 @@ "#community:federated.nexus", "--successUri", "https://federated.nexus/success", + "--failureUri", + "https://federated.nexus/failure", "--botPasswordFile", "secrets/botPassword.txt", "--smtpPasswordFile", diff --git a/bin/nexusbot.dart b/bin/nexusbot.dart index 88a7e08..36fd856 100644 --- a/bin/nexusbot.dart +++ b/bin/nexusbot.dart @@ -17,6 +17,7 @@ void main(List argsRaw) async { final parser = ConfigParser() ..addOption("socket", mandatory: true) ..addOption("homeserver", mandatory: true) + ..addOption("failureUri", mandatory: true) ..addOption("successUri", mandatory: true) ..addOption("name", mandatory: true) ..addOption("adminName", mandatory: true) @@ -120,34 +121,48 @@ If you have any issues, reply to this email.""", .addMiddleware(logRequests()) .addHandler( (Router()..post("/", (Request request) async { - final body = await request.readAsString(); - final registration = Registration.fromJson( - Uri.splitQueryString( - body, - ).map((key, value) => MapEntry(key, value.toLowerCase())), - ); - - final client = await container.read( - ClientController.provider.future, - ); - final settings = container.read(SettingsController.provider)!; - final room = client.getRoomByAlias(settings.adminRoom); - final message = - """# Registration request + try { + final body = await request.readAsString(); + final registration = Registration.fromJson( + Uri.splitQueryString( + body, + ).map((key, value) => MapEntry(key, value.toLowerCase())), + ); + + throw "test error"; + + final client = await container.read( + ClientController.provider.future, + ); + + final room = client.getRoomByAlias(settings.adminRoom)!; + final message = + """# Registration request - Username: `${registration.username}` - Email: `${registration.email}`"""; - final event = await room!.sendEvent({ - "body": message, - "msgtype": MessageTypes.Text, - "format": "org.matrix.custom.html", - "formatted_body": markdownToHtml(message), - ...registration.toJson(), - }); + final event = await room.sendEvent({ + "body": message, + "msgtype": MessageTypes.Text, + "format": "org.matrix.custom.html", + "formatted_body": markdownToHtml(message), + ...registration.toJson(), + }); - await room.sendReaction(event!, "✅"); + await room.sendReaction(event!, "✅"); - return Response.found(settings.successUri); + return Response.found(settings.successUri); + } catch (error) { + final message = "An error occurred: $error"; + + try { + final room = client.getRoomByAlias(settings.adminRoom)!; + await room.sendTextEvent(message); + } catch (_) { + print(message); + } + return Response.found(settings.failureUri); + } })) .call, ); diff --git a/lib/models/settings.dart b/lib/models/settings.dart index e466079..2c76fd5 100644 --- a/lib/models/settings.dart +++ b/lib/models/settings.dart @@ -8,6 +8,7 @@ abstract class Settings with _$Settings { const factory Settings({ required String socket, required Uri homeserver, + required Uri failureUri, required Uri successUri, required String name, required String adminName, diff --git a/lib/models/settings.freezed.dart b/lib/models/settings.freezed.dart index 1362a48..fba9f73 100644 --- a/lib/models/settings.freezed.dart +++ b/lib/models/settings.freezed.dart @@ -16,7 +16,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$Settings { - String get socket; Uri get homeserver; Uri get successUri; String get name; String get adminName; String get adminRoom; String get email; String get mailName; String? get inviteTo; String get mailDomain; String get smtpPasswordFile; String get botPasswordFile; + String get socket; Uri get homeserver; Uri get failureUri; Uri get successUri; String get name; String get adminName; String get adminRoom; String get email; String get mailName; String? get inviteTo; String get mailDomain; String get smtpPasswordFile; String get botPasswordFile; /// Create a copy of Settings /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -29,16 +29,16 @@ $SettingsCopyWith get copyWith => _$SettingsCopyWithImpl(thi @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is Settings&&(identical(other.socket, socket) || other.socket == socket)&&(identical(other.homeserver, homeserver) || other.homeserver == homeserver)&&(identical(other.successUri, successUri) || other.successUri == successUri)&&(identical(other.name, name) || other.name == name)&&(identical(other.adminName, adminName) || other.adminName == adminName)&&(identical(other.adminRoom, adminRoom) || other.adminRoom == adminRoom)&&(identical(other.email, email) || other.email == email)&&(identical(other.mailName, mailName) || other.mailName == mailName)&&(identical(other.inviteTo, inviteTo) || other.inviteTo == inviteTo)&&(identical(other.mailDomain, mailDomain) || other.mailDomain == mailDomain)&&(identical(other.smtpPasswordFile, smtpPasswordFile) || other.smtpPasswordFile == smtpPasswordFile)&&(identical(other.botPasswordFile, botPasswordFile) || other.botPasswordFile == botPasswordFile)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is Settings&&(identical(other.socket, socket) || other.socket == socket)&&(identical(other.homeserver, homeserver) || other.homeserver == homeserver)&&(identical(other.failureUri, failureUri) || other.failureUri == failureUri)&&(identical(other.successUri, successUri) || other.successUri == successUri)&&(identical(other.name, name) || other.name == name)&&(identical(other.adminName, adminName) || other.adminName == adminName)&&(identical(other.adminRoom, adminRoom) || other.adminRoom == adminRoom)&&(identical(other.email, email) || other.email == email)&&(identical(other.mailName, mailName) || other.mailName == mailName)&&(identical(other.inviteTo, inviteTo) || other.inviteTo == inviteTo)&&(identical(other.mailDomain, mailDomain) || other.mailDomain == mailDomain)&&(identical(other.smtpPasswordFile, smtpPasswordFile) || other.smtpPasswordFile == smtpPasswordFile)&&(identical(other.botPasswordFile, botPasswordFile) || other.botPasswordFile == botPasswordFile)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,socket,homeserver,successUri,name,adminName,adminRoom,email,mailName,inviteTo,mailDomain,smtpPasswordFile,botPasswordFile); +int get hashCode => Object.hash(runtimeType,socket,homeserver,failureUri,successUri,name,adminName,adminRoom,email,mailName,inviteTo,mailDomain,smtpPasswordFile,botPasswordFile); @override String toString() { - return 'Settings(socket: $socket, homeserver: $homeserver, successUri: $successUri, name: $name, adminName: $adminName, adminRoom: $adminRoom, email: $email, mailName: $mailName, inviteTo: $inviteTo, mailDomain: $mailDomain, smtpPasswordFile: $smtpPasswordFile, botPasswordFile: $botPasswordFile)'; + return 'Settings(socket: $socket, homeserver: $homeserver, failureUri: $failureUri, successUri: $successUri, name: $name, adminName: $adminName, adminRoom: $adminRoom, email: $email, mailName: $mailName, inviteTo: $inviteTo, mailDomain: $mailDomain, smtpPasswordFile: $smtpPasswordFile, botPasswordFile: $botPasswordFile)'; } @@ -49,7 +49,7 @@ abstract mixin class $SettingsCopyWith<$Res> { factory $SettingsCopyWith(Settings value, $Res Function(Settings) _then) = _$SettingsCopyWithImpl; @useResult $Res call({ - String socket, Uri homeserver, Uri successUri, String name, String adminName, String adminRoom, String email, String mailName, String? inviteTo, String mailDomain, String smtpPasswordFile, String botPasswordFile + String socket, Uri homeserver, Uri failureUri, Uri successUri, String name, String adminName, String adminRoom, String email, String mailName, String? inviteTo, String mailDomain, String smtpPasswordFile, String botPasswordFile }); @@ -66,10 +66,11 @@ class _$SettingsCopyWithImpl<$Res> /// Create a copy of Settings /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? socket = null,Object? homeserver = null,Object? successUri = null,Object? name = null,Object? adminName = null,Object? adminRoom = null,Object? email = null,Object? mailName = null,Object? inviteTo = freezed,Object? mailDomain = null,Object? smtpPasswordFile = null,Object? botPasswordFile = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? socket = null,Object? homeserver = null,Object? failureUri = null,Object? successUri = null,Object? name = null,Object? adminName = null,Object? adminRoom = null,Object? email = null,Object? mailName = null,Object? inviteTo = freezed,Object? mailDomain = null,Object? smtpPasswordFile = null,Object? botPasswordFile = null,}) { return _then(_self.copyWith( socket: null == socket ? _self.socket : socket // ignore: cast_nullable_to_non_nullable as String,homeserver: null == homeserver ? _self.homeserver : homeserver // ignore: cast_nullable_to_non_nullable +as Uri,failureUri: null == failureUri ? _self.failureUri : failureUri // ignore: cast_nullable_to_non_nullable as Uri,successUri: null == successUri ? _self.successUri : successUri // ignore: cast_nullable_to_non_nullable as Uri,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable as String,adminName: null == adminName ? _self.adminName : adminName // ignore: cast_nullable_to_non_nullable @@ -91,11 +92,12 @@ as String, @JsonSerializable() class _Settings implements Settings { - const _Settings({required this.socket, required this.homeserver, required this.successUri, required this.name, required this.adminName, required this.adminRoom, required this.email, required this.mailName, required this.inviteTo, required this.mailDomain, required this.smtpPasswordFile, required this.botPasswordFile}); + const _Settings({required this.socket, required this.homeserver, required this.failureUri, required this.successUri, required this.name, required this.adminName, required this.adminRoom, required this.email, required this.mailName, required this.inviteTo, required this.mailDomain, required this.smtpPasswordFile, required this.botPasswordFile}); factory _Settings.fromJson(Map json) => _$SettingsFromJson(json); @override final String socket; @override final Uri homeserver; +@override final Uri failureUri; @override final Uri successUri; @override final String name; @override final String adminName; @@ -120,16 +122,16 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _Settings&&(identical(other.socket, socket) || other.socket == socket)&&(identical(other.homeserver, homeserver) || other.homeserver == homeserver)&&(identical(other.successUri, successUri) || other.successUri == successUri)&&(identical(other.name, name) || other.name == name)&&(identical(other.adminName, adminName) || other.adminName == adminName)&&(identical(other.adminRoom, adminRoom) || other.adminRoom == adminRoom)&&(identical(other.email, email) || other.email == email)&&(identical(other.mailName, mailName) || other.mailName == mailName)&&(identical(other.inviteTo, inviteTo) || other.inviteTo == inviteTo)&&(identical(other.mailDomain, mailDomain) || other.mailDomain == mailDomain)&&(identical(other.smtpPasswordFile, smtpPasswordFile) || other.smtpPasswordFile == smtpPasswordFile)&&(identical(other.botPasswordFile, botPasswordFile) || other.botPasswordFile == botPasswordFile)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _Settings&&(identical(other.socket, socket) || other.socket == socket)&&(identical(other.homeserver, homeserver) || other.homeserver == homeserver)&&(identical(other.failureUri, failureUri) || other.failureUri == failureUri)&&(identical(other.successUri, successUri) || other.successUri == successUri)&&(identical(other.name, name) || other.name == name)&&(identical(other.adminName, adminName) || other.adminName == adminName)&&(identical(other.adminRoom, adminRoom) || other.adminRoom == adminRoom)&&(identical(other.email, email) || other.email == email)&&(identical(other.mailName, mailName) || other.mailName == mailName)&&(identical(other.inviteTo, inviteTo) || other.inviteTo == inviteTo)&&(identical(other.mailDomain, mailDomain) || other.mailDomain == mailDomain)&&(identical(other.smtpPasswordFile, smtpPasswordFile) || other.smtpPasswordFile == smtpPasswordFile)&&(identical(other.botPasswordFile, botPasswordFile) || other.botPasswordFile == botPasswordFile)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,socket,homeserver,successUri,name,adminName,adminRoom,email,mailName,inviteTo,mailDomain,smtpPasswordFile,botPasswordFile); +int get hashCode => Object.hash(runtimeType,socket,homeserver,failureUri,successUri,name,adminName,adminRoom,email,mailName,inviteTo,mailDomain,smtpPasswordFile,botPasswordFile); @override String toString() { - return 'Settings(socket: $socket, homeserver: $homeserver, successUri: $successUri, name: $name, adminName: $adminName, adminRoom: $adminRoom, email: $email, mailName: $mailName, inviteTo: $inviteTo, mailDomain: $mailDomain, smtpPasswordFile: $smtpPasswordFile, botPasswordFile: $botPasswordFile)'; + return 'Settings(socket: $socket, homeserver: $homeserver, failureUri: $failureUri, successUri: $successUri, name: $name, adminName: $adminName, adminRoom: $adminRoom, email: $email, mailName: $mailName, inviteTo: $inviteTo, mailDomain: $mailDomain, smtpPasswordFile: $smtpPasswordFile, botPasswordFile: $botPasswordFile)'; } @@ -140,7 +142,7 @@ abstract mixin class _$SettingsCopyWith<$Res> implements $SettingsCopyWith<$Res> factory _$SettingsCopyWith(_Settings value, $Res Function(_Settings) _then) = __$SettingsCopyWithImpl; @override @useResult $Res call({ - String socket, Uri homeserver, Uri successUri, String name, String adminName, String adminRoom, String email, String mailName, String? inviteTo, String mailDomain, String smtpPasswordFile, String botPasswordFile + String socket, Uri homeserver, Uri failureUri, Uri successUri, String name, String adminName, String adminRoom, String email, String mailName, String? inviteTo, String mailDomain, String smtpPasswordFile, String botPasswordFile }); @@ -157,10 +159,11 @@ class __$SettingsCopyWithImpl<$Res> /// Create a copy of Settings /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? socket = null,Object? homeserver = null,Object? successUri = null,Object? name = null,Object? adminName = null,Object? adminRoom = null,Object? email = null,Object? mailName = null,Object? inviteTo = freezed,Object? mailDomain = null,Object? smtpPasswordFile = null,Object? botPasswordFile = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? socket = null,Object? homeserver = null,Object? failureUri = null,Object? successUri = null,Object? name = null,Object? adminName = null,Object? adminRoom = null,Object? email = null,Object? mailName = null,Object? inviteTo = freezed,Object? mailDomain = null,Object? smtpPasswordFile = null,Object? botPasswordFile = null,}) { return _then(_Settings( socket: null == socket ? _self.socket : socket // ignore: cast_nullable_to_non_nullable as String,homeserver: null == homeserver ? _self.homeserver : homeserver // ignore: cast_nullable_to_non_nullable +as Uri,failureUri: null == failureUri ? _self.failureUri : failureUri // ignore: cast_nullable_to_non_nullable as Uri,successUri: null == successUri ? _self.successUri : successUri // ignore: cast_nullable_to_non_nullable as Uri,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable as String,adminName: null == adminName ? _self.adminName : adminName // ignore: cast_nullable_to_non_nullable diff --git a/lib/models/settings.g.dart b/lib/models/settings.g.dart index 0885b68..e13ef23 100644 --- a/lib/models/settings.g.dart +++ b/lib/models/settings.g.dart @@ -9,6 +9,7 @@ part of 'settings.dart'; _Settings _$SettingsFromJson(Map json) => _Settings( socket: json['socket'] as String, homeserver: Uri.parse(json['homeserver'] as String), + failureUri: Uri.parse(json['failureUri'] as String), successUri: Uri.parse(json['successUri'] as String), name: json['name'] as String, adminName: json['adminName'] as String, @@ -24,6 +25,7 @@ _Settings _$SettingsFromJson(Map json) => _Settings( Map _$SettingsToJson(_Settings instance) => { 'socket': instance.socket, 'homeserver': instance.homeserver.toString(), + 'failureUri': instance.failureUri.toString(), 'successUri': instance.successUri.toString(), 'name': instance.name, 'adminName': instance.adminName,