Fix and implement new 4 and 5 interaction response type; Implement interaction followup
This commit is contained in:
parent
29894ee523
commit
14219dc017
|
@ -20,7 +20,7 @@ void main() {
|
|||
// Check if the name of the command is echo
|
||||
if (event.interaction.name == "echo") {
|
||||
// Reply with the message the user sent, showSource makes discord show the command the user sent in the channel.
|
||||
await event.reply(content: event.interaction.args["message"]!.value, showSource: true);
|
||||
await event.respond(content: event.interaction.getArg("message"));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,11 +7,11 @@ void main() {
|
|||
|
||||
interactions
|
||||
..registerHandler("test", "This is test comamnd", [], handler: (event) async {
|
||||
// Acknowledge about event so you can send reply later. You have 3 second to either ack command
|
||||
// or send response
|
||||
await event.acknowledge(showSource: true);
|
||||
// Acknowledge about event so you can send reply later.
|
||||
// You have 3 second to either ack command or send response
|
||||
await event.acknowledge();
|
||||
|
||||
// After long running task, send response
|
||||
await event.reply(content: "This is example message result");
|
||||
await event.respond(content: "This is example message result");
|
||||
});
|
||||
}
|
||||
|
|
|
@ -34,93 +34,133 @@ class InteractionEvent {
|
|||
}
|
||||
}
|
||||
|
||||
/// Should be sent when you receive a ping from interactions. Used to acknowledge a ping. Internal to the InteractionEvent.
|
||||
/// Used to acknowledge a Interaction but not send any response yet.
|
||||
/// Once this is sent you can then only send ChannelMessages.
|
||||
/// You can also set showSource to also print out the command the user entered.
|
||||
Future<void> acknowledge() async {
|
||||
if (DateTime.now().isAfter(this.receivedAt.add(const Duration(minutes: 15)))) {
|
||||
return Future.error(InteractionExpiredError());
|
||||
}
|
||||
|
||||
if (hasResponded) {
|
||||
return Future.error(AlreadyRespondedError());
|
||||
}
|
||||
|
||||
final url = "/interactions/${this.interaction.id.toString()}/${this.interaction.token}/callback";
|
||||
|
||||
final response = await this._client.httpEndpoints.sendRawRequest(
|
||||
url,
|
||||
"POST",
|
||||
body: {
|
||||
"type": 5,
|
||||
"data": null,
|
||||
},
|
||||
);
|
||||
|
||||
if (response is HttpResponseError) {
|
||||
return Future.error(response);
|
||||
}
|
||||
|
||||
hasResponded = true;
|
||||
}
|
||||
|
||||
/// Used to acknowledge a Interaction and send a response.
|
||||
/// Once this is sent you can then only send ChannelMessages.
|
||||
/// You can also set showSource to also print out the command the user entered.
|
||||
Future<void> respond({ dynamic content, EmbedBuilder? embed, bool? tts, AllowedMentions? allowedMentions, bool hidden = false}) async {
|
||||
if (DateTime.now().isAfter(this.receivedAt.add(const Duration(minutes: 15)))) {
|
||||
return Future.error(InteractionExpiredError());
|
||||
}
|
||||
|
||||
late String url;
|
||||
late Map<String, dynamic> body;
|
||||
late String method;
|
||||
|
||||
if (hasResponded) {
|
||||
url = "/webhooks/${this._client.app.id.toString()}/${this.interaction.token}/messages/@original";
|
||||
body = <String, dynamic> {
|
||||
"content": content,
|
||||
"embeds": embed != null ? [BuilderUtility.buildRawEmbed(embed)] : null,
|
||||
"allowed_mentions":
|
||||
allowedMentions != null ? BuilderUtility.buildRawAllowedMentions(allowedMentions) : null,
|
||||
"tts": content != null && tts != null && tts
|
||||
};
|
||||
method = "PATCH";
|
||||
} else {
|
||||
url = "/interactions/${this.interaction.id.toString()}/${this.interaction.token}/callback";
|
||||
body = <String, dynamic>{
|
||||
"type": 4,
|
||||
"data": {
|
||||
if (hidden) "flags": 1 << 6,
|
||||
"content": content,
|
||||
"embeds": embed != null ? [BuilderUtility.buildRawEmbed(embed)] : null,
|
||||
"allowed_mentions":
|
||||
allowedMentions != null ? BuilderUtility.buildRawAllowedMentions(allowedMentions) : null,
|
||||
"tts": content != null && tts != null && tts
|
||||
},
|
||||
};
|
||||
method = "POST";
|
||||
}
|
||||
|
||||
final response = await this._client.httpEndpoints.sendRawRequest(
|
||||
url,
|
||||
method,
|
||||
body: body,
|
||||
);
|
||||
|
||||
if (response is HttpResponseError) {
|
||||
return Future.error(response);
|
||||
}
|
||||
|
||||
hasResponded = true;
|
||||
}
|
||||
|
||||
/// Create a followup message for an Interaction
|
||||
Future<void> sendFollowup({ dynamic content, EmbedBuilder? embed, bool? tts, AllowedMentions? allowedMentions, bool hidden = false}) async {
|
||||
final url = "/webhooks/${this._client.app.id.toString()}/${this.interaction.token}";
|
||||
final body = <String, dynamic> {
|
||||
"content": content,
|
||||
"embeds": embed != null ? [BuilderUtility.buildRawEmbed(embed)] : null,
|
||||
"allowed_mentions":
|
||||
allowedMentions != null ? BuilderUtility.buildRawAllowedMentions(allowedMentions) : null,
|
||||
"tts": content != null && tts != null && tts
|
||||
};
|
||||
|
||||
final response = await this._client.httpEndpoints.sendRawRequest(
|
||||
url,
|
||||
"POST",
|
||||
body: body,
|
||||
);
|
||||
|
||||
if (response is HttpResponseError) {
|
||||
return Future.error(response);
|
||||
}
|
||||
}
|
||||
|
||||
/// Should be sent when you receive a ping from interactions.
|
||||
/// Used to acknowledge a ping. Internal to the InteractionEvent.
|
||||
Future<void> _pong() async {
|
||||
if (DateTime.now().isBefore(this.receivedAt.add(const Duration(minutes: 15)))) {
|
||||
if (!hasResponded) {
|
||||
final response = await this._client.httpEndpoints.sendRawRequest(
|
||||
"/interactions/${this.interaction.id.toString()}/${this.interaction.token}/callback",
|
||||
"POST",
|
||||
body: {
|
||||
"type": 1,
|
||||
"data": null,
|
||||
},
|
||||
);
|
||||
|
||||
if (response is HttpResponseError) {
|
||||
return Future.error(response);
|
||||
}
|
||||
|
||||
hasResponded = true;
|
||||
} else {
|
||||
return Future.error(InteractionExpiredError());
|
||||
}
|
||||
} else {
|
||||
if (DateTime.now().isAfter(this.receivedAt.add(const Duration(minutes: 15)))) {
|
||||
return Future.error(InteractionExpiredError());
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to acknowledge a Interaction but not send any response yet. Once this is sent you can then only send ChannelMessages. You can also set showSource to also print out the command the user entered.
|
||||
Future<void> acknowledge({ bool showSource = false, }) async {
|
||||
if (DateTime.now().isBefore(this.receivedAt.add(const Duration(minutes: 15)))) {
|
||||
if (hasResponded) {
|
||||
return Future.error(AlreadyRespondedError());
|
||||
}
|
||||
final url = "/interactions/${this.interaction.id.toString()}/${this.interaction.token}/callback";
|
||||
|
||||
final response = await this._client.httpEndpoints.sendRawRequest(
|
||||
url,
|
||||
"POST",
|
||||
body: {
|
||||
"type": showSource ? 5 : 2,
|
||||
"data": null,
|
||||
},
|
||||
);
|
||||
|
||||
if (response is HttpResponseError) {
|
||||
return Future.error(response);
|
||||
}
|
||||
|
||||
hasResponded = true;
|
||||
} else {
|
||||
if (hasResponded) {
|
||||
return Future.error(InteractionExpiredError());
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to acknowledge a Interaction and send a response. Once this is sent you can then only send ChannelMessages. You can also set showSource to also print out the command the user entered.
|
||||
Future<void> reply({ dynamic content, EmbedBuilder? embed, bool? tts, AllowedMentions? allowedMentions, bool showSource = false, bool hidden = false}) async {
|
||||
if (DateTime.now().isBefore(this.receivedAt.add(const Duration(minutes: 15)))) {
|
||||
String url;
|
||||
if (hasResponded) {
|
||||
url = "/webhooks/${this.interaction.id.toString()}/${this.interaction.token}";
|
||||
} else {
|
||||
url = "/interactions/${this.interaction.id.toString()}/${this.interaction.token}/callback";
|
||||
}
|
||||
final response = await this._client.httpEndpoints.sendRawRequest(
|
||||
url,
|
||||
"POST",
|
||||
body: {
|
||||
"type": showSource ? 4 : 3,
|
||||
"data": {
|
||||
if (hidden) "flags": 1 << 6,
|
||||
"content": content,
|
||||
"embeds": embed != null ? [BuilderUtility.buildRawEmbed(embed)] : null,
|
||||
"allowed_mentions":
|
||||
allowedMentions != null ? BuilderUtility.buildRawAllowedMentions(allowedMentions) : null,
|
||||
"tts": content != null && tts != null && tts
|
||||
},
|
||||
},
|
||||
);
|
||||
final response = await this._client.httpEndpoints.sendRawRequest(
|
||||
"/interactions/${this.interaction.id.toString()}/${this.interaction.token}/callback",
|
||||
"POST",
|
||||
body: {
|
||||
"type": 1,
|
||||
"data": null,
|
||||
},
|
||||
);
|
||||
|
||||
if (response is HttpResponseError) {
|
||||
return Future.error(response);
|
||||
}
|
||||
|
||||
if (!hasResponded) {
|
||||
hasResponded = true;
|
||||
}
|
||||
} else {
|
||||
return Future.error(InteractionExpiredError());
|
||||
if (response is HttpResponseError) {
|
||||
return Future.error(response);
|
||||
}
|
||||
|
||||
hasResponded = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,6 +58,15 @@ class Interaction extends SnowflakeEntity {
|
|||
this.commandId = Snowflake(raw["data"]["id"]);
|
||||
}
|
||||
|
||||
/// Allows to fetch argument value by argument name
|
||||
dynamic? getArg(String name) {
|
||||
try {
|
||||
return this.args.firstWhere((element) => element.name == name);
|
||||
} on Error {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Iterable<InteractionOption> _generateArgs(Map<String, dynamic> rawData) sync* {
|
||||
if (rawData["options"] == null) {
|
||||
return;
|
||||
|
|
|
@ -2,6 +2,8 @@ part of nyxx_interactions;
|
|||
|
||||
/// A slash command, can only be instantiated through a method on [Interactions]
|
||||
class SlashCommand {
|
||||
final Nyxx _client;
|
||||
|
||||
Snowflake? _id;
|
||||
|
||||
Snowflake get id {
|
||||
|
@ -13,16 +15,16 @@ class SlashCommand {
|
|||
}
|
||||
|
||||
/// Command name to be shown to the user in the Slash Command UI
|
||||
late final String name;
|
||||
final String name;
|
||||
|
||||
/// Command description shown to the user in the Slash Command UI
|
||||
late final String description;
|
||||
final String description;
|
||||
|
||||
/// The guild that the slash Command is registered in. This can be null if its a global command.
|
||||
late final Cacheable<Snowflake, Guild>? guild;
|
||||
|
||||
/// The arguments that the command takes
|
||||
late final List<CommandArg> args;
|
||||
final List<CommandArg> args;
|
||||
|
||||
/// If the command is a global on, false if restricted to a guild.
|
||||
bool get isGlobal => this.guild == null;
|
||||
|
@ -30,8 +32,6 @@ class SlashCommand {
|
|||
/// If the command has been registered with the discord api
|
||||
late bool isRegistered = false;
|
||||
|
||||
late final Nyxx _client;
|
||||
|
||||
SlashCommand._new(this._client, this.name, this.description, this.args, {this.guild});
|
||||
|
||||
Future<SlashCommand> _register() async {
|
||||
|
|
Loading…
Reference in a new issue