]> nmode's Git Repositories - signal-cli/commitdiff
Add --hide parameter to removeContact command
authorAsamK <asamk@gmx.de>
Sat, 11 Nov 2023 10:35:23 +0000 (11:35 +0100)
committerAsamK <asamk@gmx.de>
Sat, 11 Nov 2023 10:39:33 +0000 (11:39 +0100)
14 files changed:
lib/src/main/java/org/asamk/signal/manager/Manager.java
lib/src/main/java/org/asamk/signal/manager/api/Contact.java
lib/src/main/java/org/asamk/signal/manager/helper/ContactHelper.java
lib/src/main/java/org/asamk/signal/manager/helper/SendHelper.java
lib/src/main/java/org/asamk/signal/manager/helper/StorageHelper.java
lib/src/main/java/org/asamk/signal/manager/helper/SyncHelper.java
lib/src/main/java/org/asamk/signal/manager/internal/ManagerImpl.java
lib/src/main/java/org/asamk/signal/manager/storage/AccountDatabase.java
lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java
lib/src/main/java/org/asamk/signal/manager/storage/recipients/LegacyRecipientStore2.java
lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java
man/signal-cli.1.adoc
src/main/java/org/asamk/signal/commands/RemoveContactCommand.java
src/main/java/org/asamk/signal/dbus/DbusManagerImpl.java

index da69a8da5557c561be40a7df9cec952ee5bec19c..6153000b8e0e0fa7e477c34ef6ff3a5038f13263 100644 (file)
@@ -193,6 +193,8 @@ public interface Manager extends Closeable {
 
     SendMessageResults sendEndSessionMessage(Set<RecipientIdentifier.Single> recipients) throws IOException;
 
+    void hideRecipient(RecipientIdentifier.Single recipient);
+
     void deleteRecipient(RecipientIdentifier.Single recipient);
 
     void deleteContact(RecipientIdentifier.Single recipient);
index e6dd5f930b026c74e33a54d9b1f4ea920e8f26cd..f84c667b9d3ddcfa1dd58059962c1b0753544bd4 100644 (file)
@@ -9,7 +9,8 @@ public record Contact(
         int messageExpirationTime,
         boolean isBlocked,
         boolean isArchived,
-        boolean isProfileSharingEnabled
+        boolean isProfileSharingEnabled,
+        boolean isHidden
 ) {
 
     private Contact(final Builder builder) {
@@ -17,9 +18,10 @@ public record Contact(
                 builder.familyName,
                 builder.color,
                 builder.messageExpirationTime,
-                builder.blocked,
-                builder.archived,
-                builder.profileSharingEnabled);
+                builder.isBlocked,
+                builder.isArchived,
+                builder.isProfileSharingEnabled,
+                builder.isHidden);
     }
 
     public static Builder newBuilder() {
@@ -32,9 +34,10 @@ public record Contact(
         builder.familyName = copy.familyName();
         builder.color = copy.color();
         builder.messageExpirationTime = copy.messageExpirationTime();
-        builder.blocked = copy.isBlocked();
-        builder.archived = copy.isArchived();
-        builder.profileSharingEnabled = copy.isProfileSharingEnabled();
+        builder.isBlocked = copy.isBlocked();
+        builder.isArchived = copy.isArchived();
+        builder.isProfileSharingEnabled = copy.isProfileSharingEnabled();
+        builder.isHidden = copy.isHidden();
         return builder;
     }
 
@@ -59,13 +62,18 @@ public record Contact(
         private String familyName;
         private String color;
         private int messageExpirationTime;
-        private boolean blocked;
-        private boolean archived;
-        private boolean profileSharingEnabled;
+        private boolean isBlocked;
+        private boolean isArchived;
+        private boolean isProfileSharingEnabled;
+        private boolean isHidden;
 
         private Builder() {
         }
 
+        public static Builder newBuilder() {
+            return new Builder();
+        }
+
         public Builder withGivenName(final String val) {
             givenName = val;
             return this;
@@ -86,18 +94,23 @@ public record Contact(
             return this;
         }
 
-        public Builder withBlocked(final boolean val) {
-            blocked = val;
+        public Builder withIsBlocked(final boolean val) {
+            isBlocked = val;
+            return this;
+        }
+
+        public Builder withIsArchived(final boolean val) {
+            isArchived = val;
             return this;
         }
 
-        public Builder withArchived(final boolean val) {
-            archived = val;
+        public Builder withIsProfileSharingEnabled(final boolean val) {
+            isProfileSharingEnabled = val;
             return this;
         }
 
-        public Builder withProfileSharingEnabled(final boolean val) {
-            profileSharingEnabled = val;
+        public Builder withIsHidden(final boolean val) {
+            isHidden = val;
             return this;
         }
 
index 4e96baccfb83cb13d5c648615fe72d19f8f76293..609c2bcf77ee100ceec3ddc4913f76e9b2aa580c 100644 (file)
@@ -20,6 +20,7 @@ public class ContactHelper {
     public void setContactName(final RecipientId recipientId, final String givenName, final String familyName) {
         var contact = account.getContactStore().getContact(recipientId);
         final var builder = contact == null ? Contact.newBuilder() : Contact.newBuilder(contact);
+        builder.withIsHidden(false);
         if (givenName != null) {
             builder.withGivenName(givenName);
         }
@@ -43,8 +44,14 @@ public class ContactHelper {
         var contact = account.getContactStore().getContact(recipientId);
         final var builder = contact == null ? Contact.newBuilder() : Contact.newBuilder(contact);
         if (blocked) {
-            builder.withProfileSharingEnabled(false);
+            builder.withIsProfileSharingEnabled(false);
         }
-        account.getContactStore().storeContact(recipientId, builder.withBlocked(blocked).build());
+        account.getContactStore().storeContact(recipientId, builder.withIsBlocked(blocked).build());
+    }
+
+    public void setContactHidden(RecipientId recipientId, boolean hidden) {
+        var contact = account.getContactStore().getContact(recipientId);
+        final var builder = contact == null ? Contact.newBuilder() : Contact.newBuilder(contact);
+        account.getContactStore().storeContact(recipientId, builder.withIsHidden(hidden).build());
     }
 }
index 236078157bff13d9d1100e36604c6b07793bf373..5ffb964634fcbdb8573fa822d3a36c20c1e19f0e 100644 (file)
@@ -78,9 +78,9 @@ public class SendHelper {
             Optional<Long> editTargetTimestamp
     ) {
         var contact = account.getContactStore().getContact(recipientId);
-        if (contact == null || !contact.isProfileSharingEnabled()) {
+        if (contact == null || !contact.isProfileSharingEnabled() || contact.isHidden()) {
             final var contactBuilder = contact == null ? Contact.newBuilder() : Contact.newBuilder(contact);
-            contact = contactBuilder.withProfileSharingEnabled(true).build();
+            contact = contactBuilder.withIsProfileSharingEnabled(true).withIsHidden(false).build();
             account.getContactStore().storeContact(recipientId, contact);
         }
 
index 35821c5b818e27b14b82993fd2dd5aba48c2d26f..f251856842597795c1badb7cb33eb657c0aae3b2 100644 (file)
@@ -116,11 +116,13 @@ public class StorageHelper {
         final var blocked = contact != null && contact.isBlocked();
         final var profileShared = contact != null && contact.isProfileSharingEnabled();
         final var archived = contact != null && contact.isArchived();
+        final var hidden = contact != null && contact.isHidden();
         final var contactGivenName = contact == null ? null : contact.givenName();
         final var contactFamilyName = contact == null ? null : contact.familyName();
         if (blocked != contactRecord.isBlocked()
                 || profileShared != contactRecord.isProfileSharingEnabled()
                 || archived != contactRecord.isArchived()
+                || hidden != contactRecord.isHidden()
                 || (
                 contactRecord.getSystemGivenName().isPresent() && !contactRecord.getSystemGivenName()
                         .get()
@@ -133,9 +135,10 @@ public class StorageHelper {
         )) {
             logger.debug("Storing new or updated contact {}", recipientId);
             final var contactBuilder = contact == null ? Contact.newBuilder() : Contact.newBuilder(contact);
-            final var newContact = contactBuilder.withBlocked(contactRecord.isBlocked())
-                    .withProfileSharingEnabled(contactRecord.isProfileSharingEnabled())
-                    .withArchived(contactRecord.isArchived());
+            final var newContact = contactBuilder.withIsBlocked(contactRecord.isBlocked())
+                    .withIsProfileSharingEnabled(contactRecord.isProfileSharingEnabled())
+                    .withIsArchived(contactRecord.isArchived())
+                    .withIsHidden(contactRecord.isHidden());
             if (contactRecord.getSystemGivenName().isPresent() || contactRecord.getSystemFamilyName().isPresent()) {
                 newContact.withGivenName(contactRecord.getSystemGivenName().orElse(null))
                         .withFamilyName(contactRecord.getSystemFamilyName().orElse(null));
index 0badc54498befa06010587c150c1c32995b0e369..f6392ea9e28cb233ab0fd9162f0e05c41f5f045a 100644 (file)
@@ -339,8 +339,8 @@ public class SyncHelper {
             if (c.getExpirationTimer().isPresent()) {
                 builder.withMessageExpirationTime(c.getExpirationTimer().get());
             }
-            builder.withBlocked(c.isBlocked());
-            builder.withArchived(c.isArchived());
+            builder.withIsBlocked(c.isBlocked());
+            builder.withIsArchived(c.isArchived());
             account.getContactStore().storeContact(recipientId, builder.build());
 
             if (c.getAvatar().isPresent()) {
index af2c6558c4d6f064b860d95d335f65a238123c0f..cc67229a94e92bc2372257637cb11791099eee66 100644 (file)
@@ -840,6 +840,15 @@ public class ManagerImpl implements Manager {
         }
     }
 
+    @Override
+    public void hideRecipient(final RecipientIdentifier.Single recipient) {
+        final var recipientIdOptional = context.getRecipientHelper().resolveRecipientOptional(recipient);
+        if (recipientIdOptional.isPresent()) {
+            context.getContactHelper().setContactHidden(recipientIdOptional.get(), true);
+            account.removeRecipient(recipientIdOptional.get());
+        }
+    }
+
     @Override
     public void deleteRecipient(final RecipientIdentifier.Single recipient) {
         final var recipientIdOptional = context.getRecipientHelper().resolveRecipientOptional(recipient);
index 94dff8fcb1d70efdd4889acdf12322c2235b643b..43a146a7a700f4cb87c6d8bc864f29c6a0b4b03b 100644 (file)
@@ -32,7 +32,7 @@ import java.util.UUID;
 public class AccountDatabase extends Database {
 
     private static final Logger logger = LoggerFactory.getLogger(AccountDatabase.class);
-    private static final long DATABASE_VERSION = 18;
+    private static final long DATABASE_VERSION = 19;
 
     private AccountDatabase(final HikariDataSource dataSource) {
         super(logger, DATABASE_VERSION, dataSource);
@@ -531,5 +531,13 @@ public class AccountDatabase extends Database {
                                         """);
             }
         }
+        if (oldVersion < 19) {
+            logger.debug("Updating database: Adding contact hidden column");
+            try (final var statement = connection.createStatement()) {
+                statement.executeUpdate("""
+                                        ALTER TABLE recipient ADD COLUMN hidden INTEGER NOT NULL DEFAULT FALSE;
+                                        """);
+            }
+        }
     }
 }
index dee71275bc15d56b4d25cb595b37f62292780711..4b2e64032fad44180139ed081ecc0ee7c328d9a4 100644 (file)
@@ -826,6 +826,7 @@ public class SignalAccount implements Closeable {
                                 contact.messageExpirationTime,
                                 contact.blocked,
                                 contact.archived,
+                                false,
                                 false));
 
                 // Store profile keys only in profile store
index 2f714c6f27bf0bf564bdeb1f9fcff58ee720eba6..55231cb7eb474dfcc568007f45ccc6c740b19bd8 100644 (file)
@@ -44,7 +44,8 @@ public class LegacyRecipientStore2 {
                             r.contact.messageExpirationTime,
                             r.contact.blocked,
                             r.contact.archived,
-                            r.contact.profileSharingEnabled);
+                            r.contact.profileSharingEnabled,
+                            false);
                 }
 
                 ProfileKey profileKey = null;
index c446e4680bb45564a85b1fb5ec7dc03094682ad8..bc7475b74efa0b35e8a1f1485e034a89252a635b 100644 (file)
@@ -70,6 +70,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
                                       blocked INTEGER NOT NULL DEFAULT FALSE,
                                       archived INTEGER NOT NULL DEFAULT FALSE,
                                       profile_sharing INTEGER NOT NULL DEFAULT FALSE,
+                                      hidden INTEGER NOT NULL DEFAULT FALSE,
 
                                       profile_last_update_timestamp INTEGER NOT NULL DEFAULT 0,
                                       profile_given_name TEXT,
@@ -318,9 +319,9 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
     public List<Pair<RecipientId, Contact>> getContacts() {
         final var sql = (
                 """
-                SELECT r._id, r.given_name, r.family_name, r.expiration_time, r.profile_sharing, r.color, r.blocked, r.archived
+                SELECT r._id, r.given_name, r.family_name, r.expiration_time, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden
                 FROM %s r
-                WHERE (r.number IS NOT NULL OR r.uuid IS NOT NULL) AND %s
+                WHERE (r.number IS NOT NULL OR r.uuid IS NOT NULL) AND %s AND r.hidden = FALSE
                 """
         ).formatted(TABLE_RECIPIENT, SQL_IS_CONTACT);
         try (final var connection = database.getConnection()) {
@@ -342,6 +343,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
         final var sqlWhere = new ArrayList<String>();
         if (onlyContacts) {
             sqlWhere.add("(" + SQL_IS_CONTACT + ")");
+            sqlWhere.add("r.hidden = FALSE");
         }
         if (blocked.isPresent()) {
             sqlWhere.add("r.blocked = ?");
@@ -357,7 +359,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
                 SELECT r._id,
                        r.number, r.uuid, r.pni, r.username,
                        r.profile_key, r.profile_key_credential,
-                       r.given_name, r.family_name, r.expiration_time, r.profile_sharing, r.color, r.blocked, r.archived,
+                       r.given_name, r.family_name, r.expiration_time, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden,
                        r.profile_last_update_timestamp, r.profile_given_name, r.profile_family_name, r.profile_about, r.profile_about_emoji, r.profile_avatar_url_path, r.profile_mobile_coin_address, r.profile_unidentified_access_mode, r.profile_capabilities
                 FROM %s r
                 WHERE (r.number IS NOT NULL OR r.uuid IS NOT NULL) AND %s
@@ -962,7 +964,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
     private Contact getContact(final Connection connection, final RecipientId recipientId) throws SQLException {
         final var sql = (
                 """
-                SELECT r.given_name, r.family_name, r.expiration_time, r.profile_sharing, r.color, r.blocked, r.archived
+                SELECT r.given_name, r.family_name, r.expiration_time, r.profile_sharing, r.color, r.blocked, r.archived, r.hidden
                 FROM %s r
                 WHERE r._id = ? AND (%s)
                 """
@@ -1053,7 +1055,8 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
                 resultSet.getInt("expiration_time"),
                 resultSet.getBoolean("blocked"),
                 resultSet.getBoolean("archived"),
-                resultSet.getBoolean("profile_sharing"));
+                resultSet.getBoolean("profile_sharing"),
+                resultSet.getBoolean("hidden"));
     }
 
     private Profile getProfileFromResultSet(ResultSet resultSet) throws SQLException {
index 3a28219a4cef5500aea41fd8b1ed42b562407a19..4814d28a88f60868edad778d8d9291e63f034010 100644 (file)
@@ -613,6 +613,9 @@ Remove the info of a given contact
 NUMBER::
 Specify the contact phone number.
 
+*--hide*::
+Hide the contact in the contact list, but keep the data.
+
 *--forget*::
 Delete all data associated with this contact, including identity keys and sessions.
 
index c4a3d7d807dc0d010569ac96ef39cdf13abfdd73..aca5277856cc122656ce36387dec3053cd6d6fc4 100644 (file)
@@ -20,7 +20,11 @@ public class RemoveContactCommand implements JsonRpcLocalCommand {
     public void attachToSubparser(final Subparser subparser) {
         subparser.help("Remove the details of a given contact");
         subparser.addArgument("recipient").help("Contact number");
-        subparser.addArgument("--forget")
+        final var mut = subparser.addMutuallyExclusiveGroup();
+        mut.addArgument("--hide")
+                .action(Arguments.storeTrue())
+                .help("Hide the contact in the contact list, but keep the data.");
+        mut.addArgument("--forget")
                 .action(Arguments.storeTrue())
                 .help("Delete all data associated with this contact, including identity keys and sessions.");
     }
@@ -32,8 +36,11 @@ public class RemoveContactCommand implements JsonRpcLocalCommand {
         var recipientString = ns.getString("recipient");
         var recipient = CommandUtil.getSingleRecipientIdentifier(recipientString, m.getSelfNumber());
 
+        var hide = Boolean.TRUE == ns.getBoolean("hide");
         var forget = Boolean.TRUE == ns.getBoolean("forget");
-        if (forget) {
+        if (hide) {
+            m.hideRecipient(recipient);
+        } else if (forget) {
             m.deleteRecipient(recipient);
         } else {
             m.deleteContact(recipient);
index ea09dba4a9b40e9366829fa45a5438d76650794e..a3f18393799ac234da463b76fdadac756a126123 100644 (file)
@@ -452,6 +452,10 @@ public class DbusManagerImpl implements Manager {
         return new SendMessageResults(0, Map.of());
     }
 
+    public void hideRecipient(final RecipientIdentifier.Single recipient) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public void deleteRecipient(final RecipientIdentifier.Single recipient) {
         signal.deleteRecipient(recipient.getIdentifier());
@@ -653,7 +657,7 @@ public class DbusManagerImpl implements Manager {
             }
             return Recipient.newBuilder()
                     .withAddress(new RecipientAddress(null, n))
-                    .withContact(new Contact(contactName, null, null, 0, contactBlocked, false, false))
+                    .withContact(new Contact(contactName, null, null, 0, contactBlocked, false, false, false))
                     .build();
         }).filter(Objects::nonNull).toList();
     }