From: Adimarantis <74186638+bublath@users.noreply.github.com> Date: Mon, 1 Mar 2021 19:31:17 +0000 (+0100) Subject: Dbus enhancements (#543) X-Git-Tag: v0.8.1~3 X-Git-Url: https://git.nmode.ca/signal-cli/commitdiff_plain/1d2c7a479d791dedde6c2022ac65e9c82400af79 Dbus enhancements (#543) * Dbus enhancements * reverted sendMessage, completed isContactBlocked, fixed formatting * Updates based on feedback and fixes * Added trim * fixed getContactName Exception handling --- diff --git a/lib/src/main/java/org/asamk/signal/manager/Manager.java b/lib/src/main/java/org/asamk/signal/manager/Manager.java index d34f4e08..d8a1f563 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -529,7 +529,7 @@ public class Manager implements Closeable { ServiceConfig.AUTOMATIC_NETWORK_RETRY); } - private SignalProfile getRecipientProfile( + public SignalProfile getRecipientProfile( SignalServiceAddress address ) { return getRecipientProfile(address, false); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/profiles/SignalProfile.java b/lib/src/main/java/org/asamk/signal/manager/storage/profiles/SignalProfile.java index 9e5add98..d55e7e6c 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/profiles/SignalProfile.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/profiles/SignalProfile.java @@ -76,8 +76,8 @@ public class SignalProfile { } public String getDisplayName() { - // First name and last name (if set) are separated by a NULL char - return name == null ? null : name.replace("\0", " "); + // First name and last name (if set) are separated by a NULL char + trim space in case only one is filled + return name == null ? null : name.replace("\0", " ").trim(); } public String getAbout() { diff --git a/src/main/java/org/asamk/Signal.java b/src/main/java/org/asamk/Signal.java index 3bd1c0d7..9e81c788 100644 --- a/src/main/java/org/asamk/Signal.java +++ b/src/main/java/org/asamk/Signal.java @@ -54,6 +54,22 @@ public interface Signal extends DBusInterface { void updateProfile( String name, String about, String aboutEmoji, String avatarPath, boolean removeAvatar ) throws Error.Failure; + + public String version(); + + public List listNumbers(); + + public List getContactNumber(final String name) throws Error.Failure; + + public void quitGroup(final byte[] groupId) throws Error.GroupNotFound,Error.Failure; + + public boolean isContactBlocked(final String number); + + public boolean isGroupBlocked(final byte[] groupId); + + public boolean isMember(final byte[] groupId); + + public void joinGroup(final String groupLink) throws Error.Failure; class MessageReceived extends DBusSignal { diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java index 8cbbbc03..53ba5300 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java @@ -6,17 +6,24 @@ import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.groups.GroupId; import org.asamk.signal.manager.groups.GroupNotFoundException; import org.asamk.signal.manager.groups.NotAGroupMemberException; +import org.asamk.signal.manager.groups.GroupInviteLinkUrl; +import org.asamk.signal.manager.storage.protocol.IdentityInfo; import org.asamk.signal.util.ErrorUtils; +import org.asamk.signal.manager.util.Utils; +import org.asamk.signal.BaseConfig; import org.freedesktop.dbus.exceptions.DBusExecutionException; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.util.InvalidNumberException; +import org.whispersystems.signalservice.api.groupsv2.GroupLinkNotActiveException; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; import java.util.stream.Collectors; public class DbusSignalImpl implements Signal { @@ -60,9 +67,8 @@ public class DbusSignalImpl implements Signal { } } - private static void checkSendMessageResults( - long timestamp, List results - ) throws DBusExecutionException { + private static void checkSendMessageResults(long timestamp, List results) + throws DBusExecutionException { if (results.size() == 1) { checkSendMessageResult(timestamp, results.get(0)); return; @@ -99,9 +105,8 @@ public class DbusSignalImpl implements Signal { } @Override - public long sendNoteToSelfMessage( - final String message, final List attachments - ) throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity { + public long sendNoteToSelfMessage(final String message, final List attachments) + throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity { try { final var results = m.sendSelfMessage(message, attachments); checkSendMessageResult(results.first(), results.second()); @@ -140,13 +145,17 @@ public class DbusSignalImpl implements Signal { } } + // Since contact names might be empty if not defined, also potentially return + // the profile name @Override public String getContactName(final String number) { + String name=""; try { - return m.getContactName(number); - } catch (InvalidNumberException e) { + name = m.getContactOrProfileName(number); + } catch (Exception e) { throw new Error.InvalidNumber(e.getMessage()); } + return name; } @Override @@ -202,11 +211,8 @@ public class DbusSignalImpl implements Signal { if (group == null) { return List.of(); } else { - return group.getMembers() - .stream() - .map(m::resolveSignalServiceAddress) - .map(SignalServiceAddress::getLegacyIdentifier) - .collect(Collectors.toList()); + return group.getMembers().stream().map(m::resolveSignalServiceAddress) + .map(SignalServiceAddress::getLegacyIdentifier).collect(Collectors.toList()); } } @@ -225,9 +231,7 @@ public class DbusSignalImpl implements Signal { if (avatar.isEmpty()) { avatar = null; } - final var results = m.updateGroup(groupId == null ? null : GroupId.unknownVersion(groupId), - name, - members, + final var results = m.updateGroup(groupId == null ? null : GroupId.unknownVersion(groupId), name, members, avatar == null ? null : new File(avatar)); checkSendMessageResults(0, results.second()); return results.first().serialize(); @@ -248,19 +252,13 @@ public class DbusSignalImpl implements Signal { } @Override - public void updateProfile( - final String name, - final String about, - final String aboutEmoji, - String avatarPath, - final boolean removeAvatar - ) { + public void updateProfile(final String name, final String about, final String aboutEmoji, String avatarPath, + final boolean removeAvatar) { try { if (avatarPath.isEmpty()) { avatarPath = null; } - Optional avatarFile = removeAvatar - ? Optional.absent() + Optional avatarFile = removeAvatar ? Optional.absent() : avatarPath == null ? null : Optional.of(new File(avatarPath)); m.setProfile(name, about, aboutEmoji, avatarFile); } catch (IOException e) { @@ -268,4 +266,108 @@ public class DbusSignalImpl implements Signal { } } + // Provide option to query a version string in order to react on potential + // future interface changes + @Override + public String version() { + return BaseConfig.PROJECT_VERSION; + } + + // Create a unique list of Numbers from Identities and Contacts to really get + // all numbers the system knows + @Override + public List listNumbers() { + return Stream.concat(m.getIdentities().stream().map(i -> i.getAddress().getNumber().orNull()), + m.getContacts().stream().map(c -> c.number)) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + } + + @Override + public List getContactNumber(final String name) { + // Contact names have precendence. + List numbers=new ArrayList<>(); + var contacts = m.getContacts(); + for (var c : contacts) { + if (c.name!=null && c.name.equals(name)) { + numbers.add(c.number); + } + } + // Try profiles if no contact name was found + for (IdentityInfo identity : m.getIdentities()) { + String number = identity.getAddress().getNumber().orNull(); + if (number != null) { + var address = Utils.getSignalServiceAddressFromIdentifier(number); + var profile = m.getRecipientProfile(address); + String profileName = profile.getDisplayName(); + if (profileName.equals(name)) { + numbers.add(number); + } + } + } + if (numbers.size()==0) { + throw new Error.Failure("Contact name not found"); + } + return numbers; + } + + @Override + public void quitGroup(final byte[] groupId) { + var group = GroupId.unknownVersion(groupId); + try { + m.sendQuitGroupMessage(group); + } catch (GroupNotFoundException | NotAGroupMemberException e) { + throw new Error.GroupNotFound(e.getMessage()); + } catch (IOException e) { + throw new Error.Failure(e.getMessage()); + } + } + + @Override + public void joinGroup(final String groupLink) { + final GroupInviteLinkUrl linkUrl; + try { + linkUrl = GroupInviteLinkUrl.fromUri(groupLink); + m.joinGroup(linkUrl); + } catch (GroupInviteLinkUrl.InvalidGroupLinkException | GroupLinkNotActiveException e) { + throw new Error.Failure("Group link is invalid: " + e.getMessage()); + } catch (GroupInviteLinkUrl.UnknownGroupLinkVersionException e) { + throw new Error.Failure("Group link was created with an incompatible version: " + e.getMessage()); + } catch (IOException e) { + throw new Error.Failure(e.getMessage()); + } + } + + @Override + public boolean isContactBlocked(final String number) { + var contacts = m.getContacts(); + for (var c : contacts) { + if (c.number.equals(number)) { + return c.blocked; + } + } + return false; + } + + @Override + public boolean isGroupBlocked(final byte[] groupId) { + var group = m.getGroup(GroupId.unknownVersion(groupId)); + if (group == null) { + return false; + } else { + return group.isBlocked(); + } + } + + @Override + public boolean isMember(final byte[] groupId) { + var group = m.getGroup(GroupId.unknownVersion(groupId)); + if (group == null) { + return false; + } else { + return group.isMember(m.getSelfAddress()); + } + } + }