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.AttachmentInvalidException;
import org.asamk.signal.manager.Manager;
+import org.asamk.signal.manager.api.AttachmentInvalidException;
+import org.asamk.signal.manager.api.InvalidStickerException;
import org.asamk.signal.manager.api.Message;
import org.asamk.signal.manager.api.RecipientIdentifier;
+import org.asamk.signal.manager.api.UnregisteredRecipientException;
import org.asamk.signal.manager.groups.GroupNotFoundException;
import org.asamk.signal.manager.groups.GroupSendingNotAllowedException;
import org.asamk.signal.manager.groups.NotAGroupMemberException;
-import org.asamk.signal.output.JsonWriter;
import org.asamk.signal.output.OutputWriter;
-import org.asamk.signal.output.PlainTextWriter;
import org.asamk.signal.util.CommandUtil;
-import org.asamk.signal.util.ErrorUtils;
+import org.asamk.signal.util.Hex;
import org.asamk.signal.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
+import static org.asamk.signal.util.SendMessageResultUtils.outputResult;
+
public class SendCommand implements JsonRpcLocalCommand {
private final static Logger logger = LoggerFactory.getLogger(SendCommand.class);
.help("Send the message to self without notification.")
.action(Arguments.storeTrue());
- subparser.addArgument("-m", "--message").help("Specify the message, if missing standard input is used.");
+ var mut = subparser.addMutuallyExclusiveGroup();
+ mut.addArgument("-m", "--message").help("Specify the message to be sent.");
+ mut.addArgument("--message-from-stdin")
+ .action(Arguments.storeTrue())
+ .help("Read the message from standard input.");
subparser.addArgument("-a", "--attachment").nargs("*").help("Add file as attachment");
subparser.addArgument("-e", "--end-session", "--endsession")
.help("Clear session state and send end session message.")
subparser.addArgument("--quote-mention")
.nargs("*")
.help("Quote with mention of another group member (syntax: start:length:recipientNumber)");
+ subparser.addArgument("--sticker").help("Send a sticker (syntax: stickerPackId:stickerId)");
}
@Override
try {
final var results = m.sendEndSessionMessage(singleRecipients);
- outputResult(outputWriter, results.timestamp());
- ErrorUtils.handleSendMessageResults(results.results());
+ outputResult(outputWriter, results);
return;
} catch (IOException e) {
throw new UnexpectedErrorException("Failed to send message: " + e.getMessage() + " (" + e.getClass()
}
}
+ final var stickerString = ns.getString("sticker");
+ final var sticker = stickerString == null ? null : parseSticker(stickerString);
+
var messageText = ns.getString("message");
- if (messageText == null) {
+ final var readMessageFromStdin = ns.getBoolean("message-from-stdin") == Boolean.TRUE;
+ if (readMessageFromStdin || (messageText == null && sticker == null)) {
+ logger.debug("Reading message from stdin...");
try {
messageText = IOUtils.readAll(System.in, Charset.defaultCharset());
} catch (IOException e) {
: parseMentions(m, quoteMentionStrings);
quote = new Message.Quote(quoteTimestamp,
CommandUtil.getSingleRecipientIdentifier(quoteAuthor, m.getSelfNumber()),
- quoteMessage,
+ quoteMessage == null ? "" : quoteMessage,
quoteMentions);
} else {
quote = null;
}
try {
- var results = m.sendMessage(new Message(messageText, attachments, mentions, Optional.ofNullable(quote)),
- recipientIdentifiers);
- outputResult(outputWriter, results.timestamp());
- ErrorUtils.handleSendMessageResults(results.results());
+ var results = m.sendMessage(new Message(messageText == null ? "" : messageText,
+ attachments,
+ mentions,
+ Optional.ofNullable(quote),
+ Optional.ofNullable(sticker)), recipientIdentifiers);
+ outputResult(outputWriter, results);
} catch (AttachmentInvalidException | IOException e) {
throw new UnexpectedErrorException("Failed to send message: " + e.getMessage() + " (" + e.getClass()
.getSimpleName() + ")", e);
} catch (GroupNotFoundException | NotAGroupMemberException | GroupSendingNotAllowedException e) {
throw new UserErrorException(e.getMessage());
+ } catch (UnregisteredRecipientException e) {
+ throw new UserErrorException("The user " + e.getSender().getIdentifier() + " is not registered.");
+ } catch (InvalidStickerException e) {
+ throw new UserErrorException("Failed to send sticker: " + e.getMessage(), e);
}
}
return mentions;
}
- private void outputResult(final OutputWriter outputWriter, final long timestamp) {
- if (outputWriter instanceof PlainTextWriter writer) {
- writer.println("{}", timestamp);
- } else {
- final var writer = (JsonWriter) outputWriter;
- writer.write(Map.of("timestamp", timestamp));
+ private Message.Sticker parseSticker(final String stickerString) throws UserErrorException {
+ final Pattern stickerPattern = Pattern.compile("([0-9a-f]+):([0-9]+)");
+ final var matcher = stickerPattern.matcher(stickerString);
+ if (!matcher.matches() || matcher.group(1).length() % 2 != 0) {
+ throw new UserErrorException("Invalid sticker syntax ("
+ + stickerString
+ + ") expected 'stickerPackId:stickerId'");
}
+ return new Message.Sticker(Hex.toByteArray(matcher.group(1)), Integer.parseInt(matcher.group(2)));
}
}