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