mirror of
https://github.com/AsamK/signal-cli
synced 2025-09-04 05:00:39 +00:00
DbusMention and DbusAttachment, with signals
Two new data types: `DbusMention` (created by @0b11001111) and `DbusAttachment`. Two new signals, `MessageReceivedV2` and `SyncMessageReceivedV2`. This is to address #671 #316 #658 and #491, in particular addressing the issues raised by @AsamK in #658. The new signals provide the new data structures to the user program, while the existing signals, `MessageReceived` and `SyncMessageReceived`, continue to provide the old data types (with no information about mentions or attachment metadata). As a result, for each message received, two signals will be emitted: the legacy signal and the V2 signal. Existing (old-style) programs will not see the V2 signal, and so nothing will break. New programs can ignore the legacy signal and process the enhanced data.
This commit is contained in:
parent
6c29d90503
commit
205cc8d6c2
8 changed files with 518 additions and 32 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
|
.gitignore
|
||||||
.gradle/
|
.gradle/
|
||||||
.idea/*
|
.idea/*
|
||||||
!.idea/codeStyles/
|
!.idea/codeStyles/
|
||||||
|
@ -11,3 +12,7 @@ local.properties
|
||||||
.settings/
|
.settings/
|
||||||
out/
|
out/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.asciidoctorconfig.adoc
|
||||||
|
patches/
|
||||||
|
signal-cli
|
||||||
|
/bin/
|
||||||
|
|
|
@ -238,14 +238,9 @@ isRegistred -> result<b>::
|
||||||
== Signals
|
== Signals
|
||||||
|
|
||||||
SyncMessageReceived (timestamp<x>, sender<s>, destination<s>, groupId<ay>,message<s>, attachments<as>)::
|
SyncMessageReceived (timestamp<x>, sender<s>, destination<s>, groupId<ay>,message<s>, attachments<as>)::
|
||||||
|
|
||||||
The sync message is received when the user sends a message from a linked device.
|
The sync message is received when the user sends a message from a linked device.
|
||||||
|
|
||||||
ReceiptReceived (timestamp<x>, sender<s>)::
|
|
||||||
* timestamp : Integer value that can be used to associate this e.g. with a sendMessage()
|
|
||||||
* sender : Phone number of the sender
|
|
||||||
|
|
||||||
This signal is sent by each recipient (e.g. each group member) after the message was successfully delivered to the device
|
|
||||||
|
|
||||||
MessageReceived(timestamp<x>, sender<s>, groupId<ay>, message<s>, attachments<as>)::
|
MessageReceived(timestamp<x>, sender<s>, groupId<ay>, message<s>, attachments<as>)::
|
||||||
* timestamp : Integer value that is used by the system to send a ReceiptReceived reply
|
* timestamp : Integer value that is used by the system to send a ReceiptReceived reply
|
||||||
* sender : Phone number of the sender
|
* sender : Phone number of the sender
|
||||||
|
@ -255,6 +250,59 @@ MessageReceived(timestamp<x>, sender<s>, groupId<ay>, message<s>, attachments<as
|
||||||
|
|
||||||
This signal is received whenever we get a private message or a message is posted in a group we are an active member
|
This signal is received whenever we get a private message or a message is posted in a group we are an active member
|
||||||
|
|
||||||
|
SyncMessageReceivedV2 (timestamp<x>, sender<s>, destination<s>, groupId<ay>, message<s>, mentions<a(sii)>, attachments<a(sssxibiiss)>)::
|
||||||
|
* timestamp : Integer value that is used by the system to send a ReceiptReceived reply
|
||||||
|
* sender : Phone number of the sender
|
||||||
|
* destination : UUID (legacy identifier) of the destination
|
||||||
|
* groupId : Byte array representing the internal group identifier (empty when private message)
|
||||||
|
* message : Message text
|
||||||
|
* mentions : Struct array of mentions: number, position, length
|
||||||
|
** number : String phone number
|
||||||
|
** position : Integer starting position of mention within message
|
||||||
|
** length : Integer length of mention within message
|
||||||
|
* attachments : Struct array of attachment metadata.
|
||||||
|
** contentType : String representing the MIME type of the attachment
|
||||||
|
** fileName : String representing file name if given by the Signal servers
|
||||||
|
** id : String representing remote identifier of attachment. This the name used by signal-cli to store the attachment, and the current user needs to have read access
|
||||||
|
** size : Long representing size of attachment in bytes
|
||||||
|
** keyLength : Integer representing key length
|
||||||
|
** voiceNote : boolean representing whether this attachment is a voice note
|
||||||
|
** width : Integer representation of width in pixels (0 if not image)
|
||||||
|
** height : Integer representation of height in pixels (0 if not image)
|
||||||
|
** caption : String representing photo caption
|
||||||
|
** blurHash : String representing blur hash
|
||||||
|
|
||||||
|
The sync message is received when the user sends a message from a linked device.
|
||||||
|
|
||||||
|
MessageReceivedV2(timestamp<x>, sender<s>, groupId<ay>, message<s>, mentions<a(sii)>, attachments<a(sssxibiiss)>)::
|
||||||
|
* timestamp : Integer value that is used by the system to send a ReceiptReceived reply
|
||||||
|
* sender : Phone number of the sender
|
||||||
|
* groupId : Byte array representing the internal group identifier (empty when private message)
|
||||||
|
* message : Message text
|
||||||
|
* mentions : Struct array of mentions: number, position, length
|
||||||
|
** number : String phone number
|
||||||
|
** position : Integer starting position of mention within message
|
||||||
|
** length : Integer length of mention within message
|
||||||
|
* attachments : Struct array of attachment metadata.
|
||||||
|
** contentType : String representing the MIME type of the attachment
|
||||||
|
** fileName : String representing file name if given by the Signal servers
|
||||||
|
** id : String representing remote identifier of attachment. This the name used by signal-cli to store the attachment, and the current user needs to have read access
|
||||||
|
** size : Long representing size of attachment in bytes
|
||||||
|
** keyLength : Integer representing key length
|
||||||
|
** voiceNote : boolean representing whether this attachment is a voice note
|
||||||
|
** width : Integer representation of width in pixels (0 if not image)
|
||||||
|
** height : Integer representation of height in pixels (0 if not image)
|
||||||
|
** caption : String representing photo caption
|
||||||
|
** blurHash : String representing blur hash
|
||||||
|
|
||||||
|
This signal is received whenever we get a private message or a message is posted in a group we are an active member
|
||||||
|
|
||||||
|
ReceiptReceived (timestamp<x>, sender<s>)::
|
||||||
|
* timestamp : Integer value that can be used to associate this e.g. with a sendMessage()
|
||||||
|
* sender : Phone number of the sender
|
||||||
|
|
||||||
|
This signal is sent by each recipient (e.g. each group member) after the message was successfully delivered to the device
|
||||||
|
|
||||||
== Examples
|
== Examples
|
||||||
|
|
||||||
Send a text message (without attachment) to a contact::
|
Send a text message (without attachment) to a contact::
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
package org.asamk;
|
package org.asamk;
|
||||||
|
|
||||||
|
import org.asamk.signal.dbus.DbusAttachment;
|
||||||
|
import org.asamk.signal.dbus.DbusMention;
|
||||||
import org.freedesktop.dbus.exceptions.DBusException;
|
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 java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DBus interface for the org.asamk.Signal service.
|
* DBus interface for the org.asamk.Signal service.
|
||||||
|
@ -14,11 +18,11 @@ import java.util.List;
|
||||||
public interface Signal extends DBusInterface {
|
public interface Signal extends DBusInterface {
|
||||||
|
|
||||||
long sendMessage(
|
long sendMessage(
|
||||||
String message, List<String> attachments, String recipient
|
String message, List<String> attachmentNames, String recipient
|
||||||
) 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, List<String> recipients
|
||||||
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
|
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.UntrustedIdentity;
|
||||||
|
|
||||||
void sendTyping(
|
void sendTyping(
|
||||||
|
@ -50,13 +54,13 @@ 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;
|
) 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, Error.InvalidGroupId;
|
) throws Error.GroupNotFound, Error.Failure, Error.AttachmentInvalid, Error.InvalidGroupId;
|
||||||
|
|
||||||
long sendGroupMessageReaction(
|
long sendGroupMessageReaction(
|
||||||
|
@ -77,12 +81,12 @@ public interface Signal extends DBusInterface {
|
||||||
|
|
||||||
List<String> getGroupMembers(byte[] groupId) throws Error.InvalidGroupId;
|
List<String> getGroupMembers(byte[] groupId) throws Error.InvalidGroupId;
|
||||||
|
|
||||||
|
boolean isRegistered();
|
||||||
|
|
||||||
byte[] updateGroup(
|
byte[] updateGroup(
|
||||||
byte[] groupId, String name, List<String> members, String avatar
|
byte[] groupId, String name, List<String> members, String avatar
|
||||||
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.GroupNotFound, Error.InvalidGroupId;
|
) throws Error.AttachmentInvalid, Error.Failure, Error.InvalidNumber, Error.GroupNotFound, Error.InvalidGroupId;
|
||||||
|
|
||||||
boolean isRegistered();
|
|
||||||
|
|
||||||
void updateProfile(
|
void updateProfile(
|
||||||
String name, String about, String aboutEmoji, String avatarPath, boolean removeAvatar
|
String name, String about, String aboutEmoji, String avatarPath, boolean removeAvatar
|
||||||
) throws Error.Failure;
|
) throws Error.Failure;
|
||||||
|
@ -109,7 +113,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<String> attachmentNames;
|
||||||
|
|
||||||
public MessageReceived(
|
public MessageReceived(
|
||||||
String objectpath,
|
String objectpath,
|
||||||
|
@ -117,13 +121,61 @@ public interface Signal extends DBusInterface {
|
||||||
String sender,
|
String sender,
|
||||||
byte[] groupId,
|
byte[] groupId,
|
||||||
String message,
|
String message,
|
||||||
List<String> attachments
|
List<String> attachmentNames
|
||||||
) throws DBusException {
|
) throws DBusException {
|
||||||
super(objectpath, timestamp, sender, groupId, message, attachments);
|
super(objectpath, timestamp, sender, groupId, message, attachmentNames);
|
||||||
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.attachmentNames = attachmentNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSender() {
|
||||||
|
return sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getGroupId() {
|
||||||
|
return groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getAttachmentNames() {
|
||||||
|
return attachmentNames;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MessageReceivedV2 extends DBusSignal {
|
||||||
|
|
||||||
|
private final long timestamp;
|
||||||
|
private final String sender;
|
||||||
|
private final byte[] groupId;
|
||||||
|
private final String message;
|
||||||
|
private final List<DbusMention> mentions;
|
||||||
|
private final List<DbusAttachment> attachments;
|
||||||
|
|
||||||
|
public MessageReceivedV2(
|
||||||
|
String objectpath,
|
||||||
|
long timestamp,
|
||||||
|
String sender,
|
||||||
|
byte[] groupId,
|
||||||
|
String message,
|
||||||
|
List<DbusMention> mentions,
|
||||||
|
List<DbusAttachment> attachments
|
||||||
|
) throws DBusException {
|
||||||
|
super(objectpath, timestamp, sender, groupId, message, mentions, attachments);
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.sender = sender;
|
||||||
|
this.groupId = groupId;
|
||||||
|
this.message = message;
|
||||||
|
this.mentions = mentions;
|
||||||
this.attachments = attachments;
|
this.attachments = attachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +195,11 @@ public interface Signal extends DBusInterface {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getAttachments() {
|
public List<DbusMention> getMentions() {
|
||||||
|
return mentions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DbusAttachment> getAttachments() {
|
||||||
return attachments;
|
return attachments;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,7 +231,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<String> attachmentNames;
|
||||||
|
|
||||||
public SyncMessageReceived(
|
public SyncMessageReceived(
|
||||||
String objectpath,
|
String objectpath,
|
||||||
|
@ -184,15 +240,15 @@ public interface Signal extends DBusInterface {
|
||||||
String destination,
|
String destination,
|
||||||
byte[] groupId,
|
byte[] groupId,
|
||||||
String message,
|
String message,
|
||||||
List<String> attachments
|
List<String> attachmentNames
|
||||||
) throws DBusException {
|
) throws DBusException {
|
||||||
super(objectpath, timestamp, source, destination, groupId, message, attachments);
|
super(objectpath, timestamp, source, destination, groupId, message, attachmentNames);
|
||||||
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.attachmentNames = attachmentNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getTimestamp() {
|
public long getTimestamp() {
|
||||||
|
@ -215,7 +271,65 @@ public interface Signal extends DBusInterface {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getAttachments() {
|
public List<String> getAttachmentNames() {
|
||||||
|
return attachmentNames;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SyncMessageReceivedV2 extends DBusSignal {
|
||||||
|
|
||||||
|
private final long timestamp;
|
||||||
|
private final String source;
|
||||||
|
private final String destination;
|
||||||
|
private final byte[] groupId;
|
||||||
|
private final String message;
|
||||||
|
private final List<DbusMention> mentions;
|
||||||
|
private final List<DbusAttachment> attachments;
|
||||||
|
|
||||||
|
public SyncMessageReceivedV2(
|
||||||
|
String objectpath,
|
||||||
|
long timestamp,
|
||||||
|
String source,
|
||||||
|
String destination,
|
||||||
|
byte[] groupId,
|
||||||
|
String message,
|
||||||
|
List<DbusMention> mentions,
|
||||||
|
List<DbusAttachment> attachments
|
||||||
|
) throws DBusException {
|
||||||
|
super(objectpath, timestamp, source, destination, groupId, message, mentions, attachments);
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.source = source;
|
||||||
|
this.destination = destination;
|
||||||
|
this.groupId = groupId;
|
||||||
|
this.message = message;
|
||||||
|
this.mentions = mentions;
|
||||||
|
this.attachments = attachments;
|
||||||
|
}
|
||||||
|
public long getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDestination() {
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getGroupId() {
|
||||||
|
return groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DbusMention> getMentions() {
|
||||||
|
return mentions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DbusAttachment> getAttachments() {
|
||||||
return attachments;
|
return attachments;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
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.dbus.DbusMention;
|
||||||
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 +11,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 +74,23 @@ 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);
|
||||||
|
//send both signals; only one is relevant
|
||||||
|
conn.sendMessage(new Signal.MessageReceivedV2(objectPath,
|
||||||
|
message.getTimestamp(),
|
||||||
|
getLegacyIdentifier(sender),
|
||||||
|
groupId != null ? groupId : new byte[0],
|
||||||
|
message.getBody().isPresent() ? message.getBody().get() : "",
|
||||||
|
JsonDbusReceiveMessageHandler.getMentions(message, m),
|
||||||
|
dBusAttachments
|
||||||
|
));
|
||||||
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)));
|
JsonDbusReceiveMessageHandler.getAttachmentNames(message, m)));
|
||||||
} catch (DBusException e) {
|
} catch (DBusException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -93,6 +107,19 @@ 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.SyncMessageReceivedV2(objectPath,
|
||||||
|
transcript.getTimestamp(),
|
||||||
|
getLegacyIdentifier(sender),
|
||||||
|
transcript.getDestination().isPresent()
|
||||||
|
? getLegacyIdentifier(transcript.getDestination().get())
|
||||||
|
: "",
|
||||||
|
groupId != null ? groupId : new byte[0],
|
||||||
|
message.getBody().isPresent() ? message.getBody().get() : "",
|
||||||
|
JsonDbusReceiveMessageHandler.getMentions(message, m),
|
||||||
|
dBusAttachments
|
||||||
|
));
|
||||||
conn.sendMessage(new Signal.SyncMessageReceived(objectPath,
|
conn.sendMessage(new Signal.SyncMessageReceived(objectPath,
|
||||||
transcript.getTimestamp(),
|
transcript.getTimestamp(),
|
||||||
getLegacyIdentifier(sender),
|
getLegacyIdentifier(sender),
|
||||||
|
@ -101,7 +128,7 @@ 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)));
|
JsonDbusReceiveMessageHandler.getAttachmentNames(message, m)));
|
||||||
} catch (DBusException e) {
|
} catch (DBusException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -116,7 +143,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 +155,43 @@ public class JsonDbusReceiveMessageHandler extends JsonReceiveMessageHandler {
|
||||||
return attachments;
|
return attachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static private List<DbusMention> getMentions(SignalServiceDataMessage message, Manager m) {
|
||||||
|
var mentions = new ArrayList<DbusMention>();
|
||||||
|
if (message.getMentions().isPresent()) {
|
||||||
|
for (var mention : message.getMentions().get()) {
|
||||||
|
mentions.add(new DbusMention(mention, m));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mentions;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,10 +90,10 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
|
||||||
writer.indentedWriter()
|
writer.indentedWriter()
|
||||||
.println("Id: {}", Base64.getEncoder().encodeToString(messageReceived.getGroupId()));
|
.println("Id: {}", Base64.getEncoder().encodeToString(messageReceived.getGroupId()));
|
||||||
}
|
}
|
||||||
if (messageReceived.getAttachments().size() > 0) {
|
if (messageReceived.getAttachmentNames().size() > 0) {
|
||||||
writer.println("Attachments:");
|
writer.println("Attachments:");
|
||||||
for (var attachment : messageReceived.getAttachments()) {
|
for (var attachmentName : messageReceived.getAttachmentNames()) {
|
||||||
writer.println("- Stored plaintext in: {}", attachment);
|
writer.println("- Stored plaintext in: {}", attachmentName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.println();
|
writer.println();
|
||||||
|
@ -115,10 +115,10 @@ public class ReceiveCommand implements ExtendedDbusCommand, LocalCommand {
|
||||||
writer.indentedWriter()
|
writer.indentedWriter()
|
||||||
.println("Id: {}", Base64.getEncoder().encodeToString(syncReceived.getGroupId()));
|
.println("Id: {}", Base64.getEncoder().encodeToString(syncReceived.getGroupId()));
|
||||||
}
|
}
|
||||||
if (syncReceived.getAttachments().size() > 0) {
|
if (syncReceived.getAttachmentNames().size() > 0) {
|
||||||
writer.println("Attachments:");
|
writer.println("Attachments:");
|
||||||
for (var attachment : syncReceived.getAttachments()) {
|
for (var attachmentName : syncReceived.getAttachmentNames()) {
|
||||||
writer.println("- Stored plaintext in: {}", attachment);
|
writer.println("- Stored plaintext in: {}", attachmentName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.println();
|
writer.println();
|
||||||
|
|
231
src/main/java/org/asamk/signal/dbus/DbusAttachment.java
Normal file
231
src/main/java/org/asamk/signal/dbus/DbusAttachment.java
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
package org.asamk.signal.dbus;
|
||||||
|
|
||||||
|
import org.asamk.signal.commands.exceptions.UserErrorException;
|
||||||
|
import org.asamk.signal.manager.util.Utils;
|
||||||
|
import org.freedesktop.dbus.Struct;
|
||||||
|
import org.freedesktop.dbus.annotations.Position;
|
||||||
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
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) throws UserErrorException {
|
||||||
|
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) {
|
||||||
|
throw new UserErrorException("Cannot find attachment " + fileName + ". " + f.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
28
src/main/java/org/asamk/signal/dbus/DbusMention.java
Normal file
28
src/main/java/org/asamk/signal/dbus/DbusMention.java
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package org.asamk.signal.dbus;
|
||||||
|
|
||||||
|
import org.asamk.signal.manager.Manager;
|
||||||
|
import org.freedesktop.dbus.Struct;
|
||||||
|
import org.freedesktop.dbus.annotations.Position;
|
||||||
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||||
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
|
|
||||||
|
import static org.asamk.signal.util.Util.getLegacyIdentifier;
|
||||||
|
|
||||||
|
public final class DbusMention extends Struct {
|
||||||
|
|
||||||
|
@Position(0)
|
||||||
|
public final String name;
|
||||||
|
|
||||||
|
@Position(1)
|
||||||
|
public final int start;
|
||||||
|
|
||||||
|
@Position(2)
|
||||||
|
public final int length;
|
||||||
|
|
||||||
|
public DbusMention(SignalServiceDataMessage.Mention mention, Manager m) {
|
||||||
|
this.name = getLegacyIdentifier(m.resolveSignalServiceAddress(new SignalServiceAddress(mention.getUuid())));
|
||||||
|
this.start = mention.getStart();
|
||||||
|
this.length = mention.getLength();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ class JsonDataMessage {
|
||||||
mentions = null;
|
mentions = null;
|
||||||
sticker = null;
|
sticker = null;
|
||||||
contacts = null;
|
contacts = null;
|
||||||
attachments = messageReceived.getAttachments().stream().map(JsonAttachment::new).collect(Collectors.toList());
|
attachments = messageReceived.getAttachmentNames().stream().map(JsonAttachment::new).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonDataMessage(Signal.SyncMessageReceived messageReceived) {
|
public JsonDataMessage(Signal.SyncMessageReceived messageReceived) {
|
||||||
|
@ -140,6 +140,6 @@ class JsonDataMessage {
|
||||||
mentions = null;
|
mentions = null;
|
||||||
sticker = null;
|
sticker = null;
|
||||||
contacts = null;
|
contacts = null;
|
||||||
attachments = messageReceived.getAttachments().stream().map(JsonAttachment::new).collect(Collectors.toList());
|
attachments = messageReceived.getAttachmentNames().stream().map(JsonAttachment::new).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue