Send remote delete (#593)

* 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
This commit is contained in:
Adaptive Garage 2021-04-05 19:49:45 +02:00 committed by GitHub
parent 2ad18342a8
commit 05abb3f9f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 184 additions and 3 deletions

View 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( public Pair<Long, List<SendMessageResult>> sendMessageReaction(
String emoji, boolean remove, String targetAuthor, long targetSentTimestamp, List<String> recipients String emoji, boolean remove, String targetAuthor, long targetSentTimestamp, List<String> recipients
) throws IOException, InvalidNumberException { ) throws IOException, InvalidNumberException {

View file

@ -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>:: getContactName(number<s>) -> name<s>::
* number : Phone number * 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 * 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

View file

@ -193,6 +193,19 @@ Specify the timestamp of the message to which to react.
*-r*, *--remove*:: *-r*, *--remove*::
Remove a reaction. 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 === receive
Query the server for new messages. Query the server for new messages.

View file

@ -21,6 +21,18 @@ public interface Signal extends DBusInterface {
String message, List<String> attachments, List<String> recipients String message, List<String> attachments, List<String> recipients
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity; ) 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( long sendMessageReaction(
String emoji, boolean remove, String targetAuthor, long targetSentTimestamp, String recipient String emoji, boolean remove, String targetAuthor, long targetSentTimestamp, String recipient
) throws Error.InvalidNumber, Error.Failure; ) throws Error.InvalidNumber, Error.Failure;

View file

@ -22,20 +22,21 @@ public class Commands {
addCommand("receive", new ReceiveCommand()); addCommand("receive", new ReceiveCommand());
addCommand("register", new RegisterCommand()); addCommand("register", new RegisterCommand());
addCommand("removeDevice", new RemoveDeviceCommand()); addCommand("removeDevice", new RemoveDeviceCommand());
addCommand("remoteDelete", new RemoteDeleteCommand());
addCommand("removePin", new RemovePinCommand()); addCommand("removePin", new RemovePinCommand());
addCommand("send", new SendCommand()); 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("setPin", new SetPinCommand());
addCommand("trust", new TrustCommand()); addCommand("trust", new TrustCommand());
addCommand("unblock", new UnblockCommand()); addCommand("unblock", new UnblockCommand());
addCommand("unregister", new UnregisterCommand()); addCommand("unregister", new UnregisterCommand());
addCommand("updateAccount", new UpdateAccountCommand()); addCommand("updateAccount", new UpdateAccountCommand());
addCommand("updateContact", new UpdateContactCommand());
addCommand("updateGroup", new UpdateGroupCommand()); addCommand("updateGroup", new UpdateGroupCommand());
addCommand("updateProfile", new UpdateProfileCommand()); 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() {

View file

@ -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());
}
}
}

View 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 @Override
public long sendMessageReaction( public long sendMessageReaction(
final String emoji, final boolean remove, final String targetAuthor, final long targetSentTimestamp, final String recipient final String emoji, final boolean remove, final String targetAuthor, final long targetSentTimestamp, final String recipient