From: AsamK Date: Fri, 14 May 2021 20:23:13 +0000 (+0200) Subject: Implement remove group members X-Git-Tag: v0.8.4~39 X-Git-Url: https://git.nmode.ca/signal-cli/commitdiff_plain/a91e3f762e0e5d6a9cf9e208fe85207d7829e22d?ds=inline Implement remove group members --- 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 45404154..9d73ac81 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -826,22 +826,33 @@ public class Manager implements Closeable { } public Pair> updateGroup( - GroupId groupId, String name, String description, List members, File avatarFile + GroupId groupId, + String name, + String description, + List members, + List removeMembers, + File avatarFile ) throws IOException, GroupNotFoundException, AttachmentInvalidException, InvalidNumberException, NotAGroupMemberException { return updateGroup(groupId, name, description, members == null ? null : getSignalServiceAddresses(members), + removeMembers == null ? null : getSignalServiceAddresses(removeMembers), avatarFile); } private Pair> updateGroup( - GroupId groupId, String name, String description, Set members, File avatarFile + GroupId groupId, + String name, + String description, + Set members, + final Set removeMembers, + File avatarFile ) throws IOException, GroupNotFoundException, AttachmentInvalidException, NotAGroupMemberException { var group = getGroupForUpdating(groupId); if (group instanceof GroupInfoV2) { - return updateGroupV2((GroupInfoV2) group, name, description, members, avatarFile); + return updateGroupV2((GroupInfoV2) group, name, description, members, removeMembers, avatarFile); } return updateGroupV1((GroupInfoV1) group, name, members, avatarFile); @@ -901,6 +912,7 @@ public class Manager implements Closeable { final String name, final String description, final Set members, + final Set removeMembers, final File avatarFile ) throws IOException { Pair> result = null; @@ -917,6 +929,24 @@ public class Manager implements Closeable { result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second()); } } + + if (removeMembers != null) { + var existingRemoveMembers = new HashSet<>(removeMembers); + existingRemoveMembers.retainAll(group.getMembers()); + existingRemoveMembers.remove(getSelfRecipientId());// self can be removed with sendQuitGroupMessage + if (existingRemoveMembers.size() > 0) { + var groupGroupChangePair = groupHelper.removeMembers(group, existingRemoveMembers); + result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second()); + } + + var pendingRemoveMembers = new HashSet<>(removeMembers); + pendingRemoveMembers.retainAll(group.getPendingMembers()); + if (pendingRemoveMembers.size() > 0) { + var groupGroupChangePair = groupHelper.revokeInvitedMembers(group, pendingRemoveMembers); + result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second()); + } + } + if (result == null || name != null || description != null || avatarFile != null) { var groupGroupChangePair = groupHelper.updateGroupV2(group, name, description, avatarFile); if (avatarFile != null) { @@ -954,10 +984,14 @@ public class Manager implements Closeable { private Pair> sendUpdateGroupV2Message( GroupInfoV2 group, DecryptedGroup newDecryptedGroup, GroupChange groupChange ) throws IOException { + final var selfRecipientId = account.getSelfRecipientId(); + final var members = group.getMembersIncludingPendingWithout(selfRecipientId); group.setGroup(newDecryptedGroup, this::resolveRecipient); + members.addAll(group.getMembersIncludingPendingWithout(selfRecipientId)); + final var messageBuilder = getGroupUpdateMessageBuilder(group, groupChange.toByteArray()); account.getGroupStore().updateGroup(group); - return sendMessage(messageBuilder, group.getMembersIncludingPendingWithout(account.getSelfRecipientId())); + return sendMessage(messageBuilder, members); } private static int currentTimeDays() { diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java index 0bf4069e..527fa7ab 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java @@ -263,6 +263,34 @@ public class GroupHelper { } } + public Pair removeMembers( + GroupInfoV2 groupInfoV2, Set members + ) throws IOException { + final var memberUuids = members.stream() + .map(addressResolver::resolveSignalServiceAddress) + .map(SignalServiceAddress::getUuid) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toSet()); + return ejectMembers(groupInfoV2, memberUuids); + } + + public Pair revokeInvitedMembers( + GroupInfoV2 groupInfoV2, Set members + ) throws IOException { + var pendingMembersList = groupInfoV2.getGroup().getPendingMembersList(); + final var memberUuids = members.stream() + .map(addressResolver::resolveSignalServiceAddress) + .map(SignalServiceAddress::getUuid) + .filter(Optional::isPresent) + .map(Optional::get) + .map(uuid -> DecryptedGroupUtil.findPendingByUuid(pendingMembersList, uuid)) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toSet()); + return revokeInvites(groupInfoV2, memberUuids); + } + public GroupChange joinGroup( GroupMasterKey groupMasterKey, GroupLinkPassword groupLinkPassword, @@ -309,7 +337,7 @@ public class GroupHelper { return commitChange(groupInfoV2, change); } - public Pair revokeInvites( + private Pair revokeInvites( GroupInfoV2 groupInfoV2, Set pendingMembers ) throws IOException { final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); @@ -324,7 +352,9 @@ public class GroupHelper { return commitChange(groupInfoV2, groupOperations.createRemoveInvitationChange(uuidCipherTexts)); } - public Pair ejectMembers(GroupInfoV2 groupInfoV2, Set uuids) throws IOException { + private Pair ejectMembers( + GroupInfoV2 groupInfoV2, Set uuids + ) throws IOException { final var groupSecretParams = GroupSecretParams.deriveFromMasterKey(groupInfoV2.getMasterKey()); final var groupOperations = groupsV2Operations.forGroup(groupSecretParams); return commitChange(groupInfoV2, groupOperations.createRemoveMembersChange(uuids)); diff --git a/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java b/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java index 00dd10d9..513ec2e4 100644 --- a/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java +++ b/src/main/java/org/asamk/signal/commands/UpdateGroupCommand.java @@ -38,6 +38,9 @@ public class UpdateGroupCommand implements DbusCommand, LocalCommand { subparser.addArgument("-d", "--description").help("Specify the new group description."); subparser.addArgument("-a", "--avatar").help("Specify a new group avatar image file"); subparser.addArgument("-m", "--member").nargs("*").help("Specify one or more members to add to the group"); + subparser.addArgument("-r", "--remove-member") + .nargs("*") + .help("Specify one or more members to remove from the group"); } @Override @@ -59,6 +62,8 @@ public class UpdateGroupCommand implements DbusCommand, LocalCommand { List groupMembers = ns.getList("member"); + List groupRemoveMembers = ns.getList("remove-member"); + var groupAvatar = ns.getString("avatar"); try { @@ -74,6 +79,7 @@ public class UpdateGroupCommand implements DbusCommand, LocalCommand { groupName, groupDescription, groupMembers, + groupRemoveMembers, groupAvatar == null ? null : new File(groupAvatar)); ErrorUtils.handleTimestampAndSendMessageResults(writer, results.first(), results.second()); } diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java index cdc9e8d5..6606e966 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java @@ -344,6 +344,7 @@ public class DbusSignalImpl implements Signal { name, null, members, + null, avatar == null ? null : new File(avatar)); checkSendMessageResults(results.first(), results.second()); return groupId;