]> nmode's Git Repositories - signal-cli/commitdiff
Send remote delete (#593)
authorAdaptive Garage <adaptivegarage@users.noreply.github.com>
Mon, 5 Apr 2021 17:49:45 +0000 (19:49 +0200)
committerGitHub <noreply@github.com>
Mon, 5 Apr 2021 17:49:45 +0000 (19:49 +0200)
* Implementation of remoteDelete command, iteration 1

* Implementation of remoteDelete command, iteration 2

* Implementation of remoteDelete command, iteration 3

* Implementation of remoteDelete command, iteration 4

* Implementation of remoteDelete command, iteration 5

* Implementation of remoteDelete command, iteration 6

* Renaming dbus methods remoteGroupDelete -> sendGroupRemoteDeleteMessage, remoteDelete -> sendRemoteDeleteMessage

lib/src/main/java/org/asamk/signal/manager/Manager.java
man/signal-cli-dbus.5.adoc
man/signal-cli.1.adoc
src/main/java/org/asamk/Signal.java
src/main/java/org/asamk/signal/commands/Commands.java
src/main/java/org/asamk/signal/commands/RemoteDeleteCommand.java [new file with mode: 0644]
src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java

index 99099e92535848848406dd85bb2836827451ad1e..5d0e7d3dfca0ec4605918fdc9f034f9839b63c60 100644 (file)
@@ -992,6 +992,22 @@ public class Manager implements Closeable {
         return sendSelfMessage(messageBuilder);
     }
 
         return sendSelfMessage(messageBuilder);
     }
 
+    public Pair<Long, List<SendMessageResult>> sendRemoteDeleteMessage(
+            long targetSentTimestamp, List<String> recipients
+    ) throws IOException, InvalidNumberException {
+        var delete = new SignalServiceDataMessage.RemoteDelete(targetSentTimestamp);
+        final var messageBuilder = SignalServiceDataMessage.newBuilder().withRemoteDelete(delete);
+        return sendMessage(messageBuilder, getSignalServiceAddresses(recipients));
+    }
+
+    public Pair<Long, List<SendMessageResult>> sendGroupRemoteDeleteMessage(
+            long targetSentTimestamp, GroupId groupId
+    ) throws IOException, NotAGroupMemberException, GroupNotFoundException {
+        var delete = new SignalServiceDataMessage.RemoteDelete(targetSentTimestamp);
+        final var messageBuilder = SignalServiceDataMessage.newBuilder().withRemoteDelete(delete);
+        return sendGroupMessage(messageBuilder, groupId);
+    }
+
     public Pair<Long, List<SendMessageResult>> sendMessageReaction(
             String emoji, boolean remove, String targetAuthor, long targetSentTimestamp, List<String> recipients
     ) throws IOException, InvalidNumberException {
     public Pair<Long, List<SendMessageResult>> sendMessageReaction(
             String emoji, boolean remove, String targetAuthor, long targetSentTimestamp, List<String> recipients
     ) throws IOException, InvalidNumberException {
index eccfd821a1d58501102d755241cff9bc5fc7796e..ece2460f0f2c4c36ff6fe9c4934eaea92629aa3d 100755 (executable)
@@ -149,6 +149,24 @@ Depending on the type of the recipient(s) field this sends a reaction to one or
 
 Exceptions: Failure, InvalidNumber
 
 
 Exceptions: Failure, InvalidNumber
 
+sendGroupRemoteDeleteMessage(targetSentTimestamp<x>, groupId<ay>) -> timestamp<x>::
+* targetSentTimestamp : Long representing timestamp of the message to delete
+* groupId             : Byte array with base64 encoded group identifier
+* timestamp           : Long, can be used to identify the corresponding signal reply
+
+Exceptions: Failure, GroupNotFound
+
+sendRemoteDeleteMessage(targetSentTimestamp<x>, recipient<s>) -> timestamp<x>::
+sendRemoteDeleteMessage(targetSentTimestamp<x>, recipients<as>) -> timestamp<x>::
+* targetSentTimestamp : Long representing timestamp of the message to delete
+* recipient           : String with the phone number of a single recipient
+* recipients          : Array of strings with phone numbers, should there be more recipients
+* timestamp           : Long, can be used to identify the corresponding signal reply
+
+Depending on the type of the recipient(s) field this deletes a message with one or multiple recipients.
+
+Exceptions: Failure, InvalidNumber
+
 getContactName(number<s>) -> name<s>::
 * number  : Phone number
 * name    : Contact's name in local storage (from the master device for a linked account, or the one set with setContactName); if not set, contact's profile name is used
 getContactName(number<s>) -> name<s>::
 * number  : Phone number
 * name    : Contact's name in local storage (from the master device for a linked account, or the one set with setContactName); if not set, contact's profile name is used
index 16b684eaabb50ca2252a9f42862732d624bf14d9..f6145385ee2362672bc317d6d6e6548049852f09 100644 (file)
@@ -193,6 +193,19 @@ Specify the timestamp of the message to which to react.
 *-r*, *--remove*::
 Remove a reaction.
 
 *-r*, *--remove*::
 Remove a reaction.
 
+=== remoteDelete
+
+Remotely delete a previously sent message.
+
+RECIPIENT::
+Specify the recipients’ phone number.
+
+*-g* GROUP, *--group* GROUP::
+Specify the recipient group ID in base64 encoding.
+
+*-t* TIMESTAMP, *--target-timestamp* TIMESTAMP::
+Specify the timestamp of the message to delete.
+
 === receive
 
 Query the server for new messages.
 === receive
 
 Query the server for new messages.
index f8841da95b73321a16644e85730c8d71ed15cc99..0093ab9b19e35d70ac31f05a5e0abfd1d1d5b331 100644 (file)
@@ -21,6 +21,18 @@ public interface Signal extends DBusInterface {
             String message, List<String> attachments, List<String> recipients
     ) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
 
             String message, List<String> attachments, List<String> recipients
     ) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
 
+    long sendRemoteDeleteMessage(
+            long targetSentTimestamp, String recipient
+    ) throws Error.Failure, Error.InvalidNumber;
+
+    long sendRemoteDeleteMessage(
+            long targetSentTimestamp, List<String> recipients
+    ) throws Error.Failure, Error.InvalidNumber;
+
+    long sendGroupRemoteDeleteMessage(
+            long targetSentTimestamp, byte[] groupId
+    ) throws Error.Failure, Error.GroupNotFound;
+
     long sendMessageReaction(
             String emoji, boolean remove, String targetAuthor, long targetSentTimestamp, String recipient
     ) throws Error.InvalidNumber, Error.Failure;
     long sendMessageReaction(
             String emoji, boolean remove, String targetAuthor, long targetSentTimestamp, String recipient
     ) throws Error.InvalidNumber, Error.Failure;
index 4bc17930653f58cd39b959bd5f85519ff38e3969..830049a584df5181571a5d0a13287306086d5c96 100644 (file)
@@ -22,20 +22,21 @@ public class Commands {
         addCommand("receive", new ReceiveCommand());
         addCommand("register", new RegisterCommand());
         addCommand("removeDevice", new RemoveDeviceCommand());
         addCommand("receive", new ReceiveCommand());
         addCommand("register", new RegisterCommand());
         addCommand("removeDevice", new RemoveDeviceCommand());
+        addCommand("remoteDelete", new RemoteDeleteCommand());
         addCommand("removePin", new RemovePinCommand());
         addCommand("send", new SendCommand());
         addCommand("removePin", new RemovePinCommand());
         addCommand("send", new SendCommand());
-        addCommand("sendReaction", new SendReactionCommand());
         addCommand("sendContacts", new SendContactsCommand());
         addCommand("sendContacts", new SendContactsCommand());
-        addCommand("updateContact", new UpdateContactCommand());
+        addCommand("sendReaction", new SendReactionCommand());
         addCommand("setPin", new SetPinCommand());
         addCommand("trust", new TrustCommand());
         addCommand("unblock", new UnblockCommand());
         addCommand("unregister", new UnregisterCommand());
         addCommand("updateAccount", new UpdateAccountCommand());
         addCommand("setPin", new SetPinCommand());
         addCommand("trust", new TrustCommand());
         addCommand("unblock", new UnblockCommand());
         addCommand("unregister", new UnregisterCommand());
         addCommand("updateAccount", new UpdateAccountCommand());
+        addCommand("updateContact", new UpdateContactCommand());
         addCommand("updateGroup", new UpdateGroupCommand());
         addCommand("updateProfile", new UpdateProfileCommand());
         addCommand("updateGroup", new UpdateGroupCommand());
         addCommand("updateProfile", new UpdateProfileCommand());
-        addCommand("verify", new VerifyCommand());
         addCommand("uploadStickerPack", new UploadStickerPackCommand());
         addCommand("uploadStickerPack", new UploadStickerPackCommand());
+        addCommand("verify", new VerifyCommand());
     }
 
     public static Map<String, Command> getCommands() {
     }
 
     public static Map<String, Command> getCommands() {
diff --git a/src/main/java/org/asamk/signal/commands/RemoteDeleteCommand.java b/src/main/java/org/asamk/signal/commands/RemoteDeleteCommand.java
new file mode 100644 (file)
index 0000000..796a334
--- /dev/null
@@ -0,0 +1,82 @@
+package org.asamk.signal.commands;
+
+import net.sourceforge.argparse4j.inf.Namespace;
+import net.sourceforge.argparse4j.inf.Subparser;
+
+import org.asamk.Signal;
+import org.asamk.signal.PlainTextWriterImpl;
+import org.asamk.signal.commands.exceptions.CommandException;
+import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
+import org.asamk.signal.commands.exceptions.UserErrorException;
+import org.asamk.signal.manager.groups.GroupIdFormatException;
+import org.asamk.signal.util.Util;
+import org.freedesktop.dbus.errors.UnknownObject;
+import org.freedesktop.dbus.exceptions.DBusExecutionException;
+
+import java.util.List;
+
+import static org.asamk.signal.util.ErrorUtils.handleAssertionError;
+
+public class RemoteDeleteCommand implements DbusCommand {
+
+    @Override
+    public void attachToSubparser(final Subparser subparser) {
+        subparser.help("Remotely delete a previously sent message.");
+        subparser.addArgument("-t", "--target-timestamp")
+                .required(true)
+                .type(long.class)
+                .help("Specify the timestamp of the message to delete.");
+        subparser.addArgument("-g", "--group")
+                .help("Specify the recipient group ID.");
+        subparser.addArgument("recipient")
+                .help("Specify the recipients' phone number.").nargs("*");
+    }
+
+    @Override
+    public void handleCommand(final Namespace ns, final Signal signal) throws CommandException {
+        final List<String> recipients = ns.getList("recipient");
+        final var groupIdString = ns.getString("group");
+
+        final var noRecipients = recipients == null || recipients.isEmpty();
+        if (noRecipients && groupIdString == null) {
+            throw new UserErrorException("No recipients given");
+        }
+        if (!noRecipients && groupIdString != null) {
+            throw new UserErrorException("You cannot specify recipients by phone number and groups at the same time");
+        }
+
+        final long targetTimestamp = ns.getLong("target_timestamp");
+
+        final var writer = new PlainTextWriterImpl(System.out);
+
+        byte[] groupId = null;
+        if (groupIdString != null) {
+            try {
+                groupId = Util.decodeGroupId(groupIdString).serialize();
+            } catch (GroupIdFormatException e) {
+                throw new UserErrorException("Invalid group id: " + e.getMessage());
+            }
+        }
+
+        try {
+            long timestamp;
+            if (groupId != null) {
+                timestamp = signal.sendGroupRemoteDeleteMessage(targetTimestamp, groupId);
+            } else {
+                timestamp = signal.sendRemoteDeleteMessage(targetTimestamp, recipients);
+            }
+            writer.println("{}", timestamp);
+        } catch (AssertionError e) {
+            handleAssertionError(e);
+            throw e;
+        } catch (UnknownObject e) {
+            throw new UserErrorException("Failed to find dbus object, maybe missing the -u flag: " + e.getMessage());
+        } catch (Signal.Error.InvalidNumber e) {
+            throw new UserErrorException("Invalid number: " + e.getMessage());
+        } catch (Signal.Error.GroupNotFound e) {
+            throw new UserErrorException("Failed to send to group: " + e.getMessage());
+        } catch (DBusExecutionException e) {
+            throw new UnexpectedErrorException("Failed to send message: " + e.getMessage());
+        }
+    }
+}
index 9bc4b67f9a9ba68133c005fff47b457cd5014d89..6b22029b2fc0434f05c0465f383116aabc5a6f6e 100644 (file)
@@ -103,6 +103,45 @@ public class DbusSignalImpl implements Signal {
         }
     }
 
         }
     }
 
+    @Override
+    public long sendRemoteDeleteMessage(
+            final long targetSentTimestamp, final String recipient
+    ) {
+        var recipients = new ArrayList<String>(1);
+        recipients.add(recipient);
+        return sendRemoteDeleteMessage(targetSentTimestamp, recipients);
+    }
+
+    @Override
+    public long sendRemoteDeleteMessage(
+            final long targetSentTimestamp, final List<String> recipients
+    ) {
+        try {
+            final var results = m.sendRemoteDeleteMessage(targetSentTimestamp, recipients);
+            checkSendMessageResults(results.first(), results.second());
+            return results.first();
+        } catch (IOException e) {
+            throw new Error.Failure(e.getMessage());
+        } catch (InvalidNumberException e) {
+            throw new Error.InvalidNumber(e.getMessage());
+        }
+    }
+
+    @Override
+    public long sendGroupRemoteDeleteMessage(
+            final long targetSentTimestamp, final byte[] groupId
+    ) {
+        try {
+            final var results = m.sendGroupRemoteDeleteMessage(targetSentTimestamp, GroupId.unknownVersion(groupId));
+            checkSendMessageResults(results.first(), results.second());
+            return results.first();
+        } catch (IOException e) {
+            throw new Error.Failure(e.getMessage());
+        } catch (GroupNotFoundException | NotAGroupMemberException e) {
+            throw new Error.GroupNotFound(e.getMessage());
+        }
+    }
+
     @Override
     public long sendMessageReaction(
             final String emoji, final boolean remove, final String targetAuthor, final long targetSentTimestamp, final String recipient
     @Override
     public long sendMessageReaction(
             final String emoji, final boolean remove, final String targetAuthor, final long targetSentTimestamp, final String recipient