1 package org
.asamk
.signal
.dbus
;
3 import org
.asamk
.Signal
;
4 import org
.asamk
.SignalControl
;
5 import org
.asamk
.signal
.DbusConfig
;
6 import org
.asamk
.signal
.commands
.Command
;
7 import org
.asamk
.signal
.commands
.CommandHandler
;
8 import org
.asamk
.signal
.commands
.LocalCommand
;
9 import org
.asamk
.signal
.commands
.MultiLocalCommand
;
10 import org
.asamk
.signal
.commands
.ProvisioningCommand
;
11 import org
.asamk
.signal
.commands
.RegistrationCommand
;
12 import org
.asamk
.signal
.commands
.exceptions
.CommandException
;
13 import org
.asamk
.signal
.commands
.exceptions
.UnexpectedErrorException
;
14 import org
.asamk
.signal
.commands
.exceptions
.UserErrorException
;
15 import org
.freedesktop
.dbus
.connections
.impl
.DBusConnection
;
16 import org
.freedesktop
.dbus
.connections
.impl
.DBusConnectionBuilder
;
17 import org
.freedesktop
.dbus
.errors
.ServiceUnknown
;
18 import org
.freedesktop
.dbus
.errors
.UnknownMethod
;
19 import org
.freedesktop
.dbus
.exceptions
.DBusException
;
20 import org
.freedesktop
.dbus
.exceptions
.DBusExecutionException
;
22 import java
.io
.IOException
;
24 public class DbusCommandHandler
{
26 public static void initDbusClient(
27 final Command command
, final String account
, final boolean systemBus
, final CommandHandler commandHandler
28 ) throws CommandException
{
30 final var busType
= systemBus ? DBusConnection
.DBusBusType
.SYSTEM
: DBusConnection
.DBusBusType
.SESSION
;
31 try (var dBusConn
= DBusConnectionBuilder
.forType(busType
).build()) {
32 handleCommand(command
, account
, dBusConn
, commandHandler
);
34 } catch (ServiceUnknown e
) {
35 throw new UserErrorException("signal-cli DBus daemon not running on "
36 + (systemBus ?
"system" : "session")
39 } catch (DBusExecutionException
| DBusException
| IOException e
) {
40 throw new UnexpectedErrorException("Dbus client failed: " + e
.getMessage(), e
);
44 public static void handleCommand(
45 final Command command
,
47 final DBusConnection dBusConn
,
48 final CommandHandler commandHandler
49 ) throws CommandException
, DBusException
{
51 if (command
instanceof ProvisioningCommand c
) {
52 if (account
!= null) {
53 throw new UserErrorException("You cannot specify a account (phone number) when linking");
56 handleProvisioningCommand(c
, dBusConn
, commandHandler
);
60 if (account
== null && command
instanceof MultiLocalCommand c
) {
61 handleMultiLocalCommand(c
, dBusConn
, commandHandler
);
64 if (account
!= null && command
instanceof RegistrationCommand c
) {
65 handleRegistrationCommand(c
, account
, dBusConn
, commandHandler
);
68 if (!(command
instanceof LocalCommand localCommand
)) {
69 throw new UserErrorException("Command only works in multi-account mode");
72 var accountObjectPath
= account
== null ?
tryGetSingleAccountObjectPath(dBusConn
) : null;
73 if (accountObjectPath
== null) {
74 accountObjectPath
= DbusConfig
.getObjectPath(account
);
76 handleLocalCommand(localCommand
, accountObjectPath
, dBusConn
, commandHandler
);
77 } catch (UnsupportedOperationException e
) {
78 throw new UserErrorException("Command is not yet implemented via dbus", e
);
79 } catch (DBusExecutionException e
) {
80 throw new UnexpectedErrorException(e
.getMessage(), e
);
84 private static String
tryGetSingleAccountObjectPath(final DBusConnection dBusConn
) throws DBusException
, CommandException
{
85 var control
= dBusConn
.getRemoteObject(DbusConfig
.getBusname(),
86 DbusConfig
.getObjectPath(),
89 final var accounts
= control
.listAccounts();
90 if (accounts
.isEmpty()) {
91 throw new UserErrorException("No local users found, you first need to register or link an account");
92 } else if (accounts
.size() > 1) {
93 throw new UserErrorException(
94 "Multiple users found, you need to specify an account (phone number) with -a");
97 return accounts
.getFirst().getPath();
98 } catch (UnknownMethod e
) {
99 // dbus daemon not running in multi-account mode
104 private static void handleMultiLocalCommand(
105 final MultiLocalCommand c
, final DBusConnection dBusConn
, final CommandHandler commandHandler
106 ) throws CommandException
, DBusException
{
107 final var signalControl
= dBusConn
.getRemoteObject(DbusConfig
.getBusname(),
108 DbusConfig
.getObjectPath(),
109 SignalControl
.class);
110 try (final var multiAccountManager
= new DbusMultiAccountManagerImpl(signalControl
, dBusConn
)) {
111 commandHandler
.handleMultiLocalCommand(c
, multiAccountManager
);
115 private static void handleLocalCommand(
116 final LocalCommand c
,
117 String accountObjectPath
,
118 final DBusConnection dBusConn
,
119 final CommandHandler commandHandler
120 ) throws CommandException
, DBusException
{
121 var signal
= dBusConn
.getRemoteObject(DbusConfig
.getBusname(), accountObjectPath
, Signal
.class);
122 try (final var manager
= new DbusManagerImpl(signal
, dBusConn
)) {
123 commandHandler
.handleLocalCommand(c
, manager
);
127 private static void handleRegistrationCommand(
128 final RegistrationCommand c
,
130 final DBusConnection dBusConn
,
131 final CommandHandler commandHandler
133 ) throws CommandException
, DBusException
{
134 final var signalControl
= dBusConn
.getRemoteObject(DbusConfig
.getBusname(),
135 DbusConfig
.getObjectPath(),
136 SignalControl
.class);
137 try (final var registrationManager
= new DbusRegistrationManagerImpl(account
, signalControl
, dBusConn
)) {
138 commandHandler
.handleRegistrationCommand(c
, registrationManager
);
142 private static void handleProvisioningCommand(
143 final ProvisioningCommand c
, final DBusConnection dBusConn
, final CommandHandler commandHandler
145 ) throws CommandException
, DBusException
{
146 final var signalControl
= dBusConn
.getRemoteObject(DbusConfig
.getBusname(),
147 DbusConfig
.getObjectPath(),
148 SignalControl
.class);
149 final var provisioningManager
= new DbusProvisioningManagerImpl(signalControl
, dBusConn
);
150 commandHandler
.handleProvisioningCommand(c
, provisioningManager
);