General fixes. Works.

Formatted source files.
Fixed command-line arguments processing.
Added ability to specify logging levels by name (ALL, FINE, FINER...)

Generally fixed unnoticed problems in Configuration and Priestess
classes. Stopped spuriously committing configuration file path to
preferences store, changed some Priestess methods to use her own
tokenizer, and fixed a null check in setCultableChannels method.
This commit is contained in:
Sandy Mossgrave 2023-05-07 19:56:57 +00:00
parent 7d97078e43
commit f2eec77df0
14 changed files with 1508 additions and 1504 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
/priestessconfig.txt /priestessconfig.txt
/priestessconfig.txtbkup /priestessconfig.txtbkup
/target/ /target/
dependency-reduced-pom.xml

View File

@ -21,106 +21,107 @@ import reactor.core.publisher.Mono;
* @author atomb * @author atomb
*/ */
public class Command { public class Command {
public static final HashMap<String, Command> commands = new HashMap<>();
private static final Logger log = Logger.getLogger(Priestess.class.getName());
public static void replyTo(Message m, String s){
if(m != null){
m.getChannel().block().createMessage(s).withMessageReference(m.getId()).block();
} else {
log.log(Level.INFO, s);
}
}
static void tryAll(String commandline, Message m, int permissionLevel) { public static final HashMap<String, Command> commands = new HashMap<>();
for(String s: commands.keySet()){
if(commandline.startsWith(s)){
log.log(Level.INFO, "Matched command " + s);
switch(commands.get(s).tryExecuteCommand(commandline, permissionLevel, m)){
case SUCCESS:
return;
case BADPERM:
replyTo(m, "Insufficient permissions for command.");
return;
case FAILURE:
replyTo(m, String.format("Command %s failed for some reason idfk", s));
return;
}
}
}
replyTo(m, "Unknown command");
}
private final String name;
private final int namelen;
private final int permissionLevel;
private Callback callback;
/**
*
* @param commandline
* @param permissionLevel
* @param a
* @return
*/
public CommandStatus tryExecuteCommand(String commandline, int permissionLevel, Message m){
if(!commandline.startsWith(this.name)){
return NOMATCH;
}
if(permissionLevel < this.permissionLevel){
return BADPERM;
}
String payload = commandline.substring(this.namelen).trim();
this.callback.apply(new CommandArgs(m, payload, permissionLevel));
return SUCCESS;
}
public Command setCallback(Callback c){
this.callback = c;
return this;
}
Command(String name, int permissionLevel){
this.name = name;
this.namelen = name.length();
this.permissionLevel = permissionLevel;
this.callback = new Callback(){
@Override
public Publisher<Mono> apply(CommandArgs t) {
t.replyWith(String.format("Callback for function %s not registered", name));
return null;
}
};
}
public static void registerCommand(Command c){
commands.put(c.name, c);
}
/*= "use emoji";
public static final String REPLYTO_COMMAND = "reply to";
public static final String SENDTO_COMMAND = "send to";*/
/** private static final Logger log = Logger.getLogger(Priestess.class.getName());
* @return the name
*/
public String getName() {
return name;
}
public static Command commandThatJustRepliesWith(String name, String reply){
Command c = new Command(name, 1);
c.setCallback(new Callback(){
@Override public static void replyTo(Message m, String s) {
public Publisher<Mono> apply(CommandArgs t) { if (m != null) {
t.replyWith(reply); m.getChannel().block().createMessage(s).withMessageReference(m.getId()).block();
return Mono.empty(); } else {
} log.log(Level.INFO, s);
}); }
return c; }
}
static void tryAll(String commandline, Message m, int permissionLevel) {
for (String s : commands.keySet()) {
if (commandline.startsWith(s)) {
log.log(Level.INFO, "Matched command " + s);
switch (commands.get(s).tryExecuteCommand(commandline, permissionLevel, m)) {
case SUCCESS:
return;
case BADPERM:
replyTo(m, "Insufficient permissions for command.");
return;
case FAILURE:
replyTo(m, String.format("Command %s failed for some reason idfk", s));
return;
}
}
}
replyTo(m, "Unknown command");
}
private final String name;
private final int namelen;
private final int permissionLevel;
private Callback callback;
/**
*
* @param commandline
* @param permissionLevel
* @param a
* @return
*/
public CommandStatus tryExecuteCommand(String commandline, int permissionLevel, Message m) {
if (!commandline.startsWith(this.name)) {
return NOMATCH;
}
if (permissionLevel < this.permissionLevel) {
return BADPERM;
}
String payload = commandline.substring(this.namelen).trim();
this.callback.apply(new CommandArgs(m, payload, permissionLevel));
return SUCCESS;
}
public Command setCallback(Callback c) {
this.callback = c;
return this;
}
Command(String name, int permissionLevel) {
this.name = name;
this.namelen = name.length();
this.permissionLevel = permissionLevel;
this.callback = new Callback() {
@Override
public Publisher<Mono> apply(CommandArgs t) {
t.replyWith(String.format("Callback for function %s not registered", name));
return null;
}
};
}
public static void registerCommand(Command c) {
commands.put(c.name, c);
}
/*
* = "use emoji"; public static final String REPLYTO_COMMAND = "reply to";
* public static final String SENDTO_COMMAND = "send to";
*/
/**
* @return the name
*/
public String getName() {
return name;
}
public static Command commandThatJustRepliesWith(String name, String reply) {
Command c = new Command(name, 1);
c.setCallback(new Callback() {
@Override
public Publisher<Mono> apply(CommandArgs t) {
t.replyWith(reply);
return Mono.empty();
}
});
return c;
}
} }

View File

@ -13,39 +13,39 @@ import discord4j.core.object.entity.channel.MessageChannel;
*/ */
public class CommandArgs { public class CommandArgs {
private Message m; private Message m;
private String payload; private String payload;
private final int permCalledWith; private final int permCalledWith;
public CommandArgs(Message m, String payload, int permCalledWith) { public CommandArgs(Message m, String payload, int permCalledWith) {
this.m = m; this.m = m;
this.payload = payload; this.payload = payload;
this.permCalledWith = permCalledWith; this.permCalledWith = permCalledWith;
} }
/** /**
* @return the m * @return the m
*/ */
public Message getMessage() { public Message getMessage() {
return m; return m;
} }
/** /**
* @return the payload * @return the payload
*/ */
public String getPayload() { public String getPayload() {
return payload; return payload;
} }
public void replyWith(String s){ public void replyWith(String s) {
Command.replyTo(m, s); Command.replyTo(m, s);
} }
/**
* @return the permCalledWith
*/
public int getPermCalledWith() {
return permCalledWith;
}
/**
* @return the permCalledWith
*/
public int getPermCalledWith() {
return permCalledWith;
}
} }

View File

@ -9,8 +9,5 @@ package com.tinyplantnews.priestess;
* @author atomb * @author atomb
*/ */
public enum CommandStatus { public enum CommandStatus {
NOMATCH, NOMATCH, SUCCESS, FAILURE, BADPERM;
SUCCESS,
FAILURE,
BADPERM;
} }

View File

@ -30,171 +30,179 @@ import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
/** /**
* * "Ms Merry," you may say, "You literally import the Preferences class, and yet
* @author twi * you insist on writing your own configuration store. Why?" "Iunno," I reply.
*
* @author sandy
*/ */
public class Configuration { public class Configuration {
private static String CONFIG_FILE_LOCATION = null; private static String CONFIG_FILE_LOCATION = null;
public static final String CONFIG_FILE_KEY = "PRIESTESS_CONFIG"; public static final String CONFIG_FILE_KEY = "PRIESTESS_CONFIG";
public static final Properties props = System.getProperties(); public static final Properties props = System.getProperties();
public static final Preferences prefs = Preferences.userNodeForPackage(Configuration.class); public static final Preferences prefs = Preferences.userNodeForPackage(Configuration.class);
public static final String DEFAULT_CONFIG_FILE_NAME = "priestessconfig.txt"; public static final String DEFAULT_CONFIG_FILE_NAME = "priestessconfig.txt";
private static HashMap<String, String> configuration = new HashMap<>(); private static HashMap<String, String> configuration = new HashMap<>();
private static final Logger log = Logger.getLogger(Configuration.class.getName()); private static final Logger log = Logger.getLogger(Configuration.class.getName());
public static String findConfigurationFilePath() { public static String findConfigurationFilePath() {
if (getCONFIG_FILE_LOCATION() != null) { if (getCONFIG_FILE_LOCATION() != null) {
return getCONFIG_FILE_LOCATION(); return getCONFIG_FILE_LOCATION();
} }
setCONFIG_FILE_LOCATION(setConfigurationFilePath(), false); setCONFIG_FILE_LOCATION(setConfigurationFilePath(), false);
return getCONFIG_FILE_LOCATION(); return getCONFIG_FILE_LOCATION();
} }
private static String setConfigurationFilePath() { private static String setConfigurationFilePath() {
String s = System.getenv(CONFIG_FILE_KEY); String s = System.getenv(CONFIG_FILE_KEY);
if (s != null && !s.isBlank()) { if (s != null && !s.isBlank()) {
return s; return s;
} else if (props.containsKey(CONFIG_FILE_KEY)) { } else if (props.containsKey(CONFIG_FILE_KEY)) {
return props.getProperty(CONFIG_FILE_KEY); return props.getProperty(CONFIG_FILE_KEY);
} }
s = prefs.get(CONFIG_FILE_KEY, ""); s = prefs.get(CONFIG_FILE_KEY, "");
if (s != null && !s.isBlank()) { if (s != null && !s.isBlank()) {
return s; return s;
} }
if (Files.exists(Paths.get(DEFAULT_CONFIG_FILE_NAME), LinkOption.NOFOLLOW_LINKS)) { if (Files.exists(Paths.get(DEFAULT_CONFIG_FILE_NAME), LinkOption.NOFOLLOW_LINKS)) {
return DEFAULT_CONFIG_FILE_NAME; return DEFAULT_CONFIG_FILE_NAME;
} }
//JDialog jd = new JDialog(); // JDialog jd = new JDialog();
//jd.add(new JLabel("Choose where to put Priestess Working Directory")); // jd.add(new JLabel("Choose where to put Priestess Working Directory"));
//jd.setVisible(true); // jd.setVisible(true);
JOptionPane.showConfirmDialog(null, "Select where cult files will be stored."); JOptionPane.showConfirmDialog(null, "Select where cult files will be stored.");
JFileChooser jfc = new JFileChooser("Config File for Discord Cult Priestess"); JFileChooser jfc = new JFileChooser("Config File for Discord Cult Priestess");
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int rv; int rv;
boolean approved = false; boolean approved = false;
while (!approved) { while (!approved) {
rv = jfc.showDialog(null, "Select"); rv = jfc.showDialog(null, "Select");
if (rv == JFileChooser.APPROVE_OPTION) { if (rv == JFileChooser.APPROVE_OPTION) {
File f = jfc.getSelectedFile(); File f = jfc.getSelectedFile();
if (f.isDirectory() && f.canRead() && f.canWrite()) { if (f.isDirectory() && f.canRead() && f.canWrite()) {
prefs.put(CONFIG_FILE_KEY, f.getAbsolutePath()); return f.getAbsolutePath();
try { }
prefs.flush(); } else if (rv == JFileChooser.CANCEL_OPTION) {
} catch (BackingStoreException e) { return "";
log.log(Level.WARNING, "Backing store exception while committing configuration file path to persistent storage {0}", e.getMessage()); }
}
return f.getAbsolutePath();
}
} else if(rv == JFileChooser.CANCEL_OPTION) {
return "";
}
} }
return ""; return "";
} }
private static final String delimiter = ": "; private static final String delimiter = ": ";
public static void getConfigurationFromFile() { public static void getConfigurationFromFile() {
if (CONFIG_FILE_LOCATION == null) { if (CONFIG_FILE_LOCATION == null) {
setConfigurationFilePath(); setConfigurationFilePath();
} }
try { try {
if (Files.isDirectory(Paths.get(CONFIG_FILE_LOCATION), LinkOption.NOFOLLOW_LINKS)) { if (Files.isDirectory(Paths.get(CONFIG_FILE_LOCATION), LinkOption.NOFOLLOW_LINKS)) {
CONFIG_FILE_LOCATION = CONFIG_FILE_LOCATION + System.getProperty("file.separator") + DEFAULT_CONFIG_FILE_NAME; CONFIG_FILE_LOCATION = CONFIG_FILE_LOCATION + System.getProperty("file.separator")
} + DEFAULT_CONFIG_FILE_NAME;
BufferedReader br = new BufferedReader(new FileReader(Paths.get(CONFIG_FILE_LOCATION).toFile())); }
br.lines().forEach((s) -> { BufferedReader br = new BufferedReader(new FileReader(Paths.get(CONFIG_FILE_LOCATION).toFile()));
String key = s.substring(0, s.indexOf(delimiter)); br.lines().forEach((s) -> {
if (s.length() == s.indexOf(delimiter) + delimiter.length()) { String key = s.substring(0, s.indexOf(delimiter));
System.out.println("read empty value for key (" + key + ") from configuration file"); if (s.length() == s.indexOf(delimiter) + delimiter.length()) {
configuration.put(key, ""); log.log(Level.FINE, "read empty value for key (" + key + ") from configuration file");
} else { configuration.put(key, "");
String value = s.substring(s.indexOf(delimiter) + delimiter.length()); } else {
configuration.put(key, value); String value = s.substring(s.indexOf(delimiter) + delimiter.length());
} configuration.put(key, value);
}); }
} catch (FileNotFoundException ex) { });
} catch (FileNotFoundException ex) {
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, "Error loading configuration file from (" + CONFIG_FILE_LOCATION + ") {0}", ex); Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE,
} "Error loading configuration file from (" + CONFIG_FILE_LOCATION + ") {0}", ex);
} }
}
/** /**
* @return the CONFIG_FILE_LOCATION * @return the CONFIG_FILE_LOCATION
*/ */
public static String getCONFIG_FILE_LOCATION() { public static String getCONFIG_FILE_LOCATION() {
return CONFIG_FILE_LOCATION; return CONFIG_FILE_LOCATION;
} }
/** /**
* @param aCONFIG_FILE_LOCATION the CONFIG_FILE_LOCATION to set * @param aCONFIG_FILE_LOCATION the CONFIG_FILE_LOCATION to set
*/ */
public static void setCONFIG_FILE_LOCATION(String aCONFIG_FILE_LOCATION, boolean persistent) { public static void setCONFIG_FILE_LOCATION(String aCONFIG_FILE_LOCATION, boolean persistent) {
CONFIG_FILE_LOCATION = aCONFIG_FILE_LOCATION; CONFIG_FILE_LOCATION = aCONFIG_FILE_LOCATION;
if (persistent) { if (persistent) {
props.setProperty(CONFIG_FILE_KEY, CONFIG_FILE_LOCATION); props.setProperty(CONFIG_FILE_KEY, CONFIG_FILE_LOCATION);
} prefs.put(CONFIG_FILE_KEY, CONFIG_FILE_LOCATION);
try {
prefs.flush();
} catch (BackingStoreException e) {
log.log(Level.WARNING,
"Backing store exception while committing configuration file path to persistent storage {0}",
e.getMessage());
}
}
} }
public static void setConfigurationParameter(String key, String value) { public static void setConfigurationParameter(String key, String value) {
configuration.put(key, value); configuration.put(key, value);
} }
public static String getConfigurationParameter(String key) { public static String getConfigurationParameter(String key) {
if (configuration.containsKey(key)) { if (configuration.containsKey(key)) {
return configuration.get(key); return configuration.get(key);
} else { } else {
configuration.put(key, ""); configuration.put(key, "");
return ""; return "";
} }
} }
public static void commitConfigurationToFile() { public static void commitConfigurationToFile() {
try { try {
Files.deleteIfExists(Paths.get(CONFIG_FILE_LOCATION + "bkup")); Files.deleteIfExists(Paths.get(CONFIG_FILE_LOCATION + "bkup"));
try { try {
Files.copy(Paths.get(CONFIG_FILE_LOCATION), Paths.get(CONFIG_FILE_LOCATION + "bkup")); Files.copy(Paths.get(CONFIG_FILE_LOCATION), Paths.get(CONFIG_FILE_LOCATION + "bkup"));
} catch (IOException ioe) { } catch (IOException ioe) {
if(ioe instanceof NoSuchFileException) { if (ioe instanceof NoSuchFileException) {
log.log(Level.FINE, "No existing configuration file--not creating backup"); log.log(Level.FINE, "No existing configuration file--not creating backup");
} else { } else {
log.log(Level.WARNING, "Exception encountered while trying to create configuration file backup: {0}", ioe); log.log(Level.WARNING,
} "Exception encountered while trying to create configuration file backup: {0}", ioe);
} }
} catch (IOException ex) { }
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) {
System.err.println("Making backup configuration file failed. Exiting without committing configuration to file"); Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
return; System.err.println(
} "Making backup configuration file failed. Exiting without committing configuration to file");
try ( BufferedWriter br = new BufferedWriter(new FileWriter(Paths.get(CONFIG_FILE_LOCATION).toFile(), false))) { return;
configuration.forEach((key, value) -> { }
try { try (BufferedWriter br = new BufferedWriter(new FileWriter(Paths.get(CONFIG_FILE_LOCATION).toFile(), false))) {
br.append(key + delimiter + value + "\n"); configuration.forEach((key, value) -> {
} catch (IOException ex) { try {
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex); br.append(key + delimiter + value + "\n");
} } catch (IOException ex) {
}); Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
}
});
br.flush(); br.flush();
br.close(); br.close();
} catch (FileNotFoundException ex) { } catch (FileNotFoundException ex) {
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) { } catch (IOException ex) {
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
} }
} }
public static String enumerateConfiguration() { public static String enumerateConfiguration() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
configuration.forEach((key, value) -> { configuration.forEach((key, value) -> {
sb.append(key + delimiter + value + "\n"); sb.append(key + delimiter + value + "\n");
}); });
return sb.toString(); return sb.toString();
} }
} }

View File

@ -12,7 +12,7 @@ import java.util.logging.Level;
*/ */
public class CustomLoggingLevel extends Level { public class CustomLoggingLevel extends Level {
public CustomLoggingLevel(int i) { public CustomLoggingLevel(int i) {
super("custom", i); super("custom", i);
} }
} }

View File

@ -17,65 +17,60 @@ import java.util.function.BiConsumer;
*/ */
class GuildProfile { class GuildProfile {
private final Guild g; private final Guild g;
public GuildProfile(Guild g1) { public GuildProfile(Guild g1) {
g = g1; g = g1;
} }
private HashMap<String, Snowflake> customemojis = new HashMap<>();
private HashMap<String, Snowflake> customemojis = new HashMap<>();
private HashMap<String, Snowflake> approvingcustomemojis = new HashMap<>(); private HashMap<String, Snowflake> approvingcustomemojis = new HashMap<>();
//Just so it's seekable, for the random approving emoji methods. // Just so it's seekable, for the random approving emoji methods.
private ArrayList<String> approvingcustomemojinames = new ArrayList<>(); private ArrayList<String> approvingcustomemojinames = new ArrayList<>();
/** /**
* @return the customemojis * @return the customemojis
*/ */
public HashMap<String, Snowflake> getCustomemojis() { public HashMap<String, Snowflake> getCustomemojis() {
return customemojis; return customemojis;
} }
/** /**
* @param customemojis the customemojis to set * @param customemojis the customemojis to set
*/ */
public void setCustomemojis(HashMap<String, Snowflake> customemojis) { public void setCustomemojis(HashMap<String, Snowflake> customemojis) {
this.customemojis = customemojis; this.customemojis = customemojis;
} }
public String toFile() { public String toFile() {
return ""; return "";
} }
public String emojisToString() { public String emojisToString() {
StringBuilder s = new StringBuilder(""); StringBuilder s = new StringBuilder("");
customemojis.forEach((String name, Snowflake snowflake) -> { customemojis.forEach((String name, Snowflake snowflake) -> {
s.append(new JKRSONTag(name, snowflake.asString())); s.append(new JKRSONTag(name, snowflake.asString()));
}); });
return s.toString(); return s.toString();
} }
public void setApprovingEmoji(String name, Snowflake snowflake) { public void setApprovingEmoji(String name, Snowflake snowflake) {
approvingcustomemojis.put(name, snowflake); approvingcustomemojis.put(name, snowflake);
approvingcustomemojinames.add(name); approvingcustomemojinames.add(name);
} }
public int emojiCount() { public int emojiCount() {
return customemojis.size(); return customemojis.size();
} }
public int approvingEmojiCount() { public int approvingEmojiCount() {
return approvingcustomemojis.size(); return approvingcustomemojis.size();
} }
public GuildEmoji getEmojiByNumber(int i) { public GuildEmoji getEmojiByNumber(int i) {
return g.getGuildEmojiById( return g.getGuildEmojiById(approvingcustomemojis.get(approvingcustomemojinames.get(i))).block();
approvingcustomemojis.get(approvingcustomemojinames }
.get(i)
)
).block();
}
} }

View File

@ -31,151 +31,155 @@ import javax.swing.JOptionPane;
*/ */
public class InstantiableConfiguration { public class InstantiableConfiguration {
private static String CONFIG_FILE_LOCATION = null; private static String CONFIG_FILE_LOCATION = null;
public static final String CONFIG_FILE_KEY = "PRIESTESS_CONFIG"; public static final String CONFIG_FILE_KEY = "PRIESTESS_CONFIG";
public static final Properties p = System.getProperties(); public static final Properties p = System.getProperties();
public static final String DEFAULT_CONFIG_FILE_NAME = "priestessconfig.txt"; public static final String DEFAULT_CONFIG_FILE_NAME = "priestessconfig.txt";
private static HashMap<String, String> configuration = new HashMap<>(); private static HashMap<String, String> configuration = new HashMap<>();
private static final Logger log = Logger.getLogger(InstantiableConfiguration.class.getName()); private static final Logger log = Logger.getLogger(InstantiableConfiguration.class.getName());
public static String findConfigurationFilePath() { public static String findConfigurationFilePath() {
if (getCONFIG_FILE_LOCATION() != null) { if (getCONFIG_FILE_LOCATION() != null) {
return getCONFIG_FILE_LOCATION(); return getCONFIG_FILE_LOCATION();
} }
setCONFIG_FILE_LOCATION(setConfigurationFilePath(), false); setCONFIG_FILE_LOCATION(setConfigurationFilePath(), false);
return getCONFIG_FILE_LOCATION(); return getCONFIG_FILE_LOCATION();
} }
private static String setConfigurationFilePath() { private static String setConfigurationFilePath() {
String s = System.getenv(CONFIG_FILE_KEY); String s = System.getenv(CONFIG_FILE_KEY);
if (s != null && s.length() > 0) { if (s != null && s.length() > 0) {
return s; return s;
} else if (p.containsKey(CONFIG_FILE_KEY)) { } else if (p.containsKey(CONFIG_FILE_KEY)) {
return p.getProperty(CONFIG_FILE_KEY); return p.getProperty(CONFIG_FILE_KEY);
} }
if (Files.exists(Paths.get(DEFAULT_CONFIG_FILE_NAME), LinkOption.NOFOLLOW_LINKS)) { if (Files.exists(Paths.get(DEFAULT_CONFIG_FILE_NAME), LinkOption.NOFOLLOW_LINKS)) {
return DEFAULT_CONFIG_FILE_NAME; return DEFAULT_CONFIG_FILE_NAME;
} }
//JDialog jd = new JDialog(); // JDialog jd = new JDialog();
//jd.add(new JLabel("Choose where to put Priestess Working Directory")); // jd.add(new JLabel("Choose where to put Priestess Working Directory"));
//jd.setVisible(true); // jd.setVisible(true);
JOptionPane.showConfirmDialog(null, "Select where cult files will be stored."); JOptionPane.showConfirmDialog(null, "Select where cult files will be stored.");
JFileChooser jfc = new JFileChooser("Config File for Discord Cult Priestess"); JFileChooser jfc = new JFileChooser("Config File for Discord Cult Priestess");
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int rv; int rv;
boolean approved = false; boolean approved = false;
while (!approved) { while (!approved) {
rv = jfc.showDialog(null, "Select"); rv = jfc.showDialog(null, "Select");
if (rv == JFileChooser.APPROVE_OPTION) { if (rv == JFileChooser.APPROVE_OPTION) {
File f = jfc.getSelectedFile(); File f = jfc.getSelectedFile();
if (f.isDirectory() && f.canRead() && f.canWrite()) { if (f.isDirectory() && f.canRead() && f.canWrite()) {
p.setProperty(CONFIG_FILE_KEY, f.getAbsolutePath()); p.setProperty(CONFIG_FILE_KEY, f.getAbsolutePath());
return f.getAbsolutePath(); return f.getAbsolutePath();
} }
} }
} }
return ""; return "";
} }
private static final String delimiter = ": "; private static final String delimiter = ": ";
public static void getConfigurationFromFile() { public static void getConfigurationFromFile() {
if (CONFIG_FILE_LOCATION == null) { if (CONFIG_FILE_LOCATION == null) {
setConfigurationFilePath(); setConfigurationFilePath();
} }
try { try {
if (Files.isDirectory(Paths.get(CONFIG_FILE_LOCATION), LinkOption.NOFOLLOW_LINKS)) { if (Files.isDirectory(Paths.get(CONFIG_FILE_LOCATION), LinkOption.NOFOLLOW_LINKS)) {
CONFIG_FILE_LOCATION = CONFIG_FILE_LOCATION + System.getProperty("file.separator") + DEFAULT_CONFIG_FILE_NAME; CONFIG_FILE_LOCATION = CONFIG_FILE_LOCATION + System.getProperty("file.separator")
} + DEFAULT_CONFIG_FILE_NAME;
BufferedReader br = new BufferedReader(new FileReader(Paths.get(CONFIG_FILE_LOCATION).toFile())); }
br.lines().forEach((s) -> { BufferedReader br = new BufferedReader(new FileReader(Paths.get(CONFIG_FILE_LOCATION).toFile()));
String key = s.substring(0, s.indexOf(delimiter)); br.lines().forEach((s) -> {
if (s.length() == s.indexOf(delimiter) + delimiter.length()) { String key = s.substring(0, s.indexOf(delimiter));
System.out.println("read empty value for key (" + key + ") from configuration file"); if (s.length() == s.indexOf(delimiter) + delimiter.length()) {
configuration.put(key, ""); System.out.println("read empty value for key (" + key + ") from configuration file");
} else { configuration.put(key, "");
String value = s.substring(s.indexOf(delimiter) + delimiter.length()); } else {
configuration.put(key, value); String value = s.substring(s.indexOf(delimiter) + delimiter.length());
} configuration.put(key, value);
}); }
} catch (FileNotFoundException ex) { });
} catch (FileNotFoundException ex) {
Logger.getLogger(InstantiableConfiguration.class.getName()).log(Level.SEVERE, "Error loading configuration file from (" + CONFIG_FILE_LOCATION + ") {0}", ex); Logger.getLogger(InstantiableConfiguration.class.getName()).log(Level.SEVERE,
} "Error loading configuration file from (" + CONFIG_FILE_LOCATION + ") {0}", ex);
} }
}
/** /**
* @return the CONFIG_FILE_LOCATION * @return the CONFIG_FILE_LOCATION
*/ */
public static String getCONFIG_FILE_LOCATION() { public static String getCONFIG_FILE_LOCATION() {
return CONFIG_FILE_LOCATION; return CONFIG_FILE_LOCATION;
} }
/** /**
* @param aCONFIG_FILE_LOCATION the CONFIG_FILE_LOCATION to set * @param aCONFIG_FILE_LOCATION the CONFIG_FILE_LOCATION to set
*/ */
public static void setCONFIG_FILE_LOCATION(String aCONFIG_FILE_LOCATION, boolean persistent) { public static void setCONFIG_FILE_LOCATION(String aCONFIG_FILE_LOCATION, boolean persistent) {
CONFIG_FILE_LOCATION = aCONFIG_FILE_LOCATION; CONFIG_FILE_LOCATION = aCONFIG_FILE_LOCATION;
if (persistent) { if (persistent) {
p.setProperty(CONFIG_FILE_KEY, CONFIG_FILE_LOCATION); p.setProperty(CONFIG_FILE_KEY, CONFIG_FILE_LOCATION);
} }
} }
public static void setConfigurationParameter(String key, String value) { public static void setConfigurationParameter(String key, String value) {
configuration.put(key, value); configuration.put(key, value);
} }
public static String getConfigurationParameter(String key) { public static String getConfigurationParameter(String key) {
if (configuration.containsKey(key)) { if (configuration.containsKey(key)) {
return configuration.get(key); return configuration.get(key);
} else { } else {
configuration.put(key, ""); configuration.put(key, "");
return ""; return "";
} }
} }
public static void commitConfigurationToFile() { public static void commitConfigurationToFile() {
try { try {
Files.deleteIfExists(Paths.get(CONFIG_FILE_LOCATION + "bkup")); Files.deleteIfExists(Paths.get(CONFIG_FILE_LOCATION + "bkup"));
try { try {
Files.copy(Paths.get(CONFIG_FILE_LOCATION), Paths.get(CONFIG_FILE_LOCATION + "bkup")); Files.copy(Paths.get(CONFIG_FILE_LOCATION), Paths.get(CONFIG_FILE_LOCATION + "bkup"));
} catch (IOException ioe) { } catch (IOException ioe) {
log.log(Level.WARNING, "Exception encountered while trying to create confirguation file backup: {0}", ioe); log.log(Level.WARNING, "Exception encountered while trying to create confirguation file backup: {0}",
} ioe);
} catch (IOException ex) { }
Logger.getLogger(InstantiableConfiguration.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) {
System.err.println("Making backup configuration file failed. Exiting without committing configuration to file"); Logger.getLogger(InstantiableConfiguration.class.getName()).log(Level.SEVERE, null, ex);
return; System.err.println(
} "Making backup configuration file failed. Exiting without committing configuration to file");
try ( BufferedWriter br = new BufferedWriter(new FileWriter(Paths.get(CONFIG_FILE_LOCATION).toFile(), false))) { return;
configuration.forEach((key, value) -> { }
try { try (BufferedWriter br = new BufferedWriter(new FileWriter(Paths.get(CONFIG_FILE_LOCATION).toFile(), false))) {
br.append(key + delimiter + value + "\n"); configuration.forEach((key, value) -> {
} catch (IOException ex) { try {
Logger.getLogger(InstantiableConfiguration.class.getName()).log(Level.SEVERE, null, ex); br.append(key + delimiter + value + "\n");
} } catch (IOException ex) {
}); Logger.getLogger(InstantiableConfiguration.class.getName()).log(Level.SEVERE, null, ex);
}
});
br.flush(); br.flush();
br.close(); br.close();
} catch (FileNotFoundException ex) { } catch (FileNotFoundException ex) {
Logger.getLogger(InstantiableConfiguration.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(InstantiableConfiguration.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) { } catch (IOException ex) {
Logger.getLogger(InstantiableConfiguration.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(InstantiableConfiguration.class.getName()).log(Level.SEVERE, null, ex);
} }
} }
public static String enumerateConfiguration() { public static String enumerateConfiguration() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
configuration.forEach((key, value) -> { configuration.forEach((key, value) -> {
sb.append(key + delimiter + value + "\n"); sb.append(key + delimiter + value + "\n");
}); });
return sb.toString(); return sb.toString();
} }
} }

View File

@ -10,42 +10,43 @@ package com.tinyplantnews.priestess;
*/ */
public class JKRSONTag { public class JKRSONTag {
public JKRSONTag(String key1, String val1) { public JKRSONTag(String key1, String val1) {
key = key1; key = key1;
val = val1; val = val1;
} }
public JKRSONTag() { public JKRSONTag() {
} }
/**
* @return the key
*/
public String getKey() {
return key;
}
/** /**
* @param key the key to set * @return the key
*/ */
public void setKey(String key) { public String getKey() {
this.key = key; return key;
} }
/** /**
* @return the val * @param key the key to set
*/ */
public String getVal() { public void setKey(String key) {
return val; this.key = key;
} }
/** /**
* @param val the val to set * @return the val
*/ */
public void setVal(String val) { public String getVal() {
this.val = val; return val;
} }
private String key;
private String val; /**
* @param val the val to set
*/
public void setVal(String val) {
this.val = val;
}
private String key;
private String val;
} }

View File

@ -18,25 +18,25 @@ import java.util.regex.Pattern;
*/ */
public class JKRowlingSON { public class JKRowlingSON {
public static final String TAG_PATTERN = "^\\{([a-z]*):([\\\"\\{a-z][a-z:\\}\\\"]*)\\}"; public static final String TAG_PATTERN = "^\\{([a-z]*):([\\\"\\{a-z][a-z:\\}\\\"]*)\\}";
public static String keyVal(String key, String val) { public static String keyVal(String key, String val) {
return String.format("\"%s:\" \"%s\"", key, val); return String.format("\"%s:\" \"%s\"", key, val);
} }
private static Pattern tagPattern = Pattern.compile(TAG_PATTERN); private static Pattern tagPattern = Pattern.compile(TAG_PATTERN);
public static JKRSONTag decode(String tag) { public static JKRSONTag decode(String tag) {
Matcher m = tagPattern.matcher(tag); Matcher m = tagPattern.matcher(tag);
JKRSONTag db = new JKRSONTag(); JKRSONTag db = new JKRSONTag();
if (m.matches()) { if (m.matches()) {
db.setKey(m.group(1)); db.setKey(m.group(1));
db.setVal(m.group(2)); db.setVal(m.group(2));
} else { } else {
Logger.getLogger(JKRowlingSON.class.toString()).log(Level.SEVERE, "Could not decode " + tag); Logger.getLogger(JKRowlingSON.class.toString()).log(Level.SEVERE, "Could not decode " + tag);
} }
return db; return db;
} }
} }

View File

@ -17,121 +17,134 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
* * OH IT STORES THE PROPHECIES
*
* The configuration file (priestessconfig.txt) contains a key, 'messages', for which the value is a path to the messages store.
* The messages store contains prophecies that are given every few bean goose invocations.
* This class first loads the file, scans it and generates a list of indices for the messages it contains.
*
* This class could definitely use a cache of the message starts--a special block at the beginning/end of the file with a list of message starts/ends,
* but I'm not up to writing that today - 7 May 2023
*
* @author atomb * @author atomb
*/ */
public class MessageStore { public class MessageStore {
private RandomAccessFile f; private RandomAccessFile f;
private long filelength = 0; private long filelength = 0;
private FileChannel fr = null; private FileChannel fr = null;
private MessageCacher mc; private MessageCacher mc;
private int[] messagestarts = null; private int[] messagestarts = null;
Thread t; Thread t;
private boolean messagesCached = false; private boolean messagesCached = false;
private long loadStart = Long.MAX_VALUE;
public MessageStore(File f1) throws FileNotFoundException, IOException { public MessageStore(File f1) throws FileNotFoundException, IOException {
f = new RandomAccessFile(f1.getPath(), "r"); loadStart = System.nanoTime();
System.out.println("Message store is " + f.length() + " bytes long"); f = new RandomAccessFile(f1.getPath(), "r");
fr = f.getChannel(); System.out.println("Message store is " + f.length() + " bytes long");
filelength = f.length(); fr = f.getChannel();
mc = new MessageCacher(); filelength = f.length();
t = new Thread(mc); mc = new MessageCacher();
t.start(); t = new Thread(mc);
} t.start();
}
public String messageAt(int i) { public String messageAt(int i) {
waitUntilLoaded(); waitUntilLoaded();
int start = messagestarts[i]; int start = messagestarts[i];
StringBuilder s = new StringBuilder(); StringBuilder s = new StringBuilder();
try { try {
f.seek(start); f.seek(start);
int a = 0; int a = 0;
int j = 0; int j = 0;
char c = '\0'; char c = '\0';
while ((j = f.read()) != -1 && ((char) j != '}')) { while ((j = f.read()) != -1 && ((char) j != '}')) {
c = (char) j; c = (char) j;
s.append(c); s.append(c);
a++; a++;
} }
} catch (IOException ex) { } catch (IOException ex) {
Logger.getLogger(MessageStore.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(MessageStore.class.getName()).log(Level.SEVERE, null, ex);
} }
while (s.charAt(0) == '{') { while (s.charAt(0) == '{') {
s.deleteCharAt(0); s.deleteCharAt(0);
} }
return s.toString(); return s.toString();
} }
public String randomMessage() { public String randomMessage() {
return messageAt((int) (messagestarts.length * Math.random())); return messageAt((int) (messagestarts.length * Math.random()));
} }
boolean messagesAvailable() { boolean messagesAvailable() {
return messagesCached; return messagesCached;
} }
void waitUntilLoaded() { void waitUntilLoaded() {
if (t.isAlive()) { if (t.isAlive()) {
try { try {
t.join(); t.join();
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
Logger.getLogger(MessageStore.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(MessageStore.class.getName()).log(Level.SEVERE, null, ex);
} }
} }
} }
public int messageCount() { public int messageCount() {
return messagestarts.length; return messagestarts.length;
} }
private class MessageCacher implements Runnable { private class MessageCacher implements Runnable {
@Override @Override
public void run() { public void run() {
Logger log = Logger.getLogger(this.getClass().getName()); Logger log = Logger.getLogger(this.getClass().getName());
log.setLevel(Level.FINE); log.setLevel(Level.FINE);
log.log(Level.INFO, "Attempting to characterize message store"); log.log(Level.INFO, "Attempting to characterize message store");
try { try {
ArrayList<Integer> messagestartsal = new ArrayList<>(); //contains index of every '{' ArrayList<Integer> messagestartsal = new ArrayList<>(); // contains index of every '{'
char c; char c;
int a = 0; int a = 0;
int i = 0; int i = 0;
int j = 0; int j = 0;
ByteBuffer b = ByteBuffer.allocate(20); ByteBuffer b = ByteBuffer.allocate(20);
b.rewind(); b.rewind();
log.log(Level.INFO, "Starting to characterize message store at position (" + fr.position() log.log(Level.INFO, "Starting to characterize message store at position (" + fr.position()
+ ") with channel size " + fr.size()); + ") with channel size " + fr.size());
while ((j = f.read()) != -1) { while ((j = f.read()) != -1) {
c = (char) j; c = (char) j;
if (c == '{') { if (c == '{') {
messagestartsal.add(a); messagestartsal.add(a);
} }
a++; a++;
} }
Integer[] messagestarts1 = messagestartsal.toArray(new Integer[0]); Integer[] messagestarts1 = messagestartsal.toArray(new Integer[0]);
messagestarts = new int[messagestarts1.length]; messagestarts = new int[messagestarts1.length];
for (i = 0; i < messagestarts1.length; i++) { for (i = 0; i < messagestarts1.length; i++) {
messagestarts[i] = messagestarts1[i].intValue(); messagestarts[i] = messagestarts1[i].intValue();
} }
} catch (IOException ex) { } catch (IOException ex) {
Logger.getLogger(MessageStore.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(MessageStore.class.getName()).log(Level.SEVERE, null, ex);
} }
for (int i : messagestarts) { for (int i : messagestarts) {
System.out.println("Found invocation message at position " + i); System.out.println("Found invocation message at position " + i);
} }
messagesCached = true; messagesCached = true;
}
} long loadEnd = System.nanoTime();
long tdiff = loadEnd - loadStart;
log.log(Level.FINE, "Prophecies loaded in {0} ms", tdiff);
}
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -9,5 +9,5 @@ package com.tinyplantnews.priestess;
* @author atomb * @author atomb
*/ */
public class WordsAndWhatTheyMean { public class WordsAndWhatTheyMean {
} }

View File

@ -17,101 +17,87 @@ import org.junit.jupiter.params.ParameterizedTest;
*/ */
public class PriestessTest { public class PriestessTest {
public PriestessTest() { public PriestessTest() {
} }
@org.junit.jupiter.api.BeforeAll @org.junit.jupiter.api.BeforeAll
public static void setUpClass() throws Exception { public static void setUpClass() throws Exception {
} }
@org.junit.jupiter.api.AfterAll @org.junit.jupiter.api.AfterAll
public static void tearDownClass() throws Exception { public static void tearDownClass() throws Exception {
} }
/** /**
* Test of main method, of class Priestess. * Test of main method, of class Priestess.
*/ */
@org.junit.jupiter.api.Test @org.junit.jupiter.api.Test
public void testMain() { public void testMain() {
System.out.println("main"); System.out.println("main");
String[] args = {"testsuite"}; String[] args = { "testsuite" };
Priestess.main(args); Priestess.main(args);
} }
@org.junit.jupiter.api.Test
@org.junit.jupiter.api.Test public void testCallbackHelpTexts() {
public void testCallbackHelpTexts(){ assertEquals("boi", "son".replaceAll("son", "boi"));
assertEquals("boi", "son".replaceAll("son", "boi"));
Priestess p = new Priestess();
p.shutdownCommand.help = "ha boi";
testCallbackHelpText(p.shutdownCommand,
"shut down",
"ha boi");
p.shutdownCommand.help = "${commandname}";
testCallbackHelpText(p.shutdownCommand,
"shut down",
"shut down");
p.shutdownCommand.help = "${commandname} turns off the entire internet";
testCallbackHelpText(p.shutdownCommand,
"shut down",
"shut down turns off the entire internet");
}
private void testCallbackHelpText(Priestess.Callback c, String name, String expHelp){
String help = c.getHelp(name);
Assertions.assertEquals(expHelp, help);
}
/**
* Test of tokenize method, of class Priestess.
*/
@Test
public void testTokenize() {
testTokenize1("a",
new String[]{"a"});
testTokenize1("a, b",
new String[]{"a,", "b"});
testTokenize1("ya boi",
new String[]{"ya", "boi"});
//Should handle these trivially. Single quotes not special.
testTokenize1("'''' ''' ' '''",
new String[]{"''''", "'''", "'", "'''"});
testTokenize1("*^@^$/><::;''",
new String[]{"*^@^$/><::;''"});
testTokenize1("*^@^$/> <::;''",
new String[]{"*^@^$/>", "<::;''"});
testTokenize1("this is not quoted, \"this is\"",
new String[]{"this", "is", "not", "quoted,", "this is"});
testTokenize1("this is not quoted, \"this is",
null);
/*testTokenize1("this is not quoted, \\\"this is",
new String[]{"this", "is", "not", "quoted,", "\"this is"});*/
}
private void testTokenize1(String payload, String[] expResult) { Priestess p = new Priestess();
System.out.println("tokenize for payload " + payload); p.shutdownCommand.help = "ha boi";
String[] result = Priestess.tokenize(payload); testCallbackHelpText(p.shutdownCommand, "shut down", "ha boi");
if (expResult == null && result == null) {
return; p.shutdownCommand.help = "${commandname}";
} else if (result == null && expResult != null) { testCallbackHelpText(p.shutdownCommand, "shut down", "shut down");
fail("Tokenize() returned null array");
} p.shutdownCommand.help = "${commandname} turns off the entire internet";
for (int i = 0; i < Math.max(expResult.length, result.length); i++) { testCallbackHelpText(p.shutdownCommand, "shut down", "shut down turns off the entire internet");
String a = "<nothing>"; }
String b = "<nothing>";
if (expResult.length > i) { private void testCallbackHelpText(Priestess.Callback c, String name, String expHelp) {
a = expResult[i]; String help = c.getHelp(name);
} Assertions.assertEquals(expHelp, help);
if (result.length > i) { }
b = result[i];
} /**
System.out.println(String.format("\te: %s r: %s", a, b)); * Test of tokenize method, of class Priestess.
} */
assertArrayEquals(expResult, result); @Test
} public void testTokenize() {
testTokenize1("a", new String[] { "a" });
testTokenize1("a, b", new String[] { "a,", "b" });
testTokenize1("ya boi", new String[] { "ya", "boi" });
// Should handle these trivially. Single quotes not special.
testTokenize1("'''' ''' ' '''", new String[] { "''''", "'''", "'", "'''" });
testTokenize1("*^@^$/><::;''", new String[] { "*^@^$/><::;''" });
testTokenize1("*^@^$/> <::;''", new String[] { "*^@^$/>", "<::;''" });
testTokenize1("this is not quoted, \"this is\"", new String[] { "this", "is", "not", "quoted,", "this is" });
testTokenize1("this is not quoted, \"this is", null);
/*
* testTokenize1("this is not quoted, \\\"this is", new String[]{"this", "is",
* "not", "quoted,", "\"this is"});
*/
}
private void testTokenize1(String payload, String[] expResult) {
System.out.println("tokenize for payload " + payload);
String[] result = Priestess.tokenize(payload);
if (expResult == null && result == null) {
return;
} else if (result == null && expResult != null) {
fail("Tokenize() returned null array");
}
for (int i = 0; i < Math.max(expResult.length, result.length); i++) {
String a = "<nothing>";
String b = "<nothing>";
if (expResult.length > i) {
a = expResult[i];
}
if (result.length > i) {
b = result[i];
}
System.out.println(String.format("\te: %s r: %s", a, b));
}
assertArrayEquals(expResult, result);
}
} }