]> nmode's Git Repositories - signal-cli/commitdiff
Refactor Manager interface
authorAsamK <asamk@gmx.de>
Sat, 18 Sep 2021 08:19:56 +0000 (10:19 +0200)
committerAsamK <asamk@gmx.de>
Tue, 28 Sep 2021 19:13:02 +0000 (21:13 +0200)
33 files changed:
lib/src/main/java/org/asamk/signal/manager/Manager.java
lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java
lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java
lib/src/main/java/org/asamk/signal/manager/UserAlreadyExists.java
lib/src/main/java/org/asamk/signal/manager/api/Device.java
lib/src/main/java/org/asamk/signal/manager/api/Group.java [new file with mode: 0644]
lib/src/main/java/org/asamk/signal/manager/api/Identity.java [new file with mode: 0644]
lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java
lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientAddress.java
src/main/java/org/asamk/Signal.java
src/main/java/org/asamk/signal/App.java
src/main/java/org/asamk/signal/ReceiveMessageHandler.java
src/main/java/org/asamk/signal/commands/BlockCommand.java
src/main/java/org/asamk/signal/commands/DaemonCommand.java
src/main/java/org/asamk/signal/commands/JoinGroupCommand.java
src/main/java/org/asamk/signal/commands/LinkCommand.java
src/main/java/org/asamk/signal/commands/ListContactsCommand.java
src/main/java/org/asamk/signal/commands/ListDevicesCommand.java
src/main/java/org/asamk/signal/commands/ListGroupsCommand.java
src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java
src/main/java/org/asamk/signal/commands/QuitGroupCommand.java
src/main/java/org/asamk/signal/commands/SendReactionCommand.java
src/main/java/org/asamk/signal/commands/SendReceiptCommand.java
src/main/java/org/asamk/signal/commands/SendTypingCommand.java
src/main/java/org/asamk/signal/commands/TrustCommand.java
src/main/java/org/asamk/signal/commands/UnblockCommand.java
src/main/java/org/asamk/signal/commands/UpdateContactCommand.java
src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java
src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java
src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java
src/main/java/org/asamk/signal/json/JsonMention.java
src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java
src/main/java/org/asamk/signal/util/CommandUtil.java

index d2eb0f8f04270bdfed61099ff360ea3e1148e37c..cba438f817d1e3d634f31f9b06c0c30366a8b819 100644 (file)
@@ -1,6 +1,8 @@
 package org.asamk.signal.manager;
 
 import org.asamk.signal.manager.api.Device;
+import org.asamk.signal.manager.api.Group;
+import org.asamk.signal.manager.api.Identity;
 import org.asamk.signal.manager.api.Message;
 import org.asamk.signal.manager.api.RecipientIdentifier;
 import org.asamk.signal.manager.api.SendGroupMessageResults;
@@ -17,12 +19,10 @@ import org.asamk.signal.manager.groups.GroupSendingNotAllowedException;
 import org.asamk.signal.manager.groups.LastGroupAdminException;
 import org.asamk.signal.manager.groups.NotAGroupMemberException;
 import org.asamk.signal.manager.storage.SignalAccount;
-import org.asamk.signal.manager.storage.groups.GroupInfo;
-import org.asamk.signal.manager.storage.identities.IdentityInfo;
 import org.asamk.signal.manager.storage.identities.TrustNewIdentity;
 import org.asamk.signal.manager.storage.recipients.Contact;
 import org.asamk.signal.manager.storage.recipients.Profile;
-import org.asamk.signal.manager.storage.recipients.RecipientId;
+import org.asamk.signal.manager.storage.recipients.RecipientAddress;
 import org.whispersystems.libsignal.IdentityKey;
 import org.whispersystems.libsignal.InvalidKeyException;
 import org.whispersystems.libsignal.util.Pair;
@@ -51,7 +51,7 @@ import java.util.stream.Collectors;
 public interface Manager extends Closeable {
 
     static Manager init(
-            String username,
+            String number,
             File settingsPath,
             ServiceEnvironment serviceEnvironment,
             String userAgent,
@@ -59,11 +59,11 @@ public interface Manager extends Closeable {
     ) throws IOException, NotRegisteredException {
         var pathConfig = PathConfig.createDefault(settingsPath);
 
-        if (!SignalAccount.userExists(pathConfig.getDataPath(), username)) {
+        if (!SignalAccount.userExists(pathConfig.getDataPath(), number)) {
             throw new NotRegisteredException();
         }
 
-        var account = SignalAccount.load(pathConfig.getDataPath(), username, true, trustNewIdentity);
+        var account = SignalAccount.load(pathConfig.getDataPath(), number, true, trustNewIdentity);
 
         if (!account.isRegistered()) {
             throw new NotRegisteredException();
@@ -74,7 +74,7 @@ public interface Manager extends Closeable {
         return new ManagerImpl(account, pathConfig, serviceEnvironmentConfig, userAgent);
     }
 
-    static List<String> getAllLocalUsernames(File settingsPath) {
+    static List<String> getAllLocalNumbers(File settingsPath) {
         var pathConfig = PathConfig.createDefault(settingsPath);
         final var dataPath = pathConfig.getDataPath();
         final var files = dataPath.listFiles();
@@ -90,11 +90,7 @@ public interface Manager extends Closeable {
                 .collect(Collectors.toList());
     }
 
-    String getUsername();
-
-    RecipientId getSelfRecipientId();
-
-    int getDeviceId();
+    String getSelfNumber();
 
     void checkAccountState() throws IOException;
 
@@ -120,9 +116,9 @@ public interface Manager extends Closeable {
 
     void setRegistrationLockPin(Optional<String> pin) throws IOException, UnauthenticatedResponseException;
 
-    Profile getRecipientProfile(RecipientId recipientId);
+    Profile getRecipientProfile(RecipientIdentifier.Single recipient) throws UnregisteredUserException;
 
-    List<GroupInfo> getGroups();
+    List<Group> getGroups();
 
     SendGroupMessageResults quitGroup(
             GroupId groupId, Set<RecipientIdentifier.Single> groupAdmins
@@ -221,15 +217,15 @@ public interface Manager extends Closeable {
 
     void sendContacts() throws IOException;
 
-    List<Pair<RecipientId, Contact>> getContacts();
+    List<Pair<RecipientAddress, Contact>> getContacts();
 
-    String getContactOrProfileName(RecipientIdentifier.Single recipientIdentifier);
+    String getContactOrProfileName(RecipientIdentifier.Single recipient);
 
-    GroupInfo getGroup(GroupId groupId);
+    Group getGroup(GroupId groupId);
 
-    List<IdentityInfo> getIdentities();
+    List<Identity> getIdentities();
 
-    List<IdentityInfo> getIdentities(RecipientIdentifier.Single recipient);
+    List<Identity> getIdentities(RecipientIdentifier.Single recipient);
 
     boolean trustIdentityVerified(RecipientIdentifier.Single recipient, byte[] fingerprint);
 
@@ -241,14 +237,8 @@ public interface Manager extends Closeable {
 
     String computeSafetyNumber(SignalServiceAddress theirAddress, IdentityKey theirIdentityKey);
 
-    byte[] computeSafetyNumberForScanning(SignalServiceAddress theirAddress, IdentityKey theirIdentityKey);
-
     SignalServiceAddress resolveSignalServiceAddress(SignalServiceAddress address);
 
-    SignalServiceAddress resolveSignalServiceAddress(UUID uuid);
-
-    SignalServiceAddress resolveSignalServiceAddress(RecipientId recipientId);
-
     @Override
     void close() throws IOException;
 
index d0fab3503330ae598ea6d157e76865073566d9d8..de60fa50aa8ce8b90d00f7727ef00e95c7fad763 100644 (file)
@@ -18,6 +18,8 @@ package org.asamk.signal.manager;
 
 import org.asamk.signal.manager.actions.HandleAction;
 import org.asamk.signal.manager.api.Device;
+import org.asamk.signal.manager.api.Group;
+import org.asamk.signal.manager.api.Identity;
 import org.asamk.signal.manager.api.Message;
 import org.asamk.signal.manager.api.RecipientIdentifier;
 import org.asamk.signal.manager.api.SendGroupMessageResults;
@@ -52,6 +54,7 @@ import org.asamk.signal.manager.storage.identities.IdentityInfo;
 import org.asamk.signal.manager.storage.messageCache.CachedMessage;
 import org.asamk.signal.manager.storage.recipients.Contact;
 import org.asamk.signal.manager.storage.recipients.Profile;
+import org.asamk.signal.manager.storage.recipients.RecipientAddress;
 import org.asamk.signal.manager.storage.recipients.RecipientId;
 import org.asamk.signal.manager.storage.stickers.Sticker;
 import org.asamk.signal.manager.storage.stickers.StickerPackId;
@@ -196,7 +199,7 @@ public class ManagerImpl implements Manager {
                 this::resolveSignalServiceAddress,
                 account.getRecipientStore(),
                 this::handleIdentityFailure,
-                this::getGroup,
+                this::getGroupInfo,
                 this::refreshRegisteredUser);
         this.groupHelper = new GroupHelper(account,
                 dependencies,
@@ -240,20 +243,10 @@ public class ManagerImpl implements Manager {
     }
 
     @Override
-    public String getUsername() {
+    public String getSelfNumber() {
         return account.getUsername();
     }
 
-    @Override
-    public RecipientId getSelfRecipientId() {
-        return account.getSelfRecipientId();
-    }
-
-    @Override
-    public int getDeviceId() {
-        return account.getDeviceId();
-    }
-
     @Override
     public void checkAccountState() throws IOException {
         if (account.getLastReceiveTimestamp() == 0) {
@@ -385,7 +378,11 @@ public class ManagerImpl implements Manager {
                     logger.debug("Failed to decrypt device name, maybe plain text?", e);
                 }
             }
-            return new Device(d.getId(), deviceName, d.getCreated(), d.getLastSeen());
+            return new Device(d.getId(),
+                    deviceName,
+                    d.getCreated(),
+                    d.getLastSeen(),
+                    d.getId() == account.getDeviceId());
         }).collect(Collectors.toList());
     }
 
@@ -442,13 +439,48 @@ public class ManagerImpl implements Manager {
     }
 
     @Override
-    public Profile getRecipientProfile(RecipientId recipientId) {
+    public Profile getRecipientProfile(RecipientIdentifier.Single recipient) throws UnregisteredUserException {
+        return profileHelper.getRecipientProfile(resolveRecipient(recipient));
+    }
+
+    private Profile getRecipientProfile(RecipientId recipientId) {
         return profileHelper.getRecipientProfile(recipientId);
     }
 
     @Override
-    public List<GroupInfo> getGroups() {
-        return account.getGroupStore().getGroups();
+    public List<Group> getGroups() {
+        return account.getGroupStore().getGroups().stream().map(this::toGroup).collect(Collectors.toList());
+    }
+
+    private Group toGroup(final GroupInfo groupInfo) {
+        if (groupInfo == null) {
+            return null;
+        }
+
+        return new Group(groupInfo.getGroupId(),
+                groupInfo.getTitle(),
+                groupInfo.getDescription(),
+                groupInfo.getGroupInviteLink(),
+                groupInfo.getMembers()
+                        .stream()
+                        .map(account.getRecipientStore()::resolveRecipientAddress)
+                        .collect(Collectors.toSet()),
+                groupInfo.getPendingMembers()
+                        .stream()
+                        .map(account.getRecipientStore()::resolveRecipientAddress)
+                        .collect(Collectors.toSet()),
+                groupInfo.getRequestingMembers()
+                        .stream()
+                        .map(account.getRecipientStore()::resolveRecipientAddress)
+                        .collect(Collectors.toSet()),
+                groupInfo.getAdminMembers()
+                        .stream()
+                        .map(account.getRecipientStore()::resolveRecipientAddress)
+                        .collect(Collectors.toSet()),
+                groupInfo.isBlocked(),
+                groupInfo.getMessageExpirationTime(),
+                groupInfo.isAnnouncementGroup(),
+                groupInfo.isMember(account.getSelfRecipientId()));
     }
 
     @Override
@@ -973,15 +1005,19 @@ public class ManagerImpl implements Manager {
     }
 
     @Override
-    public List<Pair<RecipientId, Contact>> getContacts() {
-        return account.getContactStore().getContacts();
+    public List<Pair<RecipientAddress, Contact>> getContacts() {
+        return account.getContactStore()
+                .getContacts()
+                .stream()
+                .map(p -> new Pair<>(account.getRecipientStore().resolveRecipientAddress(p.first()), p.second()))
+                .collect(Collectors.toList());
     }
 
     @Override
-    public String getContactOrProfileName(RecipientIdentifier.Single recipientIdentifier) {
+    public String getContactOrProfileName(RecipientIdentifier.Single recipient) {
         final RecipientId recipientId;
         try {
-            recipientId = resolveRecipient(recipientIdentifier);
+            recipientId = resolveRecipient(recipient);
         } catch (UnregisteredUserException e) {
             return null;
         }
@@ -1000,24 +1036,46 @@ public class ManagerImpl implements Manager {
     }
 
     @Override
-    public GroupInfo getGroup(GroupId groupId) {
+    public Group getGroup(GroupId groupId) {
+        return toGroup(groupHelper.getGroup(groupId));
+    }
+
+    public GroupInfo getGroupInfo(GroupId groupId) {
         return groupHelper.getGroup(groupId);
     }
 
     @Override
-    public List<IdentityInfo> getIdentities() {
-        return account.getIdentityKeyStore().getIdentities();
+    public List<Identity> getIdentities() {
+        return account.getIdentityKeyStore()
+                .getIdentities()
+                .stream()
+                .map(this::toIdentity)
+                .collect(Collectors.toList());
+    }
+
+    private Identity toIdentity(final IdentityInfo identityInfo) {
+        if (identityInfo == null) {
+            return null;
+        }
+
+        final var address = account.getRecipientStore().resolveRecipientAddress(identityInfo.getRecipientId());
+        return new Identity(address,
+                identityInfo.getIdentityKey(),
+                computeSafetyNumber(address.toSignalServiceAddress(), identityInfo.getIdentityKey()),
+                computeSafetyNumberForScanning(address.toSignalServiceAddress(), identityInfo.getIdentityKey()),
+                identityInfo.getTrustLevel(),
+                identityInfo.getDateAdded());
     }
 
     @Override
-    public List<IdentityInfo> getIdentities(RecipientIdentifier.Single recipient) {
+    public List<Identity> getIdentities(RecipientIdentifier.Single recipient) {
         IdentityInfo identity;
         try {
             identity = account.getIdentityKeyStore().getIdentity(resolveRecipient(recipient));
         } catch (UnregisteredUserException e) {
             identity = null;
         }
-        return identity == null ? List.of() : List.of(identity);
+        return identity == null ? List.of() : List.of(toIdentity(identity));
     }
 
     /**
@@ -1144,8 +1202,7 @@ public class ManagerImpl implements Manager {
         return fingerprint == null ? null : fingerprint.getDisplayableFingerprint().getDisplayText();
     }
 
-    @Override
-    public byte[] computeSafetyNumberForScanning(SignalServiceAddress theirAddress, IdentityKey theirIdentityKey) {
+    private byte[] computeSafetyNumberForScanning(SignalServiceAddress theirAddress, IdentityKey theirIdentityKey) {
         final Fingerprint fingerprint = computeSafetyNumberFingerprint(theirAddress, theirIdentityKey);
         return fingerprint == null ? null : fingerprint.getScannableFingerprint().getSerialized();
     }
@@ -1165,13 +1222,7 @@ public class ManagerImpl implements Manager {
         return resolveSignalServiceAddress(resolveRecipient(address));
     }
 
-    @Override
-    public SignalServiceAddress resolveSignalServiceAddress(UUID uuid) {
-        return resolveSignalServiceAddress(account.getRecipientStore().resolveRecipient(uuid));
-    }
-
-    @Override
-    public SignalServiceAddress resolveSignalServiceAddress(RecipientId recipientId) {
+    private SignalServiceAddress resolveSignalServiceAddress(RecipientId recipientId) {
         final var address = account.getRecipientStore().resolveRecipientAddress(recipientId);
         if (address.getUuid().isPresent()) {
             return address.toSignalServiceAddress();
@@ -1180,13 +1231,15 @@ public class ManagerImpl implements Manager {
         // Address in recipient store doesn't have a uuid, this shouldn't happen
         // Try to retrieve the uuid from the server
         final var number = address.getNumber().get();
+        final UUID uuid;
         try {
-            return resolveSignalServiceAddress(getRegisteredUser(number));
+            uuid = getRegisteredUser(number);
         } catch (IOException e) {
             logger.warn("Failed to get uuid for e164 number: {}", number, e);
             // Return SignalServiceAddress with unknown UUID
             return address.toSignalServiceAddress();
         }
+        return resolveSignalServiceAddress(account.getRecipientStore().resolveRecipient(uuid));
     }
 
     private Set<RecipientId> resolveRecipients(Collection<RecipientIdentifier.Single> recipients) throws UnregisteredUserException {
index 978f1fd556a58b409c9ca0acde4dc955be91adb9..ff94c19b400ca36be81c4262f3b52ac18c6f1601 100644 (file)
@@ -91,18 +91,18 @@ public class RegistrationManager implements Closeable {
     }
 
     public static RegistrationManager init(
-            String username, File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent
+            String number, File settingsPath, ServiceEnvironment serviceEnvironment, String userAgent
     ) throws IOException {
         var pathConfig = PathConfig.createDefault(settingsPath);
 
         final var serviceConfiguration = ServiceConfig.getServiceEnvironmentConfig(serviceEnvironment, userAgent);
-        if (!SignalAccount.userExists(pathConfig.getDataPath(), username)) {
+        if (!SignalAccount.userExists(pathConfig.getDataPath(), number)) {
             var identityKey = KeyUtils.generateIdentityKeyPair();
             var registrationId = KeyHelper.generateRegistrationId(false);
 
             var profileKey = KeyUtils.createProfileKey();
             var account = SignalAccount.create(pathConfig.getDataPath(),
-                    username,
+                    number,
                     identityKey,
                     registrationId,
                     profileKey,
@@ -111,7 +111,7 @@ public class RegistrationManager implements Closeable {
             return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent);
         }
 
-        var account = SignalAccount.load(pathConfig.getDataPath(), username, true, TrustNewIdentity.ON_FIRST_USE);
+        var account = SignalAccount.load(pathConfig.getDataPath(), number, true, TrustNewIdentity.ON_FIRST_USE);
 
         return new RegistrationManager(account, pathConfig, serviceConfiguration, userAgent);
     }
index d506f0c61d4751a9ea6aedf6500fe0ae9818fea6..905392c56ec51d560676248999e7e263d7a0ddac 100644 (file)
@@ -4,16 +4,16 @@ import java.io.File;
 
 public class UserAlreadyExists extends Exception {
 
-    private final String username;
+    private final String number;
     private final File fileName;
 
-    public UserAlreadyExists(String username, File fileName) {
-        this.username = username;
+    public UserAlreadyExists(String number, File fileName) {
+        this.number = number;
         this.fileName = fileName;
     }
 
-    public String getUsername() {
-        return username;
+    public String getNumber() {
+        return number;
     }
 
     public File getFileName() {
index 76074cbf6b7cc425a60ea968797dec1e7b069f94..9ee0d36a7b1641aa7fcc54e1b4b0932d392c57e3 100644 (file)
@@ -6,12 +6,14 @@ public class Device {
     private final String name;
     private final long created;
     private final long lastSeen;
+    private final boolean thisDevice;
 
-    public Device(long id, String name, long created, long lastSeen) {
+    public Device(long id, String name, long created, long lastSeen, final boolean thisDevice) {
         this.id = id;
         this.name = name;
         this.created = created;
         this.lastSeen = lastSeen;
+        this.thisDevice = thisDevice;
     }
 
     public long getId() {
@@ -29,4 +31,8 @@ public class Device {
     public long getLastSeen() {
         return lastSeen;
     }
+
+    public boolean isThisDevice() {
+        return thisDevice;
+    }
 }
diff --git a/lib/src/main/java/org/asamk/signal/manager/api/Group.java b/lib/src/main/java/org/asamk/signal/manager/api/Group.java
new file mode 100644 (file)
index 0000000..650e10b
--- /dev/null
@@ -0,0 +1,99 @@
+package org.asamk.signal.manager.api;
+
+import org.asamk.signal.manager.groups.GroupId;
+import org.asamk.signal.manager.groups.GroupInviteLinkUrl;
+import org.asamk.signal.manager.storage.recipients.RecipientAddress;
+
+import java.util.Set;
+
+public class Group {
+
+    private final GroupId groupId;
+    private final String title;
+    private final String description;
+    private final GroupInviteLinkUrl groupInviteLinkUrl;
+    private final Set<RecipientAddress> members;
+    private final Set<RecipientAddress> pendingMembers;
+    private final Set<RecipientAddress> requestingMembers;
+    private final Set<RecipientAddress> adminMembers;
+    private final boolean isBlocked;
+    private final int messageExpirationTime;
+    private final boolean isAnnouncementGroup;
+    private final boolean isMember;
+
+    public Group(
+            final GroupId groupId,
+            final String title,
+            final String description,
+            final GroupInviteLinkUrl groupInviteLinkUrl,
+            final Set<RecipientAddress> members,
+            final Set<RecipientAddress> pendingMembers,
+            final Set<RecipientAddress> requestingMembers,
+            final Set<RecipientAddress> adminMembers,
+            final boolean isBlocked,
+            final int messageExpirationTime,
+            final boolean isAnnouncementGroup,
+            final boolean isMember
+    ) {
+        this.groupId = groupId;
+        this.title = title;
+        this.description = description;
+        this.groupInviteLinkUrl = groupInviteLinkUrl;
+        this.members = members;
+        this.pendingMembers = pendingMembers;
+        this.requestingMembers = requestingMembers;
+        this.adminMembers = adminMembers;
+        this.isBlocked = isBlocked;
+        this.messageExpirationTime = messageExpirationTime;
+        this.isAnnouncementGroup = isAnnouncementGroup;
+        this.isMember = isMember;
+    }
+
+    public GroupId getGroupId() {
+        return groupId;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public GroupInviteLinkUrl getGroupInviteLinkUrl() {
+        return groupInviteLinkUrl;
+    }
+
+    public Set<RecipientAddress> getMembers() {
+        return members;
+    }
+
+    public Set<RecipientAddress> getPendingMembers() {
+        return pendingMembers;
+    }
+
+    public Set<RecipientAddress> getRequestingMembers() {
+        return requestingMembers;
+    }
+
+    public Set<RecipientAddress> getAdminMembers() {
+        return adminMembers;
+    }
+
+    public boolean isBlocked() {
+        return isBlocked;
+    }
+
+    public int getMessageExpirationTime() {
+        return messageExpirationTime;
+    }
+
+    public boolean isAnnouncementGroup() {
+        return isAnnouncementGroup;
+    }
+
+    public boolean isMember() {
+        return isMember;
+    }
+}
diff --git a/lib/src/main/java/org/asamk/signal/manager/api/Identity.java b/lib/src/main/java/org/asamk/signal/manager/api/Identity.java
new file mode 100644 (file)
index 0000000..4f6f21f
--- /dev/null
@@ -0,0 +1,65 @@
+package org.asamk.signal.manager.api;
+
+import org.asamk.signal.manager.TrustLevel;
+import org.asamk.signal.manager.storage.recipients.RecipientAddress;
+import org.whispersystems.libsignal.IdentityKey;
+
+import java.util.Date;
+
+public class Identity {
+
+    private final RecipientAddress recipient;
+    private final IdentityKey identityKey;
+    private final String safetyNumber;
+    private final byte[] scannableSafetyNumber;
+    private final TrustLevel trustLevel;
+    private final Date dateAdded;
+
+    public Identity(
+            final RecipientAddress recipient,
+            final IdentityKey identityKey,
+            final String safetyNumber,
+            final byte[] scannableSafetyNumber,
+            final TrustLevel trustLevel,
+            final Date dateAdded
+    ) {
+        this.recipient = recipient;
+        this.identityKey = identityKey;
+        this.safetyNumber = safetyNumber;
+        this.scannableSafetyNumber = scannableSafetyNumber;
+        this.trustLevel = trustLevel;
+        this.dateAdded = dateAdded;
+    }
+
+    public RecipientAddress getRecipient() {
+        return recipient;
+    }
+
+    public IdentityKey getIdentityKey() {
+        return this.identityKey;
+    }
+
+    public TrustLevel getTrustLevel() {
+        return this.trustLevel;
+    }
+
+    boolean isTrusted() {
+        return trustLevel == TrustLevel.TRUSTED_UNVERIFIED || trustLevel == TrustLevel.TRUSTED_VERIFIED;
+    }
+
+    public Date getDateAdded() {
+        return this.dateAdded;
+    }
+
+    public byte[] getFingerprint() {
+        return identityKey.getPublicKey().serialize();
+    }
+
+    public String getSafetyNumber() {
+        return safetyNumber;
+    }
+
+    public byte[] getScannableSafetyNumber() {
+        return scannableSafetyNumber;
+    }
+}
index cb0a08bbc3538fd19a62fe021a6904dc2c2c533a..be1029e69be4baedc4048103dc82a2f3150e40e9 100644 (file)
@@ -1,6 +1,7 @@
 package org.asamk.signal.manager.api;
 
 import org.asamk.signal.manager.groups.GroupId;
+import org.asamk.signal.manager.storage.recipients.RecipientAddress;
 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
 import org.whispersystems.signalservice.api.util.InvalidNumberException;
 import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
@@ -29,6 +30,17 @@ public abstract class RecipientIdentifier {
         public static Single fromAddress(SignalServiceAddress address) {
             return new Uuid(address.getUuid());
         }
+
+        public static Single fromAddress(RecipientAddress address) {
+            if (address.getNumber().isPresent()) {
+                return new Number(address.getNumber().get());
+            } else if (address.getUuid().isPresent()) {
+                return new Uuid(address.getUuid().get());
+            }
+            throw new AssertionError("RecipientAddress without identifier");
+        }
+
+        public abstract String getIdentifier();
     }
 
     public static class Uuid extends Single {
@@ -53,6 +65,11 @@ public abstract class RecipientIdentifier {
         public int hashCode() {
             return uuid.hashCode();
         }
+
+        @Override
+        public String getIdentifier() {
+            return uuid.toString();
+        }
     }
 
     public static class Number extends Single {
@@ -77,6 +94,11 @@ public abstract class RecipientIdentifier {
         public int hashCode() {
             return number.hashCode();
         }
+
+        @Override
+        public String getIdentifier() {
+            return number;
+        }
     }
 
     public static class Group extends RecipientIdentifier {
index 88877d8380ac560cb1799da72ec2960e8cc78012..c0f5b0b8d1cb90dd35102e6859060e5152fcde1f 100644 (file)
@@ -57,6 +57,16 @@ public class RecipientAddress {
         }
     }
 
+    public String getLegacyIdentifier() {
+        if (e164.isPresent()) {
+            return e164.get();
+        } else if (uuid.isPresent()) {
+            return uuid.get().toString();
+        } else {
+            throw new AssertionError("Given the checks in the constructor, this should not be possible.");
+        }
+    }
+
     public boolean matches(RecipientAddress other) {
         return (uuid.isPresent() && other.uuid.isPresent() && uuid.get().equals(other.uuid.get())) || (
                 e164.isPresent() && other.e164.isPresent() && e164.get().equals(other.e164.get())
index b19fba8dbf383f6a38d29433074a9d3865cd6fe2..2105ca76f330e5daaad111845cd8e3839f41bf2f 100644 (file)
@@ -13,6 +13,8 @@ import java.util.List;
  */
 public interface Signal extends DBusInterface {
 
+    String getNumber();
+
     long sendMessage(
             String message, List<String> attachments, String recipient
     ) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
@@ -26,7 +28,7 @@ public interface Signal extends DBusInterface {
     ) throws Error.Failure, Error.GroupNotFound, Error.UntrustedIdentity;
 
     void sendReadReceipt(
-            String recipient, List<Long> targetSentTimestamp
+            String recipient, List<Long> messageIds
     ) throws Error.Failure, Error.UntrustedIdentity;
 
     long sendRemoteDeleteMessage(
index 4aa510d61d2d967fd96df08d33c8d609dc27ba81..e81b7018cbb910031710c3ca6efb5830ebd5506e 100644 (file)
@@ -161,7 +161,7 @@ public class App {
         }
 
         if (username == null) {
-            var usernames = Manager.getAllLocalUsernames(dataPath);
+            var usernames = Manager.getAllLocalNumbers(dataPath);
 
             if (command instanceof MultiLocalCommand) {
                 handleMultiLocalCommand((MultiLocalCommand) command,
index bc9244f8b5822553d40f33076628bcc088769909..35790678cd379fb3c331cf121ae48da2cfc884c2 100644 (file)
@@ -61,13 +61,13 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
                     final var recipientName = getLegacyIdentifier(m.resolveSignalServiceAddress(e.getSender()));
                     writer.println(
                             "Use 'signal-cli -u {} listIdentities -n {}', verify the key and run 'signal-cli -u {} trust -v \"FINGER_PRINT\" {}' to mark it as trusted",
-                            m.getUsername(),
+                            m.getSelfNumber(),
                             recipientName,
-                            m.getUsername(),
+                            m.getSelfNumber(),
                             recipientName);
                     writer.println(
                             "If you don't care about security, use 'signal-cli -u {} trust -a {}' to trust it without verification",
-                            m.getUsername(),
+                            m.getSelfNumber(),
                             recipientName);
                 } else {
                     writer.println("Exception: {} ({})", exception.getMessage(), exception.getClass().getSimpleName());
@@ -657,7 +657,7 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
     private void printMention(
             PlainTextWriter writer, SignalServiceDataMessage.Mention mention
     ) {
-        final var address = m.resolveSignalServiceAddress(mention.getUuid());
+        final var address = m.resolveSignalServiceAddress(new SignalServiceAddress(mention.getUuid()));
         writer.println("- {}: {} (length: {})", formatContact(address), mention.getStart(), mention.getLength());
     }
 
index 5394022ecbe53acc77522f3b482857d769974a22..516224f550cd6790eec90d9d0fd4c81c615d375e 100644 (file)
@@ -37,7 +37,7 @@ public class BlockCommand implements JsonRpcLocalCommand {
             final Namespace ns, final Manager m, final OutputWriter outputWriter
     ) throws CommandException {
         final var contacts = ns.<String>getList("recipient");
-        for (var contact : CommandUtil.getSingleRecipientIdentifiers(contacts, m.getUsername())) {
+        for (var contact : CommandUtil.getSingleRecipientIdentifiers(contacts, m.getSelfNumber())) {
             try {
                 m.setContactBlocked(contact, true);
             } catch (NotMasterDeviceException e) {
index 4a322b993e82b4d2870156be2368ecceea35f7fe..9878de1595a5bd338ecb904ac27063cd51392114 100644 (file)
@@ -95,7 +95,7 @@ public class DaemonCommand implements MultiLocalCommand {
         try (var conn = DBusConnection.getConnection(busType)) {
             final var signalControl = new DbusSignalControlImpl(c, m -> {
                 try {
-                    final var objectPath = DbusConfig.getObjectPath(m.getUsername());
+                    final var objectPath = DbusConfig.getObjectPath(m.getSelfNumber());
                     return run(conn, objectPath, m, outputWriter, ignoreAttachments);
                 } catch (DBusException e) {
                     logger.error("Failed to export object", e);
index f55858811078583042656ed4661379dc63de1dce..1e06ea9ce9d3ca349cb76f4e0136b1e74f455876 100644 (file)
@@ -57,14 +57,14 @@ public class JoinGroupCommand implements JsonRpcLocalCommand {
             var newGroupId = results.first();
             if (outputWriter instanceof JsonWriter) {
                 final var writer = (JsonWriter) outputWriter;
-                if (!m.getGroup(newGroupId).isMember(m.getSelfRecipientId())) {
+                if (!m.getGroup(newGroupId).isMember()) {
                     writer.write(Map.of("groupId", newGroupId.toBase64(), "onlyRequested", true));
                 } else {
                     writer.write(Map.of("groupId", newGroupId.toBase64()));
                 }
             } else {
                 final var writer = (PlainTextWriter) outputWriter;
-                if (!m.getGroup(newGroupId).isMember(m.getSelfRecipientId())) {
+                if (!m.getGroup(newGroupId).isMember()) {
                     writer.println("Requested to join group \"{}\"", newGroupId.toBase64());
                 } else {
                     writer.println("Joined group \"{}\"", newGroupId.toBase64());
index fbc0330062c3bef1418a3a42bdcd85f4d4ceda3c..1d697299dc950657a350f198c1b43b08de02b940 100644 (file)
@@ -44,7 +44,7 @@ public class LinkCommand implements ProvisioningCommand {
         try {
             writer.println("{}", m.getDeviceLinkUri());
             try (var manager = m.finishDeviceLink(deviceName)) {
-                writer.println("Associated with: {}", manager.getUsername());
+                writer.println("Associated with: {}", manager.getSelfNumber());
             }
         } catch (TimeoutException e) {
             throw new UserErrorException("Link request timed out, please try again.");
@@ -52,7 +52,7 @@ public class LinkCommand implements ProvisioningCommand {
             throw new IOErrorException("Link request error: " + e.getMessage(), e);
         } catch (UserAlreadyExists e) {
             throw new UserErrorException("The user "
-                    + e.getUsername()
+                    + e.getNumber()
                     + " already exists\nDelete \""
                     + e.getFileName()
                     + "\" before trying again.");
index 5e609a48e45afd54f2159eee962614e612d648d9..b6dfc3ce229c92d2320ae579754dbb0035e6b42d 100644 (file)
@@ -8,10 +8,9 @@ import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriter;
 import org.asamk.signal.manager.Manager;
 
+import java.util.UUID;
 import java.util.stream.Collectors;
 
-import static org.asamk.signal.util.Util.getLegacyIdentifier;
-
 public class ListContactsCommand implements JsonRpcLocalCommand {
 
     @Override
@@ -33,7 +32,7 @@ public class ListContactsCommand implements JsonRpcLocalCommand {
             for (var c : contacts) {
                 final var contact = c.second();
                 writer.println("Number: {} Name: {} Blocked: {} Message expiration: {}",
-                        getLegacyIdentifier(m.resolveSignalServiceAddress(c.first())),
+                        c.first().getLegacyIdentifier(),
                         contact.getName(),
                         contact.isBlocked(),
                         contact.getMessageExpirationTime() == 0
@@ -43,10 +42,10 @@ public class ListContactsCommand implements JsonRpcLocalCommand {
         } else {
             final var writer = (JsonWriter) outputWriter;
             final var jsonContacts = contacts.stream().map(contactPair -> {
-                final var address = m.resolveSignalServiceAddress(contactPair.first());
+                final var address = contactPair.first();
                 final var contact = contactPair.second();
-                return new JsonContact(address.getNumber().orNull(),
-                        address.getUuid().toString(),
+                return new JsonContact(address.getNumber().orElse(null),
+                        address.getUuid().map(UUID::toString).orElse(null),
                         contact.getName(),
                         contact.isBlocked(),
                         contact.getMessageExpirationTime());
index ad0d3531503c1122abfb1a157b5a06835f58ddca..1de5b84222fa610e730b905f21e5b73da4f2af94 100644 (file)
@@ -46,7 +46,7 @@ public class ListDevicesCommand implements JsonRpcLocalCommand {
         if (outputWriter instanceof PlainTextWriter) {
             final var writer = (PlainTextWriter) outputWriter;
             for (var d : devices) {
-                writer.println("- Device {}{}:", d.getId(), (d.getId() == m.getDeviceId() ? " (this device)" : ""));
+                writer.println("- Device {}{}:", d.getId(), (d.isThisDevice() ? " (this device)" : ""));
                 writer.indent(w -> {
                     w.println("Name: {}", d.getName());
                     w.println("Created: {}", DateUtils.formatTimestamp(d.getCreated()));
index b53577be0a754e2d19676d46bfa98ebe00122a39..1eda53ced47f7f76c6955511143edbc4e4a5c9d7 100644 (file)
@@ -9,13 +9,13 @@ import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.manager.Manager;
-import org.asamk.signal.manager.storage.groups.GroupInfo;
-import org.asamk.signal.manager.storage.recipients.RecipientId;
-import org.asamk.signal.util.Util;
+import org.asamk.signal.manager.api.Group;
+import org.asamk.signal.manager.storage.recipients.RecipientAddress;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.Set;
+import java.util.UUID;
 import java.util.stream.Collectors;
 
 public class ListGroupsCommand implements JsonRpcLocalCommand {
@@ -35,44 +35,41 @@ public class ListGroupsCommand implements JsonRpcLocalCommand {
                 .help("List the members and group invite links of each group. If output=json, then this is always set");
     }
 
-    private static Set<String> resolveMembers(Manager m, Set<RecipientId> addresses) {
-        return addresses.stream()
-                .map(m::resolveSignalServiceAddress)
-                .map(Util::getLegacyIdentifier)
-                .collect(Collectors.toSet());
+    private static Set<String> resolveMembers(Set<RecipientAddress> addresses) {
+        return addresses.stream().map(RecipientAddress::getLegacyIdentifier).collect(Collectors.toSet());
     }
 
-    private static Set<JsonGroupMember> resolveJsonMembers(Manager m, Set<RecipientId> addresses) {
+    private static Set<JsonGroupMember> resolveJsonMembers(Set<RecipientAddress> addresses) {
         return addresses.stream()
-                .map(m::resolveSignalServiceAddress)
-                .map(address -> new JsonGroupMember(address.getNumber().orNull(), address.getUuid().toString()))
+                .map(address -> new JsonGroupMember(address.getNumber().orElse(null),
+                        address.getUuid().map(UUID::toString).orElse(null)))
                 .collect(Collectors.toSet());
     }
 
     private static void printGroupPlainText(
-            PlainTextWriter writer, Manager m, GroupInfo group, boolean detailed
+            PlainTextWriter writer, Group group, boolean detailed
     ) {
         if (detailed) {
-            final var groupInviteLink = group.getGroupInviteLink();
+            final var groupInviteLink = group.getGroupInviteLinkUrl();
 
             writer.println(
                     "Id: {} Name: {} Description: {} Active: {} Blocked: {} Members: {} Pending members: {} Requesting members: {} Admins: {} Message expiration: {} Link: {}",
                     group.getGroupId().toBase64(),
                     group.getTitle(),
                     group.getDescription(),
-                    group.isMember(m.getSelfRecipientId()),
+                    group.isMember(),
                     group.isBlocked(),
-                    resolveMembers(m, group.getMembers()),
-                    resolveMembers(m, group.getPendingMembers()),
-                    resolveMembers(m, group.getRequestingMembers()),
-                    resolveMembers(m, group.getAdminMembers()),
+                    resolveMembers(group.getMembers()),
+                    resolveMembers(group.getPendingMembers()),
+                    resolveMembers(group.getRequestingMembers()),
+                    resolveMembers(group.getAdminMembers()),
                     group.getMessageExpirationTime() == 0 ? "disabled" : group.getMessageExpirationTime() + "s",
                     groupInviteLink == null ? '-' : groupInviteLink.getUrl());
         } else {
             writer.println("Id: {} Name: {}  Active: {} Blocked: {}",
                     group.getGroupId().toBase64(),
                     group.getTitle(),
-                    group.isMember(m.getSelfRecipientId()),
+                    group.isMember(),
                     group.isBlocked());
         }
     }
@@ -87,18 +84,18 @@ public class ListGroupsCommand implements JsonRpcLocalCommand {
             final var jsonWriter = (JsonWriter) outputWriter;
 
             var jsonGroups = groups.stream().map(group -> {
-                final var groupInviteLink = group.getGroupInviteLink();
+                final var groupInviteLink = group.getGroupInviteLinkUrl();
 
                 return new JsonGroup(group.getGroupId().toBase64(),
                         group.getTitle(),
                         group.getDescription(),
-                        group.isMember(m.getSelfRecipientId()),
+                        group.isMember(),
                         group.isBlocked(),
                         group.getMessageExpirationTime(),
-                        resolveJsonMembers(m, group.getMembers()),
-                        resolveJsonMembers(m, group.getPendingMembers()),
-                        resolveJsonMembers(m, group.getRequestingMembers()),
-                        resolveJsonMembers(m, group.getAdminMembers()),
+                        resolveJsonMembers(group.getMembers()),
+                        resolveJsonMembers(group.getPendingMembers()),
+                        resolveJsonMembers(group.getRequestingMembers()),
+                        resolveJsonMembers(group.getAdminMembers()),
                         groupInviteLink == null ? null : groupInviteLink.getUrl());
             }).collect(Collectors.toList());
 
@@ -107,7 +104,7 @@ public class ListGroupsCommand implements JsonRpcLocalCommand {
             final var writer = (PlainTextWriter) outputWriter;
             boolean detailed = ns.getBoolean("detailed");
             for (var group : groups) {
-                printGroupPlainText(writer, m, group, detailed);
+                printGroupPlainText(writer, group, detailed);
             }
         }
     }
index 02cd1d9fe9b9b5f8e415c409c0907ac17ccbbd89..ed2942a5f7d836656db3995e7906631f6dd886a7 100644 (file)
@@ -8,7 +8,7 @@ import org.asamk.signal.OutputWriter;
 import org.asamk.signal.PlainTextWriter;
 import org.asamk.signal.commands.exceptions.CommandException;
 import org.asamk.signal.manager.Manager;
-import org.asamk.signal.manager.storage.identities.IdentityInfo;
+import org.asamk.signal.manager.api.Identity;
 import org.asamk.signal.util.CommandUtil;
 import org.asamk.signal.util.Hex;
 import org.asamk.signal.util.Util;
@@ -29,9 +29,9 @@ public class ListIdentitiesCommand implements JsonRpcLocalCommand {
         return "listIdentities";
     }
 
-    private static void printIdentityFingerprint(PlainTextWriter writer, Manager m, IdentityInfo theirId) {
-        final SignalServiceAddress address = m.resolveSignalServiceAddress(theirId.getRecipientId());
-        var digits = Util.formatSafetyNumber(m.computeSafetyNumber(address, theirId.getIdentityKey()));
+    private static void printIdentityFingerprint(PlainTextWriter writer, Manager m, Identity theirId) {
+        final SignalServiceAddress address = theirId.getRecipient().toSignalServiceAddress();
+        var digits = Util.formatSafetyNumber(theirId.getSafetyNumber());
         writer.println("{}: {} Added: {} Fingerprint: {} Safety Number: {}",
                 address.getNumber().orNull(),
                 theirId.getTrustLevel(),
@@ -52,11 +52,11 @@ public class ListIdentitiesCommand implements JsonRpcLocalCommand {
     ) throws CommandException {
         var number = ns.getString("number");
 
-        List<IdentityInfo> identities;
+        List<Identity> identities;
         if (number == null) {
             identities = m.getIdentities();
         } else {
-            identities = m.getIdentities(CommandUtil.getSingleRecipientIdentifier(number, m.getUsername()));
+            identities = m.getIdentities(CommandUtil.getSingleRecipientIdentifier(number, m.getSelfNumber()));
         }
 
         if (outputWriter instanceof PlainTextWriter) {
@@ -67,9 +67,9 @@ public class ListIdentitiesCommand implements JsonRpcLocalCommand {
         } else {
             final var writer = (JsonWriter) outputWriter;
             final var jsonIdentities = identities.stream().map(id -> {
-                final var address = m.resolveSignalServiceAddress(id.getRecipientId());
-                var safetyNumber = Util.formatSafetyNumber(m.computeSafetyNumber(address, id.getIdentityKey()));
-                var scannableSafetyNumber = m.computeSafetyNumberForScanning(address, id.getIdentityKey());
+                final var address = id.getRecipient().toSignalServiceAddress();
+                var safetyNumber = Util.formatSafetyNumber(id.getSafetyNumber());
+                var scannableSafetyNumber = id.getScannableSafetyNumber();
                 return new JsonIdentity(address.getNumber().orNull(),
                         address.getUuid().toString(),
                         Hex.toString(id.getFingerprint()),
index 67a6596b4a13e9b31b3092ecf02beb6ee870398d..7635f8ae44dc516618ea0073a1224c8af2f5aa4f 100644 (file)
@@ -50,7 +50,7 @@ public class QuitGroupCommand implements JsonRpcLocalCommand {
     ) throws CommandException {
         final var groupId = CommandUtil.getGroupId(ns.getString("group-id"));
 
-        var groupAdmins = CommandUtil.getSingleRecipientIdentifiers(ns.getList("admin"), m.getUsername());
+        var groupAdmins = CommandUtil.getSingleRecipientIdentifiers(ns.getList("admin"), m.getSelfNumber());
 
         try {
             try {
index 338e70ac8500f0d17461a7dc9a079a3256ceb5d1..f8c3c358183f819a124cb56d78ced8ce82aca18e 100644 (file)
@@ -72,7 +72,7 @@ public class SendReactionCommand implements DbusCommand, JsonRpcLocalCommand {
         try {
             final var results = m.sendMessageReaction(emoji,
                     isRemove,
-                    CommandUtil.getSingleRecipientIdentifier(targetAuthor, m.getUsername()),
+                    CommandUtil.getSingleRecipientIdentifier(targetAuthor, m.getSelfNumber()),
                     targetTimestamp,
                     recipientIdentifiers);
             outputResult(outputWriter, results.getTimestamp());
index 0d5772ecc81723c747cbfd0ec37132a00c5cbc11..5dd296827972f8ea9d694a04c342b45401670191 100644 (file)
@@ -37,7 +37,7 @@ public class SendReceiptCommand implements JsonRpcLocalCommand {
             final Namespace ns, final Manager m, final OutputWriter outputWriter
     ) throws CommandException {
         final var recipientString = ns.getString("recipient");
-        final var recipient = CommandUtil.getSingleRecipientIdentifier(recipientString, m.getUsername());
+        final var recipient = CommandUtil.getSingleRecipientIdentifier(recipientString, m.getSelfNumber());
 
         final var targetTimestamps = ns.<Long>getList("target-timestamp");
         final var type = ns.getString("type");
index 3a965e4751caf1b1f59315b02ed393c27158b829..cfe66770877aaca367b1c3a3d9b899e842ca688f 100644 (file)
@@ -45,7 +45,7 @@ public class SendTypingCommand implements JsonRpcLocalCommand {
 
         final var recipientIdentifiers = new HashSet<RecipientIdentifier>();
         if (recipientStrings != null) {
-            final var localNumber = m.getUsername();
+            final var localNumber = m.getSelfNumber();
             recipientIdentifiers.addAll(CommandUtil.getSingleRecipientIdentifiers(recipientStrings, localNumber));
         }
         if (groupIdStrings != null) {
index aedc2c3e6e48643e14180bc91660d584101ac0cb..9e59ad86ce34734cd4ef74ca13d47b5969713817 100644 (file)
@@ -38,7 +38,7 @@ public class TrustCommand implements JsonRpcLocalCommand {
             final Namespace ns, final Manager m, final OutputWriter outputWriter
     ) throws CommandException {
         var recipentString = ns.getString("recipient");
-        var recipient = CommandUtil.getSingleRecipientIdentifier(recipentString, m.getUsername());
+        var recipient = CommandUtil.getSingleRecipientIdentifier(recipentString, m.getSelfNumber());
         if (ns.getBoolean("trust-all-known-keys")) {
             boolean res = m.trustIdentityAllKeys(recipient);
             if (!res) {
index 812065bc558fb05da9c3103eb8de318bd1c8ae5c..7cf209fa05fe39adf9d6c0824560c732b409f286 100644 (file)
@@ -36,7 +36,8 @@ public class UnblockCommand implements JsonRpcLocalCommand {
     public void handleCommand(
             final Namespace ns, final Manager m, final OutputWriter outputWriter
     ) throws CommandException {
-        for (var contactNumber : CommandUtil.getSingleRecipientIdentifiers(ns.getList("recipient"), m.getUsername())) {
+        for (var contactNumber : CommandUtil.getSingleRecipientIdentifiers(ns.getList("recipient"),
+                m.getSelfNumber())) {
             try {
                 m.setContactBlocked(contactNumber, false);
             } catch (NotMasterDeviceException e) {
index 6c2916ebfdbafe378f464828c5429eaa3bbbd4c7..46641668f32a5de77d6b9c383bf26471089c073f 100644 (file)
@@ -33,7 +33,7 @@ public class UpdateContactCommand implements JsonRpcLocalCommand {
             final Namespace ns, final Manager m, final OutputWriter outputWriter
     ) throws CommandException {
         var recipientString = ns.getString("recipient");
-        var recipient = CommandUtil.getSingleRecipientIdentifier(recipientString, m.getUsername());
+        var recipient = CommandUtil.getSingleRecipientIdentifier(recipientString, m.getSelfNumber());
 
         try {
             var expiration = ns.getInt("expiration");
index b0269894ebdf7ae4d91ef85607971b6050c9d417..49cd4719be596856735b6c6ebef98854d01e95e2 100644 (file)
@@ -116,7 +116,7 @@ public class UpdateGroupCommand implements DbusCommand, JsonRpcLocalCommand {
         final var groupIdString = ns.getString("group-id");
         var groupId = CommandUtil.getGroupId(groupIdString);
 
-        final var localNumber = m.getUsername();
+        final var localNumber = m.getSelfNumber();
 
         var groupName = ns.getString("name");
         var groupDescription = ns.getString("description");
index 6ec8d964a4d999d7df4ab99568bec93c1df3253b..be628bde7ee00033cd274aebb8963ce9909e3dc3 100644 (file)
@@ -160,7 +160,7 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl {
         synchronized (receiveThreads) {
             return receiveThreads.stream()
                     .map(Pair::first)
-                    .map(Manager::getUsername)
+                    .map(Manager::getSelfNumber)
                     .map(u -> new DBusPath(DbusConfig.getObjectPath(u)))
                     .collect(Collectors.toList());
         }
index e975a67153a09b049e937d12dc686c84f95f90bc..c8208774c70d1d5193b4bf319a0658e091576325 100644 (file)
@@ -8,6 +8,7 @@ import org.asamk.signal.manager.NotMasterDeviceException;
 import org.asamk.signal.manager.StickerPackInvalidException;
 import org.asamk.signal.manager.UntrustedIdentityException;
 import org.asamk.signal.manager.api.Device;
+import org.asamk.signal.manager.api.Identity;
 import org.asamk.signal.manager.api.Message;
 import org.asamk.signal.manager.api.RecipientIdentifier;
 import org.asamk.signal.manager.api.TypingAction;
@@ -17,9 +18,9 @@ import org.asamk.signal.manager.groups.GroupNotFoundException;
 import org.asamk.signal.manager.groups.GroupSendingNotAllowedException;
 import org.asamk.signal.manager.groups.LastGroupAdminException;
 import org.asamk.signal.manager.groups.NotAGroupMemberException;
-import org.asamk.signal.manager.storage.identities.IdentityInfo;
+import org.asamk.signal.manager.storage.recipients.Profile;
+import org.asamk.signal.manager.storage.recipients.RecipientAddress;
 import org.asamk.signal.util.ErrorUtils;
-import org.asamk.signal.util.Util;
 import org.freedesktop.dbus.exceptions.DBusExecutionException;
 import org.whispersystems.libsignal.InvalidKeyException;
 import org.whispersystems.libsignal.util.Pair;
@@ -45,8 +46,6 @@ import java.util.UUID;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-import static org.asamk.signal.util.Util.getLegacyIdentifier;
-
 public class DbusSignalImpl implements Signal {
 
     private final Manager m;
@@ -67,6 +66,11 @@ public class DbusSignalImpl implements Signal {
         return objectPath;
     }
 
+    @Override
+    public String getNumber() {
+        return m.getSelfNumber();
+    }
+
     @Override
     public void addDevice(String uri) {
         try {
@@ -123,7 +127,7 @@ public class DbusSignalImpl implements Signal {
     public long sendMessage(final String message, final List<String> attachments, final List<String> recipients) {
         try {
             final var results = m.sendMessage(new Message(message, attachments),
-                    getSingleRecipientIdentifiers(recipients, m.getUsername()).stream()
+                    getSingleRecipientIdentifiers(recipients, m.getSelfNumber()).stream()
                             .map(RecipientIdentifier.class::cast)
                             .collect(Collectors.toSet()));
 
@@ -153,7 +157,7 @@ public class DbusSignalImpl implements Signal {
     ) {
         try {
             final var results = m.sendRemoteDeleteMessage(targetSentTimestamp,
-                    getSingleRecipientIdentifiers(recipients, m.getUsername()).stream()
+                    getSingleRecipientIdentifiers(recipients, m.getSelfNumber()).stream()
                             .map(RecipientIdentifier.class::cast)
                             .collect(Collectors.toSet()));
             checkSendMessageResults(results.getTimestamp(), results.getResults());
@@ -205,9 +209,9 @@ public class DbusSignalImpl implements Signal {
         try {
             final var results = m.sendMessageReaction(emoji,
                     remove,
-                    getSingleRecipientIdentifier(targetAuthor, m.getUsername()),
+                    getSingleRecipientIdentifier(targetAuthor, m.getSelfNumber()),
                     targetSentTimestamp,
-                    getSingleRecipientIdentifiers(recipients, m.getUsername()).stream()
+                    getSingleRecipientIdentifiers(recipients, m.getSelfNumber()).stream()
                             .map(RecipientIdentifier.class::cast)
                             .collect(Collectors.toSet()));
             checkSendMessageResults(results.getTimestamp(), results.getResults());
@@ -227,7 +231,7 @@ public class DbusSignalImpl implements Signal {
             var recipients = new ArrayList<String>(1);
             recipients.add(recipient);
             m.sendTypingMessage(stop ? TypingAction.STOP : TypingAction.START,
-                    getSingleRecipientIdentifiers(recipients, m.getUsername()).stream()
+                    getSingleRecipientIdentifiers(recipients, m.getSelfNumber()).stream()
                             .map(RecipientIdentifier.class::cast)
                             .collect(Collectors.toSet()));
         } catch (IOException e) {
@@ -241,10 +245,10 @@ public class DbusSignalImpl implements Signal {
 
     @Override
     public void sendReadReceipt(
-            final String recipient, final List<Long> timestamps
+            final String recipient, final List<Long> messageIds
     ) throws Error.Failure, Error.UntrustedIdentity {
         try {
-            m.sendReadReceipt(getSingleRecipientIdentifier(recipient, m.getUsername()), timestamps);
+            m.sendReadReceipt(getSingleRecipientIdentifier(recipient, m.getSelfNumber()), messageIds);
         } catch (IOException e) {
             throw new Error.Failure(e.getMessage());
         } catch (UntrustedIdentityException e) {
@@ -291,7 +295,7 @@ public class DbusSignalImpl implements Signal {
     @Override
     public void sendEndSessionMessage(final List<String> recipients) {
         try {
-            final var results = m.sendEndSessionMessage(getSingleRecipientIdentifiers(recipients, m.getUsername()));
+            final var results = m.sendEndSessionMessage(getSingleRecipientIdentifiers(recipients, m.getSelfNumber()));
             checkSendMessageResults(results.getTimestamp(), results.getResults());
         } catch (IOException e) {
             throw new Error.Failure(e.getMessage());
@@ -325,7 +329,7 @@ public class DbusSignalImpl implements Signal {
         try {
             final var results = m.sendMessageReaction(emoji,
                     remove,
-                    getSingleRecipientIdentifier(targetAuthor, m.getUsername()),
+                    getSingleRecipientIdentifier(targetAuthor, m.getSelfNumber()),
                     targetSentTimestamp,
                     Set.of(new RecipientIdentifier.Group(getGroupId(groupId))));
             checkSendMessageResults(results.getTimestamp(), results.getResults());
@@ -341,13 +345,13 @@ public class DbusSignalImpl implements Signal {
     // the profile name
     @Override
     public String getContactName(final String number) {
-        return m.getContactOrProfileName(getSingleRecipientIdentifier(number, m.getUsername()));
+        return m.getContactOrProfileName(getSingleRecipientIdentifier(number, m.getSelfNumber()));
     }
 
     @Override
     public void setContactName(final String number, final String name) {
         try {
-            m.setContactName(getSingleRecipientIdentifier(number, m.getUsername()), name);
+            m.setContactName(getSingleRecipientIdentifier(number, m.getSelfNumber()), name);
         } catch (NotMasterDeviceException e) {
             throw new Error.Failure("This command doesn't work on linked devices.");
         } catch (UnregisteredUserException e) {
@@ -358,7 +362,7 @@ public class DbusSignalImpl implements Signal {
     @Override
     public void setExpirationTimer(final String number, final int expiration) {
         try {
-            m.setExpirationTimer(getSingleRecipientIdentifier(number, m.getUsername()), expiration);
+            m.setExpirationTimer(getSingleRecipientIdentifier(number, m.getSelfNumber()), expiration);
         } catch (IOException e) {
             throw new Error.Failure(e.getMessage());
         }
@@ -367,7 +371,7 @@ public class DbusSignalImpl implements Signal {
     @Override
     public void setContactBlocked(final String number, final boolean blocked) {
         try {
-            m.setContactBlocked(getSingleRecipientIdentifier(number, m.getUsername()), blocked);
+            m.setContactBlocked(getSingleRecipientIdentifier(number, m.getSelfNumber()), blocked);
         } catch (NotMasterDeviceException e) {
             throw new Error.Failure("This command doesn't work on linked devices.");
         } catch (IOException e) {
@@ -412,11 +416,7 @@ public class DbusSignalImpl implements Signal {
         if (group == null) {
             return List.of();
         } else {
-            return group.getMembers()
-                    .stream()
-                    .map(m::resolveSignalServiceAddress)
-                    .map(Util::getLegacyIdentifier)
-                    .collect(Collectors.toList());
+            return group.getMembers().stream().map(RecipientAddress::getLegacyIdentifier).collect(Collectors.toList());
         }
     }
 
@@ -432,7 +432,7 @@ public class DbusSignalImpl implements Signal {
             if (avatar.isEmpty()) {
                 avatar = null;
             }
-            final var memberIdentifiers = getSingleRecipientIdentifiers(members, m.getUsername());
+            final var memberIdentifiers = getSingleRecipientIdentifiers(members, m.getSelfNumber());
             if (groupId == null) {
                 final var results = m.createGroup(name, memberIdentifiers, avatar == null ? null : new File(avatar));
                 checkSendMessageResults(results.second().getTimestamp(), results.second().getResults());
@@ -573,10 +573,9 @@ public class DbusSignalImpl implements Signal {
     // all numbers the system knows
     @Override
     public List<String> listNumbers() {
-        return Stream.concat(m.getIdentities().stream().map(IdentityInfo::getRecipientId),
+        return Stream.concat(m.getIdentities().stream().map(Identity::getRecipient),
                 m.getContacts().stream().map(Pair::first))
-                .map(m::resolveSignalServiceAddress)
-                .map(a -> a.getNumber().orNull())
+                .map(a -> a.getNumber().orElse(null))
                 .filter(Objects::nonNull)
                 .distinct()
                 .collect(Collectors.toList());
@@ -589,16 +588,19 @@ public class DbusSignalImpl implements Signal {
         var contacts = m.getContacts();
         for (var c : contacts) {
             if (name.equals(c.second().getName())) {
-                numbers.add(getLegacyIdentifier(m.resolveSignalServiceAddress(c.first())));
+                numbers.add(c.first().getLegacyIdentifier());
             }
         }
         // Try profiles if no contact name was found
         for (var identity : m.getIdentities()) {
-            final var recipientId = identity.getRecipientId();
-            final var address = m.resolveSignalServiceAddress(recipientId);
-            var number = address.getNumber().orNull();
+            final var address = identity.getRecipient();
+            var number = address.getNumber().orElse(null);
             if (number != null) {
-                var profile = m.getRecipientProfile(recipientId);
+                Profile profile = null;
+                try {
+                    profile = m.getRecipientProfile(RecipientIdentifier.Single.fromAddress(address));
+                } catch (UnregisteredUserException ignored) {
+                }
                 if (profile != null && profile.getDisplayName().equals(name)) {
                     numbers.add(number);
                 }
@@ -639,7 +641,7 @@ public class DbusSignalImpl implements Signal {
 
     @Override
     public boolean isContactBlocked(final String number) {
-        return m.isContactBlocked(getSingleRecipientIdentifier(number, m.getUsername()));
+        return m.isContactBlocked(getSingleRecipientIdentifier(number, m.getSelfNumber()));
     }
 
     @Override
@@ -658,7 +660,7 @@ public class DbusSignalImpl implements Signal {
         if (group == null) {
             return false;
         } else {
-            return group.isMember(m.getSelfRecipientId());
+            return group.isMember();
         }
     }
 
index b24768b7c38bb1a74dcfc53e6b7d525ffd4124a5..3c6f2eec091333721bd85ee12dd08dcafc547d35 100644 (file)
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 
 import org.asamk.signal.manager.Manager;
 import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
+import org.whispersystems.signalservice.api.push.SignalServiceAddress;
 
 import static org.asamk.signal.util.Util.getLegacyIdentifier;
 
@@ -26,7 +27,7 @@ public class JsonMention {
     final int length;
 
     JsonMention(SignalServiceDataMessage.Mention mention, Manager m) {
-        final var address = m.resolveSignalServiceAddress(mention.getUuid());
+        final var address = m.resolveSignalServiceAddress(new SignalServiceAddress(mention.getUuid()));
         this.name = getLegacyIdentifier(address);
         this.number = address.getNumber().orNull();
         this.uuid = address.getUuid().toString();
index 7b884b0e3887588013854933ab7013c0356b35d8..e49e6125b77dee0c4a58ab4e88b8e9be328d34f7 100644 (file)
@@ -86,7 +86,7 @@ public class JsonMessageEnvelope {
         }
         String name;
         try {
-            name = m.getContactOrProfileName(RecipientIdentifier.Single.fromString(this.source, m.getUsername()));
+            name = m.getContactOrProfileName(RecipientIdentifier.Single.fromString(this.source, m.getSelfNumber()));
         } catch (InvalidNumberException | NullPointerException e) {
             name = null;
         }
index 18b38a2a7c4d51b0db7997dfddeaa13d1f934978..0a624e6b214ac7596b8552fa34749528a5079f6f 100644 (file)
@@ -28,7 +28,7 @@ public class CommandUtil {
             recipientIdentifiers.add(RecipientIdentifier.NoteToSelf.INSTANCE);
         }
         if (recipientStrings != null) {
-            final var localNumber = m.getUsername();
+            final var localNumber = m.getSelfNumber();
             recipientIdentifiers.addAll(CommandUtil.getSingleRecipientIdentifiers(recipientStrings, localNumber));
         }
         if (groupIdStrings != null) {