From 32507f365461426ab15f175f59337c75cc75d88f Mon Sep 17 00:00:00 2001 From: Abitofevrything <54505189+abitofevrything@users.noreply.github.com> Date: Mon, 16 Oct 2023 18:50:11 +0200 Subject: [PATCH] Improve plugin interface and errors (#565) --- lib/nyxx.dart | 1 + lib/src/client.dart | 12 +++++++++++- lib/src/errors.dart | 12 ++++++++++++ lib/src/models/channel/thread.dart | 2 +- lib/src/plugin/plugin.dart | 13 ++++++++++++- 5 files changed, 37 insertions(+), 3 deletions(-) diff --git a/lib/nyxx.dart b/lib/nyxx.dart index 3b9a90cda..3c6582746 100644 --- a/lib/nyxx.dart +++ b/lib/nyxx.dart @@ -315,3 +315,4 @@ export 'package:http/http.dart' BaseResponse, StreamedResponse; export 'package:logging/logging.dart' show Logger, Level; +export 'package:runtime_type/runtime_type.dart' show RuntimeType; diff --git a/lib/src/client.dart b/lib/src/client.dart index 2e60e0502..c13021bec 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -2,6 +2,7 @@ import 'package:logging/logging.dart'; import 'package:nyxx/src/builders/presence.dart'; import 'package:nyxx/src/builders/voice.dart'; import 'package:nyxx/src/client_options.dart'; +import 'package:nyxx/src/errors.dart'; import 'package:nyxx/src/event_mixin.dart'; import 'package:nyxx/src/gateway/gateway.dart'; import 'package:nyxx/src/http/handler.dart'; @@ -16,12 +17,21 @@ import 'package:nyxx/src/models/user/user.dart'; import 'package:nyxx/src/plugin/plugin.dart'; import 'package:nyxx/src/utils/flags.dart'; import 'package:oauth2/oauth2.dart'; +import 'package:runtime_type/runtime_type.dart'; /// A helper function to nest and execute calls to plugin connect methods. Future _doConnect(ApiOptions apiOptions, ClientOptions clientOptions, Future Function() connect, List plugins) { + final actualClientType = RuntimeType(); + + for (final plugin in plugins) { + if (!actualClientType.isSubtypeOf(plugin.clientType)) { + throw PluginError('Unsupported client type: plugin needs ${plugin.clientType.internalType}, client was ${actualClientType.internalType}'); + } + } + connect = plugins.fold( connect, - (previousConnect, plugin) => () async => (await plugin.doConnect(apiOptions, clientOptions, previousConnect)) as T, + (previousConnect, plugin) => () async => actualClientType.castInstance(await plugin.doConnect(apiOptions, clientOptions, previousConnect)), ); return connect(); } diff --git a/lib/src/errors.dart b/lib/src/errors.dart index 89c366ae9..c94dfef36 100644 --- a/lib/src/errors.dart +++ b/lib/src/errors.dart @@ -127,3 +127,15 @@ class AlreadyRespondedError extends AlreadyAcknowledgedError { @override String toString() => 'Interaction has already been responded to'; } + +/// An error thrown when an issue with a client's plugin is encountered. +class PluginError extends Error { + /// The message for this [PluginError]. + final String message; + + /// Create a new [PluginError]. + PluginError(this.message); + + @override + String toString() => message; +} diff --git a/lib/src/models/channel/thread.dart b/lib/src/models/channel/thread.dart index f26f953e4..03ad2a23b 100644 --- a/lib/src/models/channel/thread.dart +++ b/lib/src/models/channel/thread.dart @@ -97,7 +97,7 @@ class PartialThreadMember { /// {@template thread_member} /// Additional information associated with a [Member] in a [Thread]. -/// {@endtemplate thread_member} +/// {@endtemplate} class ThreadMember extends PartialThreadMember { /// The manager for this [ThreadMember]. final ChannelManager manager; diff --git a/lib/src/plugin/plugin.dart b/lib/src/plugin/plugin.dart index a49a6a521..237863681 100644 --- a/lib/src/plugin/plugin.dart +++ b/lib/src/plugin/plugin.dart @@ -1,14 +1,22 @@ import 'dart:async'; +import 'package:logging/logging.dart'; import 'package:meta/meta.dart'; import 'package:nyxx/src/api_options.dart'; import 'package:nyxx/src/client.dart'; import 'package:nyxx/src/client_options.dart'; +import 'package:runtime_type/runtime_type.dart'; /// Provides access to the connection and closing process for implementing plugins. abstract class NyxxPlugin { /// The name of this plugin. - String get name; + String get name => runtimeType.toString(); + + /// A logger that can be used to log messages from this plugin. + Logger get logger => Logger(name); + + /// The type of client this plugin requires. + RuntimeType get clientType => RuntimeType(); late final Expando>> _states = Expando('$name plugin states'); @@ -64,6 +72,9 @@ class NyxxPluginState plugin.logger; + /// Create a new plugin state. NyxxPluginState(this.plugin);