diff --git a/lib/core.dart b/lib/core.dart index 0a05108e2..d25630525 100644 --- a/lib/core.dart +++ b/lib/core.dart @@ -10,3 +10,4 @@ export 'src/internal/http.dart'; export 'src/internal/entities/event_manager.dart' show Event, Events, MineralEvent; export 'src/internal/entities/command_manager.dart' show Command, MineralCommand, Option, OptionType, OptionChoice, Subcommand, CommandGroup; export 'src/internal/entities/store_manager.dart' show Store, MineralStore; +export 'src/internal/entities/module_manager.dart' show Module, MineralModule; diff --git a/lib/src/internal/entities/module_manager.dart b/lib/src/internal/entities/module_manager.dart new file mode 100644 index 000000000..b0152f523 --- /dev/null +++ b/lib/src/internal/entities/module_manager.dart @@ -0,0 +1,80 @@ +import 'dart:mirrors'; + +import 'package:mineral/console.dart'; +import 'package:mineral/core.dart'; +import 'package:mineral/src/exceptions/already_exist.dart'; +import 'package:mineral/src/internal/entities/command_manager.dart'; +import 'package:mineral/src/internal/entities/store_manager.dart'; + +import 'event_manager.dart'; + +class Module { + final String identifier; + final String label; + final String? description; + + const Module({ required this.identifier, required this.label, this.description }); +} + +abstract class MineralModule { + late final String identifier; + late final String label; + late final String? description; + + abstract List events; + abstract List commands; + abstract List stores; + + Future init () async {} +} + +class ModuleManager { + final Map _modules = {}; + Map get modules => _modules; + + ModuleManager add (MineralModule module, { String? overrideIdentifier }) { + Module moduleDecorator = reflect(module).type.metadata.first.reflectee; + module..identifier = moduleDecorator.identifier + ..label = moduleDecorator.label + ..description = moduleDecorator.description; + + if (_modules.containsKey(moduleDecorator.identifier)) { + if (overrideIdentifier != null) { + _modules.putIfAbsent(overrideIdentifier, () => module); + } else { + throw AlreadyExist(cause: 'Module ${moduleDecorator.identifier} is already registered, perhaps this is an error. If not, please change the name of the module when you register it.'); + } + } else { + _modules.putIfAbsent(moduleDecorator.identifier, () => module); + } + + return this; + } + + Future load () async { + EventManager eventManager = ioc.singleton(ioc.services.event); + CommandManager commandManager = ioc.singleton(ioc.services.command); + StoreManager storeManager = ioc.singleton(ioc.services.store); + + _modules.forEach((key, module) async { + await module.init(); + + for (MineralEvent event in module.events) { + eventManager.add(event); + } + + for (MineralCommand command in module.commands) { + commandManager.add(command); + } + + for (MineralStore event in module.stores) { + storeManager.add(event); + } + + Console.debug( + prefix: 'Loading module', + message: '"${module.label}" with ${module.events.length} events, ${module.commands.length} commands and ${module.stores.length} stores.' + ); + }); + } +} diff --git a/lib/src/internal/ioc.dart b/lib/src/internal/ioc.dart index 2cf5786af..b70611ac5 100644 --- a/lib/src/internal/ioc.dart +++ b/lib/src/internal/ioc.dart @@ -5,6 +5,7 @@ class Service { final event = 'Mineral/Core/Event'; final command = 'Mineral/Core/Command'; final store = 'Mineral/Core/Store'; + final modules = 'Mineral/Core/Modules'; final shards = 'Mineral/Core/Shards'; } diff --git a/lib/src/internal/kernel.dart b/lib/src/internal/kernel.dart index 1a7ee53db..2d953d397 100644 --- a/lib/src/internal/kernel.dart +++ b/lib/src/internal/kernel.dart @@ -3,8 +3,8 @@ import 'package:mineral/exception.dart'; import 'package:mineral/src/internal/entities/command_manager.dart'; import 'package:mineral/src/internal/entities/event_manager.dart'; import 'package:mineral/core.dart'; +import 'package:mineral/src/internal/entities/module_manager.dart'; import 'package:mineral/src/internal/websockets/sharding/shard_manager.dart'; -import 'package:mineral/src/internal/websockets/websocket_manager.dart'; import 'entities/store_manager.dart'; @@ -12,21 +12,23 @@ class Kernel { EventManager events = EventManager(); CommandManager commands = CommandManager(); StoreManager stores = StoreManager(); + ModuleManager modules = ModuleManager(); List intents = []; Kernel() { ioc.bind(namespace: ioc.services.event, service: events); ioc.bind(namespace: ioc.services.command, service: commands); ioc.bind(namespace: ioc.services.store, service: stores); + ioc.bind(namespace: ioc.services.modules, service: modules); } Future init () async { + Environment environment = await _loadEnvironment(); + Http http = Http(baseUrl: 'https://discord.com/api'); http.defineHeader(header: 'Content-Type', value: 'application/json'); ioc.bind(namespace: ioc.services.http, service: http); - Environment environment = await _loadEnvironment(); - String? token = environment.get('APP_TOKEN'); if (token == null) { throw TokenException( @@ -35,6 +37,8 @@ class Kernel { ); } + await modules.load(); + final String? shardsCount = environment.get('SHARDS_COUNT'); ShardManager manager = ShardManager(http, token, intents);