Compare commits
2 Commits
4bbcbcf290
...
eb4d64d189
Author | SHA1 | Date | |
---|---|---|---|
eb4d64d189 | |||
dc9ac7eddd |
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,4 +6,5 @@ dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.classpath
|
||||
.project
|
||||
.bin/
|
||||
.settings/
|
||||
|
207
pom.xml
207
pom.xml
@ -1,98 +1,113 @@
|
||||
<?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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.tinyplantnews.priestess</groupId>
|
||||
<artifactId>Priestess</artifactId>
|
||||
<name>Priestesss of the Bean Goose Cult</name>
|
||||
<version>0.2</version>
|
||||
<packaging>jar</packaging>
|
||||
<scm>
|
||||
<connection>scm:git:https://tinyplantnews.com/git/Priestess.git</connection>
|
||||
<developerConnection>scm:git:https://twi@10.0.0.1:/srv/git/Priestess.git</developerConnection>
|
||||
</scm>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>buildnumber-maven-plugin</artifactId>
|
||||
<version>1.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>buildnumber</id>
|
||||
<phase>validate</phase>
|
||||
<goals>
|
||||
<goal>create</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<format>{0,number}</format>
|
||||
<items>
|
||||
<item>buildNumber</item>
|
||||
</items>
|
||||
<doCheck>false</doCheck>
|
||||
<doUpdate>false</doUpdate>
|
||||
<revisionOnScmFailure>unknownbuild</revisionOnScmFailure>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>com.tinyplantnews.priestess.Priestess</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<finalName>${project.artifactId}-${project.version}.${buildNumber}</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/java/com/tinyplantnews/priestess/version</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.discord4j</groupId>
|
||||
<artifactId>discord4j-core</artifactId>
|
||||
<version>3.2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.6.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>5.6.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.6.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>18</maven.compiler.source>
|
||||
<maven.compiler.target>18</maven.compiler.target>
|
||||
<exec.mainClass>com.tinyplantnews.priestess.Priestess</exec.mainClass>
|
||||
</properties>
|
||||
<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>
|
||||
<groupId>com.tinyplantnews.priestess</groupId>
|
||||
<artifactId>Priestess</artifactId>
|
||||
<name>Priestesss of the Bean Goose Cult</name>
|
||||
<version>0.2</version>
|
||||
<packaging>jar</packaging>
|
||||
<scm>
|
||||
<connection>scm:git:https://tinyplantnews.com/git/Priestess.git</connection>
|
||||
<developerConnection>scm:git:https://twi@10.0.0.1:/srv/git/Priestess.git</developerConnection>
|
||||
</scm>
|
||||
<build>
|
||||
<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>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>buildnumber-maven-plugin</artifactId>
|
||||
<version>1.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>buildnumber</id>
|
||||
<phase>validate</phase>
|
||||
<goals>
|
||||
<goal>create</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<format>{0,number}</format>
|
||||
<items>
|
||||
<item>buildNumber</item>
|
||||
</items>
|
||||
<doCheck>false</doCheck>
|
||||
<doUpdate>false</doUpdate>
|
||||
<revisionOnScmFailure>unknownbuild</revisionOnScmFailure>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>
|
||||
com.tinyplantnews.priestess.Priestess</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<finalName>${project.artifactId}-${project.version}.${buildNumber}</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/java/com/tinyplantnews/priestess/version</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.discord4j</groupId>
|
||||
<artifactId>discord4j-core</artifactId>
|
||||
<version>3.2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.6.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>5.6.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.6.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>18</maven.compiler.source>
|
||||
<maven.compiler.target>18</maven.compiler.target>
|
||||
<exec.mainClass>com.tinyplantnews.priestess.Priestess</exec.mainClass>
|
||||
</properties>
|
||||
</project>
|
||||
|
@ -37,7 +37,7 @@ public class Command {
|
||||
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);
|
||||
log.log(Level.FINE, "Matched command " + s);
|
||||
switch (commands.get(s).tryExecuteCommand(commandline, permissionLevel, m)) {
|
||||
case SUCCESS:
|
||||
return;
|
||||
@ -123,7 +123,7 @@ public class Command {
|
||||
public String getHelp() {
|
||||
return callback.getHelp(this.name);
|
||||
}
|
||||
|
||||
|
||||
public static Command commandThatJustRepliesWith(String name, String reply) {
|
||||
Command c = new Command(name, 1);
|
||||
c.setCallback(new Callback() {
|
||||
|
@ -31,47 +31,23 @@ import java.util.prefs.Preferences;
|
||||
|
||||
/**
|
||||
* "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
|
||||
*/
|
||||
public class Configuration {
|
||||
|
||||
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 Properties props = System.getProperties();
|
||||
public static final Preferences prefs = Preferences.userNodeForPackage(Configuration.class);
|
||||
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());
|
||||
|
||||
public static String findConfigurationFilePath() {
|
||||
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);
|
||||
private static String findOrCreateConfigurationFile() {
|
||||
JOptionPane.showConfirmDialog(null, "Select where cult files will be stored.");
|
||||
JFileChooser jfc = new JFileChooser("Config File for Discord Cult Priestess");
|
||||
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
@ -80,8 +56,14 @@ public class Configuration {
|
||||
while (!approved) {
|
||||
rv = jfc.showDialog(null, "Select");
|
||||
if (rv == JFileChooser.APPROVE_OPTION) {
|
||||
File f = jfc.getSelectedFile();
|
||||
if (f.isDirectory() && f.canRead() && f.canWrite()) {
|
||||
File f = resolveDirectoryToConfigFile(jfc.getSelectedFile());
|
||||
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();
|
||||
}
|
||||
} else if (rv == JFileChooser.CANCEL_OPTION) {
|
||||
@ -92,33 +74,128 @@ public class Configuration {
|
||||
return "";
|
||||
}
|
||||
|
||||
private static final String delimiter = ": ";
|
||||
|
||||
public static void getConfigurationFromFile() {
|
||||
if (CONFIG_FILE_LOCATION == null) {
|
||||
setConfigurationFilePath();
|
||||
public static Path findFileInConfigurationDirectory(Path a, Path p) {
|
||||
a = a.normalize();
|
||||
Path p1 = a.resolveSibling(p);
|
||||
log.log(Level.INFO, "Resolving {0} against {1} to get {2}", new Object[] { p, a, p1 });
|
||||
if (p1.normalize().startsWith(a.getParent())) {
|
||||
return p1;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
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()));
|
||||
}
|
||||
|
||||
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) -> {
|
||||
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 {
|
||||
String value = s.substring(s.indexOf(delimiter) + delimiter.length());
|
||||
configuration.put(key, value);
|
||||
}
|
||||
sb.append(s);
|
||||
});
|
||||
v = sb.toString();
|
||||
} catch (FileNotFoundException ex) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public static Path pathCONFIG_FILE_LOCATION() {
|
||||
return Paths.get(CONFIG_FILE_LOCATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aCONFIG_FILE_LOCATION the CONFIG_FILE_LOCATION to set
|
||||
*/
|
||||
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) {
|
||||
props.setProperty(CONFIG_FILE_KEY, CONFIG_FILE_LOCATION);
|
||||
prefs.put(CONFIG_FILE_KEY, CONFIG_FILE_LOCATION);
|
||||
try {
|
||||
prefs.flush();
|
||||
@ -147,25 +227,28 @@ public class Configuration {
|
||||
|
||||
}
|
||||
|
||||
public static void setConfigurationParameter(String key, String value) {
|
||||
configuration.put(key, value);
|
||||
public static void setConfigurationParameter(String key, String value) throws FileNotFoundException {
|
||||
configuration.put(key, new StringOrIndirect(value, null));
|
||||
}
|
||||
|
||||
public static String getConfigurationParameter(String key) {
|
||||
if (configuration.containsKey(key)) {
|
||||
return configuration.get(key);
|
||||
return configuration.get(key).value;
|
||||
} else {
|
||||
configuration.put(key, "");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static void commitConfigurationToFile() {
|
||||
commitConfigurationToFile(Paths.get(getCONFIG_FILE_LOCATION()));
|
||||
}
|
||||
|
||||
public static void commitConfigurationToFile(Path p) {
|
||||
Path bkupPath = Paths.get(p.toString() + "bkup");
|
||||
try {
|
||||
Files.deleteIfExists(Paths.get(CONFIG_FILE_LOCATION + "bkup"));
|
||||
Files.deleteIfExists(bkupPath);
|
||||
try {
|
||||
Files.copy(Paths.get(CONFIG_FILE_LOCATION), Paths.get(CONFIG_FILE_LOCATION + "bkup"));
|
||||
Files.copy(p, bkupPath);
|
||||
} catch (IOException ioe) {
|
||||
if (ioe instanceof NoSuchFileException) {
|
||||
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");
|
||||
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) -> {
|
||||
try {
|
||||
br.append(key + delimiter + value + "\n");
|
||||
br.append(key + delimiter + value.toRecord(f) + "\n");
|
||||
} catch (IOException 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,11 +19,14 @@ 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.
|
||||
* 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,
|
||||
* 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
|
||||
@ -42,15 +45,30 @@ public class MessageStore {
|
||||
private boolean messagesCached = false;
|
||||
private long loadStart = Long.MAX_VALUE;
|
||||
|
||||
public MessageStore(File f1) throws FileNotFoundException, IOException {
|
||||
loadStart = System.nanoTime();
|
||||
f = new RandomAccessFile(f1.getPath(), "r");
|
||||
System.out.println("Message store is " + f.length() + " bytes long");
|
||||
fr = f.getChannel();
|
||||
filelength = f.length();
|
||||
mc = new MessageCacher();
|
||||
t = new Thread(mc);
|
||||
t.start();
|
||||
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();
|
||||
f = new RandomAccessFile(f1.getPath(), "r");
|
||||
log.log(Level.FINE, "Message store is {0} bytes long", f.length());
|
||||
fr = f.getChannel();
|
||||
filelength = f.length();
|
||||
mc = new MessageCacher();
|
||||
t = new Thread(mc);
|
||||
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) {
|
||||
@ -83,6 +101,9 @@ public class MessageStore {
|
||||
}
|
||||
|
||||
public String randomMessage() {
|
||||
if (messagestarts == null || messagestarts.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return messageAt((int) (messagestarts.length * Math.random()));
|
||||
}
|
||||
|
||||
@ -135,7 +156,7 @@ public class MessageStore {
|
||||
messagestarts[i] = messagestarts1[i].intValue();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(MessageStore.class.getName()).log(Level.SEVERE, null, ex);
|
||||
log.log(Level.SEVERE, null, ex);
|
||||
}
|
||||
for (int i : messagestarts) {
|
||||
System.out.println("Found invocation message at position " + i);
|
||||
|
@ -22,8 +22,11 @@ import discord4j.core.object.presence.ClientPresence;
|
||||
import discord4j.core.object.presence.Status;
|
||||
import discord4j.core.object.reaction.ReactionEmoji;
|
||||
import discord4j.core.spec.MessageCreateSpec;
|
||||
import discord4j.discordjson.json.ApplicationCommandRequest;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Paths;
|
||||
@ -87,7 +90,7 @@ public class Priestess {
|
||||
public static final String MESSAGES = "messages";
|
||||
public static final String TESTSUITE = "testsuite";
|
||||
|
||||
private MessageStore ms = null;
|
||||
private MessageStore ms = new MessageStore(null);
|
||||
|
||||
public static final String DEBUG_LEVEL = "debug_level";
|
||||
|
||||
@ -130,12 +133,21 @@ public class Priestess {
|
||||
break;
|
||||
case "debug-level":
|
||||
String newlevel = args[i].substring(args[i].indexOf('=') + 1);
|
||||
Configuration.setConfigurationParameter(DEBUG_LEVEL, newlevel);
|
||||
try {
|
||||
Configuration.setConfigurationParameter(DEBUG_LEVEL, newlevel);
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
log.log(Level.SEVERE, "Could not resolve debug level from given file? {0}", fnfe);
|
||||
}
|
||||
trySetDebugLevel(newlevel);
|
||||
i++;
|
||||
break;
|
||||
case "debug":
|
||||
Configuration.setConfigurationParameter(DEBUG_LEVEL, Level.ALL.toString());
|
||||
try {
|
||||
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);
|
||||
i++;
|
||||
break;
|
||||
@ -248,6 +260,14 @@ public class Priestess {
|
||||
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 String randomLetter() {
|
||||
@ -266,6 +286,8 @@ public class Priestess {
|
||||
if (botToken.isBlank()) {
|
||||
log.log(Level.SEVERE, "bot token is null. aborting.");
|
||||
return;
|
||||
} else {
|
||||
log.log(Level.FINE, "bot token set.");
|
||||
}
|
||||
SysInListener sil = new SysInListener();
|
||||
Thread t = new Thread(sil);
|
||||
@ -327,20 +349,32 @@ public class Priestess {
|
||||
dc.on(ChatInputInteractionEvent.class).flatMap(event -> {
|
||||
return event.reply().withContent("agreed");
|
||||
}).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())
|
||||
.filter(g -> !g.getGuild().blockOptional().isEmpty()).flatMap(guildedmessagehandler).subscribe();
|
||||
|
||||
dc.on(MessageCreateEvent.class).filter(event -> !event.getMessage().getAuthor().get().isBot())
|
||||
.filter(g -> g.getGuild().blockOptional().isEmpty()).flatMap(directmessagehandler).blockLast();
|
||||
/* .filter(g -> g.getGuild().blockOptional().isEmpty()) */.flatMap(messagehandler).blockLast();
|
||||
}
|
||||
}
|
||||
|
||||
private int invocationsBeforeThisSession = 0;
|
||||
|
||||
private void setup() {
|
||||
Configuration.findConfigurationFilePath();
|
||||
Configuration.getConfigurationFromFile();
|
||||
Configuration.findAndReadConfigurationFile();
|
||||
|
||||
botToken = Configuration.getConfigurationParameter(TOKEN_KEY);
|
||||
|
||||
@ -380,7 +414,9 @@ public class Priestess {
|
||||
|
||||
private void shutdown() {
|
||||
replcontinue = false;
|
||||
dc.logout().subscribe();
|
||||
if (dc != null) {
|
||||
dc.logout().subscribe();
|
||||
}
|
||||
System.out.println("Logged out");
|
||||
try {
|
||||
user_reader.close();
|
||||
@ -392,10 +428,13 @@ public class Priestess {
|
||||
}
|
||||
|
||||
int invocationsTotal = invocationsBeforeThisSession + invocationsThisSession;
|
||||
System.out.println("Bean Goose has been invoked " + invocationsTotal + " times so far.");
|
||||
Configuration.setConfigurationParameter(INVOCATIONS_KEY, Integer.toString(invocationsTotal));
|
||||
log.log(Level.INFO, "Bean Goose has been invoked " + invocationsTotal + " times so far.");
|
||||
try {
|
||||
Configuration.setConfigurationParameter(INVOCATIONS_KEY, Integer.toString(invocationsTotal));
|
||||
} catch (FileNotFoundException e) {
|
||||
}
|
||||
Configuration.commitConfigurationToFile();
|
||||
System.out.println("Configuration committed to file.");
|
||||
log.log(Level.INFO, "Configuration committed to file.");
|
||||
}
|
||||
|
||||
private void invokeDeity(Guild g, Message m) {
|
||||
@ -420,7 +459,7 @@ public class Priestess {
|
||||
|
||||
private int resolveAuthorPermissionLevel(MessageCreateEvent t, Message m) {
|
||||
int level = 0;
|
||||
Optional gio = t.getGuildId();
|
||||
Optional<Snowflake> gio = t.getGuildId();
|
||||
if (gio.isPresent()) {
|
||||
Member a = m.getAuthorAsMember().block();
|
||||
for (Snowflake snowflake : (Snowflake[]) a.getRoleIds().toArray(new Snowflake[3])) {
|
||||
@ -454,7 +493,7 @@ public class Priestess {
|
||||
if (ao.isPresent()) {
|
||||
for (String s1 : s.split(" ")) {
|
||||
if (s1.equals(ao.get().getId().asString())) {
|
||||
System.out.println("Literally catluck detected.");
|
||||
log.log(Level.FINE, "Literally catluck detected.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -510,18 +549,8 @@ public class Priestess {
|
||||
*/
|
||||
private MessageStore setupMessageStore() {
|
||||
String mesglist = Configuration.getConfigurationParameter(MESSAGES);
|
||||
File f = Paths.get(mesglist).toFile();
|
||||
try {
|
||||
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;
|
||||
File f = new File(mesglist);
|
||||
return new MessageStore(f);
|
||||
}
|
||||
|
||||
private void reloadMessageStore() {
|
||||
@ -614,17 +643,31 @@ public class Priestess {
|
||||
String[] usages = { "Undefined command 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
|
||||
public Publisher<Mono> apply(CommandArgs t) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public String getHelp(String commandName) {
|
||||
String s = getUsage(commandName);
|
||||
return help/* .replaceAll("\\$\\{usage\\}", s) */.replaceAll("\\$\\{commandname\\}", commandName);
|
||||
String s = getUsage(commandName, usages);
|
||||
return help.replaceAll("\\$\\{usage\\}", s).replaceAll("\\$\\{commandname\\}", commandName);
|
||||
}
|
||||
|
||||
public String getUsage(String commandName) {
|
||||
public String getUsage(String commandName, String[] usages) {
|
||||
StringBuilder u = new StringBuilder();
|
||||
for (int i = 0; i < usages.length; i++) {
|
||||
String s = usages[i];
|
||||
@ -639,10 +682,8 @@ public class Priestess {
|
||||
|
||||
}
|
||||
|
||||
public final Callback registerEmojiCommand = new Callback() {
|
||||
|
||||
String usage = "{commandname} EMOJI";
|
||||
String help = "register emoji for use in basic invocations." + "" + "" + "" + "";
|
||||
public final Callback registerEmojiCommand = new Callback(new String[] { "${commandname} EMOJI" },
|
||||
"register emoji for use in basic invocations.") {
|
||||
|
||||
@Override
|
||||
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
|
||||
public Publisher<Mono> apply(CommandArgs o) {
|
||||
System.out.println("Committing configuration to file.");
|
||||
@ -709,7 +751,11 @@ public class Priestess {
|
||||
String[] paytokens = tokenize(pay2);
|
||||
if (paytokens.length == 2) {
|
||||
log.log(Level.INFO, "setting configuration parameter " + paytokens[0] + " to " + paytokens[1]);
|
||||
Configuration.setConfigurationParameter(paytokens[0], paytokens[1]);
|
||||
try {
|
||||
Configuration.setConfigurationParameter(paytokens[0], paytokens[1]);
|
||||
} catch (FileNotFoundException e) {
|
||||
o.replyWith("");
|
||||
}
|
||||
} else {
|
||||
log.log(Level.INFO, "Invalid argument count for set configuration parameter command");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user