mirror of
https://github.com/AsamK/signal-cli
synced 2025-09-04 05:00:39 +00:00
create new DbusAttachment type allow URLs for --attachment option update manpage update wiki with signalmail implement setExpirationTimer() for DBus implement isRegistered() for DBus add sendNoteToSelfMessageWithDBusAttachments add sendGroupMessageWithDBusAttachments add sendMessageWithDBusAttachments bump version
This commit is contained in:
parent
8f781c019f
commit
8aed357994
18 changed files with 526 additions and 49 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -11,3 +11,6 @@ local.properties
|
||||||
.settings/
|
.settings/
|
||||||
out/
|
out/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.git/
|
||||||
|
signal-cli
|
||||||
|
bin/
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# signal-cli
|
# signal-cli
|
||||||
|
|
||||||
signal-cli is a commandline interface for [libsignal-service-java](https://github.com/WhisperSystems/libsignal-service-java). It supports registering, verifying, sending and receiving messages.
|
signal-cli is a commandline interface for [libsignal-service-java](https://github.com/WhisperSystems/libsignal-service-java). It supports registering, verifying, sending and receiving messages.
|
||||||
To be able to link to an existing Signal-Android/signal-cli instance, signal-cli uses a [patched libsignal-service-java](https://github.com/AsamK/libsignal-service-java), because libsignal-service-java does not yet support [provisioning as a slave device](https://github.com/WhisperSystems/libsignal-service-java/pull/21).
|
To be able to link to an existing Signal-Android/signal-cli instance, signal-cli uses a [patched libsignal-service-java](https://github.com/AsamK/libsignal-service-java), because libsignal-service-java does not yet support [provisioning as a secondary device](https://github.com/WhisperSystems/libsignal-service-java/pull/21).
|
||||||
For registering you need a phone number where you can receive SMS or incoming calls.
|
For registering you need a phone number where you can receive SMS or incoming calls.
|
||||||
signal-cli is primarily intended to be used on servers to notify admins of important events. For this use-case, it has a dbus interface ([man page](https://github.com/AsamK/signal-cli/blob/master/man/signal-cli-dbus.5.adoc)), that can be used to send messages from any programming language that has dbus bindings.
|
signal-cli is primarily intended to be used on servers to notify admins of important events. For this use-case, it has a dbus interface ([man page](https://github.com/AsamK/signal-cli/blob/master/man/signal-cli-dbus.5.adoc)), that can be used to send messages from any programming language that has dbus bindings.
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ plugins {
|
||||||
`check-lib-versions`
|
`check-lib-versions`
|
||||||
}
|
}
|
||||||
|
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
|
|
||||||
java {
|
java {
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
|
|
@ -1274,7 +1274,7 @@ public class Manager implements Closeable {
|
||||||
) throws IOException, AttachmentInvalidException, InvalidNumberException {
|
) throws IOException, AttachmentInvalidException, InvalidNumberException {
|
||||||
final var messageBuilder = SignalServiceDataMessage.newBuilder().withBody(messageText);
|
final var messageBuilder = SignalServiceDataMessage.newBuilder().withBody(messageText);
|
||||||
if (attachments != null) {
|
if (attachments != null) {
|
||||||
var attachmentStreams = AttachmentUtils.getSignalServiceAttachments(attachments);
|
List<SignalServiceAttachment> attachmentStreams = AttachmentUtils.getSignalServiceAttachments(attachments);
|
||||||
|
|
||||||
// Upload attachments here, so we only upload once even for multiple recipients
|
// Upload attachments here, so we only upload once even for multiple recipients
|
||||||
var messageSender = createMessageSender();
|
var messageSender = createMessageSender();
|
||||||
|
|
|
@ -11,6 +11,7 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
public class AttachmentUtils {
|
public class AttachmentUtils {
|
||||||
|
|
||||||
|
@ -21,8 +22,13 @@ public class AttachmentUtils {
|
||||||
for (var attachment : attachments) {
|
for (var attachment : attachments) {
|
||||||
try {
|
try {
|
||||||
signalServiceAttachments.add(createAttachment(new File(attachment)));
|
signalServiceAttachments.add(createAttachment(new File(attachment)));
|
||||||
} catch (IOException e) {
|
} catch (IOException f) {
|
||||||
throw new AttachmentInvalidException(attachment, e);
|
// no such file, send it as URL
|
||||||
|
try {
|
||||||
|
signalServiceAttachments.add(createAttachment(new URL(attachment)));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new AttachmentInvalidException(attachment, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,25 +40,39 @@ public class AttachmentUtils {
|
||||||
return createAttachment(streamDetails, Optional.of(attachmentFile.getName()));
|
return createAttachment(streamDetails, Optional.of(attachmentFile.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static SignalServiceAttachmentStream createAttachment(URL aURL) throws IOException {
|
||||||
|
final var streamDetails = Utils.createStreamDetailsFromURL(aURL);
|
||||||
|
String path = aURL.getPath();
|
||||||
|
String name = path.substring(path.lastIndexOf('/') + 1);
|
||||||
|
return createAttachment(streamDetails, Optional.of(name));
|
||||||
|
}
|
||||||
|
|
||||||
public static SignalServiceAttachmentStream createAttachment(
|
public static SignalServiceAttachmentStream createAttachment(
|
||||||
StreamDetails streamDetails, Optional<String> name
|
StreamDetails streamDetails, Optional<String> name
|
||||||
) {
|
) {
|
||||||
// TODO mabybe add a parameter to set the voiceNote, borderless, preview, width, height and caption option
|
// TODO maybe add a parameter to set the voiceNote, borderless, preview, width, height, caption, blurHash options
|
||||||
final var uploadTimestamp = System.currentTimeMillis();
|
final var uploadTimestamp = System.currentTimeMillis();
|
||||||
|
boolean voicenote = false;
|
||||||
|
boolean borderless = false;
|
||||||
Optional<byte[]> preview = Optional.absent();
|
Optional<byte[]> preview = Optional.absent();
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
Optional<String> caption = Optional.absent();
|
Optional<String> caption = Optional.absent();
|
||||||
Optional<String> blurHash = Optional.absent();
|
Optional<String> blurHash = Optional.absent();
|
||||||
final Optional<ResumableUploadSpec> resumableUploadSpec = Optional.absent();
|
final Optional<ResumableUploadSpec> resumableUploadSpec = Optional.absent();
|
||||||
|
//ProgressListener listener = null; //Android OS
|
||||||
|
//CancellationSignal cancellationSignal = null; //Android OS; Signal developers misspelled class name
|
||||||
|
|
||||||
return new SignalServiceAttachmentStream(streamDetails.getStream(),
|
return new SignalServiceAttachmentStream(streamDetails.getStream(),
|
||||||
streamDetails.getContentType(),
|
streamDetails.getContentType(),
|
||||||
streamDetails.getLength(),
|
streamDetails.getLength(),
|
||||||
name,
|
name,
|
||||||
false,
|
voicenote,
|
||||||
false,
|
borderless,
|
||||||
false,
|
false,
|
||||||
preview,
|
preview,
|
||||||
0,
|
width,
|
||||||
0,
|
height,
|
||||||
uploadTimestamp,
|
uploadTimestamp,
|
||||||
caption,
|
caption,
|
||||||
blurHash,
|
blurHash,
|
||||||
|
|
|
@ -11,6 +11,7 @@ import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
@ -36,6 +37,13 @@ public class Utils {
|
||||||
return new StreamDetails(stream, mime, size);
|
return new StreamDetails(stream, mime, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static StreamDetails createStreamDetailsFromURL(URL aURL) throws IOException {
|
||||||
|
InputStream stream = aURL.openStream();
|
||||||
|
final var mime = aURL.openConnection().getContentType();
|
||||||
|
final var size = aURL.openConnection().getContentLengthLong();
|
||||||
|
return new StreamDetails(stream, mime, size);
|
||||||
|
}
|
||||||
|
|
||||||
public static String computeSafetyNumber(
|
public static String computeSafetyNumber(
|
||||||
boolean isUuidCapable,
|
boolean isUuidCapable,
|
||||||
SignalServiceAddress ownAddress,
|
SignalServiceAddress ownAddress,
|
||||||
|
|
BIN
signal-cli.1.gz
Normal file
BIN
signal-cli.1.gz
Normal file
Binary file not shown.
|
@ -4,6 +4,7 @@ import org.freedesktop.dbus.exceptions.DBusException;
|
||||||
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
||||||
import org.freedesktop.dbus.interfaces.DBusInterface;
|
import org.freedesktop.dbus.interfaces.DBusInterface;
|
||||||
import org.freedesktop.dbus.messages.DBusSignal;
|
import org.freedesktop.dbus.messages.DBusSignal;
|
||||||
|
import org.asamk.signal.dbus.DbusAttachment;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -13,12 +14,21 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public interface Signal extends DBusInterface {
|
public interface Signal extends DBusInterface {
|
||||||
|
|
||||||
long sendMessage(
|
|
||||||
String message, List<String> attachments, String recipient
|
long sendMessageWithDBusAttachments(
|
||||||
|
String message, List<DbusAttachment> dBusAttachments, String recipient
|
||||||
|
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
|
||||||
|
|
||||||
|
long sendMessageWithDBusAttachments(
|
||||||
|
String message, List<DbusAttachment> dBusAttachments, List<String> recipients
|
||||||
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
|
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
|
||||||
|
|
||||||
long sendMessage(
|
long sendMessage(
|
||||||
String message, List<String> attachments, List<String> recipients
|
String message, List<String> attachmentNames, String recipient
|
||||||
|
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
|
||||||
|
|
||||||
|
long sendMessage(
|
||||||
|
String message, List<String> attachmentNames, List<String> recipients
|
||||||
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
|
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
|
||||||
|
|
||||||
long sendRemoteDeleteMessage(
|
long sendRemoteDeleteMessage(
|
||||||
|
@ -42,13 +52,21 @@ public interface Signal extends DBusInterface {
|
||||||
) throws Error.InvalidNumber, Error.Failure;
|
) throws Error.InvalidNumber, Error.Failure;
|
||||||
|
|
||||||
long sendNoteToSelfMessage(
|
long sendNoteToSelfMessage(
|
||||||
String message, List<String> attachments
|
String message, List<String> attachmentNames
|
||||||
|
) throws Error.AttachmentInvalid, Error.Failure;
|
||||||
|
|
||||||
|
long sendNoteToSelfMessageWithDBusAttachments(
|
||||||
|
String message, List<DbusAttachment> dBusAttachments
|
||||||
) throws Error.AttachmentInvalid, Error.Failure;
|
) throws Error.AttachmentInvalid, Error.Failure;
|
||||||
|
|
||||||
void sendEndSessionMessage(List<String> recipients) throws Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
|
void sendEndSessionMessage(List<String> recipients) throws Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
|
||||||
|
|
||||||
long sendGroupMessage(
|
long sendGroupMessage(
|
||||||
String message, List<String> attachments, byte[] groupId
|
String message, List<String> attachmentNames, byte[] groupId
|
||||||
|
) throws Error.GroupNotFound, Error.Failure, Error.AttachmentInvalid;
|
||||||
|
|
||||||
|
long sendGroupMessageWithDBusAttachments(
|
||||||
|
String message, List<DbusAttachment> dBusAttachments, byte[] groupId
|
||||||
) throws Error.GroupNotFound, Error.Failure, Error.AttachmentInvalid;
|
) throws Error.GroupNotFound, Error.Failure, Error.AttachmentInvalid;
|
||||||
|
|
||||||
long sendGroupMessageReaction(
|
long sendGroupMessageReaction(
|
||||||
|
@ -59,6 +77,8 @@ public interface Signal extends DBusInterface {
|
||||||
|
|
||||||
void setContactName(String number, String name) throws Error.InvalidNumber;
|
void setContactName(String number, String name) throws Error.InvalidNumber;
|
||||||
|
|
||||||
|
void setExpirationTimer(final String number, final int expiration) throws Error.InvalidNumber;
|
||||||
|
|
||||||
void setContactBlocked(String number, boolean blocked) throws Error.InvalidNumber;
|
void setContactBlocked(String number, boolean blocked) throws Error.InvalidNumber;
|
||||||
|
|
||||||
void setGroupBlocked(byte[] groupId, boolean blocked) throws Error.GroupNotFound;
|
void setGroupBlocked(byte[] groupId, boolean blocked) throws Error.GroupNotFound;
|
||||||
|
@ -101,7 +121,7 @@ public interface Signal extends DBusInterface {
|
||||||
private final String sender;
|
private final String sender;
|
||||||
private final byte[] groupId;
|
private final byte[] groupId;
|
||||||
private final String message;
|
private final String message;
|
||||||
private final List<String> attachments;
|
private final List<DbusAttachment> dBusAttachments;
|
||||||
|
|
||||||
public MessageReceived(
|
public MessageReceived(
|
||||||
String objectpath,
|
String objectpath,
|
||||||
|
@ -109,14 +129,14 @@ public interface Signal extends DBusInterface {
|
||||||
String sender,
|
String sender,
|
||||||
byte[] groupId,
|
byte[] groupId,
|
||||||
String message,
|
String message,
|
||||||
List<String> attachments
|
List<DbusAttachment> dBusAttachments
|
||||||
) throws DBusException {
|
) throws DBusException {
|
||||||
super(objectpath, timestamp, sender, groupId, message, attachments);
|
super(objectpath, timestamp, sender, groupId, message, dBusAttachments);
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.attachments = attachments;
|
this.dBusAttachments = dBusAttachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getTimestamp() {
|
public long getTimestamp() {
|
||||||
|
@ -135,9 +155,10 @@ public interface Signal extends DBusInterface {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getAttachments() {
|
public List<DbusAttachment> getAttachments() {
|
||||||
return attachments;
|
return dBusAttachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReceiptReceived extends DBusSignal {
|
class ReceiptReceived extends DBusSignal {
|
||||||
|
@ -167,7 +188,7 @@ public interface Signal extends DBusInterface {
|
||||||
private final String destination;
|
private final String destination;
|
||||||
private final byte[] groupId;
|
private final byte[] groupId;
|
||||||
private final String message;
|
private final String message;
|
||||||
private final List<String> attachments;
|
private final List<DbusAttachment> dBusAttachments;
|
||||||
|
|
||||||
public SyncMessageReceived(
|
public SyncMessageReceived(
|
||||||
String objectpath,
|
String objectpath,
|
||||||
|
@ -176,15 +197,15 @@ public interface Signal extends DBusInterface {
|
||||||
String destination,
|
String destination,
|
||||||
byte[] groupId,
|
byte[] groupId,
|
||||||
String message,
|
String message,
|
||||||
List<String> attachments
|
List<DbusAttachment> dBusAttachments
|
||||||
) throws DBusException {
|
) throws DBusException {
|
||||||
super(objectpath, timestamp, source, destination, groupId, message, attachments);
|
super(objectpath, timestamp, source, destination, groupId, message, dBusAttachments);
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.attachments = attachments;
|
this.dBusAttachments = dBusAttachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getTimestamp() {
|
public long getTimestamp() {
|
||||||
|
@ -207,8 +228,8 @@ public interface Signal extends DBusInterface {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getAttachments() {
|
public List<DbusAttachment> getAttachments() {
|
||||||
return attachments;
|
return dBusAttachments;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -163,7 +163,7 @@ public class App {
|
||||||
|
|
||||||
username = usernames.get(0);
|
username = usernames.get(0);
|
||||||
} else if (!PhoneNumberFormatter.isValidNumber(username, null)) {
|
} else if (!PhoneNumberFormatter.isValidNumber(username, null)) {
|
||||||
throw new UserErrorException("Invalid username (phone number), make sure you include the country code.");
|
throw new UserErrorException("Invalid username (phone number), make sure you include a plus sign (+) followed by the country code.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command instanceof RegistrationCommand) {
|
if (command instanceof RegistrationCommand) {
|
||||||
|
@ -264,6 +264,7 @@ public class App {
|
||||||
try {
|
try {
|
||||||
manager = Manager.init(username, dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
|
manager = Manager.init(username, dataPath, serviceEnvironment, BaseConfig.USER_AGENT);
|
||||||
} catch (NotRegisteredException e) {
|
} catch (NotRegisteredException e) {
|
||||||
|
logger.debug("dataPath=" + dataPath + " serviceEnvironment=" + serviceEnvironment, e);
|
||||||
throw new UserErrorException("User " + username + " is not registered.");
|
throw new UserErrorException("User " + username + " is not registered.");
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
logger.debug("Loading state file failed", e);
|
logger.debug("Loading state file failed", e);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.asamk.signal;
|
package org.asamk.signal;
|
||||||
|
|
||||||
import org.asamk.Signal;
|
import org.asamk.Signal;
|
||||||
|
import org.asamk.signal.dbus.DbusAttachment;
|
||||||
import org.asamk.signal.manager.Manager;
|
import org.asamk.signal.manager.Manager;
|
||||||
import org.asamk.signal.manager.groups.GroupUtils;
|
import org.asamk.signal.manager.groups.GroupUtils;
|
||||||
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
import org.freedesktop.dbus.connections.impl.DBusConnection;
|
||||||
|
@ -9,6 +10,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceContent;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
|
import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
|
||||||
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -71,12 +73,15 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler {
|
||||||
|| message.getGroupContext().get().getGroupV1Type() == SignalServiceGroup.Type.DELIVER
|
|| message.getGroupContext().get().getGroupV1Type() == SignalServiceGroup.Type.DELIVER
|
||||||
)) {
|
)) {
|
||||||
try {
|
try {
|
||||||
|
List<SignalServiceAttachment> attachments = JsonDbusReceiveMessageHandler.getAttachments(message);
|
||||||
|
List<DbusAttachment> dBusAttachments = JsonDbusReceiveMessageHandler.convertSignalAttachmentsToDbus(attachments);
|
||||||
conn.sendMessage(new Signal.MessageReceived(objectPath,
|
conn.sendMessage(new Signal.MessageReceived(objectPath,
|
||||||
message.getTimestamp(),
|
message.getTimestamp(),
|
||||||
getLegacyIdentifier(sender),
|
getLegacyIdentifier(sender),
|
||||||
groupId != null ? groupId : new byte[0],
|
groupId != null ? groupId : new byte[0],
|
||||||
message.getBody().isPresent() ? message.getBody().get() : "",
|
message.getBody().isPresent() ? message.getBody().get() : "",
|
||||||
JsonDbusReceiveMessageHandler.getAttachments(message, m)));
|
dBusAttachments
|
||||||
|
));
|
||||||
} catch (DBusException e) {
|
} catch (DBusException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -93,6 +98,8 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler {
|
||||||
var groupId = getGroupId(message);
|
var groupId = getGroupId(message);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
List<SignalServiceAttachment> attachments = JsonDbusReceiveMessageHandler.getAttachments(message);
|
||||||
|
List<DbusAttachment> dBusAttachments = JsonDbusReceiveMessageHandler.convertSignalAttachmentsToDbus(attachments);
|
||||||
conn.sendMessage(new Signal.SyncMessageReceived(objectPath,
|
conn.sendMessage(new Signal.SyncMessageReceived(objectPath,
|
||||||
transcript.getTimestamp(),
|
transcript.getTimestamp(),
|
||||||
getLegacyIdentifier(sender),
|
getLegacyIdentifier(sender),
|
||||||
|
@ -101,7 +108,8 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler {
|
||||||
: "",
|
: "",
|
||||||
groupId != null ? groupId : new byte[0],
|
groupId != null ? groupId : new byte[0],
|
||||||
message.getBody().isPresent() ? message.getBody().get() : "",
|
message.getBody().isPresent() ? message.getBody().get() : "",
|
||||||
JsonDbusReceiveMessageHandler.getAttachments(message, m)));
|
dBusAttachments
|
||||||
|
));
|
||||||
} catch (DBusException e) {
|
} catch (DBusException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -116,7 +124,7 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler {
|
||||||
.serialize() : null;
|
.serialize() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static private List<String> getAttachments(SignalServiceDataMessage message, Manager m) {
|
static private List<String> getAttachmentNames(SignalServiceDataMessage message, Manager m) {
|
||||||
var attachments = new ArrayList<String>();
|
var attachments = new ArrayList<String>();
|
||||||
if (message.getAttachments().isPresent()) {
|
if (message.getAttachments().isPresent()) {
|
||||||
for (var attachment : message.getAttachments().get()) {
|
for (var attachment : message.getAttachments().get()) {
|
||||||
|
@ -128,10 +136,34 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler {
|
||||||
return attachments;
|
return attachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static private List<SignalServiceAttachment> getAttachments(SignalServiceDataMessage message) {
|
||||||
|
var attachments = new ArrayList<SignalServiceAttachment>();
|
||||||
|
if (message.getAttachments().isPresent()) {
|
||||||
|
for (var attachment : message.getAttachments().get()) {
|
||||||
|
if (attachment.isPointer()) {
|
||||||
|
attachments.add(attachment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return attachments;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) {
|
public void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, Throwable exception) {
|
||||||
super.handleMessage(envelope, content, exception);
|
super.handleMessage(envelope, content, exception);
|
||||||
|
|
||||||
sendReceivedMessageToDbus(envelope, content, conn, objectPath, m);
|
sendReceivedMessageToDbus(envelope, content, conn, objectPath, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static private List<DbusAttachment> convertSignalAttachmentsToDbus(List<SignalServiceAttachment> attachments) {
|
||||||
|
ArrayList<DbusAttachment> dBusAttachments = new ArrayList<>();
|
||||||
|
if (!attachments.isEmpty()) {
|
||||||
|
for (SignalServiceAttachment attachment : attachments) {
|
||||||
|
DbusAttachment dBusAttachment = new DbusAttachment(attachment);
|
||||||
|
dBusAttachments.add(dBusAttachment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dBusAttachments;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -646,6 +646,9 @@ public class ReceiveMessageHandler implements Manager.ReceiveMessageHandler {
|
||||||
if (pointer.getCaption().isPresent()) {
|
if (pointer.getCaption().isPresent()) {
|
||||||
writer.println("Caption: {}", pointer.getCaption().get());
|
writer.println("Caption: {}", pointer.getCaption().get());
|
||||||
}
|
}
|
||||||
|
if (pointer.getBlurHash().isPresent()) {
|
||||||
|
writer.println("Blur Hash: {}", pointer.getBlurHash().get());
|
||||||
|
}
|
||||||
if (pointer.getFileName().isPresent()) {
|
if (pointer.getFileName().isPresent()) {
|
||||||
writer.println("Filename: {}", pointer.getFileName().get());
|
writer.println("Filename: {}", pointer.getFileName().get());
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,12 @@ public class DaemonCommand implements MultiLocalCommand {
|
||||||
var objectPath = DbusConfig.getObjectPath();
|
var objectPath = DbusConfig.getObjectPath();
|
||||||
var t = run(conn, objectPath, m, ignoreAttachments);
|
var t = run(conn, objectPath, m, ignoreAttachments);
|
||||||
|
|
||||||
conn.requestBusName(DbusConfig.getBusname());
|
try {
|
||||||
|
conn.requestBusName(DbusConfig.getBusname());
|
||||||
|
} catch (DBusException e) {
|
||||||
|
logger.error("Dbus request command failed", e);
|
||||||
|
throw new UnexpectedErrorException("Dbus request command failed");
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
t.join();
|
t.join();
|
||||||
|
|
|
@ -11,6 +11,8 @@ import org.asamk.signal.commands.exceptions.CommandException;
|
||||||
import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
|
import org.asamk.signal.commands.exceptions.UnexpectedErrorException;
|
||||||
import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException;
|
import org.asamk.signal.commands.exceptions.UntrustedKeyErrorException;
|
||||||
import org.asamk.signal.commands.exceptions.UserErrorException;
|
import org.asamk.signal.commands.exceptions.UserErrorException;
|
||||||
|
import org.asamk.signal.dbus.DbusAttachment;
|
||||||
|
|
||||||
import org.asamk.signal.manager.groups.GroupIdFormatException;
|
import org.asamk.signal.manager.groups.GroupIdFormatException;
|
||||||
import org.asamk.signal.util.IOUtils;
|
import org.asamk.signal.util.IOUtils;
|
||||||
import org.asamk.signal.util.Util;
|
import org.asamk.signal.util.Util;
|
||||||
|
@ -18,9 +20,11 @@ import org.freedesktop.dbus.errors.UnknownObject;
|
||||||
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
import org.freedesktop.dbus.exceptions.DBusExecutionException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
public class SendCommand implements DbusCommand {
|
public class SendCommand implements DbusCommand {
|
||||||
|
@ -87,13 +91,21 @@ public class SendCommand implements DbusCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> attachments = ns.getList("attachment");
|
List<String> attachmentNames = ns.getList("attachment");
|
||||||
if (attachments == null) {
|
if (attachmentNames == null) {
|
||||||
attachments = List.of();
|
attachmentNames = List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
final var writer = (PlainTextWriterImpl) outputWriter;
|
final var writer = (PlainTextWriterImpl) outputWriter;
|
||||||
|
|
||||||
|
ArrayList<DbusAttachment> dBusAttachments = new ArrayList<>();
|
||||||
|
if (!attachmentNames.isEmpty()) {
|
||||||
|
for (var attachmentName : attachmentNames) {
|
||||||
|
DbusAttachment dBusAttachment = new DbusAttachment(attachmentName);
|
||||||
|
dBusAttachments.add(dBusAttachment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (groupIdString != null) {
|
if (groupIdString != null) {
|
||||||
byte[] groupId;
|
byte[] groupId;
|
||||||
try {
|
try {
|
||||||
|
@ -103,7 +115,7 @@ public class SendCommand implements DbusCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var timestamp = signal.sendGroupMessage(messageText, attachments, groupId);
|
var timestamp = signal.sendGroupMessage(messageText, attachmentNames, groupId);
|
||||||
writer.println("{}", timestamp);
|
writer.println("{}", timestamp);
|
||||||
return;
|
return;
|
||||||
} catch (DBusExecutionException e) {
|
} catch (DBusExecutionException e) {
|
||||||
|
@ -113,25 +125,26 @@ public class SendCommand implements DbusCommand {
|
||||||
|
|
||||||
if (isNoteToSelf) {
|
if (isNoteToSelf) {
|
||||||
try {
|
try {
|
||||||
var timestamp = signal.sendNoteToSelfMessage(messageText, attachments);
|
var timestamp = signal.sendNoteToSelfMessage(messageText, attachmentNames);
|
||||||
writer.println("{}", timestamp);
|
writer.println("{}", timestamp);
|
||||||
return;
|
return;
|
||||||
} catch (Signal.Error.UntrustedIdentity e) {
|
} catch (Signal.Error.UntrustedIdentity e) {
|
||||||
throw new UntrustedKeyErrorException("Failed to send message: " + e.getMessage());
|
throw new UntrustedKeyErrorException("Failed to send note to self message: " + e.getMessage());
|
||||||
} catch (DBusExecutionException e) {
|
} catch (DBusExecutionException e) {
|
||||||
throw new UnexpectedErrorException("Failed to send note to self message: " + e.getMessage());
|
throw new UnexpectedErrorException("Failed to send note to self message: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var timestamp = signal.sendMessage(messageText, attachments, recipients);
|
var timestamp = signal.sendMessageWithDBusAttachments(messageText, dBusAttachments, recipients);
|
||||||
writer.println("{}", timestamp);
|
writer.println("{}", timestamp);
|
||||||
|
|
||||||
} catch (UnknownObject e) {
|
} catch (UnknownObject e) {
|
||||||
throw new UserErrorException("Failed to find dbus object, maybe missing the -u flag: " + e.getMessage());
|
throw new UserErrorException("Failed to find dbus object, maybe missing the -u flag: " + e.getMessage());
|
||||||
} catch (Signal.Error.UntrustedIdentity e) {
|
} catch (Signal.Error.UntrustedIdentity e) {
|
||||||
throw new UntrustedKeyErrorException("Failed to send message: " + e.getMessage());
|
throw new UntrustedKeyErrorException("Failed to send message: " + e.getMessage());
|
||||||
} catch (DBusExecutionException e) {
|
} catch (DBusExecutionException e) {
|
||||||
throw new UnexpectedErrorException("Failed to send message: " + e.getMessage());
|
throw new UnexpectedErrorException("Failed to send message, did not find attachment: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
238
src/main/java/org/asamk/signal/dbus/DbusAttachment.java
Normal file
238
src/main/java/org/asamk/signal/dbus/DbusAttachment.java
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
package org.asamk.signal.dbus;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
||||||
|
import org.whispersystems.signalservice.api.util.StreamDetails;
|
||||||
|
import org.freedesktop.dbus.exceptions.DBusException;
|
||||||
|
import org.freedesktop.dbus.annotations.Position;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
|
||||||
|
import org.asamk.signal.manager.util.Utils;
|
||||||
|
import org.freedesktop.dbus.Struct;
|
||||||
|
|
||||||
|
public final class DbusAttachment extends Struct
|
||||||
|
{
|
||||||
|
@Position(0)
|
||||||
|
private String contentType;
|
||||||
|
@Position(1)
|
||||||
|
private String fileName;
|
||||||
|
@Position(2)
|
||||||
|
private String id;
|
||||||
|
@Position(3)
|
||||||
|
private Long size;
|
||||||
|
@Position(4)
|
||||||
|
private Integer keyLength;
|
||||||
|
@Position(5)
|
||||||
|
private boolean voiceNote;
|
||||||
|
@Position(6)
|
||||||
|
private Integer width;
|
||||||
|
@Position(7)
|
||||||
|
private Integer height;
|
||||||
|
@Position(8)
|
||||||
|
private String caption;
|
||||||
|
@Position(9)
|
||||||
|
private String blurHash;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* API = 2.15.3 from https://github.com/Turasa/libsignal-service-java (nonstandard)
|
||||||
|
public SignalServiceAttachmentStream(InputStream inputStream,
|
||||||
|
String contentType,
|
||||||
|
long length,
|
||||||
|
Optional<String> fileName,
|
||||||
|
boolean voiceNote,
|
||||||
|
boolean borderless,
|
||||||
|
boolean gif, //nonstandard
|
||||||
|
Optional<byte[]> preview,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
long uploadTimestamp,
|
||||||
|
Optional<String> caption,
|
||||||
|
Optional<String> blurHash,
|
||||||
|
ProgressListener listener, //Android OS
|
||||||
|
CancellationSignal cancellationSignal, //Android OS, Signal developers misspelled class name
|
||||||
|
Optional<ResumableUploadSpec> resumableUploadSpec)
|
||||||
|
|
||||||
|
|
||||||
|
public SignalServiceAttachmentPointer(int cdnNumber,
|
||||||
|
SignalServiceAttachmentRemoteId remoteId,
|
||||||
|
String contentType,
|
||||||
|
byte[] key,
|
||||||
|
Optional<Integer> size,
|
||||||
|
Optional<byte[]> preview,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
Optional<byte[]> digest,
|
||||||
|
Optional<String> fileName,
|
||||||
|
boolean voiceNote,
|
||||||
|
boolean borderless,
|
||||||
|
Optional<String> caption,
|
||||||
|
Optional<String> blurHash,
|
||||||
|
long uploadTimestamp)
|
||||||
|
|
||||||
|
other stuff :
|
||||||
|
private long id; // used by v2 attachments, see note
|
||||||
|
private int keyLength; //TODO: if you're going to do that, probably should have previewLength and digestLength
|
||||||
|
|
||||||
|
notes :
|
||||||
|
"size" appears to be the same as "length" but is int rather than long
|
||||||
|
"length" represents file size (or stream/attachment size)
|
||||||
|
"preview" is also known as "thumbnail"
|
||||||
|
|
||||||
|
from SignalServiceAttachmentRemoteId.java :
|
||||||
|
* Represents a signal service attachment identifier. This can be either a CDN key or a long, but
|
||||||
|
* not both at once. Attachments V2 used a long as an attachment identifier. This lacks sufficient
|
||||||
|
* entropy to reduce the likelihood of any two uploads going to the same location within a 30-day
|
||||||
|
* window. Attachments V3 uses an opaque string as an attachment identifier which provides more
|
||||||
|
* flexibility in the amount of entropy present.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
public DbusAttachment(SignalServiceAttachment attachment) {
|
||||||
|
this.contentType = attachment.getContentType();
|
||||||
|
|
||||||
|
if (attachment.isPointer()) {
|
||||||
|
final var pointer = attachment.asPointer();
|
||||||
|
this.id = pointer.getRemoteId().toString();
|
||||||
|
this.fileName = pointer.getFileName().orNull();
|
||||||
|
if (this.fileName == null) {
|
||||||
|
this.fileName = "";
|
||||||
|
}
|
||||||
|
this.size = pointer.getSize().transform(Integer::longValue).orNull();
|
||||||
|
if (this.size == null) {
|
||||||
|
this.size = 0L;
|
||||||
|
}
|
||||||
|
this.setKeyLength(pointer.getKey().length);
|
||||||
|
this.setWidth(pointer.getWidth());
|
||||||
|
this.setHeight(pointer.getHeight());
|
||||||
|
this.setVoiceNote(pointer.getVoiceNote());
|
||||||
|
if (pointer.getCaption().isPresent()) {
|
||||||
|
this.setCaption(pointer.getCaption().get());
|
||||||
|
} else {
|
||||||
|
this.setCaption("");
|
||||||
|
}
|
||||||
|
this.setBlurHash("");
|
||||||
|
} else {
|
||||||
|
final var stream = attachment.asStream();
|
||||||
|
this.fileName = stream.getFileName().orNull();
|
||||||
|
if (this.fileName == null) {
|
||||||
|
this.fileName = "";
|
||||||
|
}
|
||||||
|
this.id = "";
|
||||||
|
this.size = stream.getLength();
|
||||||
|
this.setKeyLength(0);
|
||||||
|
this.setWidth(0);
|
||||||
|
this.setHeight(0);
|
||||||
|
this.setVoiceNote(false);
|
||||||
|
this.setCaption("");
|
||||||
|
this.setBlurHash("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbusAttachment(String fileName) {
|
||||||
|
this.contentType = "application/octet-stream";
|
||||||
|
try {
|
||||||
|
final File file = new File(fileName);
|
||||||
|
this.contentType = Utils.getFileMimeType(file, "application/octet-stream");
|
||||||
|
this.size = file.length();
|
||||||
|
} catch (IOException e) {
|
||||||
|
//no such file, try URL
|
||||||
|
try {
|
||||||
|
final URL aURL = new URL(fileName);
|
||||||
|
this.contentType = aURL.openConnection().getContentType();
|
||||||
|
this.size = aURL.openConnection().getContentLengthLong();
|
||||||
|
} catch (IOException f) {
|
||||||
|
f.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.fileName = fileName;
|
||||||
|
this.id = "";
|
||||||
|
this.setKeyLength(0);
|
||||||
|
this.setWidth(0);
|
||||||
|
this.setHeight(0);
|
||||||
|
this.setVoiceNote(false);
|
||||||
|
this.setCaption("");
|
||||||
|
this.setBlurHash("");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentType() {
|
||||||
|
return contentType;
|
||||||
|
}
|
||||||
|
public void setContentType(String contentType) {
|
||||||
|
this.contentType = contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileName() {
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
public void setFileName(String fileName) {
|
||||||
|
this.fileName = fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getFileSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
public void setFileSize(Long size) {
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getKeyLength() {
|
||||||
|
return keyLength;
|
||||||
|
}
|
||||||
|
public void setKeyLength(Integer keyLength) {
|
||||||
|
this.keyLength = keyLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
public void setWidth(Integer width) {
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
public void setHeight(Integer height) {
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isVoiceNote() {
|
||||||
|
return voiceNote;
|
||||||
|
}
|
||||||
|
public boolean getVoiceNote() {
|
||||||
|
return voiceNote;
|
||||||
|
}
|
||||||
|
public void setVoiceNote(boolean voiceNote) {
|
||||||
|
this.voiceNote = voiceNote;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCaption() {
|
||||||
|
return caption;
|
||||||
|
}
|
||||||
|
public void setCaption(String caption) {
|
||||||
|
this.caption = caption;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBlurHash() {
|
||||||
|
return blurHash;
|
||||||
|
}
|
||||||
|
public void setBlurHash(String blurHash) {
|
||||||
|
this.blurHash = blurHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,6 +2,8 @@ package org.asamk.signal.dbus;
|
||||||
|
|
||||||
import org.asamk.Signal;
|
import org.asamk.Signal;
|
||||||
import org.asamk.signal.BaseConfig;
|
import org.asamk.signal.BaseConfig;
|
||||||
|
import org.asamk.signal.PlainTextWriterImpl;
|
||||||
|
import org.asamk.signal.dbus.DbusAttachment;
|
||||||
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.NotMasterDeviceException;
|
import org.asamk.signal.manager.NotMasterDeviceException;
|
||||||
|
@ -52,10 +54,36 @@ public class DbusSignalImpl implements Signal {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long sendMessage(final String message, final List<String> attachments, final String recipient) {
|
public long sendMessageWithDBusAttachments(final String message, final List<DbusAttachment> dBusAttachments, final String recipient) {
|
||||||
var recipients = new ArrayList<String>(1);
|
var recipients = new ArrayList<String>(1);
|
||||||
recipients.add(recipient);
|
recipients.add(recipient);
|
||||||
return sendMessage(message, attachments, recipients);
|
return sendMessageWithDBusAttachments(message, dBusAttachments, recipients);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long sendMessageWithDBusAttachments(final String message, final List<DbusAttachment> dBusAttachments, final List<String> recipients) {
|
||||||
|
try {
|
||||||
|
ArrayList<String> attachmentNames = new ArrayList<>();
|
||||||
|
for (var dBusAttachment : dBusAttachments) {
|
||||||
|
attachmentNames.add(dBusAttachment.getFileName());
|
||||||
|
}
|
||||||
|
final var results = m.sendMessage(message, attachmentNames, recipients);
|
||||||
|
checkSendMessageResults(results.first(), results.second());
|
||||||
|
return results.first();
|
||||||
|
} catch (InvalidNumberException e) {
|
||||||
|
throw new Error.InvalidNumber(e.getMessage());
|
||||||
|
} catch (AttachmentInvalidException e) {
|
||||||
|
throw new Error.AttachmentInvalid(e.getMessage());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new Error.Failure(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long sendMessage(final String message, final List<String> attachmentNames, final String recipient) {
|
||||||
|
var recipients = new ArrayList<String>(1);
|
||||||
|
recipients.add(recipient);
|
||||||
|
return sendMessage(message, attachmentNames, recipients);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkSendMessageResult(long timestamp, SendMessageResult result) throws DBusExecutionException {
|
private static void checkSendMessageResult(long timestamp, SendMessageResult result) throws DBusExecutionException {
|
||||||
|
@ -98,9 +126,9 @@ 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> attachmentNames, final List<String> recipients) {
|
||||||
try {
|
try {
|
||||||
final var results = m.sendMessage(message, attachments, recipients);
|
final var results = m.sendMessage(message, attachmentNames, recipients);
|
||||||
checkSendMessageResults(results.first(), results.second());
|
checkSendMessageResults(results.first(), results.second());
|
||||||
return results.first();
|
return results.first();
|
||||||
} catch (InvalidNumberException e) {
|
} catch (InvalidNumberException e) {
|
||||||
|
@ -185,10 +213,10 @@ public class DbusSignalImpl implements Signal {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long sendNoteToSelfMessage(
|
public long sendNoteToSelfMessage(
|
||||||
final String message, final List<String> attachments
|
final String message, final List<String> attachmentNames
|
||||||
) throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity {
|
) throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity {
|
||||||
try {
|
try {
|
||||||
final var results = m.sendSelfMessage(message, attachments);
|
final var results = m.sendSelfMessage(message, attachmentNames);
|
||||||
checkSendMessageResult(results.first(), results.second());
|
checkSendMessageResult(results.first(), results.second());
|
||||||
return results.first();
|
return results.first();
|
||||||
} catch (AttachmentInvalidException e) {
|
} catch (AttachmentInvalidException e) {
|
||||||
|
@ -198,6 +226,25 @@ public class DbusSignalImpl implements Signal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long sendNoteToSelfMessageWithDBusAttachments(
|
||||||
|
final String message, final List<DbusAttachment> dBusAttachments
|
||||||
|
) throws Error.AttachmentInvalid, Error.Failure, Error.UntrustedIdentity {
|
||||||
|
try {
|
||||||
|
ArrayList<String> attachmentNames = new ArrayList<>();
|
||||||
|
for (var dBusAttachment : dBusAttachments) {
|
||||||
|
attachmentNames.add(dBusAttachment.getFileName());
|
||||||
|
}
|
||||||
|
final var results = m.sendSelfMessage(message, attachmentNames);
|
||||||
|
checkSendMessageResult(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 {
|
||||||
|
@ -211,9 +258,9 @@ 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> attachmentNames, final byte[] groupId) {
|
||||||
try {
|
try {
|
||||||
var results = m.sendGroupMessage(message, attachments, GroupId.unknownVersion(groupId));
|
var results = m.sendGroupMessage(message, attachmentNames, GroupId.unknownVersion(groupId));
|
||||||
checkSendMessageResults(results.first(), results.second());
|
checkSendMessageResults(results.first(), results.second());
|
||||||
return results.first();
|
return results.first();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -225,6 +272,26 @@ public class DbusSignalImpl implements Signal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long sendGroupMessageWithDBusAttachments(final String message, final List<DbusAttachment> dBusAttachments, final byte[] groupId) {
|
||||||
|
try {
|
||||||
|
ArrayList<String> attachmentNames = new ArrayList<>();
|
||||||
|
for (var dBusAttachment : dBusAttachments) {
|
||||||
|
attachmentNames.add(dBusAttachment.getFileName());
|
||||||
|
}
|
||||||
|
var results = m.sendGroupMessage(message, attachmentNames, GroupId.unknownVersion(groupId));
|
||||||
|
checkSendMessageResults(results.first(), results.second());
|
||||||
|
return results.first();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new Error.Failure(e.getMessage());
|
||||||
|
} catch (GroupNotFoundException | NotAGroupMemberException e) {
|
||||||
|
throw new Error.GroupNotFound(e.getMessage());
|
||||||
|
} catch (AttachmentInvalidException e) {
|
||||||
|
throw new Error.AttachmentInvalid(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long sendGroupMessageReaction(
|
public long sendGroupMessageReaction(
|
||||||
final String emoji,
|
final String emoji,
|
||||||
|
@ -272,6 +339,17 @@ public class DbusSignalImpl implements Signal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setExpirationTimer(final String number, final int expiration) {
|
||||||
|
try {
|
||||||
|
m.setExpirationTimer(number, expiration);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new Error.Failure(e.getMessage());
|
||||||
|
} catch (InvalidNumberException e) {
|
||||||
|
throw new Error.InvalidNumber(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setContactBlocked(final String number, final boolean blocked) {
|
public void setContactBlocked(final String number, final boolean blocked) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
|
|
||||||
|
import org.asamk.signal.dbus.DbusAttachment;
|
||||||
|
|
||||||
class JsonAttachment {
|
class JsonAttachment {
|
||||||
|
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
|
@ -18,6 +20,33 @@ class JsonAttachment {
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
final Long size;
|
final Long size;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
Integer keyLength;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
Integer width;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
Integer height;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
boolean voiceNote;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
String caption;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
String relay;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
byte[] preview;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
String digest;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
String blurHash;
|
||||||
|
|
||||||
JsonAttachment(SignalServiceAttachment attachment) {
|
JsonAttachment(SignalServiceAttachment attachment) {
|
||||||
this.contentType = attachment.getContentType();
|
this.contentType = attachment.getContentType();
|
||||||
|
|
||||||
|
@ -26,6 +55,11 @@ class JsonAttachment {
|
||||||
this.id = pointer.getRemoteId().toString();
|
this.id = pointer.getRemoteId().toString();
|
||||||
this.filename = pointer.getFileName().orNull();
|
this.filename = pointer.getFileName().orNull();
|
||||||
this.size = pointer.getSize().transform(Integer::longValue).orNull();
|
this.size = pointer.getSize().transform(Integer::longValue).orNull();
|
||||||
|
this.keyLength = pointer.getKey().length;
|
||||||
|
this.width = pointer.getWidth();
|
||||||
|
this.height = pointer.getHeight();
|
||||||
|
this.voiceNote = pointer.getVoiceNote();
|
||||||
|
if (pointer.getCaption().isPresent()) {this.caption = pointer.getCaption().get();}
|
||||||
} else {
|
} else {
|
||||||
final var stream = attachment.asStream();
|
final var stream = attachment.asStream();
|
||||||
this.id = null;
|
this.id = null;
|
||||||
|
@ -40,4 +74,17 @@ class JsonAttachment {
|
||||||
this.id = null;
|
this.id = null;
|
||||||
this.size = null;
|
this.size = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonAttachment(DbusAttachment attachment) {
|
||||||
|
this.contentType = attachment.getContentType();
|
||||||
|
this.id = attachment.getId();
|
||||||
|
this.filename = attachment.getFileName();
|
||||||
|
this.size = attachment.getFileSize();
|
||||||
|
this.keyLength = attachment.getKeyLength();
|
||||||
|
this.width = attachment.getWidth();
|
||||||
|
this.height = attachment.getHeight();
|
||||||
|
this.voiceNote = attachment.getVoiceNote();
|
||||||
|
this.caption = attachment.getCaption();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
import org.asamk.Signal;
|
import org.asamk.Signal;
|
||||||
import org.asamk.signal.manager.Manager;
|
import org.asamk.signal.manager.Manager;
|
||||||
|
import org.asamk.signal.dbus.DbusAttachment;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -126,6 +127,7 @@ class JsonDataMessage {
|
||||||
sticker = null;
|
sticker = null;
|
||||||
contacts = null;
|
contacts = null;
|
||||||
attachments = messageReceived.getAttachments().stream().map(JsonAttachment::new).collect(Collectors.toList());
|
attachments = messageReceived.getAttachments().stream().map(JsonAttachment::new).collect(Collectors.toList());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonDataMessage(Signal.SyncMessageReceived messageReceived) {
|
public JsonDataMessage(Signal.SyncMessageReceived messageReceived) {
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
package org.asamk.signal.util;
|
package org.asamk.signal.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.asamk.signal.dbus.DbusAttachment;
|
||||||
import org.asamk.signal.manager.groups.GroupId;
|
import org.asamk.signal.manager.groups.GroupId;
|
||||||
import org.asamk.signal.manager.groups.GroupIdFormatException;
|
import org.asamk.signal.manager.groups.GroupIdFormatException;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
|
|
||||||
public class Util {
|
public class Util {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue