From: AsamK Date: Sun, 21 Nov 2021 18:18:17 +0000 (+0100) Subject: Implement sending message quotes X-Git-Tag: v0.10.0~38 X-Git-Url: https://git.nmode.ca/signal-cli/commitdiff_plain/d13d150fe1c6b21dd53617cf7996d2876bc5db58?ds=sidebyside Implement sending message quotes Fixes #213 --- diff --git a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java index 93296a1c..84a866d0 100644 --- a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java @@ -708,15 +708,27 @@ public class ManagerImpl implements Manager { messageBuilder.withAttachments(attachmentHelper.uploadAttachments(attachments)); } if (message.mentions().size() > 0) { - final var mentions = new ArrayList(); - for (final var m : message.mentions()) { - final var recipientId = resolveRecipient(m.recipient()); - mentions.add(new SignalServiceDataMessage.Mention(resolveSignalServiceAddress(recipientId).getAci(), - m.start(), - m.length())); - } - messageBuilder.withMentions(mentions); + messageBuilder.withMentions(resolveMentions(message.mentions())); + } + if (message.quote().isPresent()) { + final var quote = message.quote().get(); + messageBuilder.withQuote(new SignalServiceDataMessage.Quote(quote.timestamp(), + resolveSignalServiceAddress(resolveRecipient(quote.author())), + quote.message(), + List.of(), + resolveMentions(quote.mentions()))); + } + } + + private ArrayList resolveMentions(final List mentionList) throws IOException { + final var mentions = new ArrayList(); + for (final var m : mentionList) { + final var recipientId = resolveRecipient(m.recipient()); + mentions.add(new SignalServiceDataMessage.Mention(resolveSignalServiceAddress(recipientId).getAci(), + m.start(), + m.length())); } + return mentions; } @Override diff --git a/lib/src/main/java/org/asamk/signal/manager/api/Message.java b/lib/src/main/java/org/asamk/signal/manager/api/Message.java index 5d0c78f8..13cb00cf 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/Message.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/Message.java @@ -1,8 +1,11 @@ package org.asamk.signal.manager.api; import java.util.List; +import java.util.Optional; -public record Message(String messageText, List attachments, List mentions) { +public record Message(String messageText, List attachments, List mentions, Optional quote) { public record Mention(RecipientIdentifier.Single recipient, int start, int length) {} + + public record Quote(long timestamp, RecipientIdentifier.Single author, String message, List mentions) {} } diff --git a/man/signal-cli.1.adoc b/man/signal-cli.1.adoc index c5b190eb..ff49843c 100644 --- a/man/signal-cli.1.adoc +++ b/man/signal-cli.1.adoc @@ -210,6 +210,19 @@ Mention another group member (syntax: start:length:recipientNumber) In the apps the mention replaces part of the message text, which is specified by the start and length values. e.g.: `-m "Hi X!" --mention "3:1:+123456789"` +*--quote-timestamp*:: +Specify the timestamp of a previous message with the recipient or group to add a +quote to the new message. + +*--quote-author*:: +Specify the number of the author of the original message. + +*--quote-message*:: +Specify the message of the original message. + +*--quote-mention*:: +Specify the mentions of the original message (same format as `--mention`). + === sendReaction Send reaction to a previously received or sent message. diff --git a/src/main/java/org/asamk/signal/commands/SendCommand.java b/src/main/java/org/asamk/signal/commands/SendCommand.java index 9af95e6b..f73d3e70 100644 --- a/src/main/java/org/asamk/signal/commands/SendCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendCommand.java @@ -28,6 +28,7 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -57,6 +58,14 @@ public class SendCommand implements JsonRpcLocalCommand { subparser.addArgument("--mention") .nargs("*") .help("Mention another group member (syntax: start:length:recipientNumber)"); + subparser.addArgument("--quote-timestamp") + .type(long.class) + .help("Specify the timestamp of a previous message with the recipient or group to add a quote to the new message."); + subparser.addArgument("--quote-author").help("Specify the number of the author of the original message."); + subparser.addArgument("--quote-message").help("Specify the message of the original message."); + subparser.addArgument("--quote-mention") + .nargs("*") + .help("Quote with mention of another group member (syntax: start:length:recipientNumber)"); } @Override @@ -108,26 +117,28 @@ public class SendCommand implements JsonRpcLocalCommand { } List mentionStrings = ns.getList("mention"); - List mentions; - if (mentionStrings == null) { - mentions = List.of(); + final var mentions = mentionStrings == null ? List.of() : parseMentions(m, mentionStrings); + + final Message.Quote quote; + final var quoteTimestamp = ns.getLong("quote-timestamp"); + if (quoteTimestamp != null) { + final var quoteAuthor = ns.getString("quote-author"); + final var quoteMessage = ns.getString("quote-message"); + List quoteMentionStrings = ns.getList("quote-mention"); + final var quoteMentions = quoteMentionStrings == null + ? List.of() + : parseMentions(m, quoteMentionStrings); + quote = new Message.Quote(quoteTimestamp, + CommandUtil.getSingleRecipientIdentifier(quoteAuthor, m.getSelfNumber()), + quoteMessage, + quoteMentions); } else { - final Pattern mentionPattern = Pattern.compile("([0-9]+):([0-9]+):(.+)"); - mentions = new ArrayList<>(); - for (final var mention : mentionStrings) { - final var matcher = mentionPattern.matcher(mention); - if (!matcher.matches()) { - throw new UserErrorException("Invalid mention syntax (" - + mention - + ") expected 'start:end:recipientNumber'"); - } - mentions.add(new Message.Mention(CommandUtil.getSingleRecipientIdentifier(matcher.group(3), - m.getSelfNumber()), Integer.parseInt(matcher.group(1)), Integer.parseInt(matcher.group(2)))); - } + quote = null; } try { - var results = m.sendMessage(new Message(messageText, attachments, mentions), recipientIdentifiers); + var results = m.sendMessage(new Message(messageText, attachments, mentions, Optional.ofNullable(quote)), + recipientIdentifiers); outputResult(outputWriter, results.timestamp()); ErrorUtils.handleSendMessageResults(results.results()); } catch (AttachmentInvalidException | IOException e) { @@ -138,6 +149,25 @@ public class SendCommand implements JsonRpcLocalCommand { } } + private List parseMentions( + final Manager m, final List mentionStrings + ) throws UserErrorException { + List mentions; + final Pattern mentionPattern = Pattern.compile("([0-9]+):([0-9]+):(.+)"); + mentions = new ArrayList<>(); + for (final var mention : mentionStrings) { + final var matcher = mentionPattern.matcher(mention); + if (!matcher.matches()) { + throw new UserErrorException("Invalid mention syntax (" + + mention + + ") expected 'start:end:recipientNumber'"); + } + mentions.add(new Message.Mention(CommandUtil.getSingleRecipientIdentifier(matcher.group(3), + m.getSelfNumber()), Integer.parseInt(matcher.group(1)), Integer.parseInt(matcher.group(2)))); + } + return mentions; + } + private void outputResult(final OutputWriter outputWriter, final long timestamp) { if (outputWriter instanceof PlainTextWriter writer) { writer.println("{}", timestamp); diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java index 7eb65af3..6395eb14 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java @@ -199,7 +199,7 @@ public class DbusSignalImpl implements Signal { @Override public long sendMessage(final String message, final List attachments, final List recipients) { try { - final var results = m.sendMessage(new Message(message, attachments, List.of()), + final var results = m.sendMessage(new Message(message, attachments, List.of(), Optional.empty()), getSingleRecipientIdentifiers(recipients, m.getSelfNumber()).stream() .map(RecipientIdentifier.class::cast) .collect(Collectors.toSet())); @@ -364,7 +364,7 @@ public class DbusSignalImpl implements Signal { final String message, final List attachments ) throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity { try { - final var results = m.sendMessage(new Message(message, attachments, List.of()), + final var results = m.sendMessage(new Message(message, attachments, List.of(), Optional.empty()), Set.of(RecipientIdentifier.NoteToSelf.INSTANCE)); checkSendMessageResults(results.timestamp(), results.results()); return results.timestamp(); @@ -390,7 +390,7 @@ public class DbusSignalImpl implements Signal { @Override public long sendGroupMessage(final String message, final List attachments, final byte[] groupId) { try { - var results = m.sendMessage(new Message(message, attachments, List.of()), + var results = m.sendMessage(new Message(message, attachments, List.of(), Optional.empty()), Set.of(new RecipientIdentifier.Group(getGroupId(groupId)))); checkSendMessageResults(results.timestamp(), results.results()); return results.timestamp(); diff --git a/src/main/java/org/asamk/signal/util/CommandUtil.java b/src/main/java/org/asamk/signal/util/CommandUtil.java index b9574d0e..b86a9989 100644 --- a/src/main/java/org/asamk/signal/util/CommandUtil.java +++ b/src/main/java/org/asamk/signal/util/CommandUtil.java @@ -93,7 +93,7 @@ public class CommandUtil { try { return RecipientIdentifier.Single.fromString(recipientString, localNumber); } catch (InvalidNumberException e) { - throw new UserErrorException("Invalid phone number '" + recipientString + "': " + e.getMessage()); + throw new UserErrorException("Invalid phone number '" + recipientString + "': " + e.getMessage(), e); } } }