IdkSk by Nicofisi

The Nashorn/JS Eval Addon

Events

0

Expressions

4

Effects

1

Conditions

0

Types

0

Sections

0

Structures

0

Total

5

IdkSk - The Nashorn/JS Eval Addon 2319 days, 4 hours and 10 minutes ago

Hey you! IdkSk is currently the best unnamed addon

Does it mean "I don't know Skript", you may think? No! I means that I had no idea for a name.. well, actually - the "I don't know Skript" version would be true for me, so translate it how you prefer :emoji_cactus: After all, IdkSk isn't that counter-intuitive at all, is it? Maybe let's continue to the actual features

IdkSk is an addon using which you can execute code. What type of code? - one may ask. Well, many types of code.

Inb4, I propose to take a look at the code below:

command /hi:
trigger:
set {_x} to new "js" script engine
pass sender named "sender" to script engine {_x}
add "Packages.java.lang.System.out.println(2 + 2)" to {_code::*}
add "sender.sendMessage(""hello!"")" to {_code::*}
add "throw new Packages.java.lang.RuntimeException()" to {_code::*}
set {_res} to eval {_code::*} with script engine {_x}
if {_res} is a script exception:
message "An error has occured: %title line of {_res}%"
message "For the full stacktrace check the console"
send "Stacktrace of an error caused by code executed by %sender%:" to console
send "%stacktrace of {_res}%" to console
else:
message "The result is %{_res}%"

And compare it to the result of running it:
>hi
[21:46:20 INFO]: 4
[21:46:20 INFO]: hello!
[21:46:20 INFO]: An error has occured: jdk.nashorn.internal.runtime.ECMAException: java.lang.RuntimeException
[21:46:20 INFO]: For the full stacktrace check the console
[21:46:20 INFO]: Stacktrace of an error caused by code executed by CONSOLE:
[21:46:20 INFO]: <eval>:3:0 java.lang.RuntimeException
at jdk.nashorn.internal.runtime.ECMAException.create(ECMAException.java:113)
at jdk.nashorn.internal.scripts.Script$23$\^eval\_.:program(<eval>:3)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
<many more lines here>

Let's try to understand it line by line, starting from line number three:
set {_x} to new "js" script engine
#syntax is "new %string% script[ing] engine", "new script[ing] engine (of|with|using) lang[uage] %string%"

In this line, we use the NewScriptEngine expression for the first time. It returns a new script engine, something that we will use for running code later. In this line we need to choose the language. IdkSk currently supports only Nashorn (that is, JavaScript), but if you'd like to see support for languages like Scala and Kotlin, please let me know. I'll explain later what Nashorn exactly is, please read on now.
Nashorn has a few aliases which mean the same, you can use any of these names: nashorn, Nashorn, js, JS, JavaScript, javascript, ECMAScript, ecmascript with this expression
pass sender named "sender" to script engine {_x}
#syntax is "(pass|add) [(arg[ument]|param[eter]|var[iable]|obj[ect])] %objects% (named|with name) %string% to [script[ ]engine] %scriptengine%"

Here we use the PassToScriptEngine effect for the first time. If you'd like to use any variable from the outside world in your code, pass it here. It will be kept in the script engine {_x} even after you execute the code, so you can execute it multiple times (or run very different code) and and your variables will be waiting for you safely
add "Packages.java.lang.System.out.println(2 + 2)" to {_code::*}
add "sender.sendMessage(""hello!"")" to {_code::*}
add "throw new Packages.java.lang.RuntimeException()" to {_code::*}

Here you define the code that you want to run. Of course you can choose not to save it here this way and in one of the next lines simply use "code" or "line1" and "line2" or "line1%nl%line2" or "line1;line2" etc.
Note how I used the Packages. word to let Java know that java is a package, not some variable. And by the way, here we also use the sender object that we passed before.
set {_res} to eval {_code::*} with script engine {_x}
#syntax is "(eval|run|execute|exec|evaluate)
%strings% (using|with) [script[ ]engine] %scriptengine% [and (get|return) [the] result]"

Here we actually execute the code and get the result. If can be the expected result, or a script exception (that's how it's called internally in the scripting API so i named it this way too)
if {_res} is a script exception:

Here we check if {_res(ult)} is an script exception. If it's not, it's expected result (unless the error is what you expected..)
message "An error has occured: %title line of {_res}%"
message "For the full stacktrace check the console"
send "Stacktrace of an error caused by code executed by %sender%:" to console
send "%stacktrace of {_res}%" to console

Here you can see an example use of two property expressions. Look at the console output on the top of the post to examine what they return
else:
message "The result is %{_res}%"

As I wrote before, if it's not an error - it's the actual result. Great job - your code worked! Probably at least. And, it's great unless you're DDOSing someone. If you are, it's only half great.

Cool! We did it. I did my best to explain everything and you hopefully read and understood that.

Now - about Nashorn.
Nashorn is simply a js engine written specifically for Java. And JavaScript is almost like Java. A great deal of stuff works exactly the way you'd expect it to work in java.
Just remember that when you're using something that normally would have to be imported in java, you need to use either Packages.pa.cka.ge.he.re.ClassName.method() or Java.type("pa.cka.ge.he.re.ClassName").method()
Here is an example of some "more advanced code" that you could execute (it's very simple though probably 10 times more complicated than what you'll be usually running lol):
var IntArray = Java.type("int[]");

var array = new IntArray(5);
array[0] = 5;
array[1] = 4;
array[2] = 3;
array[3] = 2;
array[4] = 1;

try {
array[5] = 23;
} catch (e) {
print(e.message); // Array index out of range: 5
}

array[0] = "17";
print(array[0]); // 17

array[0] = "wrong type";
print(array[0]); // 0

array[0] = "17.3";
print(array[0]); // 17

See? It's very similar to Java. Here are more examples:
var map = new java.util.HashMap();
map.put('foo', 'val1');
map.put('bar', 'val2');

for each (var e in map.keySet()) print(e); // foo, bar

for each (var e in map.values()) print(e); // val1, val2

// Lambda expressions and Streams
var list2 = new java.util.ArrayList();
list2.add("ddd2");
list2.add("aaa2");
list2.add("bbb1");
list2.add("aaa1");
list2.add("bbb3");
list2.add("ccc");
list2.add("bbb2");
list2.add("ddd1");

list2
.stream()
.filter(function(el) {
return el.startsWith("aaa");
})
.sorted()
.forEach(function(el) {
print(el);
});
// aaa1, aaa2

I copied the above from http://winterbe.com/posts/2014/04/05/java8-nashorn-tutorial/ - I highly recommend you to go and read that.

I made this addon mainly because I needed it for my Skript Discord bot to be fair, so I can update this thread with a Discord example later if you want - simply ask and give me some time :emoji_heart:

If you have any issues, questions or suggestions, feel free to contact me here, but even better - on Discord (I'm Nicofisi#4467), and eventually on GitHub. Have fun!

View Update

© Copyright 2014-2024 skUnity

All rights reserved.