Send self messages as normal messages, new flag --note-to-self for sync message

Fixes #373
This commit is contained in:
AsamK 2021-01-16 11:56:41 +01:00
parent b31e97dd2d
commit e1134d832a
7 changed files with 98 additions and 18 deletions

View file

@ -3,6 +3,11 @@
## [Unreleased] ## [Unreleased]
### Added ### Added
- `--verbose` flag to increase log level - `--verbose` flag to increase log level
- `--note-to-self` flag for `send` command to send a note to linked devices
### Changed
- Messages sent to self number will be sent as normal Signal messages again, to
send a sync message, use the new `--note-to-self` flag
### Fixed ### Fixed
- Disable registration lock before removing the PIN - Disable registration lock before removing the PIN

View file

@ -17,7 +17,7 @@ repositories {
} }
dependencies { dependencies {
implementation 'com.github.turasa:signal-service-java:2.15.3_unofficial_15' implementation 'com.github.turasa:signal-service-java:2.15.3_unofficial_16'
implementation 'org.bouncycastle:bcprov-jdk15on:1.68' implementation 'org.bouncycastle:bcprov-jdk15on:1.68'
implementation 'net.sourceforge.argparse4j:argparse4j:0.8.1' implementation 'net.sourceforge.argparse4j:argparse4j:0.8.1'
implementation 'com.github.hypfvieh:dbus-java:3.2.4' implementation 'com.github.hypfvieh:dbus-java:3.2.4'

View file

@ -165,6 +165,9 @@ 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*::
Send the message to self without notification.
*-e*, *--endsession*:: *-e*, *--endsession*::
Clear session state and send end session message. Clear session state and send end session message.

View file

@ -21,6 +21,10 @@ 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.UnregisteredUser, Error.UntrustedIdentity; ) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UnregisteredUser, Error.UntrustedIdentity;
long sendNoteToSelfMessage(
String message, List<String> attachments
) throws Error.AttachmentInvalid, Error.Failure, Error.UnregisteredUser, Error.UntrustedIdentity;
void sendEndSessionMessage(List<String> recipients) throws Error.Failure, Error.InvalidNumber, Error.UnregisteredUser, Error.UntrustedIdentity; void sendEndSessionMessage(List<String> recipients) throws Error.Failure, Error.InvalidNumber, Error.UnregisteredUser, Error.UntrustedIdentity;
long sendGroupMessage( long sendGroupMessage(

View file

@ -1,6 +1,7 @@
package org.asamk.signal.commands; package org.asamk.signal.commands;
import net.sourceforge.argparse4j.impl.Arguments; import net.sourceforge.argparse4j.impl.Arguments;
import net.sourceforge.argparse4j.inf.MutuallyExclusiveGroup;
import net.sourceforge.argparse4j.inf.Namespace; import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser; import net.sourceforge.argparse4j.inf.Subparser;
@ -13,7 +14,6 @@ import org.freedesktop.dbus.exceptions.DBusExecutionException;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.asamk.signal.util.ErrorUtils.handleAssertionError; import static org.asamk.signal.util.ErrorUtils.handleAssertionError;
@ -23,8 +23,13 @@ public class SendCommand implements DbusCommand {
@Override @Override
public void attachToSubparser(final Subparser subparser) { public void attachToSubparser(final Subparser subparser) {
subparser.addArgument("-g", "--group").help("Specify the recipient group ID.");
subparser.addArgument("recipient").help("Specify the recipients' phone number.").nargs("*"); subparser.addArgument("recipient").help("Specify the recipients' phone number.").nargs("*");
final MutuallyExclusiveGroup mutuallyExclusiveGroup = subparser.addMutuallyExclusiveGroup();
mutuallyExclusiveGroup.addArgument("-g", "--group").help("Specify the recipient group ID.");
mutuallyExclusiveGroup.addArgument("--note-to-self")
.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."); subparser.addArgument("-m", "--message").help("Specify the message, if missing standard input is used.");
subparser.addArgument("-a", "--attachment").nargs("*").help("Add file as attachment"); subparser.addArgument("-a", "--attachment").nargs("*").help("Add file as attachment");
subparser.addArgument("-e", "--endsession") subparser.addArgument("-e", "--endsession")
@ -37,9 +42,10 @@ public class SendCommand implements DbusCommand {
final List<String> recipients = ns.getList("recipient"); final List<String> recipients = ns.getList("recipient");
final Boolean isEndSession = ns.getBoolean("endsession"); final Boolean isEndSession = ns.getBoolean("endsession");
final String groupIdString = ns.getString("group"); final String groupIdString = ns.getString("group");
final Boolean isNoteToSelf = ns.getBoolean("note_to_self");
final boolean noRecipients = recipients == null || recipients.isEmpty(); final boolean noRecipients = recipients == null || recipients.isEmpty();
if ((noRecipients && isEndSession) || (noRecipients && groupIdString == null)) { if ((noRecipients && isEndSession) || (noRecipients && groupIdString == null && !isNoteToSelf)) {
System.err.println("No recipients given"); System.err.println("No recipients given");
System.err.println("Aborting sending."); System.err.println("Aborting sending.");
return 1; return 1;
@ -48,6 +54,10 @@ public class SendCommand implements DbusCommand {
System.err.println("You cannot specify recipients by phone number and groups at the same time"); System.err.println("You cannot specify recipients by phone number and groups at the same time");
return 1; return 1;
} }
if (!noRecipients && isNoteToSelf) {
System.err.println("You cannot specify recipients by phone number and not to self at the same time");
return 1;
}
if (isEndSession) { if (isEndSession) {
try { try {
@ -75,11 +85,11 @@ public class SendCommand implements DbusCommand {
List<String> attachments = ns.getList("attachment"); List<String> attachments = ns.getList("attachment");
if (attachments == null) { if (attachments == null) {
attachments = new ArrayList<>(); attachments = List.of();
} }
try {
if (groupIdString != null) { if (groupIdString != null) {
try {
byte[] groupId; byte[] groupId;
try { try {
groupId = Util.decodeGroupId(groupIdString).serialize(); groupId = Util.decodeGroupId(groupIdString).serialize();
@ -91,14 +101,28 @@ public class SendCommand implements DbusCommand {
long timestamp = signal.sendGroupMessage(messageText, attachments, groupId); long timestamp = signal.sendGroupMessage(messageText, attachments, groupId);
System.out.println(timestamp); System.out.println(timestamp);
return 0; return 0;
}
} catch (AssertionError e) { } catch (AssertionError e) {
handleAssertionError(e); handleAssertionError(e);
return 1; return 1;
} catch (DBusExecutionException e) { } catch (DBusExecutionException e) {
System.err.println("Failed to send message: " + e.getMessage()); System.err.println("Failed to send group message: " + e.getMessage());
return 2; return 2;
} }
}
if (isNoteToSelf) {
try {
long timestamp = signal.sendNoteToSelfMessage(messageText, attachments);
System.out.println(timestamp);
return 0;
} catch (AssertionError e) {
handleAssertionError(e);
return 1;
} catch (DBusExecutionException e) {
System.err.println("Failed to send note to self message: " + e.getMessage());
return 2;
}
}
try { try {
long timestamp = signal.sendMessage(messageText, attachments, recipients); long timestamp = signal.sendMessage(messageText, attachments, recipients);

View file

@ -78,6 +78,21 @@ public class DbusSignalImpl implements Signal {
} }
} }
@Override
public long sendNoteToSelfMessage(
final String message, final List<String> attachments
) throws Error.AttachmentInvalid, Error.Failure, Error.UnregisteredUser, Error.UntrustedIdentity {
try {
final Pair<Long, List<SendMessageResult>> results = m.sendSelfMessage(message, attachments);
checkSendMessageResults(results.first(), results.second());
return results.first();
} catch (AttachmentInvalidException e) {
throw new Error.AttachmentInvalid(e.getMessage());
} catch (IOException e) {
throw new Error.Failure(e.getMessage());
}
}
@Override @Override
public void sendEndSessionMessage(final List<String> recipients) { public void sendEndSessionMessage(final List<String> recipients) {
try { try {

View file

@ -953,6 +953,17 @@ public class Manager implements Closeable {
return sendMessage(messageBuilder, getSignalServiceAddresses(recipients)); return sendMessage(messageBuilder, getSignalServiceAddresses(recipients));
} }
public Pair<Long, List<SendMessageResult>> sendSelfMessage(
String messageText, List<String> attachments
) throws IOException, AttachmentInvalidException {
final SignalServiceDataMessage.Builder messageBuilder = SignalServiceDataMessage.newBuilder()
.withBody(messageText);
if (attachments != null) {
messageBuilder.withAttachments(AttachmentUtils.getSignalServiceAttachments(attachments));
}
return sendSelfMessage(messageBuilder);
}
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 {
@ -1253,12 +1264,8 @@ public class Manager implements Closeable {
final int expirationTime = contact != null ? contact.messageExpirationTime : 0; final int expirationTime = contact != null ? contact.messageExpirationTime : 0;
messageBuilder.withExpiration(expirationTime); messageBuilder.withExpiration(expirationTime);
message = messageBuilder.build(); message = messageBuilder.build();
if (address.matches(account.getSelfAddress())) {
results.add(sendSelfMessage(message));
} else {
results.add(sendMessage(address, message)); results.add(sendMessage(address, message));
} }
}
return new Pair<>(timestamp, results); return new Pair<>(timestamp, results);
} }
} finally { } finally {
@ -1271,6 +1278,28 @@ public class Manager implements Closeable {
} }
} }
private Pair<Long, List<SendMessageResult>> sendSelfMessage(
SignalServiceDataMessage.Builder messageBuilder
) throws IOException {
final long timestamp = System.currentTimeMillis();
messageBuilder.withTimestamp(timestamp);
getOrCreateMessagePipe();
getOrCreateUnidentifiedMessagePipe();
try {
final SignalServiceAddress address = getSelfAddress();
final ContactInfo contact = account.getContactStore().getContact(address);
final int expirationTime = contact != null ? contact.messageExpirationTime : 0;
messageBuilder.withExpiration(expirationTime);
SignalServiceDataMessage message = messageBuilder.build();
final SendMessageResult result = sendSelfMessage(message);
return new Pair<>(timestamp, List.of(result));
} finally {
account.save();
}
}
private SendMessageResult sendSelfMessage(SignalServiceDataMessage message) throws IOException { private SendMessageResult sendSelfMessage(SignalServiceDataMessage message) throws IOException {
SignalServiceMessageSender messageSender = createMessageSender(); SignalServiceMessageSender messageSender = createMessageSender();