]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/dbus/DbusCommandHandler.java
Reformat files
[signal-cli] / src / main / java / org / asamk / signal / dbus / DbusCommandHandler.java
1 package org.asamk.signal.dbus;
2
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;
21
22 import java.io.IOException;
23
24 public class DbusCommandHandler {
25
26 public static void initDbusClient(
27 final Command command,
28 final String account,
29 final boolean systemBus,
30 final String busname,
31 final CommandHandler commandHandler
32 ) throws CommandException {
33 try {
34 final var busType = systemBus ? DBusConnection.DBusBusType.SYSTEM : DBusConnection.DBusBusType.SESSION;
35 try (var dBusConn = DBusConnectionBuilder.forType(busType).build()) {
36 handleCommand(command, account, dBusConn, busname, commandHandler);
37 }
38 } catch (ServiceUnknown e) {
39 throw new UserErrorException("signal-cli DBus daemon not running on "
40 + (systemBus ? "system" : "session")
41 + " bus: "
42 + e.getMessage(), e);
43 } catch (DBusExecutionException | DBusException | IOException e) {
44 throw new UnexpectedErrorException("Dbus client failed: " + e.getMessage(), e);
45 }
46 }
47
48 public static void handleCommand(
49 final Command command,
50 final String account,
51 final DBusConnection dBusConn,
52 final String busname,
53 final CommandHandler commandHandler
54 ) throws CommandException, DBusException {
55 try {
56 if (command instanceof ProvisioningCommand c) {
57 if (account != null) {
58 throw new UserErrorException("You cannot specify a account (phone number) when linking");
59 }
60
61 handleProvisioningCommand(c, dBusConn, busname, commandHandler);
62 return;
63 }
64
65 if (account == null && command instanceof MultiLocalCommand c) {
66 handleMultiLocalCommand(c, dBusConn, busname, commandHandler);
67 return;
68 }
69 if (account != null && command instanceof RegistrationCommand c) {
70 handleRegistrationCommand(c, account, dBusConn, busname, commandHandler);
71 return;
72 }
73 if (!(command instanceof LocalCommand localCommand)) {
74 throw new UserErrorException("Command only works in multi-account mode");
75 }
76
77 var accountObjectPath = account == null ? tryGetSingleAccountObjectPath(dBusConn, busname) : null;
78 if (accountObjectPath == null) {
79 accountObjectPath = DbusConfig.getObjectPath(account);
80 }
81 handleLocalCommand(localCommand, accountObjectPath, dBusConn, busname, commandHandler);
82 } catch (UnsupportedOperationException e) {
83 throw new UserErrorException("Command is not yet implemented via dbus", e);
84 } catch (DBusExecutionException e) {
85 throw new UnexpectedErrorException(e.getMessage(), e);
86 }
87 }
88
89 private static String tryGetSingleAccountObjectPath(
90 final DBusConnection dBusConn,
91 final String busname
92 ) throws DBusException, CommandException {
93 var control = dBusConn.getRemoteObject(busname, DbusConfig.getObjectPath(), SignalControl.class);
94 try {
95 final var accounts = control.listAccounts();
96 if (accounts.isEmpty()) {
97 throw new UserErrorException("No local users found, you first need to register or link an account");
98 } else if (accounts.size() > 1) {
99 throw new UserErrorException(
100 "Multiple users found, you need to specify an account (phone number) with -a");
101 }
102
103 return accounts.getFirst().getPath();
104 } catch (UnknownMethod e) {
105 // dbus daemon not running in multi-account mode
106 return null;
107 }
108 }
109
110 private static void handleMultiLocalCommand(
111 final MultiLocalCommand c,
112 final DBusConnection dBusConn,
113 final String busname,
114 final CommandHandler commandHandler
115 ) throws CommandException, DBusException {
116 final var signalControl = dBusConn.getRemoteObject(busname, DbusConfig.getObjectPath(), SignalControl.class);
117 try (final var multiAccountManager = new DbusMultiAccountManagerImpl(signalControl, dBusConn, busname)) {
118 commandHandler.handleMultiLocalCommand(c, multiAccountManager);
119 }
120 }
121
122 private static void handleLocalCommand(
123 final LocalCommand c,
124 String accountObjectPath,
125 final DBusConnection dBusConn,
126 final String busname,
127 final CommandHandler commandHandler
128 ) throws CommandException, DBusException {
129 var signal = dBusConn.getRemoteObject(busname, accountObjectPath, Signal.class);
130 try (final var manager = new DbusManagerImpl(signal, dBusConn, busname)) {
131 commandHandler.handleLocalCommand(c, manager);
132 }
133 }
134
135 private static void handleRegistrationCommand(
136 final RegistrationCommand c,
137 String account,
138 final DBusConnection dBusConn,
139 final String busname,
140 final CommandHandler commandHandler
141
142 ) throws CommandException, DBusException {
143 final var signalControl = dBusConn.getRemoteObject(busname, DbusConfig.getObjectPath(), SignalControl.class);
144 try (final var registrationManager = new DbusRegistrationManagerImpl(account, signalControl, dBusConn)) {
145 commandHandler.handleRegistrationCommand(c, registrationManager);
146 }
147 }
148
149 private static void handleProvisioningCommand(
150 final ProvisioningCommand c,
151 final DBusConnection dBusConn,
152 final String busname,
153 final CommandHandler commandHandler
154
155 ) throws CommandException, DBusException {
156 final var signalControl = dBusConn.getRemoteObject(busname, DbusConfig.getObjectPath(), SignalControl.class);
157 final var provisioningManager = new DbusProvisioningManagerImpl(signalControl, dBusConn);
158 commandHandler.handleProvisioningCommand(c, provisioningManager);
159 }
160 }