Bukkit plugin kick reason only using first word - java

So I'm making a kick/ban command for my server and the format is /kick name reason.
I got it all working but the reason can only be 1 word and anything over that excludes it, for example /kick BattleDash hello world would say BattleDash was kicked for hello.
Here's my code:
if (cmd.getName().equalsIgnoreCase("kick") && sender instanceof Player) {
Player player = (Player) sender;
int length = args.length;
if (length >= 2) {
boolean playerFound = false;
for (Player playerToKick : Bukkit.getServer().getOnlinePlayers()) {
if(playerToKick.getName().equalsIgnoreCase(args[0])) {
playerToKick.kickPlayer(ChatColor.RED + "Kicked by Administrator " + player.getName() + "\nReason: " + args[1]);
player.sendMessage(ChatColor.RED + "[BATTLEDASHLOGS]: Kicked player " + playerToKick.getName() + "succesfully!");
break;
}
}
if (playerFound == false) {
player.sendMessage(ChatColor.RED + "[BATTLEDASHLOGS]: " + args[0] + " was not found!");
}
} else player.sendMessage(ChatColor.RED + "[BATTLEDASHLOGS]: Incorrect arguments!" + ChatColor.RED + " /kick <PlayerName> <reason>");
return true;
}
(Also if you don't include a reason it gives internal error in chat and exception occured in console)

Your code is doing that due to the way it was programmed.
If we take a look at line that takes the argument:
playerToKick.kickPlayer(ChatColor.RED + "Kicked by Administrator " + player.getName() + "\nReason: " + args[1]);
We can see that you're only using args[1]. If we see a message as an array, the problem will be clear:
At position 0 (remember arrays start at 0): BattleDash
1: hello
2: world
When you take only args[1] to your message, only hello would be used! What we need to do instead, is use all the arguments. One way to do that is like this:
// First, transform your array into a list, so it's easier to understand
List<String> arguments = new ArrayList<>(args);
String playerName = arguments.get(0); // Get the player name
arguments.remove(0); // Remove the player name from our arguments list, we don't want it in the message
String message = String.join(" ", arguments); // Combine all the other arguments into a message

Related

Seperating ArrayList items to a regular keyword group

I started Java for plugin codding in minecraft. now I'm trying to add role names as prefix and show it in chat.
ArrayList<String> userRoles = new ArrayList<String>();
if(player.hasPermission("chat.rank.admin")){
userRoles.add("[Admin]");
} if(player.hasPermission("chat.rank.vip")) {
userRoles.add("[VIP]");
}
event.setFormat(userRoles<>(1) + " " + player.getDisplayName() + "§7: " + msg);
// In this line, the expected output is "[Admin] user: msg" or both [Admin] [VIP] user: msg"
// But it gives "([Admin],[VIP]) user: msg"
// I'm sure it has a simple solution but as I said, I'm new here. thanks from now
It seems like you are trying to create a list which only stores one value.
You might want to try creating a function that get the rank name of the player outside of your PlayerChatEvent listener.
Here's a demo code:
public String getPlayerRankName(Player p){
if (p.hasPermission("chat.rank.admin"))
return "[Admin]";
else if (p.hasPermission("chat.rank.vip"))
return "[VIP]";
else
return "";
}
And in your PlayerChatEvent event listener, call this function in your chat line:
event.setFormat(getPlayerRankName(event.getPlayer()) + " " + player.getDisplayName() + "§7: " + msg);

Youtube Search Command for JDA Discord Music Bot

I've been working on a Discord bot for a few days now.
Initially only with simpler commands etc. But slowly I also devoted myself to the topic of music bot.
I also use the YouTube Data API for this and everything works so far. However, I would now like to incorporate a Youtube Search Command or build it into another (Play Command). I already have half a search command.
So far you can do $play (song title)
and the first track found will be selected.
However, I want to be able to see the first 10 search results and then choose between them.
I have already figured out how to display the search results, but now I need a little help with how to enter a command, after you have already entered another.
So you enter: $play Faded
Then a normal EmbedBuilder comes up and shows you the search results, and then you can select the desired track by entering 1, 2, 3, 4, 5, 6, 7, 8, 9 or 10.
This is the code:
public class PlayCommand implements ServerCommand {
private final YouTube youTube;
public PlayCommand() {
YouTube temp = null;
try {
temp = new YouTube.Builder(
GoogleNetHttpTransport.newTrustedTransport(),
JacksonFactory.getDefaultInstance(),
null
)
.setApplicationName("JDA Discord Bot")
.build();
} catch (Exception e) {
e.printStackTrace();
}
youTube = temp;
}
#Override
public void performCommand(List<String> args, Member m, TextChannel channel, Message message) throws RiotApiException {
String input = String.join(" ", args.subList(1, args.size() - 1));
if (!isUrl(input)) {
String ytSearched = searchYoutube(channel, input);
if (ytSearched == null) {
channel.sendMessage("Keine Ergebnisse!").queue();
return;
}
input = ytSearched;
}
PlayerManager manager = PlayerManager.getInstance();
manager.loadAndPlay(channel, input);
manager.getGuildMusicManager(channel.getGuild()).player.setVolume(100);
}
private boolean isUrl(String input) {
try {
new URL(input);
return true;
} catch (MalformedURLException ignored) {
return false;
}
}
#Nullable
private String searchYoutube(TextChannel channel, String input) {
String youtubeKey = "AIzaSyDoQ4OInMTYth7hdlWwQSIaHuxpxxv7eJs";
try {
List<SearchResult> results = youTube.search()
.list("id,snippet")
.setQ(input)
.setMaxResults(10L)
.setType("video")
.setFields("items(id/kind,id/videoId,snippet/title,snippet/thumbnails/default/url)")
.setKey(youtubeKey)
.execute()
.getItems();
if (!results.isEmpty()) {
String videoId = results.get(0).getId().getVideoId();
/*EmbedBuilder builder = new EmbedBuilder();
builder.setTitle("Suchergebnisse");
builder.setColor(Color.RED);
builder.setDescription( "1. " + results.get(0).getSnippet().getTitle() + "\n" +
"2. " + results.get(1).getSnippet().getTitle() + "\n" +
"3. " + results.get(2).getSnippet().getTitle() + "\n" +
"4. " + results.get(3).getSnippet().getTitle() + "\n" +
"5. " + results.get(4).getSnippet().getTitle() + "\n" +
"6. " + results.get(5).getSnippet().getTitle() + "\n" +
"7. " + results.get(6).getSnippet().getTitle() + "\n" +
"8. " + results.get(7).getSnippet().getTitle() + "\n" +
"9. " + results.get(8).getSnippet().getTitle() + "\n" +
"10. " + results.get(9).getSnippet().getTitle());
channel.sendMessage(builder.build()).queue();
*/
return "https://www.youtube.com/watch?v=" + videoId;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
I think you are looking for an EventWaiter.
With JDA-Utilities you can achieve what you want.
You just basically wait for an event, check if it's suitable for the use case of yours (eg: is a specific event, or contains a specific text)
Check out this stackoverflow answer about EventWaiter and adding it as an EventListener.
You would want to check if the received text for example is part of the youtube search result. Also don't forget about having a time limit for accepting answers.

JAVA Discord Bot (java.lang.ArrayIndexOutOfBoundsException)

I have a weird problem. Since I'm new in coding, maybe I am dumb and I don't know how can I resolve this issue, so the issue is, I have 2 commands for my discord bot, permanent mute, and temporary mute. I want to make something like a placeholder to be used in config.yml since it will be more configurable, but when I use args[], I have a weird problem, here is it :
[JDA MainWS-ReadThread] ERROR net.dv8tion.jda.api.JDA - One of the EventListeners had an uncaught exception
java.lang.ArrayIndexOutOfBoundsException: Index 2 out of bounds for length 2
at me.trashlord.bot.events.TempMuteCommand.onGuildMessageReceived(TempMuteCommand.java:34)
at net.dv8tion.jda.api.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:396)
at net.dv8tion.jda.api.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:96)
at net.dv8tion.jda.internal.hooks.EventManagerProxy.handleInternally(EventManagerProxy.java:82)
at net.dv8tion.jda.internal.hooks.EventManagerProxy.handle(EventManagerProxy.java:69)
at net.dv8tion.jda.internal.JDAImpl.handleEvent(JDAImpl.java:166)
at net.dv8tion.jda.internal.handle.MessageCreateHandler.handleInternally(MessageCreateHandler.java:97)
at net.dv8tion.jda.internal.handle.SocketHandler.handle(SocketHandler.java:36)
at net.dv8tion.jda.internal.requests.WebSocketClient.onDispatch(WebSocketClient.java:921)
at net.dv8tion.jda.internal.requests.WebSocketClient.onEvent(WebSocketClient.java:808)
at net.dv8tion.jda.internal.requests.WebSocketClient.handleEvent(WebSocketClient.java:786)
at net.dv8tion.jda.internal.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:959)
at com.neovisionaries.ws.client.ListenerManager.callOnBinaryMessage(ListenerManager.java:385)
at com.neovisionaries.ws.client.ReadingThread.callOnBinaryMessage(ReadingThread.java:276)
at com.neovisionaries.ws.client.ReadingThread.handleBinaryFrame(ReadingThread.java:996)
at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:755)
at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:108)
at com.neovisionaries.ws.client.ReadingThread.runMain(ReadingThread.java:64)
at com.neovisionaries.ws.client.WebSocketThread.run(WebSocketThread.java:45)
ALSO, here is my code at those lines :
String[] args = event.getMessage().getContentRaw().split("\\s+");
String MutedMessage = ConfigManager.INSTANCE.getSetting("MutedMessage")
.replaceAll("%muteduser", args[1]);
String UnMutedMessage = ConfigManager.INSTANCE.getSetting("UnMutedMessage")
.replaceAll("%unmuteduser", args[1]);
String TempMuted1 = ConfigManager.INSTANCE.getSetting("TempMutedMSG")
.replaceAll("%tempmutedusr", String.valueOf(event.getGuild().getMemberById(args[1].replaceAll("[^\\d]+", ""))))
.replaceAll("%tempmutetime", args[2]);
if (args[0].equalsIgnoreCase(Commands.prefix + "mute")) {
if (Objects.requireNonNull(event.getMember()).hasPermission(Permission.MESSAGE_MANAGE)) {
if (args.length == 2) {
Member member = event.getGuild().getMemberById(args[1].replaceAll("[^\\d]+", ""));
Role role = event.getGuild().getRoleById(MutedRole);
if (!Objects.requireNonNull(member).getRoles().contains(role)) {
// Mute user
event.getChannel().sendMessage(MutedMessage).queue();
event.getGuild().addRoleToMember(member, Objects.requireNonNull(role)).complete();
} else {
// Unmute user
event.getChannel().sendMessage(UnMutedMessage).queue();
event.getGuild().removeRoleFromMember(member, Objects.requireNonNull(role)).complete();
}
} else if (args.length == 3) {
Member member = event.getGuild().getMemberById(args[1].replaceAll("[^\\d]+", ""));
Role role = event.getGuild().getRoleById(MutedRole);
//event.getChannel().sendMessage(TempMuted1 + " " + args[1] + " " + TempMuted2 + " " + args[2] + " " + TempMuted3).queue();
event.getChannel().sendMessage(TempMuted1).queue();
event.getGuild().addRoleToMember(Objects.requireNonNull(member), Objects.requireNonNull(role))
.complete();
// Unmute after a few seconds
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
event.getChannel().sendMessage(TempUnMuted + " " + args[1] + ".").queue();
event.getGuild().removeRoleFromMember(member, role).complete();
}
},
TimeUnit.MINUTES.toMillis(Integer.parseInt(args[2]))
);
} else {
event.getChannel().sendMessage("Incorrect syntax. Use `~mute [user mention] [time {optional}]`")
.queue();
}
}
}
}
}
the problem is you are trying to get an element from args[2], which may the array only contains 2 elements (length 2) in the following code:
String TempMuted1 = ConfigManager.INSTANCE.getSetting("TempMutedMSG")
.replaceAll("%tempmutedusr", String.valueOf(event.getGuild().getMemberById(args[1].replaceAll("[^\\d]+", ""))))
.replaceAll("%tempmutetime", args[2]);
Note that in java arrays are zero-based and indexes start from 0 to length - 1.
You can take this code inside the if-condition:
else if (args.length == 3) {
String TempMuted1 = ConfigManager.INSTANCE.getSetting("TempMutedMSG")
.replaceAll("%tempmutedusr", String.valueOf(event.getGuild().getMemberById(args[1].replaceAll("[^\\d]+", ""))))
.replaceAll("%tempmutetime", args[2]);
// your code
}
Are you sure that this line from your code:
String TempMuted1 = ConfigManager.INSTANCE.getSetting("TempMutedMSG")
.replaceAll("%tempmutedusr", String.valueOf(event.getGuild().getMemberById(args[1].replaceAll("[^\\d]+", ""))))
.replaceAll("%tempmutetime", args[2]);
args[1] and args[2] is correct?
If the length is 2, Then args[2] is looking for the 3rd value and you might not have it...
Have a further look on how length and index works for arrays.

getInt Function Doesn't Return Anything

I am currently trying to making a custom rules plugin (for minecraft) and I am trying to see if the player has something activated which I stored in the config file. It is in the listener class (which calls the config from the main). Here is my code:
#EventHandler
public void onEvent(AsyncPlayerChatEvent e) {
Player player = e.getPlayer();
if (config.getInt("EditingLine." + player.getName().toLowerCase()) == 1) {
int line = 0;
try {
line = Integer.parseInt(e.getMessage());
} catch (Exception b) {
player.sendMessage(ChatColor.RED + "Invalid Number.");
config.set("EditingLine." + player.getName().toLowerCase(), 0);
}
if (!(line == 0)) {
config.set("EditingLine." + player.getName().toLowerCase(), 0);
config.set("EditingText." + player.getName().toLowerCase(), 1);
e.setCancelled(true);
player.sendMessage(ChatColor.GRAY + "[" + ChatColor.GOLD + "Custom Rules" + ChatColor.GRAY + "]" + ChatColor.GREEN + " Enter the text you would now like on that line.");
}
}
}
The, config.getInt() function in the if then statement currently returns nothing. This may be happening because the config in the Listener Class is actually calling a custom made config, called 'playerdata.yml' and not the actual 'config.yml'. If there is any easier way to write this script, also let me know. I'm trying to make this as simple as I can.
The answer has been solved by merging my two configuration files together.

Bukkit Coding - Kick message with color codes set in config.yml

So I have a plugin im making where they get kicked with a message. I want that message to be in color that is set in the config.yml. heres my code:
}
if (l == 2) {
settings.getData().set("" + target.getName() + "", null);
settings.saveData();
target.kickPlayer(this.getConfig().getString("BanMessage"));
target.setBanned(true);
Bukkit.getServer().broadcastMessage(ChatColor.RED + target.getName() + " " + "Has been tempbanned for 25 Minutes by " + sender.getName() + "" + "(3/3)");
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
public void run() {
target.setBanned(false);
}
}, 1500 * 20);
return true;
}
Heres my config.yml:
BanMessage: You have been temp banned for 25 Minutes
You could use ChatColor.translateAlternateColorCodes():
String kickMessage = plugin.getConfig().getString("BanMessage");
kickMessage = ChatColor.translateAlternateColorCodes('&', kickMessage);
target.kickPlayer(kickMessage);
target.setBanned(true);
You can use these color codes in your configuration file.
So, putting in &6You have been banned for &4Spamming Will give you ChatColor.GOLD + "You have been banned for " + ChatColor.DARK_RED + " Spamming"
and if you would like to make it so they get that same message whenever they join if they're banned, you can use:
#EventHandler
public void playerJoin(PlayerJoinEvent e){
if(myMethodToCheckIfAPlayerIsTempBanned(e.getPlayer()){
String msg = myMethodToGetPlayersBanMessage(e.getPlayer());
e.getPlayer().kickPlayer(msg);
}
}
This should work:
String kickMessage = this.getConfig().getString("BanMessage");
kickMessage.replaceAll("(?i)&([a-f0-9])", "\u00A7$1");
target.kickPlayer(kickMessage);
target.setBanned(true);
Then, you should be able to use these color codes in your config.
ex.
BanMessage: &3You &0have been banned &1for &425 &3minutes
will display as
You have been temp banned for 25 Minutes

Categories