Skip to content

Commit

Permalink
Merge pull request #61 from mineral-dart/develop
Browse files Browse the repository at this point in the history
feat: Implement forum channels and improve other
  • Loading branch information
LeadcodeDev authored Sep 21, 2022
2 parents 98fbc14 + ee0a33c commit 5f733ab
Show file tree
Hide file tree
Showing 103 changed files with 746 additions and 465 deletions.
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down
5 changes: 5 additions & 0 deletions lib/api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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';
Expand Down
9 changes: 5 additions & 4 deletions lib/console.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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');
Expand Down Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
17 changes: 17 additions & 0 deletions lib/src/api/channels/channel_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,21 @@ class ChannelBuilder {
'video_quality_mode': videoQualityMode
});
}

factory ChannelBuilder.fromForumChannel ({ required String label, String? guidelines, Snowflake? parentId, List<ForumTagBuilder>? 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())],
});
}
}
2 changes: 1 addition & 1 deletion lib/src/api/channels/dm_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<Snowflake, User> users = {};
if (payload['recipients'] != null) {
Expand Down
86 changes: 86 additions & 0 deletions lib/src/api/channels/forum_channel.dart
Original file line number Diff line number Diff line change
@@ -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<void> 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<void> setTags (List<ForumTagBuilder> 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<void> 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']),
);
}
}
6 changes: 3 additions & 3 deletions lib/src/api/channels/guild_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<MineralClient>(ioc.services.client).guilds.cache.getOrFail(_guildId);
Guild get guild => ioc.singleton<MineralClient>(Service.client).guilds.cache.getOrFail(_guildId);

/// Get [CategoryChannel] or [TextChannel] parent
GuildChannel? get parent => guild.channels.cache.get(_parentId);
Expand Down Expand Up @@ -54,7 +54,7 @@ class GuildChannel extends PartialChannel {

Future<void> 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);
}
}
Expand All @@ -66,7 +66,7 @@ class GuildChannel extends PartialChannel {
/// await channel.delete()
/// ```
Future<bool> 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);
Expand Down
2 changes: 1 addition & 1 deletion lib/src/api/channels/news_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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
});
Expand Down
2 changes: 2 additions & 0 deletions lib/src/api/channels/partial_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
2 changes: 1 addition & 1 deletion lib/src/api/channels/partial_text_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class PartialTextChannel extends GuildChannel {
/// await channel.send(content: 'Hello world ! 🔥');
/// ```
Future<Message?> send ({ String? content, List<EmbedBuilder>? embeds, List<RowBuilder>? 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,
Expand Down
2 changes: 1 addition & 1 deletion lib/src/api/channels/text_based_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<void> setNsfw (bool value) async {
await update(ChannelBuilder({ 'nsfw': value }));
}
Expand Down
2 changes: 1 addition & 1 deletion lib/src/api/channels/text_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
10 changes: 6 additions & 4 deletions lib/src/api/channels/thread_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,19 @@ 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(
payload['thread_metadata']['archived'],
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'],
Expand Down
2 changes: 1 addition & 1 deletion lib/src/api/channels/voice_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
10 changes: 5 additions & 5 deletions lib/src/api/client/mineral_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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()] : [],
Expand All @@ -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<void> registerGlobalCommands ({ required List<SlashCommand> commands }) async {
Http http = ioc.singleton(ioc.services.http);
Http http = ioc.singleton(Service.http);

await http.put(
url: "/applications/${_application.id}/commands",
Expand All @@ -100,7 +100,7 @@ class MineralClient {
}

Future<void> registerGuildCommands ({ required Guild guild, required List<SlashCommand> commands, required List<MineralContextMenu> 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: [
Expand All @@ -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']),
Expand Down
16 changes: 16 additions & 0 deletions lib/src/api/components/code_builder.dart
Original file line number Diff line number Diff line change
@@ -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) + '```';
}
}
Loading

0 comments on commit 5f733ab

Please sign in to comment.