mirror of
https://github.com/AsamK/signal-cli
synced 2025-08-29 10:30:38 +00:00
Add support for banning/unbanning group members
This commit is contained in:
parent
69f1d0c213
commit
2a20e70aab
17 changed files with 246 additions and 16 deletions
|
@ -386,6 +386,12 @@ class ManagerImpl implements Manager {
|
|||
updateGroup.getRemoveAdmins() == null
|
||||
? null
|
||||
: context.getRecipientHelper().resolveRecipients(updateGroup.getRemoveAdmins()),
|
||||
updateGroup.getBanMembers() == null
|
||||
? null
|
||||
: context.getRecipientHelper().resolveRecipients(updateGroup.getBanMembers()),
|
||||
updateGroup.getUnbanMembers() == null
|
||||
? null
|
||||
: context.getRecipientHelper().resolveRecipients(updateGroup.getUnbanMembers()),
|
||||
updateGroup.isResetGroupLink(),
|
||||
updateGroup.getGroupLinkState(),
|
||||
updateGroup.getAddMemberPermission(),
|
||||
|
|
|
@ -20,6 +20,7 @@ public record Group(
|
|||
Set<RecipientAddress> pendingMembers,
|
||||
Set<RecipientAddress> requestingMembers,
|
||||
Set<RecipientAddress> adminMembers,
|
||||
Set<RecipientAddress> bannedMembers,
|
||||
boolean isBlocked,
|
||||
int messageExpirationTimer,
|
||||
GroupPermission permissionAddMember,
|
||||
|
@ -52,6 +53,10 @@ public record Group(
|
|||
.stream()
|
||||
.map(recipientStore::resolveRecipientAddress)
|
||||
.collect(Collectors.toSet()),
|
||||
groupInfo.getBannedMembers()
|
||||
.stream()
|
||||
.map(recipientStore::resolveRecipientAddress)
|
||||
.collect(Collectors.toSet()),
|
||||
groupInfo.isBlocked(),
|
||||
groupInfo.getMessageExpirationTimer(),
|
||||
groupInfo.getPermissionAddMember(),
|
||||
|
|
|
@ -14,6 +14,8 @@ public class UpdateGroup {
|
|||
private final Set<RecipientIdentifier.Single> removeMembers;
|
||||
private final Set<RecipientIdentifier.Single> admins;
|
||||
private final Set<RecipientIdentifier.Single> removeAdmins;
|
||||
private final Set<RecipientIdentifier.Single> banMembers;
|
||||
private final Set<RecipientIdentifier.Single> unbanMembers;
|
||||
private final boolean resetGroupLink;
|
||||
private final GroupLinkState groupLinkState;
|
||||
private final GroupPermission addMemberPermission;
|
||||
|
@ -29,6 +31,8 @@ public class UpdateGroup {
|
|||
removeMembers = builder.removeMembers;
|
||||
admins = builder.admins;
|
||||
removeAdmins = builder.removeAdmins;
|
||||
banMembers = builder.banMembers;
|
||||
unbanMembers = builder.unbanMembers;
|
||||
resetGroupLink = builder.resetGroupLink;
|
||||
groupLinkState = builder.groupLinkState;
|
||||
addMemberPermission = builder.addMemberPermission;
|
||||
|
@ -43,23 +47,58 @@ public class UpdateGroup {
|
|||
}
|
||||
|
||||
public static Builder newBuilder(final UpdateGroup copy) {
|
||||
Builder builder = new Builder();
|
||||
builder.name = copy.getName();
|
||||
builder.description = copy.getDescription();
|
||||
builder.members = copy.getMembers();
|
||||
builder.removeMembers = copy.getRemoveMembers();
|
||||
builder.admins = copy.getAdmins();
|
||||
builder.removeAdmins = copy.getRemoveAdmins();
|
||||
builder.resetGroupLink = copy.isResetGroupLink();
|
||||
builder.groupLinkState = copy.getGroupLinkState();
|
||||
builder.addMemberPermission = copy.getAddMemberPermission();
|
||||
builder.editDetailsPermission = copy.getEditDetailsPermission();
|
||||
builder.avatarFile = copy.getAvatarFile();
|
||||
builder.expirationTimer = copy.getExpirationTimer();
|
||||
builder.isAnnouncementGroup = copy.getIsAnnouncementGroup();
|
||||
Builder builder = new Builder(copy.name,
|
||||
copy.description,
|
||||
copy.members,
|
||||
copy.removeMembers,
|
||||
copy.admins,
|
||||
copy.removeAdmins,
|
||||
copy.banMembers,
|
||||
copy.unbanMembers,
|
||||
copy.resetGroupLink,
|
||||
copy.groupLinkState,
|
||||
copy.addMemberPermission,
|
||||
copy.editDetailsPermission,
|
||||
copy.avatarFile,
|
||||
copy.expirationTimer,
|
||||
copy.isAnnouncementGroup);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static Builder newBuilder(
|
||||
final String name,
|
||||
final String description,
|
||||
final Set<RecipientIdentifier.Single> members,
|
||||
final Set<RecipientIdentifier.Single> removeMembers,
|
||||
final Set<RecipientIdentifier.Single> admins,
|
||||
final Set<RecipientIdentifier.Single> removeAdmins,
|
||||
final Set<RecipientIdentifier.Single> banMembers,
|
||||
final Set<RecipientIdentifier.Single> unbanMembers,
|
||||
final boolean resetGroupLink,
|
||||
final GroupLinkState groupLinkState,
|
||||
final GroupPermission addMemberPermission,
|
||||
final GroupPermission editDetailsPermission,
|
||||
final File avatarFile,
|
||||
final Integer expirationTimer,
|
||||
final Boolean isAnnouncementGroup
|
||||
) {
|
||||
return new Builder(name,
|
||||
description,
|
||||
members,
|
||||
removeMembers,
|
||||
admins,
|
||||
removeAdmins,
|
||||
banMembers,
|
||||
unbanMembers,
|
||||
resetGroupLink,
|
||||
groupLinkState,
|
||||
addMemberPermission,
|
||||
editDetailsPermission,
|
||||
avatarFile,
|
||||
expirationTimer,
|
||||
isAnnouncementGroup);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -84,6 +123,14 @@ public class UpdateGroup {
|
|||
return removeAdmins;
|
||||
}
|
||||
|
||||
public Set<RecipientIdentifier.Single> getBanMembers() {
|
||||
return banMembers;
|
||||
}
|
||||
|
||||
public Set<RecipientIdentifier.Single> getUnbanMembers() {
|
||||
return unbanMembers;
|
||||
}
|
||||
|
||||
public boolean isResetGroupLink() {
|
||||
return resetGroupLink;
|
||||
}
|
||||
|
@ -120,6 +167,8 @@ public class UpdateGroup {
|
|||
private Set<RecipientIdentifier.Single> removeMembers;
|
||||
private Set<RecipientIdentifier.Single> admins;
|
||||
private Set<RecipientIdentifier.Single> removeAdmins;
|
||||
private Set<RecipientIdentifier.Single> banMembers;
|
||||
private Set<RecipientIdentifier.Single> unbanMembers;
|
||||
private boolean resetGroupLink;
|
||||
private GroupLinkState groupLinkState;
|
||||
private GroupPermission addMemberPermission;
|
||||
|
@ -131,6 +180,40 @@ public class UpdateGroup {
|
|||
private Builder() {
|
||||
}
|
||||
|
||||
private Builder(
|
||||
final String name,
|
||||
final String description,
|
||||
final Set<RecipientIdentifier.Single> members,
|
||||
final Set<RecipientIdentifier.Single> removeMembers,
|
||||
final Set<RecipientIdentifier.Single> admins,
|
||||
final Set<RecipientIdentifier.Single> removeAdmins,
|
||||
final Set<RecipientIdentifier.Single> banMembers,
|
||||
final Set<RecipientIdentifier.Single> unbanMembers,
|
||||
final boolean resetGroupLink,
|
||||
final GroupLinkState groupLinkState,
|
||||
final GroupPermission addMemberPermission,
|
||||
final GroupPermission editDetailsPermission,
|
||||
final File avatarFile,
|
||||
final Integer expirationTimer,
|
||||
final Boolean isAnnouncementGroup
|
||||
) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.members = members;
|
||||
this.removeMembers = removeMembers;
|
||||
this.admins = admins;
|
||||
this.removeAdmins = removeAdmins;
|
||||
this.banMembers = banMembers;
|
||||
this.unbanMembers = unbanMembers;
|
||||
this.resetGroupLink = resetGroupLink;
|
||||
this.groupLinkState = groupLinkState;
|
||||
this.addMemberPermission = addMemberPermission;
|
||||
this.editDetailsPermission = editDetailsPermission;
|
||||
this.avatarFile = avatarFile;
|
||||
this.expirationTimer = expirationTimer;
|
||||
this.isAnnouncementGroup = isAnnouncementGroup;
|
||||
}
|
||||
|
||||
public Builder withName(final String val) {
|
||||
name = val;
|
||||
return this;
|
||||
|
@ -161,6 +244,16 @@ public class UpdateGroup {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder withBanMembers(final Set<RecipientIdentifier.Single> val) {
|
||||
banMembers = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withUnbanMembers(final Set<RecipientIdentifier.Single> val) {
|
||||
unbanMembers = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withResetGroupLink(final boolean val) {
|
||||
resetGroupLink = val;
|
||||
return this;
|
||||
|
|
|
@ -194,6 +194,8 @@ public class GroupHelper {
|
|||
final Set<RecipientId> removeMembers,
|
||||
final Set<RecipientId> admins,
|
||||
final Set<RecipientId> removeAdmins,
|
||||
final Set<RecipientId> banMembers,
|
||||
final Set<RecipientId> unbanMembers,
|
||||
final boolean resetGroupLink,
|
||||
final GroupLinkState groupLinkState,
|
||||
final GroupPermission addMemberPermission,
|
||||
|
@ -213,6 +215,8 @@ public class GroupHelper {
|
|||
removeMembers,
|
||||
admins,
|
||||
removeAdmins,
|
||||
banMembers,
|
||||
unbanMembers,
|
||||
resetGroupLink,
|
||||
groupLinkState,
|
||||
addMemberPermission,
|
||||
|
@ -230,6 +234,8 @@ public class GroupHelper {
|
|||
removeMembers,
|
||||
admins,
|
||||
removeAdmins,
|
||||
banMembers,
|
||||
unbanMembers,
|
||||
resetGroupLink,
|
||||
groupLinkState,
|
||||
addMemberPermission,
|
||||
|
@ -467,6 +473,8 @@ public class GroupHelper {
|
|||
final Set<RecipientId> removeMembers,
|
||||
final Set<RecipientId> admins,
|
||||
final Set<RecipientId> removeAdmins,
|
||||
final Set<RecipientId> banMembers,
|
||||
final Set<RecipientId> unbanMembers,
|
||||
final boolean resetGroupLink,
|
||||
final GroupLinkState groupLinkState,
|
||||
final GroupPermission addMemberPermission,
|
||||
|
@ -493,7 +501,13 @@ public class GroupHelper {
|
|||
|
||||
if (removeMembers != null) {
|
||||
var existingRemoveMembers = new HashSet<>(removeMembers);
|
||||
if (banMembers != null) {
|
||||
existingRemoveMembers.addAll(banMembers);
|
||||
}
|
||||
existingRemoveMembers.retainAll(group.getMembers());
|
||||
if (members != null) {
|
||||
existingRemoveMembers.removeAll(members);
|
||||
}
|
||||
existingRemoveMembers.remove(account.getSelfRecipientId());// self can be removed with sendQuitGroupMessage
|
||||
if (existingRemoveMembers.size() > 0) {
|
||||
var groupGroupChangePair = groupV2Helper.removeMembers(group, existingRemoveMembers);
|
||||
|
@ -535,6 +549,24 @@ public class GroupHelper {
|
|||
}
|
||||
}
|
||||
|
||||
if (banMembers != null) {
|
||||
final var newlyBannedMembers = new HashSet<>(banMembers);
|
||||
newlyBannedMembers.removeAll(group.getBannedMembers());
|
||||
if (newlyBannedMembers.size() > 0) {
|
||||
var groupGroupChangePair = groupV2Helper.banMembers(group, newlyBannedMembers);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
}
|
||||
}
|
||||
|
||||
if (unbanMembers != null) {
|
||||
var existingUnbanMembers = new HashSet<>(unbanMembers);
|
||||
existingUnbanMembers.retainAll(group.getBannedMembers());
|
||||
if (existingUnbanMembers.size() > 0) {
|
||||
var groupGroupChangePair = groupV2Helper.unbanMembers(group, existingUnbanMembers);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
}
|
||||
}
|
||||
|
||||
if (resetGroupLink) {
|
||||
var groupGroupChangePair = groupV2Helper.resetGroupLinkPassword(group);
|
||||
result = sendUpdateGroupV2Message(group, groupGroupChangePair.first(), groupGroupChangePair.second());
|
||||
|
|
|
@ -203,9 +203,13 @@ class GroupV2Helper {
|
|||
credentials,
|
||||
(uuid, credential) -> new GroupCandidate(uuid, Optional.ofNullable(credential)))
|
||||
.collect(Collectors.toSet());
|
||||
final var bannedUuids = groupInfoV2.getBannedMembers()
|
||||
.stream()
|
||||
.map(member -> context.getRecipientHelper().resolveSignalServiceAddress(member).getServiceId().uuid())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
final var aci = getSelfAci();
|
||||
final var change = groupOperations.createModifyGroupMembershipChange(candidates, Set.of(), aci.uuid());
|
||||
final var change = groupOperations.createModifyGroupMembershipChange(candidates, bannedUuids, aci.uuid());
|
||||
|
||||
change.setSourceUuid(getSelfAci().toByteString());
|
||||
|
||||
|
@ -259,6 +263,40 @@ class GroupV2Helper {
|
|||
return revokeInvites(groupInfoV2, memberUuids);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> banMembers(
|
||||
GroupInfoV2 groupInfoV2, Set<RecipientId> block
|
||||
) throws IOException {
|
||||
GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
|
||||
final var uuids = block.stream()
|
||||
.map(member -> context.getRecipientHelper().resolveSignalServiceAddress(member).getServiceId().uuid())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
final var change = groupOperations.createBanUuidsChange(uuids,
|
||||
false,
|
||||
groupInfoV2.getGroup().getBannedMembersList());
|
||||
|
||||
change.setSourceUuid(getSelfAci().toByteString());
|
||||
|
||||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> unbanMembers(
|
||||
GroupInfoV2 groupInfoV2, Set<RecipientId> block
|
||||
) throws IOException {
|
||||
GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
|
||||
final var uuids = block.stream()
|
||||
.map(member -> context.getRecipientHelper().resolveSignalServiceAddress(member).getServiceId().uuid())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
final var change = groupOperations.createUnbanUuidsChange(uuids);
|
||||
|
||||
change.setSourceUuid(getSelfAci().toByteString());
|
||||
|
||||
return commitChange(groupInfoV2, change);
|
||||
}
|
||||
|
||||
Pair<DecryptedGroup, GroupChange> resetGroupLinkPassword(GroupInfoV2 groupInfoV2) throws IOException {
|
||||
final GroupsV2Operations.GroupOperations groupOperations = getGroupOperations(groupInfoV2);
|
||||
final var newGroupLinkPassword = GroupLinkPassword.createNew().serialize();
|
||||
|
|
|
@ -26,6 +26,10 @@ public sealed abstract class GroupInfo permits GroupInfoV1, GroupInfoV2 {
|
|||
|
||||
public abstract Set<RecipientId> getMembers();
|
||||
|
||||
public Set<RecipientId> getBannedMembers() {
|
||||
return Set.of();
|
||||
}
|
||||
|
||||
public Set<RecipientId> getPendingMembers() {
|
||||
return Set.of();
|
||||
}
|
||||
|
|
|
@ -117,6 +117,18 @@ public final class GroupInfoV2 extends GroupInfo {
|
|||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RecipientId> getBannedMembers() {
|
||||
if (this.group == null) {
|
||||
return Set.of();
|
||||
}
|
||||
return group.getBannedMembersList()
|
||||
.stream()
|
||||
.map(m -> ServiceId.fromByteString(m.getUuid()))
|
||||
.map(recipientResolver::resolveRecipient)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RecipientId> getPendingMembers() {
|
||||
if (this.group == null) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue