clean slate

This commit is contained in:
PiggyPiglet 2021-05-21 13:32:08 +08:00
parent d5a7ed81a0
commit 75b652b86a
14 changed files with 0 additions and 1584 deletions

View File

@ -1,112 +0,0 @@
package com.extendedclip.papi.expansion.javascript;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.MemorySection;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
public class ExpansionUtils {
public static final String DEFAULT_ENGINE = "nashorn";
public static final String PREFIX = "[PAPI] [Javascript-Expansion] ";
private static final Logger logger = Bukkit.getLogger();
public static @NotNull String colorize(String s) {
return ChatColor.translateAlternateColorCodes('&', s);
}
public static void sendMsg(CommandSender sender, String... msg) {
sender.sendMessage(colorize(Arrays.stream(msg).filter(Objects::nonNull).collect(Collectors.joining("\n"))));
}
public static String plural(final int amount) {
return amount > 1 ? "s" : "";
}
public static void warnLog(String log, Throwable throwable) {
warnLog(log, throwable, true);
}
public static void infoLog(final String log) {
infoLog(log, true);
}
public static void infoLog(String log, boolean canPrefix) {
String prefix = "";
if (canPrefix) prefix = PREFIX;
logger.info(colorize(prefix + log));
}
public static void warnLog(String log, Throwable throwable, boolean canPrefix) {
String prefix = "";
if (canPrefix) prefix = PREFIX;
if (throwable == null) {
logger.log(Level.WARNING, prefix + log);
} else logger.log(Level.WARNING, prefix + log, throwable);
}
public static void errorLog(String log, Throwable throwable) {
errorLog(log, throwable, true);
}
public static void errorLog(String log, Throwable throwable, boolean canPrefix) {
String prefix = "";
if (canPrefix) prefix = PREFIX;
if (throwable == null) {
logger.log(Level.SEVERE, prefix + log);
} else {
logger.log(Level.SEVERE, prefix + log, throwable);
}
}
// Only support for Nashorn engine!
protected static Object jsonToJava(Object jsObj) {
if (jsObj instanceof ScriptObjectMirror) {
ScriptObjectMirror jsObjectMirror = (ScriptObjectMirror) jsObj;
if (jsObjectMirror.isArray()) {
List<Object> list = new ArrayList<>();
for (Map.Entry<String, Object> entry : jsObjectMirror.entrySet()) {
list.add(jsonToJava(entry.getValue()));
}
return list;
} else {
Map<String, Object> map = new HashMap<>();
for (Map.Entry<String, Object> entry : jsObjectMirror.entrySet()) {
map.put(entry.getKey(), jsonToJava(entry.getValue()));
}
return map;
}
} else {
return jsObj;
}
}
protected static Object ymlToJavaObj(Object obj) {
if (obj instanceof MemorySection) {
MemorySection ymlMem = (MemorySection) obj;
if (ymlMem.isList(ymlMem.getCurrentPath())) {
ArrayList<Object> list = new ArrayList<>();
for (String entry : ymlMem.getKeys(true)) {
list.add(ymlToJavaObj(ymlMem.get(entry)));
}
return list;
} else {
Map<String, Object> map = new HashMap<>();
for (String entry : ymlMem.getKeys(true)) {
map.put(entry, ymlToJavaObj(ymlMem.get(entry)));
}
return map;
}
} else {
return obj;
}
}
}

View File

@ -1,297 +0,0 @@
/*
*
* Javascript-Expansion
* Copyright (C) 2020 Ryan McCarthy
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
package com.extendedclip.papi.expansion.javascript;
import com.extendedclip.papi.expansion.javascript.cloud.GithubScriptManager;
import me.clip.placeholderapi.expansion.Cacheable;
import me.clip.placeholderapi.expansion.Configurable;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandMap;
import org.jetbrains.annotations.NotNull;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
public class JavascriptExpansion extends PlaceholderExpansion implements Cacheable, Configurable {
private ScriptEngine globalEngine = null;
private JavascriptPlaceholdersConfig config;
private final Set<JavascriptPlaceholder> scripts;
private final String VERSION;
private static JavascriptExpansion instance;
private boolean debug;
private GithubScriptManager githubManager;
private JavascriptExpansionCommands commands;
private CommandMap commandMap;
private String argument_split;
public JavascriptExpansion() {
instance = this;
this.VERSION = getClass().getPackage().getImplementationVersion();
this.scripts = new HashSet<>();
try {
final Field field = Bukkit.getServer().getClass().getDeclaredField("commandMap");
field.setAccessible(true);
commandMap = (CommandMap) field.get(Bukkit.getServer());
} catch (NoSuchFieldException | IllegalAccessException e) {
ExpansionUtils.errorLog("An error occurred while accessing CommandMap.", e, true);
}
}
@Override
public String getAuthor() {
return "clip";
}
@Override
public String getIdentifier() {
return "javascript";
}
@Override
public String getVersion() {
return VERSION;
}
@Override
public boolean register() {
String defaultEngine = ExpansionUtils.DEFAULT_ENGINE;
if (globalEngine == null) {
try {
globalEngine = new ScriptEngineManager(null).getEngineByName(getString("engine", defaultEngine));
} catch (NullPointerException ex) {
ExpansionUtils.warnLog("Javascript engine type was invalid! Defaulting to '" + defaultEngine + "'", null);
globalEngine = new ScriptEngineManager(null).getEngineByName(defaultEngine);
}
}
argument_split = getString("argument_split", ",");
if (argument_split.equals("_")) {
argument_split = ",";
ExpansionUtils.warnLog("Underscore character will not be allowed for splitting. Defaulting to ',' for this", null);
}
debug = (boolean) get("debug", false);
config = new JavascriptPlaceholdersConfig(this);
int amountLoaded = config.loadPlaceholders();
ExpansionUtils.infoLog(amountLoaded + " script" + ExpansionUtils.plural(amountLoaded) + " loaded!");
if (debug) {
ExpansionUtils.infoLog("Java version: " + System.getProperty("java.version"));
final ScriptEngineManager manager = new ScriptEngineManager(null);
final List<ScriptEngineFactory> factories = manager.getEngineFactories();
ExpansionUtils.infoLog("Displaying all script engine factories.", false);
for (ScriptEngineFactory factory : factories) {
System.out.println(factory.getEngineName());
System.out.println(" Version: " + factory.getEngineVersion());
System.out.println(" Lang name: " + factory.getLanguageName());
System.out.println(" Lang version: " + factory.getLanguageVersion());
System.out.println(" Extensions: ." + String.join(", .", factory.getExtensions()));
System.out.println(" Mime types: " + String.join(", ", factory.getMimeTypes()));
System.out.println(" Names: " + String.join(", ", factory.getNames()));
}
}
if ((boolean) get("github_script_downloads", false)) {
githubManager = new GithubScriptManager(this);
githubManager.fetch();
}
registerCommand();
return super.register();
}
@Override
public void clear() {
unregisterCommand();
scripts.forEach(script -> {
script.saveData();
script.cleanup();
});
if (githubManager != null) {
githubManager.clear();
githubManager = null;
}
scripts.clear();
globalEngine = null;
instance = null;
}
@Override
public String onRequest(OfflinePlayer player, @NotNull String identifier) {
if (player == null || scripts.size() == 0) {
return "";
}
for (JavascriptPlaceholder script : scripts) {
if (identifier.startsWith(script.getIdentifier() + "_")) {
identifier = identifier.replaceFirst(script.getIdentifier() + "_", "");
return !identifier.contains(argument_split) ? script.evaluate(player, identifier) : script.evaluate(player, identifier.split(argument_split));
}
if (identifier.equalsIgnoreCase(script.getIdentifier())) {
return script.evaluate(player);
}
}
return null;
}
public boolean addJSPlaceholder(JavascriptPlaceholder placeholder) {
if (placeholder == null) {
return false;
}
if (scripts.isEmpty()) {
scripts.add(placeholder);
return true;
}
if (getJSPlaceholder(placeholder.getIdentifier()) != null) {
return false;
}
scripts.add(placeholder);
return true;
}
// public Set<JavascriptPlaceholder> getJSPlaceholders() {
// return scripts;
// }
public List<String> getLoadedIdentifiers() {
return scripts.stream()
.map(JavascriptPlaceholder::getIdentifier)
.collect(Collectors.toList());
}
public JavascriptPlaceholder getJSPlaceholder(String identifier) {
return scripts.stream()
.filter(s -> s.getIdentifier().equalsIgnoreCase(identifier))
.findFirst()
.orElse(null);
}
public int getAmountLoaded() {
return scripts.size();
}
public ScriptEngine getGlobalEngine() {
return globalEngine;
}
public JavascriptPlaceholdersConfig getConfig() {
return config;
}
@Override
public Map<String, Object> getDefaults() {
final Map<String, Object> defaults = new HashMap<>();
defaults.put("engine", "javascript");
defaults.put("debug", false);
defaults.put("argument_split", ",");
defaults.put("github_script_downloads", false);
return defaults;
}
public int reloadScripts() {
scripts.forEach(script -> {
script.saveData();
script.cleanup();
});
scripts.clear();
config.reload();
return config.loadPlaceholders();
}
public static JavascriptExpansion getInstance() {
return instance;
}
public GithubScriptManager getGithubScriptManager() {
return githubManager;
}
public void setGithubScriptManager(GithubScriptManager manager) {
this.githubManager = manager;
}
private void unregisterCommand() {
if (commandMap != null && commands != null) {
try {
Class<? extends CommandMap> cmdMapClass = commandMap.getClass();
final Field f;
//Check if the server's in 1.13+
if (cmdMapClass.getSimpleName().equals("CraftCommandMap")) {
f = cmdMapClass.getSuperclass().getDeclaredField("knownCommands");
} else {
f = cmdMapClass.getDeclaredField("knownCommands");
}
f.setAccessible(true);
Map<String, Command> knownCmds = (Map<String, Command>) f.get(commandMap);
knownCmds.remove(commands.getName());
for (String alias : commands.getAliases()) {
if (knownCmds.containsKey(alias) && knownCmds.get(alias).toString().contains(commands.getName())) {
knownCmds.remove(alias);
}
}
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
commands.unregister(commandMap);
}
}
private void registerCommand() {
if (commandMap == null) {
return;
}
commands = new JavascriptExpansionCommands(this);
commandMap.register("papi" + commands.getName(), commands);
commands.isRegistered();
}
}

View File

@ -1,168 +0,0 @@
/*
*
* Javascript-Expansion
* Copyright (C) 2020 Ryan McCarthy
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
package com.extendedclip.papi.expansion.javascript;
import com.extendedclip.papi.expansion.javascript.cloud.GithubScript;
import com.extendedclip.papi.expansion.javascript.command.*;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class JavascriptExpansionCommands extends Command {
private final JavascriptExpansion expansion;
private final String PERMISSION = "placeholderapi.js.admin";
private final String command;
private List<ICommand> subCommands;
public JavascriptExpansionCommands(JavascriptExpansion expansion) {
super("jsexpansion");
command = getName();
this.expansion = expansion;
this.setDescription("Javascript expansion commands");
this.setUsage("/" + command + " <args>");
this.setAliases(new ArrayList<>(Arrays.asList("javascriptexpansion", "jsexp")));
this.setPermission(PERMISSION);
initCommands();
}
public void initCommands() {
if (subCommands != null) {
subCommands.clear();
}
subCommands = new ArrayList<>(Arrays.asList(
new GitCommand(expansion),
new ListCommand(expansion),
new ParseCommand(expansion),
new ReloadCommand(expansion),
new DebugCommand(expansion))
);
}
@Override
public boolean execute(CommandSender sender, @NotNull String label, String[] args) {
if (!sender.hasPermission(PERMISSION)) {
ExpansionUtils.sendMsg(sender, "&cYou don't have permission to do that!");
return true;
}
if (args.length == 0) {
sendHelp(sender);
return true;
}
ICommand command = null;
for (ICommand icmd : subCommands) {
if (icmd.getAlias().equalsIgnoreCase(args[0])) {
command = icmd;
command.command = getName();
break;
}
}
if (command == null) {
ExpansionUtils.sendMsg(sender, "&cInvalid expansion sub-command! Type&f /" + getName() + " &cfor help");
return true;
}
command.execute(sender, sliceFirstArr(args));
return true;
}
//TODO: This thing here has to be organized thoroughly later...
@Override
public List<String> tabComplete(CommandSender sender, @NotNull String alias, String[] args) throws IllegalArgumentException {
if (!sender.hasPermission(PERMISSION)) {
return Collections.emptyList();
}
final List<String> commands = new ArrayList<>(Arrays.asList("list", "parse", "reload"));
final List<String> completion = new ArrayList<>();
if (expansion.getGithubScriptManager() != null) {
commands.add(0, "git");
}
if (args.length == 1) {
return StringUtil.copyPartialMatches(args[0], commands, completion);
}
if (args[0].equalsIgnoreCase("git")) {
if (expansion.getGithubScriptManager() == null) {
return Collections.emptyList();
}
if (args.length == 2) {
return StringUtil.copyPartialMatches(args[1], Arrays.asList("download", "enable", "info", "list", "refresh"), completion);
}
if (args.length == 3 && args[1].equalsIgnoreCase("download")) {
if (expansion.getGithubScriptManager().getAvailableScripts() == null) {
return Collections.emptyList();
}
return StringUtil.copyPartialMatches(args[2], expansion.getGithubScriptManager().getAvailableScripts().stream().map(GithubScript::getName).collect(Collectors.toList()), completion);
}
}
return Collections.emptyList();
}
private void sendHelp(CommandSender sender) {
ExpansionUtils.sendMsg(sender,
"&eJavascript expansion &7v: &f" + expansion.getVersion(),
"&eCreated by: &f" + expansion.getAuthor(),
"&eWiki: &fhttps://github.com/PlaceholderAPI/Javascript-Expansion/wiki",
"&r",
"&e/" + command + " reload &7- &fReload your javascripts without reloading PlaceholderAPI.",
"&e/" + command + " list &7- &fList loaded script identifiers.",
"&e/" + command + " parse [me/player] [code] &7- &fTest JavaScript code in chat.",
"&e/" + command + " debug [savedata/loaddata] [identifier] &7- &fTest JavaScript code in chat."
);
if (expansion.getGithubScriptManager() != null) {
ExpansionUtils.sendMsg(sender,
"&e/" + command + " git refresh &7- &fRefresh available Github scripts",
"&e/" + command + " git download [name] &7- &fDownload a script from the js expansion github.",
"&e/" + command + " git list &7- &fList available scripts in the js expansion github.",
"&e/" + command + " git info [name] &7- &fGet the description and url of a specific script."
);
} else {
ExpansionUtils.sendMsg(sender,
"&e/" + command + " git &7- &fGithub command &7(please enable in config)"
);
}
}
public String[] sliceFirstArr(String[] args) {
return Arrays.stream(args).skip(1).toArray(String[]::new);
}
}

View File

@ -1,212 +0,0 @@
/*
*
* Javascript-Expansion
* Copyright (C) 2020 Ryan McCarthy
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
package com.extendedclip.papi.expansion.javascript;
import me.clip.placeholderapi.PlaceholderAPI;
import me.clip.placeholderapi.PlaceholderAPIPlugin;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import java.io.File;
import java.io.IOException;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class JavascriptPlaceholder {
private final ScriptEngine engine;
private final String identifier;
private final String script;
private ScriptData scriptData;
private final File dataFile;
private YamlConfiguration yaml;
private final Pattern pattern;
@SuppressWarnings("ResultOfMethodCallIgnored")
public JavascriptPlaceholder(ScriptEngine engine, String identifier, String script) {
Validate.notNull(engine, "ScriptEngine can not be null");
Validate.notNull(identifier, "Identifier can not be null");
Validate.notNull(script, "Script can not be null");
String dir = PlaceholderAPIPlugin.getInstance().getDataFolder() + "/javascripts/javascript_data";
this.engine = engine;
this.identifier = identifier;
this.script = script;
final File directory = new File(dir);
if (!directory.exists()) {
directory.mkdirs();
}
pattern = Pattern.compile("//.*|/\\*[\\S\\s]*?\\*/|%([^%]+)%");
scriptData = new ScriptData();
dataFile = new File(directory, identifier + "_data.yml");
engine.put("Data", scriptData);
engine.put("DataVar", scriptData.getData());
engine.put("BukkitServer", Bukkit.getServer());
engine.put("Expansion", JavascriptExpansion.getInstance());
engine.put("Placeholder", this);
engine.put("PlaceholderAPI", PlaceholderAPI.class);
}
public String getIdentifier() {
return identifier;
}
public String evaluate(OfflinePlayer player, String... args) {
// A checker to deny all placeholders inside comment codes
Matcher matcher = pattern.matcher(script);
StringBuffer buffer = new StringBuffer();
while (matcher.find()) {
String matched = matcher.group(0);
if (!matched.startsWith("%") || matched.startsWith("/*") || matched.startsWith("//")) continue;
matcher.appendReplacement(buffer, PlaceholderAPI.setPlaceholders(player, matched));
}
matcher.appendTail(buffer);
String exp = buffer.toString();
try {
String[] arguments = null;
if (args != null && args.length > 0) {
arguments = new String[args.length];
for (int i = 0; i < args.length; i++) {
if (args[i] == null || args[i].isEmpty()) {
continue;
}
arguments[i] = PlaceholderAPI.setBracketPlaceholders(player, args[i]);
}
}
if (arguments == null) {
arguments = new String[]{};
}
engine.put("args", arguments);
if (player != null && player.isOnline()) {
engine.put("BukkitPlayer", player.getPlayer());
engine.put("Player", player.getPlayer());
}
engine.put("OfflinePlayer", player);
Object result = engine.eval(exp);
return result != null ? PlaceholderAPI.setBracketPlaceholders(player, result.toString()) : "";
} catch (ScriptException ex) {
ExpansionUtils.errorLog("An error occurred while executing the script '" + identifier + "':\n\t" + ex.getMessage(), null);
} catch (ArrayIndexOutOfBoundsException ex) {
ExpansionUtils.errorLog("Argument out of bound while executing script '" + identifier + "':\n\t" + ex.getMessage(), null);
}
return "Script error (check console)";
}
public String getScript() {
return script;
}
public ScriptData getData() {
if (scriptData == null) {
scriptData = new ScriptData();
}
return scriptData;
}
public void setData(ScriptData data) {
this.scriptData = data;
}
@SuppressWarnings("ResultOfMethodCallIgnored")
public boolean loadData() {
yaml = new YamlConfiguration();
dataFile.getParentFile().mkdirs();
if (!dataFile.exists()) {
try {
dataFile.createNewFile();
} catch (IOException e) {
ExpansionUtils.errorLog("An error occurred while creating data file for " + getIdentifier(), e);
return false;
}
}
try {
yaml.load(dataFile);
} catch (IOException | InvalidConfigurationException e) {
ExpansionUtils.errorLog("An error occurred while loading for " + getIdentifier(), e);
return false;
}
final Set<String> keys = yaml.getKeys(true);
if (keys.size() == 0) {
return false;
}
if (scriptData == null)
scriptData = new ScriptData();
else scriptData.clear();
keys.forEach(key -> scriptData.set(key, ExpansionUtils.ymlToJavaObj(yaml.get(key))));
if (!scriptData.isEmpty()) {
setData(scriptData);
return true;
}
return false;
}
public void saveData() {
if (scriptData == null || scriptData.isEmpty() || yaml == null) {
return;
}
// Function for merging JSON.
// TODO: This will be removed along with Nashorn in a later future
scriptData.getData().forEach((key, value) -> yaml.set(key, ExpansionUtils.jsonToJava(value)));
try {
yaml.save(dataFile);
} catch (IOException e) {
ExpansionUtils.errorLog(ExpansionUtils.PREFIX + "An error occurred while saving data for " + getIdentifier(), e);
}
}
public void cleanup() {
if (this.scriptData != null) {
this.scriptData.clear();
this.scriptData = null;
}
this.yaml = null;
}
}

View File

@ -1,213 +0,0 @@
/*
*
* Javascript-Expansion
* Copyright (C) 2020 Ryan McCarthy
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
package com.extendedclip.papi.expansion.javascript;
import me.clip.placeholderapi.PlaceholderAPIPlugin;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
public class JavascriptPlaceholdersConfig {
private final JavascriptExpansion ex;
private final PlaceholderAPIPlugin plugin;
private FileConfiguration config;
private File file;
public JavascriptPlaceholdersConfig(JavascriptExpansion ex) {
this.ex = ex;
plugin = ex.getPlaceholderAPI();
reload();
}
public void reload() {
if (file == null) {
file = new File(plugin.getDataFolder(), "javascript_placeholders.yml");
}
config = YamlConfiguration.loadConfiguration(file);
config.options().header("Javascript Expansion: " + ex.getVersion()
+ "\nThis is the main configuration file for the Javascript Expansion."
+ "\n"
+ "\nYou will define your javascript placeholders in this file."
+ "\n"
+ "\nJavascript files must be located in the:"
+ "\n /plugins/placeholderapi/javascripts/ folder"
+ "\n"
+ "\nA detailed guide on how to create your own javascript placeholders"
+ "\ncan be found here:"
+ "\nhttps://github.com/PlaceholderAPI-Expansions/Javascript-Expansion/wiki"
+ "\n"
+ "\nYour javascript placeholders will be identified by: %javascript_<identifier>%"
+ "\n"
+ "\nConfiguration format:"
+ "\n"
+ "\n<identifier>:"
+ "\n file: <name of file>.<file extension>"
+ "\n engine: (name of script engine)"
+ "\n"
+ "\n"
+ "\nExample:"
+ "\n"
+ "\n'my_placeholder':"
+ "\n file: 'my_placeholder.js'"
+ "\n engine: 'nashorn'");
if (config.getKeys(false).isEmpty()) {
config.set("example.file", "example.js");
config.set("example.engine", ExpansionUtils.DEFAULT_ENGINE);
}
save();
}
public FileConfiguration load() {
if (config == null) reload();
return config;
}
public void save() {
if (config == null || file == null) {
return;
}
try {
load().save(file);
} catch (IOException ex) {
ExpansionUtils.warnLog("Could not save to " + file, ex);
}
}
@SuppressWarnings("ResultOfMethodCallIgnored")
public int loadPlaceholders() {
if (config == null || config.getKeys(false).isEmpty()) {
return 0;
}
final File directory = new File(plugin.getDataFolder(), "javascripts");
try {
if (!directory.exists()) {
directory.mkdirs();
ExpansionUtils.infoLog("Creating directory: " + directory.getPath());
}
} catch (SecurityException e) {
ExpansionUtils.errorLog("Could not create directory: " + directory.getPath(), e);
}
for (String identifier : config.getKeys(false)) {
final String fileName = config.getString(identifier + ".file");
if (!config.contains(identifier + ".file") || fileName == null) {
ExpansionUtils.warnLog("Javascript placeholder: " + identifier + " does not have a file specified", null);
continue;
}
final File scriptFile = new File(plugin.getDataFolder() + "/javascripts", fileName);
if (!scriptFile.exists()) {
ExpansionUtils.infoLog(scriptFile.getName() + " does not exist. Creating one for you...");
try {
scriptFile.createNewFile();
ExpansionUtils.infoLog(scriptFile.getName() + " created! Add your javascript to this file and use '/jsexpansion reload' to load it!");
} catch (IOException e) {
ExpansionUtils.errorLog("An error occurred while creating " + scriptFile.getName(), e);
}
continue;
}
final String script = getContents(scriptFile);
if (script == null || script.isEmpty()) {
ExpansionUtils.warnLog("File: " + scriptFile.getName() + " for Javascript placeholder: " + identifier + " is empty", null);
continue;
}
boolean debug = (boolean) ex.get("debug", false);
int errScriptEngine = 0;
ScriptEngine engine;
if (!config.contains(identifier + ".engine")) {
engine = ex.getGlobalEngine();
if (debug) {
ExpansionUtils.warnLog("ScriptEngine type for javascript placeholder: " + identifier + " is empty! Defaulting to global", null);
} else {
errScriptEngine++;
}
} else {
try {
engine = new ScriptEngineManager(null).getEngineByName(config.getString(identifier + ".engine", "nashorn"));
} catch (NullPointerException e) {
if (debug) {
ExpansionUtils.warnLog("ScriptEngine type for javascript placeholder: " + identifier + " is invalid! Defaulting to global", null);
} else {
errScriptEngine++;
}
engine = ex.getGlobalEngine();
}
}
if (errScriptEngine > 0) {
ExpansionUtils.warnLog("ScriptEngine type for " + errScriptEngine + " javascript placeholder" + ExpansionUtils.plural(errScriptEngine) +
" failed! Defaulting all to global. More information by enabling debug mode", null);
}
if (engine == null) {
ExpansionUtils.warnLog("Failed to set ScriptEngine for javascript placeholder: " + identifier, null);
continue;
}
final JavascriptPlaceholder placeholder = new JavascriptPlaceholder(engine, identifier, script);
final boolean added = ex.addJSPlaceholder(placeholder);
if (added) {
if (placeholder.loadData()) {
ExpansionUtils.infoLog("Data for placeholder &b" + identifier + "&r has been loaded");
}
ExpansionUtils.infoLog("Placeholder &b%javascript_" + identifier + "%&r has been loaded");
} else {
ExpansionUtils.warnLog("Javascript placeholder %javascript_" + identifier + "% is duplicated!", null);
}
}
return ex.getAmountLoaded();
}
private String getContents(File file) {
final StringBuilder sb = new StringBuilder();
try {
List<String> lines = Files.readAllLines(file.toPath());
lines.forEach((line) -> sb.append(line).append("\n"));
} catch (IOException e) {
return null;
}
return sb.toString();
}
}

View File

@ -1,69 +0,0 @@
/*
*
* Javascript-Expansion
* Copyright (C) 2020 Ryan McCarthy
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
package com.extendedclip.papi.expansion.javascript;
import java.util.HashMap;
import java.util.Map;
public class ScriptData {
private Map<String, Object> map;
public ScriptData(Map<String, Object> data) {
this.map = data;
}
public ScriptData() {
this.map = new HashMap<>();
}
public Map<String, Object> getData() {
return map;
}
public void clear() {
map.clear();
}
public boolean exists(String key) {
return map.get(key) != null;
}
public Object get(String key) {
return map.get(key);
}
public void remove(String key) {
map.put(key, null);
}
public void set(String key, Object value) {
map.put(key, ExpansionUtils.jsonToJava(value));
}
public void setIfNull(String key, Object value) {
map.putIfAbsent(key, ExpansionUtils.jsonToJava(value));
}
public boolean isEmpty() {
return map.isEmpty();
}
}

View File

@ -1,58 +0,0 @@
/*
*
* Javascript-Expansion
* Copyright (C) 2020 Ryan McCarthy
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
package com.extendedclip.papi.expansion.javascript.cloud;
public class GithubScript {
private final String name;
private final String version;
private final String author;
private final String description;
private final String url;
public GithubScript(String name, String version, String author, String description, String url) {
this.name = name;
this.version = version;
this.author = author;
this.description = description;
this.url = url;
}
public String getName() {
return name;
}
public String getVersion() {
return version;
}
public String getAuthor() {
return author;
}
public String getDescription() {
return description;
}
public String getUrl() {
return url;
}
}

View File

@ -1,130 +0,0 @@
/*
*
* Javascript-Expansion
* Copyright (C) 2020 Ryan McCarthy
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
package com.extendedclip.papi.expansion.javascript.cloud;
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
import com.extendedclip.papi.expansion.javascript.JavascriptExpansion;
import com.extendedclip.papi.expansion.javascript.JavascriptPlaceholdersConfig;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import jdk.nashorn.api.scripting.ScriptUtils;
import org.bukkit.Bukkit;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.logging.Level;
import java.util.stream.Collectors;
public class GithubScriptManager {
private final JavascriptExpansion expansion;
private final String JAVASCRIPTS_FOLDER;
private List<GithubScript> availableScripts;
private final String MASTER_LIST_URL = "https://raw.githubusercontent.com/PlaceholderAPI/Javascript-Expansion/master/scripts/master_list.json";
private final Gson GSON = new Gson();
public GithubScriptManager(JavascriptExpansion expansion) {
this.expansion = expansion;
JAVASCRIPTS_FOLDER = expansion.getPlaceholderAPI().getDataFolder()
+ File.separator
+ "javascripts"
+ File.separator;
}
public void clear() {
availableScripts = null;
}
public void fetch() {
Bukkit.getScheduler().runTaskAsynchronously(expansion.getPlaceholderAPI(), () -> {
final String json = getContents(MASTER_LIST_URL);
if (json.isEmpty()) {
return;
}
availableScripts = GSON.fromJson(json, new TypeToken<ArrayList<GithubScript>>() {}.getType());
});
}
public void downloadScript(GithubScript script) {
Bukkit.getScheduler().runTaskAsynchronously(expansion.getPlaceholderAPI(), () -> {
final List<String> contents = read(script.getUrl());
if (contents.isEmpty()) {
return;
}
try (final PrintStream out = new PrintStream(new FileOutputStream(new File(JAVASCRIPTS_FOLDER, script.getName() + ".js")))) {
contents.forEach(out::println);
} catch (FileNotFoundException e) {
ExpansionUtils.errorLog("An error occurred while downloading " + script.getName(), e);
return;
}
Bukkit.getScheduler().runTask(expansion.getPlaceholderAPI(), () -> {
JavascriptPlaceholdersConfig config = expansion.getConfig();
config.load().set(script.getName() + ".file", script.getName() + ".js");
config.load().set(script.getName() + ".engine", "javascript");
config.save();
});
});
}
private String getContents(String url) {
return String.join("", read(url));
}
private List<String> read(final String url) {
final List<String> lines = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(url).openStream()))) {
lines.addAll(reader.lines().filter(Objects::nonNull).collect(Collectors.toList()));
} catch (Exception ex) {
ex.printStackTrace();
}
return lines;
}
public List<GithubScript> getAvailableScripts() {
return availableScripts;
}
public GithubScript getScript(final String name) {
if (availableScripts == null) {
return null;
}
return availableScripts.stream()
.filter(s -> s.getName().equalsIgnoreCase(name))
.findFirst()
.orElse(null);
}
public String getJavascriptsFolder() {
return JAVASCRIPTS_FOLDER;
}
}

View File

@ -1,50 +0,0 @@
package com.extendedclip.papi.expansion.javascript.command;
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
import com.extendedclip.papi.expansion.javascript.JavascriptExpansion;
import com.extendedclip.papi.expansion.javascript.JavascriptPlaceholder;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.stream.Collectors;
public class DebugCommand extends ICommand {
private final JavascriptExpansion expansion;
public DebugCommand(JavascriptExpansion expansion) {
this.expansion = expansion;
}
@Override
public void execute(CommandSender sender, String[] args) {
if (args.length < 2) {
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! Type '&f/" + command + "&c' for more help.");
return;
}
JavascriptPlaceholder jsp = expansion.getJSPlaceholder(getIdentifier(args));
if (jsp == null) {
ExpansionUtils.sendMsg(sender, "&cInvalid javascript identifier! Please re-check your typo");
return;
}
if (args[0].equals("savedata")) {
jsp.saveData();
ExpansionUtils.sendMsg(sender, "&aJavascript data '" + args[1] + "' successfully saved");
} else if (args[0].equals("loaddata")) {
jsp.loadData();
ExpansionUtils.sendMsg(sender, "&aJavascript data '" + args[1] + "' successfully loaded");
}
}
public String getIdentifier(String[] args) {
return Arrays.stream(args).skip(1).collect(Collectors.joining(" "));
}
@Override
public @NotNull String getAlias() {
return "debug";
}
}

View File

@ -1,138 +0,0 @@
package com.extendedclip.papi.expansion.javascript.command;
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
import com.extendedclip.papi.expansion.javascript.JavascriptExpansion;
import com.extendedclip.papi.expansion.javascript.cloud.GithubScript;
import com.extendedclip.papi.expansion.javascript.cloud.GithubScriptManager;
import me.clip.placeholderapi.PlaceholderAPIPlugin;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class GitCommand extends ICommand {
private final JavascriptExpansion expansion;
public GitCommand(JavascriptExpansion expansion) {
this.expansion = expansion;
}
@Override
public void execute(CommandSender sender, String[] args) {
if (expansion.getGithubScriptManager() == null) {
ExpansionUtils.sendMsg(sender, "&cThis feature is disabled in the PlaceholderAPI config.");
return;
}
if (args.length < 1) {
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! Type '&f/" + command + "&c' for more help.");
return;
}
final GithubScriptManager manager = expansion.getGithubScriptManager();
switch (args[0].toLowerCase()) {
case "refresh": {
expansion.getGithubScriptManager().fetch();
ExpansionUtils.sendMsg(sender, "&aFetching available scripts... Check back in a sec!");
return;
}
case "list": {
final List<GithubScript> availableScripts = manager.getAvailableScripts();
final Set<String> scripts = availableScripts.stream().map(GithubScript::getName).collect(Collectors.toSet());
ExpansionUtils.sendMsg(sender, availableScripts.size() + " &escript" + ExpansionUtils.plural(availableScripts.size()) + " available on Github.", String.join(", ", scripts));
return;
}
case "info": {
if (args.length < 2) {
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! &f/" + command + " git info [name]");
return;
}
final GithubScript script = manager.getScript(args[1]);
if (script == null) {
ExpansionUtils.sendMsg(sender, "&cThe script &f" + args[1] + " &cdoes not exist!");
return;
}
ExpansionUtils.sendMsg(sender,
"&eName: &f" + script.getName(),
"&eVersion: &f" + script.getVersion(),
"&eDescription: &f" + script.getDescription(),
"&eAuthor: &f" + script.getAuthor(),
"&eSource URL: &f" + script.getUrl()
);
return;
}
case "download": {
if (args.length < 2) {
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! &f/" + command + " git download [name]");
return;
}
final GithubScript script = manager.getScript(args[1]);
if (script == null) {
ExpansionUtils.sendMsg(sender, "&cThe script &f" + args[1] + " &cdoes not exist!");
return;
}
if (new File(expansion.getGithubScriptManager().getJavascriptsFolder(), script.getName() + ".js").exists()) {
ExpansionUtils.sendMsg(sender, "&cCould not download " + script.getName() + " because a file with the same name already exist in the javascripts folder.");
return;
}
manager.downloadScript(script);
ExpansionUtils.sendMsg(sender, "&aDownload started. &eCheck the scripts folder in a moment...");
return;
}
case "enabled":
if (args.length < 2) {
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! &f/jsexpansion git enabled [true/false]");
return;
}
final boolean enabled = Boolean.parseBoolean(args[1]);
final PlaceholderAPIPlugin papi = expansion.getPlaceholderAPI();
papi.getConfig().set("expansions." + command + ".github_script_downloads", enabled);
papi.saveConfig();
papi.reloadConfig();
if (!enabled) {
if (expansion.getGithubScriptManager() != null) {
expansion.getGithubScriptManager().clear();
expansion.setGithubScriptManager(null);
}
} else {
if (expansion.getGithubScriptManager() == null) {
expansion.setGithubScriptManager(new GithubScriptManager(expansion));
}
expansion.getGithubScriptManager().fetch();
}
ExpansionUtils.sendMsg(sender, "&6Git script downloads set to: &e" + enabled);
return;
default: {
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! Type '&f/" + command + "&c' for more help.");
}
}
}
@Override
public @NotNull String getAlias() {
return "git";
}
}

View File

@ -1,20 +0,0 @@
package com.extendedclip.papi.expansion.javascript.command;
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Collectors;
public abstract class ICommand {
public String command;
public abstract void execute(CommandSender sender, String[] args);
public abstract @NotNull String getAlias();
}

View File

@ -1,31 +0,0 @@
package com.extendedclip.papi.expansion.javascript.command;
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
import com.extendedclip.papi.expansion.javascript.JavascriptExpansion;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class ListCommand extends ICommand {
private final JavascriptExpansion expansion;
public ListCommand(JavascriptExpansion expansion) {
this.expansion = expansion;
}
@Override
public void execute(CommandSender sender, String[] args) {
final List<String> loaded = expansion.getLoadedIdentifiers();
ExpansionUtils.sendMsg(sender,loaded.size() + " &7script" + ExpansionUtils.plural(loaded.size()) + " loaded.",
String.join(", ", loaded));
}
@Override
@NotNull
public String getAlias() {
return "list";
}
}

View File

@ -1,57 +0,0 @@
package com.extendedclip.papi.expansion.javascript.command;
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
import com.extendedclip.papi.expansion.javascript.JavascriptExpansion;
import com.extendedclip.papi.expansion.javascript.JavascriptPlaceholder;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
public class ParseCommand extends ICommand {
private final JavascriptExpansion expansion;
public ParseCommand(JavascriptExpansion expansion) {
this.expansion = expansion;
}
@Override
public void execute(CommandSender sender, String[] args) {
if (args.length < 2) {
ExpansionUtils.sendMsg(sender, "&cIncorrect usage! &f/" + command + " parse [me/player] [code]");
return;
}
final String script = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
final JavascriptPlaceholder placeholder = new JavascriptPlaceholder(expansion.getGlobalEngine(), "parse-command", String.join(" ", script));
if ("me".equalsIgnoreCase(args[0])) {
if (!(sender instanceof Player)) {
ExpansionUtils.sendMsg(sender, "&cOnly players can run this command!");
return;
}
sender.sendMessage(placeholder.evaluate((Player) sender));
return;
}
final OfflinePlayer player = Bukkit.getOfflinePlayer(args[1]);
if (!player.hasPlayedBefore() || player.getName() == null) {
ExpansionUtils.sendMsg(sender, "&cUnknown player " + args[1]);
return;
}
sender.sendMessage(placeholder.evaluate(player));
}
@Override
@NotNull
public String getAlias() {
return "parse";
}
}

View File

@ -1,29 +0,0 @@
package com.extendedclip.papi.expansion.javascript.command;
import com.extendedclip.papi.expansion.javascript.ExpansionUtils;
import com.extendedclip.papi.expansion.javascript.JavascriptExpansion;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class ReloadCommand extends ICommand {
private final JavascriptExpansion expansion;
public ReloadCommand(JavascriptExpansion expansion) {
this.expansion = expansion;
}
@Override
public void execute(CommandSender sender, String[] args) {
ExpansionUtils.sendMsg(sender, "&aJavascriptExpansion reloading...");
final int scripts = expansion.reloadScripts();
ExpansionUtils.sendMsg(sender, scripts + " &7script" + ExpansionUtils.plural(scripts) + " loaded");
}
@Override
@NotNull
public String getAlias() {
return "reload";
}
}