104 lines
3.0 KiB
Dart
104 lines
3.0 KiB
Dart
import 'package:ikar/l10n/app_localizations.dart';
|
|
import 'dart:io';
|
|
|
|
import '../../backend/modules/messages.dart';
|
|
import '../../core/media/gallery_source.dart';
|
|
import '../../core/plugins/plugin_models.dart';
|
|
import '../../core/plugins/plugin_manifest.dart';
|
|
|
|
const String kAntiFloodNotification =
|
|
'Упс! ИКАР сбросил соединение, кажется, тебе стоит немного помедлить с командами.';
|
|
const Duration _antiFloodNotificationDuration = Duration(seconds: 3);
|
|
|
|
class CommandContext {
|
|
final AppLocalizations? l10n;
|
|
final int accountId;
|
|
final int chatId;
|
|
final int? otherUserId;
|
|
final String args;
|
|
final MessagesModule messages;
|
|
final bool Function() isOnline;
|
|
final bool Function() isActive;
|
|
final void Function(String message, {Duration? duration}) notify;
|
|
final Future<String> Function(String text) postMessage;
|
|
final Future<void> Function(String id, String text) updateMessage;
|
|
final Future<void> Function(List<PickedPhoto> photos, String caption)
|
|
sendPhotos;
|
|
final Future<void> Function(File file, int durationMs) sendVideoNote;
|
|
final Future<void> Function(PluginCommandDescriptor command)? runPlugin;
|
|
|
|
const CommandContext({
|
|
this.l10n,
|
|
required this.accountId,
|
|
required this.chatId,
|
|
required this.otherUserId,
|
|
required this.args,
|
|
required this.messages,
|
|
required this.isOnline,
|
|
required this.isActive,
|
|
required this.notify,
|
|
required this.postMessage,
|
|
required this.updateMessage,
|
|
required this.sendPhotos,
|
|
required this.sendVideoNote,
|
|
this.runPlugin,
|
|
});
|
|
|
|
void notifyAntiFlood() =>
|
|
notify(kAntiFloodNotification, duration: _antiFloodNotificationDuration);
|
|
}
|
|
|
|
Future<bool> playFrames(
|
|
CommandContext ctx,
|
|
String id,
|
|
List<String> frames,
|
|
Duration delay, {
|
|
int from = 1,
|
|
}) async {
|
|
for (var i = from; i < frames.length; i++) {
|
|
await Future.delayed(delay);
|
|
if (!ctx.isActive()) return false;
|
|
if (!ctx.isOnline()) {
|
|
ctx.notifyAntiFlood();
|
|
return false;
|
|
}
|
|
try {
|
|
await ctx.updateMessage(id, frames[i]);
|
|
} catch (_) {
|
|
if (ctx.isActive() && !ctx.isOnline()) ctx.notifyAntiFlood();
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
typedef CommandRunner = Future<void> Function(CommandContext ctx);
|
|
|
|
class SlashCommand {
|
|
final String name;
|
|
final String description;
|
|
final String Function(AppLocalizations)? localizedDescription;
|
|
String describe(AppLocalizations l10n) =>
|
|
localizedDescription?.call(l10n) ?? description;
|
|
final CommandRunner? run;
|
|
final bool hidden;
|
|
final List<PluginCommandArgumentManifest> arguments;
|
|
|
|
String get usage => [
|
|
name,
|
|
for (final argument in arguments)
|
|
argument.required
|
|
? '<${argument.name}${argument.rest ? '...' : ''}>'
|
|
: '[${argument.name}${argument.rest ? '...' : ''}]',
|
|
].join(' ');
|
|
|
|
const SlashCommand(
|
|
this.name,
|
|
this.description, {
|
|
this.localizedDescription,
|
|
this.run,
|
|
this.hidden = false,
|
|
this.arguments = const [],
|
|
});
|
|
}
|