mirror of
https://github.com/AsamK/signal-cli.git
synced 2026-05-25 14:24:36 +00:00
Add support for a global configuration file
This commit is contained in:
parent
393e1efcd1
commit
44d54b3215
@ -13,7 +13,7 @@ signal-cli-dbus - A commandline and dbus interface for the Signal messenger
|
||||
|
||||
== Synopsis
|
||||
|
||||
*signal-cli* [--verbose] [--config CONFIG] [-a ACCOUNT] [-o {plain-text,json}] daemon [--dbus] [--dbus-system]
|
||||
*signal-cli* [--verbose] [--data-dir DATA_DIR] [-a ACCOUNT] [-o {plain-text,json}] daemon [--dbus] [--dbus-system]
|
||||
|
||||
*dbus-send* [--system | --session] [--print-reply] --type=method_call --dest="org.asamk.Signal" /org/asamk/Signal[/_<phonenumber>] org.asamk.Signal.<method> [string:<string argument>] [array:<type>:<array argument>]
|
||||
|
||||
|
||||
@ -13,9 +13,9 @@ signal-cli-jsonrpc - A commandline and dbus interface for the Signal messenger
|
||||
|
||||
== Synopsis
|
||||
|
||||
*signal-cli* [--verbose] [--config CONFIG] [-a ACCOUNT] daemon [--socket[=SOCKET_PATH]] [--tcp[=HOST:PORT]] [--http[=HOST:PORT]]
|
||||
*signal-cli* [--verbose] [--data-dir DATA_DIR] [-a ACCOUNT] daemon [--socket[=SOCKET_PATH]] [--tcp[=HOST:PORT]] [--http[=HOST:PORT]]
|
||||
|
||||
*signal-cli* [--verbose] [--config CONFIG] [-a ACCOUNT] jsonRpc
|
||||
*signal-cli* [--verbose] [--data-dir DATA_DIR] [-a ACCOUNT] jsonRpc
|
||||
|
||||
== Description
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ signal-cli - A commandline interface for the Signal messenger
|
||||
|
||||
== Synopsis
|
||||
|
||||
*signal-cli* [--config CONFIG] [-h | -v | -a ACCOUNT | --dbus | --dbus-system] command [command-options]
|
||||
*signal-cli* [--data-dir DATA_DIR] [-h | -v | -a ACCOUNT | --dbus | --dbus-system] command [command-options]
|
||||
|
||||
== Description
|
||||
|
||||
@ -57,8 +57,8 @@ If `--verbose` is also given, the detailed logs will only be written to the log
|
||||
Scrub possibly sensitive information from the log, like phone numbers and UUIDs.
|
||||
Doesn't work reliably on dbus logs with very verbose logging (`-vvv`)
|
||||
|
||||
*--config* CONFIG::
|
||||
Set the path, where to store the config.
|
||||
*-d* DATA_DIR, *--data-dir* DATA_DIR, *-c* CONFIG, *--config* CONFIG::
|
||||
Set the path where to store account data and local configuration.
|
||||
Make sure you have full read/write access to the given directory.
|
||||
(Default: `$XDG_DATA_HOME/signal-cli` (`$HOME/.local/share/signal-cli`))
|
||||
|
||||
@ -1172,10 +1172,25 @@ signal-cli -a ACCOUNT trust -a RECIPIENT
|
||||
|
||||
== Files
|
||||
|
||||
The password and cryptographic keys are created when registering and stored in the current users home directory, the directory can be changed with *--config*:
|
||||
The password and cryptographic keys are created when registering and stored in the current users home directory, the directory can be changed with *--data-dir* (legacy *--config*):
|
||||
|
||||
`$XDG_DATA_HOME/signal-cli/` (`$HOME/.local/share/signal-cli/`)
|
||||
|
||||
=== Configuration file
|
||||
|
||||
signal-cli supports a JSON-based global configuration file that provides defaults for CLI options.
|
||||
Keys use camelCase and generally match the long CLI parameter names (for example `dataDir`, `verbose`, `logFile`, `serviceEnvironment`, `trustNewIdentities`, `output`, `disableSendLog`, `account`).
|
||||
|
||||
Configuration files are read and merged in this order; later files override earlier ones:
|
||||
|
||||
- `/etc/signal-cli/config.json` (system-wide defaults)
|
||||
- the path in the `SIGNAL_CLI_CONFIG` environment variable (if set)
|
||||
- `$XDG_CONFIG_HOME/signal-cli/config.json` (per-user; defaults to `$HOME/.config/signal-cli/config.json`)
|
||||
|
||||
When multiple configuration files are present their settings are merged; values from later files override earlier values.
|
||||
Command-line options always take precedence over configuration file values.
|
||||
Overall precedence (highest → lowest): command-line options → per-user config → system config → built-in defaults.
|
||||
|
||||
== Authors
|
||||
|
||||
Maintained by AsamK <asamk@gmx.de>, who is assisted by other open source contributors.
|
||||
|
||||
@ -46,7 +46,9 @@ public class App {
|
||||
|
||||
private final Namespace ns;
|
||||
|
||||
static ArgumentParser buildArgumentParser() {
|
||||
static ArgumentParser buildArgumentParser(GlobalConfig config) {
|
||||
final var cfg = config == null ? GlobalConfig.DEFAULT : config;
|
||||
|
||||
var parser = ArgumentParsers.newFor("signal-cli", VERSION_0_9_0_DEFAULT_SETTINGS)
|
||||
.includeArgumentNamesAsKeysInResult(true)
|
||||
.build()
|
||||
@ -57,47 +59,60 @@ public class App {
|
||||
parser.addArgument("--version").help("Show package version.").action(Arguments.version());
|
||||
parser.addArgument("-v", "--verbose")
|
||||
.help("Raise log level and include lib signal logs. Specify multiple times for even more logs.")
|
||||
.action(Arguments.count());
|
||||
.action(Arguments.count())
|
||||
.setDefault(cfg.verbose());
|
||||
parser.addArgument("--log-file")
|
||||
.type(File.class)
|
||||
.help("Write log output to the given file. If --verbose is also given, the detailed logs will only be written to the log file.");
|
||||
.help("Write log output to the given file. If --verbose is also given, the detailed logs will only be written to the log file.")
|
||||
.setDefault(cfg.logFile() == null ? null : new File(cfg.logFile()));
|
||||
parser.addArgument("--scrub-log")
|
||||
.action(Arguments.storeTrue())
|
||||
.help("Scrub possibly sensitive information from the log, like phone numbers and UUIDs.");
|
||||
parser.addArgument("-c", "--config")
|
||||
.help("Set the path, where to store the config (Default: $XDG_DATA_HOME/signal-cli , $HOME/.local/share/signal-cli).");
|
||||
.help("Scrub possibly sensitive information from the log, like phone numbers and UUIDs.")
|
||||
.setDefault(cfg.scrubLog());
|
||||
parser.addArgument("-d", "--data-dir", "-c", "--config")
|
||||
.help("Set the path where to store data (Default: $XDG_DATA_HOME/signal-cli , $HOME/.local/share/signal-cli).")
|
||||
.setDefault(cfg.dataDir());
|
||||
|
||||
parser.addArgument("-a", "--account", "-u", "--username")
|
||||
.help("Specify your phone number, that will be your identifier.");
|
||||
|
||||
var mut = parser.addMutuallyExclusiveGroup();
|
||||
mut.addArgument("--dbus").dest("global-dbus").help("Make request via user dbus.").action(Arguments.storeTrue());
|
||||
mut.addArgument("--dbus")
|
||||
.dest("global-dbus")
|
||||
.help("Make request via user dbus.")
|
||||
.action(Arguments.storeTrue())
|
||||
.setDefault(cfg.dbus());
|
||||
mut.addArgument("--dbus-system")
|
||||
.dest("global-dbus-system")
|
||||
.help("Make request via system dbus.")
|
||||
.action(Arguments.storeTrue());
|
||||
.action(Arguments.storeTrue())
|
||||
.setDefault(cfg.dbusSystem());
|
||||
parser.addArgument("--bus-name")
|
||||
.dest("global-bus-name")
|
||||
.setDefault(DbusConfig.getBusname())
|
||||
.setDefault(cfg.busName() != null ? cfg.busName() : DbusConfig.getBusname())
|
||||
.help("Specify the D-Bus bus name to connect to.");
|
||||
|
||||
parser.addArgument("-o", "--output")
|
||||
.help("Choose to output in plain text or JSON")
|
||||
.type(Arguments.enumStringType(OutputType.class));
|
||||
.type(Arguments.enumStringType(OutputType.class))
|
||||
.setDefault(cfg.output() == null ? null : cfg.output());
|
||||
|
||||
parser.addArgument("--service-environment")
|
||||
.help("Choose the server environment to use.")
|
||||
.type(Arguments.enumStringType(ServiceEnvironmentCli.class))
|
||||
.setDefault(ServiceEnvironmentCli.LIVE);
|
||||
.setDefault(cfg.serviceEnvironment() != null ? cfg.serviceEnvironment() : ServiceEnvironmentCli.LIVE);
|
||||
|
||||
parser.addArgument("--trust-new-identities")
|
||||
.help("Choose when to trust new identities.")
|
||||
.type(Arguments.enumStringType(TrustNewIdentityCli.class))
|
||||
.setDefault(TrustNewIdentityCli.ON_FIRST_USE);
|
||||
.setDefault(cfg.trustNewIdentities() != null
|
||||
? cfg.trustNewIdentities()
|
||||
: TrustNewIdentityCli.ON_FIRST_USE);
|
||||
|
||||
parser.addArgument("--disable-send-log")
|
||||
.help("Disable message send log (for resending messages that recipient couldn't decrypt)")
|
||||
.action(Arguments.storeTrue());
|
||||
.action(Arguments.storeTrue())
|
||||
.setDefault(cfg.disableSendLog());
|
||||
|
||||
parser.epilog(
|
||||
"The global arguments are shown with 'signal-cli -h' and need to come before the subcommand, while the subcommand-specific arguments (shown with 'signal-cli SUBCOMMAND -h') need to be given after the subcommand.");
|
||||
@ -219,12 +234,12 @@ public class App {
|
||||
}
|
||||
|
||||
private SignalAccountFiles loadSignalAccountFiles() throws IOErrorException {
|
||||
final File configPath;
|
||||
final var config = ns.getString("config");
|
||||
if (config != null) {
|
||||
configPath = new File(config);
|
||||
final File dataPath;
|
||||
final var dataDir = ns.getString("data-dir");
|
||||
if (dataDir != null) {
|
||||
dataPath = new File(dataDir);
|
||||
} else {
|
||||
configPath = getDefaultConfigPath();
|
||||
dataPath = getDefaultDataPath();
|
||||
}
|
||||
|
||||
final var serviceEnvironmentCli = ns.<ServiceEnvironmentCli>get("service-environment");
|
||||
@ -240,7 +255,7 @@ public class App {
|
||||
final var disableSendLog = Boolean.TRUE.equals(ns.getBoolean("disable-send-log"));
|
||||
|
||||
try {
|
||||
return new SignalAccountFiles(configPath,
|
||||
return new SignalAccountFiles(dataPath,
|
||||
serviceEnvironment,
|
||||
BaseConfig.USER_AGENT,
|
||||
new Settings(trustNewIdentity, disableSendLog));
|
||||
@ -339,7 +354,7 @@ public class App {
|
||||
/**
|
||||
* @return the default data directory to be used by signal-cli.
|
||||
*/
|
||||
private static File getDefaultConfigPath() {
|
||||
private static File getDefaultDataPath() {
|
||||
return new File(IOUtils.getDataHomeDir(), "signal-cli");
|
||||
}
|
||||
}
|
||||
|
||||
81
src/main/java/org/asamk/signal/ConfigLoader.java
Normal file
81
src/main/java/org/asamk/signal/ConfigLoader.java
Normal file
@ -0,0 +1,81 @@
|
||||
package org.asamk.signal;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
import org.asamk.signal.commands.exceptions.UserErrorException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* Loads and merges configuration files. Merge order (later files override earlier):
|
||||
* - /etc/signal-cli/config.json
|
||||
* - file pointed to by SIGNAL_CLI_CONFIG (if set)
|
||||
* - $XDG_CONFIG_HOME/signal-cli/config.json or $HOME/.config/signal-cli/config.json
|
||||
*/
|
||||
public final class ConfigLoader {
|
||||
|
||||
private ConfigLoader() {
|
||||
}
|
||||
|
||||
public static GlobalConfig load() throws UserErrorException {
|
||||
final ObjectMapper mapper = new ObjectMapper();
|
||||
final ObjectNode merged = mapper.createObjectNode();
|
||||
|
||||
// System config
|
||||
addIfExists(merged, mapper, Paths.get("/etc/signal-cli/config.json"));
|
||||
|
||||
// User config via env (if set) else XDG or ~/.config
|
||||
final String env = System.getenv("SIGNAL_CLI_CONFIG");
|
||||
if (env != null && !env.isEmpty()) {
|
||||
addIfExists(merged, mapper, Paths.get(env));
|
||||
} else {
|
||||
final String xdg = System.getenv("XDG_CONFIG_HOME");
|
||||
if (xdg != null && !xdg.isEmpty()) {
|
||||
addIfExists(merged, mapper, Paths.get(xdg, "signal-cli", "config.json"));
|
||||
} else {
|
||||
addIfExists(merged,
|
||||
mapper,
|
||||
Paths.get(System.getProperty("user.home"), ".config", "signal-cli", "config.json"));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (merged.isEmpty()) {
|
||||
return GlobalConfig.DEFAULT;
|
||||
}
|
||||
return mapper.treeToValue(merged, GlobalConfig.class);
|
||||
} catch (Exception e) {
|
||||
throw new UserErrorException("Failed to parse configuration file(s): " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addIfExists(ObjectNode merged, ObjectMapper mapper, Path p) throws UserErrorException {
|
||||
if (p == null) return;
|
||||
try {
|
||||
if (Files.exists(p)) {
|
||||
final JsonNode node = mapper.readTree(p.toFile());
|
||||
merge(merged, node);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UserErrorException("Failed to load config from " + p + ": " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void merge(ObjectNode target, JsonNode source) {
|
||||
source.properties().forEach(entry -> {
|
||||
final String name = entry.getKey();
|
||||
final JsonNode value = entry.getValue();
|
||||
final JsonNode existing = target.get(name);
|
||||
if (existing != null && existing.isObject() && value.isObject()) {
|
||||
merge((ObjectNode) existing, value);
|
||||
} else {
|
||||
target.set(name, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
36
src/main/java/org/asamk/signal/GlobalConfig.java
Normal file
36
src/main/java/org/asamk/signal/GlobalConfig.java
Normal file
@ -0,0 +1,36 @@
|
||||
package org.asamk.signal;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public record GlobalConfig(
|
||||
@JsonProperty("verbose") Integer verbose,
|
||||
@JsonProperty("logFile") String logFile,
|
||||
@JsonProperty("scrubLog") Boolean scrubLog,
|
||||
@JsonProperty("dataDir") String dataDir,
|
||||
@JsonProperty("busName") String busName,
|
||||
@JsonProperty("dbus") Boolean dbus,
|
||||
@JsonProperty("dbusSystem") Boolean dbusSystem,
|
||||
@JsonProperty("output") OutputType output,
|
||||
@JsonProperty("serviceEnvironment") ServiceEnvironmentCli serviceEnvironment,
|
||||
@JsonProperty("trustNewIdentities") TrustNewIdentityCli trustNewIdentities,
|
||||
@JsonProperty("disableSendLog") Boolean disableSendLog,
|
||||
@JsonProperty("account") String account
|
||||
) {
|
||||
|
||||
public static final GlobalConfig DEFAULT = new GlobalConfig(null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
ServiceEnvironmentCli.LIVE,
|
||||
TrustNewIdentityCli.ON_FIRST_USE,
|
||||
null,
|
||||
null);
|
||||
|
||||
public static GlobalConfig empty() {
|
||||
return new GlobalConfig(null, null, null, null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
}
|
||||
@ -40,27 +40,32 @@ import java.security.Security;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
static void main(String[] args) {
|
||||
// enable unlimited strength crypto via Policy, supported on relevant JREs
|
||||
Security.setProperty("crypto.policy", "unlimited");
|
||||
installSecurityProviderWorkaround();
|
||||
|
||||
// Load global config early so we can use its values as parser defaults
|
||||
final GlobalConfig globalConfig;
|
||||
try {
|
||||
globalConfig = ConfigLoader.load();
|
||||
} catch (UserErrorException e) {
|
||||
System.exit(handleCommandException(e, null));
|
||||
return;
|
||||
}
|
||||
|
||||
// Configuring the logger needs to happen before any logger is initialized
|
||||
final var loggingConfig = parseLoggingConfig(args);
|
||||
final var loggingConfig = parseLoggingConfig(args, globalConfig);
|
||||
configureLogging(loggingConfig);
|
||||
|
||||
final var parser = App.buildArgumentParser();
|
||||
final var parser = App.buildArgumentParser(globalConfig);
|
||||
final var ns = parser.parseArgsOrFail(args);
|
||||
|
||||
int status = 0;
|
||||
try {
|
||||
new App(ns).init();
|
||||
} catch (CommandException e) {
|
||||
System.err.println(e.getMessage());
|
||||
if (loggingConfig.verboseLevel > 0 && e.getCause() != null) {
|
||||
e.getCause().printStackTrace(System.err);
|
||||
}
|
||||
status = getStatusForError(e);
|
||||
status = handleCommandException(e, loggingConfig);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace(System.err);
|
||||
status = 2;
|
||||
@ -69,16 +74,27 @@ public class Main {
|
||||
System.exit(status);
|
||||
}
|
||||
|
||||
private static int handleCommandException(final CommandException e, final LoggingConfig loggingConfig) {
|
||||
System.err.println(e.getMessage());
|
||||
if (loggingConfig != null && loggingConfig.verboseLevel > 0 && e.getCause() != null) {
|
||||
e.getCause().printStackTrace(System.err);
|
||||
}
|
||||
return getStatusForError(e);
|
||||
}
|
||||
|
||||
private static void installSecurityProviderWorkaround() {
|
||||
// Register our own security provider
|
||||
Security.insertProviderAt(new SecurityProvider(), 1);
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
private static LoggingConfig parseLoggingConfig(final String[] args) {
|
||||
final var nsLog = parseArgs(args);
|
||||
private static LoggingConfig parseLoggingConfig(final String[] args, final GlobalConfig config) {
|
||||
final var nsLog = parseArgs(args, config);
|
||||
if (nsLog == null) {
|
||||
return new LoggingConfig(0, null, false);
|
||||
final var verbose = config != null && config.verbose() != null ? config.verbose() : 0;
|
||||
final var logFile = config != null && config.logFile() != null ? new File(config.logFile()) : null;
|
||||
final var scrubLog = config != null && Boolean.TRUE.equals(config.scrubLog());
|
||||
return new LoggingConfig(verbose, logFile, scrubLog);
|
||||
}
|
||||
|
||||
final var verboseLevel = nsLog.getInt("verbose");
|
||||
@ -90,14 +106,20 @@ public class Main {
|
||||
/**
|
||||
* This method only parses commandline args relevant for logging configuration.
|
||||
*/
|
||||
private static Namespace parseArgs(String[] args) {
|
||||
private static Namespace parseArgs(String[] args, final GlobalConfig config) {
|
||||
var parser = ArgumentParsers.newFor("signal-cli", DefaultSettings.VERSION_0_9_0_DEFAULT_SETTINGS)
|
||||
.includeArgumentNamesAsKeysInResult(true)
|
||||
.build()
|
||||
.defaultHelp(false);
|
||||
parser.addArgument("-v", "--verbose").action(Arguments.count());
|
||||
parser.addArgument("--log-file").type(File.class);
|
||||
parser.addArgument("--scrub-log").action(Arguments.storeTrue());
|
||||
parser.addArgument("-v", "--verbose")
|
||||
.action(Arguments.count())
|
||||
.setDefault(config == null ? null : config.verbose());
|
||||
parser.addArgument("--log-file")
|
||||
.type(File.class)
|
||||
.setDefault(config == null || config.logFile() == null ? null : new File(config.logFile()));
|
||||
parser.addArgument("--scrub-log")
|
||||
.action(Arguments.storeTrue())
|
||||
.setDefault(config == null ? null : config.scrubLog());
|
||||
|
||||
try {
|
||||
return parser.parseKnownArgs(args, null);
|
||||
@ -124,12 +146,12 @@ public class Main {
|
||||
|
||||
private static int getStatusForError(final CommandException e) {
|
||||
return switch (e) {
|
||||
case UserErrorException userErrorException -> 1;
|
||||
case UnexpectedErrorException unexpectedErrorException -> 2;
|
||||
case IOErrorException ioErrorException -> 3;
|
||||
case UntrustedKeyErrorException untrustedKeyErrorException -> 4;
|
||||
case RateLimitErrorException rateLimitErrorException -> 5;
|
||||
case CaptchaRejectedErrorException captchaRejectedErrorException -> 6;
|
||||
case UserErrorException _ -> 1;
|
||||
case UnexpectedErrorException _ -> 2;
|
||||
case IOErrorException _ -> 3;
|
||||
case UntrustedKeyErrorException _ -> 4;
|
||||
case RateLimitErrorException _ -> 5;
|
||||
case CaptchaRejectedErrorException _ -> 6;
|
||||
case null -> 2;
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package org.asamk.signal;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
public enum OutputType {
|
||||
PLAIN_TEXT {
|
||||
@Override
|
||||
@ -12,5 +14,16 @@ public enum OutputType {
|
||||
public String toString() {
|
||||
return "json";
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@JsonCreator
|
||||
public static OutputType fromString(String value) {
|
||||
if (value == null) return null;
|
||||
final var norm = value.trim().toLowerCase().replaceAll("[^a-z0-9]", "");
|
||||
return switch (norm) {
|
||||
case "plaintext" -> PLAIN_TEXT;
|
||||
case "json" -> JSON;
|
||||
default -> throw new IllegalArgumentException("Invalid output type: " + value);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package org.asamk.signal;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
public enum ServiceEnvironmentCli {
|
||||
LIVE {
|
||||
@Override
|
||||
@ -12,5 +14,16 @@ public enum ServiceEnvironmentCli {
|
||||
public String toString() {
|
||||
return "staging";
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@JsonCreator
|
||||
public static ServiceEnvironmentCli fromString(String value) {
|
||||
if (value == null) return null;
|
||||
final var norm = value.trim().toLowerCase();
|
||||
return switch (norm) {
|
||||
case "live" -> LIVE;
|
||||
case "staging" -> STAGING;
|
||||
default -> throw new IllegalArgumentException("Invalid service-environment: " + value);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package org.asamk.signal;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
|
||||
public enum TrustNewIdentityCli {
|
||||
ALWAYS {
|
||||
@Override
|
||||
@ -18,5 +20,17 @@ public enum TrustNewIdentityCli {
|
||||
public String toString() {
|
||||
return "never";
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@JsonCreator
|
||||
public static TrustNewIdentityCli fromString(String value) {
|
||||
if (value == null) return null;
|
||||
final var norm = value.trim().toLowerCase().replaceAll("[^a-z0-9]", "");
|
||||
return switch (norm) {
|
||||
case "always" -> ALWAYS;
|
||||
case "onfirstuse" -> ON_FIRST_USE;
|
||||
case "never" -> NEVER;
|
||||
default -> throw new IllegalArgumentException("Invalid trust-new-identities: " + value);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1317,6 +1317,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "java.util.concurrent.CopyOnWriteArrayList",
|
||||
"fields": [
|
||||
{
|
||||
"name": "lock"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "java.util.concurrent.ForkJoinTask",
|
||||
"fields": [
|
||||
@ -1979,6 +1987,28 @@
|
||||
{
|
||||
"type": "org.asamk.SignalControl.Error.InvalidNumber"
|
||||
},
|
||||
{
|
||||
"type": "org.asamk.signal.GlobalConfig",
|
||||
"methods": [
|
||||
{
|
||||
"name": "<init>",
|
||||
"parameterTypes": [
|
||||
"java.lang.Integer",
|
||||
"java.lang.String",
|
||||
"java.lang.Boolean",
|
||||
"java.lang.String",
|
||||
"java.lang.String",
|
||||
"java.lang.Boolean",
|
||||
"java.lang.Boolean",
|
||||
"org.asamk.signal.OutputType",
|
||||
"org.asamk.signal.ServiceEnvironmentCli",
|
||||
"org.asamk.signal.TrustNewIdentityCli",
|
||||
"java.lang.Boolean",
|
||||
"java.lang.String"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "org.asamk.signal.Main",
|
||||
"jniAccessible": true,
|
||||
@ -1995,6 +2025,31 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "org.asamk.signal.OutputType"
|
||||
},
|
||||
{
|
||||
"type": "org.asamk.signal.ServiceEnvironmentCli",
|
||||
"methods": [
|
||||
{
|
||||
"name": "fromString",
|
||||
"parameterTypes": [
|
||||
"java.lang.String"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "org.asamk.signal.TrustNewIdentityCli",
|
||||
"methods": [
|
||||
{
|
||||
"name": "fromString",
|
||||
"parameterTypes": [
|
||||
"java.lang.String"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "org.asamk.signal.commands.AcceptCallCommand$JsonCallInfo",
|
||||
"allDeclaredFields": true,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user