diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cb045bd1..40d36989a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +## 1.2.1 +- Fix wrong userId key into interactions + +## 1.2.0 +- Implement `setDefaultReactionEmoji` method +- Implement `setTags` method +- Implement `setDefaultRateLimit` method + +## 1.1.0 +- Implement forum channels + +## 1.0.8 - 1.0.9 +- Add missing return + +## 1.0.7 +- Implement `unban` method +- Improve voice member + +## 1.0.6 +- Fix CategoryChannel cast +- Improve `nickname` getter, it returns the username if nickname is not defined +- Implement `getOrFail` and `getOr` methods on Environment + ## 1.0.5 - Fix missing examples diff --git a/lib/api.dart b/lib/api.dart index 0a942e22c..c3c8fc67e 100644 --- a/lib/api.dart +++ b/lib/api.dart @@ -31,7 +31,10 @@ export 'src/api/channels/partial_text_channel.dart' show PartialTextChannel; export 'src/api/channels/guild_channel.dart' show GuildChannel; export 'src/api/channels/category_channel.dart' show CategoryChannel; export 'src/api/channels/partial_channel.dart' show PartialChannel, ChannelType; +export 'src/api/channels/forum_channel.dart' show ForumChannel; export 'src/api/permission_overwrite.dart' show PermissionOverwrite, PermissionOverwriteType; +export 'src/api/components/message_builder.dart' show MessageBuilder; +export 'src/api/components/forum_tag_builder.dart' show ForumTagBuilder; export 'src/api/messages/message.dart' show Message; export 'src/api/messages/embed_builder.dart' show EmbedBuilder, Footer, Image, Thumbnail, Author, Field; @@ -55,6 +58,8 @@ export 'src/api/interactions/context_user_interaction.dart' show ContextUserInte export 'src/api/interactions/context_message_interaction.dart' show ContextMessageInteraction; export 'src/api/interactions/interaction.dart' show Interaction; +export 'src/api/components/code_builder.dart' show CodeBuilder; + export 'src/api/utils.dart'; export 'src/internal/extensions/collection.dart'; export 'src/internal/extensions/string.dart'; diff --git a/lib/console.dart b/lib/console.dart index 5a22c8416..628c1770b 100644 --- a/lib/console.dart +++ b/lib/console.dart @@ -5,11 +5,12 @@ import 'dart:io'; import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/reporter_manager.dart'; +import 'package:mineral_ioc/ioc.dart'; class Cli { void log ({ required String message, String level = 'info'}) { if (level == 'debug') { - final Environment environment = ioc.singleton(ioc.services.environment); + final Environment environment = ioc.singleton(Service.environment); final String? logLevel = environment.get('LOG_LEVEL'); if (logLevel != 'debug') return; @@ -41,7 +42,7 @@ class Console { static void log ({ required String message, String level = 'info'}) { if (level == 'debug') { - final Environment environment = ioc.singleton(ioc.services.environment); + final Environment environment = ioc.singleton(Service.environment); final String? logLevel = environment.get('LOG_LEVEL'); if (logLevel != 'debug') return; @@ -51,7 +52,7 @@ class Console { } static debug ({ String prefix = 'debug', required String message }) { - ReporterManager? reporter = ioc.singleton(ioc.services.reporter); + ReporterManager? reporter = ioc.singleton(Service.reporter); if (reporter != null && reporter.reportLevel == 'debug') { _report('[ $prefix ] $message'); @@ -94,7 +95,7 @@ class Console { } static _report (String message) { - ReporterManager? reporter = ioc.singleton(ioc.services.reporter); + ReporterManager? reporter = ioc.singleton(Service.reporter); if (reporter != null) { reporter.write(message); } diff --git a/lib/core.dart b/lib/core.dart index af4e27f4f..3dc816f6a 100644 --- a/lib/core.dart +++ b/lib/core.dart @@ -4,7 +4,7 @@ library core; export 'src/internal/services/environment.dart' show Environment; export 'src/internal/kernel.dart' show Kernel; -export 'src/internal/ioc.dart' show ioc, Service; +export 'package:mineral_ioc/ioc.dart' show ioc, Service; export 'src/constants.dart'; export 'src/internal/services/http.dart'; diff --git a/lib/src/api/channels/channel_builder.dart b/lib/src/api/channels/channel_builder.dart index a699412d6..4265e231d 100644 --- a/lib/src/api/channels/channel_builder.dart +++ b/lib/src/api/channels/channel_builder.dart @@ -58,4 +58,21 @@ class ChannelBuilder { 'video_quality_mode': videoQualityMode }); } + + factory ChannelBuilder.fromForumChannel ({ required String label, String? guidelines, Snowflake? parentId, List? tags }) { + print({ + 'type': ChannelType.guildForum.value, + 'name': label, + 'parent_id': parentId, + 'topic': guidelines, + 'available_tags': [...?tags?.map((tag) => tag.toJson())], + }); + return ChannelBuilder({ + 'type': ChannelType.guildForum.value, + 'name': label, + 'parent_id': parentId, + 'topic': guidelines, + 'available_tags': [...?tags?.map((tag) => tag.toJson())], + }); + } } diff --git a/lib/src/api/channels/dm_channel.dart b/lib/src/api/channels/dm_channel.dart index 28b65e434..5b7ad7a19 100644 --- a/lib/src/api/channels/dm_channel.dart +++ b/lib/src/api/channels/dm_channel.dart @@ -15,7 +15,7 @@ class DmChannel extends PartialChannel { ); factory DmChannel.fromPayload(dynamic payload) { - MineralClient client = ioc.singleton(ioc.services.client); + MineralClient client = ioc.singleton(Service.client); Map users = {}; if (payload['recipients'] != null) { diff --git a/lib/src/api/channels/forum_channel.dart b/lib/src/api/channels/forum_channel.dart new file mode 100644 index 000000000..9918463f9 --- /dev/null +++ b/lib/src/api/channels/forum_channel.dart @@ -0,0 +1,86 @@ +import 'package:mineral/api.dart'; +import 'package:mineral/src/api/managers/forum_discussion_manager.dart'; +import 'package:mineral/src/api/managers/permission_overwrite_manager.dart'; + +class ForumChannel extends GuildChannel { + final ForumDiscussionManager _discussions; + + ForumChannel( + super.guildId, + super.parentId, + super.label, + super.type, + super.position, + super.flags, + super.permissions, + super.id, + this._discussions, + ); + + ForumDiscussionManager get discussions => _discussions; + + /// Defines the default emoji of this + /// ```dart + /// final channel = guild.channels.cache.getOrFail('...'); + /// await channel.setDefaultReactionEmoji(EmojiBuilder.fromUnicode('🧱')); + /// ``` + Future setDefaultReactionEmoji (EmojiBuilder emoji) async { + final _emoji = {}; + if (emoji.emoji.id.isNotEmpty) { + _emoji.putIfAbsent('emoji_id', () => emoji.emoji.id); + } + + if (emoji.emoji.label.isNotEmpty) { + _emoji.putIfAbsent('emoji_name', () => emoji.emoji.label); + } + + await update(ChannelBuilder({ + 'default_reaction_emoji': _emoji + })); + } + + /// Defines the tags of this + /// ```dart + /// final channel = guild.channels.cache.getOrFail('...'); + /// await channel.setTags([ + /// ForumTagBuilder(label: 'Hello world !', moderated: false), + /// ForumTagBuilder(label: 'Hello world !', moderated: false, emoji: EmojiBuilder.fromUnicode('🧱')), + /// ]); + /// ``` + Future setTags (List tags) async { + await update(ChannelBuilder({ + 'available_tags': [...tags.map((tag) => tag.toJson())] + })); + } + + /// Defines the default rate limit per user of this + /// ```dart + /// final channel = guild.channels.cache.getOrFail('...'); + /// await channel.setRateLimit(Duration(seconds: 5)); + /// ``` + Future setDefaultRateLimit (Duration duration) async { + await update(ChannelBuilder({ + 'default_thread_rate_limit_per_user': duration.inMilliseconds + })); + } + + factory ForumChannel.fromPayload(dynamic payload) { + final permissionOverwriteManager = PermissionOverwriteManager(); + for (dynamic element in payload['permission_overwrites']) { + final PermissionOverwrite overwrite = PermissionOverwrite.from(payload: element); + permissionOverwriteManager.cache.putIfAbsent(overwrite.id, () => overwrite); + } + + return ForumChannel( + payload['guild_id'], + payload['parent_id'], + payload['name'], + payload['type'], + payload['position'], + payload['flags'], + permissionOverwriteManager, + payload['id'], + ForumDiscussionManager(payload['id']), + ); + } +} diff --git a/lib/src/api/channels/guild_channel.dart b/lib/src/api/channels/guild_channel.dart index db557713b..6b73e722f 100644 --- a/lib/src/api/channels/guild_channel.dart +++ b/lib/src/api/channels/guild_channel.dart @@ -16,7 +16,7 @@ class GuildChannel extends PartialChannel { GuildChannel(this._guildId, this._parentId, this._label, this._type, this._position, this._flags, this._permissions, super.id); /// Get [Guild] from [Ioc] - Guild get guild => ioc.singleton(ioc.services.client).guilds.cache.getOrFail(_guildId); + Guild get guild => ioc.singleton(Service.client).guilds.cache.getOrFail(_guildId); /// Get [CategoryChannel] or [TextChannel] parent GuildChannel? get parent => guild.channels.cache.get(_parentId); @@ -54,7 +54,7 @@ class GuildChannel extends PartialChannel { Future update (ChannelBuilder builder) async { if (_validate()) { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); await http.patch(url: '/channels/$id', payload: builder.payload); } } @@ -66,7 +66,7 @@ class GuildChannel extends PartialChannel { /// await channel.delete() /// ``` Future delete () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.destroy(url: '/channels/$id'); guild.channels.cache.remove(this); diff --git a/lib/src/api/channels/news_channel.dart b/lib/src/api/channels/news_channel.dart index b74aaedfd..b000a39bf 100644 --- a/lib/src/api/channels/news_channel.dart +++ b/lib/src/api/channels/news_channel.dart @@ -33,7 +33,7 @@ class NewsChannel extends TextChannel { return; } - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); await http.post(url: '/channels/$id/followers', payload: { 'webhook_channel_id': webhookId }); diff --git a/lib/src/api/channels/partial_channel.dart b/lib/src/api/channels/partial_channel.dart index 7a2c30104..4f51d872e 100644 --- a/lib/src/api/channels/partial_channel.dart +++ b/lib/src/api/channels/partial_channel.dart @@ -68,6 +68,8 @@ class ChannelWrapper { return ThreadChannel.fromPayload(payload); case ChannelType.guildStageVoice: return StageChannel.fromPayload(payload); + case ChannelType.guildForum: + return ForumChannel.fromPayload(payload); default: Console.warn(message: "$channelType is not supported"); } diff --git a/lib/src/api/channels/partial_text_channel.dart b/lib/src/api/channels/partial_text_channel.dart index 986521a21..1ca4fa6ed 100644 --- a/lib/src/api/channels/partial_text_channel.dart +++ b/lib/src/api/channels/partial_text_channel.dart @@ -25,7 +25,7 @@ class PartialTextChannel extends GuildChannel { /// await channel.send(content: 'Hello world ! 🔥'); /// ``` Future send ({ String? content, List? embeds, List? components, bool? tts }) async { - MineralClient client = ioc.singleton(ioc.services.client); + MineralClient client = ioc.singleton(Service.client); Response response = await client.sendMessage(this, content: content, diff --git a/lib/src/api/channels/text_based_channel.dart b/lib/src/api/channels/text_based_channel.dart index f4ecc8e5b..1b70d7b74 100644 --- a/lib/src/api/channels/text_based_channel.dart +++ b/lib/src/api/channels/text_based_channel.dart @@ -26,7 +26,7 @@ class TextBasedChannel extends PartialTextChannel { /// Access to [WebhookManager] WebhookManager get webhooks => _webhooks; - /// Allow or disallow [nsfw] of this + /// Allow or disallow nsfw of this Future setNsfw (bool value) async { await update(ChannelBuilder({ 'nsfw': value })); } diff --git a/lib/src/api/channels/text_channel.dart b/lib/src/api/channels/text_channel.dart index 0228e2fc4..66baedaf8 100644 --- a/lib/src/api/channels/text_channel.dart +++ b/lib/src/api/channels/text_channel.dart @@ -73,7 +73,7 @@ class TextChannel extends TextBasedChannel { payload['topic'], payload['last_pin_timestamp'], payload['rate_limit_per_user'], - ThreadManager(payload['guild_id']) , + ThreadManager(payload['guild_id']), payload['nsfw'] ?? false, WebhookManager(payload['guild_id'], payload['id']), MessageManager(), diff --git a/lib/src/api/channels/thread_channel.dart b/lib/src/api/channels/thread_channel.dart index 4dea971ab..ea63a90b9 100644 --- a/lib/src/api/channels/thread_channel.dart +++ b/lib/src/api/channels/thread_channel.dart @@ -48,9 +48,11 @@ class ThreadChannel extends PartialTextChannel { factory ThreadChannel.fromPayload(dynamic payload) { final permissionOverwriteManager = PermissionOverwriteManager(); - for (final element in payload['permission_overwrites']) { - final PermissionOverwrite overwrite = PermissionOverwrite.from(payload: element); - permissionOverwriteManager.cache.putIfAbsent(overwrite.id, () => overwrite); + if (payload['permission_overwrites'] != null) { + for (final element in payload['permission_overwrites']) { + final PermissionOverwrite overwrite = PermissionOverwrite.from(payload: element); + permissionOverwriteManager.cache.putIfAbsent(overwrite.id, () => overwrite); + } } return ThreadChannel( @@ -58,7 +60,7 @@ class ThreadChannel extends PartialTextChannel { payload['thread_metadata']['auto_archive_duration'], payload['thread_metadata']['locked'], payload['thread_metadata']['invitable'], - payload['create_timestamp'], + payload['thread_metadata']['create_timestamp'], MessageManager(), payload['last_message_id'], payload['guild_id'], diff --git a/lib/src/api/channels/voice_channel.dart b/lib/src/api/channels/voice_channel.dart index 5ac735e8c..a4d8a38df 100644 --- a/lib/src/api/channels/voice_channel.dart +++ b/lib/src/api/channels/voice_channel.dart @@ -64,7 +64,7 @@ class VoiceChannel extends TextBasedChannel { } @override - CategoryChannel get parent => super.parent as CategoryChannel; + CategoryChannel? get parent => super.parent as CategoryChannel?; factory VoiceChannel.fromPayload(dynamic payload) { final permissionOverwriteManager = PermissionOverwriteManager(); diff --git a/lib/src/api/client/mineral_client.dart b/lib/src/api/client/mineral_client.dart index 232dbf587..e2281bc4b 100644 --- a/lib/src/api/client/mineral_client.dart +++ b/lib/src/api/client/mineral_client.dart @@ -70,7 +70,7 @@ class MineralClient { /// ); /// ``` void setPresence ({ ClientActivity? activity, ClientStatus? status, bool? afk }) { - ShardManager manager = ioc.singleton(ioc.services.shards); + ShardManager manager = ioc.singleton(Service.shards); manager.send(OpCode.statusUpdate, { 'since': DateTime.now().millisecond, 'activities': activity != null ? [activity.toJson()] : [], @@ -86,12 +86,12 @@ class MineralClient { /// final int latency = client.getLatency(); /// ``` int getLatency () { - ShardManager manager = ioc.singleton(ioc.services.shards); + ShardManager manager = ioc.singleton(Service.shards); return manager.getLatency(); } Future registerGlobalCommands ({ required List commands }) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); await http.put( url: "/applications/${_application.id}/commands", @@ -100,7 +100,7 @@ class MineralClient { } Future registerGuildCommands ({ required Guild guild, required List commands, required List contextMenus }) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); await http.put( url: "/applications/${_application.id}/guilds/${guild.id}/commands", payload: [ @@ -111,7 +111,7 @@ class MineralClient { } factory MineralClient.from({ required dynamic payload }) { - ShardManager manager = ioc.singleton(ioc.services.shards); + ShardManager manager = ioc.singleton(Service.shards); return MineralClient( User.from(payload['user']), diff --git a/lib/src/api/components/code_builder.dart b/lib/src/api/components/code_builder.dart new file mode 100644 index 000000000..0a5f6d0b5 --- /dev/null +++ b/lib/src/api/components/code_builder.dart @@ -0,0 +1,16 @@ +import 'dart:convert'; + +class CodeBuilder { + final String _language; + final dynamic _code; + int? indent; + + + CodeBuilder(this._language, this._code, { this.indent }); + + @override + String toString () { + final encoder = JsonEncoder.withIndent(List.filled(indent ?? 2, ' ').join()); + return '```$_language\n' + encoder.convert(_code) + '```'; + } +} diff --git a/lib/src/api/components/forum_tag_builder.dart b/lib/src/api/components/forum_tag_builder.dart new file mode 100644 index 000000000..577194823 --- /dev/null +++ b/lib/src/api/components/forum_tag_builder.dart @@ -0,0 +1,30 @@ +import 'package:mineral/api.dart'; + +class ForumTagBuilder { + final String label; + final bool moderated; + final EmojiBuilder? emoji; + + ForumTagBuilder({ + required this.label, + required this.moderated, + this.emoji, + }); + + Object toJson () { + final json = { + 'name': label, + 'moderated': moderated, + }; + + if (emoji is EmojiBuilder && emoji!.emoji.label.isNotEmpty) { + json.putIfAbsent('emoji_name', () => emoji!.emoji.label); + } + + if (emoji is EmojiBuilder && emoji!.emoji.id.isNotEmpty) { + json.putIfAbsent('emoji_id', () => emoji!.emoji.id); + } + + return json; + } +} diff --git a/lib/src/api/components/message_builder.dart b/lib/src/api/components/message_builder.dart new file mode 100644 index 000000000..02ee02492 --- /dev/null +++ b/lib/src/api/components/message_builder.dart @@ -0,0 +1,19 @@ +import 'package:mineral/api.dart'; +import 'package:mineral/src/api/components/component.dart'; +import 'package:mineral/src/api/messages/message_sticker_item.dart'; + +class MessageBuilder { + final String? content; + final List? embeds; + final List? components; + final List? stickers; + + MessageBuilder({ this.content, this.embeds, this.components, this.stickers }); + + Object toJson () => { + 'content': content, + 'embeds': embeds?.map((embed) => embed.toJson()), + 'components': components?.map((component) => component.toJson()), + 'stickers': stickers?.map((sticker) => sticker.toJson()) + }; +} diff --git a/lib/src/api/emoji.dart b/lib/src/api/emoji.dart index a8544743e..55883392e 100644 --- a/lib/src/api/emoji.dart +++ b/lib/src/api/emoji.dart @@ -66,7 +66,7 @@ class Emoji extends PartialEmoji { /// } /// ``` Future setLabel (String label) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/${manager.guild.id}/emojis/$id", payload: { 'name': label }); if (response.statusCode == 200) { @@ -90,7 +90,7 @@ class Emoji extends PartialEmoji { /// await emoji.delete(reason: 'I will destroy this..'); /// ``` Future delete () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.destroy(url: "/guilds/${manager.guild.id}/emojis/$id"); if (response.statusCode == 200) { diff --git a/lib/src/api/forum_tag.dart b/lib/src/api/forum_tag.dart new file mode 100644 index 000000000..716c2325f --- /dev/null +++ b/lib/src/api/forum_tag.dart @@ -0,0 +1,17 @@ +import 'package:mineral/api.dart'; +import 'package:mineral/src/api/emoji.dart'; + +class ForumTag { + final Snowflake _id; + final String _label; + final bool _moderated; + final Snowflake _emojiId; + final String _emojiLabel; + final Snowflake _channelId; + + ForumTag(this._id, this._label, this._moderated, this._emojiId, this._emojiLabel, this._channelId); + + Snowflake get id => _id; + String get label => _label; + bool get moderated => _moderated; +} diff --git a/lib/src/api/guilds/guild.dart b/lib/src/api/guilds/guild.dart index 34e85713c..7012eb85f 100644 --- a/lib/src/api/guilds/guild.dart +++ b/lib/src/api/guilds/guild.dart @@ -172,7 +172,7 @@ class Guild { ModerationRuleManager get moderationRules => _moderationRules; GuildWebhookManager get webhooks => _webhooks; GuildScheduledEventManager get scheduledEvents => _scheduledEvents; - Map get bots => _members.cache.where((element) => element.isBot()); + Map get bots => _members.cache.where((element) => element.isBot); /// ### Modifies the [name] of this. /// @@ -181,7 +181,7 @@ class Guild { /// await guild.setName('Guild name'); /// ``` Future setName (String name) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'name': name }); if (response.statusCode == 200) { @@ -198,7 +198,7 @@ class Guild { /// await guild.setVerificationLevel(VerificationLevel.veryHigh); /// ``` Future setVerificationLevel (VerificationLevel level) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'verification_level': level.value }); if (response.statusCode == 200) { @@ -215,7 +215,7 @@ class Guild { /// await guild.setMessageNotification(1); /// ``` Future setMessageNotification (int level) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'default_message_notifications': level }); if (response.statusCode == 200) { @@ -234,7 +234,7 @@ class Guild { /// await guild.setExplicitContentFilter(2); /// ``` Future setExplicitContentFilter (int level) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'explicit_content_filter': level }); if (response.statusCode == 200) { @@ -253,7 +253,7 @@ class Guild { /// } /// ``` Future setAfkChannel (VoiceChannel channel) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'afk_channel_id': channel.id }); if (response.statusCode == 200) { @@ -276,8 +276,8 @@ class Guild { /// } /// ``` Future setOwner (GuildMember guildMember) async { - MineralClient client = ioc.singleton(ioc.services.client); - Http http = ioc.singleton(ioc.services.http); + MineralClient client = ioc.singleton(Service.client); + Http http = ioc.singleton(Service.http); if (owner.id != client.user.id) { Console.error(message: "You cannot change the owner of the server because it does not belong to the ${client.user.username} client."); @@ -306,7 +306,7 @@ class Guild { String file = await Helper.getPicture(filename); - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'splash': file }); if (response.statusCode == 200) { @@ -327,7 +327,7 @@ class Guild { throw MissingFeatureException(cause: "The $name guild does not have the ${GuildFeature.inviteSplash} feature."); } - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'splash': null }); if (response.statusCode == 200) { @@ -350,7 +350,7 @@ class Guild { String file = await Helper.getPicture(filename); - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'discovery_splash': file }); if (response.statusCode == 200) { @@ -371,7 +371,7 @@ class Guild { throw MissingFeatureException(cause: "The $name guild does not have the ${GuildFeature.discoverable} feature."); } - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'discovery_splash': null }); if (response.statusCode == 200) { @@ -394,7 +394,7 @@ class Guild { String file = await Helper.getPicture(filename); - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'banner': file }); if (response.statusCode == 200) { @@ -415,7 +415,7 @@ class Guild { throw MissingFeatureException(cause: "The $name guild does not have the ${GuildFeature.banner} feature."); } - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'banner': null }); if (response.statusCode == 200) { @@ -432,7 +432,7 @@ class Guild { Future setIcon (String filename) async { String file = await Helper.getPicture(filename); - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'icon': file }); if (response.statusCode == 200) { @@ -447,7 +447,7 @@ class Guild { /// await guild.removeIcon(); /// ``` Future removeIcon () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'icon': null }); if (response.statusCode == 200) { @@ -466,7 +466,7 @@ class Guild { /// } /// ``` Future setSystemChannel (TextChannel channel) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'system_channel_id': channel.id }); if (response.statusCode == 200) { @@ -486,7 +486,7 @@ class Guild { /// } /// ``` Future setRulesChannel (TextChannel channel) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'rules_channel_id': channel.id }); if (response.statusCode == 200) { @@ -506,7 +506,7 @@ class Guild { /// } /// ``` Future setPublicUpdateChannel (TextChannel channel) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'public_updates_channel_id': channel.id }); if (response.statusCode == 200) { @@ -524,7 +524,7 @@ class Guild { /// await guild.setPreferredLocale(Locale.fr); // 👈 Now you can use Lang enum /// ``` Future setPreferredLocale (Locale locale) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$id", payload: { 'public_updates_channel_id': locale }); if (response.statusCode == 200) { @@ -539,17 +539,17 @@ class Guild { /// await guild.leave(); /// ``` Future leave () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.destroy(url: '/users/@me/guilds/$id'); if (response.statusCode == 204) { - MineralClient client = ioc.singleton(ioc.services.client); + MineralClient client = ioc.singleton(Service.client); client.guilds.cache.remove(this); } } Future preview () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.get(url: '/guilds/$id/preview'); return GuildPreview.from( @@ -558,6 +558,19 @@ class Guild { ); } + /// ### Unbanned this from the [Guild] and deleted its messages for a given period + /// + /// Example : + /// ```dart + /// await member.unban(); + /// ``` + Future ban (Snowflake memberId, { String? reason }) async { + Http http = ioc.singleton(Service.http); + Response response = await http.destroy(url: '/guilds/$id/bans/$memberId'); + + return response.statusCode == 200; + } + factory Guild.from({ required EmojiManager emojiManager, required MemberManager memberManager, diff --git a/lib/src/api/guilds/guild_member.dart b/lib/src/api/guilds/guild_member.dart index 010961e1e..7fa70f91d 100644 --- a/lib/src/api/guilds/guild_member.dart +++ b/lib/src/api/guilds/guild_member.dart @@ -33,7 +33,7 @@ class GuildMember { Snowflake get id => _user.id; User get user => _user; - String? get nickname => _nickname; + String get nickname => _nickname ?? _user.username; ImageFormater? get avatar => _avatar; DateTime get joinedAt => _joinedAt; DateTime? get premiumSince => _premiumSince; @@ -42,8 +42,8 @@ class GuildMember { DateTime? get timeoutDuration => _timeoutDuration; MemberRoleManager get roles => _roles; Guild get guild => _guild; - bool get hasGuildAvatar => avatar != null; + Locale get lang => _user.lang; /// ### Update the username of this /// @@ -52,7 +52,7 @@ class GuildMember { /// await member.setUsername('John Doe'); /// ``` Future setUsername (String name) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/${guild.id}/members/${user.id}", payload: { 'nick': name }); if (response.statusCode == 200) { @@ -73,7 +73,7 @@ class GuildMember { /// ``` Future timeout (DateTime expiration) async { // @Todo add ADMINISTRATOR permission or is the owner of the guild constraint - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: '/guilds/${guild.id}/members/${user.id}', payload: { 'communication_disabled_until': expiration.toIso8601String() }); if (response.statusCode == 200 || response.statusCode == 204) { @@ -88,7 +88,7 @@ class GuildMember { /// await member.removeTimeout(); /// ``` Future removeTimeout () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: '/guilds/${guild.id}/members/${user.id}', payload: { 'communication_disabled_until': null }); if (response.statusCode == 200 || response.statusCode == 204) { @@ -109,7 +109,7 @@ class GuildMember { /// await member.ban(count: 7); /// ``` Future ban ({ int? count, String? reason }) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.put(url: "/guilds/${guild.id}/bans/${user.id}", payload: { 'delete_message_days': count, @@ -128,7 +128,7 @@ class GuildMember { /// await member.removeTimeout(); /// ``` Future kick ({ int? count, String? reason }) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); await http.destroy(url: "/guilds/${guild.id}/members/${user.id}"); } @@ -138,7 +138,7 @@ class GuildMember { /// ```dart /// print(member.isBot()); /// ``` - bool isBot () => user.bot; + bool get isBot => user.bot; /// ### Returns whether of this is pending /// @@ -149,9 +149,7 @@ class GuildMember { bool isPending () => pending; @override - String toString () { - return "<@${nickname != null ? '!' : ''}${user.id}>"; - } + String toString () => '<@${_nickname != null ? '!' : ''}${user.id}>'; GuildMember clone () => GuildMember(user, nickname, avatar, joinedAt, premiumSince, permissions, pending, timeoutDuration, roles, voice, guild); diff --git a/lib/src/api/guilds/guild_member_reaction.dart b/lib/src/api/guilds/guild_member_reaction.dart index 578f3cac8..e90cf2e73 100644 --- a/lib/src/api/guilds/guild_member_reaction.dart +++ b/lib/src/api/guilds/guild_member_reaction.dart @@ -14,7 +14,7 @@ class GuildMemberReaction { GuildMemberReaction(this._manager, this._partialEmoji, this._message, this.user); Future remove () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); String _emoji = _partialEmoji is Emoji ? '${_partialEmoji.label}:${_partialEmoji.id}' diff --git a/lib/src/api/interactions/button_interaction.dart b/lib/src/api/interactions/button_interaction.dart index 4256a73ed..737869421 100644 --- a/lib/src/api/interactions/button_interaction.dart +++ b/lib/src/api/interactions/button_interaction.dart @@ -31,7 +31,7 @@ class ButtonInteraction extends Interaction { payload['version'], payload['type'], payload['token'], - payload['user']?['id'], + payload['member']?['user']?['id'], payload['guild_id'], payload['message_id'], payload['data']['custom_id'], diff --git a/lib/src/api/interactions/command_interaction.dart b/lib/src/api/interactions/command_interaction.dart index 99eea07ce..1a6508482 100644 --- a/lib/src/api/interactions/command_interaction.dart +++ b/lib/src/api/interactions/command_interaction.dart @@ -24,7 +24,7 @@ class CommandInteraction extends Interaction { String get identifier => _identifier; TextBasedChannel? get channel => guild?.channels.cache.get(_channelId); - /// ### Returns an instance of [Channel] if the command has the designed option + /// ### Returns an instance of [PartialTextChannel] if the command has the designed option /// /// Example : /// ```dart @@ -71,7 +71,7 @@ class CommandInteraction extends Interaction { /// User? user = interaction.getUser('option_name'); /// ``` User? getUser (String optionName) { - final MineralClient client = ioc.singleton(ioc.services.client); + final MineralClient client = ioc.singleton(Service.client); return client.users.cache.get(data[optionName]?['value']); } @@ -123,7 +123,7 @@ class CommandInteraction extends Interaction { payload['version'], payload['type'], payload['token'], - payload['user']?['id'], + payload['member']?['user']?['id'], payload['guild_id'], payload['data']['name'], payload['channel_id'], diff --git a/lib/src/api/interactions/context_message_interaction.dart b/lib/src/api/interactions/context_message_interaction.dart index 58893d75e..aff95f96e 100644 --- a/lib/src/api/interactions/context_message_interaction.dart +++ b/lib/src/api/interactions/context_message_interaction.dart @@ -26,7 +26,7 @@ class ContextMessageInteraction extends Interaction { payload['version'], payload['type'], payload['token'], - payload['user']?['id'], + payload['member']?['user']?['id'], payload['guild_id'], payload['guild_id'], message, diff --git a/lib/src/api/interactions/context_user_interaction.dart b/lib/src/api/interactions/context_user_interaction.dart index 405feff58..e31e6b58e 100644 --- a/lib/src/api/interactions/context_user_interaction.dart +++ b/lib/src/api/interactions/context_user_interaction.dart @@ -26,7 +26,7 @@ class ContextUserInteraction extends Interaction { payload['version'], payload['type'], payload['token'], - payload['user']?['id'], + payload['member']?['user']?['id'], payload['guild_id'], payload['target_id'], payload['channel_id'] diff --git a/lib/src/api/interactions/interaction.dart b/lib/src/api/interactions/interaction.dart index 461ac61bf..53e7fda6f 100644 --- a/lib/src/api/interactions/interaction.dart +++ b/lib/src/api/interactions/interaction.dart @@ -30,11 +30,11 @@ class Interaction { int get version => _version; InteractionType get type => InteractionType.values.firstWhere((element) => element.value == _typeId); String get token => _token; - Guild? get guild => ioc.singleton(ioc.services.client).guilds.cache.get(_guildId); + Guild? get guild => ioc.singleton(Service.client).guilds.cache.get(_guildId); User get user => _guildId != null ? guild!.members.cache.getOrFail(_userId).user - : ioc.singleton(ioc.services.client).users.cache.getOrFail(_userId); + : ioc.singleton(Service.client).users.cache.getOrFail(_userId); GuildMember? get member => guild?.members.cache.get(_userId); @@ -45,7 +45,7 @@ class Interaction { /// await interaction.reply(content: 'Hello ${interaction.user.username}'); /// ``` Future reply ({ String? content, List? embeds, List? components, bool? tts, bool? private }) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); List embedList = []; if (embeds != null) { @@ -73,7 +73,7 @@ class Interaction { }); } - /// ### Responds to this by an [Modal] + /// ### Responds to this by an [ModalBuilder] /// /// Example : /// ```dart @@ -84,7 +84,7 @@ class Interaction { /// await interaction.modal(modal); /// ``` Future modal (ModalBuilder modal) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); await http.post(url: "/interactions/$id/$token/callback", payload: { 'type': InteractionCallbackType.modal.value, diff --git a/lib/src/api/interactions/select_menu_interaction.dart b/lib/src/api/interactions/select_menu_interaction.dart index 8f12c8e70..2d3d2a785 100644 --- a/lib/src/api/interactions/select_menu_interaction.dart +++ b/lib/src/api/interactions/select_menu_interaction.dart @@ -51,7 +51,7 @@ class SelectMenuInteraction extends Interaction { payload['version'], payload['type'], payload['token'], - payload['user']?['id'], + payload['member']?['user']?['id'], payload['guild_id'], message, payload['data']['custom_id'], diff --git a/lib/src/api/managers/channel_manager.dart b/lib/src/api/managers/channel_manager.dart index f61bfafd7..294966b5e 100644 --- a/lib/src/api/managers/channel_manager.dart +++ b/lib/src/api/managers/channel_manager.dart @@ -11,10 +11,10 @@ class ChannelManager extends CacheManager { ChannelManager(this._guildId); - Guild get guild => ioc.singleton(ioc.services.client).guilds.cache.getOrFail(_guildId); + Guild get guild => ioc.singleton(Service.client).guilds.cache.getOrFail(_guildId); Future> sync () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); cache.clear(); Response response = await http.get(url: "/guilds/$_guildId/channels"); @@ -32,11 +32,14 @@ class ChannelManager extends CacheManager { } Future create (ChannelBuilder builder) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); + Response response = await http.post(url: '/guilds/$_guildId/channels', payload: builder.payload); dynamic payload = jsonDecode(response.body); + print(payload); + final GuildChannel? channel = ChannelWrapper.create(payload); return channel as T; } diff --git a/lib/src/api/managers/emoji_manager.dart b/lib/src/api/managers/emoji_manager.dart index ff08ef2c9..5e601d41e 100644 --- a/lib/src/api/managers/emoji_manager.dart +++ b/lib/src/api/managers/emoji_manager.dart @@ -11,7 +11,7 @@ class EmojiManager extends CacheManager { late final Guild guild; Future> sync () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); cache.clear(); Response response = await http.get(url: "/guilds/${guild.id}/emojis"); @@ -36,7 +36,7 @@ class EmojiManager extends CacheManager { throw EmptyParameterException(cause: 'Parameter "path" cannot be null or empty'); } - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); String image = await Helper.getPicture(path); Response response = await http.post(url: "/guilds/${guild.id}/emojis", payload: { diff --git a/lib/src/api/managers/forum_discussion_manager.dart b/lib/src/api/managers/forum_discussion_manager.dart new file mode 100644 index 000000000..cf8b44af7 --- /dev/null +++ b/lib/src/api/managers/forum_discussion_manager.dart @@ -0,0 +1,33 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:mineral/api.dart'; +import 'package:mineral/src/api/channels/guild_channel.dart'; +import 'package:mineral/src/api/channels/thread_channel.dart'; +import 'package:mineral/src/api/managers/cache_manager.dart'; + +import 'package:mineral/core.dart'; + +class ForumDiscussionManager extends CacheManager { + final Snowflake _channelId; + + ForumDiscussionManager(this._channelId); + + /// Create a new discussion within a forum. + /// Warning guild requires [GuildFeature.community] feature + /// ``` + Future create (String label, MessageBuilder message, { int? archiveDuration, int? rateLimit, List? tags, bool? pin }) async { + Http http = ioc.singleton(Service.http); + + Response response = await http.post(url: '/channels/$_channelId/threads', payload: { + 'name': label, + 'auto_archive_duration': archiveDuration, + 'rate_limit_per_user': rateLimit, + 'applied_tags': tags, + 'message': message.toJson(), + 'flags': Flag.pinned.value, + }); + + return ThreadChannel.fromPayload(jsonDecode(response.body)); + } +} diff --git a/lib/src/api/managers/guild_role_manager.dart b/lib/src/api/managers/guild_role_manager.dart index 25a6cce92..26478e811 100644 --- a/lib/src/api/managers/guild_role_manager.dart +++ b/lib/src/api/managers/guild_role_manager.dart @@ -17,7 +17,7 @@ class GuildRoleManager extends CacheManager { /// await guild.roles.sync(); /// ``` Future> sync () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); cache.clear(); Response response = await http.get(url: "/guilds/${guild.id}/roles"); @@ -55,7 +55,7 @@ class GuildRoleManager extends CacheManager { String? _icon = icon != null ? await Helper.getPicture(icon) : null; int? _permissions = permissions != null ? Helper.reduceRolePermissions(permissions) : null; - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.post(url: "/guilds/${guild.id}/roles", payload: { 'name': label, 'color': color != null ? Helper.toRgbColor(color) : null, diff --git a/lib/src/api/managers/guild_scheduled_event_manager.dart b/lib/src/api/managers/guild_scheduled_event_manager.dart index f87e966fe..7109c21a7 100644 --- a/lib/src/api/managers/guild_scheduled_event_manager.dart +++ b/lib/src/api/managers/guild_scheduled_event_manager.dart @@ -9,7 +9,7 @@ class GuildScheduledEventManager extends CacheManager { late final Guild guild; Future> sync() async { - final Http http = ioc.singleton(ioc.services.http); + final Http http = ioc.singleton(Service.http); Response response = await http.get(url: "/guilds/${guild.id}/scheduled-events"); if (response.statusCode == 200) { diff --git a/lib/src/api/managers/guild_webhook_manager.dart b/lib/src/api/managers/guild_webhook_manager.dart index 634e17a48..8ecdddbb1 100644 --- a/lib/src/api/managers/guild_webhook_manager.dart +++ b/lib/src/api/managers/guild_webhook_manager.dart @@ -12,7 +12,7 @@ class GuildWebhookManager extends CacheManager { GuildWebhookManager(); Future> sync () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.get(url: "/guilds/${guild.id}/webhooks"); for (dynamic element in jsonDecode(response.body)) { diff --git a/lib/src/api/managers/member_manager.dart b/lib/src/api/managers/member_manager.dart index 4e442f701..51c746775 100644 --- a/lib/src/api/managers/member_manager.dart +++ b/lib/src/api/managers/member_manager.dart @@ -10,7 +10,7 @@ class MemberManager extends CacheManager { Guild get guild => _guild; Future> sync () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.get(url: "/guilds/${_guild.id}/members"); if(response.statusCode == 200) { @@ -21,17 +21,14 @@ class MemberManager extends CacheManager { for(dynamic element in payload) { VoiceManager? voiceManager = voiceStateCache.get(element['user']['id']); - VoiceChannel? voiceChannel = guild.channels.cache.get(payload['channel_id']); GuildMember guildMember = GuildMember.from( user: User.from(element['user']), roles: _guild.roles, guild: _guild, - voice: voiceManager ?? VoiceManager.from(payload, null, voiceChannel) + voice: voiceManager ?? VoiceManager.empty(element['deaf'], element['mute'], element['user']['id'], _guild.id) ); - guildMember.voice.member = guildMember; - cache.putIfAbsent(guildMember.user.id, () => guildMember); } } diff --git a/lib/src/api/managers/member_role_manager.dart b/lib/src/api/managers/member_role_manager.dart index a522438c0..9d942abce 100644 --- a/lib/src/api/managers/member_role_manager.dart +++ b/lib/src/api/managers/member_role_manager.dart @@ -34,7 +34,7 @@ class MemberRoleManager extends CacheManager { /// await member.roles.add('446556480850755604', reason: 'I love this user'); /// ``` Future add (Snowflake id, {String? reason}) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Role? role = manager.cache.get(id); if(role == null) { @@ -75,7 +75,7 @@ class MemberRoleManager extends CacheManager { /// await member.roles.remove('446556480850755604', reason: 'Hello, World!'); /// ``` Future remove (Snowflake id, {String? reason}) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Map headers = {}; if(reason != null) { @@ -116,7 +116,7 @@ class MemberRoleManager extends CacheManager { } Future> sync () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.get(url: "/guilds/${manager.guild.id}/members/$memberId"); if(response.statusCode == 200) { diff --git a/lib/src/api/managers/message_manager.dart b/lib/src/api/managers/message_manager.dart index 6c8069321..9d626ae92 100644 --- a/lib/src/api/managers/message_manager.dart +++ b/lib/src/api/managers/message_manager.dart @@ -10,7 +10,7 @@ class MessageManager extends CacheManager { late final TextBasedChannel channel; Future> sync () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); cache.clear(); Response response = await http.get(url: "/channels/${channel.id}/messages"); diff --git a/lib/src/api/managers/message_reaction_manager.dart b/lib/src/api/managers/message_reaction_manager.dart index 232e5c285..bd3b6708f 100644 --- a/lib/src/api/managers/message_reaction_manager.dart +++ b/lib/src/api/managers/message_reaction_manager.dart @@ -16,8 +16,8 @@ class MessageReactionManager MessageReactionManager(this._channel); Future add (EmojiBuilder emojiBuilder) async { - Http http = ioc.singleton(ioc.services.http); - MineralClient client = ioc.singleton(ioc.services.client); + Http http = ioc.singleton(Service.http); + MineralClient client = ioc.singleton(Service.client); String _emoji = emojiBuilder.emoji is Emoji ? '${emojiBuilder.emoji.label}:${emojiBuilder.emoji.id}' @@ -47,7 +47,7 @@ class MessageReactionManager } Future removeAll () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.destroy(url: '/channels/${message.channel.id}/messages/${message.id}/reactions'); if (response.statusCode == 200) { diff --git a/lib/src/api/managers/moderation_rule_manager.dart b/lib/src/api/managers/moderation_rule_manager.dart index 0cf61633b..0daa10176 100644 --- a/lib/src/api/managers/moderation_rule_manager.dart +++ b/lib/src/api/managers/moderation_rule_manager.dart @@ -9,7 +9,7 @@ class ModerationRuleManager extends CacheManager { late final Guild guild; Future create ({ required String label, required ModerationEventType eventType, required ModerationTriggerType triggerType, ModerationTriggerMetadata? triggerMetadata, List? actions, bool? enabled, List? exemptRoles, List? exemptChannels }) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); /** * @Todo Add contraints diff --git a/lib/src/api/managers/sticker_manager.dart b/lib/src/api/managers/sticker_manager.dart index c7ca8c2a9..8f0e22f0e 100644 --- a/lib/src/api/managers/sticker_manager.dart +++ b/lib/src/api/managers/sticker_manager.dart @@ -13,7 +13,7 @@ class StickerManager extends CacheManager { Future create ({ required String name, required String description, required String tags, required String filename }) async { if (guild.features.contains(GuildFeature.verified) || guild.features.contains(GuildFeature.partnered)) { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.post(url: "/guilds/${guild.id}/stickers", payload: { 'name': name, 'description': description, @@ -39,7 +39,7 @@ class StickerManager extends CacheManager { } Future> sync () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); cache.clear(); Response response = await http.get(url: "/guilds/${guild.id}/stickers"); diff --git a/lib/src/api/managers/thread_manager.dart b/lib/src/api/managers/thread_manager.dart index 09b082021..fdd9e1230 100644 --- a/lib/src/api/managers/thread_manager.dart +++ b/lib/src/api/managers/thread_manager.dart @@ -15,10 +15,10 @@ class ThreadManager extends CacheManager { ThreadManager(this._guildId); /// Get [Guild] from [Ioc] - Guild get guild => ioc.singleton(ioc.services.client).guilds.cache.getOrFail(_guildId); + Guild get guild => ioc.singleton(Service.client).guilds.cache.getOrFail(_guildId); Future> sync () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); cache.clear(); Response response = await http.get(url: "/guilds/$_guildId/threads/active"); @@ -33,7 +33,7 @@ class ThreadManager extends CacheManager { } Future create ({ Snowflake? messageId, String? label }) async { - MineralClient client = ioc.singleton(ioc.services.client); + MineralClient client = ioc.singleton(Service.client); return await client.createChannel(_guildId, ChannelBuilder({ 'name': label, 'auto_archive_duration': '60', diff --git a/lib/src/api/managers/voice_manager.dart b/lib/src/api/managers/voice_manager.dart index cbbb17051..7fd9597ba 100644 --- a/lib/src/api/managers/voice_manager.dart +++ b/lib/src/api/managers/voice_manager.dart @@ -1,5 +1,6 @@ import 'package:http/http.dart'; import 'package:mineral/api.dart'; +import 'package:mineral/console.dart'; import 'package:mineral/core.dart'; class VoiceManager { @@ -9,10 +10,11 @@ class VoiceManager { bool _isSelfDeaf; bool _hasVideo; bool? _hasStream; - VoiceChannel? channel; - GuildMember? member; + Snowflake _guildId; + Snowflake? _channelId; + Snowflake _memberId; - VoiceManager( this._isDeaf, this._isMute, this._isSelfMute, this._isSelfDeaf, this._hasVideo, this._hasStream, this.channel, this.member); + VoiceManager( this._isDeaf, this._isMute, this._isSelfMute, this._isSelfDeaf, this._hasVideo, this._hasStream, this._channelId, this._memberId, this._guildId); bool get isDeaf => _isDeaf; bool get isMute => _isMute; @@ -21,6 +23,10 @@ class VoiceManager { bool get hasVideo => _hasVideo; bool? get hasStream => _hasStream; + Guild get guild => ioc.singleton(Service.client).guilds.cache.getOrFail(_guildId); + VoiceChannel? get channel => guild.channels.cache.get(_channelId); + GuildMember get member => guild.members.cache.getOrFail(_memberId); + /// ### Mutes or unmute a server member /// /// Example : @@ -31,16 +37,19 @@ class VoiceManager { /// await member.setMute(true); /// } Future setMute(bool value) async { - final Http http = ioc.singleton(ioc.services.http); + final Http http = ioc.singleton(Service.http); final Response response = await http.patch( - url: '/guilds/${member!.guild.id}/members/${member!.user.id}', + url: '/guilds/$_guildId/members/$_memberId', payload: {'mute': value} ); if (response.statusCode == 204 || response.statusCode == 200) { _isMute = value; + return; } + + Console.error(message: 'Unable to ${value ? 'mute' : 'unmute'} user #$_memberId'); } /// ### Deafens or not a server member @@ -53,15 +62,18 @@ class VoiceManager { /// await member.setDeaf(true); /// } Future setDeaf(bool value) async { - final Http http = ioc.singleton(ioc.services.http); + final Http http = ioc.singleton(Service.http); final Response response = await http.patch( - url: '/guilds/${member!.guild.id}/members/${member!.user.id}', + url: '/guilds/$_guildId/members/$_memberId', payload: {'deaf': value} ); if (response.statusCode == 204 || response.statusCode == 200) { _isDeaf = value; + return; } + + Console.error(message: 'Unable to ${value ? 'deaf' : 'undeaf'} user #$_memberId'); } /// ### Moves a member from one voice channel to another @@ -92,21 +104,21 @@ class VoiceManager { } Future _updateChannel(Snowflake? channelId) async { - final Http http = ioc.singleton(ioc.services.http); + final Http http = ioc.singleton(Service.http); final Response response = await http.patch( - url: '/guilds/${member!.guild.id}/members/${member!.user.id}', + url: '/guilds/$_guildId/members/$_memberId', payload: {'channel_id': channelId} ); if (response.statusCode == 204 || response.statusCode == 200) { - final VoiceChannel? channel = member!.guild.channels.cache.get(channelId); - if (channel != null) { - this.channel = channel; - } + _channelId = _channelId; + return; } + + Console.error(message: 'Unable to move user $_memberId to $channelId'); } - factory VoiceManager.from(dynamic payload, GuildMember? member, VoiceChannel? channel) { + factory VoiceManager.from(dynamic payload, Snowflake guildId) { return VoiceManager( payload['deaf'] == true, payload['mute'] == true, @@ -114,8 +126,13 @@ class VoiceManager { payload['self_deaf'] == true, payload['self_video'] == true, payload['self_stream'] == true, - channel, - member + payload['channel_id'], + payload['user_id'], + guildId ); } + + factory VoiceManager.empty(bool deaf, bool mute, Snowflake memberId, Snowflake guildId) { + return VoiceManager(deaf, mute, false, false, false, false, null, memberId, guildId); + } } diff --git a/lib/src/api/managers/webhook_manager.dart b/lib/src/api/managers/webhook_manager.dart index 2b4d09ce7..626847d11 100644 --- a/lib/src/api/managers/webhook_manager.dart +++ b/lib/src/api/managers/webhook_manager.dart @@ -13,10 +13,10 @@ class WebhookManager extends CacheManager { WebhookManager(this._guildId, this._channelId); /// Get [Guild] from [Ioc] - Guild get guild => ioc.singleton(ioc.services.client).guilds.cache.getOrFail(_guildId); + Guild get guild => ioc.singleton(Service.client).guilds.cache.getOrFail(_guildId); Future> sync () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.get(url: "/channels/$_channelId/webhooks"); for (dynamic element in jsonDecode(response.body)) { @@ -28,7 +28,7 @@ class WebhookManager extends CacheManager { } Future create ({ required String label, String? avatar }) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.post(url: "/channels/$_channelId/webhooks", payload: { 'name': label, 'avatar': avatar != null ? await Helper.getPicture(avatar) : null diff --git a/lib/src/api/messages/dm_message.dart b/lib/src/api/messages/dm_message.dart index bb51622de..ce6a654c6 100644 --- a/lib/src/api/messages/dm_message.dart +++ b/lib/src/api/messages/dm_message.dart @@ -30,7 +30,7 @@ class DmMessage extends PartialMessage { ); factory DmMessage.from({ required DmChannel channel, required dynamic payload }) { - MineralClient client = ioc.singleton(ioc.services.client); + MineralClient client = ioc.singleton(Service.client); User? user = client.users.cache.get(payload['author']['id']); List embeds = []; diff --git a/lib/src/api/messages/embed_builder.dart b/lib/src/api/messages/embed_builder.dart index adaccc217..a2b4bf7d1 100644 --- a/lib/src/api/messages/embed_builder.dart +++ b/lib/src/api/messages/embed_builder.dart @@ -259,7 +259,7 @@ class EmbedBuilder { } factory EmbedBuilder.fromGuildPreview(GuildPreview preview) { - MineralClient client = ioc.singleton(ioc.services.client); + MineralClient client = ioc.singleton(Service.client); final EmbedBuilder embed = EmbedBuilder( title: preview.label, diff --git a/lib/src/api/messages/message.dart b/lib/src/api/messages/message.dart index 900b46717..6f7a3e67d 100644 --- a/lib/src/api/messages/message.dart +++ b/lib/src/api/messages/message.dart @@ -45,7 +45,7 @@ class Message extends PartialMessage { MessageMention get mentions => _mentions; Future edit ({ String? content, List? embeds, List? components, bool? tts }) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch( url: '/channels/${channel.id}/messages/$id', @@ -69,7 +69,7 @@ class Message extends PartialMessage { return; } - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); await http.post(url: '/channels/${super.channel.id}/messages/${super.id}/crosspost', payload: {}); } @@ -79,7 +79,7 @@ class Message extends PartialMessage { return; } - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); await http.put(url: '/channels/${channel.id}/pins/$id', payload: {}); } @@ -89,18 +89,18 @@ class Message extends PartialMessage { return; } - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); await http.destroy(url: '/channels/${channel.id}/pins/$id'); } Future reply ({ String? content, List? embeds, List? components, bool? tts }) async { - MineralClient client = ioc.singleton(ioc.services.client); + MineralClient client = ioc.singleton(Service.client); Response response = await client.sendMessage(channel, content: content, embeds: embeds, components: components, - message_reference: { + messageReference: { 'guild_id': channel.guild.id, 'channel_id': channel.id, 'message_id': id, diff --git a/lib/src/api/messages/message_sticker_item.dart b/lib/src/api/messages/message_sticker_item.dart index cf8a7c4e9..53d7e8e15 100644 --- a/lib/src/api/messages/message_sticker_item.dart +++ b/lib/src/api/messages/message_sticker_item.dart @@ -12,6 +12,12 @@ class MessageStickerItem { required this.format, }); + Object toJson () => { + 'id': id, + 'name': name, + 'format': format.value, + }; + factory MessageStickerItem.from(dynamic payload) { return MessageStickerItem( id: payload['id'], diff --git a/lib/src/api/messages/partial_message.dart b/lib/src/api/messages/partial_message.dart index eec177550..99214b5e7 100644 --- a/lib/src/api/messages/partial_message.dart +++ b/lib/src/api/messages/partial_message.dart @@ -66,7 +66,7 @@ class PartialMessage { bool get isPinned => _pinned; PartialChannel get channel => _guildId != null - ? ioc.singleton(ioc.services.client).guilds.cache.getOrFail(_guildId).channels.cache.getOrFail(_channelId) - : ioc.singleton(ioc.services.client).dmChannels.cache.getOrFail(_channelId); + ? ioc.singleton(Service.client).guilds.cache.getOrFail(_guildId).channels.cache.getOrFail(_channelId) + : ioc.singleton(Service.client).dmChannels.cache.getOrFail(_channelId); MessageReactionManager get reactions => _reactions; } diff --git a/lib/src/api/moderation_rule.dart b/lib/src/api/moderation_rule.dart index ad678d1d8..23821f62a 100644 --- a/lib/src/api/moderation_rule.dart +++ b/lib/src/api/moderation_rule.dart @@ -126,7 +126,7 @@ class ModerationRule { /// await rule.setLabel('My label'); /// ``` Future setLabel(String label) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$guildId/auto-moderation/rules/$id", payload: { 'label': label }); if (response.statusCode == 200) { @@ -141,7 +141,7 @@ class ModerationRule { /// await rule.setEventType(ModerationEventType.messageSend); /// ``` Future setEventType(ModerationEventType event) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$guildId/auto-moderation/rules/$id", payload: { 'event_type': event.value }); if (response.statusCode == 200) { @@ -161,7 +161,7 @@ class ModerationRule { /// await rule.setTriggerMetadata(metadata); /// ``` Future setTriggerMetadata(ModerationTriggerMetadata triggerMetadata) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$guildId/auto-moderation/rules/$id", payload: { 'trigger_metadata': triggerMetadata.toJson() }); if (response.statusCode == 200) { @@ -183,7 +183,7 @@ class ModerationRule { /// await rule.setActions([action]); /// ``` Future setActions(List actions) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$guildId/auto-moderation/rules/$id", payload: { 'actions': actions.map((ModerationAction action) => action.toJson()) }); @@ -200,7 +200,7 @@ class ModerationRule { /// await rule.setEnabled(true); /// ``` Future setEnabled(bool value) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$guildId/auto-moderation/rules/$id", payload: { 'value': value }); if (response.statusCode == 200) { @@ -224,7 +224,7 @@ class ModerationRule { TooMany(cause: "The list of roles cannot exceed $maxItems items (currently ${roles.length} given)"); } - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$guildId/auto-moderation/rules/$id", payload: { 'exempt_roles': roles.map((Role role) => role.id) }); @@ -250,7 +250,7 @@ class ModerationRule { TooMany(cause: "The list of channels cannot exceed $maxItems items (currently ${channels.length} given)"); } - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/$guildId/auto-moderation/rules/$id", payload: { 'exempt_roles': channels.map((GuildChannel channel) => channel.id) }); @@ -266,7 +266,7 @@ class ModerationRule { /// await rule.delete(); /// ``` Future delete() async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.destroy(url: "/guilds/$guildId/auto-moderation/rules/$id"); return response.statusCode == 204; diff --git a/lib/src/api/role.dart b/lib/src/api/role.dart index 95d56ad00..89922dd78 100644 --- a/lib/src/api/role.dart +++ b/lib/src/api/role.dart @@ -60,7 +60,7 @@ class Role { /// } /// ``` Future setLabel (String label) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/${manager.guild.id}/roles/$id", payload: { 'name': label }); if (response.statusCode == 200) { @@ -80,7 +80,7 @@ class Role { /// } /// Future setPermissions (List permissions) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); int _permissions = Helper.reduceRolePermissions(permissions); Response response = await http.patch(url: "/guilds/${manager.guild.id}/roles/$id", payload: { 'permissions': _permissions }); @@ -108,7 +108,7 @@ class Role { /// await role.setColor(Color('#ffffff')); /// ``` Future setColor (Color color) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); int _color = Helper.toRgbColor(color); Response response = await http.patch(url: "/guilds/${manager.guild.id}/roles/$id", payload: { 'color': _color }); @@ -127,7 +127,7 @@ class Role { /// } /// ``` Future setHoist (bool hoist) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/${manager.guild.id}/roles/$id", payload: { 'hoist': hoist }); if (response.statusCode == 200) { @@ -163,7 +163,7 @@ class Role { String icon = await Helper.getPicture(path); - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/${manager.guild.id}/roles/$id", payload: { 'icon': icon }); if (response.statusCode == 200) { _icon = icon; @@ -190,7 +190,7 @@ class Role { throw MissingFeatureException(cause: "Guild ${manager.guild.name} has no 'ROLE_ICONS' feature."); } - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/${manager.guild.id}/roles/$id", payload: { 'icon': null }); if (response.statusCode == 200) { _icon = null; @@ -217,7 +217,7 @@ class Role { throw MissingFeatureException(cause: "Guild ${manager.guild.name} has no 'ROLE_ICONS' feature."); } - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/${manager.guild.id}/roles/$id", payload: { 'unicode_emoji': unicode }); if (response.statusCode == 200) { _unicodeEmoji = unicode; @@ -234,7 +234,7 @@ class Role { /// } /// ``` Future setMentionable (bool mentionable) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/${manager.guild.id}/roles/$id", payload: { 'mentionable': mentionable }); if (response.statusCode == 200) { @@ -257,14 +257,14 @@ class Role { /// ```dart /// await role.delete(reason: 'I will destroy this..'); /// ``` - /// You can't delete `@everyone` and [managed] roles. + /// You can't delete `@everyone` and managed roles. /// Future delete () async { if (isManaged || label == '@everyone') { return; } - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.destroy(url: "/guilds/${manager.guild.id}/roles/$id"); if (response.statusCode == 200) { diff --git a/lib/src/api/sticker.dart b/lib/src/api/sticker.dart index 3aab4b58a..ee6d505f5 100644 --- a/lib/src/api/sticker.dart +++ b/lib/src/api/sticker.dart @@ -62,7 +62,7 @@ class Sticker { int? get sortValue => _sortValue; Future setName (String name) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/${guild.id}/stickers/$id", payload: { 'name': name }); if (response.statusCode == 200) { @@ -71,7 +71,7 @@ class Sticker { } Future setDescription (String description) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/${guild.id}/stickers/$id", payload: { 'description': description }); if (response.statusCode == 200) { @@ -80,7 +80,7 @@ class Sticker { } Future setTags (String tags) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/guilds/${guild.id}/stickers/$id", payload: { 'tags': tags }); if (response.statusCode == 200) { @@ -89,7 +89,7 @@ class Sticker { } Future delete () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.destroy(url: "/guilds/${guild.id}/stickers/$id"); if (response.statusCode == 200) { @@ -98,7 +98,7 @@ class Sticker { } factory Sticker.from(dynamic payload) { - MineralClient client = ioc.singleton(ioc.services.client); + MineralClient client = ioc.singleton(Service.client); Guild guild = client.guilds.cache.getOrFail(payload['guild_id']); GuildMember? member = guild.members.cache.get(payload['user']?['id']); diff --git a/lib/src/api/user.dart b/lib/src/api/user.dart index d6b9992ca..0cab1592b 100644 --- a/lib/src/api/user.dart +++ b/lib/src/api/user.dart @@ -16,6 +16,7 @@ class User { int _publicFlags; ImageFormater? _avatar; ImageFormater? _avatarDecoration; + String _lang; late Status status; User( @@ -26,6 +27,7 @@ class User { this._publicFlags, this._avatar, this._avatarDecoration, + this._lang, ); Snowflake get id => _id; @@ -36,6 +38,8 @@ class User { ImageFormater? get avatar => _avatar; ImageFormater? get avatarDecoration => _avatarDecoration; String get tag => '$_username#$_discriminator'; + Locale get lang => Locale.values.firstWhere((element) => element.locale == _lang); + /// ### Returns the absolute url to the user's avatar String get defaultAvatar => _avatar != null @@ -44,7 +48,7 @@ class User { /// Return [GuildMember] of [Guild] context for this GuildMember? toGuildMember (Snowflake guildId) { - MineralClient client = ioc.singleton(ioc.services.client); + MineralClient client = ioc.singleton(Service.client); return client.guilds.cache.get(guildId)?.members.cache.get(_id); } @@ -56,8 +60,8 @@ class User { /// await member.user.send(content: 'Hello World !'); /// ``` Future send ({ String? content, List? embeds, List? components, bool? tts }) async { - MineralClient client = ioc.singleton(ioc.services.client); - Http http = ioc.singleton(ioc.services.http); + MineralClient client = ioc.singleton(Service.client); + Http http = ioc.singleton(Service.http); DmChannel? channel = client.dmChannels.cache.get(_id); @@ -98,7 +102,8 @@ class User { payload['bot'] == true, payload['public_flags'] ?? 0, payload['avatar'] != null ? ImageFormater(payload['avatar'], 'avatars/${payload['id']}') : null, - payload['avatar_decoration'] + payload['avatar_decoration'], + payload['locale'] ?? 'en-GB', ); } } diff --git a/lib/src/api/utils.dart b/lib/src/api/utils.dart index 19046c0f0..989cb5e35 100644 --- a/lib/src/api/utils.dart +++ b/lib/src/api/utils.dart @@ -93,39 +93,44 @@ class SuppressChannelFlag { } enum Locale { - da('da'), - de('de'), - enGB('en-GB'), - enUS('en-US'), - esES('es-ES'), - fr('fr'), - hr('hr'), - it('it'), - lt('lt'), - hu('hu'), - nl('nl'), - no('no'), - pl('pl'), - ptBR('pt-BR'), - ro('ro'), - fi('fi'), - svSE('sv-SE'), - vi('vi'), - tr('tr'), - cs('cs'), - el('el'), - bg('bg'), - ru('ru'), - uk('uk'), - hi('hi'), - th('th'), - zhCN('zh-CN'), - ja('ja'), - zhTW('zh-TW'), - ko('ko'); - - final String locale; - const Locale(this.locale); + da('da', null), + de('de', null), + enGB('en-GB', 'en'), + enUS('en-US', 'en'), + esES('es-ES', 'es'), + fr('fr', null), + hr('hr', null), + it('it', null), + lt('lt', null), + hu('hu', null), + nl('nl', null), + no('no', null), + pl('pl', null), + ptBR('pt-BR', 'pt'), + ro('ro', null), + fi('fi', null), + svSE('sv-SE', 'sv'), + vi('vi', null), + tr('tr', null), + cs('cs', null), + el('el', null), + bg('bg', null), + ru('ru', null), + uk('uk', null), + hi('hi', null), + th('th', null), + zhCN('zh-CN', 'zh'), + ja('ja', null), + zhTW('zh-TW', null), + ko('ko', null); + + final String _locale; + final String? _normalize; + + const Locale(this._locale, this._normalize); + + String get locale => _locale; + String? get normalize => _normalize ?? _locale; @override String toString() => locale; diff --git a/lib/src/api/webhook.dart b/lib/src/api/webhook.dart index 18f902e0b..c68c739a8 100644 --- a/lib/src/api/webhook.dart +++ b/lib/src/api/webhook.dart @@ -49,7 +49,7 @@ class Webhook { /// await webhook.setLabel('My webhook name'); /// ``` Future setLabel (String label) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.patch(url: "/webhooks/$id", payload: { 'name': label }); if (response.statusCode == 200) { @@ -64,7 +64,7 @@ class Webhook { /// await webhook.setAvatar('assets/images/my_picture.png'); /// ``` Future setAvatar (String avatar) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); String path = await Helper.getPicture(avatar); Response response = await http.patch(url: "/webhooks/$id", payload: { 'avatar': path }); @@ -81,7 +81,7 @@ class Webhook { /// await webhook.update(label: 'My webhook name', avatar: 'assets/images/my_picture.png'); /// ``` Future update ({ String? label, String? avatar }) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); String? path = avatar != null ? await Helper.getPicture(avatar) : this.label; @@ -103,7 +103,7 @@ class Webhook { /// await webhook.execute(content: 'Hello World !'); /// ``` Future execute ({ String? content, String? username, String? avatarUrl, bool? tts, List? embeds, List? components, bool? suppressEmbed }) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); List embedList = []; if (embeds != null) { @@ -137,7 +137,7 @@ class Webhook { /// await webhook.delete(); /// ``` Future delete () async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.destroy(url: "/webhooks/$id/$token"); return response.statusCode == 200; diff --git a/lib/src/commands/help.dart b/lib/src/commands/help.dart index d1a568cef..42d0c10a3 100644 --- a/lib/src/commands/help.dart +++ b/lib/src/commands/help.dart @@ -19,7 +19,7 @@ class Help extends MineralCliCommand { ? command.key.split(':').first : 'Available commands'; - CliManager cli = ioc.singleton(ioc.services.cli); + CliManager cli = ioc.singleton(Service.cli); MineralCliCommand? mineralCommand = cli.commands.get(command.key); if (commands.containsKey(key)) { diff --git a/lib/src/exceptions/already_exist.dart b/lib/src/exceptions/already_exist.dart index 6cd871ce4..0e86447eb 100644 --- a/lib/src/exceptions/already_exist.dart +++ b/lib/src/exceptions/already_exist.dart @@ -1,6 +1,7 @@ import 'package:mineral/console.dart'; import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/reporter_manager.dart'; +import 'package:mineral_ioc/ioc.dart'; class AlreadyExist implements Exception { String? prefix; @@ -9,7 +10,7 @@ class AlreadyExist implements Exception { @override String toString () { - ReporterManager? reporter = ioc.singleton(ioc.services.reporter); + ReporterManager? reporter = ioc.singleton(Service.reporter); if (reporter != null) { reporter.write('[ $prefix ] $cause'); } diff --git a/lib/src/exceptions/api_error.dart b/lib/src/exceptions/api_error.dart index 8fcefb31e..fe9c7718d 100644 --- a/lib/src/exceptions/api_error.dart +++ b/lib/src/exceptions/api_error.dart @@ -1,6 +1,6 @@ import 'package:mineral/console.dart'; -import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/reporter_manager.dart'; +import 'package:mineral_ioc/ioc.dart'; class ApiError implements Exception { String? prefix; @@ -9,7 +9,7 @@ class ApiError implements Exception { @override String toString () { - ReporterManager? reporter = ioc.singleton(ioc.services.reporter); + ReporterManager? reporter = ioc.singleton(Service.reporter); if (reporter != null) { reporter.write('[ $prefix ] $cause'); } diff --git a/lib/src/exceptions/code_error_exception.dart b/lib/src/exceptions/code_error_exception.dart index 006a96f2a..43f49d923 100644 --- a/lib/src/exceptions/code_error_exception.dart +++ b/lib/src/exceptions/code_error_exception.dart @@ -1,6 +1,6 @@ import 'package:mineral/console.dart'; -import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/reporter_manager.dart'; +import 'package:mineral_ioc/ioc.dart'; class CodeErrorException implements Exception { String? prefix; @@ -9,7 +9,7 @@ class CodeErrorException implements Exception { @override String toString () { - ReporterManager? reporter = ioc.singleton(ioc.services.reporter); + ReporterManager? reporter = ioc.singleton(Service.reporter); if (reporter != null) { reporter.write('[ $prefix ] $cause'); } diff --git a/lib/src/exceptions/empty_parameter_exception.dart b/lib/src/exceptions/empty_parameter_exception.dart index 6a96cd090..a3d67cac0 100644 --- a/lib/src/exceptions/empty_parameter_exception.dart +++ b/lib/src/exceptions/empty_parameter_exception.dart @@ -1,6 +1,6 @@ import 'package:mineral/console.dart'; -import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/reporter_manager.dart'; +import 'package:mineral_ioc/ioc.dart'; class EmptyParameterException implements Exception { String prefix = 'INVALID PARAMETER'; @@ -9,7 +9,7 @@ class EmptyParameterException implements Exception { @override String toString () { - ReporterManager? reporter = ioc.singleton(ioc.services.reporter); + ReporterManager? reporter = ioc.singleton(Service.reporter); if (reporter != null) { reporter.write('[ $prefix ] $cause'); } diff --git a/lib/src/exceptions/missing_feature_exception.dart b/lib/src/exceptions/missing_feature_exception.dart index 846f225a0..2a8e2494b 100644 --- a/lib/src/exceptions/missing_feature_exception.dart +++ b/lib/src/exceptions/missing_feature_exception.dart @@ -1,6 +1,6 @@ import 'package:mineral/console.dart'; -import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/reporter_manager.dart'; +import 'package:mineral_ioc/ioc.dart'; class MissingFeatureException implements Exception { String prefix = 'MISSING FEATURE'; @@ -10,7 +10,7 @@ class MissingFeatureException implements Exception { @override String toString () { - ReporterManager? reporter = ioc.singleton(ioc.services.reporter); + ReporterManager? reporter = ioc.singleton(Service.reporter); if (reporter != null) { reporter.write('[ $prefix ] $cause'); } diff --git a/lib/src/exceptions/missing_method_exception.dart b/lib/src/exceptions/missing_method_exception.dart index 1abd6a41e..d7b9f6dc3 100644 --- a/lib/src/exceptions/missing_method_exception.dart +++ b/lib/src/exceptions/missing_method_exception.dart @@ -1,6 +1,6 @@ import 'package:mineral/console.dart'; -import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/reporter_manager.dart'; +import 'package:mineral_ioc/ioc.dart'; class MissingMethodException implements Exception { String prefix = 'Missing method'; @@ -10,7 +10,7 @@ class MissingMethodException implements Exception { @override String toString () { - ReporterManager? reporter = ioc.singleton(ioc.services.reporter); + ReporterManager? reporter = ioc.singleton(Service.reporter); if (reporter != null) { reporter.write('[ $prefix ] $cause'); } diff --git a/lib/src/exceptions/missing_premium_subscription.dart b/lib/src/exceptions/missing_premium_subscription.dart index b63811b8b..bfb5639ed 100644 --- a/lib/src/exceptions/missing_premium_subscription.dart +++ b/lib/src/exceptions/missing_premium_subscription.dart @@ -1,6 +1,6 @@ import 'package:mineral/console.dart'; -import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/reporter_manager.dart'; +import 'package:mineral_ioc/ioc.dart'; class MissingPremiumSubscription implements Exception { String? prefix; @@ -9,7 +9,7 @@ class MissingPremiumSubscription implements Exception { @override String toString () { - ReporterManager? reporter = ioc.singleton(ioc.services.reporter); + ReporterManager? reporter = ioc.singleton(Service.reporter); if (reporter != null) { reporter.write('[ $prefix ] $cause'); } diff --git a/lib/src/exceptions/not_exist.dart b/lib/src/exceptions/not_exist.dart index 034d3b81a..0ab8e8670 100644 --- a/lib/src/exceptions/not_exist.dart +++ b/lib/src/exceptions/not_exist.dart @@ -1,6 +1,6 @@ import 'package:mineral/console.dart'; -import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/reporter_manager.dart'; +import 'package:mineral_ioc/ioc.dart'; class NotExist implements Exception { String? prefix; @@ -9,7 +9,7 @@ class NotExist implements Exception { @override String toString () { - ReporterManager? reporter = ioc.singleton(ioc.services.reporter); + ReporterManager? reporter = ioc.singleton(Service.reporter); if (reporter != null) { reporter.write('[ $prefix ] $cause'); } diff --git a/lib/src/exceptions/shard_exception.dart b/lib/src/exceptions/shard_exception.dart index 6b1bbc91a..a8c67ab82 100644 --- a/lib/src/exceptions/shard_exception.dart +++ b/lib/src/exceptions/shard_exception.dart @@ -1,6 +1,6 @@ import 'package:mineral/console.dart'; -import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/reporter_manager.dart'; +import 'package:mineral_ioc/ioc.dart'; class ShardException implements Exception { String? prefix; @@ -9,7 +9,7 @@ class ShardException implements Exception { @override String toString () { - ReporterManager? reporter = ioc.singleton(ioc.services.reporter); + ReporterManager? reporter = ioc.singleton(Service.reporter); if (reporter != null) { reporter.write('[ $prefix ] $cause'); } diff --git a/lib/src/exceptions/token_exception.dart b/lib/src/exceptions/token_exception.dart index 95cd4961a..63b285b78 100644 --- a/lib/src/exceptions/token_exception.dart +++ b/lib/src/exceptions/token_exception.dart @@ -1,6 +1,6 @@ import 'package:mineral/console.dart'; -import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/reporter_manager.dart'; +import 'package:mineral_ioc/ioc.dart'; class TokenException implements Exception { String? prefix; @@ -9,7 +9,7 @@ class TokenException implements Exception { @override String toString () { - ReporterManager? reporter = ioc.singleton(ioc.services.reporter); + ReporterManager? reporter = ioc.singleton(Service.reporter); if (reporter != null) { reporter.write('[ $prefix ] $cause'); } diff --git a/lib/src/exceptions/too_many.dart b/lib/src/exceptions/too_many.dart index 474a507a7..b83fecf5f 100644 --- a/lib/src/exceptions/too_many.dart +++ b/lib/src/exceptions/too_many.dart @@ -1,6 +1,6 @@ import 'package:mineral/console.dart'; -import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/reporter_manager.dart'; +import 'package:mineral_ioc/ioc.dart'; class TooMany implements Exception { String? prefix; @@ -9,7 +9,7 @@ class TooMany implements Exception { @override String toString () { - ReporterManager? reporter = ioc.singleton(ioc.services.reporter); + ReporterManager? reporter = ioc.singleton(Service.reporter); if (reporter != null) { reporter.write('[ $prefix ] $cause'); } diff --git a/lib/src/internal/entities/event.dart b/lib/src/internal/entities/event.dart index 4212ba07c..abb63dc4a 100644 --- a/lib/src/internal/entities/event.dart +++ b/lib/src/internal/entities/event.dart @@ -54,6 +54,7 @@ enum Events { voiceStateUpdate('update::voice', { 'before': VoiceManager, 'after': VoiceManager }), voiceConnect('connect::voice', { 'member': GuildMember, 'before': 'VoiceChannel?', 'after': VoiceChannel }), voiceDisconnect('disconnect::voice', { 'member': GuildMember, 'channel': VoiceChannel }), + voiceMove('move::voice', { 'member': GuildMember, 'before': VoiceChannel, 'after': VoiceChannel}), memberMuted('mute::voice', { 'member': GuildMember }), memberUnMuted('unmute::voice', { 'member': GuildMember }), memberDeaf('deaf::voice', { 'member': GuildMember }), diff --git a/lib/src/internal/extensions/mineral_client.dart b/lib/src/internal/extensions/mineral_client.dart index 0e852bf2e..5a47d2f96 100644 --- a/lib/src/internal/extensions/mineral_client.dart +++ b/lib/src/internal/extensions/mineral_client.dart @@ -4,10 +4,11 @@ import 'package:http/http.dart'; import 'package:mineral/api.dart'; import 'package:mineral/core.dart'; import 'package:mineral/src/api/channels/partial_channel.dart'; +import 'package:mineral_ioc/ioc.dart'; extension MineralClientExtension on MineralClient { - Future sendMessage (PartialChannel channel, { String? content, List? embeds, List? components, bool? tts, Map? message_reference }) async { - Http http = ioc.singleton(ioc.services.http); + Future sendMessage (PartialChannel channel, { String? content, List? embeds, List? components, bool? tts, Map? messageReference }) async { + Http http = ioc.singleton(Service.http); List embedList = []; if (embeds != null) { @@ -28,12 +29,12 @@ extension MineralClientExtension on MineralClient { 'content': content, 'embeds': embeds != null ? embedList : [], 'components': components != null ? componentList : [], - 'message_reference': message_reference != null ? { ...message_reference, 'fail_if_not_exists': true } : null, + 'message_reference': messageReference != null ? { ...messageReference, 'fail_if_not_exists': true } : null, }); } Future createChannel (Snowflake guildId, ChannelBuilder builder) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.post(url: "/guilds/$guildId/channels", payload: builder.payload); final payload = jsonDecode(response.body); diff --git a/lib/src/internal/ioc.dart b/lib/src/internal/ioc.dart deleted file mode 100644 index 3ff4986ca..000000000 --- a/lib/src/internal/ioc.dart +++ /dev/null @@ -1,34 +0,0 @@ -class Service { - final http = 'Mineral/Core/Http'; - final client = 'Mineral/Core/Client'; - final environment = 'Mineral/Core/Environment'; - final event = 'Mineral/Core/Event'; - final command = 'Mineral/Core/Command'; - final store = 'Mineral/Core/Store'; - final modules = 'Mineral/Core/Modules'; - final cli = 'Mineral/Core/Cli'; - final shards = 'Mineral/Core/Shards'; - final reporter = 'Mineral/Core/Reporter'; - final contextMenu = 'Mineral/Core/ContextMenu'; -} - -class Ioc { - Service services = Service(); - static late Ioc _instance; - final Map _services = {}; - - static Ioc init () { - Ioc._instance = Ioc(); - return Ioc._instance; - } - - void bind ({ required String namespace, required T service }) { - _services.putIfAbsent(namespace, () => service); - } - - T singleton (String namespace) { - return Ioc._instance._services[namespace] as T; - } -} - -Ioc ioc = Ioc.init(); diff --git a/lib/src/internal/kernel.dart b/lib/src/internal/kernel.dart index 2f20d0df5..aae1ebcde 100644 --- a/lib/src/internal/kernel.dart +++ b/lib/src/internal/kernel.dart @@ -15,9 +15,11 @@ import 'package:mineral/src/internal/managers/context_menu_manager.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/module_manager.dart'; +import 'package:mineral/src/internal/managers/plugin_manager.dart'; import 'package:mineral/src/internal/managers/reporter_manager.dart'; import 'package:mineral/src/internal/managers/store_manager.dart'; import 'package:mineral/src/internal/websockets/sharding/shard_manager.dart'; +import 'package:mineral_ioc/ioc.dart'; import 'package:path/path.dart'; class Kernel { @@ -28,14 +30,18 @@ class Kernel { CliManager cli = CliManager(); ContextMenuManager contextMenus = ContextMenuManager(); IntentManager intents = IntentManager(); + PluginManager plugins = PluginManager(); + Environment environment = Environment(); 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); - ioc.bind(namespace: ioc.services.cli, service: cli); - ioc.bind(namespace: ioc.services.contextMenu, service: contextMenus); + ioc.bind(namespace: Service.event, service: events); + ioc.bind(namespace: Service.command, service: commands); + ioc.bind(namespace: Service.store, service: stores); + ioc.bind(namespace: Service.modules, service: modules); + ioc.bind(namespace: Service.cli, service: cli); + ioc.bind(namespace: Service.contextMenu, service: contextMenus); + ioc.bind(namespace: Service.environment, service: environment); + } void loadConsole () { @@ -49,21 +55,18 @@ class Kernel { } Future init () async { - Environment environment = await _loadEnvironment(); + await environment.load(); Http http = Http(baseUrl: 'https://discord.com/api'); http.defineHeader(header: 'Content-Type', value: 'application/json'); - ioc.bind(namespace: ioc.services.http, service: http); + ioc.bind(namespace: Service.http, service: http); String? report = environment.get('REPORTER'); if (report != null) { ReporterManager reporter = ReporterManager(Directory(join(Directory.current.path, 'logs'))); reporter.reportLevel = report; - ioc.bind( - namespace: ioc.services.reporter, - service: reporter - ); + ioc.bind(namespace: Service.reporter, service: reporter); } String? token = environment.get('APP_TOKEN'); @@ -75,20 +78,13 @@ class Kernel { } await modules.load(this); + await plugins.load(); final String? shardsCount = environment.get('SHARDS_COUNT'); ShardManager manager = ShardManager(http, token, intents.list); manager.start(shardsCount: (shardsCount != null ? int.tryParse(shardsCount) : null)); - ioc.bind(namespace: ioc.services.shards, service: manager); - } - - - Future _loadEnvironment () async { - Environment environment = Environment(); - ioc.bind(namespace: ioc.services.environment, service: environment); - - return await environment.load(); + ioc.bind(namespace: Service.shards, service: manager); } } diff --git a/lib/src/internal/managers/plugin_manager.dart b/lib/src/internal/managers/plugin_manager.dart new file mode 100644 index 000000000..6d30550c6 --- /dev/null +++ b/lib/src/internal/managers/plugin_manager.dart @@ -0,0 +1,22 @@ +import 'dart:io'; +import 'dart:mirrors'; + +import 'package:mineral_ioc/ioc.dart'; + +class PluginManager { + final List _plugins = []; + + void use (List plugins) { + _plugins.addAll(plugins); + } + + Future load () async { + for (final plugin in _plugins) { + final namespace = reflect(plugin).type.getField(Symbol('namespace')); + ioc.bind(namespace: namespace.reflectee, service: plugin); + + plugin..root = Directory.current + ..init(); + } + } +} diff --git a/lib/src/internal/managers/store_manager.dart b/lib/src/internal/managers/store_manager.dart index 93ac89779..62df360b8 100644 --- a/lib/src/internal/managers/store_manager.dart +++ b/lib/src/internal/managers/store_manager.dart @@ -14,7 +14,7 @@ class StoreManager { throw AlreadyExist(cause: "A store named $name already exists."); } - store.environment = ioc.singleton(ioc.services.environment); + store.environment = ioc.singleton(Service.environment); _stores[name] = store; } } diff --git a/lib/src/internal/services/environment.dart b/lib/src/internal/services/environment.dart index dc57be781..bbc7fe85a 100644 --- a/lib/src/internal/services/environment.dart +++ b/lib/src/internal/services/environment.dart @@ -18,8 +18,8 @@ class Environment { for (String line in content) { if (line.isNotEmpty) { List content = line.split(':'); - String key = content[0].trim(); - String value = content[1].trim(); + String key = content.removeAt(0).trim(); + String value = content.join(':').trim(); _cache.putIfAbsent(key, () => value); } @@ -29,8 +29,25 @@ class Environment { } - String? get (String key) { - return _cache[key]; + /// Get environment key from .env file + String? get (String key) => _cache[key]; + + /// Get environment key from .env file + String getOrFail (String key, { String? message }) { + final result = get(key); + if (result == null) { + throw NotExist(prefix: 'Missing value', cause: message ?? 'No values are attached to $key key.'); + } + + return result; + } + + T? getOr (String key, { T? defaultValue }) { + T? result = get(key) as T?; + if (result == null) { + return defaultValue; + } + return result; } Environment add (String key, dynamic value) { diff --git a/lib/src/internal/websockets/packets/auto_moderation_rule_create.dart b/lib/src/internal/websockets/packets/auto_moderation_rule_create.dart index a5a477ffc..1ce000bf1 100644 --- a/lib/src/internal/websockets/packets/auto_moderation_rule_create.dart +++ b/lib/src/internal/websockets/packets/auto_moderation_rule_create.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class AutoModerationRuleCreate implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class AutoModerationRuleCreate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/lib/src/internal/websockets/packets/auto_moderation_rule_delete.dart b/lib/src/internal/websockets/packets/auto_moderation_rule_delete.dart index 710796ac7..130234bab 100644 --- a/lib/src/internal/websockets/packets/auto_moderation_rule_delete.dart +++ b/lib/src/internal/websockets/packets/auto_moderation_rule_delete.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class AutoModerationRuleDelete implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class AutoModerationRuleDelete implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/lib/src/internal/websockets/packets/auto_moderation_rule_update.dart b/lib/src/internal/websockets/packets/auto_moderation_rule_update.dart index bb408ae9e..e62b96943 100644 --- a/lib/src/internal/websockets/packets/auto_moderation_rule_update.dart +++ b/lib/src/internal/websockets/packets/auto_moderation_rule_update.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class AutoModerationRuleCreate implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class AutoModerationRuleCreate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/lib/src/internal/websockets/packets/channel_create.dart b/lib/src/internal/websockets/packets/channel_create.dart index 4e82fcb8d..d518903bf 100644 --- a/lib/src/internal/websockets/packets/channel_create.dart +++ b/lib/src/internal/websockets/packets/channel_create.dart @@ -11,8 +11,8 @@ class ChannelCreate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/lib/src/internal/websockets/packets/channel_delete.dart b/lib/src/internal/websockets/packets/channel_delete.dart index baaa124d0..3cdb6e3e5 100644 --- a/lib/src/internal/websockets/packets/channel_delete.dart +++ b/lib/src/internal/websockets/packets/channel_delete.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class ChannelDelete implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class ChannelDelete implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/lib/src/internal/websockets/packets/channel_update.dart b/lib/src/internal/websockets/packets/channel_update.dart index 1c895b657..9f880afe7 100644 --- a/lib/src/internal/websockets/packets/channel_update.dart +++ b/lib/src/internal/websockets/packets/channel_update.dart @@ -4,6 +4,7 @@ import 'package:mineral/src/api/channels/partial_channel.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class ChannelUpdate implements WebsocketPacket { @override @@ -11,8 +12,8 @@ class ChannelUpdate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/lib/src/internal/websockets/packets/guild_create.dart b/lib/src/internal/websockets/packets/guild_create.dart index 60c37bce4..417f73891 100644 --- a/lib/src/internal/websockets/packets/guild_create.dart +++ b/lib/src/internal/websockets/packets/guild_create.dart @@ -17,6 +17,7 @@ import 'package:mineral/src/internal/managers/context_menu_manager.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class GuildCreate implements WebsocketPacket { @override @@ -24,10 +25,10 @@ class GuildCreate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - CommandManager commandManager = ioc.singleton(ioc.services.command); - ContextMenuManager contextMenuManager = ioc.singleton(ioc.services.contextMenu); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + CommandManager commandManager = ioc.singleton(Service.command); + ContextMenuManager contextMenuManager = ioc.singleton(Service.contextMenu); + MineralClient client = ioc.singleton(Service.client); websocketResponse.payload['guild_id'] = websocketResponse.payload['id']; @@ -39,10 +40,8 @@ class GuildCreate implements WebsocketPacket { Map voices = {}; for(dynamic voiceMember in websocketResponse.payload['voice_states']) { - final VoiceManager voiceManager = VoiceManager.from(voiceMember, null, null); - + final VoiceManager voiceManager = VoiceManager.from(voiceMember, websocketResponse.payload['guild_id']); voices.putIfAbsent(voiceMember['user_id'], () => voiceManager); - voices.putIfAbsent(voiceMember['channel_id'], () => voiceManager); } MemberManager memberManager = MemberManager(); @@ -101,11 +100,9 @@ class GuildCreate implements WebsocketPacket { guild: guild, voice: voices.containsKey(user.id) ? voices.get(user.id)! - : VoiceManager(member['mute'], member['deaf'], false, false, false, false, null, null) + : VoiceManager.empty(member['deaf'], member['mute'], user.id, websocketResponse.payload['guild_id']) ); - guildMember.voice.member = guildMember; - memberManager.cache.putIfAbsent(guildMember.user.id, () => guildMember); client.users.cache.putIfAbsent(user.id, () => user); } @@ -119,13 +116,6 @@ class GuildCreate implements WebsocketPacket { } } - // Assign guild channels - guild.channels.cache.forEach((Snowflake id, GuildChannel channel) { - if(voices.containsKey(id)) { - voices.getOrFail(id).channel = channel as VoiceChannel; - } - }); - guild.afkChannel = guild.channels.cache.get(guild.afkChannelId); guild.systemChannel = guild.channels.cache.get(guild.systemChannelId); guild.rulesChannel = guild.channels.cache.get(guild.rulesChannelId); @@ -153,7 +143,7 @@ class GuildCreate implements WebsocketPacket { } Future?> getAutoModerationRules (Guild guild) async { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.get(url: "/guilds/${guild.id}/auto-moderation/rules"); if (response.statusCode == 200) { diff --git a/lib/src/internal/websockets/packets/guild_integrations_update.dart b/lib/src/internal/websockets/packets/guild_integrations_update.dart index a04825b77..7f1ccdcbc 100644 --- a/lib/src/internal/websockets/packets/guild_integrations_update.dart +++ b/lib/src/internal/websockets/packets/guild_integrations_update.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class GuildIntegrationsUpdate implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class GuildIntegrationsUpdate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/lib/src/internal/websockets/packets/guild_member_add.dart b/lib/src/internal/websockets/packets/guild_member_add.dart index 131bef9ba..9a09b9f04 100644 --- a/lib/src/internal/websockets/packets/guild_member_add.dart +++ b/lib/src/internal/websockets/packets/guild_member_add.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class GuildMemberAdd implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class GuildMemberAdd implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; @@ -24,11 +25,9 @@ class GuildMemberAdd implements WebsocketPacket { roles: guild.roles, member: payload, guild: guild, - voice: VoiceManager(payload['deaf'], payload['mute'], false, false, false, false, null, null) + voice: VoiceManager.empty(payload['deaf'], payload['mute'], user.id, guild.id) ); - member.voice.member = member; - guild.members.cache.putIfAbsent(member.user.id, () => member); manager.emit(event: Events.memberJoin, params: [member]); } diff --git a/lib/src/internal/websockets/packets/guild_member_remove.dart b/lib/src/internal/websockets/packets/guild_member_remove.dart index da0bc3409..a9507e94b 100644 --- a/lib/src/internal/websockets/packets/guild_member_remove.dart +++ b/lib/src/internal/websockets/packets/guild_member_remove.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class GuildMemberRemove implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class GuildMemberRemove implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/lib/src/internal/websockets/packets/guild_member_update.dart b/lib/src/internal/websockets/packets/guild_member_update.dart index 973e1a138..6c9bae416 100644 --- a/lib/src/internal/websockets/packets/guild_member_update.dart +++ b/lib/src/internal/websockets/packets/guild_member_update.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class GuildMemberUpdate implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class GuildMemberUpdate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; @@ -21,7 +22,7 @@ class GuildMemberUpdate implements WebsocketPacket { VoiceManager voice = before != null ? before.voice - : VoiceManager(payload['deaf'], payload['mute'], false, false, false, false, null, null); + : VoiceManager.empty(payload['deaf'], payload['mute'], payload['user']['id'], guild.id); User user = User.from(payload['user']); GuildMember after = GuildMember.from( @@ -32,8 +33,6 @@ class GuildMemberUpdate implements WebsocketPacket { voice: voice ); - after.voice.member ??= after; - manager.emit( event: Events.memberUpdate, params: [before, after] diff --git a/lib/src/internal/websockets/packets/guild_scheduled_event_create.dart b/lib/src/internal/websockets/packets/guild_scheduled_event_create.dart index 91a972e6f..f296f8bfe 100644 --- a/lib/src/internal/websockets/packets/guild_scheduled_event_create.dart +++ b/lib/src/internal/websockets/packets/guild_scheduled_event_create.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class GuildScheduledEventCreate implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class GuildScheduledEventCreate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/lib/src/internal/websockets/packets/guild_scheduled_event_delete.dart b/lib/src/internal/websockets/packets/guild_scheduled_event_delete.dart index f4a9a906c..73fdda449 100644 --- a/lib/src/internal/websockets/packets/guild_scheduled_event_delete.dart +++ b/lib/src/internal/websockets/packets/guild_scheduled_event_delete.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class GuildScheduledEventDelete implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class GuildScheduledEventDelete implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/lib/src/internal/websockets/packets/guild_scheduled_event_update.dart b/lib/src/internal/websockets/packets/guild_scheduled_event_update.dart index 2cd250b42..7b5bb3dbc 100644 --- a/lib/src/internal/websockets/packets/guild_scheduled_event_update.dart +++ b/lib/src/internal/websockets/packets/guild_scheduled_event_update.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class GuildScheduledEventUpdate implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class GuildScheduledEventUpdate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/lib/src/internal/websockets/packets/guild_scheduled_event_user_add.dart b/lib/src/internal/websockets/packets/guild_scheduled_event_user_add.dart index f5a0e11d9..5a12fd631 100644 --- a/lib/src/internal/websockets/packets/guild_scheduled_event_user_add.dart +++ b/lib/src/internal/websockets/packets/guild_scheduled_event_user_add.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class GuildScheduledEventUserAdd implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class GuildScheduledEventUserAdd implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; final Snowflake eventId = payload['guild_scheduled_event_id']; diff --git a/lib/src/internal/websockets/packets/guild_scheduled_event_user_remove.dart b/lib/src/internal/websockets/packets/guild_scheduled_event_user_remove.dart index 8af9423f2..cf78d59fb 100644 --- a/lib/src/internal/websockets/packets/guild_scheduled_event_user_remove.dart +++ b/lib/src/internal/websockets/packets/guild_scheduled_event_user_remove.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class GuildScheduledEventUserRemove implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class GuildScheduledEventUserRemove implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; final Snowflake eventId = payload['guild_scheduled_event_id']; diff --git a/lib/src/internal/websockets/packets/guild_update.dart b/lib/src/internal/websockets/packets/guild_update.dart index da67c1fe6..229fe6a2c 100644 --- a/lib/src/internal/websockets/packets/guild_update.dart +++ b/lib/src/internal/websockets/packets/guild_update.dart @@ -10,6 +10,7 @@ import 'package:mineral/src/api/managers/webhook_manager.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class GuildUpdate implements WebsocketPacket { @@ -18,8 +19,8 @@ class GuildUpdate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); Guild? before = client.guilds.cache.get(websocketResponse.payload['id']); diff --git a/lib/src/internal/websockets/packets/interaction_create.dart b/lib/src/internal/websockets/packets/interaction_create.dart index ce6ec171d..cd77cbe18 100644 --- a/lib/src/internal/websockets/packets/interaction_create.dart +++ b/lib/src/internal/websockets/packets/interaction_create.dart @@ -18,8 +18,8 @@ class InteractionCreate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; @@ -61,7 +61,7 @@ class InteractionCreate implements WebsocketPacket { } _executeCommandInteraction (Guild guild, GuildMember member, dynamic payload) { - CommandManager manager = ioc.singleton(ioc.services.command); + CommandManager manager = ioc.singleton(Service.command); CommandInteraction commandInteraction = CommandInteraction.from(payload: payload); String identifier = commandInteraction.identifier; @@ -96,7 +96,7 @@ class InteractionCreate implements WebsocketPacket { } _executeContextMenuInteraction (Guild guild, GuildMember member, dynamic payload) async { - ContextMenuManager contextMenuManager = ioc.singleton(ioc.services.contextMenu); + ContextMenuManager contextMenuManager = ioc.singleton(Service.contextMenu); MineralContextMenu contextMenu = contextMenuManager.contextMenus.findOrFail((element) => element.name == payload['data']?['name']); if (payload['data']?['type'] == ApplicationCommandType.user.value) { @@ -106,7 +106,7 @@ class InteractionCreate implements WebsocketPacket { } if (payload['data']?['type'] == ApplicationCommandType.message.value) { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); TextBasedChannel? channel = guild.channels.cache.get(payload['channel_id']); Message? message = channel?.messages.cache.get(payload['data']?['target_id']); @@ -125,8 +125,8 @@ class InteractionCreate implements WebsocketPacket { } _executeButtonInteraction (Guild guild, GuildMember member, dynamic payload) async { - Http http = ioc.singleton(ioc.services.http); - EventManager manager = ioc.singleton(ioc.services.event); + Http http = ioc.singleton(Service.http); + EventManager manager = ioc.singleton(Service.event); TextBasedChannel? channel = guild.channels.cache.get(payload['channel_id']); Message? message = channel?.messages.cache.get(payload['message']['id']); @@ -158,7 +158,7 @@ class InteractionCreate implements WebsocketPacket { } _executeModalInteraction (Guild guild, GuildMember member, dynamic payload) { - EventManager manager = ioc.singleton(ioc.services.event); + EventManager manager = ioc.singleton(Service.event); ModalInteraction modalInteraction = ModalInteraction.from(payload: payload); for (dynamic row in payload['data']['components']) { @@ -180,7 +180,7 @@ class InteractionCreate implements WebsocketPacket { } void _executeSelectMenuInteraction (Guild guild, GuildMember member, dynamic payload) { - EventManager manager = ioc.singleton(ioc.services.event); + EventManager manager = ioc.singleton(Service.event); TextBasedChannel? channel = guild.channels.cache.get(payload['channel_id']); Message? message = channel?.messages.cache.get(payload['message']['id']); diff --git a/lib/src/internal/websockets/packets/member_join_request.dart b/lib/src/internal/websockets/packets/member_join_request.dart index 0276a2b7c..71c611b60 100644 --- a/lib/src/internal/websockets/packets/member_join_request.dart +++ b/lib/src/internal/websockets/packets/member_join_request.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class MemberJoinRequest implements WebsocketPacket { @override @@ -10,13 +11,13 @@ class MemberJoinRequest implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; Guild? guild = client.guilds.cache.get(payload['request']['guild_id']); - + if(payload['status'] == 'APPROVED' && guild != null) { GuildMember? member = guild.members.cache.get(payload['request']['user_id']); diff --git a/lib/src/internal/websockets/packets/message_create.dart b/lib/src/internal/websockets/packets/message_create.dart index b6890e257..a3efd08a0 100644 --- a/lib/src/internal/websockets/packets/message_create.dart +++ b/lib/src/internal/websockets/packets/message_create.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class MessageCreate implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class MessageCreate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/lib/src/internal/websockets/packets/message_delete.dart b/lib/src/internal/websockets/packets/message_delete.dart index 32c6eecc7..4b1dbff22 100644 --- a/lib/src/internal/websockets/packets/message_delete.dart +++ b/lib/src/internal/websockets/packets/message_delete.dart @@ -6,6 +6,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class MessageDelete implements WebsocketPacket { @override @@ -13,8 +14,8 @@ class MessageDelete implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; @@ -23,7 +24,7 @@ class MessageDelete implements WebsocketPacket { Message? message = channel?.messages.cache.get(payload['id']); if (message == null) { - Http http = ioc.singleton(ioc.services.http); + Http http = ioc.singleton(Service.http); Response response = await http.get(url: "/channels/${channel?.id}/messages/${payload['id']}"); if (response.statusCode == 200) { diff --git a/lib/src/internal/websockets/packets/message_update.dart b/lib/src/internal/websockets/packets/message_update.dart index 65eb25116..50a3abc10 100644 --- a/lib/src/internal/websockets/packets/message_update.dart +++ b/lib/src/internal/websockets/packets/message_update.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class MessageUpdate implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class MessageUpdate implements WebsocketPacket { @override Future handle (WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/lib/src/internal/websockets/packets/presence_update.dart b/lib/src/internal/websockets/packets/presence_update.dart index dddc167a9..6930a3807 100644 --- a/lib/src/internal/websockets/packets/presence_update.dart +++ b/lib/src/internal/websockets/packets/presence_update.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class PresenceUpdate implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class PresenceUpdate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/lib/src/internal/websockets/packets/ready.dart b/lib/src/internal/websockets/packets/ready.dart index 841fae64a..00037b9ce 100644 --- a/lib/src/internal/websockets/packets/ready.dart +++ b/lib/src/internal/websockets/packets/ready.dart @@ -6,6 +6,7 @@ import 'package:mineral/src/internal/websockets/sharding/shard.dart'; import 'package:mineral/src/internal/websockets/sharding/shard_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class Ready implements WebsocketPacket { @override @@ -13,15 +14,15 @@ class Ready implements WebsocketPacket { @override Future handle (WebsocketResponse websocketResponse) async { - EventManager eventManager = ioc.singleton(ioc.services.event); - CommandManager commandManager = ioc.singleton(ioc.services.command); - ShardManager shardManager = ioc.singleton(ioc.services.shards); + EventManager eventManager = ioc.singleton(Service.event); + CommandManager commandManager = ioc.singleton(Service.command); + ShardManager shardManager = ioc.singleton(Service.shards); - if (ioc.singleton(ioc.services.client) == null) { + if (ioc.singleton(Service.client) == null) { MineralClient client = MineralClient.from(payload: websocketResponse.payload); client.uptime = DateTime.now(); - ioc.bind(namespace: ioc.services.client, service: client); + ioc.bind(namespace: Service.client, service: client); await client.registerGlobalCommands(commands: commandManager.getGlobals()); @@ -46,7 +47,7 @@ class Ready implements WebsocketPacket { eventManager.emit( event: Events.ready, - params: [ioc.singleton(ioc.services.client)] + params: [ioc.singleton(Service.client)] ); } @@ -56,8 +57,8 @@ class Ready implements WebsocketPacket { for (Map event in events) { event['mineralEvent'] ..client = client - ..stores = ioc.singleton(ioc.services.store) - ..environment = ioc.singleton(ioc.services.environment); + ..stores = ioc.singleton(Service.store) + ..environment = ioc.singleton(Service.environment); } }); } @@ -67,8 +68,8 @@ class Ready implements WebsocketPacket { commands.forEach((_, handler) { handler['commandClass'] ..client = client - ..stores = ioc.singleton(ioc.services.store) - ..environment = ioc.singleton(ioc.services.environment); + ..stores = ioc.singleton(Service.store) + ..environment = ioc.singleton(Service.environment); }); } } diff --git a/lib/src/internal/websockets/packets/voice_state_update.dart b/lib/src/internal/websockets/packets/voice_state_update.dart index 6b7820a13..cad58aecb 100644 --- a/lib/src/internal/websockets/packets/voice_state_update.dart +++ b/lib/src/internal/websockets/packets/voice_state_update.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class VoiceStateUpdate implements WebsocketPacket { @override @@ -10,105 +11,77 @@ class VoiceStateUpdate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; Guild? guild = client.guilds.cache.get(payload['guild_id']); GuildMember? member = guild?.members.cache.get(payload['user_id']); - VoiceChannel? voiceChannel = guild?.channels.cache.get(payload['channel_id']); - if (guild != null && member != null) { - VoiceManager before = member.voice; - VoiceManager after = VoiceManager.from(payload, member, voiceChannel); - - member.voice = after; - after.member = member; - - manager.emit( - event: Events.voiceStateUpdate, - params: [before, after] - ); - - //User move - if(before.channel != null && after.channel != null && before.channel != after.channel) { - _emitEvent(manager, Events.voiceDisconnect, [member, before.channel], before.channel!.id); - _emitEvent(manager, Events.voiceConnect, [member, before.channel, after.channel], after.channel!.id); - } - - //User connect - if(before.channel == null && after.channel != null) { - _emitEvent(manager, Events.voiceConnect, [member, before.channel, after.channel], after.channel!.id); - } - - //User leave - if(before.channel != null && after.channel == null) { - _emitEvent(manager, Events.voiceDisconnect, [member, before.channel], before.channel!.id); - } - - //User muted - if(!before.isMute && after.isMute) { - manager.emit( - event: Events.memberMuted, - params: [member] - ); - } - - //User unmute - if(before.isMute && !after.isMute) { - manager.emit( - event: Events.memberUnMuted, - params: [member] - ); - } - - //User undeaf - if(before.isDeaf && !after.isDeaf) { - manager.emit( - event: Events.memberUnDeaf, - params: [member] - ); - } - - //User deaf - if(!before.isDeaf && after.isDeaf) { - manager.emit( - event: Events.memberDeaf, - params: [member] - ); - } - - //User selfUnMute - if(before.isSelfMute && !after.isSelfMute) { - manager.emit( - event: Events.memberSelfUnMuted, - params: [member] - ); - } - - //User selfMute - if(!before.isSelfMute && after.isSelfMute) { - manager.emit( - event: Events.memberSelfMuted, - params: [member] - ); - } - - //User selfUnDeaf - if(before.isSelfDeaf && !after.isSelfDeaf) { - manager.emit( - event: Events.memberSelfUnDeaf, - params: [member] - ); - } - - //User selfDeaf - if(!before.isSelfDeaf && after.isSelfDeaf) { - manager.emit( - event: Events.memberSelfDeaf, - params: [member] - ); - } + //VoiceChannel? voiceChannel = guild?.channels.cache.get(payload['channel_id']); + if(guild == null || member == null) return; + + VoiceManager before = member.voice; + VoiceManager after = VoiceManager.from(payload, guild.id); + + member.voice = after; + manager.emit(event: Events.voiceStateUpdate, params: [before, after]); + + //User move + if(before.channel != null && after.channel != null && before.channel != after.channel) { + _emitEvent(manager, Events.voiceDisconnect, [member, before.channel], before.channel!.id); + _emitEvent(manager, Events.voiceConnect, [member, before.channel, after.channel], after.channel!.id); + manager.emit(event: Events.voiceMove, params: [member, before.channel, after.channel]); + } + + //User join + if(before.channel == null && after.channel != null) { + _emitEvent(manager, Events.voiceConnect, [member, null, after.channel], after.channel!.id); + } + + //User leave + if(before.channel != null && after.channel == null) { + _emitEvent(manager, Events.voiceDisconnect, [member, before.channel], before.channel!.id); + } + + //User mute + if(!before.isMute && after.isMute) { + manager.emit(event: Events.memberMuted, params: [member]); + } + + //User unmute + if(before.isMute && !after.isMute) { + manager.emit(event: Events.memberUnMuted, params: [member]); + } + + //User undeaf + if(before.isDeaf && !after.isDeaf) { + manager.emit(event: Events.memberUnDeaf, params: [member]); + } + + //User deaf + if(!before.isDeaf && after.isDeaf) { + manager.emit(event: Events.memberDeaf, params: [member]); + } + + //User selfUnMute + if(before.isSelfMute && !after.isSelfMute) { + manager.emit(event: Events.memberSelfUnMuted, params: [member]); + } + + //User selfMute + if(!before.isSelfMute && after.isSelfMute) { + manager.emit(event: Events.memberSelfMuted, params: [member]); + } + + //User selfUnDeaf + if(before.isSelfDeaf && !after.isSelfDeaf) { + manager.emit(event: Events.memberSelfUnDeaf, params: [member]); + } + + //User selfDeaf + if(!before.isSelfDeaf && after.isSelfDeaf) { + manager.emit(event: Events.memberSelfDeaf, params: [member]); } } diff --git a/lib/src/internal/websockets/packets/webhook_update.dart b/lib/src/internal/websockets/packets/webhook_update.dart index 79180668b..7a48b3dd3 100644 --- a/lib/src/internal/websockets/packets/webhook_update.dart +++ b/lib/src/internal/websockets/packets/webhook_update.dart @@ -3,6 +3,7 @@ import 'package:mineral/core.dart'; import 'package:mineral/src/internal/managers/event_manager.dart'; import 'package:mineral/src/internal/websockets/websocket_packet.dart'; import 'package:mineral/src/internal/websockets/websocket_response.dart'; +import 'package:mineral_ioc/ioc.dart'; class WebhookUpdate implements WebsocketPacket { @override @@ -10,8 +11,8 @@ class WebhookUpdate implements WebsocketPacket { @override Future handle(WebsocketResponse websocketResponse) async { - EventManager manager = ioc.singleton(ioc.services.event); - MineralClient client = ioc.singleton(ioc.services.client); + EventManager manager = ioc.singleton(Service.event); + MineralClient client = ioc.singleton(Service.client); dynamic payload = websocketResponse.payload; diff --git a/pubspec.yaml b/pubspec.yaml index 33bd00454..4147f366f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: mineral description: Mineral is a Discord framework for designing discord bots in Dart. -version: 1.0.5 +version: 1.2.1 repository: https://github.com/mineral-dart/core # homepage: https://www.example.com @@ -19,6 +19,7 @@ dependencies: http: ^0.13.4 interact: ^2.1.1 collection: ^1.16.0 + mineral_ioc: ^1.0.0 dev_dependencies: lints: ^1.0.0 diff --git a/test/core_test.dart b/test/core_test.dart index 1b23f1056..d3c9714f2 100644 --- a/test/core_test.dart +++ b/test/core_test.dart @@ -7,9 +7,9 @@ import 'package:test/scaffolding.dart'; void main() { test('can get Http from ioc', () { String discordEndpoint = 'https://discord.com/api'; - ioc.bind(namespace: ioc.services.http, service: Http(baseUrl: discordEndpoint)); + ioc.bind(namespace: Service.http, service: Http(baseUrl: discordEndpoint)); - assert(ioc.singleton(ioc.services.http) is Http); + assert(ioc.singleton(Service.http) is Http); }); test('can emit with event emitter', () async {