Compare commits

...

2 Commits

Author SHA1 Message Date
eb4d64d189 Fixed message store. Enabled writing indirect configuration values to files. 2024-10-05 15:20:55 -07:00
dc9ac7eddd Added an example chat input interaction (/bean).
Streamlined the messagehandler functions

Changed the callback help/usage paradigm to use something that may actually work (I don't know whether it does)

Rationalized the way that configuration files are located and loaded, guarded against TOCTOU
2024-10-05 11:45:41 -07:00
6 changed files with 458 additions and 208 deletions

1
.gitignore vendored
View File

@ -6,4 +6,5 @@ dependency-reduced-pom.xml
buildNumber.properties buildNumber.properties
.classpath .classpath
.project .project
.bin/
.settings/ .settings/

21
pom.xml
View File

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.tinyplantnews.priestess</groupId> <groupId>com.tinyplantnews.priestess</groupId>
<artifactId>Priestess</artifactId> <artifactId>Priestess</artifactId>
@ -12,6 +14,17 @@
</scm> </scm>
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.4.1</version>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.tinyplantnews.priestess.Priestess</mainClass>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId> <artifactId>buildnumber-maven-plugin</artifactId>
@ -47,8 +60,10 @@
</goals> </goals>
<configuration> <configuration>
<transformers> <transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <transformer
<mainClass>com.tinyplantnews.priestess.Priestess</mainClass> implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>
com.tinyplantnews.priestess.Priestess</mainClass>
</transformer> </transformer>
</transformers> </transformers>
</configuration> </configuration>

View File

@ -37,7 +37,7 @@ public class Command {
static void tryAll(String commandline, Message m, int permissionLevel) { static void tryAll(String commandline, Message m, int permissionLevel) {
for (String s : commands.keySet()) { for (String s : commands.keySet()) {
if (commandline.startsWith(s)) { if (commandline.startsWith(s)) {
log.log(Level.INFO, "Matched command " + s); log.log(Level.FINE, "Matched command " + s);
switch (commands.get(s).tryExecuteCommand(commandline, permissionLevel, m)) { switch (commands.get(s).tryExecuteCommand(commandline, permissionLevel, m)) {
case SUCCESS: case SUCCESS:
return; return;

View File

@ -31,47 +31,23 @@ import java.util.prefs.Preferences;
/** /**
* "Ms Merry," you may say, "You literally import the Preferences class, and yet * "Ms Merry," you may say, "You literally import the Preferences class, and yet
* you insist on writing your own configuration store. Why?" "Iunno," I reply. * you insist on writing your own configuration store. Why?" I reply, "Iunno."
* *
* @author sandy * @author sandy
*/ */
public class Configuration { public class Configuration {
private static String CONFIG_FILE_LOCATION = null; private static String CONFIG_FILE_LOCATION = null;
private static Path WORKING_DIR = 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 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, StringOrIndirect> 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() { private static String findOrCreateConfigurationFile() {
if (getCONFIG_FILE_LOCATION() != null) {
return getCONFIG_FILE_LOCATION();
}
setCONFIG_FILE_LOCATION(setConfigurationFilePath(), false);
return getCONFIG_FILE_LOCATION();
}
private static String setConfigurationFilePath() {
String s = System.getenv(CONFIG_FILE_KEY);
if (s != null && !s.isBlank()) {
return s;
} else if (props.containsKey(CONFIG_FILE_KEY)) {
return props.getProperty(CONFIG_FILE_KEY);
}
s = prefs.get(CONFIG_FILE_KEY, "");
if (s != null && !s.isBlank()) {
return s;
}
if (Files.exists(Paths.get(DEFAULT_CONFIG_FILE_NAME), LinkOption.NOFOLLOW_LINKS)) {
return DEFAULT_CONFIG_FILE_NAME;
}
// JDialog jd = new JDialog();
// jd.add(new JLabel("Choose where to put Priestess Working Directory"));
// 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);
@ -80,8 +56,14 @@ public class Configuration {
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 = resolveDirectoryToConfigFile(jfc.getSelectedFile());
if (f.isDirectory() && f.canRead() && f.canWrite()) { if (f.canRead() && f.canWrite()) {
prefs.put(CONFIG_FILE_KEY, f.getAbsolutePath());
try {
prefs.flush();
} catch (BackingStoreException e) {
log.log(Level.WARNING, "Failed to flush preferences to backing store");
}
return f.getAbsolutePath(); return f.getAbsolutePath();
} }
} else if (rv == JFileChooser.CANCEL_OPTION) { } else if (rv == JFileChooser.CANCEL_OPTION) {
@ -92,33 +74,128 @@ public class Configuration {
return ""; return "";
} }
private static final String delimiter = ": "; public static Path findFileInConfigurationDirectory(Path a, Path p) {
a = a.normalize();
public static void getConfigurationFromFile() { Path p1 = a.resolveSibling(p);
if (CONFIG_FILE_LOCATION == null) { log.log(Level.INFO, "Resolving {0} against {1} to get {2}", new Object[] { p, a, p1 });
setConfigurationFilePath(); if (p1.normalize().startsWith(a.getParent())) {
} return p1;
try {
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;
}
BufferedReader br = new BufferedReader(new FileReader(Paths.get(CONFIG_FILE_LOCATION).toFile()));
br.lines().forEach((s) -> {
String key = s.substring(0, s.indexOf(delimiter));
if (s.length() == s.indexOf(delimiter) + delimiter.length()) {
log.log(Level.FINE, "read empty value for key (" + key + ") from configuration file");
configuration.put(key, "");
} else { } else {
String value = s.substring(s.indexOf(delimiter) + delimiter.length()); return null;
configuration.put(key, value);
} }
}
public static Path findFileInConfigurationDirectory(Path p) {
return findFileInConfigurationDirectory(pathCONFIG_FILE_LOCATION(), p);
}
public static final String FILE_MARKER = "(file)";
public static String resolveIndirectConfigurationValue(String v, File configfile) throws FileNotFoundException {
if (configfile == null) {
throw new FileNotFoundException(
String.format("Could not resolve indirect value {0} against configuration file {1}",
new Object[] { v, configfile }));
}
log.log(Level.INFO, "Index of <" + FILE_MARKER + "> in <" + v + "> is " + v.indexOf(FILE_MARKER));
String relpath;
if (v.contains(FILE_MARKER)) {
relpath = v.substring(v.indexOf(FILE_MARKER) + FILE_MARKER.length());
} else {
relpath = v;
}
relpath = relpath.trim();
Path indirectValuePath = findFileInConfigurationDirectory(configfile.toPath(), Paths.get(relpath));
try (BufferedReader br = new BufferedReader(new FileReader(indirectValuePath.toFile()));) {
final StringBuilder sb = new StringBuilder();
br.lines().forEach((s) -> {
sb.append(s);
}); });
v = sb.toString();
} catch (FileNotFoundException ex) { } catch (FileNotFoundException ex) {
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE,
"Error loading configuration file from (" + CONFIG_FILE_LOCATION + ") {0}", ex); "Error loading indirect configuration value from (" + indirectValuePath.toString() + ") {0}", ex);
} catch (IOException e) {
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE,
"Error loading indirect configuration value from (" + indirectValuePath.toString() + ") {0}", e);
} }
return v;
}
private static final String delimiter = ": ";
/**
* If given file is a directory, look for the default configuration filename in
* the given directory
*
* @param f The configuration file, or a directory containing the default one.
* @return
*/
private static File resolveDirectoryToConfigFile(File f) {
if (f.isDirectory()) {
f = Paths.get(f.getPath(), Configuration.DEFAULT_CONFIG_FILE_NAME).toFile();
try {
if (f.createNewFile()) {
log.log(Level.INFO, "Creating new configuration file in provided directory.");
} else {
log.log(Level.FINEST, "Using default-named configuration file in provided directory.");
}
} catch (IOException e) {
log.log(Level.SEVERE, "Could not create a configuration file in the specified directory {0}: {1}",
new Object[] { f, e.toString() });
}
}
return f;
}
/**
*
*/
private static boolean readConfigurationFromFile(String path) throws IOException {
if (path == null || path.isBlank()) {
return false;
}
File f = resolveDirectoryToConfigFile(new File(path));
try (BufferedReader br = new BufferedReader(new FileReader(f))) {
br.lines().forEach((s) -> {
String key = s.substring(0, s.indexOf(delimiter));
try {
configuration.put(key, new StringOrIndirect(s, f));
} catch (FileNotFoundException fnfe) {
log.log(Level.SEVERE,
"Unable to resolve indirect configuration value against configuration directory."
+ "This should never occur? {0}",
fnfe);
}
});
setCONFIG_FILE_LOCATION(f.toString(), true);
return true;
} catch (FileNotFoundException fnfe) {
return false;
}
}
public static void findAndReadConfigurationFile() {
try {
if (readConfigurationFromFile(System.getenv(CONFIG_FILE_KEY))) {
log.log(Level.FINE, "Using environment variable to locate configuration file");
return;
} else if (readConfigurationFromFile(prefs.get(CONFIG_FILE_KEY, ""))) {
log.log(Level.FINE, "Using package preferences to locate configuration file");
return;
} else if (readConfigurationFromFile(findOrCreateConfigurationFile())) {
log.log(Level.FINE, "Using interactive dialogue to locate configuration file");
return;
} else {
log.log(Level.WARNING, "Could not resolve a configuration file path, using defaults.");
}
} catch (IOException ioe) {
log.log(Level.SEVERE, "Could not read configuration file {0}", ioe.toString());
}
} }
/** /**
@ -128,13 +205,16 @@ public class Configuration {
return CONFIG_FILE_LOCATION; return CONFIG_FILE_LOCATION;
} }
public static Path pathCONFIG_FILE_LOCATION() {
return Paths.get(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 = resolveDirectoryToConfigFile(new File(aCONFIG_FILE_LOCATION)).getAbsolutePath();
if (persistent) { if (persistent) {
props.setProperty(CONFIG_FILE_KEY, CONFIG_FILE_LOCATION);
prefs.put(CONFIG_FILE_KEY, CONFIG_FILE_LOCATION); prefs.put(CONFIG_FILE_KEY, CONFIG_FILE_LOCATION);
try { try {
prefs.flush(); prefs.flush();
@ -147,25 +227,28 @@ public class Configuration {
} }
public static void setConfigurationParameter(String key, String value) { public static void setConfigurationParameter(String key, String value) throws FileNotFoundException {
configuration.put(key, value); configuration.put(key, new StringOrIndirect(value, null));
} }
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).value;
} else { } else {
configuration.put(key, "");
return ""; return "";
} }
} }
public static void commitConfigurationToFile() { public static void commitConfigurationToFile() {
commitConfigurationToFile(Paths.get(getCONFIG_FILE_LOCATION()));
}
public static void commitConfigurationToFile(Path p) {
Path bkupPath = Paths.get(p.toString() + "bkup");
try { try {
Files.deleteIfExists(Paths.get(CONFIG_FILE_LOCATION + "bkup")); Files.deleteIfExists(bkupPath);
try { try {
Files.copy(Paths.get(CONFIG_FILE_LOCATION), Paths.get(CONFIG_FILE_LOCATION + "bkup")); Files.copy(p, bkupPath);
} 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");
@ -180,10 +263,12 @@ public class Configuration {
"Making backup configuration file failed. Exiting without committing configuration to file"); "Making backup configuration file failed. Exiting without committing configuration to file");
return; return;
} }
try (BufferedWriter br = new BufferedWriter(new FileWriter(Paths.get(CONFIG_FILE_LOCATION).toFile(), false))) { File f = resolveDirectoryToConfigFile(p.toFile());
log.log(Level.FINE, "Committing configuration to {0}", p.toString());
try (BufferedWriter br = new BufferedWriter(new FileWriter(f, false))) {
configuration.forEach((key, value) -> { configuration.forEach((key, value) -> {
try { try {
br.append(key + delimiter + value + "\n"); br.append(key + delimiter + value.toRecord(f) + "\n");
} 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);
} }
@ -234,4 +319,86 @@ public class Configuration {
} }
} }
public static class StringOrIndirect {
public String value;
public String path;
public StringOrIndirect() {
value = "";
}
public StringOrIndirect(String source, File configfile) throws FileNotFoundException {
if (configfile == null) {
Path p = pathCONFIG_FILE_LOCATION();
if (p != null) {
configfile = p.toFile();
} else {
configfile = null;
}
}
if (source.contains(delimiter)) {
if (source.length() == source.indexOf(delimiter) + delimiter.length()) {
String key = source.substring(0, source.indexOf(delimiter));
log.log(Level.FINE, "read empty value for key (" + key + ") from configuration file");
value = "";
} else {
}
source = source.substring(source.indexOf(delimiter) + delimiter.length());
}
// After this point the 'source' string should only contain an immediate value
// or a (file) abc.xyz record
if (source.contains(FILE_MARKER)) {
path = source.substring(source.indexOf(FILE_MARKER) + FILE_MARKER.length()).trim();
value = resolveIndirectConfigurationValue(source, configfile);
} else {
value = source;
}
}
private boolean immediate() {
return path == null;
}
/**
* Converts this to a record in a configuration file. If indirect, commits its
* value to the indirect file.
*
* @return
*/
public String toRecord(File f) {
if (immediate()) {
return value;
} else {
try (BufferedWriter br = new BufferedWriter(new FileWriter(
findFileInConfigurationDirectory(f.toPath(), Paths.get(path)).toFile(), false))) {
br.append(value);
br.flush();
br.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Configuration.class.getName()).log(Level.SEVERE, null, ex);
}
return FILE_MARKER + path;
}
}
@Override
public String toString() {
return value;
}
public String toDebugString() {
if (immediate()) {
return String.format("StringOrIndirect ({0})", value);
} else {
return String.format("StringOrIndirect from {1}: ({0})", value, path);
}
}
}
} }

View File

@ -19,11 +19,14 @@ import java.util.logging.Logger;
/** /**
* OH IT STORES THE PROPHECIES * 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 configuration file (priestessconfig.txt) contains a key, 'messages', for
* The messages store contains prophecies that are given every few bean goose invocations. * which the value is a path to the messages store. The messages store contains
* This class first loads the file, scans it and generates a list of indices for the messages it 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, * 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 * but I'm not up to writing that today - 7 May 2023
* *
* @author atomb * @author atomb
@ -42,15 +45,30 @@ public class MessageStore {
private boolean messagesCached = false; private boolean messagesCached = false;
private long loadStart = Long.MAX_VALUE; private long loadStart = Long.MAX_VALUE;
public MessageStore(File f1) throws FileNotFoundException, IOException { private Logger log = Logger.getLogger(MessageStore.class.getName());
public MessageStore(File f1) {
log.log(Level.INFO, "loading message store from {0}", f1);
if (f1 == null) {
log.log(Level.WARNING, "Message store not given, initializing blank one");
messagestarts = new int[] {};
} else {
try {
f1 = Configuration.findFileInConfigurationDirectory(f1.toPath()).toFile();
loadStart = System.nanoTime(); loadStart = System.nanoTime();
f = new RandomAccessFile(f1.getPath(), "r"); f = new RandomAccessFile(f1.getPath(), "r");
System.out.println("Message store is " + f.length() + " bytes long"); log.log(Level.FINE, "Message store is {0} bytes long", f.length());
fr = f.getChannel(); fr = f.getChannel();
filelength = f.length(); filelength = f.length();
mc = new MessageCacher(); mc = new MessageCacher();
t = new Thread(mc); t = new Thread(mc);
t.start(); t.start();
log.log(Level.FINE, "Loading message store at {0}", f);
} catch (IOException fnfe) {
log.log(Level.WARNING, "Unable to open message store, initializing blank one {0}", fnfe);
messagestarts = new int[] {};
}
}
} }
public String messageAt(int i) { public String messageAt(int i) {
@ -83,6 +101,9 @@ public class MessageStore {
} }
public String randomMessage() { public String randomMessage() {
if (messagestarts == null || messagestarts.length == 0) {
return null;
}
return messageAt((int) (messagestarts.length * Math.random())); return messageAt((int) (messagestarts.length * Math.random()));
} }
@ -135,7 +156,7 @@ public class MessageStore {
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); log.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);

View File

@ -22,8 +22,11 @@ import discord4j.core.object.presence.ClientPresence;
import discord4j.core.object.presence.Status; import discord4j.core.object.presence.Status;
import discord4j.core.object.reaction.ReactionEmoji; import discord4j.core.object.reaction.ReactionEmoji;
import discord4j.core.spec.MessageCreateSpec; import discord4j.core.spec.MessageCreateSpec;
import discord4j.discordjson.json.ApplicationCommandRequest;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.file.Paths; import java.nio.file.Paths;
@ -87,7 +90,7 @@ public class Priestess {
public static final String MESSAGES = "messages"; public static final String MESSAGES = "messages";
public static final String TESTSUITE = "testsuite"; public static final String TESTSUITE = "testsuite";
private MessageStore ms = null; private MessageStore ms = new MessageStore(null);
public static final String DEBUG_LEVEL = "debug_level"; public static final String DEBUG_LEVEL = "debug_level";
@ -130,12 +133,21 @@ public class Priestess {
break; break;
case "debug-level": case "debug-level":
String newlevel = args[i].substring(args[i].indexOf('=') + 1); String newlevel = args[i].substring(args[i].indexOf('=') + 1);
try {
Configuration.setConfigurationParameter(DEBUG_LEVEL, newlevel); Configuration.setConfigurationParameter(DEBUG_LEVEL, newlevel);
} catch (FileNotFoundException fnfe) {
log.log(Level.SEVERE, "Could not resolve debug level from given file? {0}", fnfe);
}
trySetDebugLevel(newlevel); trySetDebugLevel(newlevel);
i++; i++;
break; break;
case "debug": case "debug":
try {
Configuration.setConfigurationParameter(DEBUG_LEVEL, Level.ALL.toString()); Configuration.setConfigurationParameter(DEBUG_LEVEL, Level.ALL.toString());
} catch (FileNotFoundException fnfe) {
log.log(Level.SEVERE,
"Could not resolve debug level from given file? This should never happen. {0}", fnfe);
}
trySetDebugLevel(yarg); trySetDebugLevel(yarg);
i++; i++;
break; break;
@ -248,6 +260,14 @@ public class Priestess {
return Mono.empty(); return Mono.empty();
}; };
Function<MessageCreateEvent, Publisher<Mono>> messagehandler = (MessageCreateEvent t) -> {
if (t.getGuild().blockOptional().isEmpty()) {
return directmessagehandler.apply(t);
} else {
return guildedmessagehandler.apply(t);
}
};
private static final String alphabet = "abcdefghijklmnopqrstuvwxyz"; private static final String alphabet = "abcdefghijklmnopqrstuvwxyz";
private String randomLetter() { private String randomLetter() {
@ -266,6 +286,8 @@ public class Priestess {
if (botToken.isBlank()) { if (botToken.isBlank()) {
log.log(Level.SEVERE, "bot token is null. aborting."); log.log(Level.SEVERE, "bot token is null. aborting.");
return; return;
} else {
log.log(Level.FINE, "bot token set.");
} }
SysInListener sil = new SysInListener(); SysInListener sil = new SysInListener();
Thread t = new Thread(sil); Thread t = new Thread(sil);
@ -327,20 +349,32 @@ public class Priestess {
dc.on(ChatInputInteractionEvent.class).flatMap(event -> { dc.on(ChatInputInteractionEvent.class).flatMap(event -> {
return event.reply().withContent("agreed"); return event.reply().withContent("agreed");
}).subscribe(); }).subscribe();
long applicationId = dc.getRestClient().getApplicationId().block();
ApplicationCommandRequest acr = ApplicationCommandRequest.builder().name("bean").description("beans")
.build();
dc.getGuilds().flatMap((g) -> {
log.log(Level.INFO, "Registering command with server {0}", g.getName());
dc.getRestClient().getApplicationService()
.createGuildApplicationCommand(applicationId, g.getId().asLong(), acr).block();
return Mono.empty();
}).subscribe();
// dc.on(MessageCreateEvent.class).filter(event ->
// !event.getMessage().getAuthor().get().isBot())
// .filter(g ->
// !g.getGuild().blockOptional().isEmpty()).flatMap(guildedmessagehandler).subscribe();
dc.on(MessageCreateEvent.class).filter(event -> !event.getMessage().getAuthor().get().isBot()) dc.on(MessageCreateEvent.class).filter(event -> !event.getMessage().getAuthor().get().isBot())
.filter(g -> !g.getGuild().blockOptional().isEmpty()).flatMap(guildedmessagehandler).subscribe(); /* .filter(g -> g.getGuild().blockOptional().isEmpty()) */.flatMap(messagehandler).blockLast();
dc.on(MessageCreateEvent.class).filter(event -> !event.getMessage().getAuthor().get().isBot())
.filter(g -> g.getGuild().blockOptional().isEmpty()).flatMap(directmessagehandler).blockLast();
} }
} }
private int invocationsBeforeThisSession = 0; private int invocationsBeforeThisSession = 0;
private void setup() { private void setup() {
Configuration.findConfigurationFilePath(); Configuration.findAndReadConfigurationFile();
Configuration.getConfigurationFromFile();
botToken = Configuration.getConfigurationParameter(TOKEN_KEY); botToken = Configuration.getConfigurationParameter(TOKEN_KEY);
@ -380,7 +414,9 @@ public class Priestess {
private void shutdown() { private void shutdown() {
replcontinue = false; replcontinue = false;
if (dc != null) {
dc.logout().subscribe(); dc.logout().subscribe();
}
System.out.println("Logged out"); System.out.println("Logged out");
try { try {
user_reader.close(); user_reader.close();
@ -392,10 +428,13 @@ public class Priestess {
} }
int invocationsTotal = invocationsBeforeThisSession + invocationsThisSession; int invocationsTotal = invocationsBeforeThisSession + invocationsThisSession;
System.out.println("Bean Goose has been invoked " + invocationsTotal + " times so far."); log.log(Level.INFO, "Bean Goose has been invoked " + invocationsTotal + " times so far.");
try {
Configuration.setConfigurationParameter(INVOCATIONS_KEY, Integer.toString(invocationsTotal)); Configuration.setConfigurationParameter(INVOCATIONS_KEY, Integer.toString(invocationsTotal));
} catch (FileNotFoundException e) {
}
Configuration.commitConfigurationToFile(); Configuration.commitConfigurationToFile();
System.out.println("Configuration committed to file."); log.log(Level.INFO, "Configuration committed to file.");
} }
private void invokeDeity(Guild g, Message m) { private void invokeDeity(Guild g, Message m) {
@ -420,7 +459,7 @@ public class Priestess {
private int resolveAuthorPermissionLevel(MessageCreateEvent t, Message m) { private int resolveAuthorPermissionLevel(MessageCreateEvent t, Message m) {
int level = 0; int level = 0;
Optional gio = t.getGuildId(); Optional<Snowflake> gio = t.getGuildId();
if (gio.isPresent()) { if (gio.isPresent()) {
Member a = m.getAuthorAsMember().block(); Member a = m.getAuthorAsMember().block();
for (Snowflake snowflake : (Snowflake[]) a.getRoleIds().toArray(new Snowflake[3])) { for (Snowflake snowflake : (Snowflake[]) a.getRoleIds().toArray(new Snowflake[3])) {
@ -454,7 +493,7 @@ public class Priestess {
if (ao.isPresent()) { if (ao.isPresent()) {
for (String s1 : s.split(" ")) { for (String s1 : s.split(" ")) {
if (s1.equals(ao.get().getId().asString())) { if (s1.equals(ao.get().getId().asString())) {
System.out.println("Literally catluck detected."); log.log(Level.FINE, "Literally catluck detected.");
return true; return true;
} }
} }
@ -510,18 +549,8 @@ public class Priestess {
*/ */
private MessageStore setupMessageStore() { private MessageStore setupMessageStore() {
String mesglist = Configuration.getConfigurationParameter(MESSAGES); String mesglist = Configuration.getConfigurationParameter(MESSAGES);
File f = Paths.get(mesglist).toFile(); File f = new File(mesglist);
try { return new MessageStore(f);
MessageStore ms1 = new MessageStore(f);
return ms1;
} catch (IOException e) {
if (!f.exists()) {
log.log(Level.WARNING, "Message store file does not exist.");
} else {
log.log(Level.SEVERE, e.getMessage());
}
}
return null;
} }
private void reloadMessageStore() { private void reloadMessageStore() {
@ -614,17 +643,31 @@ public class Priestess {
String[] usages = { "Undefined command usage" }; String[] usages = { "Undefined command usage" };
String help = "${usage}"; String help = "${usage}";
public Callback() {
super();
}
public Callback(String[] usages1, String help1) {
super();
if (usages1 != null) {
usages = usages1;
}
if (help1 != null) {
help = help1;
}
}
@Override @Override
public Publisher<Mono> apply(CommandArgs t) { public Publisher<Mono> apply(CommandArgs t) {
throw new UnsupportedOperationException("Not supported yet."); throw new UnsupportedOperationException("Not supported yet.");
} }
public String getHelp(String commandName) { public String getHelp(String commandName) {
String s = getUsage(commandName); String s = getUsage(commandName, usages);
return help/* .replaceAll("\\$\\{usage\\}", s) */.replaceAll("\\$\\{commandname\\}", commandName); return help.replaceAll("\\$\\{usage\\}", s).replaceAll("\\$\\{commandname\\}", commandName);
} }
public String getUsage(String commandName) { public String getUsage(String commandName, String[] usages) {
StringBuilder u = new StringBuilder(); StringBuilder u = new StringBuilder();
for (int i = 0; i < usages.length; i++) { for (int i = 0; i < usages.length; i++) {
String s = usages[i]; String s = usages[i];
@ -639,10 +682,8 @@ public class Priestess {
} }
public final Callback registerEmojiCommand = new Callback() { public final Callback registerEmojiCommand = new Callback(new String[] { "${commandname} EMOJI" },
"register emoji for use in basic invocations.") {
String usage = "{commandname} EMOJI";
String help = "register emoji for use in basic invocations." + "" + "" + "" + "";
@Override @Override
public Publisher<Mono> apply(CommandArgs o) { public Publisher<Mono> apply(CommandArgs o) {
@ -675,7 +716,8 @@ public class Priestess {
} }
}; };
public final Callback commitConfigurationCommand = new Callback() { public final Callback commitConfigurationCommand = new Callback(new String[] { "${commandname}" },
"commit configuration to the configuration file.") {
@Override @Override
public Publisher<Mono> apply(CommandArgs o) { public Publisher<Mono> apply(CommandArgs o) {
System.out.println("Committing configuration to file."); System.out.println("Committing configuration to file.");
@ -709,7 +751,11 @@ public class Priestess {
String[] paytokens = tokenize(pay2); String[] paytokens = tokenize(pay2);
if (paytokens.length == 2) { if (paytokens.length == 2) {
log.log(Level.INFO, "setting configuration parameter " + paytokens[0] + " to " + paytokens[1]); log.log(Level.INFO, "setting configuration parameter " + paytokens[0] + " to " + paytokens[1]);
try {
Configuration.setConfigurationParameter(paytokens[0], paytokens[1]); Configuration.setConfigurationParameter(paytokens[0], paytokens[1]);
} catch (FileNotFoundException e) {
o.replyWith("");
}
} else { } else {
log.log(Level.INFO, "Invalid argument count for set configuration parameter command"); log.log(Level.INFO, "Invalid argument count for set configuration parameter command");
} }