]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/dbus/DbusCommandHandler.java
5e272895256722800c0775552a84e1b3be88ebd4
[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, final String busname
91 ) throws DBusException, CommandException {
92 var control = dBusConn.getRemoteObject(busname, DbusConfig.getObjectPath(), SignalControl.class);
93 try {
94 final var accounts = control.listAccounts();
95 if (accounts.isEmpty()) {
96 throw new UserErrorException("No local users found, you first need to register or link an account");
97 } else if (accounts.size() > 1) {
98 throw new UserErrorException(
99 "Multiple users found, you need to specify an account (phone number) with -a");
100 }
101
102 return accounts.getFirst().getPath();
103 } catch (UnknownMethod e) {
104 // dbus daemon not running in multi-account mode
105 return null;
106 }
107 }
108
109 private static void handleMultiLocalCommand(
110 final MultiLocalCommand c,
111 final DBusConnection dBusConn,
112 final String busname,
113 final CommandHandler commandHandler
114 ) throws CommandException, DBusException {
115 final var signalControl = dBusConn.getRemoteObject(busname, DbusConfig.getObjectPath(), SignalControl.class);
116 try (final var multiAccountManager = new DbusMultiAccountManagerImpl(signalControl, dBusConn, busname)) {
117 commandHandler.handleMultiLocalCommand(c, multiAccountManager);
118 }
119 }
120
121 private static void handleLocalCommand(
122 final LocalCommand c,
123 String accountObjectPath,
124 final DBusConnection dBusConn,
125 final String busname,
126 final CommandHandler commandHandler
127 ) throws CommandException, DBusException {
128 var signal = dBusConn.getRemoteObject(busname, accountObjectPath, Signal.class);
129 try (final var manager = new DbusManagerImpl(signal, dBusConn, busname)) {
130 commandHandler.handleLocalCommand(c, manager);
131 }
132 }
133
134 private static void handleRegistrationCommand(
135 final RegistrationCommand c,
136 String account,
137 final DBusConnection dBusConn,
138 final String busname,
139 final CommandHandler commandHandler
140
141 ) throws CommandException, DBusException {
142 final var signalControl = dBusConn.getRemoteObject(busname, DbusConfig.getObjectPath(), SignalControl.class);
143 try (final var registrationManager = new DbusRegistrationManagerImpl(account, signalControl, dBusConn)) {
144 commandHandler.handleRegistrationCommand(c, registrationManager);
145 }
146 }
147
148 private static void handleProvisioningCommand(
149 final ProvisioningCommand c,
150 final DBusConnection dBusConn,
151 final String busname,
152 final CommandHandler commandHandler
153
154 ) throws CommandException, DBusException {
155 final var signalControl = dBusConn.getRemoteObject(busname, DbusConfig.getObjectPath(), SignalControl.class);
156 final var provisioningManager = new DbusProvisioningManagerImpl(signalControl, dBusConn);
157 commandHandler.handleProvisioningCommand(c, provisioningManager);
158 }
159 }