X-Git-Url: https://git.nmode.ca/signal-cli/blobdiff_plain/03589f858ba2cf52df4d85a9d68df3f3cda5cb74..81ee2c2d2bb80660d85cf9d1b7ecdf001983b3d6:/lib/src/main/java/org/asamk/signal/manager/Manager.java 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 03f4e8e9..f285e2ef 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -25,7 +25,9 @@ import org.asamk.signal.manager.groups.GroupIdV1; import org.asamk.signal.manager.groups.GroupInviteLinkUrl; import org.asamk.signal.manager.groups.GroupLinkState; import org.asamk.signal.manager.groups.GroupNotFoundException; +import org.asamk.signal.manager.groups.GroupPermission; import org.asamk.signal.manager.groups.GroupUtils; +import org.asamk.signal.manager.groups.LastGroupAdminException; import org.asamk.signal.manager.groups.NotAGroupMemberException; import org.asamk.signal.manager.helper.GroupV2Helper; import org.asamk.signal.manager.helper.PinHelper; @@ -762,7 +764,9 @@ public class Manager implements Closeable { return sendMessage(messageBuilder, g.getMembersWithout(account.getSelfRecipientId())); } - public Pair> sendQuitGroupMessage(GroupId groupId) throws GroupNotFoundException, IOException, NotAGroupMemberException { + public Pair> sendQuitGroupMessage( + GroupId groupId, Set groupAdmins + ) throws GroupNotFoundException, IOException, NotAGroupMemberException, InvalidNumberException, LastGroupAdminException { SignalServiceDataMessage.Builder messageBuilder; final var g = getGroupForUpdating(groupId); @@ -774,7 +778,18 @@ public class Manager implements Closeable { account.getGroupStore().updateGroup(groupInfoV1); } else { final var groupInfoV2 = (GroupInfoV2) g; - final var groupGroupChangePair = groupV2Helper.leaveGroup(groupInfoV2); + final var currentAdmins = g.getAdminMembers(); + final var newAdmins = getSignalServiceAddresses(groupAdmins); + newAdmins.removeAll(currentAdmins); + newAdmins.retainAll(g.getMembers()); + if (currentAdmins.contains(getSelfRecipientId()) + && currentAdmins.size() == 1 + && g.getMembers().size() > 1 + && newAdmins.size() == 0) { + // Last admin can't leave the group, unless she's also the last member + throw new LastGroupAdminException(g.getGroupId(), g.getTitle()); + } + final var groupGroupChangePair = groupV2Helper.leaveGroup(groupInfoV2, newAdmins); groupInfoV2.setGroup(groupGroupChangePair.first(), this::resolveRecipient); messageBuilder = getGroupUpdateMessageBuilder(groupInfoV2, groupGroupChangePair.second().toByteArray()); account.getGroupStore().updateGroup(groupInfoV2); @@ -836,7 +851,10 @@ public class Manager implements Closeable { List removeAdmins, boolean resetGroupLink, GroupLinkState groupLinkState, - File avatarFile + GroupPermission addMemberPermission, + GroupPermission editDetailsPermission, + File avatarFile, + Integer expirationTimer ) throws IOException, GroupNotFoundException, AttachmentInvalidException, InvalidNumberException, NotAGroupMemberException { return updateGroup(groupId, name, @@ -847,7 +865,10 @@ public class Manager implements Closeable { removeAdmins == null ? null : getSignalServiceAddresses(removeAdmins), resetGroupLink, groupLinkState, - avatarFile); + addMemberPermission, + editDetailsPermission, + avatarFile, + expirationTimer); } private Pair> updateGroup( @@ -860,7 +881,10 @@ public class Manager implements Closeable { final Set removeAdmins, final boolean resetGroupLink, final GroupLinkState groupLinkState, - final File avatarFile + final GroupPermission addMemberPermission, + final GroupPermission editDetailsPermission, + final File avatarFile, + final Integer expirationTimer ) throws IOException, GroupNotFoundException, AttachmentInvalidException, NotAGroupMemberException { var group = getGroupForUpdating(groupId); @@ -874,10 +898,18 @@ public class Manager implements Closeable { removeAdmins, resetGroupLink, groupLinkState, - avatarFile); + addMemberPermission, + editDetailsPermission, + avatarFile, + expirationTimer); } - return updateGroupV1((GroupInfoV1) group, name, members, avatarFile); + final var gv1 = (GroupInfoV1) group; + final var result = updateGroupV1(gv1, name, members, avatarFile); + if (expirationTimer != null) { + setExpirationTimer(gv1, expirationTimer); + } + return result; } private Pair> updateGroupV1( @@ -939,7 +971,10 @@ public class Manager implements Closeable { final Set removeAdmins, final boolean resetGroupLink, final GroupLinkState groupLinkState, - final File avatarFile + final GroupPermission addMemberPermission, + final GroupPermission editDetailsPermission, + final File avatarFile, + Integer expirationTimer ) throws IOException { Pair> result = null; if (group.isPendingMember(account.getSelfRecipientId())) { @@ -1010,7 +1045,22 @@ public class Manager implements Closeable { result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second()); } - if (result == null || name != null || description != null || avatarFile != null) { + if (addMemberPermission != null) { + var groupGroupChangePair = groupV2Helper.setAddMemberPermission(group, addMemberPermission); + result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second()); + } + + if (editDetailsPermission != null) { + var groupGroupChangePair = groupV2Helper.setEditDetailsPermission(group, editDetailsPermission); + result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second()); + } + + if (expirationTimer != null) { + var groupGroupChangePair = groupV2Helper.setMessageExpirationTimer(group, expirationTimer); + result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second()); + } + + if (name != null || description != null || avatarFile != null) { var groupGroupChangePair = groupV2Helper.updateGroup(group, name, description, avatarFile); if (avatarFile != null) { avatarStore.storeGroupAvatar(group.getGroupId(), @@ -1306,15 +1356,17 @@ public class Manager implements Closeable { /** * Change the expiration timer for a group */ - public void setExpirationTimer(GroupId groupId, int messageExpirationTimer) { - var g = getGroup(groupId); - if (g instanceof GroupInfoV1) { - var groupInfoV1 = (GroupInfoV1) g; - groupInfoV1.messageExpirationTime = messageExpirationTimer; - account.getGroupStore().updateGroup(groupInfoV1); - } else { - throw new RuntimeException("TODO Not implemented!"); - } + private void setExpirationTimer( + GroupInfoV1 groupInfoV1, int messageExpirationTimer + ) throws NotAGroupMemberException, GroupNotFoundException, IOException { + groupInfoV1.messageExpirationTime = messageExpirationTimer; + account.getGroupStore().updateGroup(groupInfoV1); + sendExpirationTimerUpdate(groupInfoV1.getGroupId()); + } + + private void sendExpirationTimerUpdate(GroupIdV1 groupId) throws IOException, NotAGroupMemberException, GroupNotFoundException { + final var messageBuilder = SignalServiceDataMessage.newBuilder().asExpirationUpdate(); + sendGroupMessage(messageBuilder, groupId); } /**