From: AsamK Date: Sat, 22 Feb 2020 10:29:17 +0000 (+0100) Subject: Add command sendReaction for emoji reactions X-Git-Tag: v0.6.6~32 X-Git-Url: https://git.nmode.ca/signal-cli/commitdiff_plain/063fb95dca87b6b57996c7379b958ae05e2e5ad9 Add command sendReaction for emoji reactions --- diff --git a/man/signal-cli.1.adoc b/man/signal-cli.1.adoc index 35a578f4..4101986f 100644 --- a/man/signal-cli.1.adoc +++ b/man/signal-cli.1.adoc @@ -140,6 +140,28 @@ RECIPIENT:: *-e*, *--endsession*:: Clear session state and send end session message. +sendReaction +~~~~~~~~~~~~ +Send reaction to a previously received or sent message. + +RECIPIENT:: + Specify the recipients’ phone number. + +*-g* GROUP, *--group* GROUP:: + Specify the recipient group ID in base64 encoding. + +*-e* EMOJI, *--emoji* EMOJI:: + Specify the emoji, should be a single unicode grapheme cluster. + +*-a* NUMBER, *--target-author* NUMBER:: + Specify the number of the author of the message to which to react. + +*-t* TIMESTAMP, *--target-timestamp* TIMESTAMP:: + Specify the timestamp of the message to which to react. + +*-r*, *--remove*:: + Remove a reaction. + receive ~~~~~~~ Query the server for new messages. New messages are printed on standardoutput and diff --git a/src/main/java/org/asamk/signal/commands/Commands.java b/src/main/java/org/asamk/signal/commands/Commands.java index 1ad0987a..24a03e3f 100644 --- a/src/main/java/org/asamk/signal/commands/Commands.java +++ b/src/main/java/org/asamk/signal/commands/Commands.java @@ -22,6 +22,7 @@ public class Commands { addCommand("removeDevice", new RemoveDeviceCommand()); addCommand("removePin", new RemovePinCommand()); addCommand("send", new SendCommand()); + addCommand("sendReaction", new SendReactionCommand()); addCommand("sendContacts", new SendContactsCommand()); addCommand("updateContact", new UpdateContactCommand()); addCommand("setPin", new SetPinCommand()); diff --git a/src/main/java/org/asamk/signal/commands/SendReactionCommand.java b/src/main/java/org/asamk/signal/commands/SendReactionCommand.java new file mode 100644 index 00000000..38560642 --- /dev/null +++ b/src/main/java/org/asamk/signal/commands/SendReactionCommand.java @@ -0,0 +1,95 @@ +package org.asamk.signal.commands; + +import net.sourceforge.argparse4j.impl.Arguments; +import net.sourceforge.argparse4j.inf.Namespace; +import net.sourceforge.argparse4j.inf.Subparser; + +import org.asamk.signal.GroupIdFormatException; +import org.asamk.signal.GroupNotFoundException; +import org.asamk.signal.NotAGroupMemberException; +import org.asamk.signal.manager.Manager; +import org.asamk.signal.util.Util; +import org.whispersystems.signalservice.api.push.SignalServiceAddress; +import org.whispersystems.signalservice.api.push.exceptions.EncapsulatedExceptions; + +import java.io.IOException; + +import static org.asamk.signal.util.ErrorUtils.handleAssertionError; +import static org.asamk.signal.util.ErrorUtils.handleEncapsulatedExceptions; +import static org.asamk.signal.util.ErrorUtils.handleGroupIdFormatException; +import static org.asamk.signal.util.ErrorUtils.handleGroupNotFoundException; +import static org.asamk.signal.util.ErrorUtils.handleIOException; +import static org.asamk.signal.util.ErrorUtils.handleNotAGroupMemberException; + +public class SendReactionCommand implements LocalCommand { + + @Override + public void attachToSubparser(final Subparser subparser) { + subparser.help("Send reaction to a previously received or sent message."); + subparser.addArgument("-g", "--group") + .help("Specify the recipient group ID."); + subparser.addArgument("recipient") + .help("Specify the recipients' phone number.") + .nargs("*"); + subparser.addArgument("-e", "--emoji") + .required(true) + .help("Specify the emoji, should be a single unicode grapheme cluster."); + subparser.addArgument("-a", "--target-author") + .required(true) + .help("Specify the number of the author of the message to which to react."); + subparser.addArgument("-t", "--target-timestamp") + .required(true) + .type(long.class) + .help("Specify the timestamp of the message to which to react."); + subparser.addArgument("-r", "--remove") + .help("Remove a reaction.") + .action(Arguments.storeTrue()); + } + + @Override + public int handleCommand(final Namespace ns, final Manager m) { + if (!m.isRegistered()) { + System.err.println("User is not registered."); + return 1; + } + + if ((ns.getList("recipient") == null || ns.getList("recipient").size() == 0) && ns.getString("group") == null) { + System.err.println("No recipients given"); + System.err.println("Aborting sending."); + return 1; + } + + String emoji = ns.getString("emoji"); + boolean isRemove = ns.getBoolean("remove"); + SignalServiceAddress targetAuthor = new SignalServiceAddress(null, ns.getString("target_author")); + long targetTimestamp = ns.getLong("target_timestamp"); + + try { + if (ns.getString("group") != null) { + byte[] groupId = Util.decodeGroupId(ns.getString("group")); + m.sendGroupMessageReaction(emoji, isRemove, targetAuthor, targetTimestamp, groupId); + } else { + m.sendMessageReaction(emoji, isRemove, targetAuthor, targetTimestamp, ns.getList("recipient")); + } + return 0; + } catch (IOException e) { + handleIOException(e); + return 3; + } catch (EncapsulatedExceptions e) { + handleEncapsulatedExceptions(e); + return 3; + } catch (AssertionError e) { + handleAssertionError(e); + return 1; + } catch (GroupNotFoundException e) { + handleGroupNotFoundException(e); + return 1; + } catch (NotAGroupMemberException e) { + handleNotAGroupMemberException(e); + return 1; + } catch (GroupIdFormatException e) { + handleGroupIdFormatException(e); + return 1; + } + } +} diff --git a/src/main/java/org/asamk/signal/manager/Manager.java b/src/main/java/org/asamk/signal/manager/Manager.java index 0847e484..8d0d46c8 100644 --- a/src/main/java/org/asamk/signal/manager/Manager.java +++ b/src/main/java/org/asamk/signal/manager/Manager.java @@ -496,6 +496,26 @@ public class Manager implements Signal { sendMessageLegacy(messageBuilder, membersSend); } + public void sendGroupMessageReaction(String emoji, boolean remove, SignalServiceAddress targetAuthor, + long targetSentTimestamp, byte[] groupId) + throws IOException, EncapsulatedExceptions, AttachmentInvalidException { + SignalServiceDataMessage.Reaction reaction = new SignalServiceDataMessage.Reaction(emoji, remove, targetAuthor, targetSentTimestamp); + final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder() + .withReaction(reaction) + .withProfileKey(account.getProfileKey()); + if (groupId != null) { + SignalServiceGroup group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.DELIVER) + .withId(groupId) + .build(); + messageBuilder.asGroupMessage(group); + } + final GroupInfo g = getGroupForSending(groupId); + // Don't send group message to ourself + final List membersSend = new ArrayList<>(g.members); + membersSend.remove(this.username); + sendMessageLegacy(messageBuilder, membersSend); + } + public void sendQuitGroupMessage(byte[] groupId) throws GroupNotFoundException, IOException, EncapsulatedExceptions { SignalServiceGroup group = SignalServiceGroup.newBuilder(SignalServiceGroup.Type.QUIT) .withId(groupId) @@ -669,6 +689,16 @@ public class Manager implements Signal { sendMessageLegacy(messageBuilder, recipients); } + public void sendMessageReaction(String emoji, boolean remove, SignalServiceAddress targetAuthor, + long targetSentTimestamp, List recipients) + throws IOException, EncapsulatedExceptions, AttachmentInvalidException { + SignalServiceDataMessage.Reaction reaction = new SignalServiceDataMessage.Reaction(emoji, remove, targetAuthor, targetSentTimestamp); + final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder() + .withReaction(reaction) + .withProfileKey(account.getProfileKey()); + sendMessageLegacy(messageBuilder, recipients); + } + @Override public void sendEndSessionMessage(List recipients) throws IOException, EncapsulatedExceptions { SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder()