]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java
Update gradle
[signal-cli] / src / main / java / org / asamk / signal / dbus / DbusSignalControlImpl.java
1 package org.asamk.signal.dbus;
2
3 import org.asamk.SignalControl;
4 import org.asamk.signal.BaseConfig;
5 import org.asamk.signal.DbusConfig;
6 import org.asamk.signal.manager.Manager;
7 import org.asamk.signal.manager.MultiAccountManager;
8 import org.asamk.signal.manager.ProvisioningManager;
9 import org.asamk.signal.manager.RegistrationManager;
10 import org.asamk.signal.manager.api.CaptchaRequiredException;
11 import org.asamk.signal.manager.api.IncorrectPinException;
12 import org.asamk.signal.manager.api.NonNormalizedPhoneNumberException;
13 import org.asamk.signal.manager.api.PinLockMissingException;
14 import org.asamk.signal.manager.api.PinLockedException;
15 import org.asamk.signal.manager.api.RateLimitException;
16 import org.asamk.signal.manager.api.UserAlreadyExistsException;
17 import org.asamk.signal.manager.api.VerificationMethodNotAvailableException;
18 import org.freedesktop.dbus.DBusPath;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 import java.io.IOException;
23 import java.net.URI;
24 import java.net.URISyntaxException;
25 import java.nio.channels.OverlappingFileLockException;
26 import java.util.List;
27 import java.util.concurrent.TimeoutException;
28
29 public class DbusSignalControlImpl implements org.asamk.SignalControl {
30
31 private static final Logger logger = LoggerFactory.getLogger(DbusSignalControlImpl.class);
32 private final MultiAccountManager c;
33
34 private final String objectPath;
35
36 public DbusSignalControlImpl(final MultiAccountManager c, final String objectPath) {
37 this.c = c;
38 this.objectPath = objectPath;
39 }
40
41 @Override
42 public boolean isRemote() {
43 return false;
44 }
45
46 @Override
47 public String getObjectPath() {
48 return objectPath;
49 }
50
51 @Override
52 public void register(
53 final String number,
54 final boolean voiceVerification
55 ) throws Error.Failure, Error.InvalidNumber {
56 registerWithCaptcha(number, voiceVerification, null);
57 }
58
59 @Override
60 public void registerWithCaptcha(
61 final String number,
62 final boolean voiceVerification,
63 final String captcha
64 ) throws Error.Failure, Error.InvalidNumber {
65 if (!Manager.isValidNumber(number, null)) {
66 throw new SignalControl.Error.InvalidNumber(
67 "Invalid account (phone number), make sure you include the country code.");
68 }
69 try (final RegistrationManager registrationManager = c.getNewRegistrationManager(number)) {
70 registrationManager.register(voiceVerification, captcha, false);
71 } catch (RateLimitException e) {
72 String message = "Rate limit reached";
73 throw new SignalControl.Error.Failure(message);
74 } catch (CaptchaRequiredException e) {
75 String message = captcha == null ? "Captcha required for verification." : "Invalid captcha given.";
76 throw new SignalControl.Error.RequiresCaptcha(message);
77 } catch (NonNormalizedPhoneNumberException e) {
78 throw new Error.InvalidNumber(e.getMessage());
79 } catch (OverlappingFileLockException e) {
80 throw new SignalControl.Error.Failure("Account is already in use");
81 } catch (IOException | VerificationMethodNotAvailableException e) {
82 throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage());
83 }
84 }
85
86 @Override
87 public void verify(final String number, final String verificationCode) throws Error.Failure, Error.InvalidNumber {
88 verifyWithPin(number, verificationCode, null);
89 }
90
91 @Override
92 public void verifyWithPin(
93 final String number,
94 final String verificationCode,
95 final String pin
96 ) throws Error.Failure, Error.InvalidNumber {
97 try (final RegistrationManager registrationManager = c.getNewRegistrationManager(number)) {
98 registrationManager.verifyAccount(verificationCode, pin);
99 } catch (OverlappingFileLockException e) {
100 throw new SignalControl.Error.Failure("Account is already in use");
101 } catch (IOException e) {
102 throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage());
103 } catch (PinLockedException e) {
104 throw new Error.Failure(
105 "Verification failed! This number is locked with a pin. Hours remaining until reset: "
106 + (e.getTimeRemaining() / 1000 / 60 / 60));
107 } catch (IncorrectPinException e) {
108 throw new Error.Failure("Verification failed! Invalid pin, tries remaining: " + e.getTriesRemaining());
109 } catch (PinLockMissingException e) {
110 throw new Error.Failure("Account is pin locked, but pin data has been deleted on the server.");
111 }
112 }
113
114 @Override
115 public String link(final String newDeviceName) throws Error.Failure {
116 final URI deviceLinkUri;
117 try {
118 deviceLinkUri = c.getNewProvisioningDeviceLinkUri();
119 } catch (TimeoutException | IOException e) {
120 throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage());
121 }
122 Thread.ofPlatform().name("dbus-link").start(() -> {
123 final ProvisioningManager provisioningManager = c.getProvisioningManagerFor(deviceLinkUri);
124 try {
125 provisioningManager.finishDeviceLink(newDeviceName);
126 } catch (IOException | TimeoutException | UserAlreadyExistsException e) {
127 logger.warn("Failed to finish linking", e);
128 }
129 });
130 return deviceLinkUri.toString();
131 }
132
133 @Override
134 public String startLink() throws Error.Failure {
135 try {
136 final URI deviceLinkUri = c.getNewProvisioningDeviceLinkUri();
137 return deviceLinkUri.toString();
138 } catch (TimeoutException | IOException e) {
139 throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage());
140 }
141 }
142
143 @Override
144 public String finishLink(String deviceLinkUri, final String newDeviceName) throws Error.Failure {
145 try {
146 final var provisioningManager = c.getProvisioningManagerFor(new URI(deviceLinkUri));
147 return provisioningManager.finishDeviceLink(newDeviceName);
148 } catch (TimeoutException | IOException | UserAlreadyExistsException | URISyntaxException e) {
149 throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage());
150 }
151 }
152
153 @Override
154 public String version() {
155 return BaseConfig.PROJECT_VERSION;
156 }
157
158 @Override
159 public List<DBusPath> listAccounts() {
160 return c.getAccountNumbers().stream().map(u -> new DBusPath(DbusConfig.getObjectPath(u))).toList();
161 }
162
163 @Override
164 public DBusPath getAccount(final String number) {
165 return new DBusPath(DbusConfig.getObjectPath(number));
166 }
167 }