185 lines
6.7 KiB
Dart
185 lines
6.7 KiB
Dart
import "dart:io";
|
|
import "package:cli_tools/config.dart";
|
|
import "package:enough_mail/enough_mail.dart" as mail;
|
|
import "package:markdown/markdown.dart";
|
|
import "package:matrix/matrix.dart";
|
|
import "package:nexusbot/controllers/client_controller.dart";
|
|
import "package:nexusbot/controllers/mail_client_controller.dart";
|
|
import "package:nexusbot/controllers/registration_controller.dart";
|
|
import "package:nexusbot/controllers/settings_controller.dart";
|
|
import "package:nexusbot/models/registration.dart";
|
|
import "package:riverpod/riverpod.dart";
|
|
import "package:shelf/shelf.dart";
|
|
import "package:shelf/shelf_io.dart";
|
|
import "package:shelf_router/shelf_router.dart";
|
|
|
|
void main(List<String> 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)
|
|
..addOption("adminRoom", mandatory: true)
|
|
..addOption("email", mandatory: true)
|
|
..addOption("emailAlias", mandatory: false)
|
|
..addOption("mailName", mandatory: true)
|
|
..addOption("mailDomain", mandatory: true)
|
|
..addOption("smtpPasswordFile", mandatory: true)
|
|
..addOption("botPasswordFile", mandatory: true)
|
|
..addOption("inviteTo");
|
|
|
|
final container = ProviderContainer();
|
|
container
|
|
.read(SettingsController.provider.notifier)
|
|
.set(parser.parse(argsRaw));
|
|
|
|
final client = await container.read(ClientController.provider.future);
|
|
client.onTimelineEvent.stream.listen((event) async {
|
|
final settings = container.read(SettingsController.provider)!;
|
|
|
|
if (event.room.canonicalAlias != settings.adminRoom) return;
|
|
if (event.senderId.startsWith("@${settings.name}:")) return;
|
|
switch (event.type) {
|
|
case EventTypes.Reaction:
|
|
if ((event.content["m.relates_to"] as Map<String, dynamic>)["key"] !=
|
|
"✅") {
|
|
return;
|
|
}
|
|
final parentEvent = await client.getOneRoomEvent(
|
|
event.roomId!,
|
|
event.relationshipEventId!,
|
|
);
|
|
if (!parentEvent.senderId.startsWith("@${settings.name}:")) return;
|
|
final registration = Registration.fromJson(parentEvent.content);
|
|
container
|
|
.read(RegistrationController.provider.notifier)
|
|
.add(registration);
|
|
|
|
await event.room.sendTextEvent(
|
|
"!admin create-user ${registration.username}",
|
|
);
|
|
break;
|
|
case EventTypes.Message:
|
|
if (!event.senderId.startsWith("@${settings.adminName}:")) break;
|
|
final results = RegExp(
|
|
r"@(?<username>[a-zA-Z0-9._-]+):[^\s]+.*?password:\s+(?<password>\S+)",
|
|
).firstMatch(event.body);
|
|
if (results == null) return;
|
|
|
|
final registration = container
|
|
.read(RegistrationController.provider)
|
|
.firstWhere(
|
|
(account) => account.username == results.namedGroup("username"),
|
|
);
|
|
final password = results.namedGroup("password")!;
|
|
final reactionEvent = await event.room.sendReaction(
|
|
event.eventId,
|
|
"✉️ Sending...",
|
|
);
|
|
|
|
await container
|
|
.read(MailClientController.provider.notifier)
|
|
.sendMessage(
|
|
plainText:
|
|
"""Your registration for Federated Nexus has been accepted! Your credentials are:
|
|
Username: ${registration.username}.
|
|
Password: $password
|
|
|
|
If you have any questions, check out our documentation: https://federated.nexus/services/matrix/.
|
|
|
|
If you have any issues, reply to this email.""",
|
|
markdown:
|
|
"""# Your registration for Federated Nexus has been accepted!
|
|
## Your credentials are:
|
|
- ### Username: ${registration.username}.
|
|
- ### Password: $password
|
|
|
|
If you have any questions, check out [our documentation](https://federated.nexus/services/matrix/).
|
|
|
|
If you have any issues, reply to this email.""",
|
|
subject:
|
|
"Your registration for Federated Nexus has been accepted!",
|
|
to: mail.MailAddress(registration.username, registration.email),
|
|
);
|
|
await event.room.redactEvent(reactionEvent!);
|
|
await event.room.sendReaction(event.eventId, "✉️ Sent!");
|
|
if (settings.inviteTo != null) {
|
|
client
|
|
.getRoomByAlias(settings.inviteTo!)!
|
|
.invite(
|
|
RegExp(
|
|
r"(?<userid>@[a-zA-Z0-9._-]+:[^\s]+)",
|
|
).firstMatch(event.body)!.namedGroup("userid")!,
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
final handler = const Pipeline()
|
|
.addMiddleware(logRequests())
|
|
.addHandler(
|
|
(Router()..post("/", (Request request) async {
|
|
final settings = container.read(SettingsController.provider)!;
|
|
try {
|
|
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 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(),
|
|
});
|
|
|
|
await room.sendReaction(event!, "✅");
|
|
|
|
return Response.found(settings.successUri);
|
|
} catch (error, stackTrace) {
|
|
final message =
|
|
"""An error occurred for this request:
|
|
${await request.readAsString()}
|
|
$error
|
|
$stackTrace
|
|
""";
|
|
|
|
try {
|
|
final room = client.getRoomByAlias(settings.adminRoom)!;
|
|
await room.sendTextEvent(message);
|
|
} catch (_) {
|
|
print(message);
|
|
}
|
|
return Response.found(settings.failureUri);
|
|
}
|
|
}))
|
|
.call,
|
|
);
|
|
|
|
final server = HttpServer.listenOn(
|
|
await ServerSocket.bind(
|
|
InternetAddress(
|
|
container.read(SettingsController.provider)!.socket,
|
|
type: InternetAddressType.unix,
|
|
),
|
|
0,
|
|
),
|
|
);
|
|
|
|
serveRequests(server, handler);
|
|
print("Bot listening at ${server.address.address}");
|
|
}
|