Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add slash command mentions #2251

Merged
merged 35 commits into from Oct 30, 2022
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
9ee9704
Add slash command mentions
freya022 Sep 17, 2022
8de34d6
Add toString, equals, hashCode
freya022 Sep 17, 2022
866116f
Check CustomEmoji instead of Emoji in isMentioned
freya022 Sep 17, 2022
8b9f904
Move SlashCommandReference to internals
freya022 Sep 17, 2022
8d0e64e
ICommandReference docs
freya022 Sep 17, 2022
cd4b794
Default `#getAsMention` in `ICommandReference`
freya022 Sep 17, 2022
a6c94b8
Mentions docs
freya022 Sep 17, 2022
d8e2f16
typo
freya022 Sep 17, 2022
ab9a704
Throw if command type isn't slash
freya022 Sep 17, 2022
0f19b57
Don't use Checks
freya022 Sep 18, 2022
2a98d56
Add Nonnull
freya022 Sep 18, 2022
cf611f3
Fix string representation
freya022 Sep 18, 2022
74b4eda
Fix equality
freya022 Sep 18, 2022
aee9ce9
Update src/main/java/net/dv8tion/jda/api/interactions/commands/IComma…
freya022 Sep 18, 2022
14b6ed7
Update src/main/java/net/dv8tion/jda/api/interactions/commands/IComma…
freya022 Sep 18, 2022
b2f25c9
Add subcommands/groups to mention, implement in subcommands/groups
freya022 Sep 18, 2022
18dca6e
Expose SlashCommandReference, add #getSubcommands and #getSubcommandG…
freya022 Sep 18, 2022
2afc16d
Return `SlashCommandReference` in `Mentions`
freya022 Sep 18, 2022
0ba8c40
Fix example
freya022 Sep 18, 2022
55ec8b1
Fix ICommandReference#getAsMention
freya022 Sep 18, 2022
6322ca2
Apply suggestions from code review
freya022 Sep 21, 2022
3dd8ecf
Update src/main/java/net/dv8tion/jda/api/entities/Mentions.java
freya022 Sep 21, 2022
9b069ea
Update src/main/java/net/dv8tion/jda/api/entities/Message.java
freya022 Oct 16, 2022
5da00db
Use Objects.hash
freya022 Oct 16, 2022
0a8312d
Move to helper method
freya022 Oct 16, 2022
84b1b72
Merge branch 'master' into feature/slash-mentions
freya022 Oct 23, 2022
9b5f3fc
Update src/main/java/net/dv8tion/jda/api/interactions/commands/SlashC…
freya022 Oct 23, 2022
a1d28b8
Add nullability annotations
freya022 Oct 23, 2022
2a3bdc1
Use EntityString
freya022 Oct 23, 2022
801795b
Rename `CommandInteractionPayload#getCommandPath` to `getFullCommandN…
freya022 Oct 23, 2022
63fce5e
Rename `SlashCommandReference#getCommandPath` to `getFullCommandName`
freya022 Oct 23, 2022
fcc1c1c
Merge branch 'master' into feature/slash-mentions
freya022 Oct 29, 2022
287d57e
Improve ICommandReference#getFullCommandName docs
freya022 Oct 29, 2022
fac7ff8
Return empty slash command references collections in select menus
freya022 Oct 29, 2022
769776e
Apply suggestions from code review
freya022 Oct 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 43 additions & 0 deletions src/main/java/net/dv8tion/jda/api/entities/Mentions.java
Expand Up @@ -20,6 +20,7 @@
import net.dv8tion.jda.api.entities.channel.concrete.PrivateChannel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
import net.dv8tion.jda.api.entities.emoji.CustomEmoji;
import net.dv8tion.jda.api.interactions.commands.SlashCommandReference;
import org.apache.commons.collections4.Bag;

import javax.annotation.Nonnull;
Expand Down Expand Up @@ -325,6 +326,48 @@ public interface Mentions
@Nonnull
Bag<Member> getMembersBag();

/**
* An immutable list of all mentioned {@link SlashCommandReference slash commands}.
* <br>If none were mentioned, this list is empty. Elements are sorted in order of appearance.
*
* <p>Be aware these mentions could be not mentioning an actual command
freya022 marked this conversation as resolved.
Show resolved Hide resolved
*
* @return Immutable list of mentioned slash commands, or an empty list
*/
@Nonnull
List<SlashCommandReference> getSlashCommands();
freya022 marked this conversation as resolved.
Show resolved Hide resolved

/**
* A {@link org.apache.commons.collections4.Bag Bag} of mentioned {@link SlashCommandReference slash commands}.
* <br>This can be used to retrieve the amount of times a slash commands was mentioned.
*
* <p>Be aware these mentions could be not mentioning an actual command
freya022 marked this conversation as resolved.
Show resolved Hide resolved
freya022 marked this conversation as resolved.
Show resolved Hide resolved
*
* <p><b>Example</b><br>
* <pre>{@code
* void sendCount(Message msg)
* {
* List<SlashCommandReference> mentions = msg.getMentions().getSlashCommands(); // distinct list, in order of appearance
* Bag<SlashCommandReference> count = msg.getMentions().getSlashCommandsBag();
* StringBuilder content = new StringBuilder();
* for (SlashCommandReference commandRef : mentions)
* {
* content.append(commandRef.getAsMention())
* .append(": ")
* .append(count.getCount(commandRef))
* .append("\n");
* }
* msg.getChannel().sendMessage(content.toString()).queue();
* }
* }</pre>
*
* @return {@link org.apache.commons.collections4.Bag Bag} of mentioned slash commands
*
* @see #getSlashCommands()
*/
@Nonnull
Bag<SlashCommandReference> getSlashCommandsBag();

/**
* Combines all instances of {@link net.dv8tion.jda.api.entities.IMentionable IMentionable}
* filtered by the specified {@link net.dv8tion.jda.api.entities.Message.MentionType MentionType} values.
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/net/dv8tion/jda/api/entities/Message.java
Expand Up @@ -1990,7 +1990,13 @@ enum MentionType
/**
* Represents a mention for all users in a server, literal {@code @everyone}.
*/
EVERYONE("@everyone", "everyone");
EVERYONE("@everyone", "everyone"),
/**
* Represents a mention for a slash command.
* <br>The first group is the command name, the second group is the subcommand group (nullable),
* the third group is the subcommand (nullable), and the fourth group is the command ID.
freya022 marked this conversation as resolved.
Show resolved Hide resolved
*/
SLASH_COMMAND("</([\\w-]+)(?> ([\\w-]+))??(?> ([\\w-]+))?:(\\d+)>", null);
freya022 marked this conversation as resolved.
Show resolved Hide resolved

private final Pattern pattern;
private final String parseKey;
Expand Down
Expand Up @@ -48,7 +48,7 @@
* @see Guild#retrieveCommandById(String)
* @see Guild#retrieveCommands()
*/
public interface Command extends ISnowflake
public interface Command extends ISnowflake, ICommandReference
freya022 marked this conversation as resolved.
Show resolved Hide resolved
{
/**
* Delete this command.
Expand Down Expand Up @@ -830,22 +830,35 @@ public String toString()
/**
* An Subcommand for a command.
*/
class Subcommand
class Subcommand implements ICommandReference
{
private final ICommandReference parentCommand; //Could be Command or SubcommandGroup
private final String name, description;
private final LocalizationMap nameLocalizations;
private final LocalizationMap descriptionLocalizations;
private final List<Option> options;

public Subcommand(DataObject json)
public Subcommand(ICommandReference parentCommand, DataObject json)
{
this.parentCommand = parentCommand;
this.name = json.getString("name");
this.nameLocalizations = LocalizationUtils.unmodifiableFromProperty(json, "name_localizations");
this.description = json.getString("description");
this.descriptionLocalizations = LocalizationUtils.unmodifiableFromProperty(json, "description_localizations");
this.options = CommandImpl.parseOptions(json, CommandImpl.OPTION_TEST, Option::new);
}

/**
* {@inheritDoc}
*
* <p><b>This will return the ID of the top level command</b>
*/
@Override
public long getIdLong()
{
return parentCommand.getIdLong();
}

/**
* The name of this subcommand.
*
Expand All @@ -868,6 +881,13 @@ public LocalizationMap getNameLocalizations()
return nameLocalizations;
}

@Nonnull
@Override
public String getCommandPath()
{
return parentCommand.getCommandPath() + " " + getName();
}

/**
* The description of this subcommand.
*
Expand Down Expand Up @@ -928,20 +948,33 @@ public String toString()
/**
* An Subcommand Group for a command.
*/
class SubcommandGroup
class SubcommandGroup implements ICommandReference
{
private final Command parentCommand;
private final String name, description;
private final LocalizationMap nameLocalizations;
private final LocalizationMap descriptionLocalizations;
private final List<Subcommand> subcommands;

public SubcommandGroup(DataObject json)
public SubcommandGroup(Command parentCommand, DataObject json)
{
this.parentCommand = parentCommand;
this.name = json.getString("name");
this.nameLocalizations = LocalizationUtils.unmodifiableFromProperty(json, "name_localizations");
this.description = json.getString("description");
this.descriptionLocalizations = LocalizationUtils.unmodifiableFromProperty(json, "description_localizations");
this.subcommands = CommandImpl.parseOptions(json, CommandImpl.SUBCOMMAND_TEST, Subcommand::new);
this.subcommands = CommandImpl.parseOptions(json, CommandImpl.SUBCOMMAND_TEST, (DataObject o) -> new Subcommand(this, o));
}

/**
* {@inheritDoc}
*
* <p><b>This will return the ID of the top level command</b>
*/
@Override
public long getIdLong()
{
return parentCommand.getIdLong();
}

/**
Expand All @@ -966,6 +999,13 @@ public LocalizationMap getNameLocalizations()
return nameLocalizations;
}

@Nonnull
@Override
public String getCommandPath()
{
return parentCommand.getCommandPath() + " " + getName();
freya022 marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* The description of this subcommand group.
*
Expand Down
@@ -0,0 +1,58 @@
/*
* Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.dv8tion.jda.api.interactions.commands;

import net.dv8tion.jda.api.entities.IMentionable;

import javax.annotation.Nonnull;

/**
* Represents a mentionable slash command.
*/
public interface ICommandReference extends IMentionable
{
/**
* Returns the name of the slash command
freya022 marked this conversation as resolved.
Show resolved Hide resolved
freya022 marked this conversation as resolved.
Show resolved Hide resolved
*
* @return the name of the slash command
*/
@Nonnull
String getName();
freya022 marked this conversation as resolved.
Show resolved Hide resolved

/**
* Returns the entire path (separated with spaces) of this command
*
* @return the entire path (separated with spaces) of this command
*/
@Nonnull
String getCommandPath();

/**
* {@inheritDoc}
*
* <p><b>This will only work on slash commands!</b>
*
* @throws IllegalStateException
* If the command is not a slash command (i.e. not of type {@link Command.Type#SLASH})
*/
@Nonnull
@Override
default String getAsMention()
{
return "</" + getCommandPath() + ":" + getIdLong() + ">";
}
}
@@ -0,0 +1,120 @@
/*
* Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.dv8tion.jda.api.interactions.commands;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;
import java.util.StringJoiner;

/**
* Represents a slash command mention, such as {@code </ban soft:1021082477038678126>}
*/
public class SlashCommandReference implements ICommandReference
{
private final long id;
private final String name;
private final String subcommand;
private final String subcommandGroup;

public SlashCommandReference(String name, String subcommandGroup, String subcommand, long id)
freya022 marked this conversation as resolved.
Show resolved Hide resolved
{
this.name = name;
this.subcommandGroup = subcommandGroup;
this.subcommand = subcommand;
this.id = id;
}

@Override
public long getIdLong()
{
return id;
}

@Nonnull
@Override
public String getName()
{
return name;
}

/**
* Returns the subcommand of the slash command
*
* @return the subcommand of the slash command
*/
@Nullable
public String getSubcommand()
freya022 marked this conversation as resolved.
Show resolved Hide resolved
{
return subcommand;
}

/**
* Returns the subcommand group of the slash command
*
* @return the subcommand group of the slash command
*/
@Nullable
public String getSubcommandGroup()
{
return subcommandGroup;
}

@Nonnull
@Override
public String getCommandPath()
{
final StringJoiner joiner = new StringJoiner(" ");
joiner.add(name);
if (subcommandGroup != null)
joiner.add(subcommandGroup);
if (subcommand != null)
joiner.add(subcommand);

return joiner.toString();
}
freya022 marked this conversation as resolved.
Show resolved Hide resolved

@Override
public String toString()
{
return "SlashCommandReference: " + getCommandPath() + " (" + getId() + ")";
freya022 marked this conversation as resolved.
Show resolved Hide resolved
}

@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (!(o instanceof SlashCommandReference)) return false;

SlashCommandReference that = (SlashCommandReference) o;

if (id != that.id) return false;
if (!name.equals(that.name)) return false;
if (!Objects.equals(subcommand, that.subcommand)) return false;
return Objects.equals(subcommandGroup, that.subcommandGroup);
freya022 marked this conversation as resolved.
Show resolved Hide resolved
}

@Override
public int hashCode()
{
int result = Long.hashCode(id);
result = 31 * result + name.hashCode();
result = 31 * result + (subcommand != null ? subcommand.hashCode() : 0);
result = 31 * result + (subcommandGroup != null ? subcommandGroup.hashCode() : 0);
return result;
}
freya022 marked this conversation as resolved.
Show resolved Hide resolved
}