Skip to content

Commit

Permalink
Implementation of Inline Replies; discord/discord-api-docs#2118
Browse files Browse the repository at this point in the history
[ci skip]
  • Loading branch information
l7ssha committed Mar 29, 2021
1 parent b8d63be commit e5c9931
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 29 deletions.
28 changes: 16 additions & 12 deletions nyxx.commander/lib/src/CommandContext.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ class CommandContext {
List<AttachmentBuilder>? files,
bool? tts,
AllowedMentions? allowedMentions,
MessageBuilder? builder
MessageBuilder? builder,
ReplyBuilder? replyBuilder
}) => channel.sendMessage(
content: content, embed: embed, tts: tts, files: files, builder: builder, allowedMentions: allowedMentions);
content: content, embed: embed, tts: tts, files: files, builder: builder, allowedMentions: allowedMentions, replyBuilder: replyBuilder);

/// Reply to messages, then delete it when [duration] expires.
///
Expand All @@ -61,15 +62,16 @@ class CommandContext {
/// await context.replyTemp(content: user.avatarURL());
/// }
/// ```
Future<Message> replyTemp(Duration duration,
{dynamic content,
EmbedBuilder? embed,
List<AttachmentBuilder>? files,
bool? tts,
AllowedMentions? allowedMentions,
MessageBuilder? builder
Future<Message> replyTemp(Duration duration, {
dynamic content,
EmbedBuilder? embed,
List<AttachmentBuilder>? files,
bool? tts,
AllowedMentions? allowedMentions,
MessageBuilder? builder,
ReplyBuilder? replyBuilder
}) => channel
.sendMessage(content: content, embed: embed, files: files, tts: tts, builder: builder, allowedMentions: allowedMentions)
.sendMessage(content: content, embed: embed, files: files, tts: tts, builder: builder, allowedMentions: allowedMentions, replyBuilder: replyBuilder)
.then((msg) {
Timer(duration, () => msg.delete());
return msg;
Expand All @@ -87,7 +89,8 @@ class CommandContext {
List<AttachmentBuilder>? files,
bool? tts,
AllowedMentions? allowedMentions,
MessageBuilder? builder
MessageBuilder? builder,
ReplyBuilder? replyBuilder
}) => Future.delayed(
duration,
() => channel.sendMessage(
Expand All @@ -96,7 +99,8 @@ class CommandContext {
files: files,
tts: tts,
builder: builder,
allowedMentions: allowedMentions));
allowedMentions: allowedMentions,
replyBuilder: replyBuilder));

/// Awaits for emoji under given [msg]
Future<IEmoji> awaitEmoji(Message msg) async =>
Expand Down
2 changes: 2 additions & 0 deletions nyxx/lib/nyxx.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ part "src/events/InviteEvents.dart";

part "src/utils/builders/Builder.dart";

part "src/utils/builders/ReplyBuilder.dart";
part "src/utils/builders/PresenceBuilder.dart";
part "src/utils/builders/AttachmentBuilder.dart";
part "src/utils/builders/PermissionsBuilder.dart";
Expand Down Expand Up @@ -148,6 +149,7 @@ part "src/core/message/Attachment.dart";
part "src/core/message/MessageFlags.dart";
part "src/core/message/MessageReference.dart";
part "src/core/message/MessageType.dart";
part "src/core/message/ReferencedMessage.dart";

part "src/core/application/ClientOAuth2Application.dart";
part "src/core/application/OAuth2Application.dart";
Expand Down
6 changes: 3 additions & 3 deletions nyxx/lib/src/core/channel/DMChannel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class DMChannel extends IChannel implements TextChannel {
Future<Message?> getMessage(Snowflake id) => Future.value(this.messageCache[id]);

@override
Future<Message> sendMessage({dynamic content, EmbedBuilder? embed, List<AttachmentBuilder>? files, bool? tts, AllowedMentions? allowedMentions, MessageBuilder? builder}) =>
client._httpEndpoints.sendMessage(this.id, content: content, embed: embed, files: files, tts: tts, allowedMentions: allowedMentions, builder: builder);
Future<Message> sendMessage({dynamic content, EmbedBuilder? embed, List<AttachmentBuilder>? files, bool? tts, AllowedMentions? allowedMentions, MessageBuilder? builder, ReplyBuilder? replyBuilder}) =>
client._httpEndpoints.sendMessage(this.id, content: content, embed: embed, files: files, tts: tts, allowedMentions: allowedMentions, builder: builder, replyBuilder: replyBuilder);

}
}
5 changes: 3 additions & 2 deletions nyxx/lib/src/core/channel/TextChannel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ abstract class TextChannel implements IChannel, ISend {
List<AttachmentBuilder>? files,
bool? tts,
AllowedMentions? allowedMentions,
MessageBuilder? builder
MessageBuilder? builder,
ReplyBuilder? replyBuilder
});

/// Bulk removes many messages by its ids. [messages] is list of messages ids to delete.
Expand Down Expand Up @@ -83,4 +84,4 @@ abstract class TextChannel implements IChannel, ISend {
/// Stops a typing loop if one is running.
@override
void stopTypingLoop();
}
}
6 changes: 3 additions & 3 deletions nyxx/lib/src/core/channel/guild/TextGuildChannel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,6 @@ class TextGuildChannel extends GuildChannel implements TextChannel {
Future<Message?> getMessage(Snowflake id) => Future.value(this.messageCache[id]);

@override
Future<Message> sendMessage({dynamic content, EmbedBuilder? embed, List<AttachmentBuilder>? files, bool? tts, AllowedMentions? allowedMentions, MessageBuilder? builder}) =>
client._httpEndpoints.sendMessage(this.id, content: content, embed: embed, files: files, tts: tts, allowedMentions: allowedMentions, builder: builder);
}
Future<Message> sendMessage({dynamic content, EmbedBuilder? embed, List<AttachmentBuilder>? files, bool? tts, AllowedMentions? allowedMentions, MessageBuilder? builder, ReplyBuilder? replyBuilder}) =>
client._httpEndpoints.sendMessage(this.id, content: content, embed: embed, files: files, tts: tts, allowedMentions: allowedMentions, builder: builder, replyBuilder: replyBuilder);
}
35 changes: 35 additions & 0 deletions nyxx/lib/src/core/message/ReferencedMessage.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
part of nyxx;

/// Message wrapper that other message replies to.
/// [message] field can be null of two reasons: backend error or message was deleted.
/// In first case [isBackendFetchError] will be true and [isDeleted] in second case.
class ReferencedMessage {
/// Message object of reply
late final Message? message;

/// If true the backend couldn't fetch the message
late final bool isBackendFetchError;

/// If true message was delted
late final bool isDeleted;

ReferencedMessage._new(Nyxx client, Map<String, dynamic> raw) {
if (!raw.containsKey(raw["referencedMessage"])) {
this.message = null;
this.isBackendFetchError = true;
this.isDeleted = false;
return;
}

if (raw["referencedMessage"] == null) {
this.message = null;
this.isBackendFetchError = false;
this.isDeleted = true;
return;
}

this.message = Message._deserialize(client, raw);
this.isBackendFetchError = false;
this.isDeleted = false;
}
}
11 changes: 8 additions & 3 deletions nyxx/lib/src/core/user/User.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,20 @@ class User extends SnowflakeEntity with Mentionable, IMessageAuthor implements I
client._httpEndpoints.userAvatarURL(this.id, this.avatar, this.discriminator, format: format, size: size);

/// Sends a message to user.
@override
Future<Message> sendMessage(
{dynamic content,
List<AttachmentBuilder>? files,
EmbedBuilder? embed,
bool? tts,
AllowedMentions? allowedMentions,
MessageBuilder? builder}) async {
MessageBuilder? builder,
ReplyBuilder? replyBuilder
}) async {
final channel = await this.dmChannel;
return channel.sendMessage(
content: content, files: files, embed: embed, tts: tts, allowedMentions: allowedMentions, builder: builder);
content: content, files: files, embed: embed, tts: tts,
allowedMentions: allowedMentions, builder: builder, replyBuilder: replyBuilder
);
}
}
}
16 changes: 11 additions & 5 deletions nyxx/lib/src/internal/_HttpEndpoints.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ abstract class IHttpEndpoints {
EmbedBuilder? embed,
bool? tts,
AllowedMentions? allowedMentions,
MessageBuilder? builder});
MessageBuilder? builder,
ReplyBuilder? replyBuilder
});

Future<Message> fetchMessage(Snowflake channelId, Snowflake messageId);

Expand Down Expand Up @@ -192,7 +194,7 @@ class _HttpEndpoints implements IHttpEndpoints {
this._httpClient = this._client._http;
}

Map<String, dynamic> _initMessage(dynamic content, EmbedBuilder? embed, AllowedMentions? allowedMentions) {
Map<String, dynamic> _initMessage(dynamic content, EmbedBuilder? embed, AllowedMentions? allowedMentions, ReplyBuilder? replyBuilder) {
if (content == null && embed == null) {
throw ArgumentError("When sending message both content and embed cannot be null");
}
Expand All @@ -202,7 +204,8 @@ class _HttpEndpoints implements IHttpEndpoints {
return <String, dynamic>{
if (content != null) "content": content.toString(),
if (embed != null) "embed": embed._build(),
if (allowedMentions != null) "allowed_mentions": allowedMentions._build()
if (allowedMentions != null) "allowed_mentions": allowedMentions._build(),
if (replyBuilder != null) "message_reference": replyBuilder._build(),
};
}

Expand Down Expand Up @@ -715,17 +718,20 @@ class _HttpEndpoints implements IHttpEndpoints {
EmbedBuilder? embed,
bool? tts,
AllowedMentions? allowedMentions,
MessageBuilder? builder}) async {
MessageBuilder? builder,
ReplyBuilder? replyBuilder
}) async {
if (builder != null) {
content = builder._content;
files = builder.files;
embed = builder.embed;
tts = builder.tts ?? false;
allowedMentions = builder.allowedMentions;
replyBuilder = builder.replyBuilder;
}

final reqBody = {
..._initMessage(content, embed, allowedMentions),
..._initMessage(content, embed, allowedMentions, replyBuilder),
if (content != null && tts != null) "tts": tts
};

Expand Down
3 changes: 3 additions & 0 deletions nyxx/lib/src/utils/builders/MessageBuilder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ class MessageBuilder extends MessageEditBuilder {
/// List of files to send with message
List<AttachmentBuilder>? files;

/// Allows to create message that replies to another message
ReplyBuilder? replyBuilder;

/// Add attachment
void addAttachment(AttachmentBuilder attachment) {
if (this.files == null) this.files = [];
Expand Down
27 changes: 27 additions & 0 deletions nyxx/lib/src/utils/builders/ReplyBuilder.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
part of nyxx;

/// Builder for replying to message
class ReplyBuilder implements Builder {
/// Id of message you reply to
final Snowflake messageId;

/// Id of channel of message which you reply to
final Snowflake channelId;

/// Constructs reply builder for given message in channel
ReplyBuilder(this.messageId, this.channelId);

/// Constructs message reply from given message
factory ReplyBuilder.froMessage(Message message) =>
ReplyBuilder(message.id, message.channel.id);

/// Constructs message reply from cacheable of message and channel
factory ReplyBuilder.fromCacheable(Cacheable<Snowflake, Message> messageCacheable, Cacheable<Snowflake, TextChannel> channelCacheable) =>
ReplyBuilder(messageCacheable.id, channelCacheable.id);

@override
Map<String, dynamic> _build() => {
"message_id": this.messageId.id,
"channel_id": this.channelId.id
};
}
2 changes: 1 addition & 1 deletion nyxx/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ environment:

dependencies:
logging: "^1.0.0-dev"
path: "^1.8.0-nullsafety.1"
path: "^1.8.0-nullsafety.2"
http: "^0.13.0-nullsafety-dev"

dependency_overrides:
Expand Down

0 comments on commit e5c9931

Please sign in to comment.