Add support for sending stickers

This commit is contained in:
AsamK 2022-01-03 13:24:13 +01:00
parent 5d83e149b3
commit 404063a080
11 changed files with 141 additions and 35 deletions

View file

@ -730,6 +730,7 @@
"queryAllDeclaredMethods":true, "queryAllDeclaredMethods":true,
"queryAllDeclaredConstructors":true, "queryAllDeclaredConstructors":true,
"methods":[ "methods":[
{"name":"<init>","parameterTypes":["java.lang.String","java.lang.String","org.asamk.signal.manager.JsonStickerPack$JsonSticker","java.util.List"] },
{"name":"author","parameterTypes":[] }, {"name":"author","parameterTypes":[] },
{"name":"cover","parameterTypes":[] }, {"name":"cover","parameterTypes":[] },
{"name":"stickers","parameterTypes":[] }, {"name":"stickers","parameterTypes":[] },
@ -742,6 +743,7 @@
"queryAllDeclaredMethods":true, "queryAllDeclaredMethods":true,
"queryAllDeclaredConstructors":true, "queryAllDeclaredConstructors":true,
"methods":[ "methods":[
{"name":"<init>","parameterTypes":["java.lang.String","java.lang.String","java.lang.String"] },
{"name":"contentType","parameterTypes":[] }, {"name":"contentType","parameterTypes":[] },
{"name":"emoji","parameterTypes":[] }, {"name":"emoji","parameterTypes":[] },
{"name":"file","parameterTypes":[] } {"name":"file","parameterTypes":[] }

View file

@ -6,6 +6,7 @@ import org.asamk.signal.manager.api.Group;
import org.asamk.signal.manager.api.Identity; import org.asamk.signal.manager.api.Identity;
import org.asamk.signal.manager.api.InactiveGroupLinkException; import org.asamk.signal.manager.api.InactiveGroupLinkException;
import org.asamk.signal.manager.api.InvalidDeviceLinkException; import org.asamk.signal.manager.api.InvalidDeviceLinkException;
import org.asamk.signal.manager.api.InvalidStickerException;
import org.asamk.signal.manager.api.Message; import org.asamk.signal.manager.api.Message;
import org.asamk.signal.manager.api.MessageEnvelope; import org.asamk.signal.manager.api.MessageEnvelope;
import org.asamk.signal.manager.api.Pair; import org.asamk.signal.manager.api.Pair;
@ -173,7 +174,7 @@ public interface Manager extends Closeable {
SendMessageResults sendMessage( SendMessageResults sendMessage(
Message message, Set<RecipientIdentifier> recipients Message message, Set<RecipientIdentifier> recipients
) throws IOException, AttachmentInvalidException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException, UnregisteredRecipientException; ) throws IOException, AttachmentInvalidException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException, UnregisteredRecipientException, InvalidStickerException;
SendMessageResults sendRemoteDeleteMessage( SendMessageResults sendRemoteDeleteMessage(
long targetSentTimestamp, Set<RecipientIdentifier> recipients long targetSentTimestamp, Set<RecipientIdentifier> recipients

View file

@ -22,6 +22,7 @@ import org.asamk.signal.manager.api.Group;
import org.asamk.signal.manager.api.Identity; import org.asamk.signal.manager.api.Identity;
import org.asamk.signal.manager.api.InactiveGroupLinkException; import org.asamk.signal.manager.api.InactiveGroupLinkException;
import org.asamk.signal.manager.api.InvalidDeviceLinkException; import org.asamk.signal.manager.api.InvalidDeviceLinkException;
import org.asamk.signal.manager.api.InvalidStickerException;
import org.asamk.signal.manager.api.Message; import org.asamk.signal.manager.api.Message;
import org.asamk.signal.manager.api.Pair; import org.asamk.signal.manager.api.Pair;
import org.asamk.signal.manager.api.RecipientIdentifier; import org.asamk.signal.manager.api.RecipientIdentifier;
@ -48,6 +49,7 @@ import org.asamk.signal.manager.storage.recipients.RecipientAddress;
import org.asamk.signal.manager.storage.recipients.RecipientId; import org.asamk.signal.manager.storage.recipients.RecipientId;
import org.asamk.signal.manager.storage.stickers.Sticker; import org.asamk.signal.manager.storage.stickers.Sticker;
import org.asamk.signal.manager.storage.stickers.StickerPackId; import org.asamk.signal.manager.storage.stickers.StickerPackId;
import org.asamk.signal.manager.util.AttachmentUtils;
import org.asamk.signal.manager.util.KeyUtils; import org.asamk.signal.manager.util.KeyUtils;
import org.asamk.signal.manager.util.StickerUtils; import org.asamk.signal.manager.util.StickerUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -484,7 +486,7 @@ public class ManagerImpl implements Manager {
@Override @Override
public SendMessageResults sendMessage( public SendMessageResults sendMessage(
Message message, Set<RecipientIdentifier> recipients Message message, Set<RecipientIdentifier> recipients
) throws IOException, AttachmentInvalidException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException, UnregisteredRecipientException { ) throws IOException, AttachmentInvalidException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException, UnregisteredRecipientException, InvalidStickerException {
final var messageBuilder = SignalServiceDataMessage.newBuilder(); final var messageBuilder = SignalServiceDataMessage.newBuilder();
applyMessage(messageBuilder, message); applyMessage(messageBuilder, message);
return sendMessage(messageBuilder, recipients); return sendMessage(messageBuilder, recipients);
@ -492,7 +494,7 @@ public class ManagerImpl implements Manager {
private void applyMessage( private void applyMessage(
final SignalServiceDataMessage.Builder messageBuilder, final Message message final SignalServiceDataMessage.Builder messageBuilder, final Message message
) throws AttachmentInvalidException, IOException, UnregisteredRecipientException { ) throws AttachmentInvalidException, IOException, UnregisteredRecipientException, InvalidStickerException {
messageBuilder.withBody(message.messageText()); messageBuilder.withBody(message.messageText());
final var attachments = message.attachments(); final var attachments = message.attachments();
if (attachments != null) { if (attachments != null) {
@ -510,6 +512,30 @@ public class ManagerImpl implements Manager {
List.of(), List.of(),
resolveMentions(quote.mentions()))); resolveMentions(quote.mentions())));
} }
if (message.sticker().isPresent()) {
final var sticker = message.sticker().get();
final var packId = StickerPackId.deserialize(sticker.packId());
final var stickerId = sticker.stickerId();
final var stickerPack = context.getAccount().getStickerStore().getStickerPack(packId);
if (stickerPack == null || !context.getStickerPackStore().existsStickerPack(packId)) {
throw new InvalidStickerException("Sticker pack not found");
}
final var manifest = context.getStickerPackStore().retrieveManifest(packId);
if (manifest.stickers().size() <= stickerId) {
throw new InvalidStickerException("Sticker id not part of this pack");
}
final var manifestSticker = manifest.stickers().get(stickerId);
final var streamDetails = context.getStickerPackStore().retrieveSticker(packId, stickerId);
if (streamDetails == null) {
throw new InvalidStickerException("Missing local sticker file");
}
messageBuilder.withSticker(new SignalServiceDataMessage.Sticker(packId.serialize(),
stickerPack.getPackKey(),
stickerId,
manifestSticker.emoji(),
AttachmentUtils.createAttachment(streamDetails, Optional.absent())));
}
} }
private ArrayList<SignalServiceDataMessage.Mention> resolveMentions(final List<Message.Mention> mentionList) throws IOException, UnregisteredRecipientException { private ArrayList<SignalServiceDataMessage.Mention> resolveMentions(final List<Message.Mention> mentionList) throws IOException, UnregisteredRecipientException {

View file

@ -4,10 +4,13 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import org.asamk.signal.manager.storage.stickers.StickerPackId; import org.asamk.signal.manager.storage.stickers.StickerPackId;
import org.asamk.signal.manager.util.IOUtils; import org.asamk.signal.manager.util.IOUtils;
import org.asamk.signal.manager.util.Utils;
import org.whispersystems.signalservice.api.util.StreamDetails;
import org.whispersystems.signalservice.internal.util.Hex; import org.whispersystems.signalservice.internal.util.Hex;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
@ -26,8 +29,22 @@ public class StickerPackStore {
return getStickerPackManifestFile(stickerPackId).exists(); return getStickerPackManifestFile(stickerPackId).exists();
} }
public JsonStickerPack retrieveManifest(StickerPackId stickerPackId) throws IOException {
try (final var inputStream = new FileInputStream(getStickerPackManifestFile(stickerPackId))) {
return new ObjectMapper().readValue(inputStream, JsonStickerPack.class);
}
}
public StreamDetails retrieveSticker(final StickerPackId stickerPackId, final int stickerId) throws IOException {
final var stickerFile = getStickerPackStickerFile(stickerPackId, stickerId);
if (!stickerFile.exists()) {
return null;
}
return Utils.createStreamDetailsFromFile(stickerFile);
}
public void storeManifest(StickerPackId stickerPackId, JsonStickerPack manifest) throws IOException { public void storeManifest(StickerPackId stickerPackId, JsonStickerPack manifest) throws IOException {
try (OutputStream output = new FileOutputStream(getStickerPackManifestFile(stickerPackId))) { try (final var output = new FileOutputStream(getStickerPackManifestFile(stickerPackId))) {
try (var writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8))) { try (var writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8))) {
new ObjectMapper().writeValue(writer, manifest); new ObjectMapper().writeValue(writer, manifest);
} }
@ -36,7 +53,7 @@ public class StickerPackStore {
public void storeSticker(StickerPackId stickerPackId, int stickerId, StickerStorer storer) throws IOException { public void storeSticker(StickerPackId stickerPackId, int stickerId, StickerStorer storer) throws IOException {
createStickerPackDir(stickerPackId); createStickerPackDir(stickerPackId);
try (OutputStream output = new FileOutputStream(getStickerPackStickerFile(stickerPackId, stickerId))) { try (final var output = new FileOutputStream(getStickerPackStickerFile(stickerPackId, stickerId))) {
storer.store(output); storer.store(output);
} }
} }

View file

@ -0,0 +1,12 @@
package org.asamk.signal.manager.api;
public class InvalidStickerException extends Exception {
public InvalidStickerException(final String message) {
super(message);
}
public InvalidStickerException(final String message, final Throwable cause) {
super(message, cause);
}
}

View file

@ -3,9 +3,17 @@ package org.asamk.signal.manager.api;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
public record Message(String messageText, List<String> attachments, List<Mention> mentions, Optional<Quote> quote) { public record Message(
String messageText,
List<String> attachments,
List<Mention> mentions,
Optional<Quote> quote,
Optional<Sticker> sticker
) {
public record Mention(RecipientIdentifier.Single recipient, int start, int length) {} public record Mention(RecipientIdentifier.Single recipient, int start, int length) {}
public record Quote(long timestamp, RecipientIdentifier.Single author, String message, List<Mention> mentions) {} public record Quote(long timestamp, RecipientIdentifier.Single author, String message, List<Mention> mentions) {}
public record Sticker(byte[] packId, int stickerId) {}
} }

View file

@ -327,7 +327,7 @@ public final class IncomingMessageHandler {
final var installed = !m.getType().isPresent() final var installed = !m.getType().isPresent()
|| m.getType().get() == StickerPackOperationMessage.Type.INSTALL; || m.getType().get() == StickerPackOperationMessage.Type.INSTALL;
var sticker = account.getStickerStore().getSticker(stickerPackId); var sticker = account.getStickerStore().getStickerPack(stickerPackId);
if (m.getPackKey().isPresent()) { if (m.getPackKey().isPresent()) {
if (sticker == null) { if (sticker == null) {
sticker = new Sticker(stickerPackId, m.getPackKey().get()); sticker = new Sticker(stickerPackId, m.getPackKey().get());
@ -598,7 +598,7 @@ public final class IncomingMessageHandler {
if (message.getSticker().isPresent()) { if (message.getSticker().isPresent()) {
final var messageSticker = message.getSticker().get(); final var messageSticker = message.getSticker().get();
final var stickerPackId = StickerPackId.deserialize(messageSticker.getPackId()); final var stickerPackId = StickerPackId.deserialize(messageSticker.getPackId());
var sticker = account.getStickerStore().getSticker(stickerPackId); var sticker = account.getStickerStore().getStickerPack(stickerPackId);
if (sticker == null) { if (sticker == null) {
sticker = new Sticker(stickerPackId, messageSticker.getPackKey()); sticker = new Sticker(stickerPackId, messageSticker.getPackKey());
account.getStickerStore().updateSticker(sticker); account.getStickerStore().updateSticker(sticker);

View file

@ -41,7 +41,7 @@ public class StickerStore {
return new StickerStore(stickers, saver); return new StickerStore(stickers, saver);
} }
public Sticker getSticker(StickerPackId packId) { public Sticker getStickerPack(StickerPackId packId) {
synchronized (stickers) { synchronized (stickers) {
return stickers.get(packId); return stickers.get(packId);
} }

View file

@ -73,11 +73,9 @@ Choose when to trust new identities:
Register a phone number with SMS or voice verification. Register a phone number with SMS or voice verification.
Use the verify command to complete the verification. Use the verify command to complete the verification.
If the account is just deactivated, the register command will just reactivate If the account is just deactivated, the register command will just reactivate account, without requiring an SMS verification.
account, without requiring an SMS verification. By default the unregister command By default the unregister command just deactivates the account, in which case it can be reactivated without sms verification if the local data is still available.
just deactivates the account, in which case it can be reactivated without sms If the account was deleted (with --delete-account) it cannot be reactivated.
verification if the local data is still available. If the account was deleted
(with --delete-account) it cannot be reactivated.
*-v*, *--voice*:: *-v*, *--voice*::
The verification should be done over voice, not SMS. The verification should be done over voice, not SMS.
@ -197,6 +195,9 @@ Send a message to another user or group.
RECIPIENT:: RECIPIENT::
Specify the recipients phone number. Specify the recipients phone number.
*--note-to-self*::
Send the message to self without notification.
*-g* GROUP, *--group-id* GROUP:: *-g* GROUP, *--group-id* GROUP::
Specify the recipient group ID in base64 encoding. Specify the recipient group ID in base64 encoding.
@ -206,11 +207,10 @@ Specify the message, if missing, standard input is used.
*-a* [ATTACHMENT [ATTACHMENT ...]], *--attachment* [ATTACHMENT [ATTACHMENT ...]]:: *-a* [ATTACHMENT [ATTACHMENT ...]], *--attachment* [ATTACHMENT [ATTACHMENT ...]]::
Add one or more files as attachment. Add one or more files as attachment.
*--note-to-self*:: *--sticker* STICKER::
Send the message to self without notification. Send a sticker of a locally known sticker pack (syntax: stickerPackId:stickerId).
Shouldn't be used together with `-m` as the official clients don't support this.
*-e*, *--end-session*:: e.g.: `--sticker 00abac3bc18d7f599bff2325dc306d43:2`
Clear session state and send end session message.
*--mention*:: *--mention*::
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. 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.
@ -228,6 +228,9 @@ Specify the message of the original message.
*--quote-mention*:: *--quote-mention*::
Specify the mentions of the original message (same format as `--mention`). Specify the mentions of the original message (same format as `--mention`).
*-e*, *--end-session*::
Clear session state and send end session message.
=== sendReaction === sendReaction
Send reaction to a previously received or sent message. Send reaction to a previously received or sent message.

View file

@ -9,6 +9,7 @@ import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.commands.exceptions.UserErrorException;
import org.asamk.signal.manager.AttachmentInvalidException; import org.asamk.signal.manager.AttachmentInvalidException;
import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.Manager;
import org.asamk.signal.manager.api.InvalidStickerException;
import org.asamk.signal.manager.api.Message; import org.asamk.signal.manager.api.Message;
import org.asamk.signal.manager.api.RecipientIdentifier; import org.asamk.signal.manager.api.RecipientIdentifier;
import org.asamk.signal.manager.api.UnregisteredRecipientException; import org.asamk.signal.manager.api.UnregisteredRecipientException;
@ -17,6 +18,7 @@ import org.asamk.signal.manager.groups.GroupSendingNotAllowedException;
import org.asamk.signal.manager.groups.NotAGroupMemberException; import org.asamk.signal.manager.groups.NotAGroupMemberException;
import org.asamk.signal.output.OutputWriter; import org.asamk.signal.output.OutputWriter;
import org.asamk.signal.util.CommandUtil; import org.asamk.signal.util.CommandUtil;
import org.asamk.signal.util.Hex;
import org.asamk.signal.util.IOUtils; import org.asamk.signal.util.IOUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -65,6 +67,7 @@ public class SendCommand implements JsonRpcLocalCommand {
subparser.addArgument("--quote-mention") subparser.addArgument("--quote-mention")
.nargs("*") .nargs("*")
.help("Quote with mention of another group member (syntax: start:length:recipientNumber)"); .help("Quote with mention of another group member (syntax: start:length:recipientNumber)");
subparser.addArgument("--sticker").help("Send a sticker (syntax: stickerPackId:stickerId)");
} }
@Override @Override
@ -100,8 +103,14 @@ public class SendCommand implements JsonRpcLocalCommand {
} }
} }
final var stickerString = ns.getString("sticker");
final var sticker = stickerString == null ? null : parseSticker(stickerString);
var messageText = ns.getString("message"); var messageText = ns.getString("message");
if (messageText == null) { if (messageText == null) {
if (sticker != null) {
messageText = "";
} else {
logger.debug("Reading message from stdin..."); logger.debug("Reading message from stdin...");
try { try {
messageText = IOUtils.readAll(System.in, Charset.defaultCharset()); messageText = IOUtils.readAll(System.in, Charset.defaultCharset());
@ -109,6 +118,7 @@ public class SendCommand implements JsonRpcLocalCommand {
throw new UserErrorException("Failed to read message from stdin: " + e.getMessage()); throw new UserErrorException("Failed to read message from stdin: " + e.getMessage());
} }
} }
}
List<String> attachments = ns.getList("attachment"); List<String> attachments = ns.getList("attachment");
if (attachments == null) { if (attachments == null) {
@ -129,15 +139,18 @@ public class SendCommand implements JsonRpcLocalCommand {
: parseMentions(m, quoteMentionStrings); : parseMentions(m, quoteMentionStrings);
quote = new Message.Quote(quoteTimestamp, quote = new Message.Quote(quoteTimestamp,
CommandUtil.getSingleRecipientIdentifier(quoteAuthor, m.getSelfNumber()), CommandUtil.getSingleRecipientIdentifier(quoteAuthor, m.getSelfNumber()),
quoteMessage, quoteMessage == null ? "" : quoteMessage,
quoteMentions); quoteMentions);
} else { } else {
quote = null; quote = null;
} }
try { try {
var results = m.sendMessage(new Message(messageText, attachments, mentions, Optional.ofNullable(quote)), var results = m.sendMessage(new Message(messageText,
recipientIdentifiers); attachments,
mentions,
Optional.ofNullable(quote),
Optional.ofNullable(sticker)), recipientIdentifiers);
outputResult(outputWriter, results); outputResult(outputWriter, results);
} catch (AttachmentInvalidException | IOException e) { } catch (AttachmentInvalidException | IOException e) {
throw new UnexpectedErrorException("Failed to send message: " + e.getMessage() + " (" + e.getClass() throw new UnexpectedErrorException("Failed to send message: " + e.getMessage() + " (" + e.getClass()
@ -146,6 +159,8 @@ public class SendCommand implements JsonRpcLocalCommand {
throw new UserErrorException(e.getMessage()); throw new UserErrorException(e.getMessage());
} catch (UnregisteredRecipientException e) { } catch (UnregisteredRecipientException e) {
throw new UserErrorException("The user " + e.getSender().getIdentifier() + " is not registered."); throw new UserErrorException("The user " + e.getSender().getIdentifier() + " is not registered.");
} catch (InvalidStickerException e) {
throw new UserErrorException("Failed to send sticker: " + e.getMessage(), e);
} }
} }
@ -167,4 +182,15 @@ public class SendCommand implements JsonRpcLocalCommand {
} }
return mentions; return mentions;
} }
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)));
}
} }

View file

@ -10,6 +10,7 @@ import org.asamk.signal.manager.api.Identity;
import org.asamk.signal.manager.api.InactiveGroupLinkException; import org.asamk.signal.manager.api.InactiveGroupLinkException;
import org.asamk.signal.manager.api.InvalidDeviceLinkException; import org.asamk.signal.manager.api.InvalidDeviceLinkException;
import org.asamk.signal.manager.api.InvalidNumberException; import org.asamk.signal.manager.api.InvalidNumberException;
import org.asamk.signal.manager.api.InvalidStickerException;
import org.asamk.signal.manager.api.Message; import org.asamk.signal.manager.api.Message;
import org.asamk.signal.manager.api.Pair; import org.asamk.signal.manager.api.Pair;
import org.asamk.signal.manager.api.RecipientIdentifier; import org.asamk.signal.manager.api.RecipientIdentifier;
@ -199,7 +200,11 @@ public class DbusSignalImpl implements Signal {
@Override @Override
public long sendMessage(final String message, final List<String> attachments, final List<String> recipients) { public long sendMessage(final String message, final List<String> attachments, final List<String> recipients) {
try { try {
final var results = m.sendMessage(new Message(message, attachments, List.of(), Optional.empty()), final var results = m.sendMessage(new Message(message,
attachments,
List.of(),
Optional.empty(),
Optional.empty()),
getSingleRecipientIdentifiers(recipients, m.getSelfNumber()).stream() getSingleRecipientIdentifiers(recipients, m.getSelfNumber()).stream()
.map(RecipientIdentifier.class::cast) .map(RecipientIdentifier.class::cast)
.collect(Collectors.toSet())); .collect(Collectors.toSet()));
@ -208,7 +213,7 @@ public class DbusSignalImpl implements Signal {
return results.timestamp(); return results.timestamp();
} catch (AttachmentInvalidException e) { } catch (AttachmentInvalidException e) {
throw new Error.AttachmentInvalid(e.getMessage()); throw new Error.AttachmentInvalid(e.getMessage());
} catch (IOException e) { } catch (IOException | InvalidStickerException e) {
throw new Error.Failure(e); throw new Error.Failure(e);
} catch (GroupNotFoundException | NotAGroupMemberException | GroupSendingNotAllowedException e) { } catch (GroupNotFoundException | NotAGroupMemberException | GroupSendingNotAllowedException e) {
throw new Error.GroupNotFound(e.getMessage()); throw new Error.GroupNotFound(e.getMessage());
@ -346,13 +351,16 @@ public class DbusSignalImpl implements Signal {
final String message, final List<String> attachments final String message, final List<String> attachments
) throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity { ) throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity {
try { try {
final var results = m.sendMessage(new Message(message, attachments, List.of(), Optional.empty()), final var results = m.sendMessage(new Message(message,
Set.of(RecipientIdentifier.NoteToSelf.INSTANCE)); attachments,
List.of(),
Optional.empty(),
Optional.empty()), Set.of(RecipientIdentifier.NoteToSelf.INSTANCE));
checkSendMessageResults(results); checkSendMessageResults(results);
return results.timestamp(); return results.timestamp();
} catch (AttachmentInvalidException e) { } catch (AttachmentInvalidException e) {
throw new Error.AttachmentInvalid(e.getMessage()); throw new Error.AttachmentInvalid(e.getMessage());
} catch (IOException e) { } catch (IOException | InvalidStickerException e) {
throw new Error.Failure(e.getMessage()); throw new Error.Failure(e.getMessage());
} catch (GroupNotFoundException | NotAGroupMemberException | GroupSendingNotAllowedException e) { } catch (GroupNotFoundException | NotAGroupMemberException | GroupSendingNotAllowedException e) {
throw new Error.GroupNotFound(e.getMessage()); throw new Error.GroupNotFound(e.getMessage());
@ -384,11 +392,14 @@ public class DbusSignalImpl implements Signal {
@Override @Override
public long sendGroupMessage(final String message, final List<String> attachments, final byte[] groupId) { public long sendGroupMessage(final String message, final List<String> attachments, final byte[] groupId) {
try { try {
var results = m.sendMessage(new Message(message, attachments, List.of(), Optional.empty()), var results = m.sendMessage(new Message(message,
Set.of(getGroupRecipientIdentifier(groupId))); attachments,
List.of(),
Optional.empty(),
Optional.empty()), Set.of(getGroupRecipientIdentifier(groupId)));
checkSendMessageResults(results); checkSendMessageResults(results);
return results.timestamp(); return results.timestamp();
} catch (IOException e) { } catch (IOException | InvalidStickerException e) {
throw new Error.Failure(e.getMessage()); throw new Error.Failure(e.getMessage());
} catch (GroupNotFoundException | NotAGroupMemberException | GroupSendingNotAllowedException e) { } catch (GroupNotFoundException | NotAGroupMemberException | GroupSendingNotAllowedException e) {
throw new Error.GroupNotFound(e.getMessage()); throw new Error.GroupNotFound(e.getMessage());