238 lines
7.1 KiB
Dart
238 lines
7.1 KiB
Dart
/*
|
|
* Famedly Matrix SDK
|
|
* Copyright (C) 2021 Famedly GmbH
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
import 'dart:async';
|
|
|
|
import '../../matrix.dart';
|
|
|
|
extension CommandsClientExtension on Client {
|
|
/// Add a command to the command handler. `command` is its name, and `callback` is the
|
|
/// callback to invoke
|
|
void addCommand(
|
|
String command, FutureOr<String?> Function(CommandArgs) callback) {
|
|
commands[command.toLowerCase()] = callback;
|
|
}
|
|
|
|
/// Parse and execute a string, `msg` is the input. Optionally `inReplyTo` is the event being
|
|
/// replied to and `editEventId` is the eventId of the event being replied to
|
|
Future<String?> parseAndRunCommand(Room room, String msg,
|
|
{Event? inReplyTo, String? editEventId, String? txid}) async {
|
|
final args = CommandArgs(
|
|
inReplyTo: inReplyTo,
|
|
editEventId: editEventId,
|
|
msg: '',
|
|
room: room,
|
|
txid: txid,
|
|
);
|
|
if (!msg.startsWith('/')) {
|
|
final sendCommand = commands['send'];
|
|
if (sendCommand != null) {
|
|
args.msg = msg;
|
|
return await sendCommand(args);
|
|
}
|
|
return null;
|
|
}
|
|
// remove the /
|
|
msg = msg.substring(1);
|
|
var command = msg;
|
|
if (msg.contains(' ')) {
|
|
final idx = msg.indexOf(' ');
|
|
command = msg.substring(0, idx).toLowerCase();
|
|
args.msg = msg.substring(idx + 1);
|
|
} else {
|
|
command = msg.toLowerCase();
|
|
}
|
|
final commandOp = commands[command];
|
|
if (commandOp != null) {
|
|
return await commandOp(args);
|
|
}
|
|
if (msg.startsWith('/') && commands.containsKey('send')) {
|
|
// re-set to include the "command"
|
|
final sendCommand = commands['send'];
|
|
if (sendCommand != null) {
|
|
args.msg = msg;
|
|
return await sendCommand(args);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// Unregister all commands
|
|
void unregisterAllCommands() {
|
|
commands.clear();
|
|
}
|
|
|
|
/// Register all default commands
|
|
void registerDefaultCommands() {
|
|
addCommand('send', (CommandArgs args) async {
|
|
return await args.room.sendTextEvent(
|
|
args.msg,
|
|
inReplyTo: args.inReplyTo,
|
|
editEventId: args.editEventId,
|
|
parseCommands: false,
|
|
txid: args.txid,
|
|
);
|
|
});
|
|
addCommand('me', (CommandArgs args) async {
|
|
return await args.room.sendTextEvent(
|
|
args.msg,
|
|
inReplyTo: args.inReplyTo,
|
|
editEventId: args.editEventId,
|
|
msgtype: MessageTypes.Emote,
|
|
parseCommands: false,
|
|
txid: args.txid,
|
|
);
|
|
});
|
|
addCommand('dm', (CommandArgs args) async {
|
|
final parts = args.msg.split(' ');
|
|
return await args.room.client.startDirectChat(
|
|
parts.first,
|
|
enableEncryption: !parts.any((part) => part == '--no-encryption'),
|
|
);
|
|
});
|
|
addCommand('create', (CommandArgs args) async {
|
|
final parts = args.msg.split(' ');
|
|
return await args.room.client.createGroupChat(
|
|
enableEncryption: !parts.any((part) => part == '--no-encryption'),
|
|
);
|
|
});
|
|
addCommand('plain', (CommandArgs args) async {
|
|
return await args.room.sendTextEvent(
|
|
args.msg,
|
|
inReplyTo: args.inReplyTo,
|
|
editEventId: args.editEventId,
|
|
parseMarkdown: false,
|
|
parseCommands: false,
|
|
txid: args.txid,
|
|
);
|
|
});
|
|
addCommand('html', (CommandArgs args) async {
|
|
final event = <String, dynamic>{
|
|
'msgtype': 'm.text',
|
|
'body': args.msg,
|
|
'format': 'org.matrix.custom.html',
|
|
'formatted_body': args.msg,
|
|
};
|
|
return await args.room.sendEvent(
|
|
event,
|
|
inReplyTo: args.inReplyTo,
|
|
editEventId: args.editEventId,
|
|
txid: args.txid,
|
|
);
|
|
});
|
|
addCommand('react', (CommandArgs args) async {
|
|
final inReplyTo = args.inReplyTo;
|
|
if (inReplyTo == null) {
|
|
return null;
|
|
}
|
|
return await args.room.sendReaction(inReplyTo.eventId, args.msg);
|
|
});
|
|
addCommand('join', (CommandArgs args) async {
|
|
await args.room.client.joinRoom(args.msg);
|
|
return null;
|
|
});
|
|
addCommand('leave', (CommandArgs args) async {
|
|
await args.room.leave();
|
|
return '';
|
|
});
|
|
addCommand('op', (CommandArgs args) async {
|
|
final parts = args.msg.split(' ');
|
|
if (parts.isEmpty) {
|
|
return null;
|
|
}
|
|
int? pl;
|
|
if (parts.length >= 2) {
|
|
pl = int.tryParse(parts[1]);
|
|
}
|
|
final mxid = parts.first;
|
|
return await args.room.setPower(mxid, pl ?? 50);
|
|
});
|
|
addCommand('kick', (CommandArgs args) async {
|
|
final parts = args.msg.split(' ');
|
|
await args.room.kick(parts.first);
|
|
return '';
|
|
});
|
|
addCommand('ban', (CommandArgs args) async {
|
|
final parts = args.msg.split(' ');
|
|
await args.room.ban(parts.first);
|
|
return '';
|
|
});
|
|
addCommand('unban', (CommandArgs args) async {
|
|
final parts = args.msg.split(' ');
|
|
await args.room.unban(parts.first);
|
|
return '';
|
|
});
|
|
addCommand('invite', (CommandArgs args) async {
|
|
final parts = args.msg.split(' ');
|
|
await args.room.invite(parts.first);
|
|
return '';
|
|
});
|
|
addCommand('myroomnick', (CommandArgs args) async {
|
|
final currentEventJson = args.room
|
|
.getState(EventTypes.RoomMember, args.room.client.userID!)
|
|
?.content
|
|
.copy() ??
|
|
{};
|
|
currentEventJson['displayname'] = args.msg;
|
|
return await args.room.client.setRoomStateWithKey(
|
|
args.room.id,
|
|
EventTypes.RoomMember,
|
|
args.room.client.userID!,
|
|
currentEventJson,
|
|
);
|
|
});
|
|
addCommand('myroomavatar', (CommandArgs args) async {
|
|
final currentEventJson = args.room
|
|
.getState(EventTypes.RoomMember, args.room.client.userID!)
|
|
?.content
|
|
.copy() ??
|
|
{};
|
|
currentEventJson['avatar_url'] = args.msg;
|
|
return await args.room.client.setRoomStateWithKey(
|
|
args.room.id,
|
|
EventTypes.RoomMember,
|
|
args.room.client.userID!,
|
|
currentEventJson,
|
|
);
|
|
});
|
|
addCommand('discardsession', (CommandArgs args) async {
|
|
await encryption?.keyManager
|
|
.clearOrUseOutboundGroupSession(args.room.id, wipe: true);
|
|
return '';
|
|
});
|
|
addCommand('clearcache', (CommandArgs args) async {
|
|
await clearCache();
|
|
return '';
|
|
});
|
|
}
|
|
}
|
|
|
|
class CommandArgs {
|
|
String msg;
|
|
String? editEventId;
|
|
Event? inReplyTo;
|
|
Room room;
|
|
String? txid;
|
|
CommandArgs(
|
|
{required this.msg,
|
|
this.editEventId,
|
|
this.inReplyTo,
|
|
required this.room,
|
|
this.txid});
|
|
}
|