I am developing my bot for discord using Java and JDA API. Before that I asked a similar question, but I ran into another problem.
From this line the problems started :
final Member MentionedMem = event.getMessage().getMentionedMembers().get(0);
Thanks to https://stackoverflow.com/users/10630900/minn for answering the previous question in which he explained to me that this line is causing the error :
java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
For some reason or other it raises an error.
I was trying to find an answer to why this command does not work. The only thing I know is that this command returns an empty array args. Because of this, I cannot finish the bot, that is, I cannot check whether a member can kick others and can't make the main block of code kick members.
How can I fix this error and / or write the rest of the code?
Sorry for my English and many thanks to you.
Some code :
public class KickComm extends ListenerAdapter {
public void onGuildMessageReceived(GuildMessageReceivedEvent event) {
String[] message = event
.getMessage()
.getContentRaw()
.split(" ");
// final Member target = event.getMessage().getMentionedMembers().get(0); ERROR CUZ I DONT NOW WHY
final Member SelfMember = event
.getGuild()
.getSelfMember();
if(message[0].equalsIgnoreCase(Main.prefix + "kick"))
{
if (message.length < 2) {
EmbedBuilder NoUser = new EmbedBuilder();
NoUser.setColor(0xff3923);
NoUser.setTitle("\uD83D\uDD34You need to add a <#username> and <reason>");
NoUser.setFooter("Usage: " + Main.prefix + "kick <#username> <reason>.",
Objects
.requireNonNull(event.getMember())
.getUser()
.getAvatarUrl());
event
.getChannel()
.sendMessage(NoUser.build())
.queue();
NoUser.clear();
} else if (message.length < 3) {
EmbedBuilder NoReason = new EmbedBuilder();
NoReason.setColor(0xff3923);
NoReason.setTitle("\uD83D\uDD34You need to add a <reason>.");
NoReason.setFooter("Usage: " + Main.prefix + "kick <#username> <reason>.",
Objects
.requireNonNull(event.getMember())
.getUser()
.getAvatarUrl());
event
.getChannel()
.sendMessage(NoReason.build())
.queue();
NoReason.clear();
} else if(!SelfMember.hasPermission(Permission.KICK_MEMBERS)) {
EmbedBuilder NoPermission = new EmbedBuilder();
NoPermission.setColor(0xff3923);
NoPermission.setTitle("\uD83D\uDD34You don't have permission to use this command.");
NoPermission.setFooter("Usage: " + Main.prefix + "kick <#username> <reason>.",
Objects
.requireNonNull(event.getMember())
.getUser()
.getAvatarUrl());
event
.getChannel()
.sendMessage(NoPermission.build())
.queue();
NoPermission.clear();
} else if(!Objects.requireNonNull(event.getMember()).hasPermission(Permission.KICK_MEMBERS) || !event.getMember().canInteract(target)) { //Example, don't works
EmbedBuilder NoPermission = new EmbedBuilder();
NoPermission.setColor(0xff3923);
NoPermission.setTitle("\uD83D\uDD34You don't have permission to use this command.");
NoPermission.setFooter("Usage: " + Main.prefix + "kick <#username> <reason>.",
Objects
.requireNonNull(event.getMember())
.getUser()
.getAvatarUrl());
event
.getChannel()
.sendMessage(NoPermission.build())
.queue();
NoPermission.clear();
}
}
}
}
UPD: Please, if you downgrade, then point out the mistakes that I made, and not just downgrade it because you wanted to. I want to correct mistakes, not ruin your mood
It seems like you didn't quite get the problems in your code.
final Member target = event.getMessage().getMentionedMembers().get(0);
This will throw an IndexOutOfBoundsException if your message doesn't include a mentioned member. Because in this case the list of getMentionedMembers() is empty. There is no object to access. get(0) can't get anything.
In order to fix this you have to check first if the list is empty or if the length is zero as Minn already proposed. If it is you can display a message stating, that they need to add an #username.
Cleaning up your code and restructuring it accordingly would help a lot I suppose. Please go over it and make sure to always check, if the needed data exists in the first place and if you really need it. Some things are only needed for a small number of cases, calling them on every message / command is not good practice.
For example, at the moment your bot tries to get the first mentioned member from EVERY message that is sent. This isn't necessary hence you only need it in case it is the kick command.
By the way, the SelfMember is the bot itself. In your code you are telling the user that they don't have the permission although the bot (and not necessarily the user) might lack it which could be confusing.
I didn't see it earlier: Your bot is receiving its own messages as well. You might want to check, if the author of a message is your / a bot before continuing.
In the end I would advice you to always try to understand the answer or advice that is given to you. Asking another question for the same problem isn't going to help you nor does it cast a good light on you and your attempt to learn.
User mentionedUser = event.getMessage().getMentionedMembers().get(0).getUser();
If someone still needs it...
The issue, for some reason, was that you used Member instead of User.
Futhermore, you must use .getUser() to really get the user you want.
I'm currently in a java course and trying to learn how to catch exceptions. In this case I have an input file that is only allowed to contain certains signs and must contain a goal and a start. I check all this in a seperate class constructor and want to insted of just telling the user something is wrong use a try/catch to tell the user that he did something wrong.
while(scanner.hasNext()){
temp = scanner.nextLine();
try {
testString(temp);
}
catch (/*Don't know what to catch*/){
System.out.println("Input file contains unvalid input");
}
mazeData.add(row, temp);
row++;
}
try{
containStartAndGoal();
}
catch(/*Dont know what to catch?*/){
System.out.println("Input file have either no goal or start!");
}
Currently this is my issue, i have tried to use a IOExecption but that does not seem to work. If I use just Execption i need to catch it every time i try to call this method. Which I do in both my test program and main program. I have tried to read as much as I can around here but don't seem to understand what I am suppose to do. Can I not try something if I don't throw it somewhere else? And what type of execption am I suppose to use when there is an input file that is incorrect. We didn't really get any information around how these work in school only that they exist.
My intentions are to ask the user to write down some code in a TextArea, then see if that code compiles, and if it does, print out the results to another TextArea, which acts like a console.
Edit:Solving this via online compilers is the priority.
To accomplish this, I've tried using online compilers (i.e. compilerjava.net) and used the library HtmlUnit, but the library came in with a lot of errors, especially when reading the JavaScript code and returned me pages of 'warnings' that increase the compile & run time for about 20 seconds. I will leave the code below with explanations if anyone has intentions about trying to fix it.
I've also tried using the JavaCompiler interface, which did succeed in compiling, but under the conditions that I have provided the exact location of the .java file, which is something I have to create using the information I get from the TextArea. So again, a dead end.
I decided to come back to online compilers, since if I can manage to just return the data from the compiled program, I am set. The only issue is I haven't yet found an online compiler that allows a user to access its fields via Java code ( since its something too specific). I would appreciate any help on this if anyone can provide a way to send and retrieve data from an online compiler.
Here is the code using the HtmlUnit library, on the site 'compilerjava.net'. It is so close to working that the only 2 issues I have is that,
1) Run-time is too long.
2) I cannot access the console output of the code. Reasoning is that, when you hit 'compile', the output text-area's text turns into "executing". After a few seconds, it turns into the output of the code. When I try to access it, the data I retrieve is always "executing" and not the desired output. Here is the code;
public class Test {
public static void main(String[] args) {
try {
// Prevents the program to print thousands of warning codes.
java.util.logging.Logger.getLogger("com.gargoylesoftware").setLevel(java.util.logging.Level.OFF);
java.util.logging.Logger.getLogger("org.apache.http").setLevel(java.util.logging.Level.OFF);
// Initializes the web client and yet again stops some warning codes.
WebClient webClient = new WebClient( BrowserVersion.CHROME);
webClient.getOptions().setThrowExceptionOnFailingStatusCode( false);
webClient.getOptions().setThrowExceptionOnScriptError( false);
webClient.getOptions().setJavaScriptEnabled( true);
webClient.getOptions().setCssEnabled( true);
// Gets the html page, which is the online compiler I'm using.
HtmlPage page = webClient.getPage("https://www.compilejava.net/");
// Succesfully finds the form which has the required buttons etc.
List<HtmlForm> forms = page.getForms();
HtmlForm form = forms.get( 0);
// Finds the textarea which will hold the code.
HtmlTextArea textArea = form.getTextAreaByName( "code");
// Finds the textarea which will hold the result of the compilation.
HtmlTextArea resultArea = page.getHtmlElementById( "execsout");
// Finds the compile button.
HtmlButtonInput button = form.getInputByName( "compile");
System.out.println( button.getValueAttribute());
// Simple code to run.
textArea.setText( "public class HelloWorld\n" +
"{\n" +
" // arguments are passed using the text field below this editor\n" +
" public static void main(String[] args)\n" +
" {\n" +
" System.out.print( \"Hello\");\n" +
" }\n" +
"}");
// Compiles.
button.click();
// Result of the compilation.
System.out.println( resultArea.getText());
} catch ( Exception e) {
e.printStackTrace();
}
}
}
As I said, this final code System.out.println( resultArea.getText()); prints out "executing", which implies that I have succeeded in pressing the compile button on the webpage via code.
So after this long wall of text, I'm either looking for a way to fix the code I presented, which is so darn close to my answer but not quite, or just an entirely different solution to the problem I presented at the beginning.
P.S. Maven is the last hope.
I've made this little ATM application in Java (CLI) and in the beginning I want to have "Code: " and then the user should enter it, and in my Java application it should say something like String(or int?) code = 1234; and if that works then proceed, if not wrong, try again, if faulty 3 times, stop app.
How would something like that look? I've been googling for hours now after masked passwords and tried different types of code without any luck. I just want something simple that converts the string to asterisk.
Currently my password masking looks like this:
java.io.Console cons;
char[] passwd;
if ((cons = System.console()) != null && (passwd = cons.readPassword("[%s]", "Code:")) != null)
However I'm not able (don't know) how to set a password in the code.
Use the readPassword method of class java.io.Console.
The API documentation of class Console has an example that shows how to read a password from the console window without echoing it in plaintext.
edit
Michael, this code is to let a user enter a keyword in the console window without displaying it. After the user has done that, the password is stored in the variable passwd. It seems that what you really want is something completely different: you have some other program that asks for a password, and you want your program to enter that password automatically.
If that is indeed what you want to do, then you don't need to use class Console. You could try using class java.awt.Robot to enter keystrokes in another application (but I'm not sure that it would work with a console window - try it out).
This site has an example of pretty much exactly what you are trying to do: http://download.oracle.com/javase/tutorial/essential/io/cl.html
To be thorough, here are two more links to similar tutorials.
Do they answer your question?
Based on your comments, perhaps you do not understand Java syntax exactly.
You cannot write:
char["mypassword"] passwd;
I think you mean instead:
String str = "mypassword";
char[] passwd = str.toCharArray();
Update
Try this code:
Console c = System.console();
if (c == null) {
System.err.println("No console.");
System.exit(1);
}
char [] passwd = c.readPassword("Enter your password: ");
c.println("Password is:");
c.println(new String(passwd));
Take a look at this sun Java article... it highlights a number of different ways to do it.
Specifically it shows how to use AWT's TextField class with the setEchoChar() method, as well as a method that runs a separate thread to remove and replace typed characters in console applications.
(This is a question my coworker posted elsewhere, but I thought I'd post it here to see if I could hit a different audience.)
Hello all,
I'm testing the possibility of writing a small java application the will use Psexec to kick off remote jobs. In the course of testing binding the stdin and stdout of a java program to psexec I came across an odd bug.
My test program is a basic echo program. It starts a thread to read from stdin and then pipes the read output directly back to stdout. When run on the local machine, not from psexec, it works beautifully. Exactly as it should.
However, when I call it from PsExec the first time the input is piped directly into stdout it is lost. What makes the bug really bizzare is that it is only the first time the input is piped directly into stdout that it is lost. If the input String is appended to another string it works fine. Either a String literal or a String variable. However, if the input String is sent directly to stdout it doesn't go through. The second time it is sent to stdout it goes through fine - and everytime there after.
I'm at a complete loss as to what's going on here. I've tried to test for every possible bug I can think of. I'm out of ideas. Did I miss one or is this just something inside psexec?
Here is the code in question, it's in three classes (one of which implements an interface which is a single function interace).
The Main class:
public class Main {
public static void main(String[] args) {
System.out.println("Starting up.");
CReader input = new CReader(new BufferedReader(
new InputStreamReader(System.in)));
CEcho echo = new CEcho();
input.addInputStreamListener(echo);
input.start();
System.out.println("Successfully started up. Awaiting input.");
}
}
The CReader class which is the thread that reads from stdin:
public class CReader extends Thread {
private ArrayList<InputStreamListener> listeners =
new ArrayList<InputStreamListener>();
private boolean exit = false;
private Reader in;
public CReader(Reader in) {
this.in = in;
}
public void addInputStreamListener(InputStreamListener listener) {
listeners.add(listener);
}
public void fireInputRecieved(String input) {
if(input.equals("quit"))
exit = true;
System.out.println("Input string has made it to fireInputRecieved: "
+ input);
for(int index = 0; index < listeners.size(); index++)
listeners.get(index).inputRecieved(input);
}
#Override
public void run() {
StringBuilder sb = new StringBuilder();
int current = 0, last = 0;
while (!exit) {
try {
current = in.read();
}
catch (IOException e) {
System.out.println("Encountered IOException.");
}
if (current == -1) {
break;
}
else if (current == (int) '\r') {
if(sb.toString().length() == 0) {
// Extra \r, don't return empty string.
continue;
}
fireInputRecieved(new String(sb.toString()));
sb = new StringBuilder();
}
else if(current == (int) '\n') {
if(sb.toString().length() == 0) {
// Extra \n, don't return empty string.
continue;
}
fireInputRecieved(new String(sb.toString()));
sb = new StringBuilder();
}
else {
System.out.println("Recieved character: " + (char)current);
sb.append((char) current);
last = current;
}
}
}
}
The CEcho class, which is the class that pipes it back to stdout:
public class CEcho implements InputStreamListener {
public void inputRecieved(String input) {
System.out.println("\n\nSTART INPUT RECIEVED");
System.out.println("The input that has been recieved is: "+input);
System.out.println("It is a String, that has been copied from a " +
"StringBuilder's toString().");
System.out.println("Outputting it cleanly to standard out: ");
System.out.println(input);
System.out.println("Outputting it cleanly to standard out again: ");
System.out.println(input);
System.out.println("Finished example outputs of input: "+input);
System.out.println("END INPUT RECIEVED\n\n");
}
}
And finally, here is the program output:
>psexec \\remotecomputer "C:\Program Files\Java\jre1.6.0_05\bin\java.exe" -jar "C:\Documents and Settings\testProram.jar"
PsExec v1.96 - Execute processes remotely
Copyright (C) 2001-2009 Mark Russinovich
Sysinternals - www.sysinternals.com
Starting up.
Successfully started up. Awaiting input.
Test
Recieved character: T
Recieved character: e
Recieved character: s
Recieved character: t
Input string has made it to fireInputRecieved: Test
START INPUT RECIEVED
The input that has been recieved is: Test
It is a String, that has been copied from a StringBuilder's toString().
Outputting it cleanly to standard out:
Outputting it cleanly to standard out again:
Test
Finished example outputs of input: Test
END INPUT RECIEVED
have you tried redirecting the output into a file ( java... >c:\output.txt )? this way you could doublecheck if everything is going into stdout and maybe just getting eaten by psexec
PsExec is eating the output. Next interesting thing might be where it's eating the output. You could check this by getting a copy of Wireshark and checking whether the output in question is traversing the network or not. If it's not, then it's being eaten on the remote side. If it is, it's being eaten locally.
Not that I'm really sure where to go from there, but collecting more information certainly seems like a good path to be following...
I was having the same issue and tried multiple combinations of redirects.
This is what worked:
processBuilder.redirectErrorStream(true);
processBuilder.redirectOutput(Redirect.PIPE);
processBuilder.redirectInput(Redirect.INHERIT);
final Process process = processBuilder.start();
// Using Apache Commons IOUtils to get output in String
StringWriter writer = new StringWriter();
IOUtils.copy(process.getInputStream(), writer, StandardCharsets.UTF_8);
String result = writer.toString();
logger.info(result);
final int exitStatus = process.waitFor();
The Redirect.INHERIT for processBuilder.redirectInput got me the missing remote command output.
Is System.out not configured for autoflush? After the first print try System.out.flush() and see if the first line appears without more lines being printed.
(oh yeah, seriously, it is "RECEIVED", not "RECIEVED".)
OK, I've been thinking about this over the weekend and I since you are jumping from machine to machine I wonder if maybe there is a CharSet issue? Maybe it is eating the string the first time and dealing with a different code page or character set issue? Java is 16bit characters normally and windows is either 8bit with code pages or utf-8 these days.
Any chance the local and remote machines have different default character sets? If you are sending localized data over the net it might misbehave.
What I see when running psexec is that it spawns a child window to do the work but doesnt return that program's output to it's console window. I would suggest using WMI or some form of windows process API framework to gain a level of control you appear to lack with psexec. Surely java has an equivalent to .Net's System.Diagnotics.Process class.
Maybe you could try passing a copy of input to your listeners:
public void fireInputRecieved(String input) {
if(input.equals("quit"))
exit = true;
String inputCopy = new String(input);
System.out.println("Input string has made it to fireInputRecieved: "
+ input);
for(int index = 0; index < listeners.size(); index++)
listeners.get(index).inputRecieved(inputCopy);
}
I had similar problems with listeners where a passed variable would end up empty unless I did pass an explicit copy of it.
I don't necessarily have an answer, but some comments may prove helpful.
The "pass a copy" idea shouldn't matter, since your output successfully prints the string twice before the failure, then succeeds again afterward.
auto-flush shouldn't matter either, as you've already mentioned
Niko's suggestion has some merit, for diagnostic purposes. Mixed with Mark's suggestion, it makes me wonder if there aren't some invisible control characters getting involved somewhere. What if you printed the characters byte values as a diagnostic step?
You know that the value is "Test" (at least in the output you gave us). What happens if you pass "Test" directly to the failing printLn statement?
In situations like this, you want to gain as much information as possible. Insert breakpoints and analyze characters. Send the bytes to files and open them in hex editors. Do whatever you can to trace things as accurately and as precisely as possible.
Come up with weird test scenarios and try them, even if they shouldn't possibly help. You never know what good idea you might have while analyzing the results of the hopeless idea.
I'd guess that there is a bogus byte in there prefacing the T. According to JavaDocs, an InputStreamReader will read one or more bytes, and decode them into characters.
You could have an escape sequence or spurious byte in there, masquerading as a multibyte character.
Quick check - see if "current" is ever > 128 or < 33.
What if you used a CharArrayReader to get individual bytes, without any charset translation?
The theory is that during the first attempt to output the String using println, it's sending an escape character of some sort, eating the rest of the string. During later prints, either Java or the network pipe are handling or removing it, since it previously got that escape sequence, perhaps changing the handling in some way.
As an unrelated nit, sb.toString() returns a new String, so it's unnecessary to call "new String(sb.toString())"
Same issue here, I'm going through this post again and again these days, hoping I can find some solution. Then I decide I should give up psexec and find some alternative. So this is the thing: PAExec. Works perfect for getting command output.
How are you executing PsExec? My suspicion is that this is some code within PsExec which is actually doing echo suppression, possibly for the purposes of protecting a password. One way to test this hypothesis would be to change this code:
System.out.println("Outputting it cleanly to standard out: ");
System.out.println(input);
System.out.println("Outputting it cleanly to standard out again: ");
System.out.println(input);
to this:
System.out.println("Outputting it cleanly to standard out: ");
System.out.print(' ');
System.out.println(input);
System.out.println("Outputting it cleanly to standard out again: ");
System.out.println(input);
...thereby causing the output to be (if I'm right):
Outputting it cleanly to standard out:
Test
Outputting it cleanly to standard out again:
Test
Finished example outputs of input: Test
In particular, it's noticeable that the apparently-suppressed line is the first line which consists solely of Test - which is exactly the text you've just sent to the remote system. This sounds like PsExec attempting to suppress a remote system which is echoing its input in addition to producing its own output.
Is the password of the user on the remote machine perhaps Test? Are you using PsExec's -p parameter? Are you specifying -i?
I am dealing with this same issue and I am wondering if it has to do with how the cmd window and pipes in windows work while you don't have a true windowed session. The suppressed output happens when any new process is spawned. You would think that if you spawn a process that the stdout/stderr/stdin would be inherited from the process that spawned it; after all that is what happens if you spawn the process from a normal cmd window and the output from the new process is piped back to your own console. However if somewhere in the inheritance of the pipes something were to go wrong, like say not passing a WINDOW.GUI object because there is no physical window, windows doesn't let the stdin/stdout/stdin to be inherited. Can any one do some investigation or open a windows support ticket for this?
Seems no easy solution. My work-around in a recent project is using paexec.exe product. It captures output/error easily in JAVA(java-8), but hangs up upon completion of the remote command execution. When running this inside a server on the hosted machine, I have to spurn a new child JVM process to run paexec.exe and force kill it via its PID upon completion in order to release all the resources.
If anyone has better solution, please post it.