1 package org
.asamk
.signal
.dbus
;
3 import org
.asamk
.Signal
;
4 import org
.asamk
.signal
.manager
.Manager
;
5 import org
.asamk
.signal
.manager
.api
.MessageEnvelope
;
6 import org
.asamk
.signal
.manager
.groups
.GroupId
;
7 import org
.asamk
.signal
.manager
.storage
.recipients
.RecipientAddress
;
8 import org
.freedesktop
.dbus
.connections
.impl
.DBusConnection
;
9 import org
.freedesktop
.dbus
.exceptions
.DBusException
;
10 import org
.freedesktop
.dbus
.types
.Variant
;
12 import java
.io
.Serializable
;
13 import java
.util
.ArrayList
;
14 import java
.util
.HashMap
;
15 import java
.util
.List
;
18 public class DbusReceiveMessageHandler
implements Manager
.ReceiveMessageHandler
{
20 private final DBusConnection conn
;
21 private final String objectPath
;
23 public DbusReceiveMessageHandler(DBusConnection conn
, final String objectPath
) {
25 this.objectPath
= objectPath
;
29 public void handleMessage(MessageEnvelope envelope
, Throwable exception
) {
31 sendDbusMessages(envelope
);
32 } catch (DBusException e
) {
37 private void sendDbusMessages(MessageEnvelope envelope
) throws DBusException
{
38 final var senderString
= envelope
.sourceAddress().map(RecipientAddress
::getLegacyIdentifier
).orElse("");
39 if (envelope
.receipt().isPresent()) {
40 final var receiptMessage
= envelope
.receipt().get();
41 final var type
= switch (receiptMessage
.type()) {
43 case VIEWED
-> "viewed";
44 case DELIVERY
-> "delivery";
45 case UNKNOWN
-> "unknown";
47 for (long timestamp
: receiptMessage
.timestamps()) {
48 conn
.sendMessage(new Signal
.ReceiptReceived(objectPath
, timestamp
, senderString
));
49 conn
.sendMessage(new Signal
.ReceiptReceivedV2(objectPath
, timestamp
, senderString
, type
, Map
.of()));
52 if (envelope
.data().isPresent()) {
53 var message
= envelope
.data().get();
55 var groupId
= message
.groupContext()
56 .map(MessageEnvelope
.Data
.GroupContext
::groupId
)
57 .map(GroupId
::serialize
)
58 .orElseGet(() -> new byte[0]);
59 var isGroupUpdate
= message
.groupContext()
60 .map(MessageEnvelope
.Data
.GroupContext
::isGroupUpdate
)
62 if (!message
.isEndSession() && !isGroupUpdate
) {
63 conn
.sendMessage(new Signal
.MessageReceived(objectPath
,
67 message
.body().orElse(""),
68 getAttachments(message
)));
69 conn
.sendMessage(new Signal
.MessageReceivedV2(objectPath
,
73 message
.body().orElse(""),
74 getMessageExtras(message
)));
77 if (envelope
.sync().isPresent()) {
78 var syncMessage
= envelope
.sync().get();
79 if (syncMessage
.sent().isPresent()) {
80 var transcript
= syncMessage
.sent().get();
82 if (transcript
.destination().isPresent() || transcript
.message().groupContext().isPresent()) {
83 var message
= transcript
.message();
84 var groupId
= message
.groupContext()
85 .map(MessageEnvelope
.Data
.GroupContext
::groupId
)
86 .map(GroupId
::serialize
)
87 .orElseGet(() -> new byte[0]);
89 conn
.sendMessage(new Signal
.SyncMessageReceived(objectPath
,
90 transcript
.message().timestamp(),
92 transcript
.destination().map(RecipientAddress
::getLegacyIdentifier
).orElse(""),
94 message
.body().orElse(""),
95 getAttachments(message
)));
96 conn
.sendMessage(new Signal
.SyncMessageReceivedV2(objectPath
,
97 transcript
.message().timestamp(),
99 transcript
.destination().map(RecipientAddress
::getLegacyIdentifier
).orElse(""),
101 message
.body().orElse(""),
102 getMessageExtras(message
)));
109 private List
<String
> getAttachments(MessageEnvelope
.Data message
) {
110 var attachments
= new ArrayList
<String
>();
111 if (message
.attachments().size() > 0) {
112 for (var attachment
: message
.attachments()) {
113 if (attachment
.file().isPresent()) {
114 attachments
.add(attachment
.file().get().getAbsolutePath());
121 private HashMap
<String
, Variant
<?
>> getMessageExtras(MessageEnvelope
.Data message
) {
122 var extras
= new HashMap
<String
, Variant
<?
>>();
123 if (message
.attachments().size() > 0) {
124 var attachments
= message
.attachments()
126 .filter(a
-> a
.id().isPresent())
127 .map(this::getAttachmentMap
)
129 extras
.put("attachments", new Variant
<>(attachments
, "aa{sv}"));
131 if (message
.mentions().size() > 0) {
132 var mentions
= message
.mentions().stream().map(this::getMentionMap
).toList();
133 extras
.put("mentions", new Variant
<>(mentions
, "aa{sv}"));
135 extras
.put("expiresInSeconds", new Variant
<>(message
.expiresInSeconds()));
136 if (message
.quote().isPresent()) {
137 extras
.put("quote", new Variant
<>(getQuoteMap(message
.quote().get()), "a{sv}"));
139 if (message
.reaction().isPresent()) {
140 final var reaction
= message
.reaction().get();
141 extras
.put("reaction", new Variant
<>(getReactionMap(reaction
), "a{sv}"));
143 if (message
.remoteDeleteId().isPresent()) {
144 extras
.put("remoteDelete",
145 new Variant
<>(Map
.of("timestamp", new Variant
<>(message
.remoteDeleteId().get())), "a{sv}"));
147 if (message
.sticker().isPresent()) {
148 final var sticker
= message
.sticker().get();
149 extras
.put("sticker", new Variant
<>(getStickerMap(sticker
), "a{sv}"));
151 extras
.put("isViewOnce", new Variant
<>(message
.isViewOnce()));
155 private Map
<String
, Variant
<?
>> getQuoteMap(final MessageEnvelope
.Data
.Quote quote
) {
157 new Variant
<>(quote
.id()),
159 new Variant
<>(quote
.author().getLegacyIdentifier()),
161 new Variant
<>(quote
.text().orElse("")));
164 private Map
<String
, Variant
<?
extends Serializable
>> getStickerMap(final MessageEnvelope
.Data
.Sticker sticker
) {
165 return Map
.of("packId",
166 new Variant
<>(sticker
.packId().serialize()),
168 new Variant
<>(sticker
.stickerId()));
171 private Map
<String
, Variant
<?
>> getReactionMap(final MessageEnvelope
.Data
.Reaction reaction
) {
172 return Map
.of("emoji",
173 new Variant
<>(reaction
.emoji()),
175 new Variant
<>(reaction
.targetAuthor().getLegacyIdentifier()),
176 "targetSentTimestamp",
177 new Variant
<>(reaction
.targetSentTimestamp()),
179 new Variant
<>(reaction
.isRemove()));
182 private Map
<String
, Variant
<?
>> getAttachmentMap(
183 final MessageEnvelope
.Data
.Attachment a
185 final var map
= new HashMap
<String
, Variant
<?
>>();
186 if (a
.id().isPresent()) {
187 map
.put("remoteId", new Variant
<>(a
.id().get()));
189 if (a
.file().isPresent()) {
190 map
.put("file", new Variant
<>(a
.file().get().getAbsolutePath()));
192 map
.put("contentType", new Variant
<>(a
.contentType()));
193 map
.put("isVoiceNote", new Variant
<>(a
.isVoiceNote()));
194 map
.put("isBorderless", new Variant
<>(a
.isBorderless()));
195 map
.put("isGif", new Variant
<>(a
.isGif()));
196 if (a
.caption().isPresent()) {
197 map
.put("caption", new Variant
<>(a
.caption().get()));
199 if (a
.fileName().isPresent()) {
200 map
.put("fileName", new Variant
<>(a
.fileName().get()));
202 if (a
.size().isPresent()) {
203 map
.put("size", new Variant
<>(a
.size().get()));
205 if (a
.width().isPresent()) {
206 map
.put("width", new Variant
<>(a
.width().get()));
208 if (a
.height().isPresent()) {
209 map
.put("height", new Variant
<>(a
.height().get()));
214 private Map
<String
, Variant
<?
>> getMentionMap(
215 final MessageEnvelope
.Data
.Mention mention
217 return Map
.of("recipient",
218 new Variant
<>(mention
.recipient().getLegacyIdentifier()),
220 new Variant
<>(mention
.start()),
222 new Variant
<>(mention
.length()));