1 package org
.asamk
.signal
.dbus
;
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
.PinLockedException
;
13 import org
.asamk
.signal
.manager
.api
.UserAlreadyExistsException
;
14 import org
.freedesktop
.dbus
.DBusPath
;
16 import java
.io
.IOException
;
18 import java
.net
.URISyntaxException
;
19 import java
.nio
.channels
.OverlappingFileLockException
;
20 import java
.util
.List
;
21 import java
.util
.concurrent
.TimeoutException
;
23 public class DbusSignalControlImpl
implements org
.asamk
.SignalControl
{
25 private final MultiAccountManager c
;
27 private final String objectPath
;
29 public DbusSignalControlImpl(final MultiAccountManager c
, final String objectPath
) {
31 this.objectPath
= objectPath
;
35 public boolean isRemote() {
40 public String
getObjectPath() {
46 final String number
, final boolean voiceVerification
47 ) throws Error
.Failure
, Error
.InvalidNumber
{
48 registerWithCaptcha(number
, voiceVerification
, null);
52 public void registerWithCaptcha(
53 final String number
, final boolean voiceVerification
, final String captcha
54 ) throws Error
.Failure
, Error
.InvalidNumber
{
55 if (!Manager
.isValidNumber(number
, null)) {
56 throw new SignalControl
.Error
.InvalidNumber(
57 "Invalid account (phone number), make sure you include the country code.");
59 try (final RegistrationManager registrationManager
= c
.getNewRegistrationManager(number
)) {
60 registrationManager
.register(voiceVerification
, captcha
);
61 } catch (CaptchaRequiredException e
) {
62 String message
= captcha
== null ?
"Captcha required for verification." : "Invalid captcha given.";
63 throw new SignalControl
.Error
.RequiresCaptcha(message
);
64 } catch (OverlappingFileLockException e
) {
65 throw new SignalControl
.Error
.Failure("Account is already in use");
66 } catch (IOException e
) {
67 throw new SignalControl
.Error
.Failure(e
.getClass().getSimpleName() + " " + e
.getMessage());
72 public void verify(final String number
, final String verificationCode
) throws Error
.Failure
, Error
.InvalidNumber
{
73 verifyWithPin(number
, verificationCode
, null);
77 public void verifyWithPin(
78 final String number
, final String verificationCode
, final String pin
79 ) throws Error
.Failure
, Error
.InvalidNumber
{
80 try (final RegistrationManager registrationManager
= c
.getNewRegistrationManager(number
)) {
81 registrationManager
.verifyAccount(verificationCode
, pin
);
82 } catch (OverlappingFileLockException e
) {
83 throw new SignalControl
.Error
.Failure("Account is already in use");
84 } catch (IOException e
) {
85 throw new SignalControl
.Error
.Failure(e
.getClass().getSimpleName() + " " + e
.getMessage());
86 } catch (PinLockedException e
) {
87 throw new Error
.Failure(
88 "Verification failed! This number is locked with a pin. Hours remaining until reset: "
89 + (e
.getTimeRemaining() / 1000 / 60 / 60));
90 } catch (IncorrectPinException e
) {
91 throw new Error
.Failure("Verification failed! Invalid pin, tries remaining: " + e
.getTriesRemaining());
96 public String
link(final String newDeviceName
) throws Error
.Failure
{
98 final URI deviceLinkUri
= c
.getNewProvisioningDeviceLinkUri();
99 final var thread
= new Thread(() -> {
100 final ProvisioningManager provisioningManager
= c
.getProvisioningManagerFor(deviceLinkUri
);
102 provisioningManager
.finishDeviceLink(newDeviceName
);
103 } catch (IOException
| TimeoutException
| UserAlreadyExistsException e
) {
107 thread
.setName("dbus-link");
109 return deviceLinkUri
.toString();
110 } catch (TimeoutException
| IOException e
) {
111 throw new SignalControl
.Error
.Failure(e
.getClass().getSimpleName() + " " + e
.getMessage());
116 public String
startLink() throws Error
.Failure
{
118 final URI deviceLinkUri
= c
.getNewProvisioningDeviceLinkUri();
119 return deviceLinkUri
.toString();
120 } catch (TimeoutException
| IOException e
) {
121 throw new SignalControl
.Error
.Failure(e
.getClass().getSimpleName() + " " + e
.getMessage());
126 public String
finishLink(String deviceLinkUri
, final String newDeviceName
) throws Error
.Failure
{
128 final var provisioningManager
= c
.getProvisioningManagerFor(new URI(deviceLinkUri
));
129 return provisioningManager
.finishDeviceLink(newDeviceName
);
130 } catch (TimeoutException
| IOException
| UserAlreadyExistsException
| URISyntaxException e
) {
131 throw new SignalControl
.Error
.Failure(e
.getClass().getSimpleName() + " " + e
.getMessage());
136 public String
version() {
137 return BaseConfig
.PROJECT_VERSION
;
141 public List
<DBusPath
> listAccounts() {
142 return c
.getAccountNumbers().stream().map(u
-> new DBusPath(DbusConfig
.getObjectPath(u
))).toList();
146 public DBusPath
getAccount(final String number
) {
147 return new DBusPath(DbusConfig
.getObjectPath(number
));